From 68884e3c0964ae6da67919e5f2d86ec4c58fd96d Mon Sep 17 00:00:00 2001
From: Paul Bakker <p.j.bakker@polarssl.org>
Date: Mon, 7 Jan 2013 18:20:04 +0100
Subject: [PATCH] Moved to advanced ciphersuite representation and more dynamic
 SSL code

---
 ChangeLog                           |    4 +
 include/polarssl/cipher.h           |   13 +-
 include/polarssl/cipher_wrap.h      |   11 +-
 include/polarssl/ssl.h              |   20 +-
 include/polarssl/ssl_ciphersuites.h |   76 ++
 library/CMakeLists.txt              |    1 +
 library/Makefile                    |    2 +-
 library/cipher.c                    |   35 +-
 library/cipher_wrap.c               |   61 +-
 library/ssl_ciphersuites.c          |  408 +++++++++
 library/ssl_cli.c                   |   38 +-
 library/ssl_srv.c                   |   40 +-
 library/ssl_tls.c                   | 1191 +++++++--------------------
 programs/test/ssl_test.c            |    7 +-
 programs/x509/cert_app.c            |    4 +-
 15 files changed, 947 insertions(+), 964 deletions(-)
 create mode 100644 include/polarssl/ssl_ciphersuites.h
 create mode 100644 library/ssl_ciphersuites.c

diff --git a/ChangeLog b/ChangeLog
index eaec163b6..59a43dcb4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@ PolarSSL ChangeLog
 
 = Development
 Changes
+   * Introduced separate SSL Ciphersuites module that is based on
+     Cipher and MD information
    * Internals for SSL module adapted to have separate IV pointer that is
      dynamically set (Better support for hardware acceleration)
 
@@ -47,6 +49,8 @@ Security
 
 = Version 1.2.4 released 2013-01-25
 Changes
+   * More advanced SSL ciphersuite representation and moved to more dynamic
+     SSL core
    * Added ssl_handshake_step() to allow single stepping the handshake process
 
 Bugfix
diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h
index 8224128e3..2ffdf668f 100644
--- a/include/polarssl/cipher.h
+++ b/include/polarssl/cipher.h
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -54,6 +54,7 @@ typedef enum {
     POLARSSL_CIPHER_ID_3DES,
     POLARSSL_CIPHER_ID_CAMELLIA,
     POLARSSL_CIPHER_ID_BLOWFISH,
+    POLARSSL_CIPHER_ID_ARC4,
 } cipher_id_t;
 
 typedef enum {
@@ -68,6 +69,8 @@ typedef enum {
     POLARSSL_CIPHER_AES_128_CTR,
     POLARSSL_CIPHER_AES_192_CTR,
     POLARSSL_CIPHER_AES_256_CTR,
+    POLARSSL_CIPHER_AES_128_GCM,
+    POLARSSL_CIPHER_AES_256_GCM,
     POLARSSL_CIPHER_CAMELLIA_128_CBC,
     POLARSSL_CIPHER_CAMELLIA_192_CBC,
     POLARSSL_CIPHER_CAMELLIA_256_CBC,
@@ -83,6 +86,7 @@ typedef enum {
     POLARSSL_CIPHER_BLOWFISH_CBC,
     POLARSSL_CIPHER_BLOWFISH_CFB64,
     POLARSSL_CIPHER_BLOWFISH_CTR,
+    POLARSSL_CIPHER_ARC4_128,
 } cipher_type_t;
 
 typedef enum {
@@ -92,6 +96,8 @@ typedef enum {
     POLARSSL_MODE_CFB,
     POLARSSL_MODE_OFB,
     POLARSSL_MODE_CTR,
+    POLARSSL_MODE_GCM,
+    POLARSSL_MODE_STREAM,
 } cipher_mode_t;
 
 typedef enum {
@@ -351,10 +357,10 @@ static inline const char *cipher_get_name( const cipher_context_t *ctx )
  */
 static inline int cipher_get_key_size ( const cipher_context_t *ctx )
 {
-    if( NULL == ctx )
+    if( NULL == ctx || NULL == ctx->cipher_info )
         return POLARSSL_KEY_LENGTH_NONE;
 
-    return ctx->key_length;
+    return ctx->cipher_info->key_length;
 }
 
 /**
@@ -448,7 +454,6 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
  */
 int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen);
 
-
 /**
  * \brief          Checkup routine
  *
diff --git a/include/polarssl/cipher_wrap.h b/include/polarssl/cipher_wrap.h
index 4abbc4ef2..4dabb44ee 100644
--- a/include/polarssl/cipher_wrap.h
+++ b/include/polarssl/cipher_wrap.h
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -54,6 +54,11 @@ extern const cipher_info_t aes_192_ctr_info;
 extern const cipher_info_t aes_256_ctr_info;
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
+#if defined(POLARSSL_GCM_C)
+extern const cipher_info_t aes_128_gcm_info;
+extern const cipher_info_t aes_256_gcm_info;
+#endif /* POLARSSL_GCM_C */
+
 #endif /* defined(POLARSSL_AES_C) */
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -96,6 +101,10 @@ extern const cipher_info_t blowfish_ctr_info;
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 #endif /* defined(POLARSSL_BLOWFISH_C) */
 
+#if defined(POLARSSL_ARC4_C)
+extern const cipher_info_t arc4_128_info;
+#endif /* defined(POLARSSL_ARC4_C) */
+
 #if defined(POLARSSL_CIPHER_NULL_CIPHER)
 extern const cipher_info_t null_cipher_info;
 #endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index c2ecbaf72..756441c8e 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -3,7 +3,7 @@
  *
  * \brief SSL/TLS functions.
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -37,6 +37,7 @@
 #include "sha4.h"
 #include "x509.h"
 #include "config.h"
+#include "ssl_ciphersuites.h"
 
 #if defined(POLARSSL_DHM_C)
 #include "dhm.h"
@@ -323,6 +324,8 @@ struct _ssl_transform
     /*
      * Session specific crypto layer
      */
+    const ssl_ciphersuite_t *ciphersuite_info;
+                                        /*!<  Chosen cipersuite_info  */
     unsigned int keylen;                /*!<  symmetric key length    */
     size_t minlen;                      /*!<  min. ciphertext length  */
     size_t ivlen;                       /*!<  IV length               */
@@ -332,8 +335,12 @@ struct _ssl_transform
     unsigned char iv_enc[16];           /*!<  IV (encryption)         */
     unsigned char iv_dec[16];           /*!<  IV (decryption)         */
 
-    unsigned char mac_enc[32];          /*!<  MAC (encryption)        */
-    unsigned char mac_dec[32];          /*!<  MAC (decryption)        */
+    /* Needed only for SSL v3.0 secret */
+    unsigned char mac_enc[32];          /*!<  SSL v3.0 secret (enc)   */
+    unsigned char mac_dec[32];          /*!<  SSL v3.0 secret (dec)   */
+
+    md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */
+    md_context_t md_ctx_dec;            /*!<  MAC (decryption)        */
 
     uint32_t ctx_enc[136];              /*!<  encryption context      */
     uint32_t ctx_dec[136];              /*!<  decryption context      */
@@ -520,8 +527,6 @@ struct _ssl_context
 extern "C" {
 #endif
 
-extern const int ssl_default_ciphersuites[];
-
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
 
 #define SSL_CHANNEL_OUTBOUND    0
@@ -547,10 +552,7 @@ extern int (*ssl_hw_record_finish)(ssl_context *ssl);
  * \return              a statically allocated array of ciphersuites, the last
  *                      entry is 0.
  */
-static inline const int *ssl_list_ciphersuites( void )
-{
-    return ssl_default_ciphersuites;
-}
+const int *ssl_list_ciphersuites( void );
 
 /**
  * \brief               Return the name of the ciphersuite associated with the given
diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h
new file mode 100644
index 000000000..62a928e87
--- /dev/null
+++ b/include/polarssl/ssl_ciphersuites.h
@@ -0,0 +1,76 @@
+/**
+ * \file ssl_ciphersuites.h
+ *
+ * \brief SSL Ciphersuites for PolarSSL
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_CIPHERSUITES_H
+#define POLARSSL_SSL_CIPHERSUITES_H
+
+#include "cipher.h"
+#include "md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    POLARSSL_KEY_EXCHANGE_NONE = 0,
+    POLARSSL_KEY_EXCHANGE_RSA,
+    POLARSSL_KEY_EXCHANGE_DHE_RSA
+} key_exchange_type_t;
+
+typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t;
+
+#define POLARSSL_CIPHERSUITE_WEAK   0x01
+
+/**
+ * \brief   This structure is used for storing ciphersuite information
+ */
+struct _ssl_ciphersuite_t
+{
+    int id;
+    const char * name;
+
+    cipher_type_t cipher;
+    md_type_t mac;
+    key_exchange_type_t key_exchange;
+
+    int min_major_ver;
+    int min_minor_ver;
+    int max_major_ver;
+    int max_minor_ver;
+
+    unsigned char flags;
+};
+
+const int *ssl_ciphersuites_list( void );
+
+const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name );
+const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite_id );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl_ciphersuites.h */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 25802d7b5..1ddd44e23 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -36,6 +36,7 @@ set(src
      sha2.c
      sha4.c
      ssl_cache.c
+     ssl_ciphersuites.c
      ssl_cli.c 
      ssl_srv.c 
      ssl_tls.c
diff --git a/library/Makefile b/library/Makefile
index 603f5d16e..2fcbce096 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -47,7 +47,7 @@ OBJS=	aes.o		arc4.o		asn1parse.o		\
 		pkcs11.o								\
 		rsa.o		sha1.o		sha2.o			\
 		sha4.o		ssl_cache.o	ssl_cli.o		\
-		ssl_srv.o								\
+		ssl_srv.o   ssl_ciphersuites.o			\
 		ssl_tls.o	timing.o	version.o		\
 		x509parse.o	x509write.o	xtea.o
 
diff --git a/library/cipher.c b/library/cipher.c
index f20cc73b4..2a2d78299 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -142,6 +142,13 @@ const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
             return &aes_256_ctr_info;
 #endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
 
+#if defined(POLARSSL_GCM_C)
+        case POLARSSL_CIPHER_AES_128_GCM:
+            return &aes_128_gcm_info;
+        case POLARSSL_CIPHER_AES_256_GCM:
+            return &aes_256_gcm_info;
+#endif /* defined(POLARSSL_GCM_C) */
+
 #endif
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -181,6 +188,11 @@ const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
             return &des_ede3_cbc_info;
 #endif
 
+#if defined(POLARSSL_ARC4_C)
+        case POLARSSL_CIPHER_ARC4_128:
+            return &arc4_128_info;
+#endif
+
 #if defined(POLARSSL_BLOWFISH_C)
         case POLARSSL_CIPHER_BLOWFISH_CBC:
             return &blowfish_cbc_info;
@@ -374,19 +386,28 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
     int ret;
     size_t copy_len = 0;
 
-    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ||
-        input == output )
+    *olen = 0;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
     {
         return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    *olen = 0;
+    if( input == output &&
+       ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(POLARSSL_CIPHER_NULL_CIPHER)
     if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
     {
-        memcpy( output, input, ilen );
         *olen = ilen;
+
+        if( output == input )
+            return( 0 );
+
+        memcpy( output, input, ilen );
         return 0;
     }
 #endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
@@ -465,6 +486,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
         return 0;
     }
 
+#if defined(POLARSSL_CIPHER_MODE_CFB)
     if( ctx->cipher_info->mode == POLARSSL_MODE_CFB )
     {
         if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
@@ -478,7 +500,9 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
 
         return 0;
     }
+#endif
 
+#if defined(POLARSSL_CIPHER_MODE_CTR)
     if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
     {
         if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
@@ -492,6 +516,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
 
         return 0;
     }
+#endif
 
     return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index 611112f0d..7ee217885 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -222,6 +222,28 @@ const cipher_info_t aes_256_ctr_info = {
 };
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
+#if defined(POLARSSL_GCM_C)
+const cipher_info_t aes_128_gcm_info = {
+    POLARSSL_CIPHER_AES_128_GCM,
+    POLARSSL_MODE_GCM,
+    128,
+    "AES-128-GCM",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_gcm_info = {
+    POLARSSL_CIPHER_AES_256_GCM,
+    POLARSSL_MODE_GCM,
+    256,
+    "AES-256-GCM",
+    16,
+    16,
+    &aes_info
+};
+#endif /* POLARSSL_GCM_C */
+
 #endif
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -440,7 +462,6 @@ static int des_crypt_ctr_wrap( void *ctx, size_t length,
     return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 
-
 static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
 {
     ((void) key_length);
@@ -674,6 +695,40 @@ const cipher_info_t blowfish_ctr_info = {
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 #endif /* POLARSSL_BLOWFISH_C */
 
+#if defined(POLARSSL_ARC4_C)
+static void * arc4_ctx_alloc( void )
+{
+    return (void *) 1;
+}
+
+
+static void arc4_ctx_free( void *ctx )
+{
+    ((void) ctx);
+}
+
+const cipher_base_t arc4_base_info = {
+    POLARSSL_CIPHER_ID_ARC4,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    arc4_ctx_alloc,
+    arc4_ctx_free
+};
+
+const cipher_info_t arc4_128_info = {
+    POLARSSL_CIPHER_ARC4_128,
+    POLARSSL_MODE_STREAM,
+    128,
+    "ARC4-128",
+    0,
+    1,
+    &arc4_base_info
+};
+#endif /* POLARSSL_ARC4_C */
+
 #if defined(POLARSSL_CIPHER_NULL_CIPHER)
 static void * null_ctx_alloc( void )
 {
@@ -702,7 +757,7 @@ const cipher_info_t null_cipher_info = {
     POLARSSL_MODE_NULL,
     0,
     "NULL",
-    1,
+    0,
     1,
     &null_base_info
 };
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
new file mode 100644
index 000000000..0218194f3
--- /dev/null
+++ b/library/ssl_ciphersuites.c
@@ -0,0 +1,408 @@
+/**
+ * \file ssl_ciphersuites.c
+ *
+ * \brief SSL ciphersuites for PolarSSL
+ *
+ *  Copyright (C) 2006-2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_TLS_C)
+
+#include "polarssl/ssl_ciphersuites.h"
+#include "polarssl/ssl.h"
+
+#include <stdlib.h>
+
+const int supported_ciphersuites[] =
+{
+#if defined(POLARSSL_DHM_C)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+#endif
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+#if defined(POLARSSL_SHA2_C)
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+#endif
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+#endif /* POLARSSL_AES_C */
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+#if defined(POLARSSL_SHA2_C)
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+#endif /* POLARSSL_CAMELLIA_C */
+#if defined(POLARSSL_DES_C)
+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+    TLS_RSA_WITH_AES_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+    TLS_RSA_WITH_AES_256_GCM_SHA384,
+#endif
+    TLS_RSA_WITH_AES_256_CBC_SHA,
+#endif /* POLARSSL_AES_C */
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+#endif /* POLARSSL_CAMELLIA_C */
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+    TLS_RSA_WITH_AES_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+    TLS_RSA_WITH_AES_128_GCM_SHA256,
+#endif /* POLARSSL_SHA2_C */
+    TLS_RSA_WITH_AES_128_CBC_SHA,
+#endif /* POLARSSL_AES_C */
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+#endif /* POLARSSL_SHA2_C */
+    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+#endif /* POLARSSL_CAMELLIA_C */
+#if defined(POLARSSL_DES_C)
+    TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif /* POLARSSL_DES_C */
+#if defined(POLARSSL_ARC4_C)
+    TLS_RSA_WITH_RC4_128_SHA,
+    TLS_RSA_WITH_RC4_128_MD5,
+#endif /* POLARSSL_ARC4_C */
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_DHM_C)
+    TLS_DHE_RSA_WITH_DES_CBC_SHA,
+#endif /* POLARSSL_DHM_C */
+    TLS_RSA_WITH_DES_CBC_SHA,
+#endif /* POLARSSL_DES_C */
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA2_C)
+    TLS_RSA_WITH_NULL_SHA256,
+#endif
+    TLS_RSA_WITH_NULL_SHA,
+    TLS_RSA_WITH_NULL_MD5,
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */
+    0
+};
+
+static const ssl_ciphersuite_t ciphersuite_definitions[] =
+{
+#if defined(POLARSSL_ARC4_C)
+    { TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_DHM_C)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA4_C) && defined(POLARSSL_GCM_C)
+    { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA4_C && POLARSSL_GCM_C */
+
+#if defined(POLARSSL_SHA2_C)
+#if defined(POLARSSL_GCM_C)
+    { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+
+    { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA2_C */
+
+    { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+    { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA2_C */
+
+    { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+    { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_DES_C */
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA4_C) && defined(POLARSSL_GCM_C)
+    { TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA4_C && POLARSSL_GCM_C */
+
+#if defined(POLARSSL_SHA2_C)
+#if defined(POLARSSL_GCM_C)
+    { TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+
+    { TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA2_C */
+
+    { TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+    { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA2_C */
+
+    { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+
+    { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+    { TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    { TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_MD5, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+
+    { TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+
+    { TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_DHM_C)
+    { TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA",
+      POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_DHM_C */
+
+    { TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA",
+      POLARSSL_CIPHER_DES_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_DES_C */
+
+#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */
+
+    { 0, "", 0, 0, 0, 0, 0, 0, 0, 0 }
+};
+
+const int *ssl_list_ciphersuites( void )
+{
+    return supported_ciphersuites;
+};
+
+const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name )
+{
+    const ssl_ciphersuite_t *cur = ciphersuite_definitions;
+
+    if( NULL == ciphersuite_name )
+        return( NULL );
+
+    while( cur->id != 0 )
+    {
+        if( 0 == strcasecmp( cur->name, ciphersuite_name ) )
+            return( cur );
+
+        cur++;
+    }
+
+    return( NULL );
+}
+
+const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite )
+{
+    const ssl_ciphersuite_t *cur = ciphersuite_definitions;
+
+    while( cur->id != 0 )
+    {
+        if( cur->id == ciphersuite )
+            return( cur );
+
+        cur++;
+    }
+
+    return( NULL );
+}
+
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
+{
+    const ssl_ciphersuite_t *cur;
+
+    cur = ssl_ciphersuite_from_id( ciphersuite_id );
+
+    if( cur == NULL )
+        return( "unknown" );
+
+    return( cur->name );
+}
+
+int ssl_get_ciphersuite_id( const char *ciphersuite_name )
+{
+    const ssl_ciphersuite_t *cur;
+
+    cur = ssl_ciphersuite_from_string( ciphersuite_name );
+
+    if( cur == NULL )
+        return( 0 );
+
+    return( cur->id );
+}
+
+#endif
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 545906a2a..c426fa875 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1,7 +1,7 @@
 /*
  *  SSLv3/TLSv1 client-side functions
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -473,6 +473,14 @@ static int ssl_parse_server_hello( ssl_context *ssl )
      * Initialize update checksum functions
      */
     ssl_optimize_checksum( ssl, i );
+    ssl->transform_negotiate->ciphersuite_info = ssl_ciphersuite_from_id( i );
+
+    if( ssl->transform_negotiate->ciphersuite_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found",
+                          ssl->ciphersuites[i] ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
 
     SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
     SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
@@ -636,18 +644,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
 
-    if( ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_DES_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+    if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
+        POLARSSL_KEY_EXCHANGE_DHE_RSA )
     {
         SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
         ssl->state++;
@@ -1044,18 +1042,8 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
 
-    if( ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+    if( ssl->transform_negotiate->ciphersuite_info->key_exchange ==
+        POLARSSL_KEY_EXCHANGE_DHE_RSA )
     {
 #if !defined(POLARSSL_DHM_C)
         SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 325440d9d..c5788ace4 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1,7 +1,7 @@
 /*
  *  SSLv3/TLSv1 server-side functions
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -658,6 +658,16 @@ static int ssl_parse_client_hello( ssl_context *ssl )
 
 have_ciphersuite:
     ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i];
+    ssl->transform_negotiate->ciphersuite_info =
+        ssl_ciphersuite_from_id( ssl->ciphersuites[i] );
+
+    if( ssl->transform_negotiate->ciphersuite_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found",
+                          ssl->ciphersuites[i] ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
     ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite );
 
     ext = buf + 44 + sess_len + ciph_len + comp_len;
@@ -1011,18 +1021,8 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
 
-    if( ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_DES_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 &&
-        ssl->session_negotiate->ciphersuite != TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+    if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
+        POLARSSL_KEY_EXCHANGE_DHE_RSA )
     {
         SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
         ssl->state++;
@@ -1288,18 +1288,8 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
     }
 
-    if( ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
-        ssl->session_negotiate->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+    if( ssl->transform_negotiate->ciphersuite_info->key_exchange ==
+        POLARSSL_KEY_EXCHANGE_DHE_RSA )
     {
 #if !defined(POLARSSL_DHM_C)
         SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 5e2d1ef04..08880beb2 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1,7 +1,7 @@
 /*
  *  SSLv3/TLSv1 shared functions
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -302,13 +302,34 @@ int ssl_derive_keys( ssl_context *ssl )
     unsigned char keyblk[256];
     unsigned char *key1;
     unsigned char *key2;
+    unsigned char *mac_enc;
+    unsigned char *mac_dec;
     unsigned int iv_copy_len;
+    const cipher_info_t *cipher_info;
+    const md_info_t *md_info;
+
     ssl_session *session = ssl->session_negotiate;
     ssl_transform *transform = ssl->transform_negotiate;
     ssl_handshake_params *handshake = ssl->handshake;
 
     SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
 
+    cipher_info = cipher_info_from_type( transform->ciphersuite_info->cipher );
+    if( cipher_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", 
+                            transform->ciphersuite_info->cipher ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    md_info = md_info_from_type( transform->ciphersuite_info->mac );
+    if( md_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "md info for %d not found", 
+                            transform->ciphersuite_info->mac ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
     /*
      * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
      */
@@ -398,130 +419,38 @@ int ssl_derive_keys( ssl_context *ssl )
     /*
      * Determine the appropriate key, IV and MAC length.
      */
-    switch( session->ciphersuite )
+
+    if( cipher_info->mode == POLARSSL_MODE_GCM )
     {
-#if defined(POLARSSL_ARC4_C)
-        case TLS_RSA_WITH_RC4_128_MD5:
-            transform->keylen = 16; transform->minlen = 16;
-            transform->ivlen  =  0; transform->maclen = 16;
-            break;
+        transform->keylen = cipher_info->key_length;
+        transform->keylen /= 8;
+        transform->minlen = 1;
+        transform->ivlen = 12;
+        transform->fixed_ivlen = 4;
+        transform->maclen = 0;
+    }
+    else
+    {
+        if( md_info->type != POLARSSL_MD_NONE )
+        {
+            md_init_ctx( &transform->md_ctx_enc, md_info );
+            md_init_ctx( &transform->md_ctx_dec, md_info );
 
-        case TLS_RSA_WITH_RC4_128_SHA:
-            transform->keylen = 16; transform->minlen = 20;
-            transform->ivlen  =  0; transform->maclen = 20;
-            break;
-#endif
+            transform->maclen = md_get_size( md_info );
+        }
 
-#if defined(POLARSSL_DES_C)
-        case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-        case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            transform->keylen = 24; transform->minlen = 24;
-            transform->ivlen  =  8; transform->maclen = 20;
-            break;
-#endif
+        transform->keylen = cipher_info->key_length;
+        transform->keylen /= 8;
+        transform->ivlen = cipher_info->iv_size;
 
-#if defined(POLARSSL_AES_C)
-        case TLS_RSA_WITH_AES_128_CBC_SHA:
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            transform->keylen = 16; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 20;
-            break;
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA:
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            transform->keylen = 32; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 20;
-            break;
-
-#if defined(POLARSSL_SHA2_C)
-        case TLS_RSA_WITH_AES_128_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            transform->keylen = 16; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 32;
-            break;
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            transform->keylen = 32; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 32;
-            break;
-#endif
-#if defined(POLARSSL_GCM_C)
-        case TLS_RSA_WITH_AES_128_GCM_SHA256:
-        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            transform->keylen = 16; transform->minlen = 1;
-            transform->ivlen  = 12; transform->maclen = 0;
-            transform->fixed_ivlen = 4;
-            break;
-
-        case TLS_RSA_WITH_AES_256_GCM_SHA384:
-        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            transform->keylen = 32; transform->minlen = 1;
-            transform->ivlen  = 12; transform->maclen = 0;
-            transform->fixed_ivlen = 4;
-            break;
-#endif
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            transform->keylen = 16; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 20;
-            break;
-
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            transform->keylen = 32; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 20;
-            break;
-
-#if defined(POLARSSL_SHA2_C)
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            transform->keylen = 16; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 32;
-            break;
-
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            transform->keylen = 32; transform->minlen = 32;
-            transform->ivlen  = 16; transform->maclen = 32;
-            break;
-#endif
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-        case TLS_RSA_WITH_NULL_MD5:
-            transform->keylen = 0; transform->minlen = 0;
-            transform->ivlen  = 0; transform->maclen = 16;
-            break;
-
-        case TLS_RSA_WITH_NULL_SHA:
-            transform->keylen = 0; transform->minlen = 0;
-            transform->ivlen  = 0; transform->maclen = 20;
-            break;
-
-        case TLS_RSA_WITH_NULL_SHA256:
-            transform->keylen = 0; transform->minlen = 0;
-            transform->ivlen  = 0; transform->maclen = 32;
-            break;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
-        case TLS_RSA_WITH_DES_CBC_SHA:
-        case TLS_DHE_RSA_WITH_DES_CBC_SHA:
-            transform->keylen =  8; transform->minlen = 8;
-            transform->ivlen  =  8; transform->maclen = 20;
-            break;
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
-        default:
-            SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available",
-                           ssl_get_ciphersuite_name( session->ciphersuite ) ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        transform->minlen = transform->keylen;
+        if( transform->minlen < transform->maclen )
+        {
+            if( cipher_info->mode == POLARSSL_MODE_STREAM )
+                transform->minlen = transform->maclen;
+            else
+                transform->minlen += transform->keylen;
+        }
     }
 
     SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
@@ -536,9 +465,8 @@ int ssl_derive_keys( ssl_context *ssl )
         key1 = keyblk + transform->maclen * 2;
         key2 = keyblk + transform->maclen * 2 + transform->keylen;
 
-        memcpy( transform->mac_enc, keyblk,  transform->maclen );
-        memcpy( transform->mac_dec, keyblk + transform->maclen,
-                transform->maclen );
+        mac_enc = keyblk;
+        mac_dec = keyblk + transform->maclen;
 
         /*
          * This is not used in TLS v1.1.
@@ -554,9 +482,8 @@ int ssl_derive_keys( ssl_context *ssl )
         key1 = keyblk + transform->maclen * 2 + transform->keylen;
         key2 = keyblk + transform->maclen * 2;
 
-        memcpy( transform->mac_dec, keyblk,  transform->maclen );
-        memcpy( transform->mac_enc, keyblk + transform->maclen,
-                transform->maclen );
+        mac_enc = keyblk + transform->maclen;
+        mac_dec = keyblk;
 
         /*
          * This is not used in TLS v1.1.
@@ -568,6 +495,17 @@ int ssl_derive_keys( ssl_context *ssl )
                 iv_copy_len );
     }
 
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        memcpy( transform->mac_enc, mac_enc, transform->maclen );
+        memcpy( transform->mac_dec, mac_dec, transform->maclen );
+    }
+    else
+    {
+        md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen );
+        md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen );
+    }
+
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
     if( ssl_hw_record_init != NULL)
     {
@@ -578,7 +516,7 @@ int ssl_derive_keys( ssl_context *ssl )
         if( ( ret = ssl_hw_record_init( ssl, key1, key2, transform->keylen,
                                         transform->iv_enc, transform->iv_dec,
                                         iv_copy_len,
-                                        transform->mac_enc, transform->mac_dec,
+                                        mac_enc, mac_dec,
                                         transform->maclen ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret );
@@ -587,11 +525,10 @@ int ssl_derive_keys( ssl_context *ssl )
     }
 #endif
 
-    switch( session->ciphersuite )
+    switch( cipher_info->type )
     {
 #if defined(POLARSSL_ARC4_C)
-        case TLS_RSA_WITH_RC4_128_MD5:
-        case TLS_RSA_WITH_RC4_128_SHA:
+        case POLARSSL_CIPHER_ARC4_128:
             arc4_setup( (arc4_context *) transform->ctx_enc, key1,
                         transform->keylen );
             arc4_setup( (arc4_context *) transform->ctx_dec, key2,
@@ -600,79 +537,51 @@ int ssl_derive_keys( ssl_context *ssl )
 #endif
 
 #if defined(POLARSSL_DES_C)
-        case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-        case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            des3_set3key_enc( (des3_context *) transform->ctx_enc, key1 );
-            des3_set3key_dec( (des3_context *) transform->ctx_dec, key2 );
-            break;
+        case POLARSSL_CIPHER_DES_EDE3_CBC:
+             des3_set3key_enc( (des3_context *) transform->ctx_enc, key1 );
+             des3_set3key_dec( (des3_context *) transform->ctx_dec, key2 );
+             break;
 #endif
 
 #if defined(POLARSSL_AES_C)
-        case TLS_RSA_WITH_AES_128_CBC_SHA:
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-        case TLS_RSA_WITH_AES_128_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            aes_setkey_enc( (aes_context *) transform->ctx_enc, key1, 128 );
-            aes_setkey_dec( (aes_context *) transform->ctx_dec, key2, 128 );
+        case POLARSSL_CIPHER_AES_128_CBC:
+        case POLARSSL_CIPHER_AES_256_CBC:
+            aes_setkey_enc( (aes_context*) transform->ctx_enc, key1,
+                            cipher_info->key_length );
+            aes_setkey_dec( (aes_context*) transform->ctx_dec, key2,
+                            cipher_info->key_length );
             break;
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA:
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-        case TLS_RSA_WITH_AES_256_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            aes_setkey_enc( (aes_context *) transform->ctx_enc, key1, 256 );
-            aes_setkey_dec( (aes_context *) transform->ctx_dec, key2, 256 );
-            break;
-
-#if defined(POLARSSL_GCM_C)
-        case TLS_RSA_WITH_AES_128_GCM_SHA256:
-        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            gcm_init( (gcm_context *) transform->ctx_enc, key1, 128 );
-            gcm_init( (gcm_context *) transform->ctx_dec, key2, 128 );
-            break;
-
-        case TLS_RSA_WITH_AES_256_GCM_SHA384:
-        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            gcm_init( (gcm_context *) transform->ctx_enc, key1, 256 );
-            gcm_init( (gcm_context *) transform->ctx_dec, key2, 256 );
-            break;
-#endif
 #endif
 
 #if defined(POLARSSL_CAMELLIA_C)
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            camellia_setkey_enc( (camellia_context *) transform->ctx_enc, key1, 128 );
-            camellia_setkey_dec( (camellia_context *) transform->ctx_dec, key2, 128 );
-            break;
-
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            camellia_setkey_enc( (camellia_context *) transform->ctx_enc, key1, 256 );
-            camellia_setkey_dec( (camellia_context *) transform->ctx_dec, key2, 256 );
+        case POLARSSL_CIPHER_CAMELLIA_128_CBC:
+        case POLARSSL_CIPHER_CAMELLIA_256_CBC:
+            camellia_setkey_enc( (camellia_context*) transform->ctx_enc, key1,
+                                 cipher_info->key_length );
+            camellia_setkey_dec( (camellia_context*) transform->ctx_dec, key2,
+                                 cipher_info->key_length );
             break;
 #endif
 
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-        case TLS_RSA_WITH_NULL_MD5:
-        case TLS_RSA_WITH_NULL_SHA:
-        case TLS_RSA_WITH_NULL_SHA256:
-            break;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
 #if defined(POLARSSL_DES_C)
-        case TLS_RSA_WITH_DES_CBC_SHA:
-        case TLS_DHE_RSA_WITH_DES_CBC_SHA:
+        case POLARSSL_CIPHER_DES_CBC:
             des_setkey_enc( (des_context *) transform->ctx_enc, key1 );
             des_setkey_dec( (des_context *) transform->ctx_dec, key2 );
             break;
 #endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+#if defined(POLARSSL_GCM_C)
+        case POLARSSL_CIPHER_AES_128_GCM:
+        case POLARSSL_CIPHER_AES_256_GCM:
+            gcm_init( (gcm_context *) transform->ctx_enc, key1,
+                      cipher_info->key_length );
+            gcm_init( (gcm_context *) transform->ctx_dec, key2,
+                      cipher_info->key_length );
+            break;
+#endif
+
+        case POLARSSL_CIPHER_NULL:
+            break;
 
         default:
             return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
@@ -799,91 +708,42 @@ void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
 /*
  * SSLv3.0 MAC functions
  */
-static void ssl_mac_md5( unsigned char *secret,
-                         unsigned char *buf, size_t len,
-                         unsigned char *ctr, int type )
+static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
+                     unsigned char *buf, size_t len,
+                     unsigned char *ctr, int type )
 {
     unsigned char header[11];
     unsigned char padding[48];
-    md5_context md5;
+    int padlen = 0;
+    int md_size = md_get_size( md_ctx->md_info );
+    int md_type = md_get_type( md_ctx->md_info );
+
+    if( md_type == POLARSSL_MD_MD5 )
+        padlen = 48;
+    else if( md_type == POLARSSL_MD_SHA1 )
+        padlen = 40;
+    else if( md_type == POLARSSL_MD_SHA256 )
+        padlen = 32;
 
     memcpy( header, ctr, 8 );
     header[ 8] = (unsigned char)  type;
     header[ 9] = (unsigned char)( len >> 8 );
     header[10] = (unsigned char)( len      );
 
-    memset( padding, 0x36, 48 );
-    md5_starts( &md5 );
-    md5_update( &md5, secret,  16 );
-    md5_update( &md5, padding, 48 );
-    md5_update( &md5, header,  11 );
-    md5_update( &md5, buf,  len );
-    md5_finish( &md5, buf + len );
+    memset( padding, 0x36, padlen );
+    md_starts( md_ctx );
+    md_update( md_ctx, secret,  md_size );
+    md_update( md_ctx, padding, padlen  );
+    md_update( md_ctx, header,  11      );
+    md_update( md_ctx, buf,     len     );
+    md_finish( md_ctx, buf +    len     );
 
-    memset( padding, 0x5C, 48 );
-    md5_starts( &md5 );
-    md5_update( &md5, secret,  16 );
-    md5_update( &md5, padding, 48 );
-    md5_update( &md5, buf + len, 16 );
-    md5_finish( &md5, buf + len );
-}
-
-static void ssl_mac_sha1( unsigned char *secret,
-                          unsigned char *buf, size_t len,
-                          unsigned char *ctr, int type )
-{
-    unsigned char header[11];
-    unsigned char padding[40];
-    sha1_context sha1;
-
-    memcpy( header, ctr, 8 );
-    header[ 8] = (unsigned char)  type;
-    header[ 9] = (unsigned char)( len >> 8 );
-    header[10] = (unsigned char)( len      );
-
-    memset( padding, 0x36, 40 );
-    sha1_starts( &sha1 );
-    sha1_update( &sha1, secret,  20 );
-    sha1_update( &sha1, padding, 40 );
-    sha1_update( &sha1, header,  11 );
-    sha1_update( &sha1, buf,  len );
-    sha1_finish( &sha1, buf + len );
-
-    memset( padding, 0x5C, 40 );
-    sha1_starts( &sha1 );
-    sha1_update( &sha1, secret,  20 );
-    sha1_update( &sha1, padding, 40 );
-    sha1_update( &sha1, buf + len, 20 );
-    sha1_finish( &sha1, buf + len );
-}
-
-static void ssl_mac_sha2( unsigned char *secret,
-                          unsigned char *buf, size_t len,
-                          unsigned char *ctr, int type )
-{
-    unsigned char header[11];
-    unsigned char padding[32];
-    sha2_context sha2;
-
-    memcpy( header, ctr, 8 );
-    header[ 8] = (unsigned char)  type;
-    header[ 9] = (unsigned char)( len >> 8 );
-    header[10] = (unsigned char)( len      );
-
-    memset( padding, 0x36, 32 );
-    sha2_starts( &sha2, 0 );
-    sha2_update( &sha2, secret,  32 );
-    sha2_update( &sha2, padding, 32 );
-    sha2_update( &sha2, header,  11 );
-    sha2_update( &sha2, buf,  len );
-    sha2_finish( &sha2, buf + len );
-
-    memset( padding, 0x5C, 32 );
-    sha2_starts( &sha2, 0 );
-    sha2_update( &sha2, secret,  32 );
-    sha2_update( &sha2, padding, 32 );
-    sha2_update( &sha2, buf + len, 32 );
-    sha2_finish( &sha2, buf + len );
+    memset( padding, 0x5C, padlen );
+    md_starts( md_ctx );
+    md_update( md_ctx, secret,    md_size );
+    md_update( md_ctx, padding,   padlen  );
+    md_update( md_ctx, buf + len, md_size );
+    md_finish( md_ctx, buf + len          );
 }
 
 /*
@@ -900,57 +760,19 @@ static int ssl_encrypt_buf( ssl_context *ssl )
      */
     if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
     {
-        if( ssl->transform_out->maclen == 16 )
-             ssl_mac_md5( ssl->transform_out->mac_enc,
-                          ssl->out_msg, ssl->out_msglen,
-                          ssl->out_ctr, ssl->out_msgtype );
-        else if( ssl->transform_out->maclen == 20 )
-            ssl_mac_sha1( ssl->transform_out->mac_enc,
-                          ssl->out_msg, ssl->out_msglen,
-                          ssl->out_ctr, ssl->out_msgtype );
-        else if( ssl->transform_out->maclen == 32 )
-            ssl_mac_sha2( ssl->transform_out->mac_enc,
-                          ssl->out_msg, ssl->out_msglen,
-                          ssl->out_ctr, ssl->out_msgtype );
-        else if( ssl->transform_out->maclen != 0 )
-        {
-            SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
-                                ssl->transform_out->maclen ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
+        ssl_mac( &ssl->transform_out->md_ctx_enc,
+                  ssl->transform_out->mac_enc,
+                  ssl->out_msg, ssl->out_msglen,
+                  ssl->out_ctr, ssl->out_msgtype );
     }
     else
     {
-        if( ssl->transform_out->maclen == 16 )
-        {
-            md5_context md5;
-            md5_hmac_starts( &md5, ssl->transform_out->mac_enc, 16 );
-            md5_hmac_update( &md5, ssl->out_ctr, 13 );
-            md5_hmac_update( &md5, ssl->out_msg, ssl->out_msglen );
-            md5_hmac_finish( &md5, ssl->out_msg + ssl->out_msglen );
-        }
-        else if( ssl->transform_out->maclen == 20 )
-        {
-            sha1_context sha1;
-            sha1_hmac_starts( &sha1, ssl->transform_out->mac_enc, 20 );
-            sha1_hmac_update( &sha1, ssl->out_ctr, 13 );
-            sha1_hmac_update( &sha1, ssl->out_msg, ssl->out_msglen );
-            sha1_hmac_finish( &sha1, ssl->out_msg + ssl->out_msglen );
-        }
-        else if( ssl->transform_out->maclen == 32 )
-        {
-            sha2_context sha2;
-            sha2_hmac_starts( &sha2, ssl->transform_out->mac_enc, 32, 0 );
-            sha2_hmac_update( &sha2, ssl->out_ctr, 13 );
-            sha2_hmac_update( &sha2, ssl->out_msg, ssl->out_msglen );
-            sha2_hmac_finish( &sha2, ssl->out_msg + ssl->out_msglen );
-        }
-        else if( ssl->transform_out->maclen != 0 )
-        {
-            SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
-                                ssl->transform_out->maclen ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
+        md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 );
+        md_hmac_update( &ssl->transform_out->md_ctx_enc,
+                         ssl->out_msg, ssl->out_msglen );
+        md_hmac_finish( &ssl->transform_out->md_ctx_enc,
+                         ssl->out_msg + ssl->out_msglen );
+        md_hmac_reset( &ssl->transform_out->md_ctx_enc );
     }
 
     SSL_DEBUG_BUF( 4, "computed mac",
@@ -958,7 +780,15 @@ static int ssl_encrypt_buf( ssl_context *ssl )
 
     ssl->out_msglen += ssl->transform_out->maclen;
 
-    if( ssl->transform_out->ivlen == 0 )
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_NULL )
+    {
+        padlen = 0;
+    }
+    else
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_ARC4_C)
+    if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 )
     {
         padlen = 0;
 
@@ -969,25 +799,15 @@ static int ssl_encrypt_buf( ssl_context *ssl )
         SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                        ssl->out_msg, ssl->out_msglen );
 
-#if defined(POLARSSL_ARC4_C)
-        if( ssl->session_out->ciphersuite == TLS_RSA_WITH_RC4_128_MD5 ||
-            ssl->session_out->ciphersuite == TLS_RSA_WITH_RC4_128_SHA )
-        {
-            arc4_crypt( (arc4_context *) ssl->transform_out->ctx_enc,
-                        ssl->out_msglen, ssl->out_msg,
-                        ssl->out_msg );
-        } else
-#endif
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-        if( ssl->session_out->ciphersuite == TLS_RSA_WITH_NULL_MD5 ||
-            ssl->session_out->ciphersuite == TLS_RSA_WITH_NULL_SHA ||
-            ssl->session_out->ciphersuite == TLS_RSA_WITH_NULL_SHA256 )
-        {
-        } else
-#endif
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        arc4_crypt( (arc4_context *) ssl->transform_out->ctx_enc,
+                    ssl->out_msglen, ssl->out_msg,
+                    ssl->out_msg );
     }
-    else if( ssl->transform_out->ivlen == 12 )
+    else
+#endif /* POLARSSL_ARC4_C */
+#if defined(POLARSSL_GCM_C)
+    if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_128_GCM ||
+        ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_256_GCM )
     {
         size_t enc_msglen;
         unsigned char *enc_msg;
@@ -1007,61 +827,51 @@ static int ssl_encrypt_buf( ssl_context *ssl )
         SSL_DEBUG_BUF( 4, "additional data used for AEAD",
                        add_data, 13 );
 
-#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
-
-        if( ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_128_GCM_SHA256 ||
-            ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
-            ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
-            ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
-        {
-            /*
-             * Generate IV
-             */
-            ret = ssl->f_rng( ssl->p_rng,
-                        ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
-                        ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
-            if( ret != 0 )
-                return( ret );
-
-            memcpy( ssl->out_iv,
+        /*
+         * Generate IV
+         */
+        ret = ssl->f_rng( ssl->p_rng,
                     ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
-                    ssl->transform_out->ivlen  - ssl->transform_out->fixed_ivlen );
+                    ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+        if( ret != 0 )
+            return( ret );
 
-            /*
-             * Fix pointer positions and message length with added IV
-             */
-            enc_msg = ssl->out_msg;
-            enc_msglen = ssl->out_msglen;
-            ssl->out_msglen += ssl->transform_out->ivlen -
-                               ssl->transform_out->fixed_ivlen;
+        memcpy( ssl->out_iv,
+                ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
 
-            SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
-                                "including %d bytes of padding",
-                           ssl->out_msglen, 0 ) );
+        /*
+         * Fix pointer positions and message length with added IV
+         */
+        enc_msg = ssl->out_msg;
+        enc_msglen = ssl->out_msglen;
+        ssl->out_msglen += ssl->transform_out->ivlen -
+                           ssl->transform_out->fixed_ivlen;
 
-            SSL_DEBUG_BUF( 4, "before encrypt: output payload",
-                           ssl->out_iv, ssl->out_msglen );
+        SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+                            "including %d bytes of padding",
+                       ssl->out_msglen, 0 ) );
 
-            /*
-             * Adjust for tag
-             */
-            ssl->out_msglen += 16;
-            
-            gcm_crypt_and_tag( (gcm_context *) ssl->transform_out->ctx_enc,
-                    GCM_ENCRYPT, enc_msglen,
-                    ssl->transform_out->iv_enc, ssl->transform_out->ivlen,
-                    add_data, 13,
-                    enc_msg, enc_msg,
-                    16, enc_msg + enc_msglen );
+        SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                       ssl->out_msg, ssl->out_msglen );
 
-            SSL_DEBUG_BUF( 4, "after encrypt: tag",
-                           enc_msg + enc_msglen, 16 );
+        /*
+         * Adjust for tag
+         */
+        ssl->out_msglen += 16;
 
-        } else
-#endif
-        return( ret );
+        gcm_crypt_and_tag( (gcm_context *) ssl->transform_out->ctx_enc,
+                GCM_ENCRYPT, enc_msglen,
+                ssl->transform_out->iv_enc, ssl->transform_out->ivlen,
+                add_data, 13,
+                enc_msg, enc_msg,
+                16, enc_msg + enc_msglen );
+
+        SSL_DEBUG_BUF( 4, "after encrypt: tag",
+                       enc_msg + enc_msglen, 16 );
     }
     else
+#endif /* POLARSSL_GCM_C */
     {
         unsigned char *enc_msg;
         size_t enc_msglen;
@@ -1111,60 +921,33 @@ static int ssl_encrypt_buf( ssl_context *ssl )
         SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                        ssl->out_iv, ssl->out_msglen );
 
-        switch( ssl->transform_out->ivlen )
+        switch( ssl->transform_out->ciphersuite_info->cipher )
         {
-#if defined(POLARSSL_DES_C)
-            case  8:
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-                if( ssl->session_out->ciphersuite == TLS_RSA_WITH_DES_CBC_SHA ||
-                    ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA )
-                {
-                    des_crypt_cbc( (des_context *) ssl->transform_out->ctx_enc,
-                                   DES_ENCRYPT, enc_msglen,
-                                   ssl->transform_out->iv_enc, enc_msg, enc_msg );
-                }
-                else
-#endif
-                    des3_crypt_cbc( (des3_context *) ssl->transform_out->ctx_enc,
-                                    DES_ENCRYPT, enc_msglen,
+            case POLARSSL_CIPHER_DES_CBC:
+                des_crypt_cbc( (des_context *) ssl->transform_out->ctx_enc,
+                               DES_ENCRYPT, enc_msglen,
+                               ssl->transform_out->iv_enc, enc_msg, enc_msg );
+                break;
+
+            case POLARSSL_CIPHER_DES_EDE3_CBC:
+                des3_crypt_cbc( (des3_context *) ssl->transform_out->ctx_enc,
+                               DES_ENCRYPT, enc_msglen,
+                               ssl->transform_out->iv_enc, enc_msg, enc_msg );
+                break;
+
+            case POLARSSL_CIPHER_AES_128_CBC:
+            case POLARSSL_CIPHER_AES_256_CBC:
+                aes_crypt_cbc( (aes_context *) ssl->transform_out->ctx_enc,
+                               AES_ENCRYPT, enc_msglen,
+                               ssl->transform_out->iv_enc, enc_msg, enc_msg );
+                break;
+
+            case POLARSSL_CIPHER_CAMELLIA_128_CBC:
+            case POLARSSL_CIPHER_CAMELLIA_256_CBC:
+                camellia_crypt_cbc( (camellia_context *) ssl->transform_out->ctx_enc,
+                                    CAMELLIA_ENCRYPT, enc_msglen,
                                     ssl->transform_out->iv_enc, enc_msg, enc_msg );
                 break;
-#endif
-
-            case 16:
-#if defined(POLARSSL_AES_C)
-        if ( ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA256 ||
-             ssl->session_out->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA256 ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 )
-        {
-                    aes_crypt_cbc( (aes_context *) ssl->transform_out->ctx_enc,
-                        AES_ENCRYPT, enc_msglen,
-                        ssl->transform_out->iv_enc, enc_msg, enc_msg);
-                    break;
-        }
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-        if ( ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
-             ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
-             ssl->session_out->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
-             ssl->session_out->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 )
-        {
-                    camellia_crypt_cbc( (camellia_context *) ssl->transform_out->ctx_enc,
-                        CAMELLIA_ENCRYPT, enc_msglen,
-                        ssl->transform_out->iv_enc, enc_msg, enc_msg );
-                    break;
-        }
-#endif
 
             default:
                 return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
@@ -1199,27 +982,27 @@ static int ssl_decrypt_buf( ssl_context *ssl )
         return( POLARSSL_ERR_SSL_INVALID_MAC );
     }
 
-    if( ssl->transform_in->ivlen == 0 )
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    if( ssl->transform_in->ciphersuite_info->cipher == POLARSSL_CIPHER_NULL )
     {
+        padlen = 0;
+    }
+    else
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
 #if defined(POLARSSL_ARC4_C)
-        if( ssl->session_in->ciphersuite == TLS_RSA_WITH_RC4_128_MD5 ||
-            ssl->session_in->ciphersuite == TLS_RSA_WITH_RC4_128_SHA )
-        {
-            arc4_crypt( (arc4_context *) ssl->transform_in->ctx_dec,
+    if( ssl->transform_in->ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 )
+    {
+        padlen = 0;
+
+        arc4_crypt( (arc4_context *) ssl->transform_in->ctx_dec,
                     ssl->in_msglen, ssl->in_msg,
                     ssl->in_msg );
-        } else
-#endif
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-        if( ssl->session_in->ciphersuite == TLS_RSA_WITH_NULL_MD5 ||
-            ssl->session_in->ciphersuite == TLS_RSA_WITH_NULL_SHA ||
-            ssl->session_in->ciphersuite == TLS_RSA_WITH_NULL_SHA256 )
-        {
-        } else
-#endif
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
     }
-    else if( ssl->transform_in->ivlen == 12 )
+    else
+#endif /* POLARSSL_ARC4_C */
+#if defined(POLARSSL_GCM_C)
+    if( ssl->transform_in->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_128_GCM ||
+        ssl->transform_in->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_256_GCM )
     {
         unsigned char *dec_msg;
         unsigned char *dec_msg_result;
@@ -1227,57 +1010,51 @@ static int ssl_decrypt_buf( ssl_context *ssl )
         unsigned char add_data[13];
         int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
 
-#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
-        if( ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_GCM_SHA256 ||
-            ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_256_GCM_SHA384 ||
-            ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
-            ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
+        padlen = 0;
+
+        dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen -
+                                        ssl->transform_in->fixed_ivlen );
+        dec_msglen -= 16;
+        dec_msg = ssl->in_msg;
+        dec_msg_result = ssl->in_msg;
+        ssl->in_msglen = dec_msglen;
+
+        memcpy( add_data, ssl->in_ctr, 8 );
+        add_data[8]  = ssl->in_msgtype;
+        add_data[9]  = ssl->major_ver;
+        add_data[10] = ssl->minor_ver;
+        add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
+        add_data[12] = ssl->in_msglen & 0xFF;
+
+        SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+                       add_data, 13 );
+
+        memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
+                ssl->in_iv,
+                ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
+
+        SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
+                                     ssl->transform_in->ivlen );
+        SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
+
+        ret = gcm_auth_decrypt( (gcm_context *) ssl->transform_in->ctx_dec,
+                                 dec_msglen,
+                                 ssl->transform_in->iv_dec,
+                                 ssl->transform_in->ivlen,
+                                 add_data, 13,
+                                 dec_msg + dec_msglen, 16,
+                                 dec_msg, dec_msg_result );
+
+        if( ret != 0 )
         {
-            dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen -
-                                            ssl->transform_in->fixed_ivlen );
-            dec_msglen -= 16;
-            dec_msg = ssl->in_msg;
-            dec_msg_result = ssl->in_msg;
-            ssl->in_msglen = dec_msglen;
+            SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)",
+                                -ret ) );
 
-            memcpy( add_data, ssl->in_ctr, 8 );
-            add_data[8]  = ssl->in_msgtype;
-            add_data[9]  = ssl->major_ver;
-            add_data[10] = ssl->minor_ver;
-            add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
-            add_data[12] = ssl->in_msglen & 0xFF;
-
-            SSL_DEBUG_BUF( 4, "additional data used for AEAD",
-                           add_data, 13 );
-
-            memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
-                    ssl->in_iv,
-                    ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
-
-            SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
-                                         ssl->transform_in->ivlen );
-            SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
-
-            ret = gcm_auth_decrypt( (gcm_context *) ssl->transform_in->ctx_dec,
-                                     dec_msglen,
-                                     ssl->transform_in->iv_dec,
-                                     ssl->transform_in->ivlen,
-                                     add_data, 13,
-                                     dec_msg + dec_msglen, 16,
-                                     dec_msg, dec_msg_result );
-            
-            if( ret != 0 )
-            {
-                SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)",
-                                    -ret ) );
-
-                return( POLARSSL_ERR_SSL_INVALID_MAC );
-            }
-        } else
-#endif
-        return( ret );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
     }
     else
+#endif /* POLARSSL_GCM_C */
     {
         /*
          * Decrypt and check the padding
@@ -1324,60 +1101,33 @@ static int ssl_decrypt_buf( ssl_context *ssl )
                 ssl->transform_in->iv_dec[i] = ssl->in_iv[i];
         }
 
-        switch( ssl->transform_in->ivlen )
+        switch( ssl->transform_in->ciphersuite_info->cipher )
         {
-#if defined(POLARSSL_DES_C)
-            case  8:
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-                if( ssl->session_in->ciphersuite == TLS_RSA_WITH_DES_CBC_SHA ||
-                    ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_DES_CBC_SHA )
-                {
-                    des_crypt_cbc( (des_context *) ssl->transform_in->ctx_dec,
-                                   DES_DECRYPT, dec_msglen,
-                                   ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                }
-                else
-#endif
-                    des3_crypt_cbc( (des3_context *) ssl->transform_in->ctx_dec,
-                        DES_DECRYPT, dec_msglen,
-                        ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+            case POLARSSL_CIPHER_DES_CBC:
+                des_crypt_cbc( (des_context *) ssl->transform_in->ctx_dec,
+                               DES_DECRYPT, dec_msglen,
+                               ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
                 break;
-#endif
 
-            case 16:
-#if defined(POLARSSL_AES_C)
-        if ( ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_CBC_SHA256 ||
-             ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_256_CBC_SHA256 ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 )
-        {
-                    aes_crypt_cbc( (aes_context *) ssl->transform_in->ctx_dec,
-                       AES_DECRYPT, dec_msglen,
-                       ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                    break;
-        }
-#endif
+            case POLARSSL_CIPHER_DES_EDE3_CBC:
+                des3_crypt_cbc( (des3_context *) ssl->transform_in->ctx_dec,
+                               DES_DECRYPT, dec_msglen,
+                               ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+                break;
 
-#if defined(POLARSSL_CAMELLIA_C)
-        if ( ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA ||
-             ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 ||
-             ssl->session_in->ciphersuite == TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 ||
-             ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 )
-        {
-                    camellia_crypt_cbc( (camellia_context *) ssl->transform_in->ctx_dec,
-                       CAMELLIA_DECRYPT, dec_msglen,
-                       ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                    break;
-        }
-#endif
+            case POLARSSL_CIPHER_AES_128_CBC:
+            case POLARSSL_CIPHER_AES_256_CBC:
+                aes_crypt_cbc( (aes_context *) ssl->transform_in->ctx_dec,
+                               AES_DECRYPT, dec_msglen,
+                               ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+                break;
+
+            case POLARSSL_CIPHER_CAMELLIA_128_CBC:
+            case POLARSSL_CIPHER_CAMELLIA_256_CBC:
+                camellia_crypt_cbc( (camellia_context *) ssl->transform_in->ctx_dec,
+                                    CAMELLIA_DECRYPT, dec_msglen,
+                                    ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
+                break;
 
             default:
                 return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
@@ -1448,24 +1198,10 @@ static int ssl_decrypt_buf( ssl_context *ssl )
 
     if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
     {
-        if( ssl->transform_in->maclen == 16 )
-             ssl_mac_md5( ssl->transform_in->mac_dec,
-                          ssl->in_msg, ssl->in_msglen,
-                          ssl->in_ctr, ssl->in_msgtype );
-        else if( ssl->transform_in->maclen == 20 )
-            ssl_mac_sha1( ssl->transform_in->mac_dec,
-                          ssl->in_msg, ssl->in_msglen,
-                          ssl->in_ctr, ssl->in_msgtype );
-        else if( ssl->transform_in->maclen == 32 )
-            ssl_mac_sha2( ssl->transform_in->mac_dec,
-                          ssl->in_msg, ssl->in_msglen,
-                          ssl->in_ctr, ssl->in_msgtype );
-        else if( ssl->transform_in->maclen != 0 )
-        {
-            SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
-                                ssl->transform_in->maclen ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
+        ssl_mac( &ssl->transform_in->md_ctx_dec,
+                  ssl->transform_in->mac_dec,
+                  ssl->in_msg, ssl->in_msglen,
+                  ssl->in_ctr, ssl->in_msgtype );
     }
     else
     {
@@ -1488,45 +1224,15 @@ static int ssl_decrypt_buf( ssl_context *ssl )
 
         extra_run &= correct * 0xFF;
 
-        if( ssl->transform_in->maclen == 16 )
-        {
-            md5_context ctx;
-            md5_hmac_starts( &ctx, ssl->transform_in->mac_dec, 16 );
-            md5_hmac_update( &ctx, ssl->in_ctr, 13 );
-            md5_hmac_update( &ctx, ssl->in_msg, ssl->in_msglen );
-            md5_hmac_finish( &ctx, ssl->in_msg + ssl->in_msglen );
+        md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 13 );
+        md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
+                         ssl->in_msglen );
+        md_hmac_finish( &ssl->transform_in->md_ctx_dec,
+                         ssl->in_msg + ssl->in_msglen );
+        for( j = 0; j < extra_run; j++ )
+            md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
 
-            for( j = 0; j < extra_run; j++ )
-                md5_process( &ctx, ssl->in_msg ); 
-        }
-        else if( ssl->transform_in->maclen == 20 )
-        {
-            sha1_context ctx;
-            sha1_hmac_starts( &ctx, ssl->transform_in->mac_dec, 20 );
-            sha1_hmac_update( &ctx, ssl->in_ctr, 13 );
-            sha1_hmac_update( &ctx, ssl->in_msg, ssl->in_msglen );
-            sha1_hmac_finish( &ctx, ssl->in_msg + ssl->in_msglen );
-
-            for( j = 0; j < extra_run; j++ )
-                sha1_process( &ctx, ssl->in_msg ); 
-        }
-        else if( ssl->transform_in->maclen == 32 )
-        {
-            sha2_context ctx;
-            sha2_hmac_starts( &ctx, ssl->transform_in->mac_dec, 32, 0 );
-            sha2_hmac_update( &ctx, ssl->in_ctr, 13 );
-            sha2_hmac_update( &ctx, ssl->in_msg, ssl->in_msglen );
-            sha2_hmac_finish( &ctx, ssl->in_msg + ssl->in_msglen );
-
-            for( j = 0; j < extra_run; j++ )
-                sha2_process( &ctx, ssl->in_msg ); 
-        }
-        else if( ssl->transform_in->maclen != 0 )
-        {
-            SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d",
-                                ssl->transform_in->maclen ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
+        md_hmac_reset( &ssl->transform_in->md_ctx_dec );
     }
 
     SSL_DEBUG_BUF( 4, "message  mac", tmp, ssl->transform_in->maclen );
@@ -1844,6 +1550,9 @@ int ssl_read_record( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> read record" ) );
 
+    SSL_DEBUG_BUF( 4, "input record from network",
+                   ssl->in_hdr, 5 + ssl->in_msglen );
+
     if( ssl->in_hslen != 0 &&
         ssl->in_hslen < ssl->in_msglen )
     {
@@ -2971,7 +2680,7 @@ int ssl_init( ssl_context *ssl )
     ssl->min_major_ver = SSL_MAJOR_VERSION_3;
     ssl->min_minor_ver = SSL_MINOR_VERSION_0;
 
-    ssl->ciphersuites = ssl_default_ciphersuites;
+    ssl->ciphersuites = ssl_list_ciphersuites();
 
 #if defined(POLARSSL_DHM_C)
     if( ( ret = mpi_read_string( &ssl->dhm_P, 16,
@@ -3291,218 +3000,6 @@ int ssl_get_verify_result( const ssl_context *ssl )
     return( ssl->verify_result );
 }
 
-const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
-{
-    switch( ciphersuite_id )
-    {
-#if defined(POLARSSL_ARC4_C)
-        case TLS_RSA_WITH_RC4_128_MD5:
-            return( "TLS-RSA-WITH-RC4-128-MD5" );
-
-        case TLS_RSA_WITH_RC4_128_SHA:
-            return( "TLS-RSA-WITH-RC4-128-SHA" );
-#endif
-
-#if defined(POLARSSL_DES_C)
-        case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
-            return( "TLS-RSA-WITH-3DES-EDE-CBC-SHA" );
-
-        case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
-            return( "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA" );
-#endif
-
-#if defined(POLARSSL_AES_C)
-        case TLS_RSA_WITH_AES_128_CBC_SHA:
-            return( "TLS-RSA-WITH-AES-128-CBC-SHA" );
-
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
-            return( "TLS-DHE-RSA-WITH-AES-128-CBC-SHA" );
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA:
-            return( "TLS-RSA-WITH-AES-256-CBC-SHA" );
-
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
-            return( "TLS-DHE-RSA-WITH-AES-256-CBC-SHA" );
-
-#if defined(POLARSSL_SHA2_C)
-        case TLS_RSA_WITH_AES_128_CBC_SHA256:
-            return( "TLS-RSA-WITH-AES-128-CBC-SHA256" );
-
-        case TLS_RSA_WITH_AES_256_CBC_SHA256:
-            return( "TLS-RSA-WITH-AES-256-CBC-SHA256" );
-
-        case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
-            return( "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256" );
-
-        case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
-            return( "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256" );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
-        case TLS_RSA_WITH_AES_128_GCM_SHA256:
-            return( "TLS-RSA-WITH-AES-128-GCM-SHA256" );
-
-        case TLS_RSA_WITH_AES_256_GCM_SHA384:
-            return( "TLS-RSA-WITH-AES-256-GCM-SHA384" );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
-        case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            return( "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256" );
-
-        case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            return( "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384" );
-#endif
-#endif /* POLARSSL_AES_C */
-
-#if defined(POLARSSL_CAMELLIA_C)
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            return( "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA" );
-
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
-            return( "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA" );
-
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            return( "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA" );
-
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
-            return( "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA" );
-
-#if defined(POLARSSL_SHA2_C)
-        case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            return( "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256" );
-
-        case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
-            return( "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256" );
-
-        case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            return( "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256" );
-
-        case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            return( "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256" );
-#endif
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-        case TLS_RSA_WITH_NULL_MD5:
-            return( "TLS-RSA-WITH-NULL-MD5" );
-        case TLS_RSA_WITH_NULL_SHA:
-            return( "TLS-RSA-WITH-NULL-SHA" );
-        case TLS_RSA_WITH_NULL_SHA256:
-            return( "TLS-RSA-WITH-NULL-SHA256" );
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
-        case TLS_RSA_WITH_DES_CBC_SHA:
-            return( "TLS-RSA-WITH-DES-CBC-SHA" );
-        case TLS_DHE_RSA_WITH_DES_CBC_SHA:
-            return( "TLS-DHE-RSA-WITH-DES-CBC-SHA" );
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
-    default:
-        break;
-    }
-
-    return( "unknown" );
-}
-
-int ssl_get_ciphersuite_id( const char *ciphersuite_name )
-{
-#if defined(POLARSSL_ARC4_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-RC4-128-MD5"))
-        return( TLS_RSA_WITH_RC4_128_MD5 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-RC4-128-SHA"))
-        return( TLS_RSA_WITH_RC4_128_SHA );
-#endif
-
-#if defined(POLARSSL_DES_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-3DES-EDE-CBC-SHA"))
-        return( TLS_RSA_WITH_3DES_EDE_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"))
-        return( TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA );
-#endif
-
-#if defined(POLARSSL_AES_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-128-CBC-SHA"))
-        return( TLS_RSA_WITH_AES_128_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA"))
-        return( TLS_DHE_RSA_WITH_AES_128_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-256-CBC-SHA"))
-        return( TLS_RSA_WITH_AES_256_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA"))
-        return( TLS_DHE_RSA_WITH_AES_256_CBC_SHA );
-
-#if defined(POLARSSL_SHA2_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-128-CBC-SHA256"))
-        return( TLS_RSA_WITH_AES_128_CBC_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-256-CBC-SHA256"))
-        return( TLS_RSA_WITH_AES_256_CBC_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256"))
-        return( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256"))
-        return( TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-128-GCM-SHA256"))
-        return( TLS_RSA_WITH_AES_128_GCM_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-AES-256-GCM-SHA384"))
-        return( TLS_RSA_WITH_AES_256_GCM_SHA384 );
-#endif
-
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256"))
-        return( TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384"))
-        return( TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 );
-#endif
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA"))
-        return( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"))
-        return( TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA"))
-        return( TLS_RSA_WITH_CAMELLIA_256_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"))
-        return( TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA );
-
-#if defined(POLARSSL_SHA2_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256"))
-        return( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"))
-        return( TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256"))
-        return( TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"))
-        return( TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 );
-#endif
-#endif
-
-#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-NULL-MD5"))
-        return( TLS_RSA_WITH_NULL_MD5 );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-NULL-SHA"))
-        return( TLS_RSA_WITH_NULL_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-NULL-SHA256"))
-        return( TLS_RSA_WITH_NULL_SHA256 );
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
-#if defined(POLARSSL_DES_C)
-    if (0 == strcasecmp(ciphersuite_name, "TLS-RSA-WITH-DES-CBC-SHA"))
-        return( TLS_RSA_WITH_DES_CBC_SHA );
-    if (0 == strcasecmp(ciphersuite_name, "TLS-DHE-RSA-WITH-DES-CBC-SHA"))
-        return( TLS_DHE_RSA_WITH_DES_CBC_SHA );
-#endif
-#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
-
-    return( 0 );
-}
-
 const char *ssl_get_ciphersuite( const ssl_context *ssl )
 {
     if( ssl == NULL || ssl->session == NULL )
@@ -3541,80 +3038,6 @@ const x509_cert *ssl_get_peer_cert( const ssl_context *ssl )
     return ssl->session->peer_cert;
 }
 
-const int ssl_default_ciphersuites[] =
-{
-#if defined(POLARSSL_DHM_C)
-#if defined(POLARSSL_AES_C)
-#if defined(POLARSSL_SHA2_C)
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
-    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
-#endif
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
-#if defined(POLARSSL_SHA2_C)
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
-#endif
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
-    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-#endif
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#if defined(POLARSSL_SHA2_C)
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-    TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
-#if defined(POLARSSL_SHA2_C)
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-    TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
-#endif
-#if defined(POLARSSL_DES_C)
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-#endif
-
-#if defined(POLARSSL_AES_C)
-#if defined(POLARSSL_SHA2_C)
-    TLS_RSA_WITH_AES_256_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
-    TLS_RSA_WITH_AES_256_GCM_SHA384,
-#endif /* POLARSSL_SHA2_C */
-    TLS_RSA_WITH_AES_256_CBC_SHA,
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#if defined(POLARSSL_SHA2_C)
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-    TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
-#endif
-#if defined(POLARSSL_AES_C)
-#if defined(POLARSSL_SHA2_C)
-    TLS_RSA_WITH_AES_128_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
-    TLS_RSA_WITH_AES_128_GCM_SHA256,
-#endif /* POLARSSL_SHA2_C */
-    TLS_RSA_WITH_AES_128_CBC_SHA,
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#if defined(POLARSSL_SHA2_C)
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
-#endif /* POLARSSL_SHA2_C */
-    TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
-#endif
-#if defined(POLARSSL_DES_C)
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA,
-#endif
-#if defined(POLARSSL_ARC4_C)
-    TLS_RSA_WITH_RC4_128_SHA,
-    TLS_RSA_WITH_RC4_128_MD5,
-#endif
-    0
-};
-
 /*
  * Perform a single step of the SSL handshake
  */
diff --git a/programs/test/ssl_test.c b/programs/test/ssl_test.c
index 802fda0c2..e067652f5 100644
--- a/programs/test/ssl_test.c
+++ b/programs/test/ssl_test.c
@@ -1,7 +1,7 @@
 /*
  *  SSL/TLS stress testing program
  *
- *  Copyright (C) 2006-2011, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -272,9 +272,8 @@ static int ssl_test( struct options *opt )
     ssl_set_bio( &ssl, net_recv, &client_fd,
                        net_send, &client_fd );
 
-    if( opt->force_ciphersuite[0] == DFL_FORCE_CIPHER )
-          ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites );
-    else  ssl_set_ciphersuites( &ssl, opt->force_ciphersuite );
+    if( opt->force_ciphersuite[0] != DFL_FORCE_CIPHER )
+        ssl_set_ciphersuites( &ssl, opt->force_ciphersuite );
 
     if( opt->iomode == IOMODE_NONBLOCK )
         net_set_nonblock( client_fd );
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 2fb0c854e..c9f74dda5 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -1,7 +1,7 @@
 /*
  *  Certificate reading application
  *
- *  Copyright (C) 2006-2011, Brainspark B.V.
+ *  Copyright (C) 2006-2013, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -284,8 +284,6 @@ int main( int argc, char *argv[] )
         ssl_set_bio( &ssl, net_recv, &server_fd,
                 net_send, &server_fd );
 
-        ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites );
-
         ssl_set_own_cert( &ssl, &clicert, &rsa );
 
         ssl_set_hostname( &ssl, opt.server_name );