gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_99_1-65-g80febdd


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_99_1-65-g80febdd
Date: Sun, 22 May 2011 14:01:14 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=80febddf239ff7209a4eaf184023f336fcdc5fde

The branch, master has been updated
       via  80febddf239ff7209a4eaf184023f336fcdc5fde (commit)
       via  f099342688710138ba8cd94e47846bda5c331faf (commit)
       via  8dcf7e8299fed143c2e61500da55b5e5910eb54c (commit)
       via  0283ba941659a1cff403e8ff64d8cbc50cc56efa (commit)
       via  2c2c4268f0fd156c5f5a67e2e2e146309af22a13 (commit)
       via  947d57a8c25075deea466117f9207eb99511af94 (commit)
      from  917a5fa7ced3690df6764bf961cef3d632e18cc2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 80febddf239ff7209a4eaf184023f336fcdc5fde
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun May 22 15:59:58 2011 +0200

    print information on ECC certificates.

commit f099342688710138ba8cd94e47846bda5c331faf
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun May 22 11:55:33 2011 +0200

    gnutls_pk_params_st is used internally to transfer public key parameters. 
This replaces the raw bigint_t arrays.

commit 8dcf7e8299fed143c2e61500da55b5e5910eb54c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 21 19:08:55 2011 +0200

    Curve TLS ID is being stored in algorithms/ecc.c.

commit 0283ba941659a1cff403e8ff64d8cbc50cc56efa
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 21 18:55:31 2011 +0200

    gnutls_algorithms.c was split into manageable files in algorithms/.

commit 2c2c4268f0fd156c5f5a67e2e2e146309af22a13
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 21 17:07:40 2011 +0200

    use the _gnutls_session_is_ecc() to check for ECDH.

commit 947d57a8c25075deea466117f9207eb99511af94
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 21 13:11:34 2011 +0200

    Added OIDs and definitions for ECDSA signature algorithm.

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                              |    1 +
 lib/Makefile.am                           |    6 +-
 lib/abstract_int.h                        |    5 +-
 lib/{gnutls_algorithms.h => algorithms.h} |   16 +-
 lib/{openpgp => algorithms}/Makefile.am   |   11 +-
 lib/algorithms/cert_types.c               |   98 ++
 lib/algorithms/ciphers.c                  |  272 +++
 lib/algorithms/ciphersuites.c             |  924 ++++++++++
 lib/algorithms/ecc.c                      |  274 +++
 lib/algorithms/kx.c                       |  284 +++
 lib/algorithms/mac.c                      |  205 +++
 lib/algorithms/protocols.c                |  301 ++++
 lib/algorithms/publickey.c                |  263 +++
 lib/algorithms/secparams.c                |  183 ++
 lib/algorithms/sign.c                     |  265 +++
 lib/auth/anon.h                           |    2 +-
 lib/auth/cert.c                           |    2 +-
 lib/auth/dh_common.c                      |    2 +-
 lib/auth/dhe.c                            |    2 +-
 lib/auth/ecdh_common.c                    |   22 +-
 lib/auth/ecdh_common.h                    |    4 +-
 lib/auth/rsa.c                            |   51 +-
 lib/auth/rsa_export.c                     |   22 +-
 lib/ext/ecc.c                             |   41 +-
 lib/ext/ecc.h                             |    2 -
 lib/ext/session_ticket.c                  |    2 +-
 lib/ext/signature.c                       |    2 +-
 lib/ext/srp.c                             |    2 +-
 lib/gnutls.asn                            |   13 +
 lib/gnutls_algorithms.c                   | 2687 -----------------------------
 lib/gnutls_asn1_tab.c                     |   12 +-
 lib/gnutls_auth.c                         |    2 +-
 lib/gnutls_cert.c                         |    2 +-
 lib/gnutls_cipher.c                       |    2 +-
 lib/gnutls_cipher_int.c                   |    2 +-
 lib/gnutls_compress.c                     |    2 +-
 lib/gnutls_constate.c                     |    2 +-
 lib/gnutls_ecc.c                          |  231 ++-
 lib/gnutls_ecc.h                          |    9 +-
 lib/gnutls_errors.c                       |    2 +
 lib/gnutls_handshake.c                    |    5 +-
 lib/gnutls_int.h                          |   11 +-
 lib/gnutls_kx.c                           |    2 +-
 lib/gnutls_pk.c                           |  140 +--
 lib/gnutls_pk.h                           |   28 +-
 lib/gnutls_priority.c                     |    2 +-
 lib/gnutls_privkey.c                      |   81 +-
 lib/gnutls_pubkey.c                       |  232 ++--
 lib/gnutls_record.c                       |    2 +-
 lib/gnutls_rsa_export.c                   |   12 +-
 lib/gnutls_rsa_export.h                   |    2 +-
 lib/gnutls_sig.c                          |   15 +-
 lib/gnutls_sig.h                          |    4 +-
 lib/gnutls_state.c                        |    7 +-
 lib/gnutls_state.h                        |    4 +-
 lib/gnutls_v2_compat.c                    |    2 +-
 lib/gnutls_x509.c                         |    2 +-
 lib/includes/gnutls/abstract.h            |    2 +
 lib/includes/gnutls/crypto.h              |    2 +-
 lib/includes/gnutls/gnutls.h.in           |   40 +-
 lib/libgnutls.map                         |    3 +
 lib/nettle/ecc_test.c                     |    4 +-
 lib/nettle/mpi.c                          |    2 +-
 lib/nettle/pk.c                           |   10 +-
 lib/opencdk/read-packet.c                 |    2 +-
 lib/openpgp/openpgp_int.h                 |    5 +-
 lib/openpgp/pgp.c                         |   59 +-
 lib/openpgp/privkey.c                     |  106 +-
 lib/x509/Makefile.am                      |    4 +-
 lib/x509/common.c                         |  181 +--
 lib/x509/common.h                         |   16 +-
 lib/x509/crq.c                            |   89 +-
 lib/x509/key_decode.c                     |  331 ++++
 lib/x509/key_encode.c                     |  834 +++++++++
 lib/x509/mpi.c                            |  404 +----
 lib/x509/output.c                         |   51 +-
 lib/x509/privkey.c                        |  900 +++-------
 lib/x509/privkey_pkcs8.c                  |   89 +-
 lib/x509/verify.c                         |   45 +-
 lib/x509/x509.c                           |  109 +-
 lib/x509/x509_int.h                       |   66 +-
 lib/x509/x509_write.c                     |    3 +-
 82 files changed, 5411 insertions(+), 4727 deletions(-)
 rename lib/{gnutls_algorithms.h => algorithms.h} (93%)
 copy lib/{openpgp => algorithms}/Makefile.am (78%)
 create mode 100644 lib/algorithms/cert_types.c
 create mode 100644 lib/algorithms/ciphers.c
 create mode 100644 lib/algorithms/ciphersuites.c
 create mode 100644 lib/algorithms/ecc.c
 create mode 100644 lib/algorithms/kx.c
 create mode 100644 lib/algorithms/mac.c
 create mode 100644 lib/algorithms/protocols.c
 create mode 100644 lib/algorithms/publickey.c
 create mode 100644 lib/algorithms/secparams.c
 create mode 100644 lib/algorithms/sign.c
 delete mode 100644 lib/gnutls_algorithms.c
 create mode 100644 lib/x509/key_decode.c
 create mode 100644 lib/x509/key_encode.c

diff --git a/configure.ac b/configure.ac
index 1f0ff9e..95eb972 100644
--- a/configure.ac
+++ b/configure.ac
@@ -411,6 +411,7 @@ AC_CONFIG_FILES([
   lib/accelerated/Makefile
   lib/accelerated/intel/Makefile
   lib/ext/Makefile
+  lib/algorithms/Makefile
   lib/auth/Makefile
 ])
 
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 17a1b87..01a87ee 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -24,7 +24,7 @@
 ACLOCAL_AMFLAGS = -I ../m4 -I ../gl/m4
 
 EXTRA_DIST = pakchois/README
-SUBDIRS = includes x509 accelerated auth ext
+SUBDIRS = includes x509 accelerated auth ext algorithms
 if ENABLE_MINITASN1
 SUBDIRS += minitasn1
 endif
@@ -61,7 +61,7 @@ PSK_COBJECTS = gnutls_psk.c
 
 COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c   \
        gnutls_mbuffers.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c \
-       gnutls_errors.c gnutls_algorithms.c gnutls_dh.c gnutls_kx.c     \
+       gnutls_errors.c gnutls_dh.c gnutls_kx.c \
        gnutls_priority.c gnutls_hash_int.c gnutls_cipher_int.c         \
        gnutls_session.c gnutls_db.c x509_b64.c                 \
        gnutls_extensions.c gnutls_auth.c gnutls_v2_compat.c            \
@@ -112,7 +112,7 @@ libgnutls_la_LDFLAGS = -no-undefined \
 
 libgnutls_la_LIBADD = ../gl/libgnu.la x509/libgnutls_x509.la \
        accelerated/libaccelerated.la ext/libgnutls_ext.la \
-       auth/libgnutls_auth.la \
+       auth/libgnutls_auth.la algorithms/libgnutls_alg.la \
        $(LTLIBZ)  $(LTLIBINTL) $(LIBSOCKET) $(LTLIBDL) \
        $(LTLIBPTHREAD)
 
diff --git a/lib/abstract_int.h b/lib/abstract_int.h
index 45440fe..1060679 100644
--- a/lib/abstract_int.h
+++ b/lib/abstract_int.h
@@ -4,13 +4,14 @@
 #include <gnutls/abstract.h>
 
 int _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
-                                     bigint_t * params, int *params_size);
+                                     gnutls_pk_params_st*);
 
+int pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st* params);
 int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t pubkey, 
gnutls_protocol_t ver, 
   gnutls_sign_algorithm_t sign);
 int _gnutls_pubkey_is_over_rsa_512(gnutls_pubkey_t pubkey);
 int
 _gnutls_pubkey_get_mpis (gnutls_pubkey_t key,
-                                 bigint_t * params, int *params_size);
+                                 gnutls_pk_params_st * params);
 
 #endif
diff --git a/lib/gnutls_algorithms.h b/lib/algorithms.h
similarity index 93%
rename from lib/gnutls_algorithms.h
rename to lib/algorithms.h
index 4877076..205a2c1 100644
--- a/lib/gnutls_algorithms.h
+++ b/lib/algorithms.h
@@ -129,7 +129,9 @@ unsigned int _gnutls_pk_bits_to_subgroup_bits (unsigned int 
pk_bits);
 struct gnutls_ecc_curve_entry_st
 {
   const char *name;
-  ecc_curve_t id;
+  const char* oid;
+  gnutls_ecc_curve_t id;
+  int tls_id; /* The RFC4492 namedCurve ID */
   int size; /* the size in bytes */
 
   /** The prime that defines the field the curve is in (encoded in hex) */
@@ -147,9 +149,13 @@ struct gnutls_ecc_curve_entry_st
 };
 typedef struct gnutls_ecc_curve_entry_st gnutls_ecc_curve_entry_st;
 
-const char * _gnutls_ecc_curve_get_name (ecc_curve_t curve);
-const gnutls_ecc_curve_entry_st * _gnutls_ecc_curve_get_params (ecc_curve_t 
curve);
-int _gnutls_ecc_curve_get_size (ecc_curve_t curve);
-ecc_curve_t _gnutls_ecc_curve_get_id (const char *name);
+const gnutls_ecc_curve_entry_st * _gnutls_ecc_curve_get_params 
(gnutls_ecc_curve_t curve);
+gnutls_ecc_curve_t _gnutls_ecc_curve_get_id (const char *name);
+int _gnutls_tls_id_to_ecc_curve (int num);
+int _gnutls_ecc_curve_get_tls_id (gnutls_ecc_curve_t supported_ecc);
+const char * _gnutls_ecc_curve_get_oid (gnutls_ecc_curve_t curve);
+gnutls_ecc_curve_t _gnutls_oid_to_ecc_curve (const char* oid);
+
+#define MAX_ECC_CURVE_SIZE 66
 
 #endif
diff --git a/lib/openpgp/Makefile.am b/lib/algorithms/Makefile.am
similarity index 78%
copy from lib/openpgp/Makefile.am
copy to lib/algorithms/Makefile.am
index 4f00d70..5fe4a38 100644
--- a/lib/openpgp/Makefile.am
+++ b/lib/algorithms/Makefile.am
@@ -1,6 +1,5 @@
 ## Process this file with automake to produce Makefile.in
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-# Free Software Foundation, Inc.
+# Copyright (C) 2011 Free Software Foundation, Inc.
 #
 # Author: Nikos Mavrogiannopoulos
 #
@@ -33,9 +32,7 @@ if ENABLE_MINITASN1
 AM_CPPFLAGS += -I$(srcdir)/../minitasn1
 endif
 
-noinst_LTLIBRARIES = libgnutls_openpgp.la
+noinst_LTLIBRARIES = libgnutls_alg.la
 
-COBJECTS = pgp.c pgpverify.c extras.c compat.c privkey.c output.c      \
-       gnutls_openpgp.c
-
-libgnutls_openpgp_la_SOURCES = $(COBJECTS) openpgp_int.h gnutls_openpgp.h
+libgnutls_alg_la_SOURCES = cert_types.c ciphers.c ciphersuites.c \
+       ecc.c kx.c mac.c protocols.c publickey.c secparams.c sign.c
diff --git a/lib/algorithms/cert_types.c b/lib/algorithms/cert_types.c
new file mode 100644
index 0000000..b0f2a88
--- /dev/null
+++ b/lib/algorithms/cert_types.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+/**
+ * gnutls_certificate_type_get_name:
+ * @type: is a certificate type
+ *
+ * Convert a #gnutls_certificate_type_t type to a string.
+ *
+ * Returns: a string that contains the name of the specified
+ *   certificate type, or %NULL in case of unknown types.
+ **/
+const char *
+gnutls_certificate_type_get_name (gnutls_certificate_type_t type)
+{
+  const char *ret = NULL;
+
+  if (type == GNUTLS_CRT_X509)
+    ret = "X.509";
+  if (type == GNUTLS_CRT_OPENPGP)
+    ret = "OPENPGP";
+
+  return ret;
+}
+
+/**
+ * gnutls_certificate_type_get_id:
+ * @name: is a certificate type name
+ *
+ * The names are compared in a case insensitive way.
+ *
+ * Returns: a #gnutls_certificate_type_t for the specified in a
+ *   string certificate type, or %GNUTLS_CRT_UNKNOWN on error.
+ **/
+gnutls_certificate_type_t
+gnutls_certificate_type_get_id (const char *name)
+{
+  gnutls_certificate_type_t ret = GNUTLS_CRT_UNKNOWN;
+
+  if (strcasecmp (name, "X.509") == 0 || strcasecmp (name, "X509") == 0)
+    return GNUTLS_CRT_X509;
+  if (strcasecmp (name, "OPENPGP") == 0)
+    return GNUTLS_CRT_OPENPGP;
+
+  return ret;
+}
+
+static const gnutls_certificate_type_t supported_certificate_types[] = {
+  GNUTLS_CRT_X509,
+  GNUTLS_CRT_OPENPGP,
+  0
+};
+
+/**
+ * gnutls_certificate_type_list:
+ *
+ * Get a list of certificate types.  Note that to be able to use
+ * OpenPGP certificates, you must link to libgnutls-extra and call
+ * gnutls_global_init_extra().
+ *
+ * Returns: a zero-terminated list of #gnutls_certificate_type_t
+ *   integers indicating the available certificate types.
+ **/
+const gnutls_certificate_type_t *
+gnutls_certificate_type_list (void)
+{
+  return supported_certificate_types;
+}
+
+
+
+
diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c
new file mode 100644
index 0000000..88c045e
--- /dev/null
+++ b/lib/algorithms/ciphers.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+struct gnutls_cipher_entry
+{
+  const char *name;
+  gnutls_cipher_algorithm_t id;
+  uint16_t blocksize;
+  uint16_t keysize;
+  unsigned block:1;
+  uint16_t iv; /* the size of IV */
+  unsigned export_flag:1; /* 0 non export */
+  unsigned auth:1; /* Whether it is authenc cipher */
+};
+typedef struct gnutls_cipher_entry gnutls_cipher_entry;
+
+/* Note that all algorithms are in CBC or STREAM modes. 
+ * Do not add any algorithms in other modes (avoid modified algorithms).
+ * View first: "The order of encryption and authentication for
+ * protecting communications" by Hugo Krawczyk - CRYPTO 2001
+ *
+ * Make sure to updated MAX_CIPHER_BLOCK_SIZE and MAX_CIPHER_KEY_SIZE as well.
+ */
+static const gnutls_cipher_entry algorithms[] = {
+  {"AES-256-CBC", GNUTLS_CIPHER_AES_256_CBC, 16, 32, CIPHER_BLOCK, 16, 0, 0},
+  {"AES-192-CBC", GNUTLS_CIPHER_AES_192_CBC, 16, 24, CIPHER_BLOCK, 16, 0, 0},
+  {"AES-128-CBC", GNUTLS_CIPHER_AES_128_CBC, 16, 16, CIPHER_BLOCK, 16, 0, 0},
+  {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_STREAM, 
AEAD_IMPLICIT_DATA_SIZE, 0, 1},
+  {"3DES-CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8, 0, 0},
+  {"DES-CBC", GNUTLS_CIPHER_DES_CBC, 8, 8, CIPHER_BLOCK, 8, 0, 0},
+  {"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM, 0, 0, 0},
+  {"ARCFOUR-40", GNUTLS_CIPHER_ARCFOUR_40, 1, 5, CIPHER_STREAM, 0, 1, 0},
+  {"RC2-40", GNUTLS_CIPHER_RC2_40_CBC, 8, 5, CIPHER_BLOCK, 8, 1, 0},
+#ifdef ENABLE_CAMELLIA
+  {"CAMELLIA-256-CBC", GNUTLS_CIPHER_CAMELLIA_256_CBC, 16, 32, CIPHER_BLOCK,
+   16, 0, 0},
+  {"CAMELLIA-128-CBC", GNUTLS_CIPHER_CAMELLIA_128_CBC, 16, 16, CIPHER_BLOCK,
+   16, 0, 0},
+#endif
+
+#ifdef ENABLE_OPENPGP
+  {"IDEA-PGP-CFB", GNUTLS_CIPHER_IDEA_PGP_CFB, 8, 16, CIPHER_BLOCK, 8, 0, 0},
+  {"3DES-PGP-CFB", GNUTLS_CIPHER_3DES_PGP_CFB, 8, 24, CIPHER_BLOCK, 8, 0, 0},
+  {"CAST5-PGP-CFB", GNUTLS_CIPHER_CAST5_PGP_CFB, 8, 16, CIPHER_BLOCK, 8, 0, 0},
+  {"BLOWFISH-PGP-CFB", GNUTLS_CIPHER_BLOWFISH_PGP_CFB, 8,
+   16 /*actually unlimited */ , CIPHER_BLOCK, 8, 0, 0},
+  {"SAFER-SK128-PGP-CFB", GNUTLS_CIPHER_SAFER_SK128_PGP_CFB, 8, 16,
+   CIPHER_BLOCK, 8, 0, 0},
+  {"AES-128-PGP-CFB", GNUTLS_CIPHER_AES128_PGP_CFB, 16, 16, CIPHER_BLOCK, 16,
+   0, 0},
+  {"AES-192-PGP-CFB", GNUTLS_CIPHER_AES192_PGP_CFB, 16, 24, CIPHER_BLOCK, 16,
+   0, 0},
+  {"AES-256-PGP-CFB", GNUTLS_CIPHER_AES256_PGP_CFB, 16, 32, CIPHER_BLOCK, 16,
+   0, 0},
+  {"TWOFISH-PGP-CFB", GNUTLS_CIPHER_TWOFISH_PGP_CFB, 16, 16, CIPHER_BLOCK, 16,
+   0, 0},
+#endif
+  {"NULL", GNUTLS_CIPHER_NULL, 1, 0, CIPHER_STREAM, 0, 0, 0},
+  {0, 0, 0, 0, 0, 0, 0}
+};
+
+#define GNUTLS_CIPHER_LOOP(b) \
+        const gnutls_cipher_entry *p; \
+                for(p = algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_ALG_LOOP(a) \
+                        GNUTLS_CIPHER_LOOP( if(p->id == algorithm) { a; break; 
} )
+
+/* CIPHER functions */
+
+/**
+ * gnutls_cipher_get_block_size:
+ * @algorithm: is an encryption algorithm
+ *
+ * Get block size for encryption algorithm.
+ *
+ * Returns: block size for encryption algorithm.
+ *
+ * Since: 2.10.0
+ **/
+int
+gnutls_cipher_get_block_size (gnutls_cipher_algorithm_t algorithm)
+{
+  size_t ret = 0;
+  GNUTLS_ALG_LOOP (ret = p->blocksize);
+  return ret;
+
+}
+
+ /* returns the priority */
+int
+_gnutls_cipher_priority (gnutls_session_t session,
+                         gnutls_cipher_algorithm_t algorithm)
+{
+  unsigned int i;
+  for (i = 0; i < session->internals.priorities.cipher.algorithms; i++)
+    {
+      if (session->internals.priorities.cipher.priority[i] == algorithm)
+        return i;
+    }
+  return -1;
+}
+
+
+int
+_gnutls_cipher_is_block (gnutls_cipher_algorithm_t algorithm)
+{
+  size_t ret = 0;
+
+  GNUTLS_ALG_LOOP (ret = p->block);
+  return ret;
+
+}
+
+int
+_gnutls_cipher_algo_is_aead (gnutls_cipher_algorithm_t algorithm)
+{
+  size_t ret = 0;
+
+  GNUTLS_ALG_LOOP (ret = p->auth);
+  return ret;
+
+}
+
+/**
+ * gnutls_cipher_get_key_size:
+ * @algorithm: is an encryption algorithm
+ *
+ * Get key size for cipher.
+ *
+ * Returns: length (in bytes) of the given cipher's key size, or 0 if
+ *   the given cipher is invalid.
+ **/
+size_t
+gnutls_cipher_get_key_size (gnutls_cipher_algorithm_t algorithm)
+{                               /* In bytes */
+  size_t ret = 0;
+  GNUTLS_ALG_LOOP (ret = p->keysize);
+  return ret;
+
+}
+
+int
+_gnutls_cipher_get_iv_size (gnutls_cipher_algorithm_t algorithm)
+{                               /* In bytes */
+  size_t ret = 0;
+  GNUTLS_ALG_LOOP (ret = p->iv);
+  return ret;
+
+}
+
+int
+_gnutls_cipher_get_export_flag (gnutls_cipher_algorithm_t algorithm)
+{                               /* In bytes */
+  size_t ret = 0;
+  GNUTLS_ALG_LOOP (ret = p->export_flag);
+  return ret;
+
+}
+
+/**
+ * gnutls_cipher_get_name:
+ * @algorithm: is an encryption algorithm
+ *
+ * Convert a #gnutls_cipher_algorithm_t type to a string.
+ *
+ * Returns: a pointer to a string that contains the name of the
+ *   specified cipher, or %NULL.
+ **/
+const char *
+gnutls_cipher_get_name (gnutls_cipher_algorithm_t algorithm)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_ALG_LOOP (ret = p->name);
+
+  return ret;
+}
+
+/**
+ * gnutls_cipher_get_id:
+ * @name: is a MAC algorithm name
+ *
+ * The names are compared in a case insensitive way.
+ *
+ * Returns: return a #gnutls_cipher_algorithm_t value corresponding to
+ *   the specified cipher, or %GNUTLS_CIPHER_UNKNOWN on error.
+ **/
+gnutls_cipher_algorithm_t
+gnutls_cipher_get_id (const char *name)
+{
+  gnutls_cipher_algorithm_t ret = GNUTLS_CIPHER_UNKNOWN;
+
+  GNUTLS_CIPHER_LOOP (
+    if (strcasecmp (p->name, name) == 0) 
+      {
+        ret = p->id;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_cipher_list:
+ *
+ * Get a list of supported cipher algorithms.  Note that not
+ * necessarily all ciphers are supported as TLS cipher suites.  For
+ * example, DES is not supported as a cipher suite, but is supported
+ * for other purposes (e.g., PKCS#8 or similar).
+ *
+ * This function is not thread safe.
+ *
+ * Returns: a zero-terminated list of #gnutls_cipher_algorithm_t
+ *   integers indicating the available ciphers.
+ *
+ **/
+const gnutls_cipher_algorithm_t *
+gnutls_cipher_list (void)
+{
+static gnutls_cipher_algorithm_t supported_ciphers[MAX_ALGOS] = {0};
+
+  if (supported_ciphers[0] == 0)
+    {
+      int i = 0;
+
+      GNUTLS_CIPHER_LOOP (supported_ciphers[i++]=p->id);
+      supported_ciphers[i++]=0;
+    }
+
+  return supported_ciphers;
+}
+
+int
+_gnutls_cipher_is_ok (gnutls_cipher_algorithm_t algorithm)
+{
+  ssize_t ret = -1;
+  GNUTLS_ALG_LOOP (ret = p->id);
+  if (ret >= 0)
+    ret = 0;
+  else
+    ret = 1;
+  return ret;
+}
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c
new file mode 100644
index 0000000..6b7f4eb
--- /dev/null
+++ b/lib/algorithms/ciphersuites.c
@@ -0,0 +1,924 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+static int
+compare_algo (gnutls_session_t session, const void *i_A1,
+                      const void *i_A2);
+static void
+_gnutls_qsort (gnutls_session_t session, void *_base, size_t nmemb,
+               size_t size, int (*compar) (gnutls_session_t, const void *,
+                                           const void *));
+
+/* Cipher SUITES */
+#define GNUTLS_CIPHER_SUITE_ENTRY( name, block_algorithm, kx_algorithm, 
mac_algorithm, min_version, max_version, dtls ) \
+       { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, 
min_version, max_version, dtls}
+
+typedef struct
+{
+  const char *name;
+  cipher_suite_st id;
+  gnutls_cipher_algorithm_t block_algorithm;
+  gnutls_kx_algorithm_t kx_algorithm;
+  gnutls_mac_algorithm_t mac_algorithm;
+  gnutls_protocol_t min_version;        /* this cipher suite is supported
+                                         * from 'version' and above;
+                                         */
+  gnutls_protocol_t max_version;        /* this cipher suite is not supported 
after that */
+  int dtls:1; /* whether this ciphersuite is valid in DTLS */
+} gnutls_cipher_suite_entry;
+
+/* RSA with NULL cipher and MD5 MAC
+ * for test purposes.
+ */
+#define GNUTLS_RSA_NULL_MD5 { 0x00, 0x01 }
+#define GNUTLS_RSA_NULL_SHA1 { 0x00, 0x02 }
+#define GNUTLS_RSA_NULL_SHA256 { 0x00, 0x3B }
+
+/* ANONymous cipher suites.
+ */
+
+#define GNUTLS_ANON_DH_3DES_EDE_CBC_SHA1 { 0x00, 0x1B }
+#define GNUTLS_ANON_DH_ARCFOUR_MD5 { 0x00, 0x18 }
+
+ /* rfc3268: */
+#define GNUTLS_ANON_DH_AES_128_CBC_SHA1 { 0x00, 0x34 }
+#define GNUTLS_ANON_DH_AES_256_CBC_SHA1 { 0x00, 0x3A }
+
+/* rfc4132 */
+#ifdef ENABLE_CAMELLIA
+#define GNUTLS_ANON_DH_CAMELLIA_128_CBC_SHA1 { 0x00,0x46 }
+#define GNUTLS_ANON_DH_CAMELLIA_256_CBC_SHA1 { 0x00,0x89 }
+#endif
+
+#define GNUTLS_ANON_DH_AES_128_CBC_SHA256 { 0x00, 0x6C }
+#define GNUTLS_ANON_DH_AES_256_CBC_SHA256 { 0x00, 0x6D }
+
+/* PSK (not in TLS 1.0)
+ * draft-ietf-tls-psk:
+ */
+#define GNUTLS_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8A }
+#define GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8B }
+#define GNUTLS_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x8C }
+#define GNUTLS_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x8D }
+
+#define GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8E }
+#define GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8F }
+#define GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x90 }
+#define GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x91 }
+
+
+/* SRP (rfc5054)
+ */
+#define GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1A }
+#define GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1B }
+#define GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1 { 0xC0, 0x1C }
+
+#define GNUTLS_SRP_SHA_AES_128_CBC_SHA1 { 0xC0, 0x1D }
+#define GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1 { 0xC0, 0x1E }
+#define GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1 { 0xC0, 0x1F }
+
+#define GNUTLS_SRP_SHA_AES_256_CBC_SHA1 { 0xC0, 0x20 }
+#define GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1 { 0xC0, 0x21 }
+#define GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1 { 0xC0, 0x22 }
+
+/* RSA
+ */
+#define GNUTLS_RSA_ARCFOUR_SHA1 { 0x00, 0x05 }
+#define GNUTLS_RSA_ARCFOUR_MD5 { 0x00, 0x04 }
+#define GNUTLS_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x0A }
+
+#define GNUTLS_RSA_EXPORT_ARCFOUR_40_MD5 { 0x00, 0x03 }
+
+/* rfc3268:
+ */
+#define GNUTLS_RSA_AES_128_CBC_SHA1 { 0x00, 0x2F }
+#define GNUTLS_RSA_AES_256_CBC_SHA1 { 0x00, 0x35 }
+
+/* rfc4132 */
+#ifdef ENABLE_CAMELLIA
+#define GNUTLS_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x41 }
+#define GNUTLS_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x84 }
+#endif
+
+#define GNUTLS_RSA_AES_128_CBC_SHA256 { 0x00, 0x3C }
+#define GNUTLS_RSA_AES_256_CBC_SHA256 { 0x00, 0x3D }
+
+/* DHE DSS
+ */
+
+#define GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1 { 0x00, 0x13 }
+
+
+/* draft-ietf-tls-56-bit-ciphersuites-01:
+ */
+#define GNUTLS_DHE_DSS_ARCFOUR_SHA1 { 0x00, 0x66 }
+
+
+/* rfc3268:
+ */
+#define GNUTLS_DHE_DSS_AES_256_CBC_SHA1 { 0x00, 0x38 }
+#define GNUTLS_DHE_DSS_AES_128_CBC_SHA1 { 0x00, 0x32 }
+
+/* rfc4132 */
+#ifdef ENABLE_CAMELLIA
+#define GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1 { 0x00,0x44 }
+#define GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1 { 0x00,0x87 }
+#endif
+
+#define GNUTLS_DHE_DSS_AES_128_CBC_SHA256 { 0x00, 0x40 }
+#define GNUTLS_DHE_DSS_AES_256_CBC_SHA256 { 0x00, 0x6A }
+
+/* DHE RSA
+ */
+#define GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x16 }
+
+/* rfc3268:
+ */
+#define GNUTLS_DHE_RSA_AES_128_CBC_SHA1 { 0x00, 0x33 }
+#define GNUTLS_DHE_RSA_AES_256_CBC_SHA1 { 0x00, 0x39 }
+
+/* rfc4132 */
+#ifdef ENABLE_CAMELLIA
+#define GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x45 }
+#define GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x88 }
+#endif
+
+#define GNUTLS_DHE_RSA_AES_128_CBC_SHA256 { 0x00, 0x67 }
+#define GNUTLS_DHE_RSA_AES_256_CBC_SHA256 { 0x00, 0x6B }
+
+/* GCM: RFC5288 */
+#define GNUTLS_RSA_AES_128_GCM_SHA256 { 0x00, 0x9C }
+#define GNUTLS_DHE_RSA_AES_128_GCM_SHA256 {0x00,0x9E}
+#define GNUTLS_DHE_DSS_AES_128_GCM_SHA256 {0x00,0xA2}
+#define GNUTLS_DH_ANON_AES_128_GCM_SHA256 {0x00,0xA6}
+
+/* RFC 5487 */
+/* GCM-PSK */
+#define GNUTLS_PSK_AES_128_GCM_SHA256 { 0x00, 0xA8 }
+#define GNUTLS_DHE_PSK_AES_128_GCM_SHA256 { 0x00, 0xAA }
+
+/* PSK - SHA256 HMAC */
+#define GNUTLS_PSK_AES_128_CBC_SHA256 { 0x00, 0xAE }
+#define GNUTLS_DHE_PSK_AES_128_CBC_SHA256 { 0x00, 0xB2 }
+
+#define GNUTLS_PSK_NULL_SHA256 { 0x00, 0xB0 }
+#define GNUTLS_DHE_PSK_NULL_SHA256 { 0x00, 0xB4 }
+
+/* ECC */
+#define GNUTLS_ECDH_ANON_NULL_SHA { 0xC0, 0x15 }
+#define GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA { 0xC0, 0x17 }
+#define GNUTLS_ECDH_ANON_AES_128_CBC_SHA { 0xC0, 0x18 }
+#define GNUTLS_ECDH_ANON_AES_256_CBC_SHA { 0xC0, 0x19 }
+
+/* ECC-RSA */
+#define GNUTLS_ECDHE_RSA_NULL_SHA { 0xC0, 0x10 }
+#define GNUTLS_ECDHE_RSA_3DES_EDE_CBC_SHA { 0xC0, 0x12 }
+#define GNUTLS_ECDHE_RSA_AES_128_CBC_SHA { 0xC0, 0x13 }
+#define GNUTLS_ECDHE_RSA_AES_256_CBC_SHA { 0xC0, 0x14 }
+
+
+#define CIPHER_SUITES_COUNT 
sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry)-1
+
+/* FIXME: what we don't handle here is TLS 1.2 requirement
+ * that each ciphersuite has it's own PRF algorithm. Now we
+ * assume that each one uses the SHA-256 PRF in TLS 1.2.
+ */
+
+static const gnutls_cipher_suite_entry cs_algorithms[] = {
+  /* ANON_DH */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_ARCFOUR_MD5,
+                             GNUTLS_CIPHER_ARCFOUR_128,
+                             GNUTLS_KX_ANON_DH, GNUTLS_MAC_MD5,
+                             GNUTLS_SSL3, GNUTLS_VERSION_MAX, 0),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, ),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+#ifdef ENABLE_CAMELLIA
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_CAMELLIA_128_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_128_CBC,
+                             GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_CAMELLIA_256_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_256_CBC,
+                             GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+#endif
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_128_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_256_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+
+  /* PSK */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_ARCFOUR_SHA1,
+                             GNUTLS_CIPHER_ARCFOUR, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 0),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_AES_128_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_AES_128_GCM_SHA256,
+                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_NULL_SHA256,
+                             GNUTLS_CIPHER_NULL, GNUTLS_KX_PSK,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  /* DHE-PSK */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1,
+                             GNUTLS_CIPHER_ARCFOUR, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 0),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_AES_128_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_AES_128_GCM_SHA256,
+                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_NULL_SHA256,
+                             GNUTLS_CIPHER_NULL, GNUTLS_KX_DHE_PSK,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  /* SRP */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_SRP,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_SRP,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_SRP_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_SRP_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_SRP_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_SRP_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+
+  /* DHE_DSS */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_ARCFOUR_SHA1,
+                             GNUTLS_CIPHER_ARCFOUR_128, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 0),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+#ifdef ENABLE_CAMELLIA
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_128_CBC,
+                             GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_256_CBC,
+                             GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+#endif
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_256_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  /* DHE_RSA */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+#ifdef ENABLE_CAMELLIA
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_128_CBC,
+                             GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_256_CBC,
+                             GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+#endif
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_256_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  /* RSA-NULL */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_MD5,
+                             GNUTLS_CIPHER_NULL,
+                             GNUTLS_KX_RSA, GNUTLS_MAC_MD5, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_SHA1,
+                             GNUTLS_CIPHER_NULL,
+                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_SHA256,
+                             GNUTLS_CIPHER_NULL,
+                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+
+  /* RSA-EXPORT */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_EXPORT_ARCFOUR_40_MD5,
+                             GNUTLS_CIPHER_ARCFOUR_40,
+                             GNUTLS_KX_RSA_EXPORT, GNUTLS_MAC_MD5,
+                             GNUTLS_SSL3, GNUTLS_TLS1_0, 0),
+
+  /* RSA */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_SHA1,
+                             GNUTLS_CIPHER_ARCFOUR_128,
+                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 0),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_MD5,
+                             GNUTLS_CIPHER_ARCFOUR_128,
+                             GNUTLS_KX_RSA, GNUTLS_MAC_MD5, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 0),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_3DES_EDE_CBC_SHA1,
+                             GNUTLS_CIPHER_3DES_CBC,
+                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA1,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
+                             GNUTLS_VERSION_MAX, 1),
+#ifdef ENABLE_CAMELLIA
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_CAMELLIA_128_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_128_CBC, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_CAMELLIA_256_CBC_SHA1,
+                             GNUTLS_CIPHER_CAMELLIA_256_CBC, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
+                             GNUTLS_VERSION_MAX, 1),
+#endif
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA256,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+/* GCM */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_GCM_SHA256,
+                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_RSA,
+                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_GCM_SHA256,
+                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_DHE_RSA,
+                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_GCM_SHA256,
+                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_DHE_DSS,
+                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DH_ANON_AES_128_GCM_SHA256,
+                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_ANON_DH,
+                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+                             GNUTLS_VERSION_MAX, 1),
+/* ECC-ANON */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_NULL_SHA,
+                             GNUTLS_CIPHER_NULL, GNUTLS_KX_ANON_ECDH,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ANON_ECDH,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_AES_128_CBC_SHA,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_ECDH,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_AES_256_CBC_SHA,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_ECDH,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+/* ECC-RSA */
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_NULL_SHA,
+                             GNUTLS_CIPHER_NULL, GNUTLS_KX_ECDHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_3DES_EDE_CBC_SHA,
+                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ECDHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_AES_128_CBC_SHA,
+                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ECDHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_AES_256_CBC_SHA,
+                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ECDHE_RSA,
+                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
+                             GNUTLS_VERSION_MAX, 1),
+  {0, {{0, 0}}, 0, 0, 0, 0, 0, 0}
+};
+
+#define GNUTLS_CIPHER_SUITE_LOOP(b) \
+        const gnutls_cipher_suite_entry *p; \
+                for(p = cs_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_CIPHER_SUITE_ALG_LOOP(a) \
+                        GNUTLS_CIPHER_SUITE_LOOP( if( (p->id.suite[0] == 
suite->suite[0]) && (p->id.suite[1] == suite->suite[1])) { a; break; } )
+
+
+/* Cipher Suite's functions */
+gnutls_cipher_algorithm_t
+_gnutls_cipher_suite_get_cipher_algo (const cipher_suite_st * suite)
+{
+  int ret = 0;
+  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->block_algorithm);
+  return ret;
+}
+
+static int
+_gnutls_cipher_suite_is_version_supported (gnutls_session_t session, const 
cipher_suite_st * suite)
+{
+  int ret = 0;
+  int version = gnutls_protocol_get_version( session);
+  
+  GNUTLS_CIPHER_SUITE_ALG_LOOP (if (version >= p->min_version
+                                 && version <= p->max_version) ret = 1;
+                                 if (IS_DTLS(session) && p->dtls==0) ret = 0;);
+  return ret;
+}
+
+gnutls_kx_algorithm_t
+_gnutls_cipher_suite_get_kx_algo (const cipher_suite_st * suite)
+{
+  int ret = 0;
+
+  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->kx_algorithm);
+  return ret;
+
+}
+
+gnutls_mac_algorithm_t
+_gnutls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
+{                               /* In bytes */
+  int ret = 0;
+  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->mac_algorithm);
+  return ret;
+
+}
+
+const char *
+_gnutls_cipher_suite_get_name (cipher_suite_st * suite)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_") - 1);
+
+  return ret;
+}
+
+/**
+ * gnutls_cipher_suite_get_name:
+ * @kx_algorithm: is a Key exchange algorithm
+ * @cipher_algorithm: is a cipher algorithm
+ * @mac_algorithm: is a MAC algorithm
+ *
+ * Note that the full cipher suite name must be prepended by TLS or
+ * SSL depending of the protocol in use.
+ *
+ * Returns: a string that contains the name of a TLS cipher suite,
+ * specified by the given algorithms, or %NULL.
+ **/
+const char *
+gnutls_cipher_suite_get_name (gnutls_kx_algorithm_t kx_algorithm,
+                              gnutls_cipher_algorithm_t cipher_algorithm,
+                              gnutls_mac_algorithm_t mac_algorithm)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_CIPHER_SUITE_LOOP (
+    if (kx_algorithm == p->kx_algorithm &&
+        cipher_algorithm == p->block_algorithm && mac_algorithm == 
p->mac_algorithm)
+      {
+        ret = p->name + sizeof ("GNUTLS_") - 1);
+        break;
+      }
+
+  return ret;
+}
+
+/**
+ * gnutls_cipher_suite_info:
+ * @idx: index of cipher suite to get information about, starts on 0.
+ * @cs_id: output buffer with room for 2 bytes, indicating cipher suite value
+ * @kx: output variable indicating key exchange algorithm, or %NULL.
+ * @cipher: output variable indicating cipher, or %NULL.
+ * @mac: output variable indicating MAC algorithm, or %NULL.
+ * @min_version: output variable indicating TLS protocol version, or %NULL.
+ *
+ * Get information about supported cipher suites.  Use the function
+ * iteratively to get information about all supported cipher suites.
+ * Call with idx=0 to get information about first cipher suite, then
+ * idx=1 and so on until the function returns NULL.
+ *
+ * Returns: the name of @idx cipher suite, and set the information
+ * about the cipher suite in the output variables.  If @idx is out of
+ * bounds, %NULL is returned.
+ **/
+const char *
+gnutls_cipher_suite_info (size_t idx,
+                          char *cs_id,
+                          gnutls_kx_algorithm_t * kx,
+                          gnutls_cipher_algorithm_t * cipher,
+                          gnutls_mac_algorithm_t * mac,
+                          gnutls_protocol_t * min_version)
+{
+  if (idx >= CIPHER_SUITES_COUNT)
+    return NULL;
+
+  if (cs_id)
+    memcpy (cs_id, cs_algorithms[idx].id.suite, 2);
+  if (kx)
+    *kx = cs_algorithms[idx].kx_algorithm;
+  if (cipher)
+    *cipher = cs_algorithms[idx].block_algorithm;
+  if (mac)
+    *mac = cs_algorithms[idx].mac_algorithm;
+  if (min_version)
+    *min_version = cs_algorithms[idx].min_version;
+
+  return cs_algorithms[idx].name + sizeof ("GNU") - 1;
+}
+
+
+static inline int
+_gnutls_cipher_suite_is_ok (cipher_suite_st * suite)
+{
+  size_t ret;
+  const char *name = NULL;
+
+  GNUTLS_CIPHER_SUITE_ALG_LOOP (name = p->name);
+  if (name != NULL)
+    ret = 0;
+  else
+    ret = 1;
+  return ret;
+
+}
+
+int
+_gnutls_supported_ciphersuites_sorted (gnutls_session_t session,
+                                       cipher_suite_st ** ciphers)
+{
+
+  int count;
+
+  count = _gnutls_supported_ciphersuites (session, ciphers);
+  if (count <= 0)
+    {
+      gnutls_assert ();
+      return count;
+    }
+
+  _gnutls_qsort (session, *ciphers, count,
+                 sizeof (cipher_suite_st), compare_algo);
+
+  return count;
+}
+
+int
+_gnutls_supported_ciphersuites (gnutls_session_t session,
+                                cipher_suite_st ** _ciphers)
+{
+
+  unsigned int i, ret_count, j;
+  unsigned int count = CIPHER_SUITES_COUNT;
+  cipher_suite_st *tmp_ciphers;
+  cipher_suite_st *ciphers;
+
+  if (count == 0)
+    {
+      return 0;
+    }
+
+  tmp_ciphers = gnutls_malloc (count * sizeof (cipher_suite_st));
+  if (tmp_ciphers == NULL)
+    return GNUTLS_E_MEMORY_ERROR;
+
+  ciphers = gnutls_malloc (count * sizeof (cipher_suite_st));
+  if (ciphers == NULL)
+    {
+      gnutls_free (tmp_ciphers);
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      memcpy (&tmp_ciphers[i], &cs_algorithms[i].id,
+              sizeof (cipher_suite_st));
+    }
+
+  for (i = j = 0; i < count; i++)
+    {
+      /* remove private cipher suites, if requested.
+       */
+      if (tmp_ciphers[i].suite[0] == 0xFF &&
+          session->internals.enable_private == 0)
+        continue;
+
+      /* remove cipher suites which do not support the
+       * protocol version used.
+       */
+      if (_gnutls_cipher_suite_is_version_supported (session, &tmp_ciphers[i])
+          == 0)
+        continue;
+
+      if (_gnutls_kx_priority
+          (session, _gnutls_cipher_suite_get_kx_algo (&tmp_ciphers[i])) < 0)
+        continue;
+
+      if (_gnutls_mac_priority
+          (session, _gnutls_cipher_suite_get_mac_algo (&tmp_ciphers[i])) < 0)
+        continue;
+
+      if (_gnutls_cipher_priority
+          (session,
+           _gnutls_cipher_suite_get_cipher_algo (&tmp_ciphers[i])) < 0)
+        continue;
+
+      memcpy (&ciphers[j], &tmp_ciphers[i], sizeof (cipher_suite_st));
+      j++;
+    }
+
+  ret_count = j;
+
+#if 0                           /* expensive */
+  if (ret_count > 0 && ret_count != count)
+    {
+      ciphers =
+        gnutls_realloc_fast (ciphers, ret_count * sizeof (cipher_suite_st));
+    }
+  else
+    {
+      if (ret_count != count)
+        {
+          gnutls_free (ciphers);
+          ciphers = NULL;
+        }
+    }
+#endif
+
+  gnutls_free (tmp_ciphers);
+
+  /* This function can no longer return 0 cipher suites.
+   * It returns an error code instead.
+   */
+  if (ret_count == 0)
+    {
+      gnutls_assert ();
+      gnutls_free (ciphers);
+      return GNUTLS_E_NO_CIPHER_SUITES;
+    }
+  *_ciphers = ciphers;
+  return ret_count;
+}
+
+#define SWAP(x, y) memcpy(tmp,x,size); \
+                  memcpy(x,y,size); \
+                  memcpy(y,tmp,size);
+
+#define MAX_ELEM_SIZE 4
+static inline int
+_gnutls_partition (gnutls_session_t session, void *_base,
+                   size_t nmemb, size_t size,
+                   int (*compar) (gnutls_session_t,
+                                  const void *, const void *))
+{
+  uint8_t *base = _base;
+  uint8_t tmp[MAX_ELEM_SIZE];
+  uint8_t ptmp[MAX_ELEM_SIZE];
+  unsigned int pivot;
+  unsigned int i, j;
+  unsigned int full;
+
+  i = pivot = 0;
+  j = full = (nmemb - 1) * size;
+
+  memcpy (ptmp, &base[0], size);        /* set pivot item */
+
+  while (i < j)
+    {
+      while ((compar (session, &base[i], ptmp) <= 0) && (i < full))
+        {
+          i += size;
+        }
+      while ((compar (session, &base[j], ptmp) >= 0) && (j > 0))
+        j -= size;
+
+      if (i < j)
+        {
+          SWAP (&base[j], &base[i]);
+        }
+    }
+
+  if (j > pivot)
+    {
+      SWAP (&base[pivot], &base[j]);
+      pivot = j;
+    }
+  else if (i < pivot)
+    {
+      SWAP (&base[pivot], &base[i]);
+      pivot = i;
+    }
+  return pivot / size;
+}
+
+static void
+_gnutls_qsort (gnutls_session_t session, void *_base, size_t nmemb,
+               size_t size, int (*compar) (gnutls_session_t, const void *,
+                                           const void *))
+{
+  unsigned int pivot;
+  char *base = _base;
+  size_t snmemb = nmemb;
+
+#ifdef DEBUG
+  if (size > MAX_ELEM_SIZE)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("QSORT BUG\n");
+      exit (1);
+    }
+#endif
+
+  if (snmemb <= 1)
+    return;
+  pivot = _gnutls_partition (session, _base, nmemb, size, compar);
+
+  _gnutls_qsort (session, base, pivot < nmemb ? pivot + 1 : pivot, size,
+                 compar);
+  _gnutls_qsort (session, &base[(pivot + 1) * size], nmemb - pivot - 1,
+                 size, compar);
+}
+
+
+/* a compare function for KX algorithms (using priorities). 
+ * For use with qsort 
+ */
+static int
+compare_algo (gnutls_session_t session, const void *i_A1,
+                      const void *i_A2)
+{
+  gnutls_kx_algorithm_t kA1 =
+    _gnutls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A1);
+  gnutls_kx_algorithm_t kA2 =
+    _gnutls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A2);
+  gnutls_cipher_algorithm_t cA1 =
+    _gnutls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A1);
+  gnutls_cipher_algorithm_t cA2 =
+    _gnutls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A2);
+  gnutls_mac_algorithm_t mA1 =
+    _gnutls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A1);
+  gnutls_mac_algorithm_t mA2 =
+    _gnutls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A2);
+
+  int p1 = (_gnutls_kx_priority (session, kA1) + 1) * 64;
+  int p2 = (_gnutls_kx_priority (session, kA2) + 1) * 64;
+  p1 += (_gnutls_cipher_priority (session, cA1) + 1) * 8;
+  p2 += (_gnutls_cipher_priority (session, cA2) + 1) * 8;
+  p1 += _gnutls_mac_priority (session, mA1);
+  p2 += _gnutls_mac_priority (session, mA2);
+
+  if (p1 > p2)
+    {
+      return 1;
+    }
+  else
+    {
+      if (p1 == p2)
+        {
+          return 0;
+        }
+      return -1;
+    }
+}
diff --git a/lib/algorithms/ecc.c b/lib/algorithms/ecc.c
new file mode 100644
index 0000000..2ba2869
--- /dev/null
+++ b/lib/algorithms/ecc.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+
+/* Supported ECC curves
+ */
+
+static const gnutls_ecc_curve_entry_st ecc_curves[] = {
+  {
+    .name = "SECP224R1", 
+    .oid = "1.3.132.0.33",
+    .id = GNUTLS_ECC_CURVE_SECP224R1,
+    .tls_id = 21,
+    .size = 28,
+    .prime = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+    .A = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
+    .B = "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
+    .order = "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
+    .Gx =    "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
+    .Gy =    "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
+  },
+  {
+    .name = "SECP256R1", 
+    .oid = "1.2.840.10045.3.1.7",
+    .id = GNUTLS_ECC_CURVE_SECP256R1,
+    .tls_id = 23,
+    .size = 32,
+    .prime = 
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+    .A = "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+    .B = "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+    .order = 
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+    .Gx = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+    .Gy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+  },
+  {
+    .name = "SECP384R1",
+    .oid = "1.3.132.0.34",
+    .id = GNUTLS_ECC_CURVE_SECP384R1,
+    .tls_id = 24,
+    .size = 48,
+    .prime = 
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+    .A = 
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+    .B = 
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+    .order = 
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+    .Gx = 
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+    .Gy = 
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"
+  },
+  {
+    .name = "SECP521R1",
+    .oid = "1.3.132.0.35",
+    .id = GNUTLS_ECC_CURVE_SECP521R1,
+    .tls_id = 25,
+    .size = 66,
+    .prime = 
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+    .A = 
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+    .B = 
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+    .order = 
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+    .Gx =    
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+    .Gy =    
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+  },
+  {0, 0, 0}
+};
+
+#define GNUTLS_ECC_CURVE_LOOP(b) \
+       { const gnutls_ecc_curve_entry_st *p; \
+                for(p = ecc_curves; p->name != NULL; p++) { b ; } }
+
+
+/* Returns the TLS id of the given curve
+ */
+int
+_gnutls_tls_id_to_ecc_curve (int num)
+{
+  gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
+
+  GNUTLS_ECC_CURVE_LOOP (
+  if (p->tls_id == num) 
+    {
+      ret = p->id;
+      break;
+    }
+  );
+  
+  return ret;
+}
+
+/* Maps numbers to TLS NamedCurve IDs (RFC4492).
+ * Returns a negative number on error.
+ */
+int
+_gnutls_ecc_curve_get_tls_id (gnutls_ecc_curve_t supported_ecc)
+{
+  int ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  GNUTLS_ECC_CURVE_LOOP (
+  if (p->id == supported_ecc) 
+    {
+      ret = p->tls_id;
+      break;
+    }
+  );
+  
+  return ret;
+}
+
+/*-
+ * _gnutls_oid_to_ecc_curve:
+ * @oid: is a curve's OID
+ *
+ * Returns: return a #gnutls_ecc_curve_t value corresponding to
+ *   the specified OID, or %GNUTLS_ECC_CURVE_INVALID on error.
+ -*/
+gnutls_ecc_curve_t _gnutls_oid_to_ecc_curve (const char* oid)
+{
+  gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
+
+  GNUTLS_ECC_CURVE_LOOP (
+  if (strcasecmp (p->oid, oid) == 0) 
+    {
+      ret = p->id;
+      break;
+    }
+  );
+
+  return ret;
+}
+
+/*-
+ * _gnutls_ecc_curve_get_id:
+ * @name: is a MAC algorithm name
+ *
+ * The names are compared in a case insensitive way.
+ *
+ * Returns: return a #gnutls_ecc_curve_t value corresponding to
+ *   the specified curve, or %GNUTLS_ECC_CURVE_INVALID on error.
+ -*/
+gnutls_ecc_curve_t
+_gnutls_ecc_curve_get_id (const char *name)
+{
+  gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
+
+  GNUTLS_ECC_CURVE_LOOP (
+  if (strcasecmp (p->name, name) == 0) 
+    {
+      ret = p->id;
+      break;
+    }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_ecc_curve_get_name:
+ * @curve: is an ECC curve
+ *
+ * Convert a #gnutls_ecc_curve_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified
+ *   curve or %NULL.
+ **/
+const char *
+gnutls_ecc_curve_get_name (gnutls_ecc_curve_t curve)
+{
+  const char *ret = NULL;
+
+  GNUTLS_ECC_CURVE_LOOP(
+    if (p->id == curve)
+      {
+        ret = p->name;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/*-
+ * _gnutls_ecc_curve_get_oid:
+ * @curve: is an ECC curve
+ *
+ * Convert a #gnutls_ecc_curve_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified
+ *   curve or %NULL.
+ -*/
+const char *
+_gnutls_ecc_curve_get_oid (gnutls_ecc_curve_t curve)
+{
+  const char *ret = NULL;
+
+  GNUTLS_ECC_CURVE_LOOP(
+    if (p->id == curve)
+      {
+        ret = p->oid;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/*-
+ * _gnutls_ecc_curve_get_params:
+ * @curve: is an ECC curve
+ *
+ * Returns the information on a curve.
+ *
+ * Returns: a pointer to #gnutls_ecc_curve_entry_st or %NULL.
+ -*/
+const gnutls_ecc_curve_entry_st *
+_gnutls_ecc_curve_get_params (gnutls_ecc_curve_t curve)
+{
+  const gnutls_ecc_curve_entry_st *ret = NULL;
+
+  GNUTLS_ECC_CURVE_LOOP(
+    if (p->id == curve)
+      {
+        ret = p;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_ecc_curve_get_size:
+ * @curve: is an ECC curve
+ *
+ * Returns the size in bytes of the curve.
+ *
+ * Returns: a the size or zero.
+ **/
+int gnutls_ecc_curve_get_size (gnutls_ecc_curve_t curve)
+{
+  int ret = 0;
+
+  GNUTLS_ECC_CURVE_LOOP(
+    if (p->id == curve)
+      {
+        ret = p->size;
+        break;
+      }
+  );
+
+  return ret;
+}
diff --git a/lib/algorithms/kx.c b/lib/algorithms/kx.c
new file mode 100644
index 0000000..c9d2cfb
--- /dev/null
+++ b/lib/algorithms/kx.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+
+extern mod_auth_st rsa_auth_struct;
+extern mod_auth_st rsa_export_auth_struct;
+extern mod_auth_st dhe_rsa_auth_struct;
+extern mod_auth_st ecdhe_rsa_auth_struct;
+extern mod_auth_st dhe_dss_auth_struct;
+extern mod_auth_st anon_auth_struct;
+extern mod_auth_st anon_ecdh_auth_struct;
+extern mod_auth_st srp_auth_struct;
+extern mod_auth_st psk_auth_struct;
+extern mod_auth_st dhe_psk_auth_struct;
+extern mod_auth_st srp_rsa_auth_struct;
+extern mod_auth_st srp_dss_auth_struct;
+
+
+/* Cred type mappings to KX algorithms 
+ * FIXME: The mappings are not 1-1. Some KX such as SRP_RSA require
+ * more than one credentials type.
+ */
+typedef struct
+{
+  gnutls_kx_algorithm_t algorithm;
+  gnutls_credentials_type_t client_type;
+  gnutls_credentials_type_t server_type;        /* The type of credentials a 
server
+                                                 * needs to set */
+} gnutls_cred_map;
+
+static const gnutls_cred_map cred_mappings[] = {
+  {GNUTLS_KX_ANON_DH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
+  {GNUTLS_KX_ANON_ECDH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
+  {GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
+  {GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
+  {GNUTLS_KX_ECDHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
+  {GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
+  {GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
+  {GNUTLS_KX_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
+  {GNUTLS_KX_DHE_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
+  {GNUTLS_KX_SRP, GNUTLS_CRD_SRP, GNUTLS_CRD_SRP},
+  {GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
+  {GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
+  {0, 0, 0}
+};
+
+#define GNUTLS_KX_MAP_LOOP(b) \
+        const gnutls_cred_map *p; \
+                for(p = cred_mappings; p->algorithm != 0; p++) { b ; }
+
+#define GNUTLS_KX_MAP_ALG_LOOP_SERVER(a) \
+                        GNUTLS_KX_MAP_LOOP( if(p->server_type == type) { a; 
break; })
+
+struct gnutls_kx_algo_entry
+{
+  const char *name;
+  gnutls_kx_algorithm_t algorithm;
+  mod_auth_st *auth_struct;
+  int needs_dh_params;
+  int needs_rsa_params;
+};
+typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry;
+
+static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = {
+#ifdef ENABLE_ANON
+  {"ANON-DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, 0},
+  {"ANON-ECDH", GNUTLS_KX_ANON_ECDH, &anon_ecdh_auth_struct, 0, 0},
+#endif
+  {"RSA", GNUTLS_KX_RSA, &rsa_auth_struct, 0, 0},
+  {"RSA-EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct, 0,
+   1 /* needs RSA params */ },
+  {"DHE-RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, 0},
+  {"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 1, 0},
+  {"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 0},
+
+#ifdef ENABLE_SRP
+  {"SRP-DSS", GNUTLS_KX_SRP_DSS, &srp_dss_auth_struct, 0, 0},
+  {"SRP-RSA", GNUTLS_KX_SRP_RSA, &srp_rsa_auth_struct, 0, 0},
+  {"SRP", GNUTLS_KX_SRP, &srp_auth_struct, 0, 0},
+#endif
+#ifdef ENABLE_PSK
+  {"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0, 0},
+  {"DHE-PSK", GNUTLS_KX_DHE_PSK, &dhe_psk_auth_struct,
+   1 /* needs DHE params */ , 0},
+#endif
+  {0, 0, 0, 0, 0}
+};
+
+#define GNUTLS_KX_LOOP(b) \
+        const gnutls_kx_algo_entry *p; \
+                for(p = _gnutls_kx_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_KX_ALG_LOOP(a) \
+                        GNUTLS_KX_LOOP( if(p->algorithm == algorithm) { a; 
break; } )
+
+
+/* Key EXCHANGE functions */
+mod_auth_st *
+_gnutls_kx_auth_struct (gnutls_kx_algorithm_t algorithm)
+{
+  mod_auth_st *ret = NULL;
+  GNUTLS_KX_ALG_LOOP (ret = p->auth_struct);
+  return ret;
+
+}
+
+
+int
+_gnutls_kx_priority (gnutls_session_t session,
+                     gnutls_kx_algorithm_t algorithm)
+{
+  unsigned int i;
+  for (i = 0; i < session->internals.priorities.kx.algorithms; i++)
+    {
+      if (session->internals.priorities.kx.priority[i] == algorithm)
+        return i;
+    }
+  return -1;
+}
+
+/**
+ * gnutls_kx_get_name:
+ * @algorithm: is a key exchange algorithm
+ *
+ * Convert a #gnutls_kx_algorithm_t value to a string.
+ *
+ * Returns: a pointer to a string that contains the name of the
+ *   specified key exchange algorithm, or %NULL.
+ **/
+const char *
+gnutls_kx_get_name (gnutls_kx_algorithm_t algorithm)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_KX_ALG_LOOP (ret = p->name);
+
+  return ret;
+}
+
+/**
+ * gnutls_kx_get_id:
+ * @name: is a KX name
+ *
+ * Convert a string to a #gnutls_kx_algorithm_t value.  The names are
+ * compared in a case insensitive way.
+ *
+ * Returns: an id of the specified KX algorithm, or %GNUTLS_KX_UNKNOWN
+ *   on error.
+ **/
+gnutls_kx_algorithm_t
+gnutls_kx_get_id (const char *name)
+{
+  gnutls_cipher_algorithm_t ret = GNUTLS_KX_UNKNOWN;
+
+  GNUTLS_KX_LOOP (
+    if (strcasecmp (p->name, name) == 0) 
+      {
+        ret = p->algorithm;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_kx_list:
+ *
+ * Get a list of supported key exchange algorithms.
+ *
+ * This function is not thread safe.
+ *
+ * Returns: a zero-terminated list of #gnutls_kx_algorithm_t integers
+ * indicating the available key exchange algorithms.
+ **/
+const gnutls_kx_algorithm_t *
+gnutls_kx_list (void)
+{
+static gnutls_kx_algorithm_t supported_kxs[MAX_ALGOS] = {0};
+
+  if (supported_kxs[0] == 0)
+    {
+      int i = 0;
+
+      GNUTLS_KX_LOOP (supported_kxs[i++]=p->algorithm);
+      supported_kxs[i++]=0;
+    }
+
+  return supported_kxs;
+}
+
+int
+_gnutls_kx_is_ok (gnutls_kx_algorithm_t algorithm)
+{
+  ssize_t ret = -1;
+  GNUTLS_KX_ALG_LOOP (ret = p->algorithm);
+  if (ret >= 0)
+    ret = 0;
+  else
+    ret = 1;
+  return ret;
+}
+
+int
+_gnutls_kx_needs_rsa_params (gnutls_kx_algorithm_t algorithm)
+{
+  ssize_t ret = 0;
+  GNUTLS_KX_ALG_LOOP (ret = p->needs_rsa_params);
+  return ret;
+}
+
+int
+_gnutls_kx_needs_dh_params (gnutls_kx_algorithm_t algorithm)
+{
+  ssize_t ret = 0;
+  GNUTLS_KX_ALG_LOOP (ret = p->needs_dh_params);
+  return ret;
+}
+
+/* Type to KX mappings */
+gnutls_kx_algorithm_t
+_gnutls_map_kx_get_kx (gnutls_credentials_type_t type, int server)
+{
+  gnutls_kx_algorithm_t ret = -1;
+
+  if (server)
+    {
+      GNUTLS_KX_MAP_ALG_LOOP_SERVER (ret = p->algorithm);
+    }
+  else
+    {
+      GNUTLS_KX_MAP_ALG_LOOP_SERVER (ret = p->algorithm);
+    }
+  return ret;
+}
+
+/* Returns the credentials type required for this
+ * Key exchange method.
+ */
+gnutls_credentials_type_t
+_gnutls_map_kx_get_cred (gnutls_kx_algorithm_t algorithm, int server)
+{
+  gnutls_credentials_type_t ret = -1;
+  if (server)
+    {
+      GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret =
+                          p->server_type);
+    }
+  else
+    {
+      GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret =
+                          p->client_type);
+    }
+
+  return ret;
+}
+
diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c
new file mode 100644
index 0000000..9390d13
--- /dev/null
+++ b/lib/algorithms/mac.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+struct gnutls_hash_entry
+{
+  const char *name;
+  const char *oid;
+  gnutls_mac_algorithm_t id;
+  size_t key_size;              /* in case of mac */
+};
+typedef struct gnutls_hash_entry gnutls_hash_entry;
+
+static const gnutls_hash_entry hash_algorithms[] = {
+  {"SHA1", HASH_OID_SHA1, GNUTLS_MAC_SHA1, 20},
+  {"MD5", HASH_OID_MD5, GNUTLS_MAC_MD5, 16},
+  {"SHA256", HASH_OID_SHA256, GNUTLS_MAC_SHA256, 32},
+  {"SHA384", HASH_OID_SHA384, GNUTLS_MAC_SHA384, 48},
+  {"SHA512", HASH_OID_SHA512, GNUTLS_MAC_SHA512, 64},
+  {"SHA224", HASH_OID_SHA224, GNUTLS_MAC_SHA224, 28},
+  {"AEAD", NULL, GNUTLS_MAC_AEAD, 0},
+  {"MD2", HASH_OID_MD2, GNUTLS_MAC_MD2, 0},     /* not used as MAC */
+  {"RIPEMD160", HASH_OID_RMD160, GNUTLS_MAC_RMD160, 20},
+  {"MAC-NULL", NULL, GNUTLS_MAC_NULL, 0},
+  {0, 0, 0, 0}
+};
+
+
+#define GNUTLS_HASH_LOOP(b) \
+        const gnutls_hash_entry *p; \
+                for(p = hash_algorithms; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_HASH_ALG_LOOP(a) \
+                        GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } 
)
+
+int
+_gnutls_mac_priority (gnutls_session_t session,
+                      gnutls_mac_algorithm_t algorithm)
+{                               /* actually returns the priority */
+  unsigned int i;
+  for (i = 0; i < session->internals.priorities.mac.algorithms; i++)
+    {
+      if (session->internals.priorities.mac.priority[i] == algorithm)
+        return i;
+    }
+  return -1;
+}
+
+/**
+ * gnutls_mac_get_name:
+ * @algorithm: is a MAC algorithm
+ *
+ * Convert a #gnutls_mac_algorithm_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified MAC
+ *   algorithm, or %NULL.
+ **/
+const char *
+gnutls_mac_get_name (gnutls_mac_algorithm_t algorithm)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_HASH_ALG_LOOP (ret = p->name);
+
+  return ret;
+}
+
+/**
+ * gnutls_mac_get_id:
+ * @name: is a MAC algorithm name
+ *
+ * Convert a string to a #gnutls_mac_algorithm_t value.  The names are
+ * compared in a case insensitive way.
+ *
+ * Returns: a #gnutls_mac_algorithm_t id of the specified MAC
+ *   algorithm string, or %GNUTLS_MAC_UNKNOWN on failures.
+ **/
+gnutls_mac_algorithm_t
+gnutls_mac_get_id (const char *name)
+{
+  gnutls_mac_algorithm_t ret = GNUTLS_MAC_UNKNOWN;
+
+  GNUTLS_HASH_LOOP (
+    if (strcasecmp (p->name, name) == 0) 
+      {
+        ret = p->id;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_mac_get_key_size:
+ * @algorithm: is an encryption algorithm
+ *
+ * Get size of MAC key.
+ *
+ * Returns: length (in bytes) of the given MAC key size, or 0 if the
+ *   given MAC algorithm is invalid.
+ **/
+size_t
+gnutls_mac_get_key_size (gnutls_mac_algorithm_t algorithm)
+{
+  size_t ret = 0;
+
+  /* avoid prefix */
+  GNUTLS_HASH_ALG_LOOP (ret = p->key_size);
+
+  return ret;
+}
+
+/**
+ * gnutls_mac_list:
+ *
+ * Get a list of hash algorithms for use as MACs.  Note that not
+ * necessarily all MACs are supported in TLS cipher suites.  For
+ * example, MD2 is not supported as a cipher suite, but is supported
+ * for other purposes (e.g., X.509 signature verification or similar).
+ *
+ * This function is not thread safe.
+ *
+ * Returns: Return a zero-terminated list of #gnutls_mac_algorithm_t
+ *   integers indicating the available MACs.
+ **/
+const gnutls_mac_algorithm_t *
+gnutls_mac_list (void)
+{
+static gnutls_mac_algorithm_t supported_macs[MAX_ALGOS] = { 0 };
+
+  if (supported_macs[0] == 0)
+    {
+      int i = 0;
+
+      GNUTLS_HASH_LOOP ( supported_macs[i++]=p->id);
+      supported_macs[i++]=0;
+    }
+
+  return supported_macs;
+}
+
+const char *
+_gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t algorithm)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_HASH_ALG_LOOP (ret = p->oid);
+
+  return ret;
+}
+
+gnutls_mac_algorithm_t
+_gnutls_x509_oid2mac_algorithm (const char *oid)
+{
+  gnutls_mac_algorithm_t ret = 0;
+
+  GNUTLS_HASH_LOOP (if (p->oid && strcmp (oid, p->oid) == 0)
+                    {
+                    ret = p->id; break;}
+  );
+
+  if (ret == 0)
+    return GNUTLS_MAC_UNKNOWN;
+  return ret;
+}
+
+int
+_gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm)
+{
+  ssize_t ret = -1;
+  GNUTLS_HASH_ALG_LOOP (ret = p->id);
+  if (ret >= 0)
+    ret = 0;
+  else
+    ret = 1;
+  return ret;
+}
diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
new file mode 100644
index 0000000..3322976
--- /dev/null
+++ b/lib/algorithms/protocols.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+
+/* TLS Versions */
+
+typedef struct
+{
+  const char *name;
+  gnutls_protocol_t id;         /* gnutls internal version number */
+  int major;                    /* defined by the protocol */
+  int minor;                    /* defined by the protocol */
+  transport_t transport;       /* Type of transport, stream or datagram */
+  int supported;                /* 0 not supported, > 0 is supported */
+} gnutls_version_entry;
+
+static const gnutls_version_entry sup_versions[] = {
+  {"SSL3.0", GNUTLS_SSL3, 3, 0, GNUTLS_STREAM, 1},
+  {"TLS1.0", GNUTLS_TLS1, 3, 1, GNUTLS_STREAM, 1},
+  {"TLS1.1", GNUTLS_TLS1_1, 3, 2, GNUTLS_STREAM, 1},
+  {"TLS1.2", GNUTLS_TLS1_2, 3, 3, GNUTLS_STREAM, 1},
+  {"DTLS1.0", GNUTLS_DTLS1_0, 254, 255, GNUTLS_DGRAM, 1}, /* 1.1 over datagram 
*/
+  {0, 0, 0, 0, 0}
+};
+
+#define GNUTLS_VERSION_LOOP(b) \
+        const gnutls_version_entry *p; \
+                for(p = sup_versions; p->name != NULL; p++) { b ; }
+
+#define GNUTLS_VERSION_ALG_LOOP(a) \
+       GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; })
+
+/* Version */
+int
+_gnutls_version_priority (gnutls_session_t session, gnutls_protocol_t version)
+{                               /* actually returns the priority */
+  unsigned int i;
+
+  for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
+    {
+      if (session->internals.priorities.protocol.priority[i] == version)
+        return i;
+    }
+  return -1;
+}
+
+gnutls_protocol_t
+_gnutls_version_lowest (gnutls_session_t session)
+{                               /* returns the lowest version supported */
+  unsigned int i, min = 0xff;
+  gnutls_protocol_t cur_prot;
+
+  for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
+    {
+      cur_prot = session->internals.priorities.protocol.priority[i];
+
+      if (cur_prot < min && _gnutls_version_is_supported(session, cur_prot))
+       min = cur_prot;
+    }
+
+  if (min == 0xff)
+    return GNUTLS_VERSION_UNKNOWN;      /* unknown version */
+
+  return min;
+}
+
+gnutls_protocol_t
+_gnutls_version_max (gnutls_session_t session)
+{                               /* returns the maximum version supported */
+  unsigned int i, max = 0x00;
+  gnutls_protocol_t cur_prot;
+
+  for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
+    {
+      cur_prot = session->internals.priorities.protocol.priority[i];
+
+      if (cur_prot > max && _gnutls_version_is_supported(session, cur_prot))
+       max = cur_prot;
+    }
+
+  if (max == 0x00)
+    return GNUTLS_VERSION_UNKNOWN;      /* unknown version */
+
+  return max;
+}
+
+
+/**
+ * gnutls_protocol_get_name:
+ * @version: is a (gnutls) version number
+ *
+ * Convert a #gnutls_protocol_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified TLS
+ *   version (e.g., "TLS1.0"), or %NULL.
+ **/
+const char *
+gnutls_protocol_get_name (gnutls_protocol_t version)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_VERSION_ALG_LOOP (ret = p->name);
+  return ret;
+}
+
+/**
+ * gnutls_protocol_get_id:
+ * @name: is a protocol name
+ *
+ * The names are compared in a case insensitive way.
+ *
+ * Returns: an id of the specified protocol, or
+ * %GNUTLS_VERSION_UNKNOWN on error.
+ **/
+gnutls_protocol_t
+gnutls_protocol_get_id (const char *name)
+{
+  gnutls_protocol_t ret = GNUTLS_VERSION_UNKNOWN;
+
+  GNUTLS_VERSION_LOOP (
+    if (strcasecmp (p->name, name) == 0) 
+      {
+        ret = p->id;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_protocol_list:
+ *
+ * Get a list of supported protocols, e.g. SSL 3.0, TLS 1.0 etc.
+ *
+ * This function is not threat safe.
+ *
+ * Returns: a zero-terminated list of #gnutls_protocol_t integers
+ * indicating the available protocols.
+ *
+ **/
+const gnutls_protocol_t *
+gnutls_protocol_list (void)
+{
+static gnutls_protocol_t supported_protocols[MAX_ALGOS] = {0};
+
+  if (supported_protocols[0] == 0)
+    {
+      int i = 0;
+
+      GNUTLS_VERSION_LOOP (supported_protocols[i++]=p->id);
+      supported_protocols[i++]=0;
+    }
+
+  return supported_protocols;
+}
+
+int
+_gnutls_version_get_minor (gnutls_protocol_t version)
+{
+  int ret = -1;
+
+  GNUTLS_VERSION_ALG_LOOP (ret = p->minor);
+  return ret;
+}
+
+gnutls_protocol_t
+_gnutls_version_get (int major, int minor)
+{
+  int ret = -1;
+
+  GNUTLS_VERSION_LOOP (if ((p->major == major) && (p->minor == minor))
+                       ret = p->id);
+  return ret;
+}
+
+int
+_gnutls_version_get_major (gnutls_protocol_t version)
+{
+  int ret = -1;
+
+  GNUTLS_VERSION_ALG_LOOP (ret = p->major);
+  return ret;
+}
+
+/* Version Functions */
+
+int
+_gnutls_version_is_supported (gnutls_session_t session,
+                              const gnutls_protocol_t version)
+{
+  int ret = 0;
+
+  GNUTLS_VERSION_ALG_LOOP (ret = p->supported && p->transport == 
session->internals.transport);
+
+  if (ret == 0)
+    return 0;
+
+  if (_gnutls_version_priority (session, version) < 0)
+    return 0;                   /* disabled by the user */
+  else
+    return 1;
+}
+
+
+/* This function determines if the version specified has a
+   cipher-suite selected PRF hash function instead of the old
+   hardcoded MD5+SHA1. */
+int
+_gnutls_version_has_selectable_prf (gnutls_protocol_t version)
+{
+  switch (version)
+    {
+    case GNUTLS_DTLS1_0:
+    case GNUTLS_TLS1_1:
+    case GNUTLS_TLS1_0:
+    case GNUTLS_SSL3:
+      return 0;
+    default:
+      return 1;
+    }
+}
+
+/* This function determines if the version specified has selectable
+   signature/hash functions for certificate authentification. */
+int
+_gnutls_version_has_selectable_sighash (gnutls_protocol_t version)
+{
+  switch (version)
+    {
+    case GNUTLS_DTLS1_0:
+    case GNUTLS_TLS1_1:
+    case GNUTLS_TLS1_0:
+    case GNUTLS_SSL3:
+      return 0;
+    default:
+      return 1;
+    }
+}
+
+/* This function determines if the version specified has support for
+   TLS extensions. */
+int
+_gnutls_version_has_extensions (gnutls_protocol_t version)
+{
+  switch (version)
+    {
+    case GNUTLS_SSL3:
+      return 0;
+    default:
+      /* Versions after TLS 1.0 are required to handle extensions.
+       * SSL 3.0 also required extensions to be ignored, but
+       * some earlier draft didn't.
+       */
+      return 1;
+    }
+}
+
+/* This function determines if the version specified has explicit IVs
+   (for CBC attack prevention). */
+int
+_gnutls_version_has_explicit_iv (gnutls_protocol_t version)
+{
+  switch (version)
+    {
+    case GNUTLS_TLS1_0:
+    case GNUTLS_SSL3:
+      return 0;
+    default:
+      /* All versions after TLS 1.1 have explicit IV */
+      return 1;
+    }
+}
+
diff --git a/lib/algorithms/publickey.c b/lib/algorithms/publickey.c
new file mode 100644
index 0000000..ce48f9f
--- /dev/null
+++ b/lib/algorithms/publickey.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+
+/* KX mappings to PK algorithms */
+typedef struct
+{
+  gnutls_kx_algorithm_t kx_algorithm;
+  gnutls_pk_algorithm_t pk_algorithm;
+  enum encipher_type encipher_type;     /* CIPHER_ENCRYPT if this algorithm is 
to be used
+                                         * for encryption, CIPHER_SIGN if 
signature only,
+                                         * CIPHER_IGN if this does not apply 
at all.
+                                         *
+                                         * This is useful to certificate 
cipher suites, which check
+                                         * against the certificate key usage 
bits.
+                                         */
+} gnutls_pk_map;
+
+/* This table maps the Key exchange algorithms to
+ * the certificate algorithms. Eg. if we have
+ * RSA algorithm in the certificate then we can
+ * use GNUTLS_KX_RSA or GNUTLS_KX_DHE_RSA.
+ */
+static const gnutls_pk_map pk_mappings[] = {
+  {GNUTLS_KX_RSA, GNUTLS_PK_RSA, CIPHER_ENCRYPT},
+  {GNUTLS_KX_RSA_EXPORT, GNUTLS_PK_RSA, CIPHER_SIGN},
+  {GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
+  {GNUTLS_KX_SRP_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
+  {GNUTLS_KX_ECDHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
+  {GNUTLS_KX_DHE_DSS, GNUTLS_PK_DSA, CIPHER_SIGN},
+  {GNUTLS_KX_SRP_DSS, GNUTLS_PK_DSA, CIPHER_SIGN},
+  {0, 0, 0}
+};
+
+#define GNUTLS_PK_MAP_LOOP(b) \
+        const gnutls_pk_map *p; \
+                for(p = pk_mappings; p->kx_algorithm != 0; p++) { b }
+
+#define GNUTLS_PK_MAP_ALG_LOOP(a) \
+                        GNUTLS_PK_MAP_LOOP( if(p->kx_algorithm == 
kx_algorithm) { a; break; })
+
+
+/* returns the gnutls_pk_algorithm_t which is compatible with
+ * the given gnutls_kx_algorithm_t.
+ */
+gnutls_pk_algorithm_t
+_gnutls_map_pk_get_pk (gnutls_kx_algorithm_t kx_algorithm)
+{
+  gnutls_pk_algorithm_t ret = -1;
+
+  GNUTLS_PK_MAP_ALG_LOOP (ret = p->pk_algorithm) return ret;
+}
+
+/* pk algorithms;
+ */
+struct gnutls_pk_entry
+{
+  const char *name;
+  const char *oid;
+  gnutls_pk_algorithm_t id;
+};
+typedef struct gnutls_pk_entry gnutls_pk_entry;
+
+static const gnutls_pk_entry pk_algorithms[] = {
+  /* having duplicate entries is ok, as long as the one
+   * we want to return OID from is first */
+  {"UNKNOWN", NULL, GNUTLS_PK_UNKNOWN},
+  {"RSA", PK_PKIX1_RSA_OID, GNUTLS_PK_RSA},
+  {"RSA (X.509)", PK_X509_RSA_OID, GNUTLS_PK_RSA},      /* some certificates 
use this OID for RSA */
+  {"RSA (MD5)", SIG_RSA_MD5_OID, GNUTLS_PK_RSA},        /* some other broken 
certificates set RSA with MD5 as an indicator of RSA */
+  {"RSA (SHA1)", SIG_RSA_SHA1_OID, GNUTLS_PK_RSA},      /* some other broken 
certificates set RSA with SHA1 as an indicator of RSA */
+  {"DSA", PK_DSA_OID, GNUTLS_PK_DSA},
+  {"GOST R 34.10-2001", PK_GOST_R3410_2001_OID, GNUTLS_PK_UNKNOWN},
+  {"GOST R 34.10-94", PK_GOST_R3410_94_OID, GNUTLS_PK_UNKNOWN},
+  {"ECC", "1.2.840.10045.2.1", GNUTLS_PK_ECC},
+  {0, 0, 0}
+};
+
+#define GNUTLS_PK_LOOP(b) \
+       { const gnutls_pk_entry *p; \
+                for(p = pk_algorithms; p->name != NULL; p++) { b ; } }
+
+
+/**
+ * gnutls_pk_algorithm_get_name:
+ * @algorithm: is a pk algorithm
+ *
+ * Convert a #gnutls_pk_algorithm_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified public
+ *   key algorithm, or %NULL.
+ **/
+const char *
+gnutls_pk_algorithm_get_name (gnutls_pk_algorithm_t algorithm)
+{
+  const char *ret = NULL;
+
+  GNUTLS_PK_LOOP(
+    if (p->id == algorithm)
+      {
+        ret = p->name;
+        break;
+      }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_pk_list:
+ *
+ * Get a list of supported public key algorithms.
+ *
+ * This function is not thread safe.
+ *
+ * Returns: a zero-terminated list of #gnutls_pk_algorithm_t integers
+ *   indicating the available ciphers.
+ *
+ * Since: 2.6.0
+ **/
+const gnutls_pk_algorithm_t *
+gnutls_pk_list (void)
+{
+static gnutls_pk_algorithm_t supported_pks[MAX_ALGOS] = {0};
+
+  if (supported_pks[0] == 0)
+    {
+      int i = 0;
+
+      GNUTLS_PK_LOOP (if (p->id != GNUTLS_PK_UNKNOWN && 
supported_pks[i>0?(i-1):0]!=p->id) supported_pks[i++]=p->id);
+      supported_pks[i++]=0;
+    }
+
+  return supported_pks;
+}
+
+/**
+ * gnutls_pk_get_id:
+ * @name: is a string containing a public key algorithm name.
+ *
+ * Convert a string to a #gnutls_pk_algorithm_t value.  The names are
+ * compared in a case insensitive way.  For example,
+ * gnutls_pk_get_id("RSA") will return %GNUTLS_PK_RSA.
+ *
+ * Returns: a #gnutls_pk_algorithm_t id of the specified public key
+ *   algorithm string, or %GNUTLS_PK_UNKNOWN on failures.
+ *
+ * Since: 2.6.0
+ **/
+gnutls_pk_algorithm_t
+gnutls_pk_get_id (const char *name)
+{
+  gnutls_pk_algorithm_t ret = GNUTLS_PK_UNKNOWN;
+  const gnutls_pk_entry *p;
+
+  for (p = pk_algorithms; p->name != NULL; p++)
+    if (name && strcmp (p->name, name) == 0)
+      {
+        ret = p->id;
+        break;
+      }
+
+  return ret;
+}
+
+/**
+ * gnutls_pk_get_name:
+ * @algorithm: is a public key algorithm
+ *
+ * Convert a #gnutls_pk_algorithm_t value to a string.
+ *
+ * Returns: a pointer to a string that contains the name of the
+ *   specified public key algorithm, or %NULL.
+ *
+ * Since: 2.6.0
+ **/
+const char *
+gnutls_pk_get_name (gnutls_pk_algorithm_t algorithm)
+{
+  const char *ret = "Unknown";
+  const gnutls_pk_entry *p;
+
+  for (p = pk_algorithms; p->name != NULL; p++)
+    if (algorithm == p->id)
+      {
+        ret = p->name;
+        break;
+      }
+
+  return ret;
+}
+
+gnutls_pk_algorithm_t
+_gnutls_x509_oid2pk_algorithm (const char *oid)
+{
+  gnutls_pk_algorithm_t ret = GNUTLS_PK_UNKNOWN;
+  const gnutls_pk_entry *p;
+
+  for (p = pk_algorithms; p->name != NULL; p++)
+    if (p->oid && strcmp (p->oid, oid) == 0)
+      {
+        ret = p->id;
+        break;
+      }
+
+  return ret;
+}
+
+const char *
+_gnutls_x509_pk_to_oid (gnutls_pk_algorithm_t algorithm)
+{
+  const char *ret = NULL;
+  const gnutls_pk_entry *p;
+
+  for (p = pk_algorithms; p->name != NULL; p++)
+    if (p->id == algorithm)
+      {
+        ret = p->oid;
+        break;
+      }
+
+  return ret;
+}
+
+/* Returns the encipher type for the given key exchange algorithm.
+ * That one of CIPHER_ENCRYPT, CIPHER_SIGN, CIPHER_IGN.
+ *
+ * ex. GNUTLS_KX_RSA requires a certificate able to encrypt... so returns 
CIPHER_ENCRYPT.
+ */
+enum encipher_type
+_gnutls_kx_encipher_type (gnutls_kx_algorithm_t kx_algorithm)
+{
+  int ret = CIPHER_IGN;
+  GNUTLS_PK_MAP_ALG_LOOP (ret = p->encipher_type) return ret;
+
+}
+
diff --git a/lib/algorithms/secparams.c b/lib/algorithms/secparams.c
new file mode 100644
index 0000000..09dd240
--- /dev/null
+++ b/lib/algorithms/secparams.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+typedef struct
+{
+  const char *name;
+  gnutls_sec_param_t sec_param;
+  int bits;                     /* security level */
+  int pk_bits;                  /* DH, RSA, SRP */
+  int dsa_bits;                 /* bits for DSA. Handled differently since
+                                 * choice of key size in DSA is political.
+                                 */
+  int subgroup_bits;            /* subgroup bits */
+  int ecc_bits;                 /* bits for ECC keys */
+} gnutls_sec_params_entry;
+
+static const gnutls_sec_params_entry sec_params[] = {
+  {"Weak", GNUTLS_SEC_PARAM_WEAK, 64, 816, 1024, 128, 128},
+  {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1248, 2048, 160, 160},
+  {"Normal", GNUTLS_SEC_PARAM_NORMAL, 112, 2432, 3072, 224, 224},
+  {"High", GNUTLS_SEC_PARAM_HIGH, 128, 3248, 3072, 256, 256},
+  {"Ultra", GNUTLS_SEC_PARAM_ULTRA, 256, 15424, 3072, 512, 512},
+  {NULL, 0, 0, 0, 0, 0}
+};
+
+#define GNUTLS_SEC_PARAM_LOOP(b) \
+       { const gnutls_sec_params_entry *p; \
+                for(p = sec_params; p->name != NULL; p++) { b ; } }
+
+/**
+ * gnutls_sec_param_to_pk_bits:
+ * @algo: is a public key algorithm
+ * @param: is a security parameter
+ *
+ * When generating private and public key pairs a difficult question
+ * is which size of "bits" the modulus will be in RSA and the group size
+ * in DSA. The easy answer is 1024, which is also wrong. This function
+ * will convert a human understandable security parameter to an
+ * appropriate size for the specific algorithm.
+ *
+ * Returns: The number of bits, or zero.
+ *
+ **/
+unsigned int
+gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t algo,
+                             gnutls_sec_param_t param)
+{
+  unsigned int ret = 0;
+
+  /* handle DSA differently */
+  if (algo == GNUTLS_PK_DSA)
+    {
+      GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
+                             {
+                               ret = p->dsa_bits; break;
+                             }
+      );
+      return ret;
+    }
+  else if (algo == GNUTLS_PK_ECC)
+    {
+      GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
+                             {
+                               ret = p->ecc_bits; break;
+                             }
+      );
+      return ret;
+    }
+  else
+    {
+      GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
+                         {
+                           ret = p->pk_bits; break;
+                         }
+      );
+
+      return ret;
+    }
+}
+
+/* Returns the corresponding size for subgroup bits (q),
+ * given the group bits (p).
+ */
+unsigned int
+_gnutls_pk_bits_to_subgroup_bits (unsigned int pk_bits)
+{
+  unsigned int ret = 0;
+
+  GNUTLS_SEC_PARAM_LOOP (if (p->pk_bits >= pk_bits)
+                         {
+                           ret = p->subgroup_bits; break;
+                         }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_sec_param_get_name:
+ * @param: is a security parameter
+ *
+ * Convert a #gnutls_sec_param_t value to a string.
+ *
+ * Returns: a pointer to a string that contains the name of the
+ *   specified public key algorithm, or %NULL.
+ *
+ **/
+const char *
+gnutls_sec_param_get_name (gnutls_sec_param_t param)
+{
+  const char *ret = "Unknown";
+
+  GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
+                         {
+                           ret = p->name; break;
+                         }
+  );
+
+  return ret;
+}
+
+/**
+ * gnutls_pk_bits_to_sec_param:
+ * @algo: is a public key algorithm
+ * @bits: is the number of bits
+ *
+ * This is the inverse of gnutls_sec_param_to_pk_bits(). Given an algorithm
+ * and the number of bits, it will return the security parameter. This is
+ * a rough indication.
+ *
+ * Returns: The security parameter.
+ *
+ **/
+gnutls_sec_param_t
+gnutls_pk_bits_to_sec_param (gnutls_pk_algorithm_t algo, unsigned int bits)
+{
+  gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_UNKNOWN;
+
+  if (algo == GNUTLS_PK_ECC)
+    {
+      GNUTLS_SEC_PARAM_LOOP (if (p->ecc_bits > bits)
+                         {
+                           break;
+                         }
+                         ret = p->sec_param;);
+    }
+  else
+    {
+      GNUTLS_SEC_PARAM_LOOP (if (p->pk_bits > bits)
+                         {
+                           break;
+                         }
+                         ret = p->sec_param;);
+    }
+
+  return ret;
+}
diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
new file mode 100644
index 0000000..ff99a64
--- /dev/null
+++ b/lib/algorithms/sign.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <algorithms.h>
+#include <gnutls_errors.h>
+#include <x509/common.h>
+
+/* signature algorithms;
+ */
+struct gnutls_sign_entry
+{
+  const char *name;
+  const char *oid;
+  gnutls_sign_algorithm_t id;
+  gnutls_pk_algorithm_t pk;
+  gnutls_mac_algorithm_t mac;
+  /* See RFC 5246 HashAlgorithm and SignatureAlgorithm
+     for values to use in aid struct. */
+  const sign_algorithm_st aid;
+};
+typedef struct gnutls_sign_entry gnutls_sign_entry;
+
+#define TLS_SIGN_AID_UNKNOWN {255, 255}
+static const sign_algorithm_st unknown_tls_aid = TLS_SIGN_AID_UNKNOWN;
+
+static const gnutls_sign_entry sign_algorithms[] = {
+  {"RSA-SHA1", SIG_RSA_SHA1_OID, GNUTLS_SIGN_RSA_SHA1, GNUTLS_PK_RSA,
+   GNUTLS_MAC_SHA1, {2, 1}},
+  {"RSA-SHA224", SIG_RSA_SHA224_OID, GNUTLS_SIGN_RSA_SHA224, GNUTLS_PK_RSA,
+   GNUTLS_MAC_SHA224, {3, 1}},
+  {"RSA-SHA256", SIG_RSA_SHA256_OID, GNUTLS_SIGN_RSA_SHA256, GNUTLS_PK_RSA,
+   GNUTLS_MAC_SHA256, {4, 1}},
+  {"RSA-SHA384", SIG_RSA_SHA384_OID, GNUTLS_SIGN_RSA_SHA384, GNUTLS_PK_RSA,
+   GNUTLS_MAC_SHA384, {5, 1}},
+  {"RSA-SHA512", SIG_RSA_SHA512_OID, GNUTLS_SIGN_RSA_SHA512, GNUTLS_PK_RSA,
+   GNUTLS_MAC_SHA512, {6, 1}},
+  {"RSA-RMD160", SIG_RSA_RMD160_OID, GNUTLS_SIGN_RSA_RMD160, GNUTLS_PK_RSA,
+   GNUTLS_MAC_RMD160, TLS_SIGN_AID_UNKNOWN},
+  {"DSA-SHA1", SIG_DSA_SHA1_OID, GNUTLS_SIGN_DSA_SHA1, GNUTLS_PK_DSA,
+   GNUTLS_MAC_SHA1, {2, 2}},
+  {"DSA-SHA224", SIG_DSA_SHA224_OID, GNUTLS_SIGN_DSA_SHA224, GNUTLS_PK_DSA,
+   GNUTLS_MAC_SHA224, {3, 2}},
+  {"DSA-SHA256", SIG_DSA_SHA256_OID, GNUTLS_SIGN_DSA_SHA256, GNUTLS_PK_DSA,
+   GNUTLS_MAC_SHA256, {4, 2}},
+  {"RSA-MD5", SIG_RSA_MD5_OID, GNUTLS_SIGN_RSA_MD5, GNUTLS_PK_RSA,
+   GNUTLS_MAC_MD5, {1, 1}},
+  {"RSA-MD2", SIG_RSA_MD2_OID, GNUTLS_SIGN_RSA_MD2, GNUTLS_PK_RSA,
+   GNUTLS_MAC_MD2, TLS_SIGN_AID_UNKNOWN},
+  {"ECDSA-SHA1", "1.2.840.10045.4.1", GNUTLS_SIGN_ECDSA_SHA1, GNUTLS_PK_ECC, 
GNUTLS_MAC_SHA1, {2, 3}},
+  {"ECDSA-SHA224", "1.2.840.10045.4.3.1", GNUTLS_SIGN_ECDSA_SHA224, 
GNUTLS_PK_ECC, GNUTLS_MAC_SHA224, {3, 3}},
+  {"ECDSA-SHA256", "1.2.840.10045.4.3.2", GNUTLS_SIGN_ECDSA_SHA256, 
GNUTLS_PK_ECC, GNUTLS_MAC_SHA256, {4, 3}},
+  {"ECDSA-SHA384", "1.2.840.10045.4.3.3", GNUTLS_SIGN_ECDSA_SHA384, 
GNUTLS_PK_ECC, GNUTLS_MAC_SHA384, {5, 3}},
+  {"ECDSA-SHA512", "1.2.840.10045.4.3.4", GNUTLS_SIGN_ECDSA_SHA512, 
GNUTLS_PK_ECC, GNUTLS_MAC_SHA512, {6, 3}},
+  {"GOST R 34.10-2001", SIG_GOST_R3410_2001_OID, 0, 0, 0,
+   TLS_SIGN_AID_UNKNOWN},
+  {"GOST R 34.10-94", SIG_GOST_R3410_94_OID, 0, 0, 0, TLS_SIGN_AID_UNKNOWN},
+  {0, 0, 0, 0, 0, TLS_SIGN_AID_UNKNOWN}
+};
+
+#define GNUTLS_SIGN_LOOP(b) \
+  do {                                                                \
+    const gnutls_sign_entry *p;                                               \
+    for(p = sign_algorithms; p->name != NULL; p++) { b ; }            \
+  } while (0)
+
+#define GNUTLS_SIGN_ALG_LOOP(a) \
+  GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
+
+/**
+ * gnutls_sign_get_name:
+ * @sign: is a sign algorithm
+ *
+ * Convert a #gnutls_sign_algorithm_t value to a string.
+ *
+ * Returns: a string that contains the name of the specified sign
+ *   algorithm, or %NULL.
+ **/
+const char *
+gnutls_sign_get_name (gnutls_sign_algorithm_t sign)
+{
+  const char *ret = NULL;
+
+  /* avoid prefix */
+  GNUTLS_SIGN_ALG_LOOP (ret = p->name);
+
+  return ret;
+}
+
+/**
+ * gnutls_sign_list:
+ *
+ * Get a list of supported public key signature algorithms.
+ *
+ * Returns: a zero-terminated list of #gnutls_sign_algorithm_t
+ *   integers indicating the available ciphers.
+ *
+ **/
+const gnutls_sign_algorithm_t *
+gnutls_sign_list (void)
+{
+static gnutls_sign_algorithm_t supported_sign[MAX_ALGOS] = {0};
+
+  if (supported_sign[0] == 0)
+    {
+      int i = 0;
+
+      GNUTLS_SIGN_LOOP (supported_sign[i++]=p->id);
+      supported_sign[i++]=0;
+    }
+
+  return supported_sign;
+}
+
+/**
+ * gnutls_sign_get_id:
+ * @name: is a MAC algorithm name
+ *
+ * The names are compared in a case insensitive way.
+ *
+ * Returns: return a #gnutls_sign_algorithm_t value corresponding to
+ *   the specified cipher, or %GNUTLS_SIGN_UNKNOWN on error.
+ **/
+gnutls_sign_algorithm_t
+gnutls_sign_get_id (const char *name)
+{
+  gnutls_sign_algorithm_t ret = GNUTLS_SIGN_UNKNOWN;
+
+  GNUTLS_SIGN_LOOP (
+    if (strcasecmp (p->name, name) == 0) 
+      {
+        ret = p->id;
+        break;
+      }
+  );
+
+  return ret;
+
+}
+
+gnutls_sign_algorithm_t
+_gnutls_x509_oid2sign_algorithm (const char *oid)
+{
+  gnutls_sign_algorithm_t ret = 0;
+
+  GNUTLS_SIGN_LOOP (if (p->oid && strcmp (oid, p->oid) == 0)
+                    {
+                      ret = p->id; 
+                      break;
+                    }
+  );
+
+  if (ret == 0)
+    {
+      _gnutls_debug_log ("Unknown SIGN OID: '%s'\n", oid);
+      return GNUTLS_SIGN_UNKNOWN;
+    }
+  return ret;
+}
+
+gnutls_sign_algorithm_t
+_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_mac_algorithm_t mac)
+{
+  gnutls_sign_algorithm_t ret = 0;
+
+  GNUTLS_SIGN_LOOP (if (pk == p->pk && mac == p->mac)
+                    {
+                    ret = p->id; break;}
+  );
+
+  if (ret == 0)
+    return GNUTLS_SIGN_UNKNOWN;
+  return ret;
+}
+
+const char *
+_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
+                          gnutls_mac_algorithm_t mac)
+{
+  gnutls_sign_algorithm_t sign;
+  const char *ret = NULL;
+
+  sign = _gnutls_x509_pk_to_sign (pk, mac);
+  if (sign == GNUTLS_SIGN_UNKNOWN)
+    return NULL;
+
+  GNUTLS_SIGN_ALG_LOOP (ret = p->oid);
+  return ret;
+}
+
+gnutls_mac_algorithm_t
+_gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t sign)
+{
+  gnutls_mac_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
+
+  GNUTLS_SIGN_ALG_LOOP (ret = p->mac);
+
+  return ret;
+}
+
+gnutls_pk_algorithm_t
+_gnutls_sign_get_pk_algorithm (gnutls_sign_algorithm_t sign)
+{
+  gnutls_pk_algorithm_t ret = GNUTLS_PK_UNKNOWN;
+
+  GNUTLS_SIGN_ALG_LOOP (ret = p->pk);
+
+  return ret;
+}
+
+gnutls_sign_algorithm_t
+_gnutls_tls_aid_to_sign (const sign_algorithm_st * aid)
+{
+  gnutls_sign_algorithm_t ret = GNUTLS_SIGN_UNKNOWN;
+
+  if (memcmp(aid, &unknown_tls_aid, sizeof(*aid))==0)
+    return ret;
+
+  GNUTLS_SIGN_LOOP (if (p->aid.hash_algorithm == aid->hash_algorithm
+                        && p->aid.sign_algorithm == aid->sign_algorithm)
+                    {
+                      ret = p->id; break;
+                    }
+  );
+
+
+  return ret;
+}
+
+/* Returns NULL if a valid AID is not found
+ */
+const sign_algorithm_st*
+_gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign)
+{
+  const sign_algorithm_st * ret = NULL;
+
+  GNUTLS_SIGN_ALG_LOOP (ret = &p->aid);
+
+  if (ret != NULL && memcmp(ret, &unknown_tls_aid, sizeof(*ret))==0)
+    return NULL;
+
+  return ret;
+}
+
diff --git a/lib/auth/anon.h b/lib/auth/anon.h
index b2616df..ce51f53 100644
--- a/lib/auth/anon.h
+++ b/lib/auth/anon.h
@@ -44,7 +44,7 @@ typedef struct gnutls_anon_client_credentials_st
 typedef struct anon_auth_info_st
 {
   dh_info_st dh;
-  ecc_curve_t curve;
+  gnutls_ecc_curve_t curve;
 } *anon_auth_info_t;
 
 typedef struct anon_auth_info_st anon_auth_info_st;
diff --git a/lib/auth/cert.c b/lib/auth/cert.c
index ac87412..deb9451 100644
--- a/lib/auth/cert.c
+++ b/lib/auth/cert.c
@@ -37,7 +37,7 @@
 #include "gnutls_datum.h"
 #include "ext/signature.h"
 #include <gnutls_pk.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_global.h>
 #include <gnutls_record.h>
 #include <gnutls_sig.h>
diff --git a/lib/auth/dh_common.c b/lib/auth/dh_common.c
index f887af6..5b8aab3 100644
--- a/lib/auth/dh_common.c
+++ b/lib/auth/dh_common.c
@@ -38,7 +38,7 @@
 #include <gnutls_x509.h>
 #include <gnutls_state.h>
 #include <auth/dh_common.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <auth/psk.h>
 
 /* Frees the dh_info_st structure.
diff --git a/lib/auth/dhe.c b/lib/auth/dhe.c
index a261576..fe78b70 100644
--- a/lib/auth/dhe.c
+++ b/lib/auth/dhe.c
@@ -35,7 +35,7 @@
 #include "gnutls_num.h"
 #include "gnutls_sig.h"
 #include <gnutls_datum.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <auth/cert.h>
 #include <gnutls_x509.h>
 #include <gnutls_state.h>
diff --git a/lib/auth/ecdh_common.c b/lib/auth/ecdh_common.c
index e4440c1..f04526a 100644
--- a/lib/auth/ecdh_common.c
+++ b/lib/auth/ecdh_common.c
@@ -39,7 +39,7 @@
 #include <auth/ecdh_common.h>
 #include <gnutls_ecc.h>
 #include <ext/ecc.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <auth/psk.h>
 #include <gnutls_pk.h>
 
@@ -61,7 +61,7 @@ int ret;
   
   _gnutls_mpi_set_ui(pub.params[7], 1);
   
-  ret = _gnutls_pk_derive(GNUTLS_PK_ECDH, &session->key->key, 
&session->key->ecdh_params, &pub);
+  ret = _gnutls_pk_derive(GNUTLS_PK_ECC, &session->key->key, 
&session->key->ecdh_params, &pub);
   
   _gnutls_mpi_release(&pub.params[7]);
   
@@ -75,7 +75,7 @@ int ret;
 int
 _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
                                   opaque * data, size_t _data_size,
-                                  ecc_curve_t curve)
+                                  gnutls_ecc_curve_t curve)
 {
   ssize_t data_size = _data_size;
   int ret, i = 0;
@@ -89,7 +89,7 @@ _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
   i+=1;
 
   DECR_LEN (data_size, point_size);
-  ret = _gnutls_ecc_ansi_x963_import(curve, &data[i], point_size, 
&session->key->ecdh_x, &session->key->ecdh_y);
+  ret = _gnutls_ecc_ansi_x963_import(&data[i], point_size, 
&session->key->ecdh_x, &session->key->ecdh_y);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
@@ -109,7 +109,7 @@ _gnutls_gen_ecdh_common_client_kx (gnutls_session_t 
session, gnutls_buffer_st* d
   int curve = _gnutls_session_ecc_curve_get(session);
 
   /* generate temporal key */
-  ret = _gnutls_pk_generate(GNUTLS_PK_ECDH, curve, &session->key->ecdh_params);
+  ret = _gnutls_pk_generate(GNUTLS_PK_ECC, curve, &session->key->ecdh_params);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
@@ -139,7 +139,7 @@ _gnutls_proc_ecdh_common_server_kx (gnutls_session_t 
session,
                                   opaque * data, size_t _data_size)
 {
   int i, ret, point_size;
-  ecc_curve_t curve;
+  gnutls_ecc_curve_t curve;
   ssize_t data_size = _data_size;
 
   i = 0;
@@ -148,7 +148,7 @@ _gnutls_proc_ecdh_common_server_kx (gnutls_session_t 
session,
     return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
   
   DECR_LEN (data_size, 2);
-  curve = _gnutls_num_to_ecc(_gnutls_read_uint16 (&data[i]));
+  curve = _gnutls_tls_id_to_ecc_curve(_gnutls_read_uint16 (&data[i]));
   i += 2;
 
   ret = _gnutls_session_supports_ecc_curve(session, curve);
@@ -162,7 +162,7 @@ _gnutls_proc_ecdh_common_server_kx (gnutls_session_t 
session,
   i++;
 
   DECR_LEN (data_size, point_size);
-  ret = _gnutls_ecc_ansi_x963_import(curve, &data[i], point_size, 
&session->key->ecdh_x, &session->key->ecdh_y);
+  ret = _gnutls_ecc_ansi_x963_import(&data[i], point_size, 
&session->key->ecdh_x, &session->key->ecdh_y);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
@@ -174,7 +174,7 @@ _gnutls_proc_ecdh_common_server_kx (gnutls_session_t 
session,
 /* If the psk flag is set, then an empty psk_identity_hint will
  * be inserted */
 int _gnutls_ecdh_common_print_server_kx (gnutls_session_t session, 
gnutls_buffer_st* data,
-                                         ecc_curve_t curve)
+                                         gnutls_ecc_curve_t curve)
 {
   opaque p;
   int ret;
@@ -190,12 +190,12 @@ int _gnutls_ecdh_common_print_server_kx (gnutls_session_t 
session, gnutls_buffer
   if (ret < 0)
     return gnutls_assert_val(ret);
 
-  ret = _gnutls_buffer_append_prefix(data, 16, _gnutls_ecc_to_num(curve));
+  ret = _gnutls_buffer_append_prefix(data, 16, 
_gnutls_ecc_curve_get_tls_id(curve));
   if (ret < 0)
     return gnutls_assert_val(ret);
 
   /* generate temporal key */
-  ret = _gnutls_pk_generate(GNUTLS_PK_ECDH, curve, &session->key->ecdh_params);
+  ret = _gnutls_pk_generate(GNUTLS_PK_ECC, curve, &session->key->ecdh_params);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
diff --git a/lib/auth/ecdh_common.h b/lib/auth/ecdh_common.h
index 1fa6eba..9b7a92b 100644
--- a/lib/auth/ecdh_common.h
+++ b/lib/auth/ecdh_common.h
@@ -30,9 +30,9 @@
 int _gnutls_gen_ecdh_common_client_kx (gnutls_session_t, gnutls_buffer_st*);
 int _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session,
                                       opaque * data, size_t _data_size,
-                                      ecc_curve_t curve);
+                                      gnutls_ecc_curve_t curve);
 int _gnutls_ecdh_common_print_server_kx (gnutls_session_t, gnutls_buffer_st* 
data,
-                                         ecc_curve_t curve);
+                                         gnutls_ecc_curve_t curve);
 int _gnutls_proc_ecdh_common_server_kx (gnutls_session_t session, opaque * 
data,
                                       size_t _data_size);
 
diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c
index f20a375..52aceaa 100644
--- a/lib/auth/rsa.c
+++ b/lib/auth/rsa.c
@@ -35,7 +35,7 @@
 #include "gnutls_datum.h"
 #include <auth/cert.h>
 #include <gnutls_pk.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_global.h>
 #include "debug.h"
 #include <gnutls_sig.h>
@@ -68,14 +68,11 @@ const mod_auth_st rsa_auth_struct = {
  */
 static int
 _gnutls_get_public_rsa_params (gnutls_session_t session,
-                               bigint_t params[MAX_PUBLIC_PARAMS_SIZE],
-                               int *params_len)
+                               gnutls_pk_params_st * params)
 {
   int ret;
   cert_auth_info_t info;
   gnutls_pcert_st peer_cert;
-  bigint_t tmp_params[RSA_PUBLIC_PARAMS];
-  int tmp_params_size;
   int i;
 
   /* normal non export case */
@@ -99,13 +96,8 @@ _gnutls_get_public_rsa_params (gnutls_session_t session,
       return ret;
     }
 
-  if (*params_len < RSA_PUBLIC_PARAMS)
-    {
-      gnutls_assert ();
-      ret = GNUTLS_E_INTERNAL_ERROR;
-      goto cleanup;
-    }
-  *params_len = RSA_PUBLIC_PARAMS;
+  gnutls_pk_params_init(params);
+  params->params_nr = RSA_PUBLIC_PARAMS;
 
   /* EXPORT case: */
   if (_gnutls_cipher_suite_get_kx_algo
@@ -120,29 +112,22 @@ _gnutls_get_public_rsa_params (gnutls_session_t session,
           goto cleanup;
         }
 
-      for (i = 0; i < *params_len; i++)
+      for (i = 0; i < params->params_nr; i++)
         {
-          params[i] = _gnutls_mpi_copy (session->key->rsa[i]);
+          params->params[i] = _gnutls_mpi_copy (session->key->rsa[i]);
         }
 
       ret = 0;
       goto cleanup;
     }
 
-  tmp_params_size = RSA_PUBLIC_PARAMS;
-  ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, tmp_params, 
&tmp_params_size);
+  ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params);
   if (ret < 0)
     {
       ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
       goto cleanup;
     }
 
-  /* end of export case */
-  for (i = 0; i < *params_len; i++)
-    {
-      params[i] = _gnutls_mpi_copy (tmp_params[i]);
-    }
-    
   ret = 0;
   
 cleanup:
@@ -263,9 +248,8 @@ _gnutls_gen_rsa_client_kx (gnutls_session_t session, 
gnutls_buffer_st* data)
 {
   cert_auth_info_t auth = session->key->auth_info;
   gnutls_datum_t sdata;         /* data to send */
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_len = MAX_PUBLIC_PARAMS_SIZE;
-  int ret, i;
+  gnutls_pk_params_st params;
+  int ret;
   gnutls_protocol_t ver;
 
   if (auth == NULL)
@@ -310,22 +294,21 @@ _gnutls_gen_rsa_client_kx (gnutls_session_t session, 
gnutls_buffer_st* data)
   /* move RSA parameters to key (session).
    */
   if ((ret =
-       _gnutls_get_public_rsa_params (session, params, &params_len)) < 0)
+       _gnutls_get_public_rsa_params (session, &params)) < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  if ((ret =
+  ret =
        _gnutls_pkcs1_rsa_encrypt (&sdata, &session->key->key,
-                                  params, params_len, 2)) < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
+                                  &params, 2);
+
+  gnutls_pk_params_release(&params);
+
+  if (ret < 0)
+    return gnutls_assert_val(ret);
 
-  for (i = 0; i < params_len; i++)
-    _gnutls_mpi_release (&params[i]);
 
   if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
     {
diff --git a/lib/auth/rsa_export.c b/lib/auth/rsa_export.c
index 4f10f55..baa990f 100644
--- a/lib/auth/rsa_export.c
+++ b/lib/auth/rsa_export.c
@@ -35,7 +35,7 @@
 #include "gnutls_datum.h"
 #include <auth/cert.h>
 #include <gnutls_pk.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_global.h>
 #include "debug.h"
 #include <gnutls_sig.h>
@@ -72,7 +72,7 @@ const mod_auth_st rsa_export_auth_struct = {
  */
 static int
 _gnutls_get_private_rsa_params (gnutls_session_t session,
-                                bigint_t ** params, int *params_size)
+                                gnutls_pk_params_st** params)
 {
   int ret;
   gnutls_certificate_credentials_t cred;
@@ -116,8 +116,7 @@ _gnutls_get_private_rsa_params (gnutls_session_t session,
    * of 512 bits size. The params in the certificate are
    * used to sign this temporary stuff.
    */
-  *params_size = RSA_PRIVATE_PARAMS;
-  *params = rsa_params->params;
+  *params = &rsa_params->params;
 
   return 0;
 }
@@ -129,8 +128,7 @@ proc_rsa_export_client_kx (gnutls_session_t session, opaque 
* data,
   gnutls_datum_t plaintext;
   gnutls_datum_t ciphertext;
   int ret, dsize;
-  bigint_t *params;
-  int params_len;
+  gnutls_pk_params_st *params;
   int randomize_key = 0;
   ssize_t data_size = _data_size;
 
@@ -157,14 +155,14 @@ proc_rsa_export_client_kx (gnutls_session_t session, 
opaque * data,
       ciphertext.size = dsize;
     }
 
-  ret = _gnutls_get_private_rsa_params (session, &params, &params_len);
+  ret = _gnutls_get_private_rsa_params (session, &params);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, 
params_len, 2);     /* btype==2 */
+  ret = _gnutls_pkcs1_rsa_decrypt (&plaintext, &ciphertext, params, 2);     /* 
btype==2 */
 
   if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
     {
@@ -236,7 +234,7 @@ static int
 gen_rsa_export_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
 {
   gnutls_rsa_params_t rsa_params;
-  const bigint_t *rsa_mpis;
+  const gnutls_pk_params_st *rsa_mpis;
   int ret = 0;
   gnutls_pcert_st *apr_cert_list;
   gnutls_privkey_t apr_pkey;
@@ -290,13 +288,13 @@ gen_rsa_export_server_kx (gnutls_session_t session, 
gnutls_buffer_st* data)
       return ret;
     }
 
-  _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);
+  _gnutls_rsa_export_set_pubkey (session, rsa_mpis->params[1], 
rsa_mpis->params[0]);
 
-  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[0], 0);
+  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis->params[0], 0);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
-  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[1], 0);
+  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis->params[1], 0);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c
index 11c0071..7f744ca 100644
--- a/lib/ext/ecc.c
+++ b/lib/ext/ecc.c
@@ -33,6 +33,7 @@
 #include <ext/ecc.h>
 #include <gnutls_state.h>
 #include <gnutls_num.h>
+#include <algorithms.h>
 
 /* Maps record size to numbers according to the
  * extensions draft.
@@ -110,7 +111,7 @@ _gnutls_supported_ecc_recv_params (gnutls_session_t session,
 
       for (i = 0; i < len; i+=2)
         {
-          new_type = _gnutls_num_to_ecc (_gnutls_read_uint16(&p[i]));
+          new_type = _gnutls_tls_id_to_ecc_curve (_gnutls_read_uint16(&p[i]));
           if (new_type < 0)
             continue;
 
@@ -177,7 +178,7 @@ _gnutls_supported_ecc_send_params (gnutls_session_t 
session, gnutls_buffer_st* e
           for (i = 0; i < len; i++)
             {
               p =
-                _gnutls_ecc_to_num (session->internals.priorities.
+                _gnutls_ecc_curve_get_tls_id (session->internals.priorities.
                                        supported_ecc.priority[i]);
               ret = _gnutls_buffer_append_prefix(extdata, 16, p);
               if (ret < 0)
@@ -246,40 +247,6 @@ _gnutls_supported_ecc_pf_send_params (gnutls_session_t 
session, gnutls_buffer_st
   return 2;
 }
 
-/* Maps numbers to record sizes according to the
- * extensions draft.
- */
-int
-_gnutls_num_to_ecc (int num)
-{
-  switch (num)
-    {
-    case 23:
-      /* sec256r1 */
-      return GNUTLS_ECC_CURVE_SECP256R1;
-    case 24:
-      return GNUTLS_ECC_CURVE_SECP384R1;
-    default:
-      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
-    }
-}
-
-/* Maps record size to numbers according to the
- * extensions draft.
- */
-int
-_gnutls_ecc_to_num (ecc_curve_t supported_ecc)
-{
-  switch (supported_ecc)
-    {
-    case GNUTLS_ECC_CURVE_SECP256R1:
-      return 23;
-    case GNUTLS_ECC_CURVE_SECP384R1:
-      return 24;
-    default:
-      return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
-    }
-}
 
 /* Returns 0 if the given ECC curve is allowed in the current
  * session. A negative error value is returned otherwise.
@@ -298,5 +265,5 @@ _gnutls_session_supports_ecc_curve (gnutls_session_t 
session, int ecc_type)
         }
     }
 
-  return GNUTLS_E_ECC_NO_SUPPORTED_CURVES;
+  return GNUTLS_E_ECC_UNSUPPORTED_CURVE;
 }
diff --git a/lib/ext/ecc.h b/lib/ext/ecc.h
index 745a000..b2c22a4 100644
--- a/lib/ext/ecc.h
+++ b/lib/ext/ecc.h
@@ -29,8 +29,6 @@
 extern extension_entry_st ext_mod_supported_ecc;
 extern extension_entry_st ext_mod_supported_ecc_pf;
 
-int _gnutls_num_to_ecc (int num);
-int _gnutls_ecc_to_num (ecc_curve_t);
 int
 _gnutls_session_supports_ecc_curve (gnutls_session_t session, int ecc_type);
 
diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
index 5bc8ab6..2975691 100644
--- a/lib/ext/session_ticket.c
+++ b/lib/ext/session_ticket.c
@@ -25,7 +25,7 @@
 #include <gnutls_int.h>
 #include <gnutls_errors.h>
 #include <gnutls_datum.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_handshake.h>
 #include <gnutls_num.h>
 #include <gnutls_constate.h>
diff --git a/lib/ext/signature.c b/lib/ext/signature.c
index 76a8c02..d2abd48 100644
--- a/lib/ext/signature.c
+++ b/lib/ext/signature.c
@@ -33,7 +33,7 @@
 #include <ext/signature.h>
 #include <gnutls_state.h>
 #include <gnutls_num.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <x509/common.h> /* dsa_q_to_hash */
 #include <abstract_int.h>
 
diff --git a/lib/ext/srp.c b/lib/ext/srp.c
index 7c80d68..1a3fa01 100644
--- a/lib/ext/srp.c
+++ b/lib/ext/srp.c
@@ -31,7 +31,7 @@
 #include "gnutls_auth.h"
 #include <auth/srp.h>
 #include "gnutls_errors.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include <gnutls_num.h>
 #include <gnutls_extensions.h>
 
diff --git a/lib/gnutls.asn b/lib/gnutls.asn
index f485c27..64e0519 100644
--- a/lib/gnutls.asn
+++ b/lib/gnutls.asn
@@ -89,5 +89,18 @@ DHParameter ::= SEQUENCE {
   privateValueLength  INTEGER OPTIONAL 
 }
 
+-- ECC from RFC5480
+ECPoint ::= OCTET STRING
+
+ECParameters ::= CHOICE {
+  namedCurve         OBJECT IDENTIFIER
+}
+
+ECPrivateKey ::= SEQUENCE {
+   Version       INTEGER, -- { ecPrivkeyVer1(1) }
+   privateKey    OCTET STRING,
+   parameters    [0] ECParameters OPTIONAL,
+   publicKey     [1] BIT STRING OPTIONAL
+}
 
 END
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
deleted file mode 100644
index 44cc0a0..0000000
--- a/lib/gnutls_algorithms.c
+++ /dev/null
@@ -1,2687 +0,0 @@
-/*
- * Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2010 Free Software Foundation, Inc.
- *
- * Author: Nikos Mavrogiannopoulos
- *
- * This file is part of GnuTLS.
- *
- * The GnuTLS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- */
-
-#include "gnutls_int.h"
-#include "gnutls_algorithms.h"
-#include "gnutls_errors.h"
-#include <x509/common.h>
-
-
-typedef struct
-{
-  const char *name;
-  gnutls_sec_param_t sec_param;
-  int bits;                     /* security level */
-  int pk_bits;                  /* DH, RSA, SRP */
-  int dsa_bits;                 /* bits for DSA. Handled differently since
-                                 * choice of key size in DSA is political.
-                                 */
-  int subgroup_bits;            /* subgroup bits */
-  int ecc_bits;                 /* bits for ECC keys */
-} gnutls_sec_params_entry;
-
-static const gnutls_sec_params_entry sec_params[] = {
-  {"Weak", GNUTLS_SEC_PARAM_WEAK, 64, 816, 1024, 128, 128},
-  {"Low", GNUTLS_SEC_PARAM_LOW, 80, 1248, 2048, 160, 160},
-  {"Normal", GNUTLS_SEC_PARAM_NORMAL, 112, 2432, 3072, 224, 224},
-  {"High", GNUTLS_SEC_PARAM_HIGH, 128, 3248, 3072, 256, 256},
-  {"Ultra", GNUTLS_SEC_PARAM_ULTRA, 256, 15424, 3072, 512, 512},
-  {NULL, 0, 0, 0, 0, 0}
-};
-
-#define GNUTLS_SEC_PARAM_LOOP(b) \
-       { const gnutls_sec_params_entry *p; \
-                for(p = sec_params; p->name != NULL; p++) { b ; } }
-
-
-/* Cred type mappings to KX algorithms 
- * FIXME: The mappings are not 1-1. Some KX such as SRP_RSA require
- * more than one credentials type.
- */
-typedef struct
-{
-  gnutls_kx_algorithm_t algorithm;
-  gnutls_credentials_type_t client_type;
-  gnutls_credentials_type_t server_type;        /* The type of credentials a 
server
-                                                 * needs to set */
-} gnutls_cred_map;
-
-static const gnutls_cred_map cred_mappings[] = {
-  {GNUTLS_KX_ANON_DH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
-  {GNUTLS_KX_ANON_ECDH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
-  {GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
-  {GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
-  {GNUTLS_KX_ECDHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
-  {GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
-  {GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
-  {GNUTLS_KX_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
-  {GNUTLS_KX_DHE_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
-  {GNUTLS_KX_SRP, GNUTLS_CRD_SRP, GNUTLS_CRD_SRP},
-  {GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
-  {GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
-  {0, 0, 0}
-};
-
-#define GNUTLS_KX_MAP_LOOP(b) \
-        const gnutls_cred_map *p; \
-                for(p = cred_mappings; p->algorithm != 0; p++) { b ; }
-
-#define GNUTLS_KX_MAP_ALG_LOOP_SERVER(a) \
-                        GNUTLS_KX_MAP_LOOP( if(p->server_type == type) { a; 
break; })
-
-/* KX mappings to PK algorithms */
-typedef struct
-{
-  gnutls_kx_algorithm_t kx_algorithm;
-  gnutls_pk_algorithm_t pk_algorithm;
-  enum encipher_type encipher_type;     /* CIPHER_ENCRYPT if this algorithm is 
to be used
-                                         * for encryption, CIPHER_SIGN if 
signature only,
-                                         * CIPHER_IGN if this does not apply 
at all.
-                                         *
-                                         * This is useful to certificate 
cipher suites, which check
-                                         * against the certificate key usage 
bits.
-                                         */
-} gnutls_pk_map;
-
-/* This table maps the Key exchange algorithms to
- * the certificate algorithms. Eg. if we have
- * RSA algorithm in the certificate then we can
- * use GNUTLS_KX_RSA or GNUTLS_KX_DHE_RSA.
- */
-static const gnutls_pk_map pk_mappings[] = {
-  {GNUTLS_KX_RSA, GNUTLS_PK_RSA, CIPHER_ENCRYPT},
-  {GNUTLS_KX_RSA_EXPORT, GNUTLS_PK_RSA, CIPHER_SIGN},
-  {GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
-  {GNUTLS_KX_SRP_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
-  {GNUTLS_KX_ECDHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
-  {GNUTLS_KX_DHE_DSS, GNUTLS_PK_DSA, CIPHER_SIGN},
-  {GNUTLS_KX_SRP_DSS, GNUTLS_PK_DSA, CIPHER_SIGN},
-  {0, 0, 0}
-};
-
-#define GNUTLS_PK_MAP_LOOP(b) \
-        const gnutls_pk_map *p; \
-                for(p = pk_mappings; p->kx_algorithm != 0; p++) { b }
-
-#define GNUTLS_PK_MAP_ALG_LOOP(a) \
-                        GNUTLS_PK_MAP_LOOP( if(p->kx_algorithm == 
kx_algorithm) { a; break; })
-
-
-
-/* TLS Versions */
-
-typedef struct
-{
-  const char *name;
-  gnutls_protocol_t id;         /* gnutls internal version number */
-  int major;                    /* defined by the protocol */
-  int minor;                    /* defined by the protocol */
-  transport_t transport;       /* Type of transport, stream or datagram */
-  int supported;                /* 0 not supported, > 0 is supported */
-} gnutls_version_entry;
-
-static const gnutls_version_entry sup_versions[] = {
-  {"SSL3.0", GNUTLS_SSL3, 3, 0, GNUTLS_STREAM, 1},
-  {"TLS1.0", GNUTLS_TLS1, 3, 1, GNUTLS_STREAM, 1},
-  {"TLS1.1", GNUTLS_TLS1_1, 3, 2, GNUTLS_STREAM, 1},
-  {"TLS1.2", GNUTLS_TLS1_2, 3, 3, GNUTLS_STREAM, 1},
-  {"DTLS1.0", GNUTLS_DTLS1_0, 254, 255, GNUTLS_DGRAM, 1}, /* 1.1 over datagram 
*/
-  {0, 0, 0, 0, 0}
-};
-
-#define GNUTLS_VERSION_LOOP(b) \
-        const gnutls_version_entry *p; \
-                for(p = sup_versions; p->name != NULL; p++) { b ; }
-
-#define GNUTLS_VERSION_ALG_LOOP(a) \
-       GNUTLS_VERSION_LOOP( if(p->id == version) { a; break; })
-
-struct gnutls_cipher_entry
-{
-  const char *name;
-  gnutls_cipher_algorithm_t id;
-  uint16_t blocksize;
-  uint16_t keysize;
-  unsigned block:1;
-  uint16_t iv; /* the size of IV */
-  unsigned export_flag:1; /* 0 non export */
-  unsigned auth:1; /* Whether it is authenc cipher */
-};
-typedef struct gnutls_cipher_entry gnutls_cipher_entry;
-
-/* Note that all algorithms are in CBC or STREAM modes. 
- * Do not add any algorithms in other modes (avoid modified algorithms).
- * View first: "The order of encryption and authentication for
- * protecting communications" by Hugo Krawczyk - CRYPTO 2001
- *
- * Make sure to updated MAX_CIPHER_BLOCK_SIZE and MAX_CIPHER_KEY_SIZE as well.
- */
-static const gnutls_cipher_entry algorithms[] = {
-  {"AES-256-CBC", GNUTLS_CIPHER_AES_256_CBC, 16, 32, CIPHER_BLOCK, 16, 0, 0},
-  {"AES-192-CBC", GNUTLS_CIPHER_AES_192_CBC, 16, 24, CIPHER_BLOCK, 16, 0, 0},
-  {"AES-128-CBC", GNUTLS_CIPHER_AES_128_CBC, 16, 16, CIPHER_BLOCK, 16, 0, 0},
-  {"AES-128-GCM", GNUTLS_CIPHER_AES_128_GCM, 16, 16, CIPHER_STREAM, 
AEAD_IMPLICIT_DATA_SIZE, 0, 1},
-  {"3DES-CBC", GNUTLS_CIPHER_3DES_CBC, 8, 24, CIPHER_BLOCK, 8, 0, 0},
-  {"DES-CBC", GNUTLS_CIPHER_DES_CBC, 8, 8, CIPHER_BLOCK, 8, 0, 0},
-  {"ARCFOUR-128", GNUTLS_CIPHER_ARCFOUR_128, 1, 16, CIPHER_STREAM, 0, 0, 0},
-  {"ARCFOUR-40", GNUTLS_CIPHER_ARCFOUR_40, 1, 5, CIPHER_STREAM, 0, 1, 0},
-  {"RC2-40", GNUTLS_CIPHER_RC2_40_CBC, 8, 5, CIPHER_BLOCK, 8, 1, 0},
-#ifdef ENABLE_CAMELLIA
-  {"CAMELLIA-256-CBC", GNUTLS_CIPHER_CAMELLIA_256_CBC, 16, 32, CIPHER_BLOCK,
-   16, 0, 0},
-  {"CAMELLIA-128-CBC", GNUTLS_CIPHER_CAMELLIA_128_CBC, 16, 16, CIPHER_BLOCK,
-   16, 0, 0},
-#endif
-
-#ifdef ENABLE_OPENPGP
-  {"IDEA-PGP-CFB", GNUTLS_CIPHER_IDEA_PGP_CFB, 8, 16, CIPHER_BLOCK, 8, 0, 0},
-  {"3DES-PGP-CFB", GNUTLS_CIPHER_3DES_PGP_CFB, 8, 24, CIPHER_BLOCK, 8, 0, 0},
-  {"CAST5-PGP-CFB", GNUTLS_CIPHER_CAST5_PGP_CFB, 8, 16, CIPHER_BLOCK, 8, 0, 0},
-  {"BLOWFISH-PGP-CFB", GNUTLS_CIPHER_BLOWFISH_PGP_CFB, 8,
-   16 /*actually unlimited */ , CIPHER_BLOCK, 8, 0, 0},
-  {"SAFER-SK128-PGP-CFB", GNUTLS_CIPHER_SAFER_SK128_PGP_CFB, 8, 16,
-   CIPHER_BLOCK, 8, 0, 0},
-  {"AES-128-PGP-CFB", GNUTLS_CIPHER_AES128_PGP_CFB, 16, 16, CIPHER_BLOCK, 16,
-   0, 0},
-  {"AES-192-PGP-CFB", GNUTLS_CIPHER_AES192_PGP_CFB, 16, 24, CIPHER_BLOCK, 16,
-   0, 0},
-  {"AES-256-PGP-CFB", GNUTLS_CIPHER_AES256_PGP_CFB, 16, 32, CIPHER_BLOCK, 16,
-   0, 0},
-  {"TWOFISH-PGP-CFB", GNUTLS_CIPHER_TWOFISH_PGP_CFB, 16, 16, CIPHER_BLOCK, 16,
-   0, 0},
-#endif
-  {"NULL", GNUTLS_CIPHER_NULL, 1, 0, CIPHER_STREAM, 0, 0, 0},
-  {0, 0, 0, 0, 0, 0, 0}
-};
-
-#define GNUTLS_CIPHER_LOOP(b) \
-        const gnutls_cipher_entry *p; \
-                for(p = algorithms; p->name != NULL; p++) { b ; }
-
-#define GNUTLS_ALG_LOOP(a) \
-                        GNUTLS_CIPHER_LOOP( if(p->id == algorithm) { a; break; 
} )
-
-
-struct gnutls_hash_entry
-{
-  const char *name;
-  const char *oid;
-  gnutls_mac_algorithm_t id;
-  size_t key_size;              /* in case of mac */
-};
-typedef struct gnutls_hash_entry gnutls_hash_entry;
-
-static const gnutls_hash_entry hash_algorithms[] = {
-  {"SHA1", HASH_OID_SHA1, GNUTLS_MAC_SHA1, 20},
-  {"MD5", HASH_OID_MD5, GNUTLS_MAC_MD5, 16},
-  {"SHA256", HASH_OID_SHA256, GNUTLS_MAC_SHA256, 32},
-  {"SHA384", HASH_OID_SHA384, GNUTLS_MAC_SHA384, 48},
-  {"SHA512", HASH_OID_SHA512, GNUTLS_MAC_SHA512, 64},
-  {"SHA224", HASH_OID_SHA224, GNUTLS_MAC_SHA224, 28},
-  {"AEAD", NULL, GNUTLS_MAC_AEAD, 0},
-  {"MD2", HASH_OID_MD2, GNUTLS_MAC_MD2, 0},     /* not used as MAC */
-  {"RIPEMD160", HASH_OID_RMD160, GNUTLS_MAC_RMD160, 20},
-  {"MAC-NULL", NULL, GNUTLS_MAC_NULL, 0},
-  {0, 0, 0, 0}
-};
-
-
-#define GNUTLS_HASH_LOOP(b) \
-        const gnutls_hash_entry *p; \
-                for(p = hash_algorithms; p->name != NULL; p++) { b ; }
-
-#define GNUTLS_HASH_ALG_LOOP(a) \
-                        GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } 
)
-
-/* Key Exchange Section */
-
-
-extern mod_auth_st rsa_auth_struct;
-extern mod_auth_st rsa_export_auth_struct;
-extern mod_auth_st dhe_rsa_auth_struct;
-extern mod_auth_st ecdhe_rsa_auth_struct;
-extern mod_auth_st dhe_dss_auth_struct;
-extern mod_auth_st anon_auth_struct;
-extern mod_auth_st anon_ecdh_auth_struct;
-extern mod_auth_st srp_auth_struct;
-extern mod_auth_st psk_auth_struct;
-extern mod_auth_st dhe_psk_auth_struct;
-extern mod_auth_st srp_rsa_auth_struct;
-extern mod_auth_st srp_dss_auth_struct;
-
-struct gnutls_kx_algo_entry
-{
-  const char *name;
-  gnutls_kx_algorithm_t algorithm;
-  mod_auth_st *auth_struct;
-  int needs_dh_params;
-  int needs_rsa_params;
-};
-typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry;
-
-static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = {
-#ifdef ENABLE_ANON
-  {"ANON-DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, 0},
-  {"ANON-ECDH", GNUTLS_KX_ANON_ECDH, &anon_ecdh_auth_struct, 0, 0},
-#endif
-  {"RSA", GNUTLS_KX_RSA, &rsa_auth_struct, 0, 0},
-  {"RSA-EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct, 0,
-   1 /* needs RSA params */ },
-  {"DHE-RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, 0},
-  {"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 1, 0},
-  {"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 0},
-
-#ifdef ENABLE_SRP
-  {"SRP-DSS", GNUTLS_KX_SRP_DSS, &srp_dss_auth_struct, 0, 0},
-  {"SRP-RSA", GNUTLS_KX_SRP_RSA, &srp_rsa_auth_struct, 0, 0},
-  {"SRP", GNUTLS_KX_SRP, &srp_auth_struct, 0, 0},
-#endif
-#ifdef ENABLE_PSK
-  {"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0, 0},
-  {"DHE-PSK", GNUTLS_KX_DHE_PSK, &dhe_psk_auth_struct,
-   1 /* needs DHE params */ , 0},
-#endif
-  {0, 0, 0, 0, 0}
-};
-
-#define GNUTLS_KX_LOOP(b) \
-        const gnutls_kx_algo_entry *p; \
-                for(p = _gnutls_kx_algorithms; p->name != NULL; p++) { b ; }
-
-#define GNUTLS_KX_ALG_LOOP(a) \
-                        GNUTLS_KX_LOOP( if(p->algorithm == algorithm) { a; 
break; } )
-
-
-
-/* Cipher SUITES */
-#define GNUTLS_CIPHER_SUITE_ENTRY( name, block_algorithm, kx_algorithm, 
mac_algorithm, min_version, max_version, dtls ) \
-       { #name, {name}, block_algorithm, kx_algorithm, mac_algorithm, 
min_version, max_version, dtls}
-
-typedef struct
-{
-  const char *name;
-  cipher_suite_st id;
-  gnutls_cipher_algorithm_t block_algorithm;
-  gnutls_kx_algorithm_t kx_algorithm;
-  gnutls_mac_algorithm_t mac_algorithm;
-  gnutls_protocol_t min_version;        /* this cipher suite is supported
-                                         * from 'version' and above;
-                                         */
-  gnutls_protocol_t max_version;        /* this cipher suite is not supported 
after that */
-  int dtls:1; /* whether this ciphersuite is valid in DTLS */
-} gnutls_cipher_suite_entry;
-
-/* RSA with NULL cipher and MD5 MAC
- * for test purposes.
- */
-#define GNUTLS_RSA_NULL_MD5 { 0x00, 0x01 }
-#define GNUTLS_RSA_NULL_SHA1 { 0x00, 0x02 }
-#define GNUTLS_RSA_NULL_SHA256 { 0x00, 0x3B }
-
-/* ANONymous cipher suites.
- */
-
-#define GNUTLS_ANON_DH_3DES_EDE_CBC_SHA1 { 0x00, 0x1B }
-#define GNUTLS_ANON_DH_ARCFOUR_MD5 { 0x00, 0x18 }
-
- /* rfc3268: */
-#define GNUTLS_ANON_DH_AES_128_CBC_SHA1 { 0x00, 0x34 }
-#define GNUTLS_ANON_DH_AES_256_CBC_SHA1 { 0x00, 0x3A }
-
-/* rfc4132 */
-#ifdef ENABLE_CAMELLIA
-#define GNUTLS_ANON_DH_CAMELLIA_128_CBC_SHA1 { 0x00,0x46 }
-#define GNUTLS_ANON_DH_CAMELLIA_256_CBC_SHA1 { 0x00,0x89 }
-#endif
-
-#define GNUTLS_ANON_DH_AES_128_CBC_SHA256 { 0x00, 0x6C }
-#define GNUTLS_ANON_DH_AES_256_CBC_SHA256 { 0x00, 0x6D }
-
-/* PSK (not in TLS 1.0)
- * draft-ietf-tls-psk:
- */
-#define GNUTLS_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8A }
-#define GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8B }
-#define GNUTLS_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x8C }
-#define GNUTLS_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x8D }
-
-#define GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8E }
-#define GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8F }
-#define GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x90 }
-#define GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x91 }
-
-
-/* SRP (rfc5054)
- */
-#define GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1A }
-#define GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1 { 0xC0, 0x1B }
-#define GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1 { 0xC0, 0x1C }
-
-#define GNUTLS_SRP_SHA_AES_128_CBC_SHA1 { 0xC0, 0x1D }
-#define GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1 { 0xC0, 0x1E }
-#define GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1 { 0xC0, 0x1F }
-
-#define GNUTLS_SRP_SHA_AES_256_CBC_SHA1 { 0xC0, 0x20 }
-#define GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1 { 0xC0, 0x21 }
-#define GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1 { 0xC0, 0x22 }
-
-/* RSA
- */
-#define GNUTLS_RSA_ARCFOUR_SHA1 { 0x00, 0x05 }
-#define GNUTLS_RSA_ARCFOUR_MD5 { 0x00, 0x04 }
-#define GNUTLS_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x0A }
-
-#define GNUTLS_RSA_EXPORT_ARCFOUR_40_MD5 { 0x00, 0x03 }
-
-/* rfc3268:
- */
-#define GNUTLS_RSA_AES_128_CBC_SHA1 { 0x00, 0x2F }
-#define GNUTLS_RSA_AES_256_CBC_SHA1 { 0x00, 0x35 }
-
-/* rfc4132 */
-#ifdef ENABLE_CAMELLIA
-#define GNUTLS_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x41 }
-#define GNUTLS_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x84 }
-#endif
-
-#define GNUTLS_RSA_AES_128_CBC_SHA256 { 0x00, 0x3C }
-#define GNUTLS_RSA_AES_256_CBC_SHA256 { 0x00, 0x3D }
-
-/* DHE DSS
- */
-
-#define GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1 { 0x00, 0x13 }
-
-
-/* draft-ietf-tls-56-bit-ciphersuites-01:
- */
-#define GNUTLS_DHE_DSS_ARCFOUR_SHA1 { 0x00, 0x66 }
-
-
-/* rfc3268:
- */
-#define GNUTLS_DHE_DSS_AES_256_CBC_SHA1 { 0x00, 0x38 }
-#define GNUTLS_DHE_DSS_AES_128_CBC_SHA1 { 0x00, 0x32 }
-
-/* rfc4132 */
-#ifdef ENABLE_CAMELLIA
-#define GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1 { 0x00,0x44 }
-#define GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1 { 0x00,0x87 }
-#endif
-
-#define GNUTLS_DHE_DSS_AES_128_CBC_SHA256 { 0x00, 0x40 }
-#define GNUTLS_DHE_DSS_AES_256_CBC_SHA256 { 0x00, 0x6A }
-
-/* DHE RSA
- */
-#define GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1 { 0x00, 0x16 }
-
-/* rfc3268:
- */
-#define GNUTLS_DHE_RSA_AES_128_CBC_SHA1 { 0x00, 0x33 }
-#define GNUTLS_DHE_RSA_AES_256_CBC_SHA1 { 0x00, 0x39 }
-
-/* rfc4132 */
-#ifdef ENABLE_CAMELLIA
-#define GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1 { 0x00,0x45 }
-#define GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 { 0x00,0x88 }
-#endif
-
-#define GNUTLS_DHE_RSA_AES_128_CBC_SHA256 { 0x00, 0x67 }
-#define GNUTLS_DHE_RSA_AES_256_CBC_SHA256 { 0x00, 0x6B }
-
-/* GCM: RFC5288 */
-#define GNUTLS_RSA_AES_128_GCM_SHA256 { 0x00, 0x9C }
-#define GNUTLS_DHE_RSA_AES_128_GCM_SHA256 {0x00,0x9E}
-#define GNUTLS_DHE_DSS_AES_128_GCM_SHA256 {0x00,0xA2}
-#define GNUTLS_DH_ANON_AES_128_GCM_SHA256 {0x00,0xA6}
-
-/* RFC 5487 */
-/* GCM-PSK */
-#define GNUTLS_PSK_AES_128_GCM_SHA256 { 0x00, 0xA8 }
-#define GNUTLS_DHE_PSK_AES_128_GCM_SHA256 { 0x00, 0xAA }
-
-/* PSK - SHA256 HMAC */
-#define GNUTLS_PSK_AES_128_CBC_SHA256 { 0x00, 0xAE }
-#define GNUTLS_DHE_PSK_AES_128_CBC_SHA256 { 0x00, 0xB2 }
-
-#define GNUTLS_PSK_NULL_SHA256 { 0x00, 0xB0 }
-#define GNUTLS_DHE_PSK_NULL_SHA256 { 0x00, 0xB4 }
-
-/* ECC */
-#define GNUTLS_ECDH_ANON_NULL_SHA { 0xC0, 0x15 }
-#define GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA { 0xC0, 0x17 }
-#define GNUTLS_ECDH_ANON_AES_128_CBC_SHA { 0xC0, 0x18 }
-#define GNUTLS_ECDH_ANON_AES_256_CBC_SHA { 0xC0, 0x19 }
-
-/* ECC-RSA */
-#define GNUTLS_ECDHE_RSA_NULL_SHA { 0xC0, 0x10 }
-#define GNUTLS_ECDHE_RSA_3DES_EDE_CBC_SHA { 0xC0, 0x12 }
-#define GNUTLS_ECDHE_RSA_AES_128_CBC_SHA { 0xC0, 0x13 }
-#define GNUTLS_ECDHE_RSA_AES_256_CBC_SHA { 0xC0, 0x14 }
-
-
-#define CIPHER_SUITES_COUNT 
sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry)-1
-
-/* FIXME: what we don't handle here is TLS 1.2 requirement
- * that each ciphersuite has it's own PRF algorithm. Now we
- * assume that each one uses the SHA-256 PRF in TLS 1.2.
- */
-
-static const gnutls_cipher_suite_entry cs_algorithms[] = {
-  /* ANON_DH */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_ARCFOUR_MD5,
-                             GNUTLS_CIPHER_ARCFOUR_128,
-                             GNUTLS_KX_ANON_DH, GNUTLS_MAC_MD5,
-                             GNUTLS_SSL3, GNUTLS_VERSION_MAX, 0),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, ),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-#ifdef ENABLE_CAMELLIA
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_CAMELLIA_128_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_128_CBC,
-                             GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_CAMELLIA_256_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_256_CBC,
-                             GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-#endif
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_128_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ANON_DH_AES_256_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-
-  /* PSK */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_ARCFOUR_SHA1,
-                             GNUTLS_CIPHER_ARCFOUR, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 0),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_SHA_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_AES_128_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_AES_128_GCM_SHA256,
-                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_PSK_NULL_SHA256,
-                             GNUTLS_CIPHER_NULL, GNUTLS_KX_PSK,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  /* DHE-PSK */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_ARCFOUR_SHA1,
-                             GNUTLS_CIPHER_ARCFOUR, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 0),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_SHA_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_AES_128_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_AES_128_GCM_SHA256,
-                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_PSK_NULL_SHA256,
-                             GNUTLS_CIPHER_NULL, GNUTLS_KX_DHE_PSK,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  /* SRP */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_SRP,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_SRP,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_SRP_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_SRP_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_DSS_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_SRP_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_SRP_SHA_RSA_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_SRP_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-
-  /* DHE_DSS */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_ARCFOUR_SHA1,
-                             GNUTLS_CIPHER_ARCFOUR_128, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 0),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-#ifdef ENABLE_CAMELLIA
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_CAMELLIA_128_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_128_CBC,
-                             GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_CAMELLIA_256_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_256_CBC,
-                             GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-#endif
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_256_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  /* DHE_RSA */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-#ifdef ENABLE_CAMELLIA
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_CAMELLIA_128_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_128_CBC,
-                             GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_CAMELLIA_256_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_256_CBC,
-                             GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-#endif
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_256_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  /* RSA-NULL */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_MD5,
-                             GNUTLS_CIPHER_NULL,
-                             GNUTLS_KX_RSA, GNUTLS_MAC_MD5, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_SHA1,
-                             GNUTLS_CIPHER_NULL,
-                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_NULL_SHA256,
-                             GNUTLS_CIPHER_NULL,
-                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-
-  /* RSA-EXPORT */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_EXPORT_ARCFOUR_40_MD5,
-                             GNUTLS_CIPHER_ARCFOUR_40,
-                             GNUTLS_KX_RSA_EXPORT, GNUTLS_MAC_MD5,
-                             GNUTLS_SSL3, GNUTLS_TLS1_0, 0),
-
-  /* RSA */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_SHA1,
-                             GNUTLS_CIPHER_ARCFOUR_128,
-                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 0),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_ARCFOUR_MD5,
-                             GNUTLS_CIPHER_ARCFOUR_128,
-                             GNUTLS_KX_RSA, GNUTLS_MAC_MD5, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 0),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_3DES_EDE_CBC_SHA1,
-                             GNUTLS_CIPHER_3DES_CBC,
-                             GNUTLS_KX_RSA, GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA1,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_SSL3,
-                             GNUTLS_VERSION_MAX, 1),
-#ifdef ENABLE_CAMELLIA
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_CAMELLIA_128_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_128_CBC, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_CAMELLIA_256_CBC_SHA1,
-                             GNUTLS_CIPHER_CAMELLIA_256_CBC, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1,
-                             GNUTLS_VERSION_MAX, 1),
-#endif
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_256_CBC_SHA256,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_SHA256, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-/* GCM */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_RSA_AES_128_GCM_SHA256,
-                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_RSA,
-                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_RSA_AES_128_GCM_SHA256,
-                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_DHE_RSA,
-                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DHE_DSS_AES_128_GCM_SHA256,
-                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_DHE_DSS,
-                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_DH_ANON_AES_128_GCM_SHA256,
-                             GNUTLS_CIPHER_AES_128_GCM, GNUTLS_KX_ANON_DH,
-                             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-                             GNUTLS_VERSION_MAX, 1),
-/* ECC-ANON */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_NULL_SHA,
-                             GNUTLS_CIPHER_NULL, GNUTLS_KX_ANON_ECDH,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_3DES_EDE_CBC_SHA,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ANON_ECDH,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_AES_128_CBC_SHA,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ANON_ECDH,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDH_ANON_AES_256_CBC_SHA,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_ECDH,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-/* ECC-RSA */
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_NULL_SHA,
-                             GNUTLS_CIPHER_NULL, GNUTLS_KX_ECDHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_3DES_EDE_CBC_SHA,
-                             GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_ECDHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_AES_128_CBC_SHA,
-                             GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_ECDHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  GNUTLS_CIPHER_SUITE_ENTRY (GNUTLS_ECDHE_RSA_AES_256_CBC_SHA,
-                             GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ECDHE_RSA,
-                             GNUTLS_MAC_SHA1, GNUTLS_TLS1_0,
-                             GNUTLS_VERSION_MAX, 1),
-  {0, {{0, 0}}, 0, 0, 0, 0, 0, 0}
-};
-
-#define GNUTLS_CIPHER_SUITE_LOOP(b) \
-        const gnutls_cipher_suite_entry *p; \
-                for(p = cs_algorithms; p->name != NULL; p++) { b ; }
-
-#define GNUTLS_CIPHER_SUITE_ALG_LOOP(a) \
-                        GNUTLS_CIPHER_SUITE_LOOP( if( (p->id.suite[0] == 
suite->suite[0]) && (p->id.suite[1] == suite->suite[1])) { a; break; } )
-
-
-
-/* Generic Functions */
-
-int
-_gnutls_mac_priority (gnutls_session_t session,
-                      gnutls_mac_algorithm_t algorithm)
-{                               /* actually returns the priority */
-  unsigned int i;
-  for (i = 0; i < session->internals.priorities.mac.algorithms; i++)
-    {
-      if (session->internals.priorities.mac.priority[i] == algorithm)
-        return i;
-    }
-  return -1;
-}
-
-/**
- * gnutls_mac_get_name:
- * @algorithm: is a MAC algorithm
- *
- * Convert a #gnutls_mac_algorithm_t value to a string.
- *
- * Returns: a string that contains the name of the specified MAC
- *   algorithm, or %NULL.
- **/
-const char *
-gnutls_mac_get_name (gnutls_mac_algorithm_t algorithm)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_HASH_ALG_LOOP (ret = p->name);
-
-  return ret;
-}
-
-/**
- * gnutls_mac_get_id:
- * @name: is a MAC algorithm name
- *
- * Convert a string to a #gnutls_mac_algorithm_t value.  The names are
- * compared in a case insensitive way.
- *
- * Returns: a #gnutls_mac_algorithm_t id of the specified MAC
- *   algorithm string, or %GNUTLS_MAC_UNKNOWN on failures.
- **/
-gnutls_mac_algorithm_t
-gnutls_mac_get_id (const char *name)
-{
-  gnutls_mac_algorithm_t ret = GNUTLS_MAC_UNKNOWN;
-
-  GNUTLS_HASH_LOOP (
-    if (strcasecmp (p->name, name) == 0) 
-      {
-        ret = p->id;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_mac_get_key_size:
- * @algorithm: is an encryption algorithm
- *
- * Get size of MAC key.
- *
- * Returns: length (in bytes) of the given MAC key size, or 0 if the
- *   given MAC algorithm is invalid.
- **/
-size_t
-gnutls_mac_get_key_size (gnutls_mac_algorithm_t algorithm)
-{
-  size_t ret = 0;
-
-  /* avoid prefix */
-  GNUTLS_HASH_ALG_LOOP (ret = p->key_size);
-
-  return ret;
-}
-
-/**
- * gnutls_mac_list:
- *
- * Get a list of hash algorithms for use as MACs.  Note that not
- * necessarily all MACs are supported in TLS cipher suites.  For
- * example, MD2 is not supported as a cipher suite, but is supported
- * for other purposes (e.g., X.509 signature verification or similar).
- *
- * This function is not thread safe.
- *
- * Returns: Return a zero-terminated list of #gnutls_mac_algorithm_t
- *   integers indicating the available MACs.
- **/
-const gnutls_mac_algorithm_t *
-gnutls_mac_list (void)
-{
-static gnutls_mac_algorithm_t supported_macs[MAX_ALGOS] = { 0 };
-
-  if (supported_macs[0] == 0)
-    {
-      int i = 0;
-
-      GNUTLS_HASH_LOOP ( supported_macs[i++]=p->id);
-      supported_macs[i++]=0;
-    }
-
-  return supported_macs;
-}
-
-const char *
-_gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t algorithm)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_HASH_ALG_LOOP (ret = p->oid);
-
-  return ret;
-}
-
-gnutls_mac_algorithm_t
-_gnutls_x509_oid2mac_algorithm (const char *oid)
-{
-  gnutls_mac_algorithm_t ret = 0;
-
-  GNUTLS_HASH_LOOP (if (p->oid && strcmp (oid, p->oid) == 0)
-                    {
-                    ret = p->id; break;}
-  );
-
-  if (ret == 0)
-    return GNUTLS_MAC_UNKNOWN;
-  return ret;
-}
-
-
-int
-_gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm)
-{
-  ssize_t ret = -1;
-  GNUTLS_HASH_ALG_LOOP (ret = p->id);
-  if (ret >= 0)
-    ret = 0;
-  else
-    ret = 1;
-  return ret;
-}
-
-/* CIPHER functions */
-
-/**
- * gnutls_cipher_get_block_size:
- * @algorithm: is an encryption algorithm
- *
- * Get block size for encryption algorithm.
- *
- * Returns: block size for encryption algorithm.
- *
- * Since: 2.10.0
- **/
-int
-gnutls_cipher_get_block_size (gnutls_cipher_algorithm_t algorithm)
-{
-  size_t ret = 0;
-  GNUTLS_ALG_LOOP (ret = p->blocksize);
-  return ret;
-
-}
-
- /* returns the priority */
-int
-_gnutls_cipher_priority (gnutls_session_t session,
-                         gnutls_cipher_algorithm_t algorithm)
-{
-  unsigned int i;
-  for (i = 0; i < session->internals.priorities.cipher.algorithms; i++)
-    {
-      if (session->internals.priorities.cipher.priority[i] == algorithm)
-        return i;
-    }
-  return -1;
-}
-
-
-int
-_gnutls_cipher_is_block (gnutls_cipher_algorithm_t algorithm)
-{
-  size_t ret = 0;
-
-  GNUTLS_ALG_LOOP (ret = p->block);
-  return ret;
-
-}
-
-int
-_gnutls_cipher_algo_is_aead (gnutls_cipher_algorithm_t algorithm)
-{
-  size_t ret = 0;
-
-  GNUTLS_ALG_LOOP (ret = p->auth);
-  return ret;
-
-}
-
-/**
- * gnutls_cipher_get_key_size:
- * @algorithm: is an encryption algorithm
- *
- * Get key size for cipher.
- *
- * Returns: length (in bytes) of the given cipher's key size, or 0 if
- *   the given cipher is invalid.
- **/
-size_t
-gnutls_cipher_get_key_size (gnutls_cipher_algorithm_t algorithm)
-{                               /* In bytes */
-  size_t ret = 0;
-  GNUTLS_ALG_LOOP (ret = p->keysize);
-  return ret;
-
-}
-
-int
-_gnutls_cipher_get_iv_size (gnutls_cipher_algorithm_t algorithm)
-{                               /* In bytes */
-  size_t ret = 0;
-  GNUTLS_ALG_LOOP (ret = p->iv);
-  return ret;
-
-}
-
-int
-_gnutls_cipher_get_export_flag (gnutls_cipher_algorithm_t algorithm)
-{                               /* In bytes */
-  size_t ret = 0;
-  GNUTLS_ALG_LOOP (ret = p->export_flag);
-  return ret;
-
-}
-
-/**
- * gnutls_cipher_get_name:
- * @algorithm: is an encryption algorithm
- *
- * Convert a #gnutls_cipher_algorithm_t type to a string.
- *
- * Returns: a pointer to a string that contains the name of the
- *   specified cipher, or %NULL.
- **/
-const char *
-gnutls_cipher_get_name (gnutls_cipher_algorithm_t algorithm)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_ALG_LOOP (ret = p->name);
-
-  return ret;
-}
-
-/**
- * gnutls_cipher_get_id:
- * @name: is a MAC algorithm name
- *
- * The names are compared in a case insensitive way.
- *
- * Returns: return a #gnutls_cipher_algorithm_t value corresponding to
- *   the specified cipher, or %GNUTLS_CIPHER_UNKNOWN on error.
- **/
-gnutls_cipher_algorithm_t
-gnutls_cipher_get_id (const char *name)
-{
-  gnutls_cipher_algorithm_t ret = GNUTLS_CIPHER_UNKNOWN;
-
-  GNUTLS_CIPHER_LOOP (
-    if (strcasecmp (p->name, name) == 0) 
-      {
-        ret = p->id;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_cipher_list:
- *
- * Get a list of supported cipher algorithms.  Note that not
- * necessarily all ciphers are supported as TLS cipher suites.  For
- * example, DES is not supported as a cipher suite, but is supported
- * for other purposes (e.g., PKCS#8 or similar).
- *
- * This function is not thread safe.
- *
- * Returns: a zero-terminated list of #gnutls_cipher_algorithm_t
- *   integers indicating the available ciphers.
- *
- **/
-const gnutls_cipher_algorithm_t *
-gnutls_cipher_list (void)
-{
-static gnutls_cipher_algorithm_t supported_ciphers[MAX_ALGOS] = {0};
-
-  if (supported_ciphers[0] == 0)
-    {
-      int i = 0;
-
-      GNUTLS_CIPHER_LOOP (supported_ciphers[i++]=p->id);
-      supported_ciphers[i++]=0;
-    }
-
-  return supported_ciphers;
-}
-
-int
-_gnutls_cipher_is_ok (gnutls_cipher_algorithm_t algorithm)
-{
-  ssize_t ret = -1;
-  GNUTLS_ALG_LOOP (ret = p->id);
-  if (ret >= 0)
-    ret = 0;
-  else
-    ret = 1;
-  return ret;
-}
-
-/* Key EXCHANGE functions */
-mod_auth_st *
-_gnutls_kx_auth_struct (gnutls_kx_algorithm_t algorithm)
-{
-  mod_auth_st *ret = NULL;
-  GNUTLS_KX_ALG_LOOP (ret = p->auth_struct);
-  return ret;
-
-}
-
-
-int
-_gnutls_kx_priority (gnutls_session_t session,
-                     gnutls_kx_algorithm_t algorithm)
-{
-  unsigned int i;
-  for (i = 0; i < session->internals.priorities.kx.algorithms; i++)
-    {
-      if (session->internals.priorities.kx.priority[i] == algorithm)
-        return i;
-    }
-  return -1;
-}
-
-/**
- * gnutls_kx_get_name:
- * @algorithm: is a key exchange algorithm
- *
- * Convert a #gnutls_kx_algorithm_t value to a string.
- *
- * Returns: a pointer to a string that contains the name of the
- *   specified key exchange algorithm, or %NULL.
- **/
-const char *
-gnutls_kx_get_name (gnutls_kx_algorithm_t algorithm)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_KX_ALG_LOOP (ret = p->name);
-
-  return ret;
-}
-
-/**
- * gnutls_kx_get_id:
- * @name: is a KX name
- *
- * Convert a string to a #gnutls_kx_algorithm_t value.  The names are
- * compared in a case insensitive way.
- *
- * Returns: an id of the specified KX algorithm, or %GNUTLS_KX_UNKNOWN
- *   on error.
- **/
-gnutls_kx_algorithm_t
-gnutls_kx_get_id (const char *name)
-{
-  gnutls_cipher_algorithm_t ret = GNUTLS_KX_UNKNOWN;
-
-  GNUTLS_KX_LOOP (
-    if (strcasecmp (p->name, name) == 0) 
-      {
-        ret = p->algorithm;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_kx_list:
- *
- * Get a list of supported key exchange algorithms.
- *
- * This function is not thread safe.
- *
- * Returns: a zero-terminated list of #gnutls_kx_algorithm_t integers
- * indicating the available key exchange algorithms.
- **/
-const gnutls_kx_algorithm_t *
-gnutls_kx_list (void)
-{
-static gnutls_kx_algorithm_t supported_kxs[MAX_ALGOS] = {0};
-
-  if (supported_kxs[0] == 0)
-    {
-      int i = 0;
-
-      GNUTLS_KX_LOOP (supported_kxs[i++]=p->algorithm);
-      supported_kxs[i++]=0;
-    }
-
-  return supported_kxs;
-}
-
-int
-_gnutls_kx_is_ok (gnutls_kx_algorithm_t algorithm)
-{
-  ssize_t ret = -1;
-  GNUTLS_KX_ALG_LOOP (ret = p->algorithm);
-  if (ret >= 0)
-    ret = 0;
-  else
-    ret = 1;
-  return ret;
-}
-
-int
-_gnutls_kx_needs_rsa_params (gnutls_kx_algorithm_t algorithm)
-{
-  ssize_t ret = 0;
-  GNUTLS_KX_ALG_LOOP (ret = p->needs_rsa_params);
-  return ret;
-}
-
-int
-_gnutls_kx_needs_dh_params (gnutls_kx_algorithm_t algorithm)
-{
-  ssize_t ret = 0;
-  GNUTLS_KX_ALG_LOOP (ret = p->needs_dh_params);
-  return ret;
-}
-
-
-/* Version */
-int
-_gnutls_version_priority (gnutls_session_t session, gnutls_protocol_t version)
-{                               /* actually returns the priority */
-  unsigned int i;
-
-  for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
-    {
-      if (session->internals.priorities.protocol.priority[i] == version)
-        return i;
-    }
-  return -1;
-}
-
-gnutls_protocol_t
-_gnutls_version_lowest (gnutls_session_t session)
-{                               /* returns the lowest version supported */
-  unsigned int i, min = 0xff;
-  gnutls_protocol_t cur_prot;
-
-  for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
-    {
-      cur_prot = session->internals.priorities.protocol.priority[i];
-
-      if (cur_prot < min && _gnutls_version_is_supported(session, cur_prot))
-       min = cur_prot;
-    }
-
-  if (min == 0xff)
-    return GNUTLS_VERSION_UNKNOWN;      /* unknown version */
-
-  return min;
-}
-
-gnutls_protocol_t
-_gnutls_version_max (gnutls_session_t session)
-{                               /* returns the maximum version supported */
-  unsigned int i, max = 0x00;
-  gnutls_protocol_t cur_prot;
-
-  for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
-    {
-      cur_prot = session->internals.priorities.protocol.priority[i];
-
-      if (cur_prot > max && _gnutls_version_is_supported(session, cur_prot))
-       max = cur_prot;
-    }
-
-  if (max == 0x00)
-    return GNUTLS_VERSION_UNKNOWN;      /* unknown version */
-
-  return max;
-}
-
-
-/**
- * gnutls_protocol_get_name:
- * @version: is a (gnutls) version number
- *
- * Convert a #gnutls_protocol_t value to a string.
- *
- * Returns: a string that contains the name of the specified TLS
- *   version (e.g., "TLS1.0"), or %NULL.
- **/
-const char *
-gnutls_protocol_get_name (gnutls_protocol_t version)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_VERSION_ALG_LOOP (ret = p->name);
-  return ret;
-}
-
-/**
- * gnutls_protocol_get_id:
- * @name: is a protocol name
- *
- * The names are compared in a case insensitive way.
- *
- * Returns: an id of the specified protocol, or
- * %GNUTLS_VERSION_UNKNOWN on error.
- **/
-gnutls_protocol_t
-gnutls_protocol_get_id (const char *name)
-{
-  gnutls_protocol_t ret = GNUTLS_VERSION_UNKNOWN;
-
-  GNUTLS_VERSION_LOOP (
-    if (strcasecmp (p->name, name) == 0) 
-      {
-        ret = p->id;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_protocol_list:
- *
- * Get a list of supported protocols, e.g. SSL 3.0, TLS 1.0 etc.
- *
- * This function is not threat safe.
- *
- * Returns: a zero-terminated list of #gnutls_protocol_t integers
- * indicating the available protocols.
- *
- **/
-const gnutls_protocol_t *
-gnutls_protocol_list (void)
-{
-static gnutls_protocol_t supported_protocols[MAX_ALGOS] = {0};
-
-  if (supported_protocols[0] == 0)
-    {
-      int i = 0;
-
-      GNUTLS_VERSION_LOOP (supported_protocols[i++]=p->id);
-      supported_protocols[i++]=0;
-    }
-
-  return supported_protocols;
-}
-
-int
-_gnutls_version_get_minor (gnutls_protocol_t version)
-{
-  int ret = -1;
-
-  GNUTLS_VERSION_ALG_LOOP (ret = p->minor);
-  return ret;
-}
-
-gnutls_protocol_t
-_gnutls_version_get (int major, int minor)
-{
-  int ret = -1;
-
-  GNUTLS_VERSION_LOOP (if ((p->major == major) && (p->minor == minor))
-                       ret = p->id);
-  return ret;
-}
-
-int
-_gnutls_version_get_major (gnutls_protocol_t version)
-{
-  int ret = -1;
-
-  GNUTLS_VERSION_ALG_LOOP (ret = p->major);
-  return ret;
-}
-
-/* Version Functions */
-
-int
-_gnutls_version_is_supported (gnutls_session_t session,
-                              const gnutls_protocol_t version)
-{
-  int ret = 0;
-
-  GNUTLS_VERSION_ALG_LOOP (ret = p->supported && p->transport == 
session->internals.transport);
-
-  if (ret == 0)
-    return 0;
-
-  if (_gnutls_version_priority (session, version) < 0)
-    return 0;                   /* disabled by the user */
-  else
-    return 1;
-}
-
-
-/* This function determines if the version specified has a
-   cipher-suite selected PRF hash function instead of the old
-   hardcoded MD5+SHA1. */
-int
-_gnutls_version_has_selectable_prf (gnutls_protocol_t version)
-{
-  switch (version)
-    {
-    case GNUTLS_DTLS1_0:
-    case GNUTLS_TLS1_1:
-    case GNUTLS_TLS1_0:
-    case GNUTLS_SSL3:
-      return 0;
-    default:
-      return 1;
-    }
-}
-
-/* This function determines if the version specified has selectable
-   signature/hash functions for certificate authentification. */
-int
-_gnutls_version_has_selectable_sighash (gnutls_protocol_t version)
-{
-  switch (version)
-    {
-    case GNUTLS_DTLS1_0:
-    case GNUTLS_TLS1_1:
-    case GNUTLS_TLS1_0:
-    case GNUTLS_SSL3:
-      return 0;
-    default:
-      return 1;
-    }
-}
-
-/* This function determines if the version specified has support for
-   TLS extensions. */
-int
-_gnutls_version_has_extensions (gnutls_protocol_t version)
-{
-  switch (version)
-    {
-    case GNUTLS_SSL3:
-      return 0;
-    default:
-      /* Versions after TLS 1.0 are required to handle extensions.
-       * SSL 3.0 also required extensions to be ignored, but
-       * some earlier draft didn't.
-       */
-      return 1;
-    }
-}
-
-/* This function determines if the version specified has explicit IVs
-   (for CBC attack prevention). */
-int
-_gnutls_version_has_explicit_iv (gnutls_protocol_t version)
-{
-  switch (version)
-    {
-    case GNUTLS_TLS1_0:
-    case GNUTLS_SSL3:
-      return 0;
-    default:
-      /* All versions after TLS 1.1 have explicit IV */
-      return 1;
-    }
-}
-
-/* Type to KX mappings */
-gnutls_kx_algorithm_t
-_gnutls_map_kx_get_kx (gnutls_credentials_type_t type, int server)
-{
-  gnutls_kx_algorithm_t ret = -1;
-
-  if (server)
-    {
-      GNUTLS_KX_MAP_ALG_LOOP_SERVER (ret = p->algorithm);
-    }
-  else
-    {
-      GNUTLS_KX_MAP_ALG_LOOP_SERVER (ret = p->algorithm);
-    }
-  return ret;
-}
-
-/* Returns the credentials type required for this
- * Key exchange method.
- */
-gnutls_credentials_type_t
-_gnutls_map_kx_get_cred (gnutls_kx_algorithm_t algorithm, int server)
-{
-  gnutls_credentials_type_t ret = -1;
-  if (server)
-    {
-      GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret =
-                          p->server_type);
-    }
-  else
-    {
-      GNUTLS_KX_MAP_LOOP (if (p->algorithm == algorithm) ret =
-                          p->client_type);
-    }
-
-  return ret;
-}
-
-
-/* Cipher Suite's functions */
-gnutls_cipher_algorithm_t
-_gnutls_cipher_suite_get_cipher_algo (const cipher_suite_st * suite)
-{
-  int ret = 0;
-  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->block_algorithm);
-  return ret;
-}
-
-static int
-_gnutls_cipher_suite_is_version_supported (gnutls_session_t session, const 
cipher_suite_st * suite)
-{
-  int ret = 0;
-  int version = gnutls_protocol_get_version( session);
-  
-  GNUTLS_CIPHER_SUITE_ALG_LOOP (if (version >= p->min_version
-                                 && version <= p->max_version) ret = 1;
-                                 if (IS_DTLS(session) && p->dtls==0) ret = 0;);
-  return ret;
-}
-
-gnutls_kx_algorithm_t
-_gnutls_cipher_suite_get_kx_algo (const cipher_suite_st * suite)
-{
-  int ret = 0;
-
-  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->kx_algorithm);
-  return ret;
-
-}
-
-gnutls_mac_algorithm_t
-_gnutls_cipher_suite_get_mac_algo (const cipher_suite_st * suite)
-{                               /* In bytes */
-  int ret = 0;
-  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->mac_algorithm);
-  return ret;
-
-}
-
-const char *
-_gnutls_cipher_suite_get_name (cipher_suite_st * suite)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_CIPHER_SUITE_ALG_LOOP (ret = p->name + sizeof ("GNUTLS_") - 1);
-
-  return ret;
-}
-
-/**
- * gnutls_cipher_suite_get_name:
- * @kx_algorithm: is a Key exchange algorithm
- * @cipher_algorithm: is a cipher algorithm
- * @mac_algorithm: is a MAC algorithm
- *
- * Note that the full cipher suite name must be prepended by TLS or
- * SSL depending of the protocol in use.
- *
- * Returns: a string that contains the name of a TLS cipher suite,
- * specified by the given algorithms, or %NULL.
- **/
-const char *
-gnutls_cipher_suite_get_name (gnutls_kx_algorithm_t kx_algorithm,
-                              gnutls_cipher_algorithm_t cipher_algorithm,
-                              gnutls_mac_algorithm_t mac_algorithm)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_CIPHER_SUITE_LOOP (if (kx_algorithm == p->kx_algorithm &&
-                                cipher_algorithm == p->block_algorithm &&
-                                mac_algorithm == p->mac_algorithm)
-                            ret = p->name + sizeof ("GNUTLS_") - 1);
-
-  return ret;
-}
-
-/**
- * gnutls_cipher_suite_info:
- * @idx: index of cipher suite to get information about, starts on 0.
- * @cs_id: output buffer with room for 2 bytes, indicating cipher suite value
- * @kx: output variable indicating key exchange algorithm, or %NULL.
- * @cipher: output variable indicating cipher, or %NULL.
- * @mac: output variable indicating MAC algorithm, or %NULL.
- * @min_version: output variable indicating TLS protocol version, or %NULL.
- *
- * Get information about supported cipher suites.  Use the function
- * iteratively to get information about all supported cipher suites.
- * Call with idx=0 to get information about first cipher suite, then
- * idx=1 and so on until the function returns NULL.
- *
- * Returns: the name of @idx cipher suite, and set the information
- * about the cipher suite in the output variables.  If @idx is out of
- * bounds, %NULL is returned.
- **/
-const char *
-gnutls_cipher_suite_info (size_t idx,
-                          char *cs_id,
-                          gnutls_kx_algorithm_t * kx,
-                          gnutls_cipher_algorithm_t * cipher,
-                          gnutls_mac_algorithm_t * mac,
-                          gnutls_protocol_t * min_version)
-{
-  if (idx >= CIPHER_SUITES_COUNT)
-    return NULL;
-
-  if (cs_id)
-    memcpy (cs_id, cs_algorithms[idx].id.suite, 2);
-  if (kx)
-    *kx = cs_algorithms[idx].kx_algorithm;
-  if (cipher)
-    *cipher = cs_algorithms[idx].block_algorithm;
-  if (mac)
-    *mac = cs_algorithms[idx].mac_algorithm;
-  if (min_version)
-    *min_version = cs_algorithms[idx].min_version;
-
-  return cs_algorithms[idx].name + sizeof ("GNU") - 1;
-}
-
-
-static inline int
-_gnutls_cipher_suite_is_ok (cipher_suite_st * suite)
-{
-  size_t ret;
-  const char *name = NULL;
-
-  GNUTLS_CIPHER_SUITE_ALG_LOOP (name = p->name);
-  if (name != NULL)
-    ret = 0;
-  else
-    ret = 1;
-  return ret;
-
-}
-
-#define SWAP(x, y) memcpy(tmp,x,size); \
-                  memcpy(x,y,size); \
-                  memcpy(y,tmp,size);
-
-#define MAX_ELEM_SIZE 4
-static inline int
-_gnutls_partition (gnutls_session_t session, void *_base,
-                   size_t nmemb, size_t size,
-                   int (*compar) (gnutls_session_t,
-                                  const void *, const void *))
-{
-  uint8_t *base = _base;
-  uint8_t tmp[MAX_ELEM_SIZE];
-  uint8_t ptmp[MAX_ELEM_SIZE];
-  unsigned int pivot;
-  unsigned int i, j;
-  unsigned int full;
-
-  i = pivot = 0;
-  j = full = (nmemb - 1) * size;
-
-  memcpy (ptmp, &base[0], size);        /* set pivot item */
-
-  while (i < j)
-    {
-      while ((compar (session, &base[i], ptmp) <= 0) && (i < full))
-        {
-          i += size;
-        }
-      while ((compar (session, &base[j], ptmp) >= 0) && (j > 0))
-        j -= size;
-
-      if (i < j)
-        {
-          SWAP (&base[j], &base[i]);
-        }
-    }
-
-  if (j > pivot)
-    {
-      SWAP (&base[pivot], &base[j]);
-      pivot = j;
-    }
-  else if (i < pivot)
-    {
-      SWAP (&base[pivot], &base[i]);
-      pivot = i;
-    }
-  return pivot / size;
-}
-
-static void
-_gnutls_qsort (gnutls_session_t session, void *_base, size_t nmemb,
-               size_t size, int (*compar) (gnutls_session_t, const void *,
-                                           const void *))
-{
-  unsigned int pivot;
-  char *base = _base;
-  size_t snmemb = nmemb;
-
-#ifdef DEBUG
-  if (size > MAX_ELEM_SIZE)
-    {
-      gnutls_assert ();
-      _gnutls_debug_log ("QSORT BUG\n");
-      exit (1);
-    }
-#endif
-
-  if (snmemb <= 1)
-    return;
-  pivot = _gnutls_partition (session, _base, nmemb, size, compar);
-
-  _gnutls_qsort (session, base, pivot < nmemb ? pivot + 1 : pivot, size,
-                 compar);
-  _gnutls_qsort (session, &base[(pivot + 1) * size], nmemb - pivot - 1,
-                 size, compar);
-}
-
-
-/* a compare function for KX algorithms (using priorities). 
- * For use with qsort 
- */
-static int
-_gnutls_compare_algo (gnutls_session_t session, const void *i_A1,
-                      const void *i_A2)
-{
-  gnutls_kx_algorithm_t kA1 =
-    _gnutls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A1);
-  gnutls_kx_algorithm_t kA2 =
-    _gnutls_cipher_suite_get_kx_algo ((const cipher_suite_st *) i_A2);
-  gnutls_cipher_algorithm_t cA1 =
-    _gnutls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A1);
-  gnutls_cipher_algorithm_t cA2 =
-    _gnutls_cipher_suite_get_cipher_algo ((const cipher_suite_st *) i_A2);
-  gnutls_mac_algorithm_t mA1 =
-    _gnutls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A1);
-  gnutls_mac_algorithm_t mA2 =
-    _gnutls_cipher_suite_get_mac_algo ((const cipher_suite_st *) i_A2);
-
-  int p1 = (_gnutls_kx_priority (session, kA1) + 1) * 64;
-  int p2 = (_gnutls_kx_priority (session, kA2) + 1) * 64;
-  p1 += (_gnutls_cipher_priority (session, cA1) + 1) * 8;
-  p2 += (_gnutls_cipher_priority (session, cA2) + 1) * 8;
-  p1 += _gnutls_mac_priority (session, mA1);
-  p2 += _gnutls_mac_priority (session, mA2);
-
-  if (p1 > p2)
-    {
-      return 1;
-    }
-  else
-    {
-      if (p1 == p2)
-        {
-          return 0;
-        }
-      return -1;
-    }
-}
-
-int
-_gnutls_supported_ciphersuites_sorted (gnutls_session_t session,
-                                       cipher_suite_st ** ciphers)
-{
-
-  int count;
-
-  count = _gnutls_supported_ciphersuites (session, ciphers);
-  if (count <= 0)
-    {
-      gnutls_assert ();
-      return count;
-    }
-
-  _gnutls_qsort (session, *ciphers, count,
-                 sizeof (cipher_suite_st), _gnutls_compare_algo);
-
-  return count;
-}
-
-int
-_gnutls_supported_ciphersuites (gnutls_session_t session,
-                                cipher_suite_st ** _ciphers)
-{
-
-  unsigned int i, ret_count, j;
-  unsigned int count = CIPHER_SUITES_COUNT;
-  cipher_suite_st *tmp_ciphers;
-  cipher_suite_st *ciphers;
-
-  if (count == 0)
-    {
-      return 0;
-    }
-
-  tmp_ciphers = gnutls_malloc (count * sizeof (cipher_suite_st));
-  if (tmp_ciphers == NULL)
-    return GNUTLS_E_MEMORY_ERROR;
-
-  ciphers = gnutls_malloc (count * sizeof (cipher_suite_st));
-  if (ciphers == NULL)
-    {
-      gnutls_free (tmp_ciphers);
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  for (i = 0; i < count; i++)
-    {
-      memcpy (&tmp_ciphers[i], &cs_algorithms[i].id,
-              sizeof (cipher_suite_st));
-    }
-
-  for (i = j = 0; i < count; i++)
-    {
-      /* remove private cipher suites, if requested.
-       */
-      if (tmp_ciphers[i].suite[0] == 0xFF &&
-          session->internals.enable_private == 0)
-        continue;
-
-      /* remove cipher suites which do not support the
-       * protocol version used.
-       */
-      if (_gnutls_cipher_suite_is_version_supported (session, &tmp_ciphers[i])
-          == 0)
-        continue;
-
-      if (_gnutls_kx_priority
-          (session, _gnutls_cipher_suite_get_kx_algo (&tmp_ciphers[i])) < 0)
-        continue;
-
-      if (_gnutls_mac_priority
-          (session, _gnutls_cipher_suite_get_mac_algo (&tmp_ciphers[i])) < 0)
-        continue;
-
-      if (_gnutls_cipher_priority
-          (session,
-           _gnutls_cipher_suite_get_cipher_algo (&tmp_ciphers[i])) < 0)
-        continue;
-
-      memcpy (&ciphers[j], &tmp_ciphers[i], sizeof (cipher_suite_st));
-      j++;
-    }
-
-  ret_count = j;
-
-#if 0                           /* expensive */
-  if (ret_count > 0 && ret_count != count)
-    {
-      ciphers =
-        gnutls_realloc_fast (ciphers, ret_count * sizeof (cipher_suite_st));
-    }
-  else
-    {
-      if (ret_count != count)
-        {
-          gnutls_free (ciphers);
-          ciphers = NULL;
-        }
-    }
-#endif
-
-  gnutls_free (tmp_ciphers);
-
-  /* This function can no longer return 0 cipher suites.
-   * It returns an error code instead.
-   */
-  if (ret_count == 0)
-    {
-      gnutls_assert ();
-      gnutls_free (ciphers);
-      return GNUTLS_E_NO_CIPHER_SUITES;
-    }
-  *_ciphers = ciphers;
-  return ret_count;
-}
-
-/**
- * gnutls_certificate_type_get_name:
- * @type: is a certificate type
- *
- * Convert a #gnutls_certificate_type_t type to a string.
- *
- * Returns: a string that contains the name of the specified
- *   certificate type, or %NULL in case of unknown types.
- **/
-const char *
-gnutls_certificate_type_get_name (gnutls_certificate_type_t type)
-{
-  const char *ret = NULL;
-
-  if (type == GNUTLS_CRT_X509)
-    ret = "X.509";
-  if (type == GNUTLS_CRT_OPENPGP)
-    ret = "OPENPGP";
-
-  return ret;
-}
-
-/**
- * gnutls_certificate_type_get_id:
- * @name: is a certificate type name
- *
- * The names are compared in a case insensitive way.
- *
- * Returns: a #gnutls_certificate_type_t for the specified in a
- *   string certificate type, or %GNUTLS_CRT_UNKNOWN on error.
- **/
-gnutls_certificate_type_t
-gnutls_certificate_type_get_id (const char *name)
-{
-  gnutls_certificate_type_t ret = GNUTLS_CRT_UNKNOWN;
-
-  if (strcasecmp (name, "X.509") == 0 || strcasecmp (name, "X509") == 0)
-    return GNUTLS_CRT_X509;
-  if (strcasecmp (name, "OPENPGP") == 0)
-    return GNUTLS_CRT_OPENPGP;
-
-  return ret;
-}
-
-static const gnutls_certificate_type_t supported_certificate_types[] = {
-  GNUTLS_CRT_X509,
-  GNUTLS_CRT_OPENPGP,
-  0
-};
-
-/**
- * gnutls_certificate_type_list:
- *
- * Get a list of certificate types.  Note that to be able to use
- * OpenPGP certificates, you must link to libgnutls-extra and call
- * gnutls_global_init_extra().
- *
- * Returns: a zero-terminated list of #gnutls_certificate_type_t
- *   integers indicating the available certificate types.
- **/
-const gnutls_certificate_type_t *
-gnutls_certificate_type_list (void)
-{
-  return supported_certificate_types;
-}
-
-/* returns the gnutls_pk_algorithm_t which is compatible with
- * the given gnutls_kx_algorithm_t.
- */
-gnutls_pk_algorithm_t
-_gnutls_map_pk_get_pk (gnutls_kx_algorithm_t kx_algorithm)
-{
-  gnutls_pk_algorithm_t ret = -1;
-
-  GNUTLS_PK_MAP_ALG_LOOP (ret = p->pk_algorithm) return ret;
-}
-
-/* Returns the encipher type for the given key exchange algorithm.
- * That one of CIPHER_ENCRYPT, CIPHER_SIGN, CIPHER_IGN.
- *
- * ex. GNUTLS_KX_RSA requires a certificate able to encrypt... so returns 
CIPHER_ENCRYPT.
- */
-enum encipher_type
-_gnutls_kx_encipher_type (gnutls_kx_algorithm_t kx_algorithm)
-{
-  int ret = CIPHER_IGN;
-  GNUTLS_PK_MAP_ALG_LOOP (ret = p->encipher_type) return ret;
-
-}
-
-/* signature algorithms;
- */
-struct gnutls_sign_entry
-{
-  const char *name;
-  const char *oid;
-  gnutls_sign_algorithm_t id;
-  gnutls_pk_algorithm_t pk;
-  gnutls_mac_algorithm_t mac;
-  /* See RFC 5246 HashAlgorithm and SignatureAlgorithm
-     for values to use in aid struct. */
-  const sign_algorithm_st aid;
-};
-typedef struct gnutls_sign_entry gnutls_sign_entry;
-
-#define TLS_SIGN_AID_UNKNOWN {255, 255}
-static const sign_algorithm_st unknown_tls_aid = TLS_SIGN_AID_UNKNOWN;
-
-static const gnutls_sign_entry sign_algorithms[] = {
-  {"RSA-SHA1", SIG_RSA_SHA1_OID, GNUTLS_SIGN_RSA_SHA1, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA1, {2, 1}},
-  {"RSA-SHA224", SIG_RSA_SHA224_OID, GNUTLS_SIGN_RSA_SHA224, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA224, {3, 1}},
-  {"RSA-SHA256", SIG_RSA_SHA256_OID, GNUTLS_SIGN_RSA_SHA256, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA256, {4, 1}},
-  {"RSA-SHA384", SIG_RSA_SHA384_OID, GNUTLS_SIGN_RSA_SHA384, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA384, {5, 1}},
-  {"RSA-SHA512", SIG_RSA_SHA512_OID, GNUTLS_SIGN_RSA_SHA512, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA512, {6, 1}},
-  {"RSA-RMD160", SIG_RSA_RMD160_OID, GNUTLS_SIGN_RSA_RMD160, GNUTLS_PK_RSA,
-   GNUTLS_MAC_RMD160, TLS_SIGN_AID_UNKNOWN},
-  {"DSA-SHA1", SIG_DSA_SHA1_OID, GNUTLS_SIGN_DSA_SHA1, GNUTLS_PK_DSA,
-   GNUTLS_MAC_SHA1, {2, 2}},
-  {"DSA-SHA224", SIG_DSA_SHA224_OID, GNUTLS_SIGN_DSA_SHA224, GNUTLS_PK_DSA,
-   GNUTLS_MAC_SHA224, {3, 2}},
-  {"DSA-SHA256", SIG_DSA_SHA256_OID, GNUTLS_SIGN_DSA_SHA256, GNUTLS_PK_DSA,
-   GNUTLS_MAC_SHA256, {4, 2}},
-  {"RSA-MD5", SIG_RSA_MD5_OID, GNUTLS_SIGN_RSA_MD5, GNUTLS_PK_RSA,
-   GNUTLS_MAC_MD5, {1, 1}},
-  {"RSA-MD2", SIG_RSA_MD2_OID, GNUTLS_SIGN_RSA_MD2, GNUTLS_PK_RSA,
-   GNUTLS_MAC_MD2, TLS_SIGN_AID_UNKNOWN},
-  {"GOST R 34.10-2001", SIG_GOST_R3410_2001_OID, 0, 0, 0,
-   TLS_SIGN_AID_UNKNOWN},
-  {"GOST R 34.10-94", SIG_GOST_R3410_94_OID, 0, 0, 0, TLS_SIGN_AID_UNKNOWN},
-  {0, 0, 0, 0, 0, TLS_SIGN_AID_UNKNOWN}
-};
-
-#define GNUTLS_SIGN_LOOP(b) \
-  do {                                                                \
-    const gnutls_sign_entry *p;                                               \
-    for(p = sign_algorithms; p->name != NULL; p++) { b ; }            \
-  } while (0)
-
-#define GNUTLS_SIGN_ALG_LOOP(a) \
-  GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
-
-/**
- * gnutls_sign_get_name:
- * @sign: is a sign algorithm
- *
- * Convert a #gnutls_sign_algorithm_t value to a string.
- *
- * Returns: a string that contains the name of the specified sign
- *   algorithm, or %NULL.
- **/
-const char *
-gnutls_sign_get_name (gnutls_sign_algorithm_t sign)
-{
-  const char *ret = NULL;
-
-  /* avoid prefix */
-  GNUTLS_SIGN_ALG_LOOP (ret = p->name);
-
-  return ret;
-}
-
-/**
- * gnutls_sign_list:
- *
- * Get a list of supported public key signature algorithms.
- *
- * Returns: a zero-terminated list of #gnutls_sign_algorithm_t
- *   integers indicating the available ciphers.
- *
- **/
-const gnutls_sign_algorithm_t *
-gnutls_sign_list (void)
-{
-static gnutls_sign_algorithm_t supported_sign[MAX_ALGOS] = {0};
-
-  if (supported_sign[0] == 0)
-    {
-      int i = 0;
-
-      GNUTLS_SIGN_LOOP (supported_sign[i++]=p->id);
-      supported_sign[i++]=0;
-    }
-
-  return supported_sign;
-}
-
-/**
- * gnutls_sign_get_id:
- * @name: is a MAC algorithm name
- *
- * The names are compared in a case insensitive way.
- *
- * Returns: return a #gnutls_sign_algorithm_t value corresponding to
- *   the specified cipher, or %GNUTLS_SIGN_UNKNOWN on error.
- **/
-gnutls_sign_algorithm_t
-gnutls_sign_get_id (const char *name)
-{
-  gnutls_sign_algorithm_t ret = GNUTLS_SIGN_UNKNOWN;
-
-  GNUTLS_SIGN_LOOP (
-    if (strcasecmp (p->name, name) == 0) 
-      {
-        ret = p->id;
-        break;
-      }
-  );
-
-  return ret;
-
-}
-
-gnutls_sign_algorithm_t
-_gnutls_x509_oid2sign_algorithm (const char *oid)
-{
-  gnutls_sign_algorithm_t ret = 0;
-
-  GNUTLS_SIGN_LOOP (if (p->oid && strcmp (oid, p->oid) == 0)
-                    {
-                    ret = p->id; break;}
-  );
-
-  if (ret == 0)
-    {
-      _gnutls_debug_log ("Unknown SIGN OID: '%s'\n", oid);
-      return GNUTLS_SIGN_UNKNOWN;
-    }
-  return ret;
-}
-
-gnutls_sign_algorithm_t
-_gnutls_x509_pk_to_sign (gnutls_pk_algorithm_t pk, gnutls_mac_algorithm_t mac)
-{
-  gnutls_sign_algorithm_t ret = 0;
-
-  GNUTLS_SIGN_LOOP (if (pk == p->pk && mac == p->mac)
-                    {
-                    ret = p->id; break;}
-  );
-
-  if (ret == 0)
-    return GNUTLS_SIGN_UNKNOWN;
-  return ret;
-}
-
-const char *
-_gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk,
-                          gnutls_mac_algorithm_t mac)
-{
-  gnutls_sign_algorithm_t sign;
-  const char *ret = NULL;
-
-  sign = _gnutls_x509_pk_to_sign (pk, mac);
-  if (sign == GNUTLS_SIGN_UNKNOWN)
-    return NULL;
-
-  GNUTLS_SIGN_ALG_LOOP (ret = p->oid);
-  return ret;
-}
-
-gnutls_mac_algorithm_t
-_gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t sign)
-{
-  gnutls_mac_algorithm_t ret = GNUTLS_DIG_UNKNOWN;
-
-  GNUTLS_SIGN_ALG_LOOP (ret = p->mac);
-
-  return ret;
-}
-
-gnutls_pk_algorithm_t
-_gnutls_sign_get_pk_algorithm (gnutls_sign_algorithm_t sign)
-{
-  gnutls_pk_algorithm_t ret = GNUTLS_PK_UNKNOWN;
-
-  GNUTLS_SIGN_ALG_LOOP (ret = p->pk);
-
-  return ret;
-}
-
-gnutls_sign_algorithm_t
-_gnutls_tls_aid_to_sign (const sign_algorithm_st * aid)
-{
-  gnutls_sign_algorithm_t ret = GNUTLS_SIGN_UNKNOWN;
-
-  if (memcmp(aid, &unknown_tls_aid, sizeof(*aid))==0)
-    return ret;
-
-  GNUTLS_SIGN_LOOP (if (p->aid.hash_algorithm == aid->hash_algorithm
-                        && p->aid.sign_algorithm == aid->sign_algorithm)
-                    {
-                      ret = p->id; break;
-                    }
-  );
-
-
-  return ret;
-}
-
-/* Returns NULL if a valid AID is not found
- */
-const sign_algorithm_st*
-_gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign)
-{
-  const sign_algorithm_st * ret = NULL;
-
-  GNUTLS_SIGN_ALG_LOOP (ret = &p->aid);
-
-  if (ret != NULL && memcmp(ret, &unknown_tls_aid, sizeof(*ret))==0)
-    return NULL;
-
-  return ret;
-}
-
-/* ECC curves;
- */
-
-static const gnutls_ecc_curve_entry_st ecc_curves[] = {
-  {
-    .name = "SECP224R1", 
-    .id = GNUTLS_ECC_CURVE_SECP224R1,
-    .size = 28,
-    .prime = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
-    .A = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
-    .B = "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
-    .order = "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
-    .Gx =    "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
-    .Gy =    "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
-  },
-  {
-    .name = "SECP256R1", 
-    .id = GNUTLS_ECC_CURVE_SECP256R1,
-    .size = 32,
-    .prime = 
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
-    .A = "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
-    .B = "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
-    .order = 
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
-    .Gx = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
-    .Gy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
-  },
-  {
-    .name = "SECP384R1",
-    .id = GNUTLS_ECC_CURVE_SECP384R1,
-    .size = 48,
-    .prime = 
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
-    .A = 
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
-    .B = 
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
-    .order = 
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
-    .Gx = 
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
-    .Gy = 
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"
-  },
-  {
-    .name = "SECP521R1",
-    .id = GNUTLS_ECC_CURVE_SECP521R1,
-    .size = 66,
-    .prime = 
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
-    .A = 
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
-    .B = 
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
-    .order = 
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
-    .Gx =    
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
-    .Gy =    
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
-  },
-  {0, 0, 0}
-};
-
-#define GNUTLS_ECC_CURVE_LOOP(b) \
-       { const gnutls_ecc_curve_entry_st *p; \
-                for(p = ecc_curves; p->name != NULL; p++) { b ; } }
-/*-
- * _gnutls_ecc_curve_get_id:
- * @name: is a MAC algorithm name
- *
- * The names are compared in a case insensitive way.
- *
- * Returns: return a #ecc_curve_t value corresponding to
- *   the specified cipher, or %GNUTLS_ECC_CURVE_INVALID on error.
- -*/
-ecc_curve_t
-_gnutls_ecc_curve_get_id (const char *name)
-{
-  ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
-
-  GNUTLS_ECC_CURVE_LOOP (
-  if (strcasecmp (p->name, name) == 0) 
-    {
-      ret = p->id;
-      break;
-    }
-  );
-
-  return ret;
-}
-
-/*-
- * _gnutls_ecc_curve_get_name:
- * @curve: is an ECC curve
- *
- * Convert a #ecc_curve_t value to a string.
- *
- * Returns: a string that contains the name of the specified
- *   curve or %NULL.
- -*/
-const char *
-_gnutls_ecc_curve_get_name (ecc_curve_t curve)
-{
-  const char *ret = NULL;
-
-  GNUTLS_ECC_CURVE_LOOP(
-    if (p->id == curve)
-      {
-        ret = p->name;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/*-
- * _gnutls_ecc_curve_get_params:
- * @curve: is an ECC curve
- *
- * Returns the information on a curve.
- *
- * Returns: a pointer to #gnutls_ecc_curve_entry_st or %NULL.
- -*/
-const gnutls_ecc_curve_entry_st *
-_gnutls_ecc_curve_get_params (ecc_curve_t curve)
-{
-  const gnutls_ecc_curve_entry_st *ret = NULL;
-
-  GNUTLS_ECC_CURVE_LOOP(
-    if (p->id == curve)
-      {
-        ret = p;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/*-
- * _gnutls_ecc_curve_get_size:
- * @curve: is an ECC curve
- *
- * Returns the size in bytes of the curve.
- *
- * Returns: a the size or zero.
- -*/
-int _gnutls_ecc_curve_get_size (ecc_curve_t curve)
-{
-  int ret = 0;
-
-  GNUTLS_ECC_CURVE_LOOP(
-    if (p->id == curve)
-      {
-        ret = p->size;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-
-
-/* pk algorithms;
- */
-struct gnutls_pk_entry
-{
-  const char *name;
-  const char *oid;
-  gnutls_pk_algorithm_t id;
-};
-typedef struct gnutls_pk_entry gnutls_pk_entry;
-
-static const gnutls_pk_entry pk_algorithms[] = {
-  /* having duplicate entries is ok, as long as the one
-   * we want to return OID from is first */
-  {"UNKNOWN", NULL, GNUTLS_PK_UNKNOWN},
-  {"RSA", PK_PKIX1_RSA_OID, GNUTLS_PK_RSA},
-  {"RSA (X.509)", PK_X509_RSA_OID, GNUTLS_PK_RSA},      /* some certificates 
use this OID for RSA */
-  {"RSA (MD5)", SIG_RSA_MD5_OID, GNUTLS_PK_RSA},        /* some other broken 
certificates set RSA with MD5 as an indicator of RSA */
-  {"RSA (SHA1)", SIG_RSA_SHA1_OID, GNUTLS_PK_RSA},      /* some other broken 
certificates set RSA with SHA1 as an indicator of RSA */
-  {"DSA", PK_DSA_OID, GNUTLS_PK_DSA},
-  {"GOST R 34.10-2001", PK_GOST_R3410_2001_OID, GNUTLS_PK_UNKNOWN},
-  {"GOST R 34.10-94", PK_GOST_R3410_94_OID, GNUTLS_PK_UNKNOWN},
-  {"ECDH", "1.2.840.10045.2.1", GNUTLS_PK_ECDH},
-  {0, 0, 0}
-};
-
-#define GNUTLS_PK_LOOP(b) \
-       { const gnutls_pk_entry *p; \
-                for(p = pk_algorithms; p->name != NULL; p++) { b ; } }
-
-
-/**
- * gnutls_pk_algorithm_get_name:
- * @algorithm: is a pk algorithm
- *
- * Convert a #gnutls_pk_algorithm_t value to a string.
- *
- * Returns: a string that contains the name of the specified public
- *   key algorithm, or %NULL.
- **/
-const char *
-gnutls_pk_algorithm_get_name (gnutls_pk_algorithm_t algorithm)
-{
-  const char *ret = NULL;
-
-  GNUTLS_PK_LOOP(
-    if (p->id == algorithm)
-      {
-        ret = p->name;
-        break;
-      }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_pk_list:
- *
- * Get a list of supported public key algorithms.
- *
- * This function is not thread safe.
- *
- * Returns: a zero-terminated list of #gnutls_pk_algorithm_t integers
- *   indicating the available ciphers.
- *
- * Since: 2.6.0
- **/
-const gnutls_pk_algorithm_t *
-gnutls_pk_list (void)
-{
-static gnutls_pk_algorithm_t supported_pks[MAX_ALGOS] = {0};
-
-  if (supported_pks[0] == 0)
-    {
-      int i = 0;
-
-      GNUTLS_PK_LOOP (if (p->id != GNUTLS_PK_UNKNOWN && 
supported_pks[i>0?(i-1):0]!=p->id) supported_pks[i++]=p->id);
-      supported_pks[i++]=0;
-    }
-
-  return supported_pks;
-}
-
-/**
- * gnutls_pk_get_id:
- * @name: is a string containing a public key algorithm name.
- *
- * Convert a string to a #gnutls_pk_algorithm_t value.  The names are
- * compared in a case insensitive way.  For example,
- * gnutls_pk_get_id("RSA") will return %GNUTLS_PK_RSA.
- *
- * Returns: a #gnutls_pk_algorithm_t id of the specified public key
- *   algorithm string, or %GNUTLS_PK_UNKNOWN on failures.
- *
- * Since: 2.6.0
- **/
-gnutls_pk_algorithm_t
-gnutls_pk_get_id (const char *name)
-{
-  gnutls_pk_algorithm_t ret = GNUTLS_PK_UNKNOWN;
-  const gnutls_pk_entry *p;
-
-  for (p = pk_algorithms; p->name != NULL; p++)
-    if (name && strcmp (p->name, name) == 0)
-      {
-        ret = p->id;
-        break;
-      }
-
-  return ret;
-}
-
-/**
- * gnutls_pk_get_name:
- * @algorithm: is a public key algorithm
- *
- * Convert a #gnutls_pk_algorithm_t value to a string.
- *
- * Returns: a pointer to a string that contains the name of the
- *   specified public key algorithm, or %NULL.
- *
- * Since: 2.6.0
- **/
-const char *
-gnutls_pk_get_name (gnutls_pk_algorithm_t algorithm)
-{
-  const char *ret = "Unknown";
-  const gnutls_pk_entry *p;
-
-  for (p = pk_algorithms; p->name != NULL; p++)
-    if (algorithm == p->id)
-      {
-        ret = p->name;
-        break;
-      }
-
-  return ret;
-}
-
-gnutls_pk_algorithm_t
-_gnutls_x509_oid2pk_algorithm (const char *oid)
-{
-  gnutls_pk_algorithm_t ret = GNUTLS_PK_UNKNOWN;
-  const gnutls_pk_entry *p;
-
-  for (p = pk_algorithms; p->name != NULL; p++)
-    if (p->oid && strcmp (p->oid, oid) == 0)
-      {
-        ret = p->id;
-        break;
-      }
-
-  return ret;
-}
-
-const char *
-_gnutls_x509_pk_to_oid (gnutls_pk_algorithm_t algorithm)
-{
-  const char *ret = NULL;
-  const gnutls_pk_entry *p;
-
-  for (p = pk_algorithms; p->name != NULL; p++)
-    if (p->id == algorithm)
-      {
-        ret = p->oid;
-        break;
-      }
-
-  return ret;
-}
-
-/**
- * gnutls_sec_param_to_pk_bits:
- * @algo: is a public key algorithm
- * @param: is a security parameter
- *
- * When generating private and public key pairs a difficult question
- * is which size of "bits" the modulus will be in RSA and the group size
- * in DSA. The easy answer is 1024, which is also wrong. This function
- * will convert a human understandable security parameter to an
- * appropriate size for the specific algorithm.
- *
- * Returns: The number of bits, or zero.
- *
- **/
-unsigned int
-gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t algo,
-                             gnutls_sec_param_t param)
-{
-  unsigned int ret = 0;
-
-  /* handle DSA differently */
-  if (algo == GNUTLS_PK_DSA)
-    {
-      GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
-                             {
-                               ret = p->dsa_bits; break;
-                             }
-      );
-      return ret;
-    }
-
-  GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
-                         {
-                           ret = p->pk_bits; break;
-                         }
-  );
-
-  return ret;
-}
-
-/* Returns the corresponding size for subgroup bits (q),
- * given the group bits (p).
- */
-unsigned int
-_gnutls_pk_bits_to_subgroup_bits (unsigned int pk_bits)
-{
-  unsigned int ret = 0;
-
-  GNUTLS_SEC_PARAM_LOOP (if (p->pk_bits >= pk_bits)
-                         {
-                           ret = p->subgroup_bits; break;
-                         }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_sec_param_get_name:
- * @param: is a security parameter
- *
- * Convert a #gnutls_sec_param_t value to a string.
- *
- * Returns: a pointer to a string that contains the name of the
- *   specified public key algorithm, or %NULL.
- *
- **/
-const char *
-gnutls_sec_param_get_name (gnutls_sec_param_t param)
-{
-  const char *ret = "Unknown";
-
-  GNUTLS_SEC_PARAM_LOOP (if (p->sec_param == param)
-                         {
-                           ret = p->name; break;
-                         }
-  );
-
-  return ret;
-}
-
-/**
- * gnutls_pk_bits_to_sec_param:
- * @algo: is a public key algorithm
- * @bits: is the number of bits
- *
- * This is the inverse of gnutls_sec_param_to_pk_bits(). Given an algorithm
- * and the number of bits, it will return the security parameter. This is
- * a rough indication.
- *
- * Returns: The security parameter.
- *
- **/
-gnutls_sec_param_t
-gnutls_pk_bits_to_sec_param (gnutls_pk_algorithm_t algo, unsigned int bits)
-{
-  gnutls_sec_param_t ret = GNUTLS_SEC_PARAM_WEAK;
-
-  GNUTLS_SEC_PARAM_LOOP (if (p->pk_bits > bits)
-                         {
-                           break;
-                         }
-                         ret = p->sec_param;);
-
-  return ret;
-}
diff --git a/lib/gnutls_asn1_tab.c b/lib/gnutls_asn1_tab.c
index ecac746..74af21d 100644
--- a/lib/gnutls_asn1_tab.c
+++ b/lib/gnutls_asn1_tab.c
@@ -55,9 +55,19 @@ const ASN1_ARRAY_TYPE gnutls_asn1_tab[] = {
   { "g", 1073741827, NULL },
   { "Y", 1073741827, NULL },
   { "priv", 3, NULL },
-  { "DHParameter", 536870917, NULL },
+  { "DHParameter", 1610612741, NULL },
   { "prime", 1073741827, NULL },
   { "base", 1073741827, NULL },
   { "privateValueLength", 16387, NULL },
+  { "ECPoint", 1073741831, NULL },
+  { "ECParameters", 1610612754, NULL },
+  { "namedCurve", 12, NULL },
+  { "ECPrivateKey", 536870917, NULL },
+  { "Version", 1073741827, NULL },
+  { "privateKey", 1073741831, NULL },
+  { "parameters", 1610637314, "ECParameters"},
+  { NULL, 2056, "0"},
+  { "publicKey", 536895494, NULL },
+  { NULL, 2056, "1"},
   { NULL, 0, NULL }
 };
diff --git a/lib/gnutls_auth.c b/lib/gnutls_auth.c
index d2c85ae..8af8d69 100644
--- a/lib/gnutls_auth.c
+++ b/lib/gnutls_auth.c
@@ -27,7 +27,7 @@
 #include "gnutls_errors.h"
 #include "gnutls_auth.h"
 #include "gnutls_auth.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include <auth/cert.h>
 #include <auth/psk.h>
 #include <auth/anon.h>
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 2b8101c..f726c7d 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -33,7 +33,7 @@
 #include <gnutls_datum.h>
 #include <gnutls_mpi.h>
 #include <gnutls_global.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_dh.h>
 #include <gnutls_str.h>
 #include <gnutls_state.h>
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index ccbbbf5..1130ab8 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -31,7 +31,7 @@
 #include "gnutls_errors.h"
 #include "gnutls_compress.h"
 #include "gnutls_cipher.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include "gnutls_hash_int.h"
 #include "gnutls_cipher_int.h"
 #include "debug.h"
diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c
index 0ca4408..89ce0de 100644
--- a/lib/gnutls_cipher_int.c
+++ b/lib/gnutls_cipher_int.c
@@ -28,7 +28,7 @@
 #include <gnutls_datum.h>
 #include <gnutls/crypto.h>
 #include <crypto.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 
 #define SR(x, cleanup) if ( (x)<0 ) { \
   gnutls_assert(); \
diff --git a/lib/gnutls_compress.c b/lib/gnutls_compress.c
index 67db1fa..2c5fa09 100644
--- a/lib/gnutls_compress.c
+++ b/lib/gnutls_compress.c
@@ -31,7 +31,7 @@
 #include "gnutls_compress.h"
 #include "gnutls_errors.h"
 #include "gnutls_constate.h"
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls/gnutls.h>
 
 /* These functions allocate the return value internally
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index a853098..83a7793 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -31,7 +31,7 @@
 #include <gnutls_constate.h>
 #include <gnutls_errors.h>
 #include <gnutls_kx.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_num.h>
 #include <gnutls_datum.h>
 #include <gnutls_state.h>
diff --git a/lib/gnutls_ecc.c b/lib/gnutls_ecc.c
index c156008..60f1c8e 100644
--- a/lib/gnutls_ecc.c
+++ b/lib/gnutls_ecc.c
@@ -28,74 +28,179 @@
 #include <gnutls_int.h>
 #include <gnutls_mpi.h>
 #include <gnutls_ecc.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_errors.h>
 
-int _gnutls_ecc_ansi_x963_export(ecc_curve_t curve, bigint_t x, bigint_t y, 
gnutls_datum_t * out)
+int
+_gnutls_ecc_ansi_x963_export (gnutls_ecc_curve_t curve, bigint_t x, bigint_t y,
+                              gnutls_datum_t * out)
 {
-   int numlen = _gnutls_ecc_curve_get_size(curve);
-   int byte_size, ret;
-   size_t size;
-   
-   if (numlen == 0)
-     return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-   
-   out->size = 1 + 2*numlen;
-   
-   out->data = gnutls_malloc(out->size);
-   if (out->data == NULL)
-     return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
-   memset(out->data, 0, out->size);
-
-   /* store byte 0x04 */
-   out->data[0] = 0x04;
-
-   /* pad and store x */
-   byte_size = (_gnutls_mpi_get_nbits(x)+7)/8;
-   size = out->size - (1+(numlen-byte_size));
-   ret = _gnutls_mpi_print(x, &out->data[1+(numlen-byte_size)], &size);
-   if (ret < 0)
-     return gnutls_assert_val(ret);
-   
-   byte_size = (_gnutls_mpi_get_nbits(y)+7)/8;
-   size = out->size - (1+(numlen+numlen-byte_size));
-   ret = _gnutls_mpi_print(y, &out->data[1+numlen+numlen-byte_size], &size);
-   if (ret < 0)
-     return gnutls_assert_val(ret);
-
-   /* pad and store y */
-   return 0;
+  int numlen = gnutls_ecc_curve_get_size (curve);
+  int byte_size, ret;
+  size_t size;
+
+  if (numlen == 0)
+    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
+
+  out->size = 1 + 2 * numlen;
+
+  out->data = gnutls_malloc (out->size);
+  if (out->data == NULL)
+    return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
+
+  memset (out->data, 0, out->size);
+
+  /* store byte 0x04 */
+  out->data[0] = 0x04;
+
+  /* pad and store x */
+  byte_size = (_gnutls_mpi_get_nbits (x) + 7) / 8;
+  size = out->size - (1 + (numlen - byte_size));
+  ret = _gnutls_mpi_print (x, &out->data[1 + (numlen - byte_size)], &size);
+  if (ret < 0)
+    return gnutls_assert_val (ret);
+
+  byte_size = (_gnutls_mpi_get_nbits (y) + 7) / 8;
+  size = out->size - (1 + (numlen + numlen - byte_size));
+  ret =
+    _gnutls_mpi_print (y, &out->data[1 + numlen + numlen - byte_size], &size);
+  if (ret < 0)
+    return gnutls_assert_val (ret);
+
+  /* pad and store y */
+  return 0;
 }
 
 
-int _gnutls_ecc_ansi_x963_import(ecc_curve_t curve, const opaque *in, unsigned 
long inlen, bigint_t* x, bigint_t* y)
+int
+_gnutls_ecc_ansi_x963_import (const opaque * in,
+                              unsigned long inlen, bigint_t * x, bigint_t * y)
+{
+  int ret;
+
+  /* must be odd */
+  if ((inlen & 1) == 0)
+    {
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  /* check for 4  */
+  if (in[0] != 4)
+    {
+      return gnutls_assert_val (GNUTLS_E_PARSING_ERROR);
+    }
+
+  /* read data */
+  ret = _gnutls_mpi_scan (x, in + 1, (inlen - 1) >> 1);
+  if (ret < 0)
+    return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
+
+  ret = _gnutls_mpi_scan (y, in + 1 + ((inlen - 1) >> 1), (inlen - 1) >> 1);
+  if (ret < 0)
+    {
+      _gnutls_mpi_release (x);
+      return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
+    }
+
+  return 0;
+}
+
+int _gnutls_ecc_curve_fill_params(gnutls_ecc_curve_t curve, 
gnutls_pk_params_st* params)
 {
-   int ret;
-   int numlen = _gnutls_ecc_curve_get_size(curve);
- 
-   /* must be odd */
-   if ((inlen & 1) == 0 || numlen == 0) 
-     {
-       return GNUTLS_E_INVALID_REQUEST;
-     }
-
-   /* check for 4, 6 or 7 */
-   if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
-      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
-   }
-
-   /* read data */
-   ret = _gnutls_mpi_scan(x, in+1, (inlen-1)>>1);
-   if (ret < 0)
-     return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
-   ret = _gnutls_mpi_scan(y, in+1+((inlen-1)>>1), (inlen-1)>>1);
-   if (ret < 0)
-     {
-       _gnutls_mpi_release(x);
-       return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-     }
-
-   return 0;
+const gnutls_ecc_curve_entry_st *st;
+uint8_t val[MAX_ECC_CURVE_SIZE];
+size_t val_size;
+int ret;
+
+  st = _gnutls_ecc_curve_get_params(curve);
+  if (st == NULL)
+    return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+
+  val_size = sizeof(val);
+  ret = _gnutls_hex2bin(st->prime, strlen(st->prime), val, &val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = _gnutls_mpi_scan_nz(&params->params[0], val, val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  params->params_nr++;
+  
+  val_size = sizeof(val);
+  ret = _gnutls_hex2bin(st->order, strlen(st->order), val, &val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = _gnutls_mpi_scan_nz(&params->params[1], val, val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  params->params_nr++;
+  
+  val_size = sizeof(val);
+  ret = _gnutls_hex2bin(st->A, strlen(st->A), val, &val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = _gnutls_mpi_scan_nz(&params->params[2], val, val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  params->params_nr++;
+  
+  val_size = sizeof(val);
+  ret = _gnutls_hex2bin(st->Gx, strlen(st->Gx), val, &val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = _gnutls_mpi_scan_nz(&params->params[3], val, val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  params->params_nr++;
+  
+  val_size = sizeof(val);
+  ret = _gnutls_hex2bin(st->Gy, strlen(st->Gy), val, &val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = _gnutls_mpi_scan_nz(&params->params[4], val, val_size);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  params->params_nr++;
+  
+
+  return 0;
+
+cleanup:
+  gnutls_pk_params_release(params);
+  return ret;
+
 }
diff --git a/lib/gnutls_ecc.h b/lib/gnutls_ecc.h
index 5f91ac5..2ae4541 100644
--- a/lib/gnutls_ecc.h
+++ b/lib/gnutls_ecc.h
@@ -1,2 +1,7 @@
-int _gnutls_ecc_ansi_x963_import(ecc_curve_t curve, const opaque *in, unsigned 
long inlen, bigint_t* x, bigint_t* y);
-int _gnutls_ecc_ansi_x963_export(ecc_curve_t curve, bigint_t x, bigint_t y, 
gnutls_datum_t * out);
+#ifndef GNUTLS_ECC_H
+# define GNUTLS_ECC_H
+
+int _gnutls_ecc_ansi_x963_import(const opaque *in, unsigned long inlen, 
bigint_t* x, bigint_t* y);
+int _gnutls_ecc_ansi_x963_export(gnutls_ecc_curve_t curve, bigint_t x, 
bigint_t y, gnutls_datum_t * out);
+int _gnutls_ecc_curve_fill_params(gnutls_ecc_curve_t curve, 
gnutls_pk_params_st* params);
+#endif
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 9f700b7..39bf11b 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -330,6 +330,8 @@ static const gnutls_error_entry error_algorithms[] = {
                GNUTLS_E_USER_ERROR, 1),
   ERROR_ENTRY (N_("No supported ECC curves were found"),
                GNUTLS_E_ECC_NO_SUPPORTED_CURVES, 1),
+  ERROR_ENTRY (N_("The curve is unsupported"),
+               GNUTLS_E_ECC_UNSUPPORTED_CURVE, 1),
   {NULL, NULL, 0, 0}
 };
 
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index c262f6f..d42d415 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -30,7 +30,7 @@
 #include "gnutls_errors.h"
 #include "gnutls_dh.h"
 #include "debug.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include "gnutls_compress.h"
 #include "gnutls_cipher.h"
 #include "gnutls_buffers.h"
@@ -3348,8 +3348,7 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
       /* If we have not agreed to a common curve with the peer don't bother
        * negotiating ECDH.
        */
-      if (session->security_parameters.entity == GNUTLS_SERVER && (kx == 
GNUTLS_KX_ANON_ECDH ||
-          kx == GNUTLS_KX_ECDHE_RSA))
+      if (session->security_parameters.entity == GNUTLS_SERVER && 
_gnutls_session_is_ecc(session))
         {
           if (_gnutls_session_ecc_curve_get(session) == 
GNUTLS_ECC_CURVE_INVALID)
             delete = 1;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 8dbec24..0f7609d 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -226,15 +226,6 @@ typedef enum extensions_t
 } extensions_t;
 
 typedef enum
-{
-  GNUTLS_ECC_CURVE_INVALID=0,
-  GNUTLS_ECC_CURVE_SECP224R1,
-  GNUTLS_ECC_CURVE_SECP256R1,
-  GNUTLS_ECC_CURVE_SECP384R1,
-  GNUTLS_ECC_CURVE_SECP521R1,
-} ecc_curve_t;
-
-typedef enum
 { CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;
 
 #define RESUME_TRUE 0
@@ -486,7 +477,7 @@ typedef struct
   uint16_t max_record_recv_size;
   /* holds the negotiated certificate type */
   gnutls_certificate_type_t cert_type;
-  ecc_curve_t ecc_curve; /* holds the first supported ECC curve requested by 
client */
+  gnutls_ecc_curve_t ecc_curve; /* holds the first supported ECC curve 
requested by client */
   gnutls_protocol_t version;    /* moved here */
 
   /* FIXME: The following are not saved in the session storage
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index b9e5b3e..de4074f 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -32,7 +32,7 @@
 #include "gnutls_kx.h"
 #include "gnutls_dh.h"
 #include "gnutls_errors.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include "debug.h"
 #include "gnutls_mpi.h"
 #include <gnutls_state.h>
diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c
index 5fc3aa2..358cef4 100644
--- a/lib/gnutls_pk.c
+++ b/lib/gnutls_pk.c
@@ -45,7 +45,7 @@
 int
 _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
                            const gnutls_datum_t * plaintext,
-                           bigint_t * params, unsigned params_len,
+                           gnutls_pk_params_st * params, 
                            unsigned btype)
 {
   unsigned int i, pad;
@@ -53,14 +53,9 @@ _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
   opaque *edata, *ps;
   size_t k, psize;
   size_t mod_bits;
-  gnutls_pk_params_st pk_params;
   gnutls_datum_t to_encrypt, encrypted;
 
-  for (i = 0; i < params_len; i++)
-    pk_params.params[i] = params[i];
-  pk_params.params_nr = params_len;
-
-  mod_bits = _gnutls_mpi_get_nbits (params[0]);
+  mod_bits = _gnutls_mpi_get_nbits (params->params[0]);
   k = mod_bits / 8;
   if (mod_bits % 8 != 0)
     k++;
@@ -91,7 +86,7 @@ _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
     {
     case 2:
       /* using public key */
-      if (params_len < RSA_PUBLIC_PARAMS)
+      if (params->params_nr < RSA_PUBLIC_PARAMS)
         {
           gnutls_assert ();
           gnutls_free (edata);
@@ -120,7 +115,7 @@ _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
     case 1:
       /* using private key */
 
-      if (params_len < RSA_PRIVATE_PARAMS)
+      if (params->params_nr < RSA_PRIVATE_PARAMS)
         {
           gnutls_assert ();
           gnutls_free (edata);
@@ -144,10 +139,10 @@ _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
 
   if (btype == 2)               /* encrypt */
     ret =
-      _gnutls_pk_encrypt (GNUTLS_PK_RSA, &encrypted, &to_encrypt, &pk_params);
+      _gnutls_pk_encrypt (GNUTLS_PK_RSA, &encrypted, &to_encrypt, params);
   else                          /* sign */
     ret =
-      _gnutls_pk_sign (GNUTLS_PK_RSA, &encrypted, &to_encrypt, &pk_params);
+      _gnutls_pk_sign (GNUTLS_PK_RSA, &encrypted, &to_encrypt, params);
 
   gnutls_free (edata);
 
@@ -211,19 +206,14 @@ cleanup:
 int
 _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
                            const gnutls_datum_t * ciphertext,
-                           bigint_t * params, unsigned params_len,
+                           gnutls_pk_params_st* params,
                            unsigned btype)
 {
   unsigned int k, i;
   int ret;
   size_t esize, mod_bits;
-  gnutls_pk_params_st pk_params;
-
-  for (i = 0; i < params_len; i++)
-    pk_params.params[i] = params[i];
-  pk_params.params_nr = params_len;
 
-  mod_bits = _gnutls_mpi_get_nbits (params[0]);
+  mod_bits = _gnutls_mpi_get_nbits (params->params[0]);
   k = mod_bits / 8;
   if (mod_bits % 8 != 0)
     k++;
@@ -242,12 +232,12 @@ _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
   if (btype == 2)
     {
       ret =
-        _gnutls_pk_decrypt (GNUTLS_PK_RSA, plaintext, ciphertext, &pk_params);
+        _gnutls_pk_decrypt (GNUTLS_PK_RSA, plaintext, ciphertext, params);
     }
   else
     {
       ret =
-        _gnutls_pk_encrypt (GNUTLS_PK_RSA, plaintext, ciphertext, &pk_params);
+        _gnutls_pk_encrypt (GNUTLS_PK_RSA, plaintext, ciphertext, params);
     }
 
   if (ret < 0)
@@ -324,8 +314,9 @@ _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
 
 int
 _gnutls_rsa_verify (const gnutls_datum_t * vdata,
-                    const gnutls_datum_t * ciphertext, bigint_t * params,
-                    int params_len, int btype)
+                    const gnutls_datum_t * ciphertext, 
+                    gnutls_pk_params_st * params,
+                    int btype)
 {
 
   gnutls_datum_t plain;
@@ -333,7 +324,7 @@ _gnutls_rsa_verify (const gnutls_datum_t * vdata,
 
   /* decrypt signature */
   if ((ret =
-       _gnutls_pkcs1_rsa_decrypt (&plain, ciphertext, params, params_len,
+       _gnutls_pkcs1_rsa_decrypt (&plain, ciphertext, params,
                                   btype)) < 0)
     {
       gnutls_assert ();
@@ -410,17 +401,11 @@ _gnutls_encode_ber_rs (gnutls_datum_t * sig_value, 
bigint_t r, bigint_t s)
  */
 int
 _gnutls_dsa_sign (gnutls_datum_t * signature,
-                  const gnutls_datum_t * hash, bigint_t * params,
-                  unsigned int params_len)
+                  const gnutls_datum_t * hash, 
+                  gnutls_pk_params_st * params)
 {
   int ret;
-  size_t i;
   size_t k;
-  gnutls_pk_params_st pk_params;
-
-  for (i = 0; i < params_len; i++)
-    pk_params.params[i] = params[i];
-  pk_params.params_nr = params_len;
 
   k = hash->size;
   if (k < 20)
@@ -429,7 +414,7 @@ _gnutls_dsa_sign (gnutls_datum_t * signature,
       return GNUTLS_E_PK_SIGN_FAILED;
     }
 
-  ret = _gnutls_pk_sign (GNUTLS_PK_DSA, signature, hash, &pk_params);
+  ret = _gnutls_pk_sign (GNUTLS_PK_DSA, signature, hash, params);
   /* rs[0], rs[1] now hold r,s */
 
   if (ret < 0)
@@ -493,16 +478,11 @@ _gnutls_decode_ber_rs (const gnutls_datum_t * sig_value, 
bigint_t * r,
  */
 int
 _gnutls_dsa_verify (const gnutls_datum_t * vdata,
-                    const gnutls_datum_t * sig_value, bigint_t * params,
-                    int params_len)
+                    const gnutls_datum_t * sig_value,
+                    gnutls_pk_params_st* params)
 {
 
-  int ret, i;
-  gnutls_pk_params_st pk_params;
-
-  for (i = 0; i < params_len; i++)
-    pk_params.params[i] = params[i];
-  pk_params.params_nr = params_len;
+  int ret;
 
   if (vdata->size < 20)
     { /* SHA1 or better only */
@@ -511,7 +491,7 @@ _gnutls_dsa_verify (const gnutls_datum_t * vdata,
     }
 
   /* decrypt signature */
-  ret = _gnutls_pk_verify (GNUTLS_PK_DSA, vdata, sig_value, &pk_params);
+  ret = _gnutls_pk_verify (GNUTLS_PK_DSA, vdata, sig_value, params);
 
   if (ret < 0)
     {
@@ -523,68 +503,21 @@ _gnutls_dsa_verify (const gnutls_datum_t * vdata,
 }
 
 /* some generic pk functions */
-static int
-_generate_params (int algo, bigint_t * resarr, unsigned int *resarr_len,
-                  int bits)
-{
-  gnutls_pk_params_st params;
-  int ret;
-  unsigned int i;
-
-  ret = _gnutls_pk_generate (algo, bits, &params);
-
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  if (resarr && resarr_len && *resarr_len >= params.params_nr)
-    {
-      *resarr_len = params.params_nr;
-      for (i = 0; i < params.params_nr; i++)
-        resarr[i] = params.params[i];
-    }
-  else
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-  return 0;
-}
-
-
 
-int
-_gnutls_rsa_generate_params (bigint_t * resarr, unsigned int *resarr_len,
-                             int bits)
-{
-  return _generate_params (GNUTLS_PK_RSA, resarr, resarr_len, bits);
-}
-
-int
-_gnutls_dsa_generate_params (bigint_t * resarr, unsigned int *resarr_len,
-                             int bits)
-{
-  return _generate_params (GNUTLS_PK_DSA, resarr, resarr_len, bits);
-}
-
-int
-_gnutls_pk_params_copy (gnutls_pk_params_st * dst, bigint_t * params,
-                        int params_len)
+int _gnutls_pk_params_copy (gnutls_pk_params_st * dst, const 
gnutls_pk_params_st * src)
 {
   int i, j;
   dst->params_nr = 0;
 
-  if (params_len == 0 || params == NULL)
+  if (src == NULL || src->params_nr == 0)
     {
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  for (i = 0; i < params_len; i++)
+  for (i = 0; i < src->params_nr; i++)
     {
-      dst->params[i] = _gnutls_mpi_set (NULL, params[i]);
+      dst->params[i] = _gnutls_mpi_set (NULL, src->params[i]);
       if (dst->params[i] == NULL)
         {
           for (j = 0; j < i; j++)
@@ -611,14 +544,15 @@ gnutls_pk_params_release (gnutls_pk_params_st * p)
     {
       _gnutls_mpi_release (&p->params[i]);
     }
+  p->params_nr = 0;
 }
 
 int
-_gnutls_calc_rsa_exp (bigint_t * params, unsigned int params_size)
+_gnutls_calc_rsa_exp (gnutls_pk_params_st* params)
 {
-  bigint_t tmp = _gnutls_mpi_alloc_like (params[0]);
+  bigint_t tmp = _gnutls_mpi_alloc_like (params->params[0]);
 
-  if (params_size < RSA_PRIVATE_PARAMS - 2)
+  if (params->params_nr < RSA_PRIVATE_PARAMS - 2)
     {
       gnutls_assert ();
       return GNUTLS_E_INTERNAL_ERROR;
@@ -631,15 +565,15 @@ _gnutls_calc_rsa_exp (bigint_t * params, unsigned int 
params_size)
     }
 
   /* [6] = d % p-1, [7] = d % q-1 */
-  _gnutls_mpi_sub_ui (tmp, params[3], 1);
-  params[6] = _gnutls_mpi_mod (params[2] /*d */ , tmp);
+  _gnutls_mpi_sub_ui (tmp, params->params[3], 1);
+  params->params[6] = _gnutls_mpi_mod (params->params[2] /*d */ , tmp);
 
-  _gnutls_mpi_sub_ui (tmp, params[4], 1);
-  params[7] = _gnutls_mpi_mod (params[2] /*d */ , tmp);
+  _gnutls_mpi_sub_ui (tmp, params->params[4], 1);
+  params->params[7] = _gnutls_mpi_mod (params->params[2] /*d */ , tmp);
 
   _gnutls_mpi_release (&tmp);
 
-  if (params[7] == NULL || params[6] == NULL)
+  if (params->params[7] == NULL || params->params[6] == NULL)
     {
       gnutls_assert ();
       return GNUTLS_E_MEMORY_ERROR;
@@ -649,8 +583,8 @@ _gnutls_calc_rsa_exp (bigint_t * params, unsigned int 
params_size)
 }
 
 int
-_gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk, bigint_t * params,
-                               int params_size,
+_gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk, 
+                               gnutls_pk_params_st* params,
                                gnutls_digest_algorithm_t * dig,
                                unsigned int *mand)
 {
@@ -663,6 +597,6 @@ _gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk, 
bigint_t * params,
     }
 
   return _gnutls_x509_verify_algorithm ((gnutls_mac_algorithm_t *) dig,
-                                        NULL, pk, params, params_size);
+                                        NULL, pk, params);
 
 }
diff --git a/lib/gnutls_pk.h b/lib/gnutls_pk.h
index 07a1acd..1cdcf86 100644
--- a/lib/gnutls_pk.h
+++ b/lib/gnutls_pk.h
@@ -45,32 +45,26 @@ _gnutls_pk_fixup (gnutls_pk_algorithm_t algo, 
gnutls_direction_t direction,
   return 0;
 }
 
-int _gnutls_pk_params_copy (gnutls_pk_params_st * dst, bigint_t * params,
-                            int params_len);
-
-int _gnutls_rsa_generate_params (bigint_t * resarr, unsigned int *resarr_len,
-                                 int bits);
-int _gnutls_dsa_generate_params (bigint_t * resarr, unsigned int *resarr_len,
-                                 int bits);
+int _gnutls_pk_params_copy (gnutls_pk_params_st * dst, const 
gnutls_pk_params_st * src);
 
 /* The internal PK interface */
 int _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext,
                                const gnutls_datum_t * plaintext,
-                               bigint_t * params, unsigned params_len,
+                               gnutls_pk_params_st * params,
                                unsigned btype);
 int _gnutls_dsa_sign (gnutls_datum_t * signature,
-                      const gnutls_datum_t * plaintext, bigint_t * params,
-                      unsigned params_len);
+                      const gnutls_datum_t * plaintext, gnutls_pk_params_st*);
 int _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext,
                                const gnutls_datum_t * ciphertext,
-                               bigint_t * params, unsigned params_len,
+                               gnutls_pk_params_st* params,
                                unsigned btype);
 int _gnutls_rsa_verify (const gnutls_datum_t * vdata,
-                        const gnutls_datum_t * ciphertext, bigint_t * params,
-                        int params_len, int btype);
+                        const gnutls_datum_t * ciphertext, 
+                        gnutls_pk_params_st*,
+                        int btype);
 int _gnutls_dsa_verify (const gnutls_datum_t * vdata,
-                        const gnutls_datum_t * sig_value, bigint_t * params,
-                        int params_len);
+                        const gnutls_datum_t * sig_value,
+                        gnutls_pk_params_st* params);
 
 int
 _gnutls_encode_ber_rs (gnutls_datum_t * sig_value, bigint_t r, bigint_t s);
@@ -79,10 +73,10 @@ int
 _gnutls_decode_ber_rs (const gnutls_datum_t * sig_value, bigint_t * r,
                        bigint_t * s);
 
-int _gnutls_calc_rsa_exp (bigint_t * params, unsigned int params_size);
+int _gnutls_calc_rsa_exp (gnutls_pk_params_st*);
 
 int _gnutls_pk_get_hash_algorithm (gnutls_pk_algorithm_t pk,
-                                   bigint_t * params, int params_size,
+                                   gnutls_pk_params_st*,
                                    gnutls_digest_algorithm_t * dig,
                                    unsigned int *mand);
 
diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c
index f54bd51..4b3f733 100644
--- a/lib/gnutls_priority.c
+++ b/lib/gnutls_priority.c
@@ -27,7 +27,7 @@
  */
 
 #include "gnutls_int.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include "gnutls_errors.h"
 #include <gnutls_num.h>
 
diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c
index 2b92efb..b71e04a 100644
--- a/lib/gnutls_privkey.c
+++ b/lib/gnutls_privkey.c
@@ -95,7 +95,7 @@ gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, 
unsigned int *bits)
       return gnutls_pkcs11_privkey_get_pk_algorithm (key->key.pkcs11, bits);
     case GNUTLS_PRIVKEY_X509:
       if (bits)
-        *bits = _gnutls_mpi_get_nbits (key->key.x509->params[0]);
+        *bits = _gnutls_mpi_get_nbits (key->key.x509->params.params[0]);
       return gnutls_x509_privkey_get_pk_algorithm (key->key.x509);
     default:
       gnutls_assert ();
@@ -106,27 +106,20 @@ gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, 
unsigned int *bits)
 
 static int
 privkey_to_pubkey (gnutls_pk_algorithm_t pk,
-                   const bigint_t * params, int params_size,
-                   bigint_t * new_params, int *new_params_size)
+                   const gnutls_pk_params_st* priv,
+                   gnutls_pk_params_st* pub)
 {
-  int ret, i;
+  int ret;
 
   switch (pk)
     {
     case GNUTLS_PK_RSA:
-      if (*new_params_size < RSA_PUBLIC_PARAMS
-          || params_size < RSA_PRIVATE_PARAMS)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_INVALID_REQUEST;
-        }
-
-      new_params[0] = _gnutls_mpi_copy (params[0]);
-      new_params[1] = _gnutls_mpi_copy (params[1]);
+      pub->params[0] = _gnutls_mpi_copy (priv->params[0]);
+      pub->params[1] = _gnutls_mpi_copy (priv->params[1]);
 
-      *new_params_size = RSA_PUBLIC_PARAMS;
+      pub->params_nr = RSA_PUBLIC_PARAMS;
 
-      if (new_params[0] == NULL || new_params[1] == NULL)
+      if (pub->params[0] == NULL || pub->params[1] == NULL)
         {
           gnutls_assert ();
           ret = GNUTLS_E_MEMORY_ERROR;
@@ -135,22 +128,15 @@ privkey_to_pubkey (gnutls_pk_algorithm_t pk,
 
       break;
     case GNUTLS_PK_DSA:
-      if (*new_params_size < DSA_PUBLIC_PARAMS
-          || params_size < DSA_PRIVATE_PARAMS)
-        {
-          gnutls_assert ();
-          return GNUTLS_E_INVALID_REQUEST;
-        }
+      pub->params[0] = _gnutls_mpi_copy (priv->params[0]);
+      pub->params[1] = _gnutls_mpi_copy (priv->params[1]);
+      pub->params[2] = _gnutls_mpi_copy (priv->params[2]);
+      pub->params[3] = _gnutls_mpi_copy (priv->params[3]);
 
-      new_params[0] = _gnutls_mpi_copy (params[0]);
-      new_params[1] = _gnutls_mpi_copy (params[1]);
-      new_params[2] = _gnutls_mpi_copy (params[2]);
-      new_params[3] = _gnutls_mpi_copy (params[3]);
+      pub->params_nr = DSA_PUBLIC_PARAMS;
 
-      *new_params_size = DSA_PUBLIC_PARAMS;
-
-      if (new_params[0] == NULL || new_params[1] == NULL ||
-          new_params[2] == NULL || new_params[3] == NULL)
+      if (pub->params[0] == NULL || pub->params[1] == NULL ||
+          pub->params[2] == NULL || pub->params[3] == NULL)
         {
           gnutls_assert ();
           ret = GNUTLS_E_MEMORY_ERROR;
@@ -165,8 +151,7 @@ privkey_to_pubkey (gnutls_pk_algorithm_t pk,
 
   return 0;
 cleanup:
-  for (i = 0; i < *new_params_size; i++)
-    _gnutls_mpi_release (new_params[i]);
+  gnutls_pk_params_release(pub);
   return ret;
 }
 
@@ -175,7 +160,7 @@ cleanup:
  */
 int
 _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
-                                 bigint_t * params, int *params_size)
+                                 gnutls_pk_params_st * params)
 {
   int ret;
   gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm (key, NULL);
@@ -185,9 +170,8 @@ _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
 #ifdef ENABLE_OPENPGP
     case GNUTLS_PRIVKEY_OPENPGP:
       {
-        bigint_t tmp_params[MAX_PRIV_PARAMS_SIZE];
-        int tmp_params_size = MAX_PRIV_PARAMS_SIZE;
-        uint32_t kid[2], i;
+        gnutls_pk_params_st tmp_params;
+        uint32_t kid[2];
         uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
 
         ret =
@@ -197,13 +181,11 @@ _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
           {
             KEYID_IMPORT (kid, keyid);
             ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid,
-                                                    tmp_params,
-                                                    &tmp_params_size);
+                                                    &tmp_params);
           }
         else
           ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL,
-                                                  tmp_params,
-                                                  &tmp_params_size);
+                                                  &tmp_params);
 
         if (ret < 0)
           {
@@ -212,21 +194,18 @@ _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
           }
 
         ret = privkey_to_pubkey (pk,
-                                 tmp_params, tmp_params_size,
-                                 params, params_size);
-
-        for (i = 0; i < tmp_params_size; i++)
-          _gnutls_mpi_release (&tmp_params[i]);
+                                 &tmp_params,
+                                 params);
 
+        gnutls_pk_params_release(&tmp_params);
       }
 
       break;
 #endif
     case GNUTLS_PRIVKEY_X509:
       ret = privkey_to_pubkey (pk,
-                               key->key.x509->params,
-                               key->key.x509->params_size, params,
-                               params_size);
+                               &key->key.x509->params,
+                               params);
       break;
     default:
       gnutls_assert ();
@@ -574,8 +553,8 @@ _gnutls_privkey_sign_hash (gnutls_privkey_t key,
                                                hash, signature);
     case GNUTLS_PRIVKEY_X509:
       return _gnutls_soft_sign (key->key.x509->pk_algorithm,
-                                key->key.x509->params,
-                                key->key.x509->params_size, hash, signature);
+                                &key->key.x509->params,
+                                hash, signature);
     default:
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
@@ -616,8 +595,8 @@ gnutls_privkey_decrypt_data (gnutls_privkey_t key,
 #endif
     case GNUTLS_PRIVKEY_X509:
       return _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext,
-                                        key->key.x509->params,
-                                        key->key.x509->params_size, 2);
+                                        &key->key.x509->params,
+                                        2);
     case GNUTLS_PRIVKEY_PKCS11:
       return _gnutls_pkcs11_privkey_decrypt_data (key->key.pkcs11,
                                                  flags,
diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c
index 0c60ea5..c75f7f8 100644
--- a/lib/gnutls_pubkey.c
+++ b/lib/gnutls_pubkey.c
@@ -1,6 +1,6 @@
 /*
  * GnuTLS PKCS#11 support
- * Copyright (C) 2010 Free Software Foundation
+ * Copyright (C) 2010,2011 Free Software Foundation
  * 
  * Author: Nikos Mavrogiannopoulos
  *
@@ -58,8 +58,7 @@ struct gnutls_pubkey_st
    *      [2] is g
    *      [3] is public key
    */
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size;              /* holds the size of MPI params */
+  gnutls_pk_params_st params;
 
   uint8_t openpgp_key_id[GNUTLS_OPENPGP_KEYID_SIZE];
   int openpgp_key_id_set;
@@ -67,15 +66,16 @@ struct gnutls_pubkey_st
   unsigned int key_usage;       /* bits from GNUTLS_KEY_* */
 };
 
-static int pubkey_to_bits(gnutls_pk_algorithm_t pk, bigint_t* params, int 
params_size)
+int pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st* params)
 {
   switch(pk) 
     {
       case GNUTLS_PK_RSA:
-        return _gnutls_mpi_get_nbits(params[0]);
+        return _gnutls_mpi_get_nbits(params->params[0]);
       case GNUTLS_PK_DSA:
-        if (params_size < 3) return 0;
-        return _gnutls_mpi_get_nbits(params[3]);
+        return _gnutls_mpi_get_nbits(params->params[3]);
+      case GNUTLS_PK_ECC:
+        return gnutls_ecc_curve_get_size(params->flags)*8;
       default:
         return 0;
     }
@@ -152,13 +152,7 @@ gnutls_pubkey_init (gnutls_pubkey_t * key)
 void
 gnutls_pubkey_deinit (gnutls_pubkey_t key)
 {
-int i;
-
-  for (i = 0; i < key->params_size; i++)
-    {
-      _gnutls_mpi_release (&key->params[i]);
-    }
-
+  gnutls_pk_params_release(&key->params);
   gnutls_free (key);
 }
 
@@ -186,29 +180,11 @@ gnutls_pubkey_import_x509 (gnutls_pubkey_t key, 
gnutls_x509_crt_t crt,
   if (ret < 0)
     key->key_usage = 0;
 
-  key->params_size = sizeof (key->params) / sizeof (key->params[0]);
-  switch (key->pk_algorithm)
+  ret = _gnutls_x509_crt_get_mpis (crt, &key->params);
+  if (ret < 0)
     {
-    case GNUTLS_PK_RSA:
-      ret = _gnutls_x509_crt_get_mpis (crt, key->params, &key->params_size);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-      break;
-    case GNUTLS_PK_DSA:
-      ret = _gnutls_x509_crt_get_mpis (crt, key->params, &key->params_size);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-
-      break;
-    default:
       gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
+      return ret;
     }
 
   return 0;
@@ -237,10 +213,7 @@ gnutls_pubkey_import_privkey (gnutls_pubkey_t key, 
gnutls_privkey_t pkey,
 
   key->key_usage = usage;
 
-  key->params_size = sizeof (key->params) / sizeof (key->params[0]);
-
-  return _gnutls_privkey_get_public_mpis (pkey, key->params,
-                                          &key->params_size);
+  return _gnutls_privkey_get_public_mpis (pkey, &key->params);
 }
 
 /**
@@ -272,7 +245,7 @@ gnutls_pubkey_get_preferred_hash_algorithm (gnutls_pubkey_t 
key,
     }
 
   ret = _gnutls_pk_get_hash_algorithm (key->pk_algorithm,
-                                       key->params, key->params_size,
+                                       &key->params,
                                        hash, mand);
 
   return ret;
@@ -396,34 +369,10 @@ gnutls_pubkey_import_openpgp (gnutls_pubkey_t key,
       key->pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm (crt, 
idx, NULL);
     }
 
-  switch (key->pk_algorithm)
-    {
-    case GNUTLS_PK_RSA:
-      key->params_size = MAX_PUBLIC_PARAMS_SIZE;
-      ret =
-        _gnutls_openpgp_crt_get_mpis (crt, k, key->params,
-                                      &key->params_size);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-      break;
-    case GNUTLS_PK_DSA:
-      key->params_size = MAX_PUBLIC_PARAMS_SIZE;
-      ret =
-        _gnutls_openpgp_crt_get_mpis (crt, k, key->params,
-                                      &key->params_size);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-      break;
-    default:
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
+  ret =
+    _gnutls_openpgp_crt_get_mpis (crt, k, &key->params);
+  if (ret < 0)
+     return gnutls_assert_val(ret);
 
   return 0;
 }
@@ -529,7 +478,7 @@ gnutls_pubkey_export (gnutls_pubkey_t key,
   result =
     _gnutls_x509_encode_and_copy_PKI_params (spk, "",
                                              key->pk_algorithm,
-                                             key->params, key->params_size);
+                                             &key->params);
   if (result < 0)
     {
       gnutls_assert ();
@@ -588,8 +537,8 @@ gnutls_pubkey_get_key_id (gnutls_pubkey_t key, unsigned int 
flags,
     }
 
   ret =
-    _gnutls_get_key_id (key->pk_algorithm, key->params,
-                        key->params_size, output_data, output_data_size);
+    _gnutls_get_key_id (key->pk_algorithm, &key->params,
+                        output_data, output_data_size);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -629,14 +578,14 @@ gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_mpi_dprint (key->params[0], m);
+  ret = _gnutls_mpi_dprint (key->params.params[0], m);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  ret = _gnutls_mpi_dprint (key->params[1], e);
+  ret = _gnutls_mpi_dprint (key->params.params[1], e);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -681,7 +630,7 @@ gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
     }
 
   /* P */
-  ret = _gnutls_mpi_dprint (key->params[0], p);
+  ret = _gnutls_mpi_dprint (key->params.params[0], p);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -689,7 +638,7 @@ gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
     }
 
   /* Q */
-  ret = _gnutls_mpi_dprint (key->params[1], q);
+  ret = _gnutls_mpi_dprint (key->params.params[1], q);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -699,7 +648,7 @@ gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
 
 
   /* G */
-  ret = _gnutls_mpi_dprint (key->params[2], g);
+  ret = _gnutls_mpi_dprint (key->params.params[2], g);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -710,7 +659,7 @@ gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
 
 
   /* Y */
-  ret = _gnutls_mpi_dprint (key->params[3], y);
+  ret = _gnutls_mpi_dprint (key->params.params[3], y);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -724,6 +673,59 @@ gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
 }
 
 /**
+ * gnutls_pubkey_get_pk_ecc_raw:
+ * @key: Holds the public key
+ * @curve: will hold the curve
+ * @x: will hold x
+ * @y: will hold y
+ *
+ * This function will export the ECC public key's parameters found in
+ * the given certificate.  The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ **/
+int
+gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, gnutls_ecc_curve_t *curve,
+                              gnutls_datum_t * x, gnutls_datum_t * y)
+{
+  int ret;
+
+  if (key == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  if (key->pk_algorithm != GNUTLS_PK_ECC)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  *curve = key->params.flags;
+
+  /* X */
+  ret = _gnutls_mpi_dprint (key->params.params[5], x);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      return ret;
+    }
+
+  /* Y */
+  ret = _gnutls_mpi_dprint (key->params.params[6], y);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      _gnutls_free_datum (x);
+      return ret;
+    }
+
+  return 0;
+}
+
+/**
  * gnutls_pubkey_import:
  * @key: The structure to store the parsed public key. 
  * @data: The DER or PEM encoded certificate. 
@@ -795,8 +797,7 @@ gnutls_pubkey_import (gnutls_pubkey_t key,
       goto cleanup;
     }
 
-  key->params_size = sizeof (key->params) / sizeof (key->params[0]);
-  result = _gnutls_get_asn_mpis (spk, "", key->params, &key->params_size);
+  result = _gnutls_get_asn_mpis (spk, "", &key->params);
   if (result < 0)
     {
       gnutls_assert ();
@@ -807,7 +808,7 @@ gnutls_pubkey_import (gnutls_pubkey_t key,
    * fail.
    */
   key->pk_algorithm = _gnutls_x509_get_pk_algorithm (spk, "", NULL);
-  key->bits = pubkey_to_bits(key->pk_algorithm, key->params, key->params_size);
+  key->bits = pubkey_to_bits(key->pk_algorithm, &key->params);
 
   result = 0;
 
@@ -844,8 +845,7 @@ gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, 
gnutls_pubkey_t key)
   result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert,
                                                     
"tbsCertificate.subjectPublicKeyInfo",
                                                     key->pk_algorithm,
-                                                    key->params,
-                                                    key->params_size);
+                                                    &key->params);
 
   if (result < 0)
     {
@@ -884,7 +884,7 @@ gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, 
gnutls_pubkey_t key)
   result = _gnutls_x509_encode_and_copy_PKI_params
     (crq->crq,
      "certificationRequestInfo.subjectPKInfo",
-     key->pk_algorithm, key->params, key->params_size);
+     key->pk_algorithm, &key->params);
 
   if (result < 0)
     {
@@ -992,24 +992,26 @@ gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
+  gnutls_pk_params_init(&key->params);
+
   siz = m->size;
-  if (_gnutls_mpi_scan_nz (&key->params[0], m->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz))
     {
       gnutls_assert ();
       return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
   siz = e->size;
-  if (_gnutls_mpi_scan_nz (&key->params[1], e->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz))
     {
       gnutls_assert ();
-      _gnutls_mpi_release (&key->params[0]);
+      _gnutls_mpi_release (&key->params.params[0]);
       return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
-  key->params_size = RSA_PUBLIC_PARAMS;
+  key->params.params_nr = RSA_PUBLIC_PARAMS;
   key->pk_algorithm = GNUTLS_PK_RSA;
-  key->bits = pubkey_to_bits(GNUTLS_PK_RSA, key->params, key->params_size);
+  key->bits = pubkey_to_bits(GNUTLS_PK_RSA, &key->params);
 
   return 0;
 }
@@ -1038,6 +1040,8 @@ gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key,
 {
   size_t siz = 0;
 
+  gnutls_pk_params_init(&key->params);
+
   if (key == NULL)
     {
       gnutls_assert ();
@@ -1045,42 +1049,42 @@ gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key,
     }
 
   siz = p->size;
-  if (_gnutls_mpi_scan_nz (&key->params[0], p->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[0], p->data, siz))
     {
       gnutls_assert ();
       return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
   siz = q->size;
-  if (_gnutls_mpi_scan_nz (&key->params[1], q->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[1], q->data, siz))
     {
       gnutls_assert ();
-      _gnutls_mpi_release (&key->params[0]);
+      _gnutls_mpi_release (&key->params.params[0]);
       return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
   siz = g->size;
-  if (_gnutls_mpi_scan_nz (&key->params[2], g->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[2], g->data, siz))
     {
       gnutls_assert ();
-      _gnutls_mpi_release (&key->params[1]);
-      _gnutls_mpi_release (&key->params[0]);
+      _gnutls_mpi_release (&key->params.params[1]);
+      _gnutls_mpi_release (&key->params.params[0]);
       return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
   siz = y->size;
-  if (_gnutls_mpi_scan_nz (&key->params[3], y->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[3], y->data, siz))
     {
       gnutls_assert ();
-      _gnutls_mpi_release (&key->params[2]);
-      _gnutls_mpi_release (&key->params[1]);
-      _gnutls_mpi_release (&key->params[0]);
+      _gnutls_mpi_release (&key->params.params[2]);
+      _gnutls_mpi_release (&key->params.params[1]);
+      _gnutls_mpi_release (&key->params.params[0]);
       return GNUTLS_E_MPI_SCAN_FAILED;
     }
 
-  key->params_size = DSA_PUBLIC_PARAMS;
+  key->params.params_nr = DSA_PUBLIC_PARAMS;
   key->pk_algorithm = GNUTLS_PK_DSA;
-  key->bits = pubkey_to_bits(GNUTLS_PK_DSA, key->params, key->params_size);
+  key->bits = pubkey_to_bits(GNUTLS_PK_DSA, &key->params);
 
   return 0;
 
@@ -1116,7 +1120,7 @@ gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey, 
unsigned int flags,
     }
 
   ret = pubkey_verify_sig( data, NULL, signature, pubkey->pk_algorithm, 
-    pubkey->params, pubkey->params_size);
+    &pubkey->params);
   if (ret < 0)
     {
       gnutls_assert();
@@ -1151,12 +1155,11 @@ gnutls_pubkey_verify_hash (gnutls_pubkey_t key, 
unsigned int flags,
     }
 
   if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA)
-    return _gnutls_rsa_verify (hash, signature, key->params,
-                                     key->params_size, 1);
+    return _gnutls_rsa_verify (hash, signature, &key->params, 1);
   else
     {
       return pubkey_verify_sig (NULL, hash, signature, key->pk_algorithm,
-                       key->params, key->params_size);
+                       &key->params);
     }
 }
 
@@ -1186,7 +1189,7 @@ gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key,
   return _gnutls_x509_verify_algorithm ((gnutls_mac_algorithm_t *)
                                         hash, signature,
                                         key->pk_algorithm,
-                                        key->params, key->params_size);
+                                        &key->params);
 
 }
 
@@ -1196,7 +1199,7 @@ int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t 
pubkey, gnutls_protocol_t
 {
   if (pubkey->pk_algorithm == GNUTLS_PK_DSA)
     { /* override */
-      int hash_algo = _gnutls_dsa_q_to_hash (pubkey->params[1]);
+      int hash_algo = _gnutls_dsa_q_to_hash (pubkey->params.params[1]);
 
       /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
       if (!_gnutls_version_has_selectable_sighash (ver))
@@ -1218,27 +1221,18 @@ int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t 
pubkey, gnutls_protocol_t
 /* Returns zero if the public key has more than 512 bits */
 int _gnutls_pubkey_is_over_rsa_512(gnutls_pubkey_t pubkey)
 {
-  if (pubkey->pk_algorithm == GNUTLS_PK_RSA && _gnutls_mpi_get_nbits 
(pubkey->params[0]) > 512)
+  if (pubkey->pk_algorithm == GNUTLS_PK_RSA && _gnutls_mpi_get_nbits 
(pubkey->params.params[0]) > 512)
     return 0;
   else
     return GNUTLS_E_INVALID_REQUEST; /* doesn't matter */
 
 }
 
-/* Returns the public key. The mpis are the internal copy. Should
- * not be deallocated.
+/* Returns the public key. 
  */
 int
 _gnutls_pubkey_get_mpis (gnutls_pubkey_t key,
-                                 bigint_t * params, int *params_size)
+                                 gnutls_pk_params_st * params)
 {
-  int i;
-
-  if (*params_size < key->params_size)
-    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
-
-  for (i=0;i<key->params_size;i++)
-    params[i] = key->params[i];
-
-  return 0;
+  return _gnutls_pk_params_copy(params, &key->params);
 }
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 9b1f8de..1e0be23 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -36,7 +36,7 @@
 #include "gnutls_handshake.h"
 #include "gnutls_hash_int.h"
 #include "gnutls_cipher_int.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include "gnutls_db.h"
 #include "gnutls_auth.h"
 #include "gnutls_num.h"
diff --git a/lib/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c
index e867927..858e5a6 100644
--- a/lib/gnutls_rsa_export.c
+++ b/lib/gnutls_rsa_export.c
@@ -37,7 +37,7 @@
 /* returns e and m, depends on the requested bits.
  * We only support limited key sizes.
  */
-const bigint_t *
+const gnutls_pk_params_st*
 _gnutls_rsa_params_to_mpi (gnutls_rsa_params_t rsa_params)
 {
   if (rsa_params == NULL)
@@ -45,7 +45,7 @@ _gnutls_rsa_params_to_mpi (gnutls_rsa_params_t rsa_params)
       return NULL;
     }
 
-  return rsa_params->params;
+  return &rsa_params->params;
 }
 
 /**
@@ -201,7 +201,7 @@ gnutls_rsa_params_export_pkcs1 (gnutls_rsa_params_t params,
 
 /**
  * gnutls_rsa_params_export_raw:
- * @params: a structure that holds the rsa parameters
+ * @rsa: a structure that holds the rsa parameters
  * @m: will hold the modulus
  * @e: will hold the public exponent
  * @d: will hold the private exponent
@@ -217,7 +217,7 @@ gnutls_rsa_params_export_pkcs1 (gnutls_rsa_params_t params,
  * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
  **/
 int
-gnutls_rsa_params_export_raw (gnutls_rsa_params_t params,
+gnutls_rsa_params_export_raw (gnutls_rsa_params_t rsa,
                               gnutls_datum_t * m, gnutls_datum_t * e,
                               gnutls_datum_t * d, gnutls_datum_t * p,
                               gnutls_datum_t * q, gnutls_datum_t * u,
@@ -225,7 +225,7 @@ gnutls_rsa_params_export_raw (gnutls_rsa_params_t params,
 {
   int ret;
 
-  ret = gnutls_x509_privkey_export_rsa_raw (params, m, e, d, p, q, u);
+  ret = gnutls_x509_privkey_export_rsa_raw (rsa, m, e, d, p, q, u);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -233,7 +233,7 @@ gnutls_rsa_params_export_raw (gnutls_rsa_params_t params,
     }
 
   if (bits)
-    *bits = _gnutls_mpi_get_nbits (params->params[3]);
+    *bits = _gnutls_mpi_get_nbits (rsa->params.params[3]);
 
   return 0;
 }
diff --git a/lib/gnutls_rsa_export.h b/lib/gnutls_rsa_export.h
index d148a91..fa64189 100644
--- a/lib/gnutls_rsa_export.h
+++ b/lib/gnutls_rsa_export.h
@@ -23,5 +23,5 @@
  *
  */
 
-const bigint_t *_gnutls_rsa_params_to_mpi (gnutls_rsa_params_t);
+const gnutls_pk_params_st *_gnutls_rsa_params_to_mpi (gnutls_rsa_params_t);
 int _gnutls_peers_cert_less_512 (gnutls_session_t session);
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index cfc491e..1f2ac23 100644
--- a/lib/gnutls_sig.c
+++ b/lib/gnutls_sig.c
@@ -27,7 +27,7 @@
 #include <gnutls_errors.h>
 #include <x509_b64.h>
 #include <auth/cert.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_datum.h>
 #include <gnutls_mpi.h>
 #include <gnutls_global.h>
@@ -166,8 +166,8 @@ _gnutls_handshake_sign_data (gnutls_session_t session, 
gnutls_pcert_st* cert,
  * given data. The output will be allocated and be put in signature.
  */
 int
-_gnutls_soft_sign (gnutls_pk_algorithm_t algo, bigint_t * params,
-                   int params_size, const gnutls_datum_t * data,
+_gnutls_soft_sign (gnutls_pk_algorithm_t algo, gnutls_pk_params_st * params,
+                   const gnutls_datum_t * data,
                    gnutls_datum_t * signature)
 {
   int ret;
@@ -176,8 +176,7 @@ _gnutls_soft_sign (gnutls_pk_algorithm_t algo, bigint_t * 
params,
     {
     case GNUTLS_PK_RSA:
       /* encrypt */
-      if ((ret = _gnutls_pkcs1_rsa_encrypt (signature, data, params,
-                                            params_size, 1)) < 0)
+      if ((ret = _gnutls_pkcs1_rsa_encrypt (signature, data, params, 1)) < 0)
         {
           gnutls_assert ();
           return ret;
@@ -186,7 +185,7 @@ _gnutls_soft_sign (gnutls_pk_algorithm_t algo, bigint_t * 
params,
       break;
     case GNUTLS_PK_DSA:
       /* sign */
-      if ((ret = _gnutls_dsa_sign (signature, data, params, params_size)) < 0)
+      if ((ret = _gnutls_dsa_sign (signature, data, params)) < 0)
         {
           gnutls_assert ();
           return ret;
@@ -747,7 +746,7 @@ _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
 
 int
 pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
-              bigint_t * params,
+              gnutls_pk_params_st* params,
               const gnutls_datum_t * data, gnutls_datum_t * digest)
 {
   int ret;
@@ -757,7 +756,7 @@ pk_hash_data (gnutls_pk_algorithm_t pk, 
gnutls_digest_algorithm_t hash,
     case GNUTLS_PK_RSA:
       break;
     case GNUTLS_PK_DSA:
-      if (params && hash != _gnutls_dsa_q_to_hash (params[1]))
+      if (params && hash != _gnutls_dsa_q_to_hash (params->params[1]))
         {
           gnutls_assert ();
           return GNUTLS_E_INVALID_REQUEST;
diff --git a/lib/gnutls_sig.h b/lib/gnutls_sig.h
index 44bbce0..3b6957a 100644
--- a/lib/gnutls_sig.h
+++ b/lib/gnutls_sig.h
@@ -52,14 +52,14 @@ int _gnutls_handshake_verify_data (gnutls_session_t session,
                                    gnutls_sign_algorithm_t algo);
 
 int _gnutls_soft_sign (gnutls_pk_algorithm_t algo,
-                       bigint_t * params, int params_size,
+                       gnutls_pk_params_st* params,
                        const gnutls_datum_t * data,
                        gnutls_datum_t * signature);
 
 int pk_prepare_hash (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
                      gnutls_datum_t * output);
 int pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
-                  bigint_t * params, const gnutls_datum_t * data,
+                  gnutls_pk_params_st * params, const gnutls_datum_t * data,
                   gnutls_datum_t * digest);
 
 int
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index c8c83b8..0a4ee1d 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -44,7 +44,7 @@
 #include <auth/cert.h>
 #include <auth/anon.h>
 #include <auth/psk.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_rsa_export.h>
 #include <gnutls_extensions.h>
 #include <system.h>
@@ -67,7 +67,7 @@ _gnutls_session_cert_type_set (gnutls_session_t session,
 
 void
 _gnutls_session_ecc_curve_set (gnutls_session_t session,
-                               ecc_curve_t c)
+                               gnutls_ecc_curve_t c)
 {
   _gnutls_handshake_log("HSK[%p]: Selected ECC curve (%d)\n", session, c);
   session->security_parameters.ecc_curve = c;
@@ -1188,6 +1188,9 @@ _gnutls_session_is_ecc (gnutls_session_t session)
 {
   gnutls_kx_algorithm_t kx;
 
+  /* We get the key exchange algorithm through the ciphersuite because
+   * the negotiated key exchange might not have been set yet.
+   */
   kx =
     _gnutls_cipher_suite_get_kx_algo (&session->
                                       
security_parameters.current_cipher_suite);
diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h
index 7e51463..3266dd9 100644
--- a/lib/gnutls_state.h
+++ b/lib/gnutls_state.h
@@ -31,7 +31,7 @@
 void _gnutls_session_cert_type_set (gnutls_session_t session,
                                     gnutls_certificate_type_t);
 
-inline static ecc_curve_t _gnutls_session_ecc_curve_get(gnutls_session_t 
session)
+inline static gnutls_ecc_curve_t 
_gnutls_session_ecc_curve_get(gnutls_session_t session)
 {
   return session->security_parameters.ecc_curve;
 }
@@ -40,7 +40,7 @@ int _gnutls_session_is_ecc (gnutls_session_t session);
 
 void
 _gnutls_session_ecc_curve_set (gnutls_session_t session,
-                               ecc_curve_t c);
+                               gnutls_ecc_curve_t c);
 
 void
 _gnutls_record_set_default_version (gnutls_session_t session,
diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c
index add3274..73e22b7 100644
--- a/lib/gnutls_v2_compat.c
+++ b/lib/gnutls_v2_compat.c
@@ -30,7 +30,7 @@
 #include "gnutls_errors.h"
 #include "gnutls_dh.h"
 #include "debug.h"
-#include "gnutls_algorithms.h"
+#include "algorithms.h"
 #include "gnutls_compress.h"
 #include "gnutls_cipher.h"
 #include "gnutls_buffers.h"
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index db506b5..ea8da3f 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -31,7 +31,7 @@
 #include "gnutls_num.h"
 #include "gnutls_datum.h"
 #include <gnutls_pk.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_global.h>
 #include <gnutls_record.h>
 #include <gnutls_sig.h>
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 3c6274f..ba097b0 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -40,6 +40,8 @@ int gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t key,
 int gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
                                   gnutls_datum_t * p, gnutls_datum_t * q,
                                   gnutls_datum_t * g, gnutls_datum_t * y);
+int gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, gnutls_ecc_curve_t 
*curve,
+                              gnutls_datum_t * x, gnutls_datum_t * y);
 
 int gnutls_pubkey_export (gnutls_pubkey_t key,
                           gnutls_x509_crt_fmt_t format,
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index 4ff4510..80fbf82 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -279,7 +279,7 @@ extern "C"
  *  [3] is y (public key)
  *  [4] is x (private key only)
  *
- * ECDH:
+ * ECC:
  *  [0] is prime
  *  [1] is order
  *  [2] is A
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 0a08825..58e53cd 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -559,7 +559,7 @@ extern "C"
    * @GNUTLS_PK_RSA: RSA public-key algorithm.
    * @GNUTLS_PK_DSA: DSA public-key algorithm.
    * @GNUTLS_PK_DH: Diffie-Hellman algorithm. Used to generate parameters.
-   * @GNUTLS_PK_ECDH: Elliptic curve Diffie-Hellman algorithm. Used to 
generate parameters.
+   * @GNUTLS_PK_ECC: Elliptic curve algorithm. Used to generate parameters.
    *
    * Enumeration of different public-key algorithms.
    */
@@ -569,7 +569,7 @@ extern "C"
     GNUTLS_PK_RSA = 1,
     GNUTLS_PK_DSA = 2,
     GNUTLS_PK_DH = 3,
-    GNUTLS_PK_ECDH = 4,
+    GNUTLS_PK_ECC = 4,
   } gnutls_pk_algorithm_t;
 
   const char *gnutls_pk_algorithm_get_name (gnutls_pk_algorithm_t algorithm);
@@ -590,6 +590,11 @@ extern "C"
    * @GNUTLS_SIGN_RSA_SHA384: Digital signature algorithm RSA with SHA-384.
    * @GNUTLS_SIGN_RSA_SHA512: Digital signature algorithm RSA with SHA-512.
    * @GNUTLS_SIGN_RSA_SHA224: Digital signature algorithm RSA with SHA-224.
+   * @GNUTLS_SIGN_ECDSA_SHA1: ECDSA with SHA1.
+   * @GNUTLS_SIGN_ECDSA_SHA256: Digital signature algorithm ECDSA with SHA-256.
+   * @GNUTLS_SIGN_ECDSA_SHA384: Digital signature algorithm ECDSA with SHA-384.
+   * @GNUTLS_SIGN_ECDSA_SHA512: Digital signature algorithm ECDSA with SHA-512.
+   * @GNUTLS_SIGN_ECDSA_SHA224: Digital signature algorithm ECDSA with SHA-224.
    *
    * Enumeration of different digital signature algorithms.
    */
@@ -608,10 +613,34 @@ extern "C"
     GNUTLS_SIGN_RSA_SHA512 = 8,
     GNUTLS_SIGN_RSA_SHA224 = 9,
     GNUTLS_SIGN_DSA_SHA224 = 10,
-    GNUTLS_SIGN_DSA_SHA256 = 11
+    GNUTLS_SIGN_DSA_SHA256 = 11,
+    GNUTLS_SIGN_ECDSA_SHA1 = 12,
+    GNUTLS_SIGN_ECDSA_SHA224 = 13,
+    GNUTLS_SIGN_ECDSA_SHA256 = 14,
+    GNUTLS_SIGN_ECDSA_SHA384 = 15,
+    GNUTLS_SIGN_ECDSA_SHA512 = 16,
   } gnutls_sign_algorithm_t;
 
   /**
+   * gnutls_ecc_curve_t:
+   * @GNUTLS_ECC_CURVE_INVALID: Cannot be known
+   * @GNUTLS_ECC_CURVE_SECP224R1: the SECP224R1 curve
+   * @GNUTLS_ECC_CURVE_SECP256R1: the SECP256R1 curve
+   * @GNUTLS_ECC_CURVE_SECP384R1: the SECP384R1 curve
+   * @GNUTLS_ECC_CURVE_SECP521R1: the SECP521R1 curve
+   *
+   * Enumeration of ECC curves.
+   */
+typedef enum
+{
+  GNUTLS_ECC_CURVE_INVALID=0,
+  GNUTLS_ECC_CURVE_SECP224R1,
+  GNUTLS_ECC_CURVE_SECP256R1,
+  GNUTLS_ECC_CURVE_SECP384R1,
+  GNUTLS_ECC_CURVE_SECP521R1,
+} gnutls_ecc_curve_t;
+
+  /**
    * gnutls_sec_param_t:
    * @GNUTLS_SEC_PARAM_UNKNOWN: Cannot be known
    * @GNUTLS_SEC_PARAM_WEAK: 50 or less bits of security
@@ -711,6 +740,10 @@ extern "C"
   unsigned int gnutls_sec_param_to_pk_bits (gnutls_pk_algorithm_t algo,
                                             gnutls_sec_param_t param);
 
+/* Elliptic curves */
+const char * gnutls_ecc_curve_get_name (gnutls_ecc_curve_t curve);
+int gnutls_ecc_curve_get_size (gnutls_ecc_curve_t curve);
+
 /* get information on the current session */
   gnutls_cipher_algorithm_t gnutls_cipher_get (gnutls_session_t session);
   gnutls_kx_algorithm_t gnutls_kx_get (gnutls_session_t session);
@@ -1762,6 +1795,7 @@ extern "C"
 #define GNUTLS_E_TIMEDOUT -319
 #define GNUTLS_E_USER_ERROR -320
 #define GNUTLS_E_ECC_NO_SUPPORTED_CURVES -321
+#define GNUTLS_E_ECC_UNSUPPORTED_CURVE -322
 
 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
 
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index ccae457..a26bb5b 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -713,6 +713,9 @@ GNUTLS_3_0_0 {
        gnutls_certificate_set_retrieve_function2;
        gnutls_x509_trust_list_get_issuer;
        gnutls_global_set_audit_log_function;
+       gnutls_ecc_curve_get_name;
+       gnutls_ecc_curve_get_size;
+       gnutls_pubkey_get_pk_ecc_raw;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
diff --git a/lib/nettle/ecc_test.c b/lib/nettle/ecc_test.c
index dd84b82..30250fa 100644
--- a/lib/nettle/ecc_test.c
+++ b/lib/nettle/ecc_test.c
@@ -17,7 +17,7 @@
 #include "ecc.h"
 #include "gnettle.h"
 #include <gnutls_int.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 
 /**
   @file ecc_test.c
@@ -54,7 +54,7 @@ ecc_test (void)
     {
       const gnutls_ecc_curve_entry_st *st = _gnutls_ecc_curve_get_params (i);
 
-      printf ("Testing %s (%d)\n", _gnutls_ecc_curve_get_name (i), i);
+      printf ("Testing %s (%d)\n", gnutls_ecc_curve_get_name (i), i);
 
       if (mpz_set_str (A, (char *) st->A, 16) != 0)
         {
diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c
index eef8a2c..e6082dd 100644
--- a/lib/nettle/mpi.c
+++ b/lib/nettle/mpi.c
@@ -28,7 +28,7 @@
 
 #include <gnutls_int.h>
 #include <gnutls_errors.h>
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_num.h>
 #include <gnutls_mpi.h>
 #include <gmp.h>
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 22bf8b0..971e6f0 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -92,7 +92,7 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, 
gnutls_datum_t * o
 
   switch (algo)
     {
-    case GNUTLS_PK_ECDH:
+    case GNUTLS_PK_ECC:
       {
         ecc_key ecc_pub, ecc_priv;
         int curve = priv->flags;
@@ -555,7 +555,7 @@ cleanup:
 
 static inline int is_supported_curve(int curve)
 {
-  if (_gnutls_ecc_curve_get_name(curve) != NULL)
+  if (gnutls_ecc_curve_get_name(curve) != NULL)
     return 1;
   else
     return 0;
@@ -681,7 +681,7 @@ rsa_fail:
 
         break;
       }
-    case GNUTLS_PK_ECDH:
+    case GNUTLS_PK_ECC:
       {
         ecc_key key;
         ecc_set_type tls_ecc_set;
@@ -703,7 +703,7 @@ rsa_fail:
           return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
         params->params_nr = 0;
-        for (i = 0; i < ECDH_PRIVATE_PARAMS; i++)
+        for (i = 0; i < ECC_PRIVATE_PARAMS; i++)
           {
             params->params[i] = _gnutls_mpi_alloc_like(&key.prime);
             if (params->params[i] == NULL)
@@ -773,7 +773,7 @@ wrap_nettle_pk_fixup (gnutls_pk_algorithm_t algo,
       _gnutls_mpi_release (&params->params[6]);
       _gnutls_mpi_release (&params->params[7]);
 
-      result = _gnutls_calc_rsa_exp (params->params, RSA_PRIVATE_PARAMS - 2);
+      result = _gnutls_calc_rsa_exp (params);
       if (result < 0)
         {
           gnutls_assert ();
diff --git a/lib/opencdk/read-packet.c b/lib/opencdk/read-packet.c
index 3b40056..aa2a89c 100644
--- a/lib/opencdk/read-packet.c
+++ b/lib/opencdk/read-packet.c
@@ -34,7 +34,7 @@
 #include "main.h"
 #include "packet.h"
 #include "types.h"
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_str.h>
 #include <minmax.h>
 
diff --git a/lib/openpgp/openpgp_int.h b/lib/openpgp/openpgp_int.h
index 7ad6d29..9a17b04 100644
--- a/lib/openpgp/openpgp_int.h
+++ b/lib/openpgp/openpgp_int.h
@@ -49,12 +49,11 @@ unsigned int _gnutls_get_pgp_key_usage (unsigned int 
pgp_usage);
 
 int
 _gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert, uint32_t keyid[2],
-                              bigint_t * params, int *params_size);
+                              gnutls_pk_params_st * params);
 
 int
 _gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey,
-                                  uint32_t keyid[2], bigint_t * params,
-                                  int *params_size);
+                                  uint32_t keyid[2], gnutls_pk_params_st* 
params);
 
 cdk_packet_t _gnutls_openpgp_find_key (cdk_kbnode_t knode, uint32_t keyid[2],
                                        unsigned int priv);
diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c
index 9630448..45b93ff 100644
--- a/lib/openpgp/pgp.c
+++ b/lib/openpgp/pgp.c
@@ -1187,7 +1187,7 @@ _gnutls_read_pgp_mpi (cdk_packet_t pkt, unsigned int 
priv, size_t idx,
 int
 _gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert,
                               uint32_t * keyid /* [2] */ ,
-                              bigint_t * params, int *params_size)
+                              gnutls_pk_params_st * params)
 {
   int result, i;
   int pk_algorithm, local_params;
@@ -1219,32 +1219,23 @@ _gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert,
       return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
     }
 
-  if (*params_size < local_params)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INTERNAL_ERROR;
-    }
-
-  *params_size = local_params;
+  gnutls_pk_params_init(params);
 
   for (i = 0; i < local_params; i++)
     {
-      result = _gnutls_read_pgp_mpi (pkt, 0, i, &params[i]);
+      result = _gnutls_read_pgp_mpi (pkt, 0, i, &params->params[i]);
       if (result < 0)
         {
           gnutls_assert ();
           goto error;
         }
+      params->params_nr++;
     }
 
   return 0;
 
 error:
-  {
-    int j;
-    for (j = 0; j < i; j++)
-      _gnutls_mpi_release (&params[j]);
-  }
+  gnutls_pk_params_release(params);
 
   return result;
 }
@@ -1255,11 +1246,12 @@ static int
 _get_pk_rsa_raw (gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t keyid,
                  gnutls_datum_t * m, gnutls_datum_t * e)
 {
-  int pk_algorithm, ret, i;
+  int pk_algorithm, ret;
   cdk_packet_t pkt;
   uint32_t kid32[2];
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
+  gnutls_pk_params_st params;
+
+  gnutls_pk_params_init(&params);
 
   if (crt == NULL)
     {
@@ -1284,21 +1276,21 @@ _get_pk_rsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_openpgp_crt_get_mpis (crt, kid32, params, &params_size);
+  ret = _gnutls_openpgp_crt_get_mpis (crt, kid32, &params);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  ret = _gnutls_mpi_dprint (params[0], m);
+  ret = _gnutls_mpi_dprint (params.params[0], m);
   if (ret < 0)
     {
       gnutls_assert ();
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[1], e);
+  ret = _gnutls_mpi_dprint (params.params[1], e);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1309,10 +1301,7 @@ _get_pk_rsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 }
 
@@ -1321,11 +1310,12 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
                  gnutls_datum_t * p, gnutls_datum_t * q,
                  gnutls_datum_t * g, gnutls_datum_t * y)
 {
-  int pk_algorithm, ret, i;
+  int pk_algorithm, ret;
   cdk_packet_t pkt;
   uint32_t kid32[2];
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
+  gnutls_pk_params_st params;
+  
+  gnutls_pk_params_init(&params);
 
   if (crt == NULL)
     {
@@ -1350,7 +1340,7 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_openpgp_crt_get_mpis (crt, kid32, params, &params_size);
+  ret = _gnutls_openpgp_crt_get_mpis (crt, kid32, &params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1358,7 +1348,7 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
     }
 
   /* P */
-  ret = _gnutls_mpi_dprint (params[0], p);
+  ret = _gnutls_mpi_dprint (params.params[0], p);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1366,7 +1356,7 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
     }
 
   /* Q */
-  ret = _gnutls_mpi_dprint (params[1], q);
+  ret = _gnutls_mpi_dprint (params.params[1], q);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1376,7 +1366,7 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
 
 
   /* G */
-  ret = _gnutls_mpi_dprint (params[2], g);
+  ret = _gnutls_mpi_dprint (params.params[2], g);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1387,7 +1377,7 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
 
 
   /* Y */
-  ret = _gnutls_mpi_dprint (params[3], y);
+  ret = _gnutls_mpi_dprint (params.params[3], y);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1400,10 +1390,7 @@ _get_pk_dsa_raw (gnutls_openpgp_crt_t crt, 
gnutls_openpgp_keyid_t keyid,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 }
 
diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c
index 2d0a39c..d596637 100644
--- a/lib/openpgp/privkey.c
+++ b/lib/openpgp/privkey.c
@@ -712,14 +712,13 @@ gnutls_openpgp_privkey_get_subkey_fingerprint 
(gnutls_openpgp_privkey_t key,
 int
 _gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey,
                                   uint32_t * keyid /*[2] */ ,
-                                  bigint_t * params, int *params_size)
+                                  gnutls_pk_params_st * params)
 {
   int result, i;
   int pk_algorithm;
-  gnutls_pk_params_st pk_params;
   cdk_packet_t pkt;
 
-  memset (&pk_params, 0, sizeof (pk_params));
+  gnutls_pk_params_init(params);
 
   if (keyid == NULL)
     pkt = cdk_kbnode_find_packet (pkey->knode, CDK_PKT_SECRET_KEY);
@@ -740,19 +739,19 @@ _gnutls_openpgp_privkey_get_mpis 
(gnutls_openpgp_privkey_t pkey,
     case GNUTLS_PK_RSA:
       /* openpgp does not hold all parameters as in PKCS #1
        */
-      pk_params.params_nr = RSA_PRIVATE_PARAMS - 2;
+      params->params_nr = RSA_PRIVATE_PARAMS - 2;
       break;
     case GNUTLS_PK_DSA:
-      pk_params.params_nr = DSA_PRIVATE_PARAMS;
+      params->params_nr = DSA_PRIVATE_PARAMS;
       break;
     default:
       gnutls_assert ();
       return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
     }
 
-  for (i = 0; i < pk_params.params_nr; i++)
+  for (i = 0; i < params->params_nr; i++)
     {
-      result = _gnutls_read_pgp_mpi (pkt, 1, i, &pk_params.params[i]);
+      result = _gnutls_read_pgp_mpi (pkt, 1, i, &params->params[i]);
       if (result < 0)
         {
           gnutls_assert ();
@@ -763,31 +762,17 @@ _gnutls_openpgp_privkey_get_mpis 
(gnutls_openpgp_privkey_t pkey,
   /* fixup will generate exp1 and exp2 that are not
    * available here.
    */
-  result = _gnutls_pk_fixup (pk_algorithm, GNUTLS_IMPORT, &pk_params);
+  result = _gnutls_pk_fixup (pk_algorithm, GNUTLS_IMPORT, params);
   if (result < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
-  if (*params_size < pk_params.params_nr)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INTERNAL_ERROR;
-    }
-
-  *params_size = pk_params.params_nr;
-  for (i = 0; i < pk_params.params_nr; i++)
-    params[i] = pk_params.params[i];
-
   return 0;
 
 error:
-  {
-    int j;
-    for (j = 0; j < i; j++)
-      _gnutls_mpi_release (&pk_params.params[j]);
-  }
+  gnutls_pk_params_release(params);
 
   return result;
 }
@@ -800,11 +785,10 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
                  gnutls_datum_t * d, gnutls_datum_t * p,
                  gnutls_datum_t * q, gnutls_datum_t * u)
 {
-  int pk_algorithm, ret, i;
+  int pk_algorithm, ret;
   cdk_packet_t pkt;
   uint32_t kid32[2];
-  bigint_t params[MAX_PRIV_PARAMS_SIZE];
-  int params_size = MAX_PRIV_PARAMS_SIZE;
+  gnutls_pk_params_st params;
 
   if (pkey == NULL)
     {
@@ -830,21 +814,21 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, params, &params_size);
+  ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, &params);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  ret = _gnutls_mpi_dprint (params[0], m);
+  ret = _gnutls_mpi_dprint (params.params[0], m);
   if (ret < 0)
     {
       gnutls_assert ();
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[1], e);
+  ret = _gnutls_mpi_dprint (params.params[1], e);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -852,7 +836,7 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[2], d);
+  ret = _gnutls_mpi_dprint (params.params[2], d);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -861,7 +845,7 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[3], p);
+  ret = _gnutls_mpi_dprint (params.params[3], p);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -871,7 +855,7 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[4], q);
+  ret = _gnutls_mpi_dprint (params.params[4], q);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -882,7 +866,7 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[5], u);
+  ret = _gnutls_mpi_dprint (params.params[5], u);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -897,10 +881,7 @@ _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 }
 
@@ -909,11 +890,10 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
                  gnutls_datum_t * p, gnutls_datum_t * q,
                  gnutls_datum_t * g, gnutls_datum_t * y, gnutls_datum_t * x)
 {
-  int pk_algorithm, ret, i;
+  int pk_algorithm, ret;
   cdk_packet_t pkt;
   uint32_t kid32[2];
-  bigint_t params[MAX_PRIV_PARAMS_SIZE];
-  int params_size = MAX_PRIV_PARAMS_SIZE;
+  gnutls_pk_params_st params;
 
   if (pkey == NULL)
     {
@@ -939,7 +919,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, params, &params_size);
+  ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, &params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -947,7 +927,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
     }
 
   /* P */
-  ret = _gnutls_mpi_dprint (params[0], p);
+  ret = _gnutls_mpi_dprint (params.params[0], p);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -955,7 +935,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
     }
 
   /* Q */
-  ret = _gnutls_mpi_dprint (params[1], q);
+  ret = _gnutls_mpi_dprint (params.params[1], q);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -965,7 +945,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
 
 
   /* G */
-  ret = _gnutls_mpi_dprint (params[2], g);
+  ret = _gnutls_mpi_dprint (params.params[2], g);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -976,7 +956,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
 
 
   /* Y */
-  ret = _gnutls_mpi_dprint (params[3], y);
+  ret = _gnutls_mpi_dprint (params.params[3], y);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -986,7 +966,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[4], x);
+  ret = _gnutls_mpi_dprint (params.params[4], x);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1000,10 +980,7 @@ _get_sk_dsa_raw (gnutls_openpgp_privkey_t pkey, 
gnutls_openpgp_keyid_t keyid,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 }
 
@@ -1249,9 +1226,8 @@ gnutls_openpgp_privkey_sign_hash 
(gnutls_openpgp_privkey_t key,
                                    const gnutls_datum_t * hash,
                                    gnutls_datum_t * signature)
 {
-  int result, i;
-  bigint_t params[MAX_PRIV_PARAMS_SIZE];
-  int params_size = MAX_PRIV_PARAMS_SIZE;
+  int result;
+  gnutls_pk_params_st params;
   int pk_algorithm;
   uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
 
@@ -1273,13 +1249,12 @@ gnutls_openpgp_privkey_sign_hash 
(gnutls_openpgp_privkey_t key,
       pk_algorithm =
         gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL);
       result =
-        _gnutls_openpgp_privkey_get_mpis (key, kid, params, &params_size);
+        _gnutls_openpgp_privkey_get_mpis (key, kid, &params);
     }
   else
     {
       pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
-      result = _gnutls_openpgp_privkey_get_mpis (key, NULL,
-                                                 params, &params_size);
+      result = _gnutls_openpgp_privkey_get_mpis (key, NULL, &params);
     }
 
   if (result < 0)
@@ -1290,10 +1265,9 @@ gnutls_openpgp_privkey_sign_hash 
(gnutls_openpgp_privkey_t key,
 
 
   result =
-    _gnutls_soft_sign (pk_algorithm, params, params_size, hash, signature);
+    _gnutls_soft_sign (pk_algorithm, &params, hash, signature);
 
-  for (i = 0; i < params_size; i++)
-    _gnutls_mpi_release (&params[i]);
+  gnutls_pk_params_release(&params);
 
   if (result < 0)
     {
@@ -1325,8 +1299,7 @@ _gnutls_openpgp_privkey_decrypt_data 
(gnutls_openpgp_privkey_t key,
                                      gnutls_datum_t * plaintext)
 {
   int result, i;
-  bigint_t params[MAX_PRIV_PARAMS_SIZE];
-  int params_size = MAX_PRIV_PARAMS_SIZE;
+  gnutls_pk_params_st params;
   int pk_algorithm;
   uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
 
@@ -1342,8 +1315,7 @@ _gnutls_openpgp_privkey_decrypt_data 
(gnutls_openpgp_privkey_t key,
       uint32_t kid[2];
 
       KEYID_IMPORT (kid, keyid);
-      result = _gnutls_openpgp_privkey_get_mpis (key, kid,
-                                                 params, &params_size);
+      result = _gnutls_openpgp_privkey_get_mpis (key, kid, &params);
 
       i = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
 
@@ -1353,8 +1325,7 @@ _gnutls_openpgp_privkey_decrypt_data 
(gnutls_openpgp_privkey_t key,
     {
       pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
 
-      result = _gnutls_openpgp_privkey_get_mpis (key, NULL,
-                                                 params, &params_size);
+      result = _gnutls_openpgp_privkey_get_mpis (key, NULL, &params);
 
     }
 
@@ -1371,10 +1342,9 @@ _gnutls_openpgp_privkey_decrypt_data 
(gnutls_openpgp_privkey_t key,
     }
 
   result =
-    _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext, params, params_size, 2);
+    _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext, &params, 2);
 
-  for (i = 0; i < params_size; i++)
-    _gnutls_mpi_release (&params[i]);
+  gnutls_pk_params_release(&params);
 
   if (result < 0)
     {
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index 7b022bf..4af52a1 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -34,8 +34,8 @@ endif
 noinst_LTLIBRARIES = libgnutls_x509.la
 
 libgnutls_x509_la_SOURCES =    \
-       common.c                \
-       common.h                \
+       common.c key_encode.c   \
+       common.h key_decode.c   \
        crl.c                   \
        crl_write.c             \
        crq.c                   \
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 6b76d28..3395834 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1183,8 +1183,7 @@ int
 _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
                                          const char *dst_name,
                                          gnutls_pk_algorithm_t
-                                         pk_algorithm, bigint_t * params,
-                                         int params_size)
+                                         pk_algorithm, gnutls_pk_params_st * 
params)
 {
   const char *pk;
   gnutls_datum_t der = { NULL, 0 };
@@ -1209,87 +1208,45 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
       return _gnutls_asn2err (result);
     }
 
-  if (pk_algorithm == GNUTLS_PK_RSA)
+  result = _gnutls_x509_write_pubkey_params (pk_algorithm, params, &der);
+  if (result < 0)
     {
-      /* disable parameters, which are not used in RSA.
-       */
-      _asnstr_append_name (name, sizeof (name), dst_name,
-                           ".algorithm.parameters");
-
-      result = asn1_write_value (dst, name, ASN1_NULL, ASN1_NULL_SIZE);
-      if (result != ASN1_SUCCESS)
-        {
-          gnutls_assert ();
-          return _gnutls_asn2err (result);
-        }
-
-      result = _gnutls_x509_write_rsa_params (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          return result;
-        }
-
-      /* Write the DER parameters. (in bits)
-       */
-      _asnstr_append_name (name, sizeof (name), dst_name,
-                           ".subjectPublicKey");
-      result = asn1_write_value (dst, name, der.data, der.size * 8);
-
-      _gnutls_free_datum (&der);
-
-      if (result != ASN1_SUCCESS)
-        {
-          gnutls_assert ();
-          return _gnutls_asn2err (result);
-        }
+      gnutls_assert ();
+      return result;
     }
-  else if (pk_algorithm == GNUTLS_PK_DSA)
-    {
 
-      result = _gnutls_x509_write_dsa_params (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          return result;
-        }
+  _asnstr_append_name (name, sizeof (name), dst_name,
+                       ".algorithm.parameters");
 
-      /* Write the DER parameters.
-       */
-      _asnstr_append_name (name, sizeof (name), dst_name,
-                           ".algorithm.parameters");
-      result = asn1_write_value (dst, name, der.data, der.size);
+  result = asn1_write_value (dst, name, der.data, der.size);
 
-      _gnutls_free_datum (&der);
-
-      if (result != ASN1_SUCCESS)
-        {
-          gnutls_assert ();
-          return _gnutls_asn2err (result);
-        }
-
-      result = _gnutls_x509_write_dsa_public_key (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          return result;
-        }
+  _gnutls_free_datum (&der);
 
-      _asnstr_append_name (name, sizeof (name), dst_name,
-                           ".subjectPublicKey");
-      result = asn1_write_value (dst, name, der.data, der.size * 8);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
 
-      _gnutls_free_datum (&der);
+  result = _gnutls_x509_write_pubkey (pk_algorithm, params, &der);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
 
-      if (result != ASN1_SUCCESS)
-        {
-          gnutls_assert ();
-          return _gnutls_asn2err (result);
-        }
+  /* Write the DER parameters. (in bits)
+   */
+  _asnstr_append_name (name, sizeof (name), dst_name,
+                       ".subjectPublicKey");
+  result = asn1_write_value (dst, name, der.data, der.size * 8);
+  _gnutls_free_datum (&der);
 
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
     }
-  else
-    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
 
   return 0;
 }
@@ -1302,13 +1259,13 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const 
char *src_name,
                                unsigned int *bits)
 {
   int result;
-  opaque *str = NULL;
   int algo;
   char oid[64];
   int len;
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
+  gnutls_pk_params_st params;
   char name[128];
 
+  gnutls_pk_params_init(&params);
 
   _asnstr_append_name (name, sizeof (name), src_name, ".algorithm.algorithm");
   len = sizeof (oid);
@@ -1334,77 +1291,13 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const 
char *src_name,
 
   /* Now read the parameters' bits 
    */
-  _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey");
-
-  len = 0;
-  result = asn1_read_value (src, name, NULL, &len);
-  if (result != ASN1_MEM_ERROR)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  if (len % 8 != 0)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_CERTIFICATE_ERROR;
-    }
-
-  len /= 8;
-
-  str = gnutls_malloc (len);
-  if (str == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey");
-
-  result = asn1_read_value (src, name, str, &len);
-
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      gnutls_free (str);
-      return _gnutls_asn2err (result);
-    }
-
-  len /= 8;
-
-  switch (algo)
-    {
-    case GNUTLS_PK_RSA:
-      {
-        if ((result = _gnutls_x509_read_rsa_params (str, len, params)) < 0)
-          {
-            gnutls_assert ();
-            return result;
-          }
-
-        bits[0] = _gnutls_mpi_get_nbits (params[0]);
-
-        _gnutls_mpi_release (&params[0]);
-        _gnutls_mpi_release (&params[1]);
-      }
-      break;
-    case GNUTLS_PK_DSA:
-      {
-
-        if ((result = _gnutls_x509_read_dsa_pubkey (str, len, params)) < 0)
-          {
-            gnutls_assert ();
-            return result;
-          }
-
-        bits[0] = _gnutls_mpi_get_nbits (params[3]);
+  result = _gnutls_get_asn_mpis(src, src_name, &params);
+  if (result < 0)
+    return gnutls_assert_val(result);
 
-        _gnutls_mpi_release (&params[3]);
-      }
-      break;
-    }
+  bits[0] = pubkey_to_bits(algo, &params);
 
-  gnutls_free (str);
+  gnutls_pk_params_release(&params);
   return algo;
 }
 
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 95be482..86e6b8d 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -26,7 +26,8 @@
 #ifndef COMMON_H
 #define COMMON_H
 
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
+#include <abstract_int.h>
 #include <x509/x509_int.h>
 
 #define MAX_STRING_LEN 512
@@ -130,8 +131,7 @@ int _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const 
char *src_name,
 int _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
                                              const char *dst_name,
                                              gnutls_pk_algorithm_t
-                                             pk_algorithm, bigint_t * params,
-                                             int params_size);
+                                             pk_algorithm, gnutls_pk_params_st 
* params);
 int _gnutls_asn1_copy_node (ASN1_TYPE * dst, const char *dst_name,
                             ASN1_TYPE src, const char *src_name);
 
@@ -143,10 +143,10 @@ int _gnutls_x509_get_signature (ASN1_TYPE src, const char 
*src_name,
 gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (bigint_t q);
 
 int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
-                          bigint_t * params, int *params_size);
+                          gnutls_pk_params_st * params);
 
-int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t * params,
-                        int params_size, unsigned char *output_data,
+int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, gnutls_pk_params_st*,
+                        unsigned char *output_data,
                         size_t * output_data_size);
 
 void _asnstr_append_name (char *name, size_t name_size, const char *part1,
@@ -155,8 +155,8 @@ void _asnstr_append_name (char *name, size_t name_size, 
const char *part1,
 int pubkey_verify_sig (const gnutls_datum_t * tbs,
                        const gnutls_datum_t * hash,
                        const gnutls_datum_t * signature,
-                       gnutls_pk_algorithm_t pk, bigint_t * issuer_params,
-                       int issuer_params_size);
+                       gnutls_pk_algorithm_t pk, 
+                       gnutls_pk_params_st * issuer_params);
 
 int
 check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2);
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index 6cd0c96..c61b3c4 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -792,7 +792,7 @@ gnutls_x509_crq_set_key (gnutls_x509_crq_t crq, 
gnutls_x509_privkey_t key)
   result = _gnutls_x509_encode_and_copy_PKI_params
     (crq->crq,
      "certificationRequestInfo.subjectPKInfo",
-     key->pk_algorithm, key->params, key->params_size);
+     key->pk_algorithm, &key->params);
 
   if (result < 0)
     {
@@ -823,9 +823,9 @@ gnutls_x509_crq_get_key_rsa_raw (gnutls_x509_crq_t crq,
                                  gnutls_datum_t * m, gnutls_datum_t * e)
 {
   int ret;
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
-  int i;
+  gnutls_pk_params_st params;
+
+  gnutls_pk_params_init(&params);
 
   if (crq == NULL)
     {
@@ -840,21 +840,21 @@ gnutls_x509_crq_get_key_rsa_raw (gnutls_x509_crq_t crq,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_x509_crq_get_mpis (crq, params, &params_size);
+  ret = _gnutls_x509_crq_get_mpis (crq, &params);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  ret = _gnutls_mpi_dprint (params[0], m);
+  ret = _gnutls_mpi_dprint (params.params[0], m);
   if (ret < 0)
     {
       gnutls_assert ();
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint (params[1], e);
+  ret = _gnutls_mpi_dprint (params.params[1], e);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -865,10 +865,7 @@ gnutls_x509_crq_get_key_rsa_raw (gnutls_x509_crq_t crq,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 }
 
@@ -893,7 +890,9 @@ gnutls_x509_crq_set_key_rsa_raw (gnutls_x509_crq_t crq,
 {
   int result, ret;
   size_t siz = 0;
-  bigint_t temp_params[RSA_PUBLIC_PARAMS];
+  gnutls_pk_params_st temp_params;
+
+  gnutls_pk_params_init(&temp_params);
 
   if (crq == NULL)
     {
@@ -901,10 +900,10 @@ gnutls_x509_crq_set_key_rsa_raw (gnutls_x509_crq_t crq,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  memset (temp_params, 0, sizeof (temp_params));
+  memset (&temp_params, 0, sizeof (temp_params));
 
   siz = m->size;
-  if (_gnutls_mpi_scan_nz (&temp_params[0], m->data, siz))
+  if (_gnutls_mpi_scan_nz (&temp_params.params[0], m->data, siz))
     {
       gnutls_assert ();
       ret = GNUTLS_E_MPI_SCAN_FAILED;
@@ -912,17 +911,19 @@ gnutls_x509_crq_set_key_rsa_raw (gnutls_x509_crq_t crq,
     }
 
   siz = e->size;
-  if (_gnutls_mpi_scan_nz (&temp_params[1], e->data, siz))
+  if (_gnutls_mpi_scan_nz (&temp_params.params[1], e->data, siz))
     {
       gnutls_assert ();
       ret = GNUTLS_E_MPI_SCAN_FAILED;
       goto error;
     }
 
+  temp_params.params_nr = RSA_PUBLIC_PARAMS;
+
   result = _gnutls_x509_encode_and_copy_PKI_params
     (crq->crq,
      "certificationRequestInfo.subjectPKInfo",
-     GNUTLS_PK_RSA, temp_params, RSA_PUBLIC_PARAMS);
+     GNUTLS_PK_RSA, &temp_params);
 
   if (result < 0)
     {
@@ -934,8 +935,7 @@ gnutls_x509_crq_set_key_rsa_raw (gnutls_x509_crq_t crq,
   ret = 0;
 
 error:
-  _gnutls_mpi_release (&temp_params[0]);
-  _gnutls_mpi_release (&temp_params[1]);
+  gnutls_pk_params_release(&temp_params);
   return ret;
 }
 
@@ -2271,39 +2271,26 @@ static int
 rsadsa_crq_get_key_id (gnutls_x509_crq_t crq, int pk,
                        unsigned char *output_data, size_t * output_data_size)
 {
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
-  int i, result = 0;
+  gnutls_pk_params_st params;
+  int result = 0;
   gnutls_datum_t der = { NULL, 0 };
   digest_hd_st hd;
 
-  result = _gnutls_x509_crq_get_mpis (crq, params, &params_size);
+  gnutls_pk_params_init(&params);
+
+  result = _gnutls_x509_crq_get_mpis (crq, &params);
   if (result < 0)
     {
       gnutls_assert ();
       return result;
     }
 
-  if (pk == GNUTLS_PK_RSA)
-    {
-      result = _gnutls_x509_write_rsa_params (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
-    }
-  else if (pk == GNUTLS_PK_DSA)
+  result = _gnutls_x509_write_pubkey( pk, &params, &der);
+  if (result < 0)
     {
-      result = _gnutls_x509_write_dsa_public_key (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
+      gnutls_assert ();
+      goto cleanup;
     }
-  else
-    return GNUTLS_E_INTERNAL_ERROR;
 
   result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (result < 0)
@@ -2325,10 +2312,7 @@ cleanup:
 
   /* release all allocated MPIs
    */
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return result;
 }
 
@@ -2538,8 +2522,10 @@ gnutls_x509_crq_verify (gnutls_x509_crq_t crq,
 {
 gnutls_datum data = { NULL, 0 };
 gnutls_datum signature = { NULL, 0 };
-bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-int ret, params_size = 0, i;
+gnutls_pk_params_st params;
+int ret;
+
+  gnutls_pk_params_init(&params);
 
   ret =
     _gnutls_x509_get_signed_data (crq->crq, "certificationRequestInfo", &data);
@@ -2556,9 +2542,8 @@ int ret, params_size = 0, i;
       goto cleanup;
     }
 
-  params_size = MAX_PUBLIC_PARAMS_SIZE;
   ret =
-    _gnutls_x509_crq_get_mpis(crq, params, &params_size);
+    _gnutls_x509_crq_get_mpis(crq, &params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -2567,7 +2552,7 @@ int ret, params_size = 0, i;
 
   ret = pubkey_verify_sig(&data, NULL, &signature,
                           gnutls_x509_crq_get_pk_algorithm (crq, NULL),
-                          params, params_size);
+                          &params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -2579,11 +2564,7 @@ int ret, params_size = 0, i;
 cleanup:
   _gnutls_free_datum (&data);
   _gnutls_free_datum (&signature);
-
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
 
   return ret;
 }
diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c
new file mode 100644
index 0000000..d0bbce1
--- /dev/null
+++ b/lib/x509/key_decode.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_global.h>
+#include <libtasn1.h>
+#include <gnutls_datum.h>
+#include "common.h"
+#include "x509_int.h"
+#include <gnutls_num.h>
+#include <gnutls_ecc.h>
+
+static int _gnutls_x509_read_rsa_pubkey (opaque * der, int dersize,
+                                  gnutls_pk_params_st* params);
+static int _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize,
+                                  gnutls_pk_params_st * params);
+static int _gnutls_x509_read_ecc_pubkey (opaque * der, int dersize,
+                                  gnutls_pk_params_st * params);
+
+static int
+_gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * 
params);
+
+static int
+_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * 
params);
+
+/*
+ * some x509 certificate parsing functions that relate to MPI parameter
+ * extraction. This reads the BIT STRING subjectPublicKey.
+ * Returns 2 parameters (m,e). It does not set params_nr.
+ */
+int
+_gnutls_x509_read_rsa_pubkey (opaque * der, int dersize, gnutls_pk_params_st * 
params)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = asn1_der_decoding (&spk, der, dersize, NULL);
+
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      return _gnutls_asn2err (result);
+    }
+
+
+  if ((result = _gnutls_x509_read_int (spk, "modulus", &params->params[0])) < 
0)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  if ((result = _gnutls_x509_read_int (spk, "publicExponent",
+                                       &params->params[1])) < 0)
+    {
+      gnutls_assert ();
+      _gnutls_mpi_release (&params->params[0]);
+      asn1_delete_structure (&spk);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  asn1_delete_structure (&spk);
+
+  return 0;
+
+}
+
+/*
+ * some x509 certificate parsing functions that relate to MPI parameter
+ * extraction. This reads the BIT STRING subjectPublicKey.
+ * Returns 2 parameters (m,e). It does not set params_nr.
+ */
+int
+_gnutls_x509_read_ecc_pubkey (opaque * der, int dersize, gnutls_pk_params_st * 
params)
+{
+#if 0  
+  int ret;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+  gnutls_datum_t octet;
+
+  if ((ret = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.ECPoint", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (ret);
+    }
+
+  ret = asn1_der_decoding (&spk, der, dersize, NULL);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      return _gnutls_asn2err (ret);
+    }
+
+
+  if ((ret = _gnutls_x509_read_value (spk, "", &octet, 0)) < 0)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  ret = _gnutls_ecc_ansi_x963_import (octet.data, octet.size, 
&params->params[5],
+                                     &params->params[6]);
+  _gnutls_free_datum(&octet);
+  
+  return ret;
+#endif
+  return _gnutls_ecc_ansi_x963_import (der, dersize, &params->params[5],
+                                     &params->params[6]);
+}
+
+
+/* reads p,q and g 
+ * from the certificate (subjectPublicKey BIT STRING).
+ * params[0-2]. It does NOT set params_nr.
+ */
+static int
+_gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * 
params)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+  
+  if ((result = asn1_create_element
+       (_gnutls_get_pkix (), "PKIX1.Dss-Parms", &spk)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = asn1_der_decoding (&spk, der, dersize, NULL);
+
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      return _gnutls_asn2err (result);
+    }
+
+  /* FIXME: If the parameters are not included in the certificate
+   * then the issuer's parameters should be used. This is not
+   * done yet.
+   */
+
+  /* Read p */
+
+  if ((result = _gnutls_x509_read_int (spk, "p", &params->params[0])) < 0)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  /* Read q */
+
+  if ((result = _gnutls_x509_read_int (spk, "q", &params->params[1])) < 0)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      _gnutls_mpi_release (&params->params[0]);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  /* Read g */
+
+  if ((result = _gnutls_x509_read_int (spk, "g", &params->params[2])) < 0)
+    {
+      gnutls_assert ();
+      asn1_delete_structure (&spk);
+      _gnutls_mpi_release (&params->params[0]);
+      _gnutls_mpi_release (&params->params[1]);
+      return GNUTLS_E_ASN1_GENERIC_ERROR;
+    }
+
+  asn1_delete_structure (&spk);
+
+  return 0;
+
+}
+
+/* reads the curve from the certificate.
+ * params[0-4]. It does NOT set params_nr.
+ */
+static int
+_gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * 
params)
+{
+  int ret;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+  char oid[MAX_OID_SIZE];
+  unsigned int oid_size;
+  
+  if ((ret = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk)) != 
ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (ret);
+    }
+
+  ret = asn1_der_decoding (&spk, der, dersize, NULL);
+
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  /* Read curve */
+  /* read the curve */
+  oid_size = sizeof(oid);
+  ret = asn1_read_value(spk, "namedCurve", oid, &oid_size);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+    
+  params->flags = _gnutls_oid_to_ecc_curve(oid);
+  if (params->flags == GNUTLS_ECC_CURVE_INVALID)
+    {
+      _gnutls_debug_log("Curve %s is not supported\n", oid);
+      gnutls_assert();
+      ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
+      goto cleanup;
+    }
+
+  ret = _gnutls_ecc_curve_fill_params(params->flags, params);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+
+  ret = 0;
+  
+cleanup:
+
+  asn1_delete_structure (&spk);
+
+  return ret;
+
+}
+
+int _gnutls_x509_read_pubkey (gnutls_pk_algorithm_t algo, opaque * der, int 
dersize,
+                                  gnutls_pk_params_st * params)
+{
+int ret;
+
+  switch(algo)
+    {
+      case GNUTLS_PK_RSA:
+        ret = _gnutls_x509_read_rsa_pubkey(der, dersize, params);
+        if (ret >= 0) params->params_nr = RSA_PUBLIC_PARAMS;
+        break;
+      case GNUTLS_PK_DSA:
+        ret = _gnutls_x509_read_dsa_pubkey(der, dersize, params);
+        if (ret >= 0) params->params_nr = DSA_PUBLIC_PARAMS;
+        break;
+      case GNUTLS_PK_ECC:
+        ret = _gnutls_x509_read_ecc_pubkey(der, dersize, params);
+        if (ret >= 0) params->params_nr = ECC_PUBLIC_PARAMS;
+        break;
+      default:
+        ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+        break;
+    }
+  return ret;
+}
+
+int _gnutls_x509_read_pubkey_params (gnutls_pk_algorithm_t algo, opaque * der, 
int dersize,
+                                  gnutls_pk_params_st * params)
+{
+  switch(algo)
+    {
+      case GNUTLS_PK_RSA:
+        return 0;
+      case GNUTLS_PK_DSA:
+        return _gnutls_x509_read_dsa_params(der, dersize, params);
+      case GNUTLS_PK_ECC:
+        return _gnutls_x509_read_ecc_params(der, dersize, params);
+      default:
+        return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+    }
+}
+
+/* reads DSA's Y
+ * from the certificate 
+ * only sets params[3]
+ */
+int
+_gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, gnutls_pk_params_st * 
params)
+{
+  /* do not set a number */
+  params->params_nr = 0;
+  return _gnutls_x509_read_der_int (der, dersize, &params->params[3]);
+}
+
diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c
new file mode 100644
index 0000000..8b44d08
--- /dev/null
+++ b/lib/x509/key_encode.c
@@ -0,0 +1,834 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_global.h>
+#include <libtasn1.h>
+#include <gnutls_datum.h>
+#include "common.h"
+#include "x509_int.h"
+#include <gnutls_num.h>
+#include <gnutls_pk.h>
+#include <gnutls_mpi.h>
+#include <gnutls_ecc.h>
+
+static int _gnutls_x509_write_rsa_pubkey (gnutls_pk_params_st * params, 
+                                   gnutls_datum_t * der);
+static int _gnutls_x509_write_dsa_params (gnutls_pk_params_st * params,
+                                   gnutls_datum_t * der);
+static int _gnutls_x509_write_dsa_pubkey (gnutls_pk_params_st * params,
+                                       gnutls_datum_t * der);
+
+static int _gnutls_x509_write_ecc_params (gnutls_pk_params_st * params,
+                                   gnutls_datum_t * der);
+static int _gnutls_x509_write_ecc_pubkey (gnutls_pk_params_st * params,
+                                       gnutls_datum_t * der);
+
+
+/*
+ * some x509 certificate functions that relate to MPI parameter
+ * setting. This writes the BIT STRING subjectPublicKey.
+ * Needs 2 parameters (m,e).
+ *
+ * Allocates the space used to store the DER data.
+ */
+static int
+_gnutls_x509_write_rsa_pubkey (gnutls_pk_params_st * params,
+                               gnutls_datum_t * der)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+  der->data = NULL;
+  der->size = 0;
+
+  if (params->params_nr < RSA_PUBLIC_PARAMS)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_INVALID_REQUEST;
+      goto cleanup;
+    }
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = _gnutls_x509_write_int (spk, "modulus", params->params[0], 1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_write_int (spk, "publicExponent", params->params[1], 
1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_der_encode (spk, "", der, 0);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
+  asn1_delete_structure (&spk);
+
+  return result;
+}
+
+/*
+ * some x509 certificate functions that relate to MPI parameter
+ * setting. This writes an ECPoint.
+ *
+ * Allocates the space used to store the DER data.
+ */
+static int
+_gnutls_x509_write_ecc_pubkey (gnutls_pk_params_st * params,
+                               gnutls_datum_t * der)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+  gnutls_datum_t out;
+
+  der->data = NULL;
+  der->size = 0;
+
+  if (params->params_nr < ECC_PUBLIC_PARAMS)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_INVALID_REQUEST;
+      goto cleanup;
+    }
+
+  result = _gnutls_ecc_ansi_x963_export(params->flags, params->params[5], 
params->params[6], &out);
+  if (result < 0)
+    return gnutls_assert_val(result);
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.ECPoint", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  result = asn1_write_value (spk, "", out.data, out.size);
+  if (result != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+  
+  result = _gnutls_x509_der_encode (spk, "", der, 0);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
+  _gnutls_free_datum(&out);
+  asn1_delete_structure (&spk);
+
+  return result;
+}
+
+int
+_gnutls_x509_write_pubkey_params (gnutls_pk_algorithm_t algo,
+                                   gnutls_pk_params_st* params,
+                                   gnutls_datum_t * der)
+{
+  switch(algo)
+    {
+      case GNUTLS_PK_DSA:
+        return _gnutls_x509_write_dsa_params(params, der);
+      case GNUTLS_PK_RSA:
+        der->data = gnutls_malloc(ASN1_NULL_SIZE);
+        if (der->data == NULL)
+          return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+        
+        memcpy(der->data, ASN1_NULL, ASN1_NULL_SIZE);
+        der->size = ASN1_NULL_SIZE;
+        return 0;
+      case GNUTLS_PK_ECC:
+        return _gnutls_x509_write_ecc_params(params, der);
+      default:
+        return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+    }
+}
+
+int
+_gnutls_x509_write_pubkey (gnutls_pk_algorithm_t algo,
+                                   gnutls_pk_params_st* params,
+                                   gnutls_datum_t * der)
+{
+  switch(algo)
+    {
+      case GNUTLS_PK_DSA:
+        return _gnutls_x509_write_dsa_pubkey(params, der);
+      case GNUTLS_PK_RSA:
+        return _gnutls_x509_write_rsa_pubkey(params, der);
+      case GNUTLS_PK_ECC:
+        return _gnutls_x509_write_ecc_pubkey(params, der);
+      default:
+        return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
+    }
+}
+
+/*
+ * This function writes the parameters for DSS keys.
+ * Needs 3 parameters (p,q,g).
+ *
+ * Allocates the space used to store the DER data.
+ */
+static int
+_gnutls_x509_write_dsa_params (gnutls_pk_params_st* params,
+                               gnutls_datum_t * der)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+  der->data = NULL;
+  der->size = 0;
+
+  if (params->params_nr < DSA_PUBLIC_PARAMS-1)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_INVALID_REQUEST;
+      goto cleanup;
+    }
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.DSAParameters", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = _gnutls_x509_write_int (spk, "p", params->params[0], 1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_write_int (spk, "q", params->params[1], 1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_write_int (spk, "g", params->params[2], 1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_der_encode (spk, "", der, 0);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
+  asn1_delete_structure (&spk);
+  return result;
+}
+
+/*
+ * This function writes the parameters for ECC keys.
+ * That is the ECParameters struct.
+ *
+ * Allocates the space used to store the DER data.
+ */
+static int
+_gnutls_x509_write_ecc_params (gnutls_pk_params_st* params,
+                               gnutls_datum_t * der)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+  const char* oid;
+
+  der->data = NULL;
+  der->size = 0;
+
+  if (params->params_nr < ECC_PUBLIC_PARAMS)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_INVALID_REQUEST;
+      goto cleanup;
+    }
+
+  oid = _gnutls_ecc_curve_get_oid(params->flags);
+  if (oid == NULL)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  if ((result = asn1_write_value (spk, "parameters", "namedCurve", 1)) != 
ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+  
+  if ((result = asn1_write_value (spk, "parameters.namedCurve", oid, 1)) != 
ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_der_encode (spk, "", der, 0);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
+  asn1_delete_structure (&spk);
+  return result;
+}
+
+/*
+ * This function writes the public parameters for DSS keys.
+ * Needs 1 parameter (y).
+ *
+ * Allocates the space used to store the DER data.
+ */
+static int
+_gnutls_x509_write_dsa_pubkey (gnutls_pk_params_st * params,
+                                   gnutls_datum_t * der)
+{
+  int result;
+  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+  der->data = NULL;
+  der->size = 0;
+
+  if (params->params_nr < DSA_PUBLIC_PARAMS)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_INVALID_REQUEST;
+      goto cleanup;
+    }
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", &spk))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return _gnutls_asn2err (result);
+    }
+
+  result = _gnutls_x509_write_int (spk, "", params->params[3], 1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_x509_der_encode (spk, "", der, 0);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
+  asn1_delete_structure (&spk);
+  return result;
+}
+
+/* Encodes the RSA parameters into an ASN.1 RSA private key structure.
+ */
+static int
+_gnutls_asn1_encode_rsa (ASN1_TYPE * c2, gnutls_pk_params_st * params)
+{
+  int result;
+  opaque null = '\0';
+  gnutls_pk_params_st pk_params;
+  gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
+
+  gnutls_pk_params_init(&pk_params);
+
+  memset (&m, 0, sizeof (m));
+  memset (&p, 0, sizeof (p));
+  memset (&q, 0, sizeof (q));
+  memset (&p, 0, sizeof (p));
+  memset (&u, 0, sizeof (u));
+  memset (&e, 0, sizeof (e));
+  memset (&d, 0, sizeof (d));
+  memset (&exp1, 0, sizeof (exp1));
+  memset (&exp2, 0, sizeof (exp2));
+
+  result = _gnutls_pk_params_copy (&pk_params, params);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+  result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_EXPORT, &pk_params);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  /* retrieve as data */
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[0], &m);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[1], &e);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[2], &d);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[3], &p);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[4], &q);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[5], &u);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[6], &exp1);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = _gnutls_mpi_dprint_lz (pk_params.params[7], &exp2);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  /* Ok. Now we have the data. Create the asn1 structures
+   */
+
+  /* first make sure that no previously allocated data are leaked */
+  if (*c2 != ASN1_TYPE_EMPTY)
+    {
+      asn1_delete_structure (c2);
+      *c2 = ASN1_TYPE_EMPTY;
+    }
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", c2))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  /* Write PRIME 
+   */
+  if ((result = asn1_write_value (*c2, "modulus",
+                                  m.data, m.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "publicExponent",
+                                  e.data, e.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "privateExponent",
+                                  d.data, d.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "prime1",
+                                  p.data, p.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "prime2",
+                                  q.data, q.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "coefficient",
+                                  u.data, u.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "exponent1",
+                                  exp1.data, exp1.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "exponent2",
+                                  exp2.data, exp2.size)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "otherPrimeInfos",
+                                  NULL, 0)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
+  if (result != 0)
+    asn1_delete_structure (c2);
+
+  gnutls_pk_params_release (&pk_params);
+
+  _gnutls_free_datum (&m);
+  _gnutls_free_datum (&d);
+  _gnutls_free_datum (&e);
+  _gnutls_free_datum (&p);
+  _gnutls_free_datum (&q);
+  _gnutls_free_datum (&u);
+  _gnutls_free_datum (&exp1);
+  _gnutls_free_datum (&exp2);
+
+  return result;
+}
+
+/* Encodes the ECC parameters into an ASN.1 ECPrivateKey structure.
+ */
+static int
+_gnutls_asn1_encode_ecc (ASN1_TYPE * c2, gnutls_pk_params_st * params)
+{
+  int ret;
+  opaque one = '\x01';
+  gnutls_datum pubkey = { NULL, 0 };
+  const char *oid;
+  
+  oid = _gnutls_ecc_curve_get_oid(params->flags);
+
+  if (params->params_nr != ECC_PRIVATE_PARAMS || oid == NULL)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  ret = _gnutls_ecc_ansi_x963_export(params->flags, params->params[5], 
params->params[6], &pubkey);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+  
+  /* Ok. Now we have the data. Create the asn1 structures
+   */
+
+  /* first make sure that no previously allocated data are leaked */
+  if (*c2 != ASN1_TYPE_EMPTY)
+    {
+      asn1_delete_structure (c2);
+      *c2 = ASN1_TYPE_EMPTY;
+    }
+
+  if ((ret = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.ECPrivateKey", c2))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  /* Write PRIME 
+   */
+  if ((ret = asn1_write_value (*c2, "version", &one, 1)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  ret = _gnutls_x509_write_int (*c2, "privateKey", params->params[8], 1);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  if ((ret = asn1_write_value (*c2, "publibKey", pubkey.data, pubkey.size)) != 
ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  /* write our choice */
+  if ((ret = asn1_write_value (*c2, "parameters", "namedCurve", 1)) != 
ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+  
+  if ((ret = asn1_write_value (*c2, "parameters.namedCurve", oid, 1)) != 
ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  _gnutls_free_datum(&pubkey);
+  return 0;
+
+cleanup:
+  asn1_delete_structure (c2);
+  _gnutls_free_datum(&pubkey);
+
+  return ret;
+}
+
+
+/* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure.
+ */
+static int
+_gnutls_asn1_encode_dsa (ASN1_TYPE * c2, gnutls_pk_params_st * params)
+{
+  int result, i;
+  size_t size[DSA_PRIVATE_PARAMS], total;
+  opaque *p_data, *q_data, *g_data, *x_data, *y_data;
+  opaque *all_data = NULL, *p;
+  opaque null = '\0';
+
+  /* Read all the sizes */
+  total = 0;
+  for (i = 0; i < DSA_PRIVATE_PARAMS; i++)
+    {
+      _gnutls_mpi_print_lz (params->params[i], NULL, &size[i]);
+      total += size[i];
+    }
+
+  /* Encoding phase.
+   * allocate data enough to hold everything
+   */
+  all_data = gnutls_secure_malloc (total);
+  if (all_data == NULL)
+    {
+      gnutls_assert ();
+      result = GNUTLS_E_MEMORY_ERROR;
+      goto cleanup;
+    }
+
+  p = all_data;
+  p_data = p;
+  p += size[0];
+  q_data = p;
+  p += size[1];
+  g_data = p;
+  p += size[2];
+  y_data = p;
+  p += size[3];
+  x_data = p;
+
+  _gnutls_mpi_print_lz (params->params[0], p_data, &size[0]);
+  _gnutls_mpi_print_lz (params->params[1], q_data, &size[1]);
+  _gnutls_mpi_print_lz (params->params[2], g_data, &size[2]);
+  _gnutls_mpi_print_lz (params->params[3], y_data, &size[3]);
+  _gnutls_mpi_print_lz (params->params[4], x_data, &size[4]);
+
+  /* Ok. Now we have the data. Create the asn1 structures
+   */
+
+  /* first make sure that no previously allocated data are leaked */
+  if (*c2 != ASN1_TYPE_EMPTY)
+    {
+      asn1_delete_structure (c2);
+      *c2 = ASN1_TYPE_EMPTY;
+    }
+
+  if ((result = asn1_create_element
+       (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPrivateKey", c2))
+      != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  /* Write PRIME 
+   */
+  if ((result = asn1_write_value (*c2, "p", p_data, size[0])) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "q", q_data, size[1])) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "g", g_data, size[2])) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "Y", y_data, size[3])) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  if ((result = asn1_write_value (*c2, "priv",
+                                  x_data, size[4])) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  gnutls_free (all_data);
+
+  if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      result = _gnutls_asn2err (result);
+      goto cleanup;
+    }
+
+  return 0;
+
+cleanup:
+  asn1_delete_structure (c2);
+  gnutls_free (all_data);
+
+  return result;
+}
+
+int _gnutls_asn1_encode_privkey (gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, 
gnutls_pk_params_st * params)
+{
+  switch(pk)
+    {
+      case GNUTLS_PK_RSA:
+        return _gnutls_asn1_encode_rsa(c2, params);
+      case GNUTLS_PK_DSA:
+        return _gnutls_asn1_encode_dsa(c2, params);
+      case GNUTLS_PK_ECC:
+        return _gnutls_asn1_encode_ecc(c2, params);
+      default:
+        return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+    }
+}
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index 1bd26cb..37a8386 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -31,125 +31,8 @@
 #include "common.h"
 #include "x509_int.h"
 #include <gnutls_num.h>
+#include <gnutls_ecc.h>
 
-/*
- * some x509 certificate parsing functions that relate to MPI parameter
- * extraction. This reads the BIT STRING subjectPublicKey.
- * Returns 2 parameters (m,e).
- */
-int
-_gnutls_x509_read_rsa_params (opaque * der, int dersize, bigint_t * params)
-{
-  int result;
-  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
-
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk))
-      != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = asn1_der_decoding (&spk, der, dersize, NULL);
-
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&spk);
-      return _gnutls_asn2err (result);
-    }
-
-
-  if ((result = _gnutls_x509_read_int (spk, "modulus", &params[0])) < 0)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&spk);
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
-
-  if ((result = _gnutls_x509_read_int (spk, "publicExponent",
-                                       &params[1])) < 0)
-    {
-      gnutls_assert ();
-      _gnutls_mpi_release (&params[0]);
-      asn1_delete_structure (&spk);
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
-
-  asn1_delete_structure (&spk);
-
-  return 0;
-
-}
-
-
-/* reads p,q and g 
- * from the certificate (subjectPublicKey BIT STRING).
- * params[0-2]
- */
-int
-_gnutls_x509_read_dsa_params (opaque * der, int dersize, bigint_t * params)
-{
-  int result;
-  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
-
-  if ((result = asn1_create_element
-       (_gnutls_get_pkix (), "PKIX1.Dss-Parms", &spk)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = asn1_der_decoding (&spk, der, dersize, NULL);
-
-  if (result != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&spk);
-      return _gnutls_asn2err (result);
-    }
-
-  /* FIXME: If the parameters are not included in the certificate
-   * then the issuer's parameters should be used. This is not
-   * done yet.
-   */
-
-  /* Read p */
-
-  if ((result = _gnutls_x509_read_int (spk, "p", &params[0])) < 0)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&spk);
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
-
-  /* Read q */
-
-  if ((result = _gnutls_x509_read_int (spk, "q", &params[1])) < 0)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&spk);
-      _gnutls_mpi_release (&params[0]);
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
-
-  /* Read g */
-
-  if ((result = _gnutls_x509_read_int (spk, "g", &params[2])) < 0)
-    {
-      gnutls_assert ();
-      asn1_delete_structure (&spk);
-      _gnutls_mpi_release (&params[0]);
-      _gnutls_mpi_release (&params[1]);
-      return GNUTLS_E_ASN1_GENERIC_ERROR;
-    }
-
-  asn1_delete_structure (&spk);
-
-  return 0;
-
-}
 
 /* Reads an Integer from the DER encoded data
  */
@@ -193,28 +76,20 @@ _gnutls_x509_read_der_int (opaque * der, int dersize, 
bigint_t * out)
 
 }
 
-/* reads DSA's Y
- * from the certificate 
- * only sets params[3]
- */
-int
-_gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, bigint_t * params)
-{
-  return _gnutls_x509_read_der_int (der, dersize, &params[3]);
-}
-
 
 /* Extracts DSA and RSA parameters from a certificate.
  */
 int
 _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
-                      bigint_t * params, int *params_size)
+                      gnutls_pk_params_st * params)
 {
   int result;
   char name[256];
   gnutls_datum_t tmp = { NULL, 0 };
   gnutls_pk_algorithm_t pk_algorithm;
 
+  gnutls_pk_params_init(params);
+
   result = _gnutls_x509_get_pk_algorithm (asn, root, NULL);
   if (result < 0)
     {
@@ -235,87 +110,40 @@ _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
       return result;
     }
 
-  switch (pk_algorithm)
+  if ((result =
+       _gnutls_x509_read_pubkey (pk_algorithm, tmp.data, tmp.size, params)) < 
0)
     {
-    case GNUTLS_PK_RSA:
-      /* params[0] is the modulus,
-       * params[1] is the exponent
-       */
-      if (*params_size < RSA_PUBLIC_PARAMS)
-        {
-          gnutls_assert ();
-          /* internal error. Increase the bigint_ts in params */
-          result = GNUTLS_E_INTERNAL_ERROR;
-          goto error;
-        }
-
-      if ((result =
-           _gnutls_x509_read_rsa_params (tmp.data, tmp.size, params)) < 0)
-        {
-          gnutls_assert ();
-          goto error;
-        }
-      *params_size = RSA_PUBLIC_PARAMS;
-
-      break;
-    case GNUTLS_PK_DSA:
-      /* params[0] is p,
-       * params[1] is q,
-       * params[2] is q,
-       * params[3] is pub.
-       */
-
-      if (*params_size < DSA_PUBLIC_PARAMS)
-        {
-          gnutls_assert ();
-          /* internal error. Increase the bigint_ts in params */
-          result = GNUTLS_E_INTERNAL_ERROR;
-          goto error;
-        }
+      gnutls_assert ();
+      goto error;
+    }
 
-      if ((result =
-           _gnutls_x509_read_dsa_pubkey (tmp.data, tmp.size, params)) < 0)
-        {
-          gnutls_assert ();
-          goto error;
-        }
+  /* Now read the parameters
+   */
+  _gnutls_free_datum (&tmp);
+ 
+  _asnstr_append_name (name, sizeof (name), root,
+                       ".algorithm.parameters");
 
-      /* Now read the parameters
-       */
-      _gnutls_free_datum (&tmp);
+  /* FIXME: If the parameters are not included in the certificate
+   * then the issuer's parameters should be used. This is not
+   * done yet.
+   */
 
-      _asnstr_append_name (name, sizeof (name), root,
-                           ".algorithm.parameters");
+  if (pk_algorithm != GNUTLS_PK_RSA) /* RSA doesn't use parameters */
+    {
       result = _gnutls_x509_read_value (asn, name, &tmp, 0);
-
-      /* FIXME: If the parameters are not included in the certificate
-       * then the issuer's parameters should be used. This is not
-       * done yet.
-       */
-
-      if (result < 0)
+      if (result < 0) 
         {
           gnutls_assert ();
           goto error;
         }
 
       if ((result =
-           _gnutls_x509_read_dsa_params (tmp.data, tmp.size, params)) < 0)
+           _gnutls_x509_read_pubkey_params (pk_algorithm, tmp.data, tmp.size, 
params)) < 0)
         {
           gnutls_assert ();
           goto error;
         }
-      *params_size = DSA_PUBLIC_PARAMS;
-
-      break;
-
-    default:
-      /* other types like DH
-       * currently not supported
-       */
-      gnutls_assert ();
-      result = GNUTLS_E_X509_CERTIFICATE_ERROR;
-      goto error;
     }
 
   result = 0;
@@ -329,13 +157,12 @@ error:
  */
 int
 _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert,
-                           bigint_t * params, int *params_size)
+                           gnutls_pk_params_st * params)
 {
   /* Read the algorithm's OID
    */
   return _gnutls_get_asn_mpis (cert->cert,
-                               "tbsCertificate.subjectPublicKeyInfo", params,
-                               params_size);
+                               "tbsCertificate.subjectPublicKeyInfo", params);
 }
 
 #ifdef ENABLE_PKI
@@ -344,78 +171,17 @@ _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert,
  */
 int
 _gnutls_x509_crq_get_mpis (gnutls_x509_crq_t cert,
-                           bigint_t * params, int *params_size)
+                           gnutls_pk_params_st* params)
 {
   /* Read the algorithm's OID
    */
   return _gnutls_get_asn_mpis (cert->crq,
                                "certificationRequestInfo.subjectPKInfo",
-                               params, params_size);
+                               params);
 }
 
 #endif
 
-/*
- * some x509 certificate functions that relate to MPI parameter
- * setting. This writes the BIT STRING subjectPublicKey.
- * Needs 2 parameters (m,e).
- *
- * Allocates the space used to store the DER data.
- */
-int
-_gnutls_x509_write_rsa_params (bigint_t * params, int params_size,
-                               gnutls_datum_t * der)
-{
-  int result;
-  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
-
-  der->data = NULL;
-  der->size = 0;
-
-  if (params_size < 2)
-    {
-      gnutls_assert ();
-      result = GNUTLS_E_INVALID_REQUEST;
-      goto cleanup;
-    }
-
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk))
-      != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = _gnutls_x509_write_int (spk, "modulus", params[0], 1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_x509_write_int (spk, "publicExponent", params[1], 1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_x509_der_encode (spk, "", der, 0);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  asn1_delete_structure (&spk);
-  return 0;
-
-cleanup:
-  asn1_delete_structure (&spk);
-
-  return result;
-}
 
 /*
  * This function writes and encodes the parameters for DSS or RSA keys.
@@ -473,123 +239,7 @@ _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char 
*dst_name,
   return 0;
 }
 
-/*
- * This function writes the parameters for DSS keys.
- * Needs 3 parameters (p,q,g).
- *
- * Allocates the space used to store the DER data.
- */
-int
-_gnutls_x509_write_dsa_params (bigint_t * params, int params_size,
-                               gnutls_datum_t * der)
-{
-  int result;
-  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
-
-  der->data = NULL;
-  der->size = 0;
-
-  if (params_size < 3)
-    {
-      gnutls_assert ();
-      result = GNUTLS_E_INVALID_REQUEST;
-      goto cleanup;
-    }
 
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.DSAParameters", &spk))
-      != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = _gnutls_x509_write_int (spk, "p", params[0], 1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_x509_write_int (spk, "q", params[1], 1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_x509_write_int (spk, "g", params[2], 1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_x509_der_encode (spk, "", der, 0);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = 0;
-
-cleanup:
-  asn1_delete_structure (&spk);
-  return result;
-}
-
-/*
- * This function writes the public parameters for DSS keys.
- * Needs 1 parameter (y).
- *
- * Allocates the space used to store the DER data.
- */
-int
-_gnutls_x509_write_dsa_public_key (bigint_t * params, int params_size,
-                                   gnutls_datum_t * der)
-{
-  int result;
-  ASN1_TYPE spk = ASN1_TYPE_EMPTY;
-
-  der->data = NULL;
-  der->size = 0;
-
-  if (params_size < 3)
-    {
-      gnutls_assert ();
-      result = GNUTLS_E_INVALID_REQUEST;
-      goto cleanup;
-    }
-
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", &spk))
-      != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      return _gnutls_asn2err (result);
-    }
-
-  result = _gnutls_x509_write_int (spk, "", params[3], 1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_x509_der_encode (spk, "", der, 0);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = 0;
-
-cleanup:
-  asn1_delete_structure (&spk);
-  return result;
-}
 
 
 /* this function reads a (small) unsigned integer
diff --git a/lib/x509/output.c b/lib/x509/output.c
index a49ae95..3977596 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -1147,7 +1147,7 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert, int notsigned)
 
   /* SubjectPublicKeyInfo. */
   {
-    int err;
+    int err, pk;
     unsigned int bits;
 
     err = gnutls_x509_crt_get_pk_algorithm (cert, &bits);
@@ -1155,23 +1155,39 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert, int notsigned)
       addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err));
     else
       {
+        gnutls_pubkey_t pubkey;
         const char *name = gnutls_pk_algorithm_get_name (err);
         if (name == NULL)
           name = _("unknown");
+          
+        pk = err;
 
         addf (str, _("\tSubject Public Key Algorithm: %s\n"), name);
         addf (str, _("\tCertificate Security Level: %s\n"),
               gnutls_sec_param_get_name (gnutls_pk_bits_to_sec_param
                                          (err, bits)));
-
 #ifdef ENABLE_PKI
-        switch (err)
+        err = gnutls_pubkey_init(&pubkey);
+        if (err < 0)
+         {
+            addf (str, "error: gnutls_pubkey_init: %s\n", gnutls_strerror 
(err));
+            return;
+          }
+
+        err = gnutls_pubkey_import_x509(pubkey, cert, 0);
+        if (err < 0)
+          {
+            addf (str, "error: gnutls_pubkey_import_x509: %s\n", 
gnutls_strerror (err));
+            return;
+          }
+
+        switch (pk)
           {
           case GNUTLS_PK_RSA:
             {
               gnutls_datum_t m, e;
 
-              err = gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e);
+              err = gnutls_pubkey_get_pk_rsa_raw (pubkey, &m, &e);
               if (err < 0)
                 addf (str, "error: get_pk_rsa_raw: %s\n",
                       gnutls_strerror (err));
@@ -1189,11 +1205,34 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert, int notsigned)
             }
             break;
 
+          case GNUTLS_PK_ECC:
+            {
+              gnutls_datum_t x, y;
+              gnutls_ecc_curve_t curve;
+
+              err = gnutls_pubkey_get_pk_ecc_raw (pubkey, &curve, &x, &y);
+              if (err < 0)
+                addf (str, "error: get_pk_ecc_raw: %s\n",
+                      gnutls_strerror (err));
+              else
+                {
+                  addf (str, _("\t\tCurve:\t%s\n"), 
gnutls_ecc_curve_get_name(curve));
+                  addf (str, _("\t\tX:\n"));
+                  hexdump (str, x.data, x.size, "\t\t\t");
+                  adds (str, _("\t\tY:\n"));
+                  hexdump (str, y.data, y.size, "\t\t\t");
+
+                  gnutls_free (x.data);
+                  gnutls_free (y.data);
+
+                }
+            }
+            break;
           case GNUTLS_PK_DSA:
             {
               gnutls_datum_t p, q, g, y;
 
-              err = gnutls_x509_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y);
+              err = gnutls_pubkey_get_pk_dsa_raw (pubkey, &p, &q, &g, &y);
               if (err < 0)
                 addf (str, "error: get_pk_dsa_raw: %s\n",
                       gnutls_strerror (err));
@@ -1220,6 +1259,8 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t 
cert, int notsigned)
           default:
             break;
           }
+        
+        gnutls_pubkey_deinit(pubkey);
 #endif
       }
   }
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 66f3290..925a970 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -35,8 +35,7 @@
 #include <x509_int.h>
 #include <gnutls_pk.h>
 #include <gnutls_mpi.h>
-
-static int _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params);
+#include <gnutls_ecc.h>
 
 /**
  * gnutls_x509_privkey_init:
@@ -71,16 +70,10 @@ gnutls_x509_privkey_init (gnutls_x509_privkey_t * key)
 void
 gnutls_x509_privkey_deinit (gnutls_x509_privkey_t key)
 {
-  int i;
-
   if (!key)
     return;
 
-  for (i = 0; i < key->params_size; i++)
-    {
-      _gnutls_mpi_release (&key->params[i]);
-    }
-
+  gnutls_pk_params_release(&key->params);
   asn1_delete_structure (&key->key);
   gnutls_free (key);
 }
@@ -104,40 +97,26 @@ gnutls_x509_privkey_cpy (gnutls_x509_privkey_t dst, 
gnutls_x509_privkey_t src)
   if (!src || !dst)
     return GNUTLS_E_INVALID_REQUEST;
 
-  for (i = 0; i < src->params_size; i++)
+  for (i = 0; i < src->params.params_nr; i++)
     {
-      dst->params[i] = _gnutls_mpi_copy (src->params[i]);
-      if (dst->params[i] == NULL)
+      dst->params.params[i] = _gnutls_mpi_copy (src->params.params[i]);
+      if (dst->params.params[i] == NULL)
         return GNUTLS_E_MEMORY_ERROR;
     }
 
-  dst->params_size = src->params_size;
+  dst->params.params_nr = src->params.params_nr;
+  dst->params.flags = src->params.flags;
+
   dst->pk_algorithm = src->pk_algorithm;
   dst->crippled = src->crippled;
 
   if (!src->crippled)
     {
-      switch (dst->pk_algorithm)
+      ret = _gnutls_asn1_encode_privkey (dst->pk_algorithm, &dst->key, 
&dst->params);
+      if (ret < 0)
         {
-        case GNUTLS_PK_DSA:
-          ret = _gnutls_asn1_encode_dsa (&dst->key, dst->params);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              return ret;
-            }
-          break;
-        case GNUTLS_PK_RSA:
-          ret = _gnutls_asn1_encode_rsa (&dst->key, dst->params);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              return ret;
-            }
-          break;
-        default:
           gnutls_assert ();
-          return GNUTLS_E_INVALID_REQUEST;
+          return ret;
         }
     }
 
@@ -153,10 +132,9 @@ _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t 
* raw_key,
 {
   int result;
   ASN1_TYPE pkey_asn;
-  gnutls_pk_params_st pk_params;
 
-  memset (&pk_params, 0, sizeof (pk_params));
-  pk_params.params_nr = RSA_PRIVATE_PARAMS;
+  gnutls_pk_params_init(&pkey->params);
+
 
   if ((result =
        asn1_create_element (_gnutls_get_gnutls_asn (),
@@ -175,7 +153,7 @@ _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t 
* raw_key,
     }
 
   if ((result = _gnutls_x509_read_int (pkey_asn, "modulus",
-                                       &pk_params.params[0])) < 0)
+                                       &pkey->params.params[0])) < 0)
     {
       gnutls_assert ();
       goto error;
@@ -183,7 +161,7 @@ _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t 
* raw_key,
 
   if ((result =
        _gnutls_x509_read_int (pkey_asn, "publicExponent",
-                              &pk_params.params[1])) < 0)
+                              &pkey->params.params[1])) < 0)
     {
       gnutls_assert ();
       goto error;
@@ -191,74 +169,174 @@ _gnutls_privkey_decode_pkcs1_rsa_key (const 
gnutls_datum_t * raw_key,
 
   if ((result =
        _gnutls_x509_read_int (pkey_asn, "privateExponent",
-                              &pk_params.params[2])) < 0)
+                              &pkey->params.params[2])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
   if ((result = _gnutls_x509_read_int (pkey_asn, "prime1",
-                                       &pk_params.params[3])) < 0)
+                                       &pkey->params.params[3])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
   if ((result = _gnutls_x509_read_int (pkey_asn, "prime2",
-                                       &pk_params.params[4])) < 0)
+                                       &pkey->params.params[4])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
   if ((result = _gnutls_x509_read_int (pkey_asn, "coefficient",
-                                       &pk_params.params[5])) < 0)
+                                       &pkey->params.params[5])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
   if ((result = _gnutls_x509_read_int (pkey_asn, "exponent1",
-                                       &pk_params.params[6])) < 0)
+                                       &pkey->params.params[6])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
   if ((result = _gnutls_x509_read_int (pkey_asn, "exponent2",
-                                       &pk_params.params[7])) < 0)
+                                       &pkey->params.params[7])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
 
-  result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pk_params);
+  result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pkey->params);
   if (result < 0)
     {
       gnutls_assert ();
       goto error;
     }
 
-  pkey->params[0] = pk_params.params[0];
-  pkey->params[1] = pk_params.params[1];
-  pkey->params[2] = pk_params.params[2];
-  pkey->params[3] = pk_params.params[3];
-  pkey->params[4] = pk_params.params[4];
-  pkey->params[5] = pk_params.params[5];
-  pkey->params[6] = pk_params.params[6];
-  pkey->params[7] = pk_params.params[7];
-  pkey->params_size = pk_params.params_nr;
+  pkey->params.params_nr = RSA_PRIVATE_PARAMS;
 
   return pkey_asn;
 
 error:
   asn1_delete_structure (&pkey_asn);
-  gnutls_pk_params_release (&pk_params);
+  gnutls_pk_params_release (&pkey->params);
+  return NULL;
+
+}
+
+/* Converts an ECC key to
+ * an internal structure (gnutls_private_key)
+ */
+ASN1_TYPE
+_gnutls_privkey_decode_ecc_key (const gnutls_datum_t * raw_key,
+                                      gnutls_x509_privkey_t pkey)
+{
+  int ret;
+  ASN1_TYPE pkey_asn;
+  unsigned int version;
+  char oid[MAX_OID_SIZE];
+  unsigned int oid_size;
+  gnutls_datum out;
+
+  gnutls_pk_params_init(&pkey->params);
+
+  if ((ret =
+       asn1_create_element (_gnutls_get_gnutls_asn (),
+                            "GNUTLS.ECPrivateKey",
+                            &pkey_asn)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      return NULL;
+    }
+
+  ret = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      goto error;
+    }
+
+  ret = _gnutls_x509_read_uint (pkey_asn, "Version", &version);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto error;
+    }
+
+  if (version != 1)
+    {
+      _gnutls_debug_log("ECC private key version %u is not supported\n", 
version);
+      gnutls_assert();
+      goto error;
+    }
+
+  /* read the curve */
+  oid_size = sizeof(oid);
+  ret = asn1_read_value(pkey_asn, "parameters.namedCurve", oid, &oid_size);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      goto error;
+    }
+    
+  pkey->params.flags = _gnutls_oid_to_ecc_curve(oid);
+  if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID)
+    {
+      _gnutls_debug_log("Curve %s is not supported\n", oid);
+      gnutls_assert();
+      goto error;
+    }
+    
+  ret = _gnutls_ecc_curve_fill_params(pkey->params.flags, &pkey->params);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto error;
+    }
+
+  /* read the public key */
+  ret = _gnutls_x509_read_value(pkey_asn, "publicKey", &out, 2);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto error;
+    }
+
+  ret = _gnutls_ecc_ansi_x963_import (out.data, out.size, 
&pkey->params.params[5],
+                                         &pkey->params.params[6]);
+  
+  _gnutls_free_datum(&out);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto error;
+    }
+  pkey->params.params_nr += 2;
+
+  /* read the private key */
+  ret = _gnutls_x509_read_int (pkey_asn, "privateKey", 
&pkey->params.params[7]);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto error;
+    }
+  pkey->params.params_nr ++;
+
+  return pkey_asn;
+
+error:
+  asn1_delete_structure (&pkey_asn);
+  gnutls_pk_params_release (&pkey->params);
   return NULL;
 
 }
 
+
 static ASN1_TYPE
 decode_dsa_key (const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey)
 {
@@ -274,54 +352,57 @@ decode_dsa_key (const gnutls_datum_t * raw_key, 
gnutls_x509_privkey_t pkey)
       return NULL;
     }
 
+  pkey->params.params_nr = 0;
+
   result = asn1_der_decoding (&dsa_asn, raw_key->data, raw_key->size, NULL);
   if (result != ASN1_SUCCESS)
     {
       gnutls_assert ();
       goto error;
     }
+  pkey->params.params_nr++;
 
-  if ((result = _gnutls_x509_read_int (dsa_asn, "p", &pkey->params[0])) < 0)
+  if ((result = _gnutls_x509_read_int (dsa_asn, "p", &pkey->params.params[0])) 
< 0)
     {
       gnutls_assert ();
       goto error;
     }
+  pkey->params.params_nr++;
 
-  if ((result = _gnutls_x509_read_int (dsa_asn, "q", &pkey->params[1])) < 0)
+  if ((result = _gnutls_x509_read_int (dsa_asn, "q", &pkey->params.params[1])) 
< 0)
     {
       gnutls_assert ();
       goto error;
     }
+  pkey->params.params_nr++;
 
-  if ((result = _gnutls_x509_read_int (dsa_asn, "g", &pkey->params[2])) < 0)
+  if ((result = _gnutls_x509_read_int (dsa_asn, "g", &pkey->params.params[2])) 
< 0)
     {
       gnutls_assert ();
       goto error;
     }
+  pkey->params.params_nr++;
 
-  if ((result = _gnutls_x509_read_int (dsa_asn, "Y", &pkey->params[3])) < 0)
+  if ((result = _gnutls_x509_read_int (dsa_asn, "Y", &pkey->params.params[3])) 
< 0)
     {
       gnutls_assert ();
       goto error;
     }
+  pkey->params.params_nr++;
 
   if ((result = _gnutls_x509_read_int (dsa_asn, "priv",
-                                       &pkey->params[4])) < 0)
+                                       &pkey->params.params[4])) < 0)
     {
       gnutls_assert ();
       goto error;
     }
-  pkey->params_size = 5;
+  pkey->params.params_nr++;
 
   return dsa_asn;
 
 error:
   asn1_delete_structure (&dsa_asn);
-  _gnutls_mpi_release (&pkey->params[0]);
-  _gnutls_mpi_release (&pkey->params[1]);
-  _gnutls_mpi_release (&pkey->params[2]);
-  _gnutls_mpi_release (&pkey->params[3]);
-  _gnutls_mpi_release (&pkey->params[4]);
+  gnutls_pk_params_release(&pkey->params);
   return NULL;
 
 }
@@ -414,6 +495,12 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
       if (key->key == NULL)
         gnutls_assert ();
     }
+  else if (key->pk_algorithm == GNUTLS_PK_ECC)
+    {
+      key->key = _gnutls_privkey_decode_ecc_key (&_data, key);
+      if (key->key == NULL)
+        gnutls_assert ();
+    }
   else
     {
       /* Try decoding with both, and accept the one that
@@ -463,11 +550,6 @@ failover:
   return result;
 }
 
-#define FREE_RSA_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
-               _gnutls_mpi_release(&key->params[i])
-#define FREE_DSA_PRIVATE_PARAMS for (i=0;i<DSA_PRIVATE_PARAMS;i++) \
-               _gnutls_mpi_release(&key->params[i])
-
 /**
  * gnutls_x509_privkey_import_rsa_raw:
  * @key: The structure to store the parsed key
@@ -528,11 +610,10 @@ gnutls_x509_privkey_import_rsa_raw2 
(gnutls_x509_privkey_t key,
                                      const gnutls_datum_t * e1,
                                      const gnutls_datum_t * e2)
 {
-  int i = 0, ret;
+  int ret;
   size_t siz = 0;
-  gnutls_pk_params_st pk_params;
 
-  memset (&pk_params, 0, sizeof (pk_params));
+  gnutls_pk_params_init(&key->params);
 
   if (key == NULL)
     {
@@ -540,120 +621,109 @@ gnutls_x509_privkey_import_rsa_raw2 
(gnutls_x509_privkey_t key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  key->params_size = 0;
+  key->params.params_nr = 0;
 
   siz = m->size;
-  if (_gnutls_mpi_scan_nz (&key->params[0], m->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz))
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
-  key->params_size++;
+  key->params.params_nr++;
 
   siz = e->size;
-  if (_gnutls_mpi_scan_nz (&key->params[1], e->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz))
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
-  key->params_size++;
+  key->params.params_nr++;
 
   siz = d->size;
-  if (_gnutls_mpi_scan_nz (&key->params[2], d->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[2], d->data, siz))
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
-  key->params_size++;
+  key->params.params_nr++;
 
   siz = p->size;
-  if (_gnutls_mpi_scan_nz (&key->params[3], p->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[3], p->data, siz))
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
-  key->params_size++;
+  key->params.params_nr++;
 
   siz = q->size;
-  if (_gnutls_mpi_scan_nz (&key->params[4], q->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[4], q->data, siz))
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
-  key->params_size++;
+  key->params.params_nr++;
 
   siz = u->size;
-  if (_gnutls_mpi_scan_nz (&key->params[5], u->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[5], u->data, siz))
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
-  key->params_size++;
+  key->params.params_nr++;
 
   if (e1 && e2)
     {
       siz = e1->size;
-      if (_gnutls_mpi_scan_nz (&key->params[6], e1->data, siz))
+      if (_gnutls_mpi_scan_nz (&key->params.params[6], e1->data, siz))
         {
           gnutls_assert ();
-          FREE_RSA_PRIVATE_PARAMS;
-          return GNUTLS_E_MPI_SCAN_FAILED;
+          ret = GNUTLS_E_MPI_SCAN_FAILED;
+          goto cleanup;
         }
-      key->params_size++;
+      key->params.params_nr++;
 
       siz = e2->size;
-      if (_gnutls_mpi_scan_nz (&key->params[7], e2->data, siz))
+      if (_gnutls_mpi_scan_nz (&key->params.params[7], e2->data, siz))
         {
           gnutls_assert ();
-          FREE_RSA_PRIVATE_PARAMS;
-          return GNUTLS_E_MPI_SCAN_FAILED;
+          ret = GNUTLS_E_MPI_SCAN_FAILED;
+          goto cleanup;
         }
-      key->params_size++;
-    }
-
-  for (i = 0; i < key->params_size; i++)
-    {
-      pk_params.params[i] = key->params[i];
+      key->params.params_nr++;
     }
 
-  pk_params.params_nr = key->params_size;
-
-  ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pk_params);
+  ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &key->params);
   if (ret < 0)
     {
       gnutls_assert ();
-      FREE_RSA_PRIVATE_PARAMS;
-      return ret;
-    }
-
-  for (i = 0; i < pk_params.params_nr; i++)
-    {
-      key->params[i] = pk_params.params[i];
+      goto cleanup;
     }
-  key->params_size = pk_params.params_nr;
 
   if (!key->crippled)
     {
-      ret = _gnutls_asn1_encode_rsa (&key->key, key->params);
+      ret = _gnutls_asn1_encode_privkey (GNUTLS_PK_RSA, &key->key, 
&key->params);
       if (ret < 0)
         {
           gnutls_assert ();
-          FREE_RSA_PRIVATE_PARAMS;
-          return ret;
+          goto cleanup;
         }
     }
 
-  key->params_size = RSA_PRIVATE_PARAMS;
+  key->params.params_nr = RSA_PRIVATE_PARAMS;
   key->pk_algorithm = GNUTLS_PK_RSA;
 
   return 0;
 
+cleanup:
+  gnutls_pk_params_release(&key->params);
+  return ret;
+
 }
 
 /**
@@ -680,7 +750,7 @@ gnutls_x509_privkey_import_dsa_raw (gnutls_x509_privkey_t 
key,
                                     const gnutls_datum_t * y,
                                     const gnutls_datum_t * x)
 {
-  int i = 0, ret;
+  int ret;
   size_t siz = 0;
 
   if (key == NULL)
@@ -690,61 +760,64 @@ gnutls_x509_privkey_import_dsa_raw (gnutls_x509_privkey_t 
key,
     }
 
   siz = p->size;
-  if (_gnutls_mpi_scan_nz (&key->params[0], p->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[0], p->data, siz))
     {
       gnutls_assert ();
-      FREE_DSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
 
   siz = q->size;
-  if (_gnutls_mpi_scan_nz (&key->params[1], q->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[1], q->data, siz))
     {
       gnutls_assert ();
-      FREE_DSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
 
   siz = g->size;
-  if (_gnutls_mpi_scan_nz (&key->params[2], g->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[2], g->data, siz))
     {
       gnutls_assert ();
-      FREE_DSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
 
   siz = y->size;
-  if (_gnutls_mpi_scan_nz (&key->params[3], y->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[3], y->data, siz))
     {
       gnutls_assert ();
-      FREE_DSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
 
   siz = x->size;
-  if (_gnutls_mpi_scan_nz (&key->params[4], x->data, siz))
+  if (_gnutls_mpi_scan_nz (&key->params.params[4], x->data, siz))
     {
       gnutls_assert ();
-      FREE_DSA_PRIVATE_PARAMS;
-      return GNUTLS_E_MPI_SCAN_FAILED;
+      ret = GNUTLS_E_MPI_SCAN_FAILED;
+      goto cleanup;
     }
 
   if (!key->crippled)
     {
-      ret = _gnutls_asn1_encode_dsa (&key->key, key->params);
+      ret = _gnutls_asn1_encode_privkey (GNUTLS_PK_DSA, &key->key, 
&key->params);
       if (ret < 0)
         {
           gnutls_assert ();
-          FREE_DSA_PRIVATE_PARAMS;
-          return ret;
+          goto cleanup;
         }
     }
 
-  key->params_size = DSA_PRIVATE_PARAMS;
+  key->params.params_nr = DSA_PRIVATE_PARAMS;
   key->pk_algorithm = GNUTLS_PK_DSA;
 
   return 0;
 
+cleanup:
+  gnutls_pk_params_release(&key->params);
+  return ret;
+
 }
 
 
@@ -814,29 +887,12 @@ gnutls_x509_privkey_export (gnutls_x509_privkey_t key,
     msg = NULL;
 
   if (key->crippled)
-    {                           /* encode the parameters on the fly.
-                                 */
-      switch (key->pk_algorithm)
+    {                           /* encode the parameters on the fly. */
+      ret = _gnutls_asn1_encode_privkey (key->pk_algorithm, &key->key, 
&key->params);
+      if (ret < 0)
         {
-        case GNUTLS_PK_DSA:
-          ret = _gnutls_asn1_encode_dsa (&key->key, key->params);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              return ret;
-            }
-          break;
-        case GNUTLS_PK_RSA:
-          ret = _gnutls_asn1_encode_rsa (&key->key, key->params);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              return ret;
-            }
-          break;
-        default:
           gnutls_assert ();
-          return GNUTLS_E_INVALID_REQUEST;
+          return ret;
         }
     }
 
@@ -857,23 +913,13 @@ gnutls_x509_privkey_export (gnutls_x509_privkey_t key,
 gnutls_sec_param_t
 gnutls_x509_privkey_sec_param (gnutls_x509_privkey_t key)
 {
-  int ret;
+  int bits;
 
-  switch (key->pk_algorithm)
-    {
-    case GNUTLS_PK_RSA:
-      ret = gnutls_pk_bits_to_sec_param (GNUTLS_PK_RSA, _gnutls_mpi_get_nbits 
(key->params[0]   /*m */
-                                         ));
-      break;
-    case GNUTLS_PK_DSA:
-      ret = gnutls_pk_bits_to_sec_param (GNUTLS_PK_DSA, _gnutls_mpi_get_nbits 
(key->params[0]   /*p */
-                                         ));
-      break;
-    default:
-      ret = GNUTLS_SEC_PARAM_UNKNOWN;
-    }
-
-  return ret;
+  bits = pubkey_to_bits(key->pk_algorithm, &key->params);
+  if (bits <= 0)
+    return GNUTLS_SEC_PARAM_UNKNOWN;
+  
+  return gnutls_pk_bits_to_sec_param(key->pk_algorithm, bits);
 }
 
 /**
@@ -932,8 +978,8 @@ gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t 
key,
 {
   int ret;
   gnutls_pk_params_st pk_params;
-
-  memset (&pk_params, 0, sizeof (pk_params));
+  
+  gnutls_pk_params_init(&pk_params);
 
   if (key == NULL)
     {
@@ -944,7 +990,7 @@ gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t 
key,
   m->data = e->data = d->data = p->data = q->data = u->data = NULL;
   m->size = e->size = d->size = p->size = q->size = u->size = 0;
 
-  ret = _gnutls_pk_params_copy (&pk_params, key->params, RSA_PRIVATE_PARAMS);
+  ret = _gnutls_pk_params_copy (&pk_params, &key->params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -998,7 +1044,7 @@ gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t 
key,
     }
 
   /* U */
-  ret = _gnutls_mpi_dprint_lz (key->params[5], u);
+  ret = _gnutls_mpi_dprint_lz (key->params.params[5], u);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1008,7 +1054,7 @@ gnutls_x509_privkey_export_rsa_raw2 
(gnutls_x509_privkey_t key,
   /* E1 */
   if (e1)
     {
-      ret = _gnutls_mpi_dprint_lz (key->params[6], e1);
+      ret = _gnutls_mpi_dprint_lz (key->params.params[6], e1);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -1019,7 +1065,7 @@ gnutls_x509_privkey_export_rsa_raw2 
(gnutls_x509_privkey_t key,
   /* E2 */
   if (e2)
     {
-      ret = _gnutls_mpi_dprint_lz (key->params[7], e2);
+      ret = _gnutls_mpi_dprint_lz (key->params.params[7], e2);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -1073,7 +1119,7 @@ gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t 
key,
     }
 
   /* P */
-  ret = _gnutls_mpi_dprint_lz (key->params[0], p);
+  ret = _gnutls_mpi_dprint_lz (key->params.params[0], p);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1081,7 +1127,7 @@ gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t 
key,
     }
 
   /* Q */
-  ret = _gnutls_mpi_dprint_lz (key->params[1], q);
+  ret = _gnutls_mpi_dprint_lz (key->params.params[1], q);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1091,7 +1137,7 @@ gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t 
key,
 
 
   /* G */
-  ret = _gnutls_mpi_dprint_lz (key->params[2], g);
+  ret = _gnutls_mpi_dprint_lz (key->params.params[2], g);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1102,7 +1148,7 @@ gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t 
key,
 
 
   /* Y */
-  ret = _gnutls_mpi_dprint_lz (key->params[3], y);
+  ret = _gnutls_mpi_dprint_lz (key->params.params[3], y);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1113,7 +1159,7 @@ gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t 
key,
     }
 
   /* X */
-  ret = _gnutls_mpi_dprint_lz (key->params[4], x);
+  ret = _gnutls_mpi_dprint_lz (key->params.params[4], x);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1128,343 +1174,6 @@ gnutls_x509_privkey_export_dsa_raw 
(gnutls_x509_privkey_t key,
 }
 
 
-/* Encodes the RSA parameters into an ASN.1 RSA private key structure.
- */
-static int
-_gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
-{
-  int result;
-  opaque null = '\0';
-  gnutls_pk_params_st pk_params;
-  gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
-
-  memset (&pk_params, 0, sizeof (pk_params));
-
-  memset (&m, 0, sizeof (m));
-  memset (&p, 0, sizeof (p));
-  memset (&q, 0, sizeof (q));
-  memset (&p, 0, sizeof (p));
-  memset (&u, 0, sizeof (u));
-  memset (&e, 0, sizeof (e));
-  memset (&d, 0, sizeof (d));
-  memset (&exp1, 0, sizeof (exp1));
-  memset (&exp2, 0, sizeof (exp2));
-
-  result = _gnutls_pk_params_copy (&pk_params, params, RSA_PRIVATE_PARAMS);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      return result;
-    }
-
-  result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_EXPORT, &pk_params);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  /* retrieve as data */
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[0], &m);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[1], &e);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[2], &d);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[3], &p);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[4], &q);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[5], &u);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[6], &exp1);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  result = _gnutls_mpi_dprint_lz (pk_params.params[7], &exp2);
-  if (result < 0)
-    {
-      gnutls_assert ();
-      goto cleanup;
-    }
-
-  /* Ok. Now we have the data. Create the asn1 structures
-   */
-
-  /* first make sure that no previously allocated data are leaked */
-  if (*c2 != ASN1_TYPE_EMPTY)
-    {
-      asn1_delete_structure (c2);
-      *c2 = ASN1_TYPE_EMPTY;
-    }
-
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", c2))
-      != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  /* Write PRIME 
-   */
-  if ((result = asn1_write_value (*c2, "modulus",
-                                  m.data, m.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "publicExponent",
-                                  e.data, e.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "privateExponent",
-                                  d.data, d.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "prime1",
-                                  p.data, p.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "prime2",
-                                  q.data, q.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "coefficient",
-                                  u.data, u.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "exponent1",
-                                  exp1.data, exp1.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "exponent2",
-                                  exp2.data, exp2.size)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "otherPrimeInfos",
-                                  NULL, 0)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  result = 0;
-
-cleanup:
-  if (result != 0)
-    asn1_delete_structure (c2);
-
-  gnutls_pk_params_release (&pk_params);
-
-  _gnutls_free_datum (&m);
-  _gnutls_free_datum (&d);
-  _gnutls_free_datum (&e);
-  _gnutls_free_datum (&p);
-  _gnutls_free_datum (&q);
-  _gnutls_free_datum (&u);
-  _gnutls_free_datum (&exp1);
-  _gnutls_free_datum (&exp2);
-
-  return result;
-}
-
-/* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure.
- */
-int
-_gnutls_asn1_encode_dsa (ASN1_TYPE * c2, bigint_t * params)
-{
-  int result, i;
-  size_t size[DSA_PRIVATE_PARAMS], total;
-  opaque *p_data, *q_data, *g_data, *x_data, *y_data;
-  opaque *all_data = NULL, *p;
-  opaque null = '\0';
-
-  /* Read all the sizes */
-  total = 0;
-  for (i = 0; i < DSA_PRIVATE_PARAMS; i++)
-    {
-      _gnutls_mpi_print_lz (params[i], NULL, &size[i]);
-      total += size[i];
-    }
-
-  /* Encoding phase.
-   * allocate data enough to hold everything
-   */
-  all_data = gnutls_secure_malloc (total);
-  if (all_data == NULL)
-    {
-      gnutls_assert ();
-      result = GNUTLS_E_MEMORY_ERROR;
-      goto cleanup;
-    }
-
-  p = all_data;
-  p_data = p;
-  p += size[0];
-  q_data = p;
-  p += size[1];
-  g_data = p;
-  p += size[2];
-  y_data = p;
-  p += size[3];
-  x_data = p;
-
-  _gnutls_mpi_print_lz (params[0], p_data, &size[0]);
-  _gnutls_mpi_print_lz (params[1], q_data, &size[1]);
-  _gnutls_mpi_print_lz (params[2], g_data, &size[2]);
-  _gnutls_mpi_print_lz (params[3], y_data, &size[3]);
-  _gnutls_mpi_print_lz (params[4], x_data, &size[4]);
-
-  /* Ok. Now we have the data. Create the asn1 structures
-   */
-
-  /* first make sure that no previously allocated data are leaked */
-  if (*c2 != ASN1_TYPE_EMPTY)
-    {
-      asn1_delete_structure (c2);
-      *c2 = ASN1_TYPE_EMPTY;
-    }
-
-  if ((result = asn1_create_element
-       (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPrivateKey", c2))
-      != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  /* Write PRIME 
-   */
-  if ((result = asn1_write_value (*c2, "p", p_data, size[0])) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "q", q_data, size[1])) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "g", g_data, size[2])) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "Y", y_data, size[3])) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  if ((result = asn1_write_value (*c2, "priv",
-                                  x_data, size[4])) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  gnutls_free (all_data);
-
-  if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS)
-    {
-      gnutls_assert ();
-      result = _gnutls_asn2err (result);
-      goto cleanup;
-    }
-
-  return 0;
-
-cleanup:
-  asn1_delete_structure (c2);
-  gnutls_free (all_data);
-
-  return result;
-}
-
 
 /**
  * gnutls_x509_privkey_generate:
@@ -1487,8 +1196,6 @@ gnutls_x509_privkey_generate (gnutls_x509_privkey_t key,
                               unsigned int flags)
 {
   int ret;
-  unsigned int params_len = MAX_PRIV_PARAMS_SIZE;
-  unsigned int i;
 
   if (key == NULL)
     {
@@ -1496,74 +1203,31 @@ gnutls_x509_privkey_generate (gnutls_x509_privkey_t key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  switch (algo)
-    {
-    case GNUTLS_PK_DSA:
-      ret = _gnutls_dsa_generate_params (key->params, &params_len, bits);
-      if (params_len != DSA_PRIVATE_PARAMS)
-        {
-          gnutls_assert ();
-          ret = GNUTLS_E_INTERNAL_ERROR;
-        }
-
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
+  gnutls_pk_params_init(&key->params);
 
-      if (!key->crippled)
-        {
-          ret = _gnutls_asn1_encode_dsa (&key->key, key->params);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              goto cleanup;
-            }
-        }
-      key->params_size = params_len;
-      key->pk_algorithm = GNUTLS_PK_DSA;
+  ret = _gnutls_pk_generate (algo, bits, &key->params);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      return ret;
+    }
 
-      break;
-    case GNUTLS_PK_RSA:
-      ret = _gnutls_rsa_generate_params (key->params, &params_len, bits);
-      if (params_len != RSA_PRIVATE_PARAMS)
-        {
-          gnutls_assert ();
-          ret = GNUTLS_E_INTERNAL_ERROR;
-        }
+  if (!key->crippled)
+    {
+      ret = _gnutls_asn1_encode_privkey (algo, &key->key, &key->params);
       if (ret < 0)
         {
           gnutls_assert ();
-          return ret;
-        }
-
-      if (!key->crippled)
-        {
-          ret = _gnutls_asn1_encode_rsa (&key->key, key->params);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              goto cleanup;
-            }
+          goto cleanup;
         }
-
-      key->params_size = params_len;
-      key->pk_algorithm = GNUTLS_PK_RSA;
-
-      break;
-    default:
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
     }
+  key->pk_algorithm = algo;
 
   return 0;
 
 cleanup:
   key->pk_algorithm = GNUTLS_PK_UNKNOWN;
-  key->params_size = 0;
-  for (i = 0; i < params_len; i++)
-    _gnutls_mpi_release (&key->params[i]);
+  gnutls_pk_params_release(&key->params);
 
   return ret;
 }
@@ -1611,29 +1275,12 @@ gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t 
key,
       return GNUTLS_E_SHORT_MEMORY_BUFFER;
     }
 
-  if (key->pk_algorithm == GNUTLS_PK_RSA)
-    {
-      result =
-        _gnutls_x509_write_rsa_params (key->params, key->params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
-    }
-  else if (key->pk_algorithm == GNUTLS_PK_DSA)
+  result = _gnutls_x509_write_pubkey(key->pk_algorithm, &key->params, &der);
+  if (result < 0)
     {
-      result =
-        _gnutls_x509_write_dsa_public_key (key->params,
-                                           key->params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
+      gnutls_assert ();
+      goto cleanup;
     }
-  else
-    return GNUTLS_E_INTERNAL_ERROR;
 
   result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (result < 0)
@@ -1705,8 +1352,8 @@ _gnutls_x509_privkey_sign_hash2 (gnutls_x509_privkey_t 
signer,
       goto cleanup;
     }
 
-  ret = _gnutls_soft_sign (signer->pk_algorithm, signer->params,
-                           signer->params_size, &digest, signature);
+  ret = _gnutls_soft_sign (signer->pk_algorithm, &signer->params,
+                           &digest, signature);
 
   if (ret < 0)
     {
@@ -1750,8 +1397,8 @@ gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  result = _gnutls_soft_sign (key->pk_algorithm, key->params,
-                              key->params_size, hash, signature);
+  result = _gnutls_soft_sign (key->pk_algorithm, &key->params,
+                              hash, signature);
   if (result < 0)
     {
       gnutls_assert ();
@@ -1806,7 +1453,7 @@ gnutls_x509_privkey_sign_data (gnutls_x509_privkey_t key,
     }
 
   result =
-    pk_hash_data (key->pk_algorithm, digest, key->params, data, &hash);
+    pk_hash_data (key->pk_algorithm, digest, &key->params, data, &hash);
   if (result < 0)
     {
       gnutls_assert ();
@@ -1902,27 +1549,12 @@ gnutls_x509_privkey_fix (gnutls_x509_privkey_t key)
 
   if (!key->crippled)
     asn1_delete_structure (&key->key);
-  switch (key->pk_algorithm)
+
+  ret = _gnutls_asn1_encode_privkey (key->pk_algorithm, &key->key, 
&key->params);
+  if (ret < 0)
     {
-    case GNUTLS_PK_DSA:
-      ret = _gnutls_asn1_encode_dsa (&key->key, key->params);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-      break;
-    case GNUTLS_PK_RSA:
-      ret = _gnutls_asn1_encode_rsa (&key->key, key->params);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          return ret;
-        }
-      break;
-    default:
       gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
+      return ret;
     }
 
   return 0;
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 2659eeb..5ef565d 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -35,11 +35,13 @@
 #include <gnutls_x509.h>
 #include <x509_b64.h>
 #include "x509_int.h"
-#include <gnutls_algorithms.h>
+#include <algorithms.h>
 #include <gnutls_num.h>
 #include <random.h>
 #include <pbkdf2-sha1.h>
 
+static int _decode_pkcs8_ecc_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t 
pkey);
+
 #define PBES2_OID "1.2.840.113549.1.5.13"
 #define PBKDF2_OID "1.2.840.113549.1.5.12"
 #define DES_EDE3_CBC_OID "1.2.840.113549.3.7"
@@ -140,6 +142,7 @@ _encode_privkey (gnutls_x509_privkey_t pkey, gnutls_datum_t 
* raw)
   switch (pkey->pk_algorithm)
     {
     case GNUTLS_PK_RSA:
+    case GNUTLS_PK_ECC:
       ret =
         gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, NULL, &size);
       if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
@@ -178,7 +181,7 @@ _encode_privkey (gnutls_x509_privkey_t pkey, gnutls_datum_t 
* raw)
           return _gnutls_asn2err (ret);
         }
 
-      ret = _gnutls_x509_write_int (spk, "", pkey->params[4], 1);
+      ret = _gnutls_x509_write_int (spk, "", pkey->params.params[4], 1);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -223,30 +226,19 @@ encode_to_private_key_info (gnutls_x509_privkey_t pkey,
   gnutls_datum_t algo_params = { NULL, 0 };
   gnutls_datum_t algo_privkey = { NULL, 0 };
 
-  if (pkey->pk_algorithm != GNUTLS_PK_RSA
-      && pkey->pk_algorithm != GNUTLS_PK_DSA)
+  oid = _gnutls_x509_pk_to_oid(pkey->pk_algorithm);
+  if (oid == NULL)
     {
       gnutls_assert ();
       return GNUTLS_E_UNIMPLEMENTED_FEATURE;
     }
 
-  if (pkey->pk_algorithm == GNUTLS_PK_RSA)
-    {
-      oid = PK_PKIX1_RSA_OID;
-      /* parameters are null 
-       */
-    }
-  else
+  result =
+      _gnutls_x509_write_pubkey_params (pkey->pk_algorithm, &pkey->params, 
&algo_params);
+  if (result < 0)
     {
-      oid = PK_DSA_OID;
-      result =
-        _gnutls_x509_write_dsa_params (pkey->params, pkey->params_size,
-                                       &algo_params);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          return result;
-        }
+      gnutls_assert ();
+      return result;
     }
 
   if ((result =
@@ -986,6 +978,36 @@ error:
   return ret;
 }
 
+/* Decodes an ECC privateKey from a PKCS8 structure.
+ */
+static int
+_decode_pkcs8_ecc_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
+{
+  int ret;
+  gnutls_datum_t tmp;
+
+  ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto error;
+    }
+
+  pkey->key = _gnutls_privkey_decode_ecc_key (&tmp, pkey);
+  _gnutls_free_datum (&tmp);
+  if (pkey->key == NULL)
+    {
+      gnutls_assert ();
+      goto error;
+    }
+
+  return 0;
+
+error:
+  gnutls_x509_privkey_deinit (pkey);
+  return ret;
+}
+
 /* Decodes an DSA privateKey and params from a PKCS8 structure.
  */
 static int
@@ -1001,7 +1023,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
       goto error;
     }
 
-  ret = _gnutls_x509_read_der_int (tmp.data, tmp.size, &pkey->params[4]);
+  ret = _gnutls_x509_read_der_int (tmp.data, tmp.size, 
&pkey->params.params[4]);
   _gnutls_free_datum (&tmp);
 
   if (ret < 0)
@@ -1019,7 +1041,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
       goto error;
     }
 
-  ret = _gnutls_x509_read_dsa_params (tmp.data, tmp.size, pkey->params);
+  ret = _gnutls_x509_read_pubkey_params (GNUTLS_PK_DSA, tmp.data, tmp.size, 
&pkey->params);
   _gnutls_free_datum (&tmp);
   if (ret < 0)
     {
@@ -1028,19 +1050,19 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
     }
 
   /* the public key can be generated as g^x mod p */
-  pkey->params[3] = _gnutls_mpi_alloc_like (pkey->params[0]);
-  if (pkey->params[3] == NULL)
+  pkey->params.params[3] = _gnutls_mpi_alloc_like (pkey->params.params[0]);
+  if (pkey->params.params[3] == NULL)
     {
       gnutls_assert ();
       goto error;
     }
 
-  _gnutls_mpi_powm (pkey->params[3], pkey->params[2], pkey->params[4],
-                    pkey->params[0]);
+  _gnutls_mpi_powm (pkey->params.params[3], pkey->params.params[2], 
pkey->params.params[4],
+                    pkey->params.params[0]);
 
   if (!pkey->crippled)
     {
-      ret = _gnutls_asn1_encode_dsa (&pkey->key, pkey->params);
+      ret = _gnutls_asn1_encode_privkey (GNUTLS_PK_DSA, &pkey->key, 
&pkey->params);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -1048,7 +1070,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, 
gnutls_x509_privkey_t pkey)
         }
     }
 
-  pkey->params_size = DSA_PRIVATE_PARAMS;
+  pkey->params.params_nr = DSA_PRIVATE_PARAMS;
 
   return 0;
 
@@ -1099,11 +1121,9 @@ decode_private_key_info (const gnutls_datum_t * der,
 
   /* we only support RSA and DSA private keys.
    */
-  if (strcmp (oid, PK_PKIX1_RSA_OID) == 0)
-    pkey->pk_algorithm = GNUTLS_PK_RSA;
-  else if (strcmp (oid, PK_DSA_OID) == 0)
-    pkey->pk_algorithm = GNUTLS_PK_DSA;
-  else
+
+  pkey->pk_algorithm = _gnutls_x509_oid2pk_algorithm(oid);
+  if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
     {
       gnutls_assert ();
       _gnutls_debug_log
@@ -1119,6 +1139,9 @@ decode_private_key_info (const gnutls_datum_t * der,
     result = _decode_pkcs8_rsa_key (pkcs8_asn, pkey);
   else if (pkey->pk_algorithm == GNUTLS_PK_DSA)
     result = _decode_pkcs8_dsa_key (pkcs8_asn, pkey);
+  else if (pkey->pk_algorithm == GNUTLS_PK_ECC)
+    result = _decode_pkcs8_ecc_key (pkcs8_asn, pkey);
+  else return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
 
   if (result < 0)
     {
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 5a9db51..747405f 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -752,8 +752,8 @@ decode_ber_digest_info (const gnutls_datum_t * info,
 static int
 _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
                        const gnutls_datum_t * prehash,
-                       const gnutls_datum_t * signature, bigint_t * params,
-                       int params_len)
+                       const gnutls_datum_t * signature, 
+                       gnutls_pk_params_st * params)
 {
   gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
   int ret;
@@ -763,7 +763,7 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
   gnutls_datum_t decrypted;
 
   ret =
-    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1);
+    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, 1);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -829,8 +829,8 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
 static int
 dsa_verify_sig (const gnutls_datum_t * text,
                 const gnutls_datum_t * hash,
-                const gnutls_datum_t * signature, bigint_t * params,
-                int params_len)
+                const gnutls_datum_t * signature,
+                gnutls_pk_params_st* params)
 {
   int ret;
   opaque _digest[MAX_HASH_SIZE];
@@ -838,7 +838,7 @@ dsa_verify_sig (const gnutls_datum_t * text,
   digest_hd_st hd;
   gnutls_digest_algorithm_t algo;
 
-  algo = _gnutls_dsa_q_to_hash (params[1]);
+  algo = _gnutls_dsa_q_to_hash (params->params[1]);
   if (hash)
     {
       /* SHA1 or better allowed */
@@ -867,7 +867,7 @@ dsa_verify_sig (const gnutls_datum_t * text,
       digest.size = _gnutls_hash_get_algo_len(algo);
     }
 
-  ret = _gnutls_dsa_verify (&digest, signature, params, params_len);
+  ret = _gnutls_dsa_verify (&digest, signature, params);
 
   return ret;
 }
@@ -879,8 +879,8 @@ int
 pubkey_verify_sig (const gnutls_datum_t * tbs,
                    const gnutls_datum_t * hash,
                    const gnutls_datum_t * signature,
-                   gnutls_pk_algorithm_t pk, bigint_t * issuer_params,
-                   int issuer_params_size)
+                   gnutls_pk_algorithm_t pk,
+                   gnutls_pk_params_st * issuer_params)
 {
 
   switch (pk)
@@ -888,7 +888,7 @@ pubkey_verify_sig (const gnutls_datum_t * tbs,
     case GNUTLS_PK_RSA:
 
       if (_pkcs1_rsa_verify_sig
-          (tbs, hash, signature, issuer_params, issuer_params_size) != 0)
+          (tbs, hash, signature, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -899,7 +899,7 @@ pubkey_verify_sig (const gnutls_datum_t * tbs,
 
     case GNUTLS_PK_DSA:
       if (dsa_verify_sig
-          (tbs, hash, signature, issuer_params, issuer_params_size) != 0)
+          (tbs, hash, signature, issuer_params) != 0)
         {
           gnutls_assert ();
           return GNUTLS_E_PK_SIG_VERIFY_FAILED;
@@ -941,8 +941,7 @@ int
 _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
                                const gnutls_datum_t * signature,
                                gnutls_pk_algorithm_t pk,
-                               bigint_t * issuer_params,
-                               unsigned int issuer_params_size)
+                               gnutls_pk_params_st * issuer_params)
 {
   opaque digest[MAX_HASH_SIZE];
   gnutls_datum_t decrypted;
@@ -954,7 +953,7 @@ _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * 
hash,
     case GNUTLS_PK_DSA:
 
       if (hash)
-        *hash = _gnutls_dsa_q_to_hash (issuer_params[1]);
+        *hash = _gnutls_dsa_q_to_hash (issuer_params->params[1]);
 
       ret = 0;
       break;
@@ -968,7 +967,7 @@ _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * 
hash,
 
       ret =
         _gnutls_pkcs1_rsa_decrypt (&decrypted, signature,
-                                   issuer_params, issuer_params_size, 1);
+                                   issuer_params, 1);
 
 
       if (ret < 0)
@@ -1021,14 +1020,13 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * 
tbs,
                                const gnutls_datum_t * signature,
                                gnutls_x509_crt_t issuer)
 {
-  bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE];
-  int ret, issuer_params_size, i;
+  gnutls_pk_params_st issuer_params;
+  int ret;
 
   /* Read the MPI parameters from the issuer's certificate.
    */
-  issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
   ret =
-    _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size);
+    _gnutls_x509_crt_get_mpis (issuer, &issuer_params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1038,7 +1036,7 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
   ret =
     pubkey_verify_sig (tbs, hash, signature,
                        gnutls_x509_crt_get_pk_algorithm (issuer, NULL),
-                       issuer_params, issuer_params_size);
+                       &issuer_params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -1046,10 +1044,7 @@ _gnutls_x509_verify_signature (const gnutls_datum_t * 
tbs,
 
   /* release all allocated MPIs
    */
-  for (i = 0; i < issuer_params_size; i++)
-    {
-      _gnutls_mpi_release (&issuer_params[i]);
-    }
+  gnutls_pk_params_release(&issuer_params);
 
   return ret;
 }
@@ -1068,7 +1063,7 @@ _gnutls_x509_privkey_verify_signature (const 
gnutls_datum_t * tbs,
   int ret;
 
   ret = pubkey_verify_sig (tbs, NULL, signature, issuer->pk_algorithm,
-                           issuer->params, issuer->params_size);
+                           &issuer->params);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 020dc7d..810057a 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -881,6 +881,9 @@ gnutls_x509_crt_get_pk_algorithm (gnutls_x509_crt_t cert, 
unsigned int *bits)
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
     }
+  
+  if (bits)
+    *bits = 0;
 
   result =
     _gnutls_x509_get_pk_algorithm (cert->cert,
@@ -2187,8 +2190,8 @@ gnutls_x509_crt_export (gnutls_x509_crt_t cert,
 }
 
 int
-_gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t * params,
-                    int params_size, unsigned char *output_data,
+_gnutls_get_key_id (gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params,
+                    unsigned char *output_data,
                     size_t * output_data_size)
 {
   int result = 0;
@@ -2202,26 +2205,12 @@ _gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t 
* params,
       return GNUTLS_E_SHORT_MEMORY_BUFFER;
     }
 
-  if (pk == GNUTLS_PK_RSA)
-    {
-      result = _gnutls_x509_write_rsa_params (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
-    }
-  else if (pk == GNUTLS_PK_DSA)
+  result = _gnutls_x509_write_pubkey(pk, params, &der);
+  if (result < 0)
     {
-      result = _gnutls_x509_write_dsa_public_key (params, params_size, &der);
-      if (result < 0)
-        {
-          gnutls_assert ();
-          goto cleanup;
-        }
+      gnutls_assert ();
+      goto cleanup;
     }
-  else
-    return GNUTLS_E_INTERNAL_ERROR;
 
   result = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
   if (result < 0)
@@ -2248,11 +2237,10 @@ static int
 rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
                    unsigned char *output_data, size_t * output_data_size)
 {
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
-  int i, result = 0;
+  gnutls_pk_params_st params;
+  int result = 0;
 
-  result = _gnutls_x509_crt_get_mpis (crt, params, &params_size);
+  result = _gnutls_x509_crt_get_mpis (crt, &params);
   if (result < 0)
     {
       gnutls_assert ();
@@ -2260,7 +2248,7 @@ rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
     }
 
   result =
-    _gnutls_get_key_id (pk, params, params_size, output_data,
+    _gnutls_get_key_id (pk, &params, output_data,
                         output_data_size);
   if (result < 0)
     {
@@ -2274,10 +2262,7 @@ cleanup:
 
   /* release all allocated MPIs
    */
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return result;
 }
 
@@ -2521,9 +2506,8 @@ gnutls_x509_crt_get_verify_algorithm (gnutls_x509_crt_t 
crt,
                                       const gnutls_datum_t * signature,
                                       gnutls_digest_algorithm_t * hash)
 {
-  bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE];
-  int issuer_params_size;
-  int ret, i;
+  gnutls_pk_params_st issuer_params;
+  int ret;
 
   if (crt == NULL)
     {
@@ -2531,8 +2515,7 @@ gnutls_x509_crt_get_verify_algorithm (gnutls_x509_crt_t 
crt,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
-  ret = _gnutls_x509_crt_get_mpis (crt, issuer_params, &issuer_params_size);
+  ret = _gnutls_x509_crt_get_mpis (crt, &issuer_params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -2543,13 +2526,10 @@ gnutls_x509_crt_get_verify_algorithm (gnutls_x509_crt_t 
crt,
                                        signature,
                                        gnutls_x509_crt_get_pk_algorithm (crt,
                                                                          NULL),
-                                       issuer_params, issuer_params_size);
+                                       &issuer_params);
 
   /* release allocated mpis */
-  for (i = 0; i < issuer_params_size; i++)
-    {
-      _gnutls_mpi_release (&issuer_params[i]);
-    }
+  gnutls_pk_params_release(&issuer_params);
 
   return ret;
 }
@@ -2578,9 +2558,8 @@ gnutls_x509_crt_get_preferred_hash_algorithm 
(gnutls_x509_crt_t crt,
                                               gnutls_digest_algorithm_t *
                                               hash, unsigned int *mand)
 {
-  bigint_t issuer_params[MAX_PUBLIC_PARAMS_SIZE];
-  int issuer_params_size;
-  int ret, i;
+  gnutls_pk_params_st issuer_params;
+  int ret;
 
   if (crt == NULL)
     {
@@ -2588,8 +2567,7 @@ gnutls_x509_crt_get_preferred_hash_algorithm 
(gnutls_x509_crt_t crt,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
-  ret = _gnutls_x509_crt_get_mpis (crt, issuer_params, &issuer_params_size);
+  ret = _gnutls_x509_crt_get_mpis (crt, &issuer_params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -2598,14 +2576,11 @@ gnutls_x509_crt_get_preferred_hash_algorithm 
(gnutls_x509_crt_t crt,
 
   ret =
     _gnutls_pk_get_hash_algorithm (gnutls_x509_crt_get_pk_algorithm
-                                   (crt, NULL), issuer_params,
-                                   issuer_params_size, hash, mand);
+                                   (crt, NULL), &issuer_params,
+                                   hash, mand);
 
   /* release allocated mpis */
-  for (i = 0; i < issuer_params_size; i++)
-    {
-      _gnutls_mpi_release (&issuer_params[i]);
-    }
+  gnutls_pk_params_release(&issuer_params);
 
   return ret;
 }
@@ -2933,9 +2908,7 @@ gnutls_x509_crt_get_pk_rsa_raw (gnutls_x509_crt_t crt,
                                 gnutls_datum_t * m, gnutls_datum_t * e)
 {
   int ret;
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
-  int i;
+  gnutls_pk_params_st params;
 
   if (crt == NULL)
     {
@@ -2950,21 +2923,21 @@ gnutls_x509_crt_get_pk_rsa_raw (gnutls_x509_crt_t crt,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_x509_crt_get_mpis (crt, params, &params_size);
+  ret = _gnutls_x509_crt_get_mpis (crt, &params);
   if (ret < 0)
     {
       gnutls_assert ();
       return ret;
     }
 
-  ret = _gnutls_mpi_dprint_lz (params[0], m);
+  ret = _gnutls_mpi_dprint_lz (params.params[0], m);
   if (ret < 0)
     {
       gnutls_assert ();
       goto cleanup;
     }
 
-  ret = _gnutls_mpi_dprint_lz (params[1], e);
+  ret = _gnutls_mpi_dprint_lz (params.params[1], e);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -2975,10 +2948,7 @@ gnutls_x509_crt_get_pk_rsa_raw (gnutls_x509_crt_t crt,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 }
 
@@ -3002,9 +2972,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
                                 gnutls_datum_t * g, gnutls_datum_t * y)
 {
   int ret;
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
-  int i;
+  gnutls_pk_params_st params;
 
   if (crt == NULL)
     {
@@ -3019,7 +2987,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  ret = _gnutls_x509_crt_get_mpis (crt, params, &params_size);
+  ret = _gnutls_x509_crt_get_mpis (crt, &params);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -3028,7 +2996,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
 
 
   /* P */
-  ret = _gnutls_mpi_dprint_lz (params[0], p);
+  ret = _gnutls_mpi_dprint_lz (params.params[0], p);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -3036,7 +3004,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
     }
 
   /* Q */
-  ret = _gnutls_mpi_dprint_lz (params[1], q);
+  ret = _gnutls_mpi_dprint_lz (params.params[1], q);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -3046,7 +3014,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
 
 
   /* G */
-  ret = _gnutls_mpi_dprint_lz (params[2], g);
+  ret = _gnutls_mpi_dprint_lz (params.params[2], g);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -3057,7 +3025,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
 
 
   /* Y */
-  ret = _gnutls_mpi_dprint_lz (params[3], y);
+  ret = _gnutls_mpi_dprint_lz (params.params[3], y);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -3070,10 +3038,7 @@ gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt,
   ret = 0;
 
 cleanup:
-  for (i = 0; i < params_size; i++)
-    {
-      _gnutls_mpi_release (&params[i]);
-    }
+  gnutls_pk_params_release(&params);
   return ret;
 
 }
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index ce9faae..95132ff 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -78,7 +78,7 @@ typedef struct gnutls_pkcs7_int
 /* parameters should not be larger than this limit */
 #define DSA_PUBLIC_PARAMS 4
 #define RSA_PUBLIC_PARAMS 2
-#define ECDH_PUBLIC_PARAMS 8
+#define ECC_PUBLIC_PARAMS 8
 
 
 #define MAX_PRIV_PARAMS_SIZE GNUTLS_MAX_PK_PARAMS       /* ok for RSA and DSA 
*/
@@ -86,12 +86,16 @@ typedef struct gnutls_pkcs7_int
 /* parameters should not be larger than this limit */
 #define DSA_PRIVATE_PARAMS 5
 #define RSA_PRIVATE_PARAMS 8
-#define ECDH_PRIVATE_PARAMS 9
+#define ECC_PRIVATE_PARAMS 9
 
 #if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0
 #error INCREASE MAX_PRIV_PARAMS
 #endif
 
+#if MAX_PRIV_PARAMS_SIZE - ECC_PRIVATE_PARAMS < 0
+#error INCREASE MAX_PRIV_PARAMS
+#endif
+
 #if MAX_PRIV_PARAMS_SIZE - DSA_PRIVATE_PARAMS < 0
 #error INCREASE MAX_PRIV_PARAMS
 #endif
@@ -101,29 +105,7 @@ typedef struct gnutls_x509_privkey_int
   /* the size of params depends on the public
    * key algorithm
    */
-  bigint_t params[MAX_PRIV_PARAMS_SIZE];
-
-  /*
-   * RSA: [0] is modulus
-   *      [1] is public exponent
-   *      [2] is private exponent
-   *      [3] is prime1 (p)
-   *      [4] is prime2 (q)
-   *      [5] is coefficient (u == inverse of p mod q)
-   *          note that other packages used inverse of q mod p,
-   *          so we need to perform conversions on import/export
-   *          using fixup.
-   *      The following two are also not always available thus fixup
-   *      will generate them.
-   *      [6] e1 == d mod (p-1)
-   *      [7] e2 == d mod (q-1)
-   * DSA: [0] is p
-   *      [1] is q
-   *      [2] is g
-   *      [3] is y (public key)
-   *      [4] is x (private key)
-   */
-  int params_size;              /* holds the number of params */
+  gnutls_pk_params_st params;
 
   gnutls_pk_algorithm_t pk_algorithm;
 
@@ -198,8 +180,7 @@ int
 _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
                                const gnutls_datum_t * signature,
                                gnutls_pk_algorithm_t pk,
-                               bigint_t * issuer_params,
-                               unsigned int issuer_params_size);
+                               gnutls_pk_params_st * issuer_params);
 
 int _gnutls_x509_verify_signature (const gnutls_datum_t * tbs,
                                    const gnutls_datum_t * hash,
@@ -213,7 +194,10 @@ int _gnutls_x509_privkey_verify_signature (const 
gnutls_datum_t * tbs,
 ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t *
                                                 raw_key,
                                                 gnutls_x509_privkey_t pkey);
-int _gnutls_asn1_encode_dsa (ASN1_TYPE * c2, bigint_t * params);
+ASN1_TYPE _gnutls_privkey_decode_ecc_key (const gnutls_datum_t *
+                                                raw_key,
+                                                gnutls_x509_privkey_t pkey);
+int _gnutls_asn1_encode_privkey (gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, 
gnutls_pk_params_st * params);
 
 /* extensions.c */
 int _gnutls_x509_crl_get_extension (gnutls_x509_crl_t crl,
@@ -288,22 +272,22 @@ int _gnutls_x509_ext_gen_proxyCertInfo (int 
pathLenConstraint,
 
 /* mpi.c */
 int _gnutls_x509_crq_get_mpis (gnutls_x509_crq_t cert,
-                               bigint_t * params, int *params_size);
+                               gnutls_pk_params_st*);
 
 int _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert,
-                               bigint_t * params, int *params_size);
-int _gnutls_x509_read_rsa_params (opaque * der, int dersize,
-                                  bigint_t * params);
-int _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize,
-                                  bigint_t * params);
-int _gnutls_x509_read_dsa_params (opaque * der, int dersize,
-                                  bigint_t * params);
-
-int _gnutls_x509_write_rsa_params (bigint_t * params, int params_size,
-                                   gnutls_datum_t * der);
-int _gnutls_x509_write_dsa_params (bigint_t * params, int params_size,
+                               gnutls_pk_params_st * params);
+
+int _gnutls_x509_read_pubkey_params (gnutls_pk_algorithm_t, opaque * der, int 
dersize,
+                                  gnutls_pk_params_st * params);
+
+int _gnutls_x509_read_pubkey (gnutls_pk_algorithm_t, opaque * der, int dersize,
+                                  gnutls_pk_params_st * params);
+
+int
+_gnutls_x509_write_pubkey_params (gnutls_pk_algorithm_t algo,
+                                   gnutls_pk_params_st* params,
                                    gnutls_datum_t * der);
-int _gnutls_x509_write_dsa_public_key (bigint_t * params, int params_size,
+int _gnutls_x509_write_pubkey (gnutls_pk_algorithm_t, gnutls_pk_params_st * 
params,
                                        gnutls_datum_t * der);
 
 int _gnutls_x509_read_uint (ASN1_TYPE node, const char *value,
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index 68f0103..45c3e74 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -233,8 +233,7 @@ gnutls_x509_crt_set_key (gnutls_x509_crt_t crt, 
gnutls_x509_privkey_t key)
   result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert,
                                                     
"tbsCertificate.subjectPublicKeyInfo",
                                                     key->pk_algorithm,
-                                                    key->params,
-                                                    key->params_size);
+                                                    &key->params);
 
   if (result < 0)
     {


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]