Merged refactored x509write module into development
diff --git a/ChangeLog b/ChangeLog
index 505d90a..6cfdd00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,8 @@
    * Elliptic Curve Diffie Hellman module added
    * Ephemeral Elliptic Curve Diffie Hellman support for SSL/TLS
     (ECDHE-based ciphersuites)
+   * Ephemeral Elliptic Curve Digital Signature Algorithm support for SSL/TLS
+    (ECDSA-based ciphersuites)
    * Ability to specify allowed ciphersuites based on the protocol version.
    * PSK and DHE-PSK based ciphersuites added
    * Memory allocation abstraction layer added
@@ -18,8 +20,12 @@
    * Support for zeros-and-length (ANSI X.923) padding, one-and-zeros
      (ISO/IEC 7816-4) padding and zero padding in the cipher layer
    * Support for session tickets (RFC 5077)
+   * Certificate Request (CSR) generation with extensions (key_usage,
+     ns_cert_type)
 
 Changes
+   * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2
+     individually
    * 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
@@ -29,6 +35,7 @@
    * Split up the GCM module into a starts/update/finish cycle
    * Client and server now filter sent and accepted ciphersuites on minimum
      and maximum protocol version
+   * Ability to disable server_name extension (RFC 6066)
    * Renamed error_strerror() to the less conflicting polarssl_strerror()
      (Ability to keep old as well with POLARSSL_ERROR_STRERROR_BC)
    * SHA2 renamed to SHA256, SHA4 renamed to SHA512 and functions accordingly
diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h
index 13d714b..0ab2b56 100644
--- a/include/polarssl/cipher.h
+++ b/include/polarssl/cipher.h
@@ -491,4 +491,4 @@
 }
 #endif
 
-#endif /* POLARSSL_MD_H */
+#endif /* POLARSSL_CIPHER_H */
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index 84b36b6..c1a1269 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -364,6 +364,28 @@
 #define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
 
 /**
+ * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ *
+ * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ *      TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ *      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ *      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+
+/**
  * \def POLARSSL_ERROR_STRERROR_BC
  *
  * Make available the backward compatible error_strerror() next to the
@@ -538,6 +560,54 @@
 #define POLARSSL_SSL_MAX_FRAGMENT_LENGTH
 
 /**
+ * \def POLARSSL_SSL_PROTO_SSL3
+ *
+ * Enable support for SSL 3.0
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for SSL 3.0
+ */
+#define POLARSSL_SSL_PROTO_SSL3
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1
+ *
+ * Enable support for TLS 1.0
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.0
+ */
+#define POLARSSL_SSL_PROTO_TLS1
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1_1
+ *
+ * Enable support for TLS 1.1
+ *
+ * Requires: POLARSSL_MD5_C
+ *           POLARSSL_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.1
+ */
+#define POLARSSL_SSL_PROTO_TLS1_1
+
+/**
+ * \def POLARSSL_SSL_PROTO_TLS1_2
+ *
+ * Enable support for TLS 1.2
+ *
+ * Requires: POLARSSL_SHA256_C or POLARSSL_SHA512_C
+ *           (Depends on ciphersuites)
+ *
+ * Comment this macro to disable support for TLS 1.2
+ */
+#define POLARSSL_SSL_PROTO_TLS1_2
+
+/**
  * \def POLARSSL_SSL_SESSION_TICKETS
  *
  * Enable support for RFC 5077 session tickets in SSL
@@ -550,6 +620,15 @@
 #define POLARSSL_SSL_SESSION_TICKETS
 
 /**
+ * \def POLARSSL_SSL_SERVER_NAME_INDICATION
+ *
+ * Enable support for RFC 6066 server name indication (SNI) in SSL
+ *
+ * Comment this macro to disable support for server name indication in SSL
+ */
+#define POLARSSL_SSL_SERVER_NAME_INDICATION
+
+/**
  * \def POLARSSL_SSL_TRUNCATED_HMAC
  *
  * Enable support for RFC 6066 truncated HMAC in SSL
@@ -1072,6 +1151,21 @@
 #define POLARSSL_PEM_C
 
 /**
+ * \def POLARSSL_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module:  library/pk.c
+ * Caller:  library/x509parse.c
+ *          library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define POLARSSL_PK_C
+
+/**
  * \def POLARSSL_PKCS5_C
  *
  * Enable PKCS#5 functions
@@ -1089,11 +1183,10 @@
  *
  * Enable wrapper for PKCS#11 smartcard support.
  *
- * Module:  library/ssl_srv.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
  *
- * Requires: POLARSSL_SSL_TLS_C
+ * Requires: POLARSSL_PK_C
  *
  * This module enables SSL/TLS PKCS #11 smartcard support.
  * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
@@ -1226,7 +1319,8 @@
  * Caller:  library/ssl_cli.c
  *          library/ssl_srv.c
  *
- * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_CIPHER_C
+ * Requires: POLARSSL_CIPHER_C, POLARSSL_PK_C, POLARSSL_MD_C
+ *           and at least one of the POLARSSL_SSL_PROTO_* defines
  *
  * This module is required for SSL/TLS.
  */
@@ -1266,7 +1360,7 @@
  *          library/ssl_tls.c
  *
  * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C,
- *           POLARSSL_RSA_C
+ *           POLARSSL_PK_C
  *
  * This module is required for X.509 certificate parsing.
  */
@@ -1326,7 +1420,7 @@
 
 // CTR_DRBG options
 //
-#define CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default */
+#define CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
 #define CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
 #define CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
 #define CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
@@ -1382,9 +1476,18 @@
 #error "POLARSSL_ECP_C defined, but not all prerequisites"
 #endif
 
-#if defined(POLARSSL_ENTROPY_C) && !defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) &&      \
+                                    !defined(POLARSSL_SHA256_C))
 #error "POLARSSL_ENTROPY_C defined, but not all prerequisites"
 #endif
+#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) &&         \
+    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 64)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && !defined(POLARSSL_SHA512_C) &&        \
+    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 32)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
 
 #if defined(POLARSSL_GCM_C) && !defined(POLARSSL_AES_C)
 #error "POLARSSL_GCM_C defined, but not all prerequisites"
@@ -1410,6 +1513,12 @@
 #error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
 #endif
 
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) ||          \
+      !defined(POLARSSL_X509_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
 #if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
     ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_PARSE_C) )
 #error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
@@ -1432,7 +1541,7 @@
 #error "POLARSSL_PEM_C defined, but not all prerequisites"
 #endif
 
-#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_SSL_TLS_C)
+#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C)
 #error "POLARSSL_PKCS11_C defined, but not all prerequisites"
 #endif
 
@@ -1445,8 +1554,8 @@
 #error "POLARSSL_SSL_CLI_C defined, but not all prerequisites"
 #endif
 
-#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_MD5_C) ||        \
-    !defined(POLARSSL_SHA1_C) || !defined(POLARSSL_CIPHER_C) )
+#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) ||     \
+    !defined(POLARSSL_PK_C) || !defined(POLARSSL_MD_C) )
 #error "POLARSSL_SSL_TLS_C defined, but not all prerequisites"
 #endif
 
@@ -1454,6 +1563,28 @@
 #error "POLARSSL_SSL_SRV_C defined, but not all prerequisites"
 #endif
 
+#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2))
+#error "POLARSSL_SSL_TLS_C defined, but no protocols are active"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1)))
+#error "Illegal protocol selection"
+#endif
+
 #if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \
     ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) )
 #error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
@@ -1461,7 +1592,7 @@
 
 #if defined(POLARSSL_X509_PARSE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
     !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) ||      \
-    !defined(POLARSSL_RSA_C) )
+    !defined(POLARSSL_PK_C) )
 #error "POLARSSL_X509_PARSE_C defined, but not all prerequisites"
 #endif
 
diff --git a/include/polarssl/ctr_drbg.h b/include/polarssl/ctr_drbg.h
index b47d389..4c0fc17 100644
--- a/include/polarssl/ctr_drbg.h
+++ b/include/polarssl/ctr_drbg.h
@@ -43,7 +43,11 @@
                                             /**< The seed length (counter + AES key)            */
 
 #if !defined(POLARSSL_CONFIG_OPTIONS)
-#define CTR_DRBG_ENTROPY_LEN        48      /**< Amount of entropy used per seed by default */
+#if defined(POLARSSL_SHA512_C)
+#define CTR_DRBG_ENTROPY_LEN        48      /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+#else
+#define CTR_DRBG_ENTROPY_LEN        32      /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+#endif
 #define CTR_DRBG_RESEED_INTERVAL    10000   /**< Interval before reseed is performed by default */
 #define CTR_DRBG_MAX_INPUT          256     /**< Maximum number of additional input bytes */
 #define CTR_DRBG_MAX_REQUEST        1024    /**< Maximum number of requested bytes per call */
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index 36c6185..ad31bff 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -34,8 +34,9 @@
  */
 #define POLARSSL_ERR_ECP_BAD_INPUT_DATA                    -0x4F80  /**< Bad input parameters to function. */
 #define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL                  -0x4F00  /**< The buffer is too small to write to. */
-#define POLARSSL_ERR_ECP_GENERIC                           -0x4E80  /**<  Generic ECP error */
+#define POLARSSL_ERR_ECP_GENERIC                           -0x4E80  /**< Generic ECP error. */
 #define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE               -0x4E00  /**< Requested curve not available. */
+#define POLARSSL_ERR_ECP_VERIFY_FAILED                     -0x4E00  /**< The signature is not valid. */
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/polarssl/entropy.h b/include/polarssl/entropy.h
index 69d5b3b..ea27848 100644
--- a/include/polarssl/entropy.h
+++ b/include/polarssl/entropy.h
@@ -31,7 +31,16 @@
 
 #include "config.h"
 
+#if defined(POLARSSL_SHA512_C)
 #include "sha512.h"
+#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR
+#else
+#if defined(POLARSSL_SHA256_C)
+#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR
+#include "sha256.h"
+#endif
+#endif
+
 #if defined(POLARSSL_HAVEGE_C)
 #include "havege.h"
 #endif
@@ -45,7 +54,11 @@
 #define ENTROPY_MAX_GATHER      128     /**< Maximum amount requested from entropy sources */
 #endif /* !POLARSSL_CONFIG_OPTIONS  */
 
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
 #define ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */
+#else
+#define ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */
+#endif
 
 #define ENTROPY_SOURCE_MANUAL   ENTROPY_MAX_SOURCES
 
@@ -83,7 +96,11 @@
  */
 typedef struct
 {
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
     sha512_context  accumulator;
+#else
+    sha256_context  accumulator;
+#endif
     int             source_count;
     source_state    source[ENTROPY_MAX_SOURCES];
 #if defined(POLARSSL_HAVEGE_C)
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index fb0e92e..4ff4747 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -82,6 +82,7 @@
     POLARSSL_PK_ECKEY,
     POLARSSL_PK_ECKEY_DH,
     POLARSSL_PK_ECDSA,
+    POLARSSL_PK_RSA_ALT,
 } pk_type_t;
 
 /**
@@ -129,6 +130,25 @@
                         const unsigned char *hash, size_t hash_len,
                         const unsigned char *sig, size_t sig_len );
 
+    /** Make signature */
+    int (*sign_func)( void *ctx, md_type_t md_alg,
+                      const unsigned char *hash, size_t hash_len,
+                      unsigned char *sig, size_t *sig_len,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng );
+
+    /** Decrypt message */
+    int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen, size_t osize,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
+
+    /** Encrypt message */
+    int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen, size_t osize,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
+
     /** Allocate a new context */
     void * (*ctx_alloc_func)( void );
 
@@ -150,6 +170,18 @@
 } pk_context;
 
 /**
+ * \brief           Types for RSA-alt abstraction
+ */
+typedef int (*pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen,
+                    const unsigned char *input, unsigned char *output,
+                    size_t output_max_len );
+typedef int (*pk_rsa_alt_sign_func)( void *ctx,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                    int mode, int hash_id, unsigned int hashlen,
+                    const unsigned char *hash, unsigned char *sig );
+typedef size_t (*pk_rsa_alt_key_len_func)( void *ctx );
+
+/**
  * \brief           Return information associated with the given PK type
  *
  * \param type      PK type to search for.
@@ -164,6 +196,11 @@
 void pk_init( pk_context *ctx );
 
 /**
+ * \brief           Free a pk_context
+ */
+void pk_free( pk_context *ctx );
+
+/**
  * \brief           Initialize a PK context with the information given
  *                  and allocates the type-specific PK subcontext.
  *
@@ -173,13 +210,30 @@
  * \return          0 on success,
  *                  POLARSSL_ERR_PK_BAD_INPUT_DATA on invalid input,
  *                  POLARSSL_ERR_PK_MALLOC_FAILED on allocation failure.
+ *
+ * \note            For contexts holding an RSA-alt key, use
+ *                  \c pk_init_ctx_rsa_alt() instead.
  */
 int pk_init_ctx( pk_context *ctx, const pk_info_t *info );
 
 /**
- * \brief           Free a pk_context
+ * \brief           Initialiaze an RSA-alt context
+ *
+ * \param ctx       Context to initialize. Must be empty (type NONE).
+ * \param key       RSA key pointer
+ * \param decrypt_func  Decryption function
+ * \param sign_func     Signing function
+ * \param key_len_func  Function returning key length
+ *
+ * \return          0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the
+ *                  context wasn't already initialized as RSA_ALT.
+ *
+ * \note            This function replaces \c pk_init_ctx() for RSA-alt.
  */
-void pk_free( pk_context *ctx );
+int pk_init_ctx_rsa_alt( pk_context *ctx, void * key,
+                         pk_rsa_alt_decrypt_func decrypt_func,
+                         pk_rsa_alt_sign_func sign_func,
+                         pk_rsa_alt_key_len_func key_len_func );
 
 /**
  * \brief           Get the size in bits of the underlying key
@@ -191,6 +245,17 @@
 size_t pk_get_size( const pk_context *ctx );
 
 /**
+ * \brief           Get the length in bytes of the underlying key
+ * \param ctx       Context to use
+ *
+ * \return          Key lenght in bytes, or 0 on error
+ */
+static inline size_t pk_get_len( const pk_context *ctx )
+{
+    return( ( pk_get_size( ctx ) + 7 ) / 8 );
+}
+
+/**
  * \brief           Tell if a context can do the operation given by type
  *
  * \param ctx       Context to test
@@ -205,20 +270,83 @@
  * \brief           Verify signature
  *
  * \param ctx       PK context to use
- * \param md_alg    Hash algorithm used
+ * \param md_alg    Hash algorithm used (see notes)
  * \param hash      Hash of the message to sign
- * \param hash_len  Hash length
+ * \param hash_len  Hash length or 0 (see notes)
  * \param sig       Signature to verify
  * \param sig_len   Signature length
  *
  * \return          0 on success (signature is valid),
  *                  or a specific error code.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            md_alg may be POLARSSL_MD_NONE, only if hash_len != 0
  */
 int pk_verify( pk_context *ctx, md_type_t md_alg,
                const unsigned char *hash, size_t hash_len,
                const unsigned char *sig, size_t sig_len );
 
 /**
+ * \brief           Make signature
+ *
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Place to write the signature
+ * \param sig_len   Number of bytes written
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 on success, or a specific error code.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            md_alg may be POLARSSL_MD_NONE, only if hash_len != 0
+ */
+int pk_sign( pk_context *ctx, md_type_t md_alg,
+             const unsigned char *hash, size_t hash_len,
+             unsigned char *sig, size_t *sig_len,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Decrypt message
+ *
+ * \param ctx       PK context to use
+ * \param input     Input to decrypt
+ * \param ilen      Input size
+ * \param output    Decrypted output
+ * \param olen      Decrypted message lenght
+ * \param osize     Size of the output buffer
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int pk_decrypt( pk_context *ctx,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output, size_t *olen, size_t osize,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief           Encrypt message
+ *
+ * \param ctx       PK context to use
+ * \param input     Message to encrypt
+ * \param ilen      Message size
+ * \param output    Encrypted output
+ * \param olen      Encrypted output length
+ * \param osize     Size of the output buffer
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int pk_encrypt( pk_context *ctx,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output, size_t *olen, size_t osize,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
  * \brief           Export debug information
  *
  * \param ctx       Context to use
diff --git a/include/polarssl/pk_wrap.h b/include/polarssl/pk_wrap.h
index a24fbd1..91a671e 100644
--- a/include/polarssl/pk_wrap.h
+++ b/include/polarssl/pk_wrap.h
@@ -32,6 +32,15 @@
 
 #include "pk.h"
 
+/* Container for RSA-alt */
+typedef struct
+{
+    void *key;
+    pk_rsa_alt_decrypt_func decrypt_func;
+    pk_rsa_alt_sign_func sign_func;
+    pk_rsa_alt_key_len_func key_len_func;
+} rsa_alt_context;
+
 #if defined(POLARSSL_RSA_C)
 extern const pk_info_t rsa_info;
 #endif
@@ -45,4 +54,6 @@
 extern const pk_info_t ecdsa_info;
 #endif
 
+extern const pk_info_t rsa_alt_info;
+
 #endif /* POLARSSL_PK_WRAP_H */
diff --git a/include/polarssl/rsa.h b/include/polarssl/rsa.h
index 8e52e7d..90cfd55 100644
--- a/include/polarssl/rsa.h
+++ b/include/polarssl/rsa.h
@@ -29,8 +29,6 @@
 
 #include "config.h"
 
-#if defined(POLARSSL_RSA_C)
-
 #include "bignum.h"
 #include "md.h"
 
@@ -59,6 +57,12 @@
 #define RSA_SIGN        1
 #define RSA_CRYPT       2
 
+/*
+ * The above constants may be used even if the RSA module is compile out,
+ * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
+ */
+#if defined(POLARSSL_RSA_C)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index d5a2fc0..354c6c2 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -31,14 +31,40 @@
 #include "net.h"
 #include "bignum.h"
 
-#include "md5.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "sha512.h"
-#include "aes.h"
-
 #include "ssl_ciphersuites.h"
 
+#if defined(POLARSSL_MD5_C)
+#include "md5.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA256_C)
+#include "sha256.h"
+#endif
+
+#if defined(POLARSSL_SHA512_C)
+#include "sha512.h"
+#endif
+
+#if defined(POLARSSL_AES_C)
+#include "aes.h"
+#endif
+#if defined(POLARSSL_ARC4_C)
+#include "arc4.h"
+#endif
+#if defined(POLARSSL_DES_C)
+#include "des.h"
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#include "camellia.h"
+#endif
+#if defined(POLARSSL_GCM_C)
+#include "gcm.h"
+#endif
+
 #if defined(POLARSSL_X509_PARSE_C)
 #include "x509.h"
 #endif
@@ -121,6 +147,44 @@
 #define SSL_MINOR_VERSION_2             2   /*!< TLS v1.1 */
 #define SSL_MINOR_VERSION_3             3   /*!< TLS v1.2 */
 
+/* Determine minimum supported version */
+#define SSL_MIN_MAJOR_VERSION           SSL_MAJOR_VERSION_3
+
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_0
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_1
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1_1)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_2
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_3
+#endif
+#endif
+#endif
+#endif
+
+/* Determine maximum supported version */
+#define SSL_MAX_MAJOR_VERSION           SSL_MAJOR_VERSION_3
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_3
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1_1)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_2
+#else
+#if defined(POLARSSL_SSL_PROTO_TLS1)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_1
+#else
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+#define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_0
+#endif
+#endif
+#endif
+#endif
+
 /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c
  * NONE must be zero so that memset()ing structure to zero works */
 #define SSL_MAX_FRAG_LEN_NONE           0   /*!< don't use this extension   */
@@ -192,6 +256,7 @@
 
 /*
  * Supported Signature and Hash algorithms (For TLS 1.2)
+ * RFC 5246 section 7.4.1.4.1
  */
 #define SSL_HASH_NONE                0
 #define SSL_HASH_MD5                 1
@@ -201,12 +266,16 @@
 #define SSL_HASH_SHA384              5
 #define SSL_HASH_SHA512              6
 
+#define SSL_SIG_ANON                 0
 #define SSL_SIG_RSA                  1
+#define SSL_SIG_ECDSA                3
 
 /*
  * Client Certificate Types
+ * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5
  */
 #define SSL_CERT_TYPE_RSA_SIGN       1
+#define SSL_CERT_TYPE_ECDSA_SIGN    64
 
 /*
  * Message, alert and handshake types
@@ -355,6 +424,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     x509_cert *peer_cert;       /*!< peer X.509 cert chain */
 #endif /* POLARSSL_X509_PARSE_C */
+    int verify_result;          /*!<  verification result     */
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
     unsigned char *ticket;      /*!< RFC 5077 session ticket */
@@ -372,6 +442,40 @@
 };
 
 /*
+ * Helpers to find the correct size of the context in _ssl_transform
+ * (in the long run, we'll use the cipher layer, but for now...)
+ */
+#define SSL_MAX(a, b)       ( a > b ? a : b )
+#define SSL_CTX_MAX_0       0
+#if defined(POLARSSL_AES_C)
+#define SSL_CTX_MAX_1       SSL_MAX( SSL_CTX_MAX_0, sizeof( aes_context ) )
+#else
+#define SSL_CTX_MAX_1       SSL_CTX_MAX_0
+#endif
+#if defined(POLARSSL_ARC4_C)
+#define SSL_CTX_MAX_2       SSL_MAX( SSL_CTX_MAX_1, sizeof( arc4_context ) )
+#else
+#define SSL_CTX_MAX_2       SSL_CTX_MAX_1
+#endif
+#if defined(POLARSSL_DES_C)
+#define SSL_CTX_MAX_3       SSL_MAX( SSL_CTX_MAX_2, sizeof( des_context ) )
+#define SSL_CTX_MAX_4       SSL_MAX( SSL_CTX_MAX_3, sizeof( des3_context ) )
+#else
+#define SSL_CTX_MAX_4       SSL_CTX_MAX_2
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#define SSL_CTX_MAX_5       SSL_MAX( SSL_CTX_MAX_4, sizeof( camellia_context ) )
+#else
+#define SSL_CTX_MAX_5       SSL_CTX_MAX_4
+#endif
+#if defined(POLARSSL_GCM_C)
+#define SSL_CTX_MAX_6       SSL_MAX( SSL_CTX_MAX_5, sizeof( gcm_context ) )
+#else
+#define SSL_CTX_MAX_6       SSL_CTX_MAX_5
+#endif
+#define SSL_CTX_MAX         SSL_CTX_MAX_6
+
+/*
  * This structure contains a full set of runtime transform parameters
  * either in negotiation or active.
  */
@@ -391,16 +495,17 @@
     unsigned char iv_enc[16];           /*!<  IV (encryption)         */
     unsigned char iv_dec[16];           /*!<  IV (decryption)         */
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     /* 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)   */
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 
     md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */
     md_context_t md_ctx_dec;            /*!<  MAC (decryption)        */
 
-    /* 151 == 604 bytes is size of gcm_context (largest context in PolarSSL) */
-    uint32_t ctx_enc[151];              /*!<  encryption context      */
-    uint32_t ctx_dec[151];              /*!<  decryption context      */
+    uint32_t ctx_enc[SSL_CTX_MAX / 4];  /*!<  encryption context      */
+    uint32_t ctx_dec[SSL_CTX_MAX / 4];  /*!<  decryption context      */
 
     /*
      * Session specific compression layer
@@ -411,6 +516,17 @@
 #endif
 };
 
+/* Not needed any more */
+#undef SSL_MAX
+#undef SSL_CTX_MAX_0
+#undef SSL_CTX_MAX_1
+#undef SSL_CTX_MAX_2
+#undef SSL_CTX_MAX_3
+#undef SSL_CTX_MAX_4
+#undef SSL_CTX_MAX_5
+#undef SSL_CTX_MAX_6
+#undef SSL_CTX_MAX
+
 /*
  * This structure contains the parameters only needed during handshake.
  */
@@ -435,10 +551,19 @@
     /*
      * Checksum contexts
      */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
        md5_context fin_md5;
       sha1_context fin_sha1;
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
     sha256_context fin_sha256;
+#endif
+#if defined(POLARSSL_SHA512_C)
     sha512_context fin_sha512;
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
     void (*update_checksum)(ssl_context *, const unsigned char *, size_t);
     void (*calc_verify)(ssl_context *, unsigned char *);
@@ -500,7 +625,6 @@
     int (*f_send)(void *, const unsigned char *, size_t);
     int (*f_get_cache)(void *, ssl_session *);
     int (*f_set_cache)(void *, const ssl_session *);
-    int (*f_sni)(void *, ssl_context *, const unsigned char *, size_t);
 
     void *p_rng;                /*!< context for the RNG function     */
     void *p_dbg;                /*!< context for the debug function   */
@@ -508,9 +632,13 @@
     void *p_send;               /*!< context for writing operations   */
     void *p_get_cache;          /*!< context for cache retrieval      */
     void *p_set_cache;          /*!< context for cache store          */
-    void *p_sni;                /*!< context for SNI extension        */
     void *p_hw_data;            /*!< context for HW acceleration      */
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    int (*f_sni)(void *, ssl_context *, const unsigned char *, size_t);
+    void *p_sni;                /*!< context for SNI extension        */
+#endif
+
 #if defined(POLARSSL_X509_PARSE_C)
     int (*f_vrfy)(void *, x509_cert *, int, int *);
     void *p_vrfy;               /*!< context for verification         */
@@ -571,12 +699,8 @@
     /*
      * PKI layer
      */
-#if defined(POLARSSL_RSA_C)
-    void *rsa_key;                      /*!<  own RSA private key     */
-    rsa_decrypt_func rsa_decrypt;       /*!<  function for RSA decrypt*/
-    rsa_sign_func rsa_sign;             /*!<  function for RSA sign   */
-    rsa_key_len_func rsa_key_len;       /*!<  function for RSA key len*/
-#endif /* POLARSSL_RSA_C */
+    pk_context *pk_key;                 /*!<  own private key         */
+    int pk_key_own_alloc;               /*!<  did we allocate pk_key? */
 
 #if defined(POLARSSL_X509_PARSE_C)
     x509_cert *own_cert;                /*!<  own X.509 certificate   */
@@ -625,11 +749,13 @@
     size_t         psk_identity_len;
 #endif
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     /*
-     * TLS extensions
+     * SNI extension
      */
     unsigned char *hostname;
     size_t         hostname_len;
+#endif
 
     /*
      * Secure renegotiation
@@ -896,13 +1022,31 @@
  *
  * \param ssl      SSL context
  * \param own_cert own public certificate chain
- * \param rsa_key  own private RSA key
+ * \param pk_key   own private key
  */
 void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
-                       rsa_context *rsa_key );
+                       pk_context *pk_key );
+
+#if defined(POLARSSL_RSA_C)
+/**
+ * \brief          Set own certificate chain and private RSA key
+ *
+ *                 Note: own_cert should contain IN order from the bottom
+ *                 up your certificate chain. The top certificate (self-signed)
+ *                 can be omitted.
+ *
+ * \param ssl      SSL context
+ * \param own_cert own public certificate chain
+ * \param rsa_key  own private RSA key
+ *
+ * \return          0 on success, or a specific error code.
+ */
+int ssl_set_own_cert_rsa( ssl_context *ssl, x509_cert *own_cert,
+                          rsa_context *rsa_key );
+#endif /* POLARSSL_RSA_C */
 
 /**
- * \brief          Set own certificate and alternate non-PolarSSL private
+ * \brief          Set own certificate and alternate non-PolarSSL RSA private
  *                 key and handling callbacks, such as the PKCS#11 wrappers
  *                 or any other external private key handler.
  *                 (see the respective RSA functions in rsa.h for documentation
@@ -919,12 +1063,14 @@
  * \param rsa_decrypt_func  alternate implementation of \c rsa_pkcs1_decrypt()
  * \param rsa_sign_func     alternate implementation of \c rsa_pkcs1_sign()
  * \param rsa_key_len_func  function returning length of RSA key in bytes
+ *
+ * \return          0 on success, or a specific error code.
  */
-void ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
-                           void *rsa_key,
-                           rsa_decrypt_func rsa_decrypt,
-                           rsa_sign_func rsa_sign,
-                           rsa_key_len_func rsa_key_len );
+int ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
+                          void *rsa_key,
+                          rsa_decrypt_func rsa_decrypt,
+                          rsa_sign_func rsa_sign,
+                          rsa_key_len_func rsa_key_len );
 #endif /* POLARSSL_X509_PARSE_C */
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
@@ -968,6 +1114,7 @@
 int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
 #endif
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 /**
  * \brief          Set hostname for ServerName TLS extension
  *                 (client-side only)
@@ -1003,15 +1150,17 @@
                   int (*f_sni)(void *, ssl_context *, const unsigned char *,
                                size_t),
                   void *p_sni );
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
 /**
  * \brief          Set the maximum supported version sent from the client side
  *                 and/or accepted at the server side
- *                 (Default: SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3)
+ *                 (Default: SSL_MAX_MAJOR_VERSION, SSL_MAX_MINOR_VERSION)
  *
- *                 Note: This prevents ciphersuites from 'higher' versions to
- *                 be ignored.
- * 
+ *                 Note: This ignores ciphersuites from 'higher' versions.
+ *                 Note: Input outside of the SSL_MAX_XXXXX_VERSION and
+ *                       SSL_MIN_XXXXX_VERSION range is ignored.
+ *
  * \param ssl      SSL context
  * \param major    Major version number (only SSL_MAJOR_VERSION_3 supported)
  * \param minor    Minor version number (SSL_MINOR_VERSION_0,
@@ -1023,7 +1172,10 @@
 
 /**
  * \brief          Set the minimum accepted SSL/TLS protocol version
- *                 (Default: SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0)
+ *                 (Default: SSL_MIN_MAJOR_VERSION, SSL_MIN_MINOR_VERSION)
+ *
+ *                 Note: Input outside of the SSL_MAX_XXXXX_VERSION and
+ *                       SSL_MIN_XXXXX_VERSION range is ignored.
  *
  * \param ssl      SSL context
  * \param major    Major version number (only SSL_MAJOR_VERSION_3 supported)
@@ -1360,6 +1512,10 @@
 
 void ssl_optimize_checksum( ssl_context *ssl, const ssl_ciphersuite_t *ciphersuite_info );
 
+unsigned char ssl_sig_from_pk( pk_context *pk );
+pk_type_t ssl_pk_alg_from_sig( unsigned char sig );
+md_type_t ssl_md_alg_from_hash( unsigned char hash );
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/polarssl/ssl_ciphersuites.h b/include/polarssl/ssl_ciphersuites.h
index 8a489b4..85392c1 100644
--- a/include/polarssl/ssl_ciphersuites.h
+++ b/include/polarssl/ssl_ciphersuites.h
@@ -27,6 +27,7 @@
 #ifndef POLARSSL_SSL_CIPHERSUITES_H
 #define POLARSSL_SSL_CIPHERSUITES_H
 
+#include "pk.h"
 #include "cipher.h"
 #include "md.h"
 
@@ -119,18 +120,33 @@
 #define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     0xC0   /**< TLS 1.2 */
 #define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4   /**< TLS 1.2 */
 
+#define TLS_ECDHE_ECDSA_WITH_NULL_SHA            0xC006 /**< Weak! */
+#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA         0xC007 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA    0xC008 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA     0xC009 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA     0xC00A /**< Not in SSL3! */
+
 #define TLS_ECDHE_RSA_WITH_NULL_SHA              0xC010 /**< Weak! */
 #define TLS_ECDHE_RSA_WITH_RC4_128_SHA           0xC011 /**< Not in SSL3! */
 #define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA      0xC012 /**< Not in SSL3! */
 #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA       0xC013 /**< Not in SSL3! */
 #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA       0xC014 /**< Not in SSL3! */
 
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256  0xC023 /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384  0xC024 /**< TLS 1.2 */
+
 #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256    0xC027 /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384    0xC028 /**< TLS 1.2 */
 
+#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  0xC02B /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  0xC02C /**< TLS 1.2 */
+
 #define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    0xC02F /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    0xC030 /**< TLS 1.2 */
 
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< TLS 1.2 */
+
 #define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256  0xC076 /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384  0xC077 /**< TLS 1.2 */
 
@@ -146,6 +162,7 @@
     POLARSSL_KEY_EXCHANGE_RSA,
     POLARSSL_KEY_EXCHANGE_DHE_RSA,
     POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
+    POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
     POLARSSL_KEY_EXCHANGE_PSK,
     POLARSSL_KEY_EXCHANGE_DHE_PSK,
     POLARSSL_KEY_EXCHANGE_RSA_PSK,
@@ -181,6 +198,8 @@
 const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name );
 const ssl_ciphersuite_t *ssl_ciphersuite_from_id( int ciphersuite_id );
 
+pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info );
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index dc15bb6..e68789c 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -54,7 +54,7 @@
 #define POLARSSL_ERR_X509_CERT_INVALID_ALG                 -0x2300  /**< The algorithm tag or value is invalid. */
 #define POLARSSL_ERR_X509_CERT_INVALID_NAME                -0x2380  /**< The name tag or value is invalid. */
 #define POLARSSL_ERR_X509_CERT_INVALID_DATE                -0x2400  /**< The date tag or value is invalid. */
-#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY              -0x2480  /**< The pubkey tag or value is invalid (only RSA is supported). */
+#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY              -0x2480  /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
 #define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE           -0x2500  /**< The signature tag or value invalid. */
 #define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS          -0x2580  /**< The extension tag or value is invalid. */
 #define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION             -0x2600  /**< Certificate or CRL has an unsupported version number. */
diff --git a/library/bignum.c b/library/bignum.c
index b0bbf8f..f94d08d 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1980,7 +1980,7 @@
     return( ret );
 }
 
-#endif
+#endif /* POLARSSL_GENPRIME */
 
 #if defined(POLARSSL_SELF_TEST)
 
@@ -2092,7 +2092,6 @@
     if( verbose != 0 )
         printf( "passed\n" );
 
-#if defined(POLARSSL_GENPRIME)
     MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
 
     MPI_CHK( mpi_read_string( &U, 16,
@@ -2113,7 +2112,6 @@
 
     if( verbose != 0 )
         printf( "passed\n" );
-#endif
 
     if( verbose != 0 )
         printf( "  MPI test #5 (simple gcd): " );
diff --git a/library/certs.c b/library/certs.c
index e2d07f7..ecfc829 100644
--- a/library/certs.c
+++ b/library/certs.c
@@ -27,6 +27,77 @@
 
 #if defined(POLARSSL_CERTS_C)
 
+#if defined(POLARSSL_ECDSA_C)
+const char test_ca_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIICEjCCAbmgAwIBAgIJAK1CeXaecvbhMAkGByqGSM49BAEwPjELMAkGA1UEBhMC\r\n"
+"TkwxETAPBgNVBAoTCFBvbGFyU1NMMRwwGgYDVQQDExNQb2xhcnNzbCBUZXN0IEVD\r\n"
+"IENBMB4XDTEzMDgwOTA3NDk0NloXDTIzMDgwNzA3NDk0NlowPjELMAkGA1UEBhMC\r\n"
+"TkwxETAPBgNVBAoTCFBvbGFyU1NMMRwwGgYDVQQDExNQb2xhcnNzbCBUZXN0IEVD\r\n"
+"IENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElrizLPspIX2+kNvC+BOpJnw1\r\n"
+"9tnAi5nsUnt8r6N+KDybdaVUWmLIqZCrjuaGKwOdOZtl/bBp8KOpLZ4UDujV/qOB\r\n"
+"oDCBnTAdBgNVHQ4EFgQUvEDvue6auzY54S2porosu6a9EHEwbgYDVR0jBGcwZYAU\r\n"
+"vEDvue6auzY54S2porosu6a9EHGhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQK\r\n"
+"EwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAK1CeXae\r\n"
+"cvbhMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNIADBFAiBs5rd9NzQs/wQZVS6D\r\n"
+"rjpOpzFteqBkqe6YgKWkG5kDVwIhAKr4Lr4v+MU1G5D5oSZXYxvUPBa4yARcD7QM\r\n"
+"espQnlFX\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_ca_key[] =
+"-----BEGIN EC PRIVATE KEY-----\r\n"
+"Proc-Type: 4,ENCRYPTED\r\n"
+"DEK-Info: AES-128-CBC,2A7435F5137D68C6402DB35E5BFD277A\r\n"
+"\r\n"
+"Sw5YgGVvNxXMvnGKYPuUqiDfjXhK/VTQ6dE9+33jwobKJvqR4pIrelw5QbJ5MCi2\r\n"
+"dRGEMi4hT+EiS1UZtagqYUQyYZegZB48eoSRySsfW3kqQ4aG99+4iDLCY+JhICs9\r\n"
+"aZdJhyUSOy2KRnFN/ZUy/Hvlsy10dw/Cp73TpJZmTz4=\r\n"
+"-----END EC PRIVATE KEY-----\r\n";
+
+const char test_ca_pwd[] = "PolarSSLTest";
+
+const char test_srv_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIB7TCCAZSgAwIBAgIBAzAJBgcqhkjOPQQBMD4xCzAJBgNVBAYTAk5MMREwDwYD\r\n"
+"VQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQTAeFw0x\r\n"
+"MzA4MDkwNzU3NDBaFw0yMzA4MDcwNzU3NDBaMDQxCzAJBgNVBAYTAk5MMREwDwYD\r\n"
+"VQQKEwhQb2xhclNTTDESMBAGA1UEAxMJbG9jYWxob3N0MEkwEwYHKoZIzj0CAQYI\r\n"
+"KoZIzj0DAQEDMgAEy0Lh3ZfhEwBiC8jmJfEg8NGxCDqHEtz+hPgYs37hDz9wTOoY\r\n"
+"+CJDtEUcDedgFCpqo4GdMIGaMAkGA1UdEwQCMAAwHQYDVR0OBBYEFKItALYotNzi\r\n"
+"cfBPd7LwETtkYmdBMG4GA1UdIwRnMGWAFLxA77numrs2OeEtqaK6LLumvRBxoUKk\r\n"
+"QDA+MQswCQYDVQQGEwJOTDERMA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1Bv\r\n"
+"bGFyc3NsIFRlc3QgRUMgQ0GCCQCtQnl2nnL24TAJBgcqhkjOPQQBA0gAMEUCIE/J\r\n"
+"rb3TrYL+z1OsZ2rtCmji7hrPj570X4Qkm1Pb5QEvAiEAiq46sM0+1DSAU0u8FcuL\r\n"
+"jbRvSP9W7EJjb9QR3zNYbX4=\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_srv_key[] =
+"-----BEGIN EC PRIVATE KEY-----\r\n"
+"MF8CAQEEGO82j8OXBoUhVyauCA8XZ288l595u7BXWqAKBggqhkjOPQMBAaE0AzIA\r\n"
+"BMtC4d2X4RMAYgvI5iXxIPDRsQg6hxLc/oT4GLN+4Q8/cEzqGPgiQ7RFHA3nYBQq\r\n"
+"ag==\r\n"
+"-----END EC PRIVATE KEY-----\r\n";
+
+const char test_cli_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIBUjCB+gIBEjAJBgcqhkjOPQQBMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQ\r\n"
+"b2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQTAeFw0xMzA4MjIx\r\n"
+"NDQyMTdaFw0yMzA4MjAxNDQyMTdaMD8xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQ\r\n"
+"b2xhclNTTDEdMBsGA1UEAxMUUG9sYXJTU0wgVGVzdCBDbGllbnQwSTATBgcqhkjO\r\n"
+"PQIBBggqhkjOPQMBAQMyAATnnXkhKuPh1tou3B+DV9lyE4IlISuYVm86E776WBm5\r\n"
+"+hNTqK0AaV6gqEL/XdLEGVwwCQYHKoZIzj0EAQNIADBFAiEA/xaze0PZk51nJJSR\r\n"
+"Z5SmN9VlzqgN2aSmL4JQRPzjDr0CIFOmuwP8WRdPUJvXh7NQgvl4kW3xkcrmfd6a\r\n"
+"zJbBMLxH\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_cli_key[] =
+"-----BEGIN EC PRIVATE KEY-----\r\n"
+"MF8CAQEEGCTQxP5vTfEwCWdeLdPqgGQ4AuxGG3gPA6AKBggqhkjOPQMBAaE0AzIA\r\n"
+"BOedeSEq4+HW2i7cH4NX2XITgiUhK5hWbzoTvvpYGbn6E1OorQBpXqCoQv9d0sQZ\r\n"
+"XA==\r\n"
+"-----END EC PRIVATE KEY-----\r\n";
+
+#else /* !POLARSSL_ECDSA_C, so POLARSSL_RSA_C */
 const char test_ca_crt[] =
 "-----BEGIN CERTIFICATE-----\r\n"
 "MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
@@ -123,7 +194,7 @@
 "oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n"
 "GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n"
 "//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n"
-"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
+"Lx/92YdI9op8ppln3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
 "LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n"
 "Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n"
 "ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n"
@@ -185,6 +256,7 @@
 "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"
 "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"
 "-----END RSA PRIVATE KEY-----\r\n";
+#endif /* !POLARSSL_ECDSA_C, so POLARSSL_RSA_C */
 
 const char test_dhm_params[] =
 "-----BEGIN DH PARAMETERS-----\r\n"
@@ -193,4 +265,4 @@
 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
 "-----END DH PARAMETERS-----\r\n";
 
-#endif
+#endif /* POLARSSL_CERTS_C */
diff --git a/library/ecdsa.c b/library/ecdsa.c
index bdb3567..67774c9 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -134,7 +134,7 @@
     if( mpi_cmp_int( r, 1 ) < 0 || mpi_cmp_mpi( r, &grp->N ) >= 0 ||
         mpi_cmp_int( s, 1 ) < 0 || mpi_cmp_mpi( s, &grp->N ) >= 0 )
     {
-        ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
+        ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
 
@@ -168,7 +168,7 @@
 
     if( ecp_is_zero( &R ) )
     {
-        ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
+        ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
 
@@ -177,7 +177,7 @@
      */
     if( mpi_cmp_mpi( &R.X, r ) != 0 )
     {
-        ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
+        ret = POLARSSL_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
 
diff --git a/library/entropy.c b/library/entropy.c
index a6704d7..2352bcf 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -40,7 +40,11 @@
 {
     memset( ctx, 0, sizeof(entropy_context) );
 
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
     sha512_starts( &ctx->accumulator, 0 );
+#else
+    sha256_starts( &ctx->accumulator, 0 );
+#endif
 #if defined(POLARSSL_HAVEGE_C)
     havege_init( &ctx->havege_data );
 #endif
@@ -91,8 +95,11 @@
 
     if( use_len > ENTROPY_BLOCK_SIZE )
     {
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
         sha512( data, len, tmp, 0 );
-
+#else
+        sha256( data, len, tmp, 0 );
+#endif
         p = tmp;
         use_len = ENTROPY_BLOCK_SIZE;
     }
@@ -100,8 +107,13 @@
     header[0] = source_id;
     header[1] = use_len & 0xFF;
 
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
     sha512_update( &ctx->accumulator, header, 2 );
     sha512_update( &ctx->accumulator, p, use_len );
+#else
+    sha256_update( &ctx->accumulator, header, 2 );
+    sha256_update( &ctx->accumulator, p, use_len );
+#endif
 
     return( 0 );
 }
@@ -179,6 +191,7 @@
 
     memset( buf, 0, ENTROPY_BLOCK_SIZE );
 
+#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
     sha512_finish( &ctx->accumulator, buf );
 
     /*
@@ -192,6 +205,21 @@
     memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
     sha512_starts( &ctx->accumulator, 0 );
     sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
+    sha256_finish( &ctx->accumulator, buf );
+
+    /*
+     * Perform second SHA-256 on entropy
+     */
+    sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+
+    /*
+     * Reset accumulator and counters and recycle existing entropy
+     */
+    memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
+    sha256_starts( &ctx->accumulator, 0 );
+    sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+#endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
 
     for( i = 0; i < ctx->source_count; i++ )
         ctx->source[i].size = 0;
diff --git a/library/pk.c b/library/pk.c
index 3711794..77f5034 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -25,6 +25,8 @@
 
 #include "polarssl/config.h"
 
+#if defined(POLARSSL_PK_C)
+
 #include "polarssl/pk.h"
 #include "polarssl/pk_wrap.h"
 
@@ -84,6 +86,7 @@
         case POLARSSL_PK_ECDSA:
             return &ecdsa_info;
 #endif
+        /* POLARSSL_PK_RSA_ALT ommited on purpose */
         default:
             return NULL;
     }
@@ -106,6 +109,35 @@
 }
 
 /*
+ * Initialize an RSA-alt context
+ */
+int pk_init_ctx_rsa_alt( pk_context *ctx, void * key,
+                         pk_rsa_alt_decrypt_func decrypt_func,
+                         pk_rsa_alt_sign_func sign_func,
+                         pk_rsa_alt_key_len_func key_len_func )
+{
+    rsa_alt_context *rsa_alt;
+    const pk_info_t *info = &rsa_alt_info;
+
+    if( ctx == NULL || ctx->pk_info != NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
+        return( POLARSSL_ERR_PK_MALLOC_FAILED );
+
+    ctx->pk_info = info;
+
+    rsa_alt = (rsa_alt_context *) ctx->pk_ctx;
+
+    rsa_alt->key = key;
+    rsa_alt->decrypt_func = decrypt_func;
+    rsa_alt->sign_func = sign_func;
+    rsa_alt->key_len_func = key_len_func;
+
+    return( 0 );
+}
+
+/*
  * Tell if a PK can do the operations of the given type
  */
 int pk_can_do( pk_context *ctx, pk_type_t type )
@@ -118,24 +150,96 @@
 }
 
 /*
+ * Helper for pk_sign and pk_verify
+ */
+static inline int pk_hashlen_helper( md_type_t md_alg, size_t *hash_len )
+{
+    const md_info_t *md_info;
+
+    if( *hash_len != 0 )
+        return( 0 );
+
+    if( ( md_info = md_info_from_type( md_alg ) ) == NULL )
+        return( -1 );
+
+    *hash_len = md_info->size;
+    return( 0 );
+}
+
+/*
  * Verify a signature
  */
 int pk_verify( pk_context *ctx, md_type_t md_alg,
                const unsigned char *hash, size_t hash_len,
                const unsigned char *sig, size_t sig_len )
 {
-    if( ctx == NULL || ctx->pk_info == NULL )
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
         return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
 
     if( ctx->pk_info->verify_func == NULL )
         return( POLARSSL_ERR_PK_TYPE_MISMATCH );
 
-    return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg,
-                                       hash, hash_len,
+    return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
                                        sig, sig_len ) );
 }
 
 /*
+ * Make a signature
+ */
+int pk_sign( pk_context *ctx, md_type_t md_alg,
+             const unsigned char *hash, size_t hash_len,
+             unsigned char *sig, size_t *sig_len,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    if( ctx == NULL || ctx->pk_info == NULL ||
+        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->sign_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
+                                     sig, sig_len, f_rng, p_rng ) );
+}
+
+/*
+ * Decrypt message
+ */
+int pk_decrypt( pk_context *ctx,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output, size_t *olen, size_t osize,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->decrypt_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
+                output, olen, osize, f_rng, p_rng ) );
+}
+
+/*
+ * Encrypt message
+ */
+int pk_encrypt( pk_context *ctx,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output, size_t *olen, size_t osize,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ctx->pk_info->encrypt_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
+                output, olen, osize, f_rng, p_rng ) );
+}
+
+/*
  * Get key size in bits
  */
 size_t pk_get_size( const pk_context *ctx )
@@ -168,3 +272,5 @@
 
     return( ctx->pk_info->name );
 }
+
+#endif /* POLARSSL_PK_C */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index c2a4c7f..94f5282 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -25,11 +25,12 @@
 
 #include "polarssl/config.h"
 
+#if defined(POLARSSL_PK_C)
+
 #include "polarssl/pk_wrap.h"
 
-#if defined(POLARSSL_RSA_C)
+/* Even if RSA not activated, for the sake of RSA-alt */
 #include "polarssl/rsa.h"
-#endif
 
 #if defined(POLARSSL_ECP_C)
 #include "polarssl/ecp.h"
@@ -47,13 +48,14 @@
 #define polarssl_free       free
 #endif
 
-#if defined(POLARSSL_RSA_C)
+/* Used by RSA-alt too */
 static int rsa_can_do( pk_type_t type )
 {
     return( type == POLARSSL_PK_RSA );
 }
 
-static size_t rsa_get_size( const void * ctx )
+#if defined(POLARSSL_RSA_C)
+static size_t rsa_get_size( const void *ctx )
 {
     return( 8 * ((rsa_context *) ctx)->len );
 }
@@ -69,6 +71,45 @@
                 RSA_PUBLIC, md_alg, hash_len, hash, sig ) );
 }
 
+static int rsa_sign_wrap( void *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    *sig_len = ((rsa_context *) ctx)->len;
+
+    return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, RSA_PRIVATE,
+                md_alg, hash_len, hash, sig ) );
+}
+
+static int rsa_decrypt_wrap( void *ctx,
+                    const unsigned char *input, size_t ilen,
+                    unsigned char *output, size_t *olen, size_t osize,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    ((void) f_rng);
+    ((void) p_rng);
+
+    if( ilen != ((rsa_context *) ctx)->len )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    return( rsa_pkcs1_decrypt( (rsa_context *) ctx,
+                RSA_PRIVATE, olen, input, output, osize ) );
+}
+
+static int rsa_encrypt_wrap( void *ctx,
+                    const unsigned char *input, size_t ilen,
+                    unsigned char *output, size_t *olen, size_t osize,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    ((void) osize);
+
+    *olen = ((rsa_context *) ctx)->len;
+
+    return( rsa_pkcs1_encrypt( (rsa_context *) ctx,
+                f_rng, p_rng, RSA_PUBLIC, ilen, input, output ) );
+}
+
 static void *rsa_alloc_wrap( void )
 {
     void *ctx = polarssl_malloc( sizeof( rsa_context ) );
@@ -104,6 +145,9 @@
     rsa_get_size,
     rsa_can_do,
     rsa_verify_wrap,
+    rsa_sign_wrap,
+    rsa_decrypt_wrap,
+    rsa_encrypt_wrap,
     rsa_alloc_wrap,
     rsa_free_wrap,
     rsa_debug,
@@ -127,11 +171,16 @@
 }
 
 #if defined(POLARSSL_ECDSA_C)
-/* Forward declaration */
+/* Forward declarations */
 static int ecdsa_verify_wrap( void *ctx, md_type_t md_alg,
                        const unsigned char *hash, size_t hash_len,
                        const unsigned char *sig, size_t sig_len );
 
+static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
 static int eckey_verify_wrap( void *ctx, md_type_t md_alg,
                        const unsigned char *hash, size_t hash_len,
                        const unsigned char *sig, size_t sig_len )
@@ -141,13 +190,33 @@
 
     ecdsa_init( &ecdsa );
 
-    ret = ecdsa_from_keypair( &ecdsa, ctx ) ||
-          ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );
+    if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
+        ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );
 
     ecdsa_free( &ecdsa );
 
     return( ret );
 }
+
+static int eckey_sign_wrap( void *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+    ecdsa_context ecdsa;
+
+    ecdsa_init( &ecdsa );
+
+    if( ( ret = ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
+        ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len,
+                               f_rng, p_rng );
+
+    ecdsa_free( &ecdsa );
+
+    return( ret );
+}
+
 #endif /* POLARSSL_ECDSA_C */
 
 static void *eckey_alloc_wrap( void )
@@ -180,9 +249,13 @@
     eckey_can_do,
 #if defined(POLARSSL_ECDSA_C)
     eckey_verify_wrap,
+    eckey_sign_wrap,
 #else
     NULL,
+    NULL,
 #endif
+    NULL,
+    NULL,
     eckey_alloc_wrap,
     eckey_free_wrap,
     eckey_debug,
@@ -203,6 +276,9 @@
     eckey_get_size,         /* Same underlying key structure */
     eckeydh_can_do,
     NULL,
+    NULL,
+    NULL,
+    NULL,
     eckey_alloc_wrap,       /* Same underlying key structure */
     eckey_free_wrap,        /* Same underlying key structure */
     eckey_debug,            /* Same underlying key structure */
@@ -225,6 +301,17 @@
                 hash, hash_len, sig, sig_len ) );
 }
 
+static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    ((void) md_alg);
+
+    return( ecdsa_write_signature( (ecdsa_context *) ctx,
+                hash, hash_len, sig, sig_len, f_rng, p_rng ) );
+}
+
 static void *ecdsa_alloc_wrap( void )
 {
     void *ctx = polarssl_malloc( sizeof( ecdsa_context ) );
@@ -247,8 +334,83 @@
     eckey_get_size,     /* Compatible key structures */
     ecdsa_can_do,
     ecdsa_verify_wrap,
+    ecdsa_sign_wrap,
+    NULL,
+    NULL,
     ecdsa_alloc_wrap,
     ecdsa_free_wrap,
     eckey_debug,        /* Compatible key structures */
 };
 #endif /* POLARSSL_ECDSA_C */
+
+/*
+ * Support for alternative RSA-private implementations
+ */
+
+static size_t rsa_alt_get_size( const void *ctx )
+{
+    rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+
+    return( rsa_alt->key_len_func( rsa_alt->key ) );
+}
+
+static int rsa_alt_sign_wrap( void *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   unsigned char *sig, size_t *sig_len,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+
+    *sig_len = rsa_alt->key_len_func( rsa_alt->key );
+
+    return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, RSA_PRIVATE,
+                md_alg, hash_len, hash, sig ) );
+}
+
+static int rsa_alt_decrypt_wrap( void *ctx,
+                    const unsigned char *input, size_t ilen,
+                    unsigned char *output, size_t *olen, size_t osize,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+
+    ((void) f_rng);
+    ((void) p_rng);
+
+    if( ilen != rsa_alt->key_len_func( rsa_alt->key ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    return( rsa_alt->decrypt_func( rsa_alt->key,
+                RSA_PRIVATE, olen, input, output, osize ) );
+}
+
+static void *rsa_alt_alloc_wrap( void )
+{
+    void *ctx = polarssl_malloc( sizeof( rsa_alt_context ) );
+
+    if( ctx != NULL )
+        memset( ctx, 0, sizeof( rsa_alt_context ) );
+
+    return ctx;
+}
+
+static void rsa_alt_free_wrap( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+const pk_info_t rsa_alt_info = {
+    POLARSSL_PK_RSA_ALT,
+    "RSA-alt",
+    rsa_alt_get_size,
+    rsa_can_do,
+    NULL,
+    rsa_alt_sign_wrap,
+    rsa_alt_decrypt_wrap,
+    NULL,
+    rsa_alt_alloc_wrap,
+    rsa_alt_free_wrap,
+    NULL,
+};
+
+#endif /* POLARSSL_PK_C */
diff --git a/library/ssl_cache.c b/library/ssl_cache.c
index f5d3e48..7c7da4b 100644
--- a/library/ssl_cache.c
+++ b/library/ssl_cache.c
@@ -83,6 +83,8 @@
 
         memcpy( session->master, entry->session.master, 48 );
 
+        session->verify_result = entry->session.verify_result;
+
 #if defined(POLARSSL_X509_PARSE_C)
         /*
          * Restore peer certificate (without rest of the original chain)
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index e714a3c..6089ca8 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -40,34 +40,44 @@
 static const int ciphersuite_preference[] =
 {
     /* All AES-256 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
     TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
     TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
     TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
 
     /* All CAMELLIA-256 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
     TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
     TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
     TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
 
     /* All AES-128 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
     TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
     TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
 
     /* All CAMELLIA-128 ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
     TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
     TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
     TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
 
     /* All remaining > 128-bit ephemeral suites */
+    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
     TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
     TLS_ECDHE_RSA_WITH_RC4_128_SHA,
 
     /* The PSK ephemeral suites */
@@ -132,6 +142,7 @@
     /* Weak or NULL suites */
     TLS_DHE_RSA_WITH_DES_CBC_SHA,
     TLS_RSA_WITH_DES_CBC_SHA,
+    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
     TLS_ECDHE_RSA_WITH_NULL_SHA,
     TLS_RSA_WITH_NULL_SHA256,
     TLS_RSA_WITH_NULL_SHA,
@@ -149,12 +160,96 @@
     0
 };
 
-#define MAX_CIPHERSUITES    60
+#define MAX_CIPHERSUITES    128
 static int supported_ciphersuites[MAX_CIPHERSUITES];
 static int supported_init = 0;
 
 static const ssl_ciphersuite_t ciphersuite_definitions[] =
 {
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+    { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+    { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC },
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    { TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_EC | POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
 #if defined(POLARSSL_AES_C)
     { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
@@ -746,16 +841,18 @@
     {
         const int *p = ciphersuite_preference;
         int *q = supported_ciphersuites;
+        size_t i;
+        size_t max = sizeof(supported_ciphersuites) / sizeof(int);
 
         memset( supported_ciphersuites, 0x00, sizeof(supported_ciphersuites) );
 
-        while( *p != 0 )
+        /* Leave room for a final 0 */
+        for( i = 0; i < max - 1 && p[i] != 0; i++ )
         {
-            if( ssl_ciphersuite_from_id( *p ) != NULL )
-                *(q++) = *p;
-
-            p++;
+            if( ssl_ciphersuite_from_id( p[i] ) != NULL )
+                *(q++) = p[i];
         }
+
         supported_init = 1;
     }
 
@@ -819,4 +916,20 @@
     return( cur->id );
 }
 
+pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info )
+{
+    switch( info->key_exchange )
+    {
+        case POLARSSL_KEY_EXCHANGE_DHE_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDHE_RSA:
+            return( POLARSSL_PK_RSA );
+
+        case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
+            return( POLARSSL_PK_ECDSA );
+
+        default:
+            return( POLARSSL_PK_NONE );
+    }
+}
+
 #endif
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 1c2c395..0fccf34 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -51,6 +51,7 @@
 #include <time.h>
 #endif
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 static void ssl_write_hostname_ext( ssl_context *ssl,
                                     unsigned char *buf,
                                     size_t *olen )
@@ -100,6 +101,7 @@
 
     *olen = ssl->hostname_len + 9;
 }
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
 static void ssl_write_renegotiation_ext( ssl_context *ssl,
                                          unsigned char *buf,
@@ -129,12 +131,13 @@
     *olen = 5 + ssl->verify_data_len;
 }
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
 static void ssl_write_signature_algorithms_ext( ssl_context *ssl,
                                                 unsigned char *buf,
                                                 size_t *olen )
 {
     unsigned char *p = buf;
-    unsigned char sig_alg_list[20];
+    unsigned char *sig_alg_list = buf + 6;
     size_t sig_alg_len = 0;
 
     *olen = 0;
@@ -147,6 +150,7 @@
     /*
      * Prepare signature_algorithms extension (TLS 1.2)
      */
+#if defined(POLARSSL_RSA_C)
 #if defined(POLARSSL_SHA512_C)
     sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
     sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
@@ -167,6 +171,29 @@
     sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
     sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
 #endif
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECDSA_C)
+#if defined(POLARSSL_SHA512_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#if defined(POLARSSL_SHA256_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#if defined(POLARSSL_SHA1_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#if defined(POLARSSL_MD5_C)
+    sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
+    sig_alg_list[sig_alg_len++] = SSL_SIG_ECDSA;
+#endif
+#endif /* POLARSSL_ECDSA_C */
 
     /*
      * enum {
@@ -194,10 +221,9 @@
     *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( sig_alg_len      ) & 0xFF );
 
-    memcpy( p, sig_alg_list, sig_alg_len );
-
     *olen = 6 + sig_alg_len;
 }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
 static void ssl_write_supported_elliptic_curves_ext( ssl_context *ssl,
@@ -384,8 +410,8 @@
 
     if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 )
     {
-        ssl->max_major_ver = SSL_MAJOR_VERSION_3;
-        ssl->max_minor_ver = SSL_MINOR_VERSION_3;
+        ssl->max_major_ver = SSL_MAX_MAJOR_VERSION;
+        ssl->max_minor_ver = SSL_MAX_MINOR_VERSION;
     }
 
     /*
@@ -532,14 +558,18 @@
 
     // First write extensions, then the total length
     //
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen );
     ext_len += olen;
+#endif
 
     ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
     ext_len += olen;
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
     ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen );
     ext_len += olen;
+#endif
 
 #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
     ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
@@ -1047,7 +1077,8 @@
     return( 0 );
 }
 
-#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
 static int ssl_parse_server_dh_params( ssl_context *ssl, unsigned char **p,
                                        unsigned char *end )
 {
@@ -1081,9 +1112,11 @@
 
     return( ret );
 }
-#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 static int ssl_parse_server_ecdh_params( ssl_context *ssl,
                                          unsigned char **p,
                                          unsigned char *end )
@@ -1116,7 +1149,8 @@
 
     return( ret );
 }
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) ||                           \
     defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
@@ -1152,56 +1186,47 @@
 #endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED ||
           POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 static int ssl_parse_signature_algorithm( ssl_context *ssl,
                                           unsigned char **p,
                                           unsigned char *end,
-                                          md_type_t *md_alg )
+                                          md_type_t *md_alg,
+                                          pk_type_t *pk_alg )
 {
     ((void) ssl);
     *md_alg = POLARSSL_MD_NONE;
+    *pk_alg = POLARSSL_PK_NONE;
+
+    /* Only in TLS 1.2 */
+    if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+    {
+        return( 0 );
+    }
 
     if( (*p) + 2 > end )
         return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
 
-    if( (*p)[1] != SSL_SIG_RSA )
+    /*
+     * Get hash algorithm
+     */
+    if( ( *md_alg = ssl_md_alg_from_hash( (*p)[0] ) ) == POLARSSL_MD_NONE )
     {
-        SSL_DEBUG_MSG( 2, ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) );
+        SSL_DEBUG_MSG( 2, ( "Server used unsupported "
+                            "HashAlgorithm %d", *(p)[0] ) );
         return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
-    switch( (*p)[0] )
+    /*
+     * Get signature algorithm
+     */
+    if( ( *pk_alg = ssl_pk_alg_from_sig( (*p)[1] ) ) == POLARSSL_PK_NONE )
     {
-#if defined(POLARSSL_MD5_C)
-        case SSL_HASH_MD5:
-            *md_alg = POLARSSL_MD_MD5;
-            break;
-#endif
-#if defined(POLARSSL_SHA1_C)
-        case SSL_HASH_SHA1:
-            *md_alg = POLARSSL_MD_SHA1;
-            break;
-#endif
-#if defined(POLARSSL_SHA256_C)
-        case SSL_HASH_SHA224:
-            *md_alg = POLARSSL_MD_SHA224;
-            break;
-        case SSL_HASH_SHA256:
-            *md_alg = POLARSSL_MD_SHA256;
-            break;
-#endif
-#if defined(POLARSSL_SHA512_C)
-        case SSL_HASH_SHA384:
-            *md_alg = POLARSSL_MD_SHA384;
-            break;
-        case SSL_HASH_SHA512:
-            *md_alg = POLARSSL_MD_SHA512;
-            break;
-#endif
-        default:
-            SSL_DEBUG_MSG( 2, ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) );
-            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+        SSL_DEBUG_MSG( 2, ( "server used unsupported "
+                            "SignatureAlgorithm %d", (*p)[1] ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
     SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) );
@@ -1211,7 +1236,9 @@
     return( 0 );
 }
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 static int ssl_parse_server_key_exchange( ssl_context *ssl )
 {
@@ -1219,17 +1246,20 @@
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
     unsigned char *p, *end;
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-    size_t n;
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    size_t sig_len, params_len;
     unsigned char hash[64];
     md_type_t md_alg = POLARSSL_MD_NONE;
-    unsigned int hashlen = 0;
-#endif 
+    size_t hashlen;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+#endif
 
     SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
 
     if( ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_RSA &&
         ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA &&
+        ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA &&
         ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_PSK &&
         ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
@@ -1278,8 +1308,10 @@
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA )
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
         if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
         {
@@ -1288,7 +1320,8 @@
         }
     }
     else
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK )
     {
@@ -1321,50 +1354,78 @@
     }
 
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ||
-        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA )
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
+        params_len = p - ( ssl->in_msg + 4 );
+
         /*
          * Handle the digitally-signed structure
          */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
         if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
         {
-            if( ssl_parse_signature_algorithm( ssl, &p, end, &md_alg ) != 0 )
+            if( ssl_parse_signature_algorithm( ssl, &p, end,
+                                               &md_alg, &pk_alg ) != 0 )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+                return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+            }
+
+            if( pk_alg != ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
             {
                 SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
                 return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
             }
         }
+        else
+#endif
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+        {
+            pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
 
-        n = ( p[0] << 8 ) | p[1];
+            /* Default hash for ECDSA is SHA-1 */
+            if( pk_alg == POLARSSL_PK_ECDSA && md_alg == POLARSSL_MD_NONE )
+                md_alg = POLARSSL_MD_SHA1;
+        }
+        else
+#endif
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        /*
+         * Read signature
+         */
+        sig_len = ( p[0] << 8 ) | p[1];
         p += 2;
 
-        if( end != p + n )
+        if( end != p + sig_len )
         {
             SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
             return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
 
-        if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk,
-                         POLARSSL_PK_RSA ) )
-        {
-            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
-        }
+        SSL_DEBUG_BUF( 3, "signature", p, sig_len );
 
-        if( 8 * (unsigned int)( end - p ) !=
-            pk_get_size( &ssl->session_negotiate->peer_cert->pk ) )
-        {
-            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-
-        if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+        /*
+         * Compute the hash that has been signed
+         */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if( md_alg == POLARSSL_MD_NONE )
         {
             md5_context md5;
             sha1_context sha1;
 
+            hashlen = 36;
+
             /*
              * digitally-signed struct {
              *     opaque md5_hash[16];
@@ -1378,26 +1439,27 @@
              *     SHA(ClientHello.random + ServerHello.random
              *                            + ServerParams);
              */
-            n = ssl->in_hslen - ( end - p ) - 6;
-
             md5_starts( &md5 );
             md5_update( &md5, ssl->handshake->randbytes, 64 );
-            md5_update( &md5, ssl->in_msg + 4, n );
+            md5_update( &md5, ssl->in_msg + 4, params_len );
             md5_finish( &md5, hash );
 
             sha1_starts( &sha1 );
             sha1_update( &sha1, ssl->handshake->randbytes, 64 );
-            sha1_update( &sha1, ssl->in_msg + 4, n );
+            sha1_update( &sha1, ssl->in_msg + 4, params_len );
             sha1_finish( &sha1, hash + 16 );
-
-            md_alg = POLARSSL_MD_NONE;
-            hashlen = 36;
         }
         else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( md_alg != POLARSSL_MD_NONE )
         {
             md_context_t ctx;
 
-            n = ssl->in_hslen - ( end - p ) - 8;
+            /* Info from md_alg will be used instead */
+            hashlen = 0;
 
             /*
              * digitally-signed struct {
@@ -1414,23 +1476,40 @@
 
             md_starts( &ctx );
             md_update( &ctx, ssl->handshake->randbytes, 64 );
-            md_update( &ctx, ssl->in_msg + 4, n );
+            md_update( &ctx, ssl->in_msg + 4, params_len );
             md_finish( &ctx, hash );
             md_free_ctx( &ctx );
         }
-
-        SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
-
-        if( ( ret = rsa_pkcs1_verify(
-                        pk_rsa( ssl->session_negotiate->peer_cert->pk ),
-                        RSA_PUBLIC, md_alg, hashlen, hash, p ) ) != 0 )
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
         {
-            SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
+                (unsigned int) ( md_info_from_type( md_alg ) )->size );
+
+        /*
+         * Verify signature
+         */
+        if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+            return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+        }
+
+        if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk,
+                               md_alg, hash, hashlen, p, sig_len ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "pk_verify", ret );
             return( ret );
         }
     }
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 exit:
     ssl->state++;
@@ -1445,7 +1524,7 @@
     int ret;
     unsigned char *buf, *p;
     size_t n = 0, m = 0;
-    size_t cert_type_len = 0, sig_alg_len = 0, dn_len = 0;
+    size_t cert_type_len = 0, dn_len = 0;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
 
@@ -1527,10 +1606,11 @@
         return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
     }
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
     {
-        sig_alg_len = ( ( buf[5 + n] <<  8 )
-                      | ( buf[6 + n]       ) );
+        size_t sig_alg_len = ( ( buf[5 + n] <<  8 )
+                             | ( buf[6 + n]       ) );
 
         p = buf + 7 + n;
         m += 2;
@@ -1542,6 +1622,7 @@
             return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
         }
     }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
     dn_len = ( ( buf[5 + m + n] <<  8 )
              | ( buf[6 + m + n]       ) );
@@ -1642,8 +1723,10 @@
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA )
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
         /*
          * ECDH key exchange -- send client public value
@@ -1674,7 +1757,8 @@
         SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z );
     }
     else
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK )
     {
@@ -1805,26 +1889,27 @@
             return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
         }
 
-        i = 4;
-        n = pk_get_size( &ssl->session_negotiate->peer_cert->pk ) / 8;
+        i = ssl->minor_ver == SSL_MINOR_VERSION_0 ? 4 : 6;
 
-        if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
-        {
-            i += 2;
-            ssl->out_msg[4] = (unsigned char)( n >> 8 );
-            ssl->out_msg[5] = (unsigned char)( n      );
-        }
-
-        ret = rsa_pkcs1_encrypt(
-                pk_rsa( ssl->session_negotiate->peer_cert->pk ),
-                ssl->f_rng, ssl->p_rng, RSA_PUBLIC,
-                ssl->handshake->pmslen, ssl->handshake->premaster,
-                ssl->out_msg + i );
+        ret = pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
+                ssl->handshake->premaster, ssl->handshake->pmslen,
+                ssl->out_msg + i, &n, SSL_BUFFER_LEN,
+                ssl->f_rng, ssl->p_rng );
         if( ret != 0 )
         {
             SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
             return( ret );
         }
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+        {
+            ssl->out_msg[4] = (unsigned char)( n >> 8 );
+            ssl->out_msg[5] = (unsigned char)( n      );
+        }
+#endif
+
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
@@ -1883,8 +1968,9 @@
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
     size_t n = 0, offset = 0;
     unsigned char hash[48];
+    unsigned char *hash_start = hash;
     md_type_t md_alg = POLARSSL_MD_NONE;
-    unsigned int hashlen = 0;
+    unsigned int hashlen;
 
     SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
 
@@ -1903,7 +1989,7 @@
         return( 0 );
     }
 
-    if( ssl->rsa_key == NULL )
+    if( ssl->pk_key == NULL )
     {
         SSL_DEBUG_MSG( 1, ( "got no private key" ) );
         return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
@@ -1914,6 +2000,8 @@
      */
     ssl->handshake->calc_verify( ssl, hash );
 
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
     if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
     {
         /*
@@ -1930,8 +2018,22 @@
          */
         hashlen = 36;
         md_alg = POLARSSL_MD_NONE;
+
+        /*
+         * For ECDSA, default hash is SHA-1 only
+         */
+        if( pk_can_do( ssl->pk_key, POLARSSL_PK_ECDSA ) )
+        {
+            hash_start += 16;
+            hashlen -= 16;
+            md_alg = POLARSSL_MD_SHA1;
+        }
     }
     else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
     {
         /*
          * digitally-signed struct {
@@ -1953,37 +2055,36 @@
         {
             md_alg = POLARSSL_MD_SHA384;
             ssl->out_msg[4] = SSL_HASH_SHA384;
-            ssl->out_msg[5] = SSL_SIG_RSA;
         }
         else
         {
             md_alg = POLARSSL_MD_SHA256;
             ssl->out_msg[4] = SSL_HASH_SHA256;
-            ssl->out_msg[5] = SSL_SIG_RSA;
         }
+        ssl->out_msg[5] = ssl_sig_from_pk( ssl->pk_key );
 
+        /* Info from md_alg will be used instead */
+        hashlen = 0;
         offset = 2;
     }
+    else
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
 
-    if ( ssl->rsa_key )
-        n = ssl->rsa_key_len ( ssl->rsa_key );
+    if( ( ret = pk_sign( ssl->pk_key, md_alg, hash_start, hashlen,
+                         ssl->out_msg + 6 + offset, &n,
+                         ssl->f_rng, ssl->p_rng ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "pk_sign", ret );
+        return( ret );
+    }
 
     ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
     ssl->out_msg[5 + offset] = (unsigned char)( n      );
 
-    if( ssl->rsa_key )
-    {
-        ret = ssl->rsa_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
-                             RSA_PRIVATE, md_alg,
-                             hashlen, hash, ssl->out_msg + 6 + offset );
-    }
-
-    if (ret != 0)
-    {
-        SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
-        return( ret );
-    }
-
     ssl->out_msglen  = 6 + n + offset;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = SSL_HS_CERTIFICATE_VERIFY;
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 0780da5..5bedcad 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -56,16 +56,22 @@
  *
  *  Assumes ticket is NULL (always true on server side).
  */
-static void ssl_save_session( const ssl_session *session,
-                              unsigned char *buf, size_t *olen )
+static int ssl_save_session( const ssl_session *session,
+                             unsigned char *buf, size_t buf_len,
+                             size_t *olen )
 {
     unsigned char *p = buf;
+    size_t left = buf_len;
 #if defined(POLARSSL_X509_PARSE_C)
     size_t cert_len;
 #endif /* POLARSSL_X509_PARSE_C */
 
+    if( left < sizeof( ssl_session ) )
+        return( -1 );
+
     memcpy( p, session, sizeof( ssl_session ) );
     p += sizeof( ssl_session );
+    left -= sizeof( ssl_session );
 
 #if defined(POLARSSL_X509_PARSE_C)
     ((ssl_session *) buf)->peer_cert = NULL;
@@ -75,6 +81,9 @@
     else
         cert_len = session->peer_cert->raw.len;
 
+    if( left < 3 + cert_len )
+        return( -1 );
+
     *p++ = (unsigned char)( cert_len >> 16 & 0xFF );
     *p++ = (unsigned char)( cert_len >>  8 & 0xFF );
     *p++ = (unsigned char)( cert_len       & 0xFF );
@@ -86,6 +95,8 @@
 #endif /* POLARSSL_X509_PARSE_C */
 
     *olen = p - buf;
+
+    return( 0 );
 }
 
 /*
@@ -169,6 +180,8 @@
     unsigned char iv[16];
     size_t clear_len, enc_len, pad_len, i;
 
+    *tlen = 0;
+
     if( ssl->ticket_keys == NULL )
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
 
@@ -182,9 +195,19 @@
     memcpy( iv, p, 16 );
     p += 16;
 
-    /* Dump session state */
+    /*
+     * Dump session state
+     *
+     * After the session state itself, we still need room for 16 bytes of
+     * padding and 32 bytes of MAC, so there's only so much room left
+     */
     state = p + 2;
-    ssl_save_session( ssl->session_negotiate, state, &clear_len );
+    if( ssl_save_session( ssl->session_negotiate, state,
+                          SSL_MAX_CONTENT_LEN - (state - ssl->out_ctr) - 48,
+                          &clear_len ) != 0 )
+    {
+        return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
+    }
     SSL_DEBUG_BUF( 3, "session ticket cleartext", state, clear_len );
 
     /* Apply PKCS padding */
@@ -313,6 +336,7 @@
 }
 #endif /* POLARSSL_SSL_SESSION_TICKETS */
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 static int ssl_parse_servername_ext( ssl_context *ssl,
                                      const unsigned char *buf,
                                      size_t len )
@@ -362,6 +386,7 @@
 
     return( 0 );
 }
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
 static int ssl_parse_renegotiation_info( ssl_context *ssl,
                                          const unsigned char *buf,
@@ -401,6 +426,7 @@
     return( 0 );
 }
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
 static int ssl_parse_signature_algorithms_ext( ssl_context *ssl,
                                                const unsigned char *buf,
                                                size_t len )
@@ -419,12 +445,10 @@
     p = buf + 2;
     while( sig_alg_list_size > 0 )
     {
-        if( p[1] != SSL_SIG_RSA )
-        {
-            sig_alg_list_size -= 2;
-            p += 2;
-            continue;
-        }
+        /*
+         * For now, just ignore signature algorithm and rely on offered
+         * ciphersuites only. To be fixed later.
+         */
 #if defined(POLARSSL_SHA512_C)
         if( p[0] == SSL_HASH_SHA512 )
         {
@@ -469,6 +493,7 @@
 
     return( 0 );
 }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
 static int ssl_parse_supported_elliptic_curves( ssl_context *ssl,
@@ -889,6 +914,7 @@
     int handshake_failure = 0;
     const int *ciphersuites;
     const ssl_ciphersuite_t *ciphersuite_info;
+    pk_type_t pk_alg;
 
     SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
 
@@ -1132,6 +1158,7 @@
         }
         switch( ext_id )
         {
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
         case TLS_EXT_SERVERNAME:
             SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
             if( ssl->f_sni == NULL )
@@ -1141,6 +1168,7 @@
             if( ret != 0 )
                 return( ret );
             break;
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
         case TLS_EXT_RENEGOTIATION_INFO:
             SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
@@ -1151,6 +1179,7 @@
                 return( ret );
             break;
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
         case TLS_EXT_SIG_ALG:
             SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
             if( ssl->renegotiation == SSL_RENEGOTIATION )
@@ -1160,6 +1189,7 @@
             if( ret != 0 )
                 return( ret );
             break;
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
         case TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
@@ -1280,7 +1310,7 @@
 
                 if( ciphersuite_info == NULL )
                 {
-                    SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found",
+                    SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found",
                                    ciphersuites[i] ) );
                     return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
                 }
@@ -1295,6 +1325,14 @@
                     continue;
 #endif
 
+                /* If ciphersuite requires us to have a private key of a
+                 * certain type, make sure we do */
+                pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
+                if( pk_alg != POLARSSL_PK_NONE &&
+                    ( ssl->pk_key == NULL ||
+                      ! pk_can_do( ssl->pk_key, pk_alg ) ) )
+                    continue;
+
                 goto have_ciphersuite;
             }
         }
@@ -1580,9 +1618,9 @@
     *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite      );
     *p++ = (unsigned char)( ssl->session_negotiate->compression      );
 
-    SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d",
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: 0x%04X",
                    ssl->session_negotiate->ciphersuite ) );
-    SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
+    SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
                    ssl->session_negotiate->compression ) );
 
     /*
@@ -1653,7 +1691,8 @@
 {
     int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
-    size_t n = 0, dn_size, total_dn_size;
+    size_t dn_size, total_dn_size; /* excluding length bytes */
+    size_t ct_len, sa_len; /* including length bytes */
     unsigned char *buf, *p;
     const x509_cert *crt;
 
@@ -1685,37 +1724,75 @@
     p = buf + 4;
 
     /*
-     * At the moment, only RSA certificates are supported
+     * Supported certificate types
+     *
+     *     ClientCertificateType certificate_types<1..2^8-1>;
+     *     enum { (255) } ClientCertificateType;
      */
-    *p++ = 1;
-    *p++ = SSL_CERT_TYPE_RSA_SIGN;
+    ct_len = 0;
 
+#if defined(POLARSSL_RSA_C)
+    p[1 + ct_len++] = SSL_CERT_TYPE_RSA_SIGN;
+#endif
+#if defined(POLARSSL_ECDSA_C)
+    p[1 + ct_len++] = SSL_CERT_TYPE_ECDSA_SIGN;
+#endif
+
+    p[0] = ct_len++;
+    p += ct_len;
+
+    sa_len = 0;
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
     /*
      * Add signature_algorithms for verify (TLS 1.2)
-     * Only add current running algorithm that is already required for
-     * requested ciphersuite.
      *
-     * Length is always 2
+     *     SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;
+     *
+     *     struct {
+     *           HashAlgorithm hash;
+     *           SignatureAlgorithm signature;
+     *     } SignatureAndHashAlgorithm;
+     *
+     *     enum { (255) } HashAlgorithm;
+     *     enum { (255) } SignatureAlgorithm;
      */
     if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
     {
+        /*
+         * Only use current running hash algorithm that is already required
+         * for requested ciphersuite.
+         */
         ssl->handshake->verify_sig_alg = SSL_HASH_SHA256;
 
-        *p++ = 0;
-        *p++ = 2;
-
         if( ssl->transform_negotiate->ciphersuite_info->mac ==
             POLARSSL_MD_SHA384 )
         {
             ssl->handshake->verify_sig_alg = SSL_HASH_SHA384;
         }
 
-        *p++ = ssl->handshake->verify_sig_alg;
-        *p++ = SSL_SIG_RSA;
+        /*
+         * Supported signature algorithms
+         */
+#if defined(POLARSSL_RSA_C)
+        p[2 + sa_len++] = ssl->handshake->verify_sig_alg;
+        p[2 + sa_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_ECDSA_C)
+        p[2 + sa_len++] = ssl->handshake->verify_sig_alg;
+        p[2 + sa_len++] = SSL_SIG_ECDSA;
+#endif
 
-        n += 4;
+        p[0] = (unsigned char)( sa_len >> 8 );
+        p[1] = (unsigned char)( sa_len      );
+        sa_len += 2;
+        p += sa_len;
     }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
+    /*
+     * DistinguishedName certificate_authorities<0..2^16-1>;
+     * opaque DistinguishedName<1..2^16-1>;
+     */
     p += 2;
     crt = ssl->ca_chain;
 
@@ -1740,8 +1817,8 @@
     ssl->out_msglen  = p - buf;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = SSL_HS_CERTIFICATE_REQUEST;
-    ssl->out_msg[6 + n]  = (unsigned char)( total_dn_size  >> 8 );
-    ssl->out_msg[7 + n]  = (unsigned char)( total_dn_size       );
+    ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size  >> 8 );
+    ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size       );
 
     ret = ssl_write_record( ssl );
 
@@ -1761,8 +1838,8 @@
     md_type_t md_alg = POLARSSL_MD_NONE;
     unsigned int hashlen = 0;
     unsigned char *p = ssl->out_msg + 4;
-    unsigned char *dig_sig = p;
-    size_t dig_sig_len = 0;
+    unsigned char *dig_signed = p;
+    size_t dig_signed_len = 0;
 
     const ssl_ciphersuite_t *ciphersuite_info;
     ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
@@ -1771,6 +1848,7 @@
 
     if( ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_RSA &&
         ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_RSA &&
+        ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA &&
         ciphersuite_info->key_exchange != POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
         SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
@@ -1778,14 +1856,6 @@
         return( 0 );
     }
 
-#if defined(POLARSSL_RSA_C)
-    if( ssl->rsa_key == NULL )
-    {
-        SSL_DEBUG_MSG( 1, ( "got no private key" ) );
-        return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
-    }
-#endif /* POLARSSL_RSA_C */
-
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
@@ -1827,8 +1897,8 @@
             return( ret );
         }
 
-        dig_sig = p;
-        dig_sig_len = len;
+        dig_signed = p;
+        dig_signed_len = len;
 
         p += len;
         n += len;
@@ -1841,8 +1911,10 @@
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
           POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA )
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
         /*
          * Ephemeral ECDH parameters:
@@ -1868,24 +1940,61 @@
             return( ret );
         }
 
-        dig_sig = p;
-        dig_sig_len = len;
+        dig_signed = p;
+        dig_signed_len = len;
 
         p += len;
         n += len;
 
         SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
     }
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA ||
-        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA )
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
-        size_t rsa_key_len = 0;
+        size_t signature_len = 0;
 
-        if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+        /*
+         * Choose hash algorithm. NONE means MD5 + SHA1 here.
+         */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+        {
+            md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg );
+
+            if( md_alg == POLARSSL_MD_NONE )
+            {
+                SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            }
+        }
+        else
+#endif
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if ( ciphersuite_info->key_exchange ==
+                  POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+        {
+            md_alg = POLARSSL_MD_SHA1;
+        }
+        else
+#endif
+        {
+            md_alg = POLARSSL_MD_NONE;
+        }
+
+        /*
+         * Compute the hash to be signed
+         */
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+        if( md_alg == POLARSSL_MD_NONE )
         {
             md5_context md5;
             sha1_context sha1;
@@ -1905,21 +2014,28 @@
              */
             md5_starts( &md5 );
             md5_update( &md5, ssl->handshake->randbytes,  64 );
-            md5_update( &md5, dig_sig, dig_sig_len );
+            md5_update( &md5, dig_signed, dig_signed_len );
             md5_finish( &md5, hash );
 
             sha1_starts( &sha1 );
             sha1_update( &sha1, ssl->handshake->randbytes,  64 );
-            sha1_update( &sha1, dig_sig, dig_sig_len );
+            sha1_update( &sha1, dig_signed, dig_signed_len );
             sha1_finish( &sha1, hash + 16 );
 
             hashlen = 36;
-            md_alg = POLARSSL_MD_NONE;
         }
         else
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
+          POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( md_alg != POLARSSL_MD_NONE )
         {
             md_context_t ctx;
 
+            /* Info from md_alg will be used instead */
+            hashlen = 0;
+
             /*
              * digitally-signed struct {
              *     opaque client_random[32];
@@ -1927,40 +2043,7 @@
              *     ServerDHParams params;
              * };
              */
-            switch( ssl->handshake->sig_alg )
-            {
-#if defined(POLARSSL_MD5_C)
-                case SSL_HASH_MD5:
-                    md_alg = POLARSSL_MD_MD5;
-                    break;
-#endif
-#if defined(POLARSSL_SHA1_C)
-                case SSL_HASH_SHA1:
-                    md_alg = POLARSSL_MD_SHA1;
-                    break;
-#endif
-#if defined(POLARSSL_SHA256_C)
-                case SSL_HASH_SHA224:
-                    md_alg = POLARSSL_MD_SHA224;
-                    break;
-                case SSL_HASH_SHA256:
-                    md_alg = POLARSSL_MD_SHA256;
-                    break;
-#endif
-#if defined(POLARSSL_SHA512_C)
-                case SSL_HASH_SHA384:
-                    md_alg = POLARSSL_MD_SHA384;
-                    break;
-                case SSL_HASH_SHA512:
-                    md_alg = POLARSSL_MD_SHA512;
-                    break;
-#endif
-                default:
-                    /* Should never happen */
-                    return( -1 );
-            }
-
-            if( ( ret = md_init_ctx( &ctx, md_info_from_type( md_alg ) ) ) != 0 )
+            if( ( ret = md_init_ctx( &ctx, md_info_from_type(md_alg) ) ) != 0 )
             {
                 SSL_DEBUG_RET( 1, "md_init_ctx", ret );
                 return( ret );
@@ -1968,7 +2051,7 @@
 
             md_starts( &ctx );
             md_update( &ctx, ssl->handshake->randbytes, 64 );
-            md_update( &ctx, dig_sig, dig_sig_len );
+            md_update( &ctx, dig_signed, dig_signed_len );
             md_finish( &ctx, hash );
 
             if( ( ret = md_free_ctx( &ctx ) ) != 0 )
@@ -1978,43 +2061,56 @@
             }
 
         }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
 
-        SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
+        SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
+                (unsigned int) ( md_info_from_type( md_alg ) )->size );
 
-        if ( ssl->rsa_key )
-            rsa_key_len = ssl->rsa_key_len( ssl->rsa_key );
+        /*
+         * Make the signature
+         */
+        if( ssl->pk_key == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+            return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+        }
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
         if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
         {
             *(p++) = ssl->handshake->sig_alg;
-            *(p++) = SSL_SIG_RSA;
+            *(p++) = ssl_sig_from_pk( ssl->pk_key );
 
             n += 2;
         }
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
-        *(p++) = (unsigned char)( rsa_key_len >> 8 );
-        *(p++) = (unsigned char)( rsa_key_len      );
-        n += 2;
-
-        if ( ssl->rsa_key )
+        if( ( ret = pk_sign( ssl->pk_key, md_alg, hash, hashlen,
+                        p + 2 , &signature_len,
+                        ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
-            ret = ssl->rsa_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
-                    RSA_PRIVATE, md_alg, hashlen, hash, p );
-        }
-
-        if( ret != 0 )
-        {
-            SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+            SSL_DEBUG_RET( 1, "pk_sign", ret );
             return( ret );
         }
 
-        SSL_DEBUG_BUF( 3, "my RSA sig", p, rsa_key_len );
+        *(p++) = (unsigned char)( signature_len >> 8 );
+        *(p++) = (unsigned char)( signature_len      );
+        n += 2;
 
-        p += rsa_key_len;
-        n += rsa_key_len;
+        SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
+
+        p += signature_len;
+        n += signature_len;
     }
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+          POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
     ssl->out_msglen  = 4 + n;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
@@ -2096,7 +2192,8 @@
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
           POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 static int ssl_parse_client_ecdh_public( ssl_context *ssl )
 {
     int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -2125,7 +2222,8 @@
 
     return( ret );
 }
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 #if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
 static int ssl_parse_encrypted_pms_secret( ssl_context *ssl )
@@ -2133,9 +2231,9 @@
     int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     size_t i, n = 0;
 
-    if( ssl->rsa_key == NULL )
+    if( ! pk_can_do( ssl->pk_key, POLARSSL_PK_RSA ) )
     {
-        SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+        SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
         return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
     }
 
@@ -2143,10 +2241,11 @@
      * Decrypt the premaster using own private RSA key
      */
     i = 4;
-    if( ssl->rsa_key )
-        n = ssl->rsa_key_len( ssl->rsa_key );
+    n = pk_get_len( ssl->pk_key );
     ssl->handshake->pmslen = 48;
 
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
     {
         i += 2;
@@ -2157,6 +2256,7 @@
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
         }
     }
+#endif
 
     if( ssl->in_hslen != i + n )
     {
@@ -2164,13 +2264,11 @@
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
     }
 
-    if( ssl->rsa_key ) {
-        ret = ssl->rsa_decrypt( ssl->rsa_key, RSA_PRIVATE,
-                               &ssl->handshake->pmslen,
-                                ssl->in_msg + i,
-                                ssl->handshake->premaster,
-                                sizeof(ssl->handshake->premaster) );
-    }
+    ret = pk_decrypt( ssl->pk_key,
+                      ssl->in_msg + i, n,
+                      ssl->handshake->premaster, &ssl->handshake->pmslen,
+                      sizeof(ssl->handshake->premaster),
+                      ssl->f_rng, ssl->p_rng );
 
     if( ret != 0 || ssl->handshake->pmslen != 48 ||
         ssl->handshake->premaster[0] != ssl->handshake->max_major_ver ||
@@ -2298,8 +2396,10 @@
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA )
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
     {
         if( ( ret = ssl_parse_client_ecdh_public( ssl ) ) != 0 )
         {
@@ -2319,7 +2419,8 @@
         SSL_DEBUG_MPI( 3, "ECDH: z  ", &ssl->handshake->ecdh_ctx.z );
     }
     else
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK )
     {
@@ -2367,6 +2468,8 @@
         *(p++) = (unsigned char)( ssl->handshake->dhm_ctx.len >> 8 );
         *(p++) = (unsigned char)( ssl->handshake->dhm_ctx.len      );
 
+        n = ssl->handshake->dhm_ctx.len;
+
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       p, &n ) ) != 0 )
         {
@@ -2405,6 +2508,7 @@
     else
 #endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
     {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
         return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
     }
 
@@ -2445,10 +2549,14 @@
 static int ssl_parse_certificate_verify( ssl_context *ssl )
 {
     int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
-    size_t n = 0, n1, n2;
+    size_t sa_len, sig_len;
     unsigned char hash[48];
-    md_type_t md_alg = POLARSSL_MD_NONE;
-    unsigned int hashlen = 0;
+    unsigned char *hash_start = hash;
+    size_t hashlen;
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    pk_type_t pk_alg;
+#endif
+    md_type_t md_alg;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
@@ -2490,54 +2598,94 @@
         return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
     }
 
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   sig alg (TLS 1.2 only)
+     *    4+n .  5+n  signature length (n = sa_len)
+     *    6+n . 6+n+m signature (m = sig_len)
+     */
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+    if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+    {
+        sa_len = 0;
+
+        md_alg = POLARSSL_MD_NONE;
+        hashlen = 36;
+
+        /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
+        if( pk_can_do( &ssl->session_negotiate->peer_cert->pk,
+                        POLARSSL_PK_ECDSA ) )
+        {
+            hash_start += 16;
+            hashlen -= 16;
+            md_alg = POLARSSL_MD_SHA1;
+        }
+    }
+    else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
     {
+        sa_len = 2;
+
         /*
-         * As server we know we either have SSL_HASH_SHA384 or
-         * SSL_HASH_SHA256
+         * Hash
          */
-        if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg ||
-            ssl->in_msg[5] != SSL_SIG_RSA )
+        if( ssl->in_msg[4] != ssl->handshake->verify_sig_alg )
         {
-            SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg for verify message" ) );
+            SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
+                                " for verify message" ) );
             return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
         }
 
-        if( ssl->handshake->verify_sig_alg == SSL_HASH_SHA384 )
-            md_alg = POLARSSL_MD_SHA384;
-        else
-            md_alg = POLARSSL_MD_SHA256;
+        md_alg = ssl_md_alg_from_hash( ssl->handshake->verify_sig_alg );
 
-        n += 2;
+        /* Info from md_alg will be used instead */
+        hashlen = 0;
+
+        /*
+         * Signature
+         */
+        if( ( pk_alg = ssl_pk_alg_from_sig( ssl->in_msg[5] ) )
+                        == POLARSSL_PK_NONE )
+        {
+            SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
+                                " for verify message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        }
+
+        /*
+         * Check the certificate's key type matches the signature alg
+         */
+        if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
+        {
+            SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+        }
     }
     else
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
     {
-        hashlen = 36;
-        md_alg = POLARSSL_MD_NONE;
-    }
-
-    /* EC NOT IMPLEMENTED YET */
-    if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk,
-                     POLARSSL_PK_RSA ) )
-    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
         return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
     }
 
-    n1 = pk_get_size( &ssl->session_negotiate->peer_cert->pk ) / 8;
-    n2 = ( ssl->in_msg[4 + n] << 8 ) | ssl->in_msg[5 + n];
+    sig_len = ( ssl->in_msg[4 + sa_len] << 8 ) | ssl->in_msg[5 + sa_len];
 
-    if( n + n1 + 6 != ssl->in_hslen || n1 != n2 )
+    if( sa_len + sig_len + 6 != ssl->in_hslen )
     {
         SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
     }
 
-    ret = rsa_pkcs1_verify( pk_rsa( ssl->session_negotiate->peer_cert->pk ),
-                            RSA_PUBLIC, md_alg, hashlen, hash,
-                            ssl->in_msg + 6 + n );
-    if( ret != 0 )
+    if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk,
+                           md_alg, hash_start, hashlen,
+                           ssl->in_msg + 6 + sa_len, sig_len ) ) != 0 )
     {
-        SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+        SSL_DEBUG_RET( 1, "pk_verify", ret );
         return( ret );
     }
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 9c1e53a..ed95d3e 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -35,17 +35,9 @@
 
 #if defined(POLARSSL_SSL_TLS_C)
 
-#include "polarssl/aes.h"
-#include "polarssl/arc4.h"
-#include "polarssl/camellia.h"
-#include "polarssl/des.h"
 #include "polarssl/debug.h"
 #include "polarssl/ssl.h"
 
-#if defined(POLARSSL_GCM_C)
-#include "polarssl/gcm.h"
-#endif
-
 #if defined(POLARSSL_MEMORY_C)
 #include "polarssl/memory.h"
 #else
@@ -131,33 +123,10 @@
 int (*ssl_hw_record_finish)(ssl_context *ssl) = NULL;
 #endif
 
-#if defined(POLARSSL_RSA_C)
-static int ssl_rsa_decrypt( void *ctx, int mode, size_t *olen,
-                        const unsigned char *input, unsigned char *output,
-                        size_t output_max_len )
-{
-    return rsa_pkcs1_decrypt( (rsa_context *) ctx, mode, olen, input, output,
-                              output_max_len );
-}
-
-static int ssl_rsa_sign( void *ctx,
-                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                    int mode, int hash_id, unsigned int hashlen,
-                    const unsigned char *hash, unsigned char *sig )
-{
-    return rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, mode, hash_id,
-                           hashlen, hash, sig );
-}
-
-static size_t ssl_rsa_key_len( void *ctx )
-{
-    return ( (rsa_context *) ctx )->len;
-}
-#endif /* POLARSSL_RSA_C */
-
 /*
  * Key material generation
  */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
 static int ssl3_prf( const unsigned char *secret, size_t slen,
                      const char *label,
                      const unsigned char *random, size_t rlen,
@@ -202,7 +171,9 @@
 
     return( 0 );
 }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
 static int tls1_prf( const unsigned char *secret, size_t slen,
                      const char *label,
                      const unsigned char *random, size_t rlen,
@@ -263,7 +234,10 @@
 
     return( 0 );
 }
+#endif /* POLARSSL_SSL_PROTO_TLS1) || POLARSSL_SSL_PROTO_TLS1_1 */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
 static int tls_prf_sha256( const unsigned char *secret, size_t slen,
                            const char *label,
                            const unsigned char *random, size_t rlen,
@@ -303,6 +277,7 @@
 
     return( 0 );
 }
+#endif /* POLARSSL_SHA256_C */
 
 #if defined(POLARSSL_SHA512_C)
 static int tls_prf_sha384( const unsigned char *secret, size_t slen,
@@ -344,25 +319,39 @@
 
     return( 0 );
 }
-#endif
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 static void ssl_update_checksum_start(ssl_context *, const unsigned char *, size_t);
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
 static void ssl_update_checksum_md5sha1(ssl_context *, const unsigned char *, size_t);
-static void ssl_update_checksum_sha256(ssl_context *, const unsigned char *, size_t);
+#endif
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
 static void ssl_calc_verify_ssl(ssl_context *,unsigned char *);
-static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
-static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
-
 static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int);
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
 static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int);
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+static void ssl_update_checksum_sha256(ssl_context *, const unsigned char *, size_t);
+static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
 static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int);
+#endif
 
 #if defined(POLARSSL_SHA512_C)
 static void ssl_update_checksum_sha384(ssl_context *, const unsigned char *, size_t);
 static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *);
 static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
 #endif
+#endif
 
 int ssl_derive_keys( ssl_context *ssl )
 {
@@ -375,7 +364,6 @@
     unsigned int iv_copy_len;
     const cipher_info_t *cipher_info;
     const md_info_t *md_info;
-    int ret;
 
     ssl_session *session = ssl->session_negotiate;
     ssl_transform *transform = ssl->transform_negotiate;
@@ -402,33 +390,49 @@
     /*
      * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
      */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
     {
         handshake->tls_prf = ssl3_prf;
         handshake->calc_verify = ssl_calc_verify_ssl;
         handshake->calc_finished = ssl_calc_finished_ssl;
     }
-    else if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+    else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
+    if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
     {
         handshake->tls_prf = tls1_prf;
         handshake->calc_verify = ssl_calc_verify_tls;
         handshake->calc_finished = ssl_calc_finished_tls;
     }
+    else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
 #if defined(POLARSSL_SHA512_C)
-    else if( transform->ciphersuite_info->mac ==
-             POLARSSL_MD_SHA384 )
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 &&
+        transform->ciphersuite_info->mac == POLARSSL_MD_SHA384 )
     {
         handshake->tls_prf = tls_prf_sha384;
         handshake->calc_verify = ssl_calc_verify_tls_sha384;
         handshake->calc_finished = ssl_calc_finished_tls_sha384;
     }
-#endif
     else
+#endif
+#if defined(POLARSSL_SHA256_C)
+    if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
     {
         handshake->tls_prf = tls_prf_sha256;
         handshake->calc_verify = ssl_calc_verify_tls_sha256;
         handshake->calc_finished = ssl_calc_finished_tls_sha256;
     }
+    else
+#endif
+#endif
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
 
     /*
      * SSLv3:
@@ -437,7 +441,7 @@
      *     MD5( premaster + SHA1( 'BB'  + premaster + randbytes ) ) +
      *     MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
      *
-     * TLSv1:
+     * TLSv1+:
      *   master = PRF( premaster, "master secret", randbytes )[0..47]
      */
     if( handshake->resume == 0 )
@@ -502,6 +506,8 @@
     {
         if( md_info->type != POLARSSL_MD_NONE )
         {
+            int ret;
+
             if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 )
             {
                 SSL_DEBUG_RET( 1, "md_init_ctx", ret );
@@ -583,16 +589,27 @@
                 iv_copy_len );
     }
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     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
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
     {
         md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen );
         md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen );
     }
+    else
+#endif
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
     if( ssl_hw_record_init != NULL)
@@ -701,6 +718,7 @@
     return( 0 );
 }
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
 void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] )
 {
     md5_context md5;
@@ -741,7 +759,9 @@
 
     return;
 }
+#endif
 
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
 void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
 {
     md5_context md5;
@@ -760,7 +780,10 @@
 
     return;
 }
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
 void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] )
 {
     sha256_context sha256;
@@ -775,6 +798,7 @@
 
     return;
 }
+#endif /* POLARSSL_SHA256_C */
 
 #if defined(POLARSSL_SHA512_C)
 void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
@@ -791,8 +815,10 @@
 
     return;
 }
-#endif
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
 /*
  * SSLv3.0 MAC functions
  */
@@ -833,6 +859,7 @@
     md_update( md_ctx, buf + len, md_size );
     md_finish( md_ctx, buf + len          );
 }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 
 /*
  * Encryption/decryption functions
@@ -846,6 +873,7 @@
     /*
      * Add MAC then encrypt
      */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
     {
         ssl_mac( &ssl->transform_out->md_ctx_enc,
@@ -854,6 +882,10 @@
                   ssl->out_ctr, ssl->out_msgtype );
     }
     else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
     {
         md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 );
         md_hmac_update( &ssl->transform_out->md_ctx_enc,
@@ -862,6 +894,12 @@
                          ssl->out_msg + ssl->out_msglen );
         md_hmac_reset( &ssl->transform_out->md_ctx_enc );
     }
+    else
+#endif
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
 
     SSL_DEBUG_BUF( 4, "computed mac",
                    ssl->out_msg + ssl->out_msglen, ssl->transform_out->maclen );
@@ -977,6 +1015,7 @@
         enc_msglen = ssl->out_msglen;
         enc_msg = ssl->out_msg;
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
         /*
          * Prepend per-record IV for block cipher in TLS v1.1 and up as per
          * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
@@ -1001,6 +1040,7 @@
             enc_msglen = ssl->out_msglen;
             ssl->out_msglen += ssl->transform_out->ivlen;
         }
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */
 
         SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
                             "including %d bytes of IV and %d bytes of padding",
@@ -1165,8 +1205,10 @@
             return( POLARSSL_ERR_SSL_INVALID_MAC );
         }
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
         if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
             minlen += ssl->transform_in->ivlen;
+#endif
 
         if( ssl->in_msglen < minlen + ssl->transform_in->ivlen ||
             ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 )
@@ -1180,6 +1222,7 @@
         dec_msg = ssl->in_msg;
         dec_msg_result = ssl->in_msg;
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
         /*
          * Initialize for prepended IV for block cipher in TLS v1.1 and up
          */
@@ -1191,6 +1234,7 @@
             for( i = 0; i < ssl->transform_in->ivlen; i++ )
                 ssl->transform_in->iv_dec[i] = ssl->in_iv[i];
         }
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */
 
         switch( ssl->transform_in->ciphersuite_info->cipher )
         {
@@ -1242,6 +1286,7 @@
             correct = 0;
         }
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
         if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
         {
             if( padlen > ssl->transform_in->ivlen )
@@ -1255,6 +1300,10 @@
             }
         }
         else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver > SSL_MINOR_VERSION_0 )
         {
             /*
              * TLSv1+: always check the padding up to the first failure
@@ -1278,6 +1327,13 @@
 #endif
             padlen &= correct * 0x1FF;
         }
+        else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
     }
 
     SSL_DEBUG_BUF( 4, "raw buffer after decryption",
@@ -1293,6 +1349,7 @@
 
     memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen );
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
     {
         ssl_mac( &ssl->transform_in->md_ctx_dec,
@@ -1301,6 +1358,10 @@
                   ssl->in_ctr, ssl->in_msgtype );
     }
     else
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver > SSL_MINOR_VERSION_0 )
     {
         /*
          * Process MAC and always update for padlen afterwards to make
@@ -1331,6 +1392,13 @@
 
         md_hmac_reset( &ssl->transform_in->md_ctx_dec );
     }
+    else
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
 
     SSL_DEBUG_BUF( 4, "message  mac", tmp, ssl->transform_in->maclen );
     SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
@@ -1742,13 +1810,17 @@
             return( POLARSSL_ERR_SSL_INVALID_RECORD );
         }
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
         if( ssl->minor_ver == SSL_MINOR_VERSION_0 &&
             ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN )
         {
             SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( POLARSSL_ERR_SSL_INVALID_RECORD );
         }
+#endif
 
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
         /*
          * TLS encrypted messages can have up to 256 bytes of padding
          */
@@ -1758,6 +1830,7 @@
             SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( POLARSSL_ERR_SSL_INVALID_RECORD );
         }
+#endif
     }
 
     /*
@@ -2014,6 +2087,7 @@
             return( 0 );
         }
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
         /*
          * If using SSLv3 and got no cert, send an Alert message
          * (otherwise an empty Certificate message will be sent).
@@ -2029,6 +2103,7 @@
             SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
             goto write_msg;
         }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
     }
     else /* SSL_IS_SERVER */
     {
@@ -2079,7 +2154,9 @@
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = SSL_HS_CERTIFICATE;
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
 write_msg:
+#endif
 
     ssl->state++;
 
@@ -2113,7 +2190,7 @@
     if( ssl->endpoint == SSL_IS_SERVER &&
         ssl->authmode == SSL_VERIFY_NONE )
     {
-        ssl->verify_result = BADCERT_SKIP_VERIFY;
+        ssl->session_negotiate->verify_result = BADCERT_SKIP_VERIFY;
         SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
         ssl->state++;
         return( 0 );
@@ -2127,6 +2204,7 @@
 
     ssl->state++;
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
     /*
      * Check if the client sent an empty certificate
      */
@@ -2140,14 +2218,17 @@
         {
             SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
 
-            ssl->verify_result = BADCERT_MISSING;
+            ssl->session_negotiate->verify_result = BADCERT_MISSING;
             if( ssl->authmode == SSL_VERIFY_OPTIONAL )
                 return( 0 );
             else
                 return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
         }
     }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
     if( ssl->endpoint  == SSL_IS_SERVER &&
         ssl->minor_ver != SSL_MINOR_VERSION_0 )
     {
@@ -2158,13 +2239,15 @@
         {
             SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
 
-            ssl->verify_result = BADCERT_MISSING;
+            ssl->session_negotiate->verify_result = BADCERT_MISSING;
             if( ssl->authmode == SSL_VERIFY_REQUIRED )
                 return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
             else
                 return( 0 );
         }
     }
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
+          POLARSSL_SSL_PROTO_TLS1_2 */
 
     if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
     {
@@ -2241,8 +2324,8 @@
         }
 
         ret = x509parse_verify( ssl->session_negotiate->peer_cert,
-                                ssl->ca_chain, ssl->ca_crl,
-                                ssl->peer_cn,  &ssl->verify_result,
+                                ssl->ca_chain, ssl->ca_crl, ssl->peer_cn,
+                               &ssl->session_negotiate->verify_result,
                                 ssl->f_vrfy, ssl->p_vrfy );
 
         if( ret != 0 )
@@ -2317,45 +2400,66 @@
 void ssl_optimize_checksum( ssl_context *ssl,
                             const ssl_ciphersuite_t *ciphersuite_info )
 {
-#if !defined(POLARSSL_SHA512_C)
-    ((void) ciphersuite);
-#endif
+    ((void) ciphersuite_info);
 
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
     if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
         ssl->handshake->update_checksum = ssl_update_checksum_md5sha1;
-#if defined(POLARSSL_SHA512_C)
-    else if( ciphersuite_info->mac == POLARSSL_MD_SHA384 )
-    {
-        ssl->handshake->update_checksum = ssl_update_checksum_sha384;
-    }
-#endif
     else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA512_C)
+    if( ciphersuite_info->mac == POLARSSL_MD_SHA384 )
+        ssl->handshake->update_checksum = ssl_update_checksum_sha384;
+    else
+#endif
+#if defined(POLARSSL_SHA256_C)
+    if( ciphersuite_info->mac != POLARSSL_MD_SHA384 )
         ssl->handshake->update_checksum = ssl_update_checksum_sha256;
+    else
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+        /* Should never happen */
+        return;
 }
 
 static void ssl_update_checksum_start( ssl_context *ssl,
                                        const unsigned char *buf, size_t len )
 {
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
      md5_update( &ssl->handshake->fin_md5 , buf, len );
     sha1_update( &ssl->handshake->fin_sha1, buf, len );
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
     sha256_update( &ssl->handshake->fin_sha256, buf, len );
+#endif
 #if defined(POLARSSL_SHA512_C)
     sha512_update( &ssl->handshake->fin_sha512, buf, len );
 #endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 }
 
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
 static void ssl_update_checksum_md5sha1( ssl_context *ssl,
                                          const unsigned char *buf, size_t len )
 {
      md5_update( &ssl->handshake->fin_md5 , buf, len );
     sha1_update( &ssl->handshake->fin_sha1, buf, len );
 }
+#endif
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
 static void ssl_update_checksum_sha256( ssl_context *ssl,
                                         const unsigned char *buf, size_t len )
 {
     sha256_update( &ssl->handshake->fin_sha256, buf, len );
 }
+#endif
 
 #if defined(POLARSSL_SHA512_C)
 static void ssl_update_checksum_sha384( ssl_context *ssl,
@@ -2364,7 +2468,9 @@
     sha512_update( &ssl->handshake->fin_sha512, buf, len );
 }
 #endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
 static void ssl_calc_finished_ssl(
                 ssl_context *ssl, unsigned char *buf, int from )
 {
@@ -2444,7 +2550,9 @@
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
 static void ssl_calc_finished_tls(
                 ssl_context *ssl, unsigned char *buf, int from )
 {
@@ -2498,7 +2606,10 @@
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */
 
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
 static void ssl_calc_finished_tls_sha256(
                 ssl_context *ssl, unsigned char *buf, int from )
 {
@@ -2543,6 +2654,7 @@
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
+#endif /* POLARSSL_SHA256_C */
 
 #if defined(POLARSSL_SHA512_C)
 static void ssl_calc_finished_tls_sha384(
@@ -2589,7 +2701,8 @@
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
-#endif
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 void ssl_handshake_wrapup( ssl_context *ssl )
 {
@@ -2828,12 +2941,19 @@
     memset( ssl->transform_negotiate, 0, sizeof(ssl_transform) );
     memset( ssl->session_negotiate, 0, sizeof(ssl_session) );
 
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
      md5_starts( &ssl->handshake->fin_md5 );
     sha1_starts( &ssl->handshake->fin_sha1 );
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
     sha256_starts( &ssl->handshake->fin_sha256, 0 );
+#endif
 #if defined(POLARSSL_SHA512_C)
     sha512_starts( &ssl->handshake->fin_sha512, 1 );
 #endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
     ssl->handshake->update_checksum = ssl_update_checksum_start;
     ssl->handshake->sig_alg = SSL_HASH_SHA1;
@@ -2858,16 +2978,10 @@
     /*
      * Sane defaults
      */
-#if defined(POLARSSL_RSA_C)
-    ssl->rsa_decrypt = ssl_rsa_decrypt;
-    ssl->rsa_sign = ssl_rsa_sign;
-    ssl->rsa_key_len = ssl_rsa_key_len;
-#endif
-
-    ssl->min_major_ver = SSL_MAJOR_VERSION_3;
-    ssl->min_minor_ver = SSL_MINOR_VERSION_0;
-    ssl->max_major_ver = SSL_MAJOR_VERSION_3;
-    ssl->max_minor_ver = SSL_MINOR_VERSION_3;
+    ssl->min_major_ver = SSL_MIN_MAJOR_VERSION;
+    ssl->min_minor_ver = SSL_MIN_MINOR_VERSION;
+    ssl->max_major_ver = SSL_MAX_MAJOR_VERSION;
+    ssl->max_minor_ver = SSL_MAX_MINOR_VERSION;
 
     ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() );
 
@@ -2911,8 +3025,10 @@
     memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN );
     memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     ssl->hostname = NULL;
     ssl->hostname_len = 0;
+#endif
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
     ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME;
@@ -3143,23 +3259,55 @@
 }
 
 void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
-                       rsa_context *rsa_key )
+                       pk_context *pk_key )
 {
     ssl->own_cert   = own_cert;
-    ssl->rsa_key    = rsa_key;
+    ssl->pk_key     = pk_key;
 }
 
-void ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
-                           void *rsa_key,
-                           rsa_decrypt_func rsa_decrypt,
-                           rsa_sign_func rsa_sign,
-                           rsa_key_len_func rsa_key_len )
+#if defined(POLARSSL_RSA_C)
+int ssl_set_own_cert_rsa( ssl_context *ssl, x509_cert *own_cert,
+                           rsa_context *rsa_key )
 {
+    int ret;
+
     ssl->own_cert   = own_cert;
-    ssl->rsa_key    = rsa_key;
-    ssl->rsa_decrypt = rsa_decrypt;
-    ssl->rsa_sign = rsa_sign;
-    ssl->rsa_key_len = rsa_key_len;
+
+    if( ( ssl->pk_key = polarssl_malloc( sizeof( pk_context ) ) ) == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    ssl->pk_key_own_alloc = 1;
+
+    pk_init( ssl->pk_key );
+
+    ret = pk_init_ctx( ssl->pk_key, pk_info_from_type( POLARSSL_PK_RSA ) );
+    if( ret != 0 )
+        return( ret );
+
+    if( ( ret = rsa_copy( ssl->pk_key->pk_ctx, rsa_key ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+int ssl_set_own_cert_alt( ssl_context *ssl, x509_cert *own_cert,
+                          void *rsa_key,
+                          rsa_decrypt_func rsa_decrypt,
+                          rsa_sign_func rsa_sign,
+                          rsa_key_len_func rsa_key_len )
+{
+    ssl->own_cert    = own_cert;
+
+    if( ( ssl->pk_key = polarssl_malloc( sizeof( pk_context ) ) ) == NULL )
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+    ssl->pk_key_own_alloc = 1;
+
+    pk_init( ssl->pk_key );
+
+    return( pk_init_ctx_rsa_alt( ssl->pk_key, rsa_key,
+                                 rsa_decrypt, rsa_sign, rsa_key_len ) );
 }
 #endif /* POLARSSL_X509_PARSE_C */
 
@@ -3214,6 +3362,7 @@
 }
 #endif /* POLARSSL_DHM_C */
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 int ssl_set_hostname( ssl_context *ssl, const char *hostname )
 {
     if( hostname == NULL )
@@ -3245,17 +3394,26 @@
     ssl->f_sni = f_sni;
     ssl->p_sni = p_sni;
 }
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
 void ssl_set_max_version( ssl_context *ssl, int major, int minor )
 {
-    ssl->max_major_ver = major;
-    ssl->max_minor_ver = minor;
+    if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION &&
+        minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION )
+    {
+        ssl->max_major_ver = major;
+        ssl->max_minor_ver = minor;
+    }
 }
 
 void ssl_set_min_version( ssl_context *ssl, int major, int minor )
 {
-    ssl->min_major_ver = major;
-    ssl->min_minor_ver = minor;
+    if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION &&
+        minor >= SSL_MIN_MINOR_VERSION && minor <= SSL_MAX_MINOR_VERSION )
+    {
+        ssl->min_major_ver = major;
+        ssl->min_minor_ver = minor;
+    }
 }
 
 #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
@@ -3325,7 +3483,7 @@
 
 int ssl_get_verify_result( const ssl_context *ssl )
 {
-    return( ssl->verify_result );
+    return( ssl->session->verify_result );
 }
 
 const char *ssl_get_ciphersuite( const ssl_context *ssl )
@@ -3516,6 +3674,7 @@
             {
                 SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) );
 
+#if defined(POLARSSL_SSL_PROTO_SSL3)
                 if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
                 {
                     /*
@@ -3525,6 +3684,10 @@
                         return( ret );
                 }
                 else
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_2)
+                if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
                 {
                     if( ( ret = ssl_send_alert_message( ssl,
                                     SSL_ALERT_LEVEL_WARNING,
@@ -3533,6 +3696,12 @@
                         return( ret );
                     }
                 }
+                else
+#endif
+                {
+                    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                    return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+                }
             }
             else
             {
@@ -3759,12 +3928,20 @@
     polarssl_free( ssl->ticket_keys );
 #endif
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     if ( ssl->hostname != NULL)
     {
         memset( ssl->hostname, 0, ssl->hostname_len );
         polarssl_free( ssl->hostname );
         ssl->hostname_len = 0;
     }
+#endif
+
+    if( ssl->pk_key_own_alloc )
+    {
+        pk_free( ssl->pk_key );
+        polarssl_free( ssl->pk_key );
+    }
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
     if( ssl_hw_record_finish != NULL )
@@ -3780,4 +3957,66 @@
     memset( ssl, 0, sizeof( ssl_context ) );
 }
 
+/*
+ * Get the SSL_SIG_* constant corresponding to a public key
+ */
+unsigned char ssl_sig_from_pk( pk_context *pk )
+{
+#if defined(POLARSSL_RSA_C)
+    if( pk_can_do( pk, POLARSSL_PK_RSA ) )
+        return( SSL_SIG_RSA );
+#endif
+#if defined(POLARSSL_ECDSA_C)
+    if( pk_can_do( pk, POLARSSL_PK_ECDSA ) )
+        return( SSL_SIG_ECDSA );
+#endif
+    return( SSL_SIG_ANON );
+}
+
+pk_type_t ssl_pk_alg_from_sig( unsigned char sig )
+{
+    switch( sig )
+    {
+#if defined(POLARSSL_RSA_C)
+        case SSL_SIG_RSA:
+            return( POLARSSL_PK_RSA );
+#endif
+#if defined(POLARSSL_ECDSA_C)
+        case SSL_SIG_ECDSA:
+            return( POLARSSL_PK_ECDSA );
+#endif
+        default:
+            return( POLARSSL_PK_NONE );
+    }
+}
+
+md_type_t ssl_md_alg_from_hash( unsigned char hash )
+{
+    switch( hash )
+    {
+#if defined(POLARSSL_MD5_C)
+        case SSL_HASH_MD5:
+            return( POLARSSL_MD_MD5 );
+#endif
+#if defined(POLARSSL_SHA1_C)
+        case SSL_HASH_SHA1:
+            return( POLARSSL_MD_SHA1 );
+#endif
+#if defined(POLARSSL_SHA256_C)
+        case SSL_HASH_SHA224:
+            return( POLARSSL_MD_SHA224 );
+        case SSL_HASH_SHA256:
+            return( POLARSSL_MD_SHA256 );
+#endif
+#if defined(POLARSSL_SHA512_C)
+        case SSL_HASH_SHA384:
+            return( POLARSSL_MD_SHA384 );
+        case SSL_HASH_SHA512:
+            return( POLARSSL_MD_SHA512 );
+#endif
+        default:
+            return( POLARSSL_MD_NONE );
+    }
+}
+
 #endif
diff --git a/library/x509parse.c b/library/x509parse.c
index bbaca8e..c175df4 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -605,8 +605,9 @@
 #if defined(POLARSSL_ECP_C)
     if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY )
     {
-        ret = x509_use_ecparams( &alg_params, &pk_ec( *pk )->grp ) ||
-              x509_get_ecpubkey( p, end, pk_ec( *pk ) );
+        ret = x509_use_ecparams( &alg_params, &pk_ec( *pk )->grp );
+        if( ret == 0 )
+            ret = x509_get_ecpubkey( p, end, pk_ec( *pk ) );
     } else
 #endif /* POLARSSL_ECP_C */
         ret = POLARSSL_ERR_X509_UNKNOWN_PK_ALG;
@@ -3166,7 +3167,7 @@
     if( ret != 0 )
         ret = snprintf( p, n, "???"  );
     else
-        ret = snprintf( p, n, desc );
+        ret = snprintf( p, n, "%s", desc );
     SAFE_SNPRINTF();
 
     if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
@@ -3274,7 +3275,7 @@
     if( ret != 0 )
         ret = snprintf( p, n, "???"  );
     else
-        ret = snprintf( p, n, desc );
+        ret = snprintf( p, n, "%s", desc );
     SAFE_SNPRINTF();
 
     ret = snprintf( p, n, "\n" );
@@ -3504,6 +3505,17 @@
      */
     *flags |= BADCERT_NOT_TRUSTED;
 
+    md_info = md_info_from_type( child->sig_md );
+    if( md_info == NULL )
+    {
+        /*
+         * Cannot check 'unknown', no need to try any CA
+         */
+        trust_ca = NULL;
+    }
+    else
+        md( md_info, child->tbs.p, child->tbs.len, hash );
+
     while( trust_ca != NULL )
     {
         if( trust_ca->version == 0 ||
@@ -3533,18 +3545,6 @@
             continue;
         }
 
-        md_info = md_info_from_type( child->sig_md );
-        if( md_info == NULL )
-        {
-            /*
-             * Cannot check 'unknown' hash
-             */
-            trust_ca = trust_ca->next;
-            continue;
-        }
-
-        md( md_info, child->tbs.p, child->tbs.len, hash );
-
         if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 ||
             pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size,
                        child->sig.p, child->sig.len ) != 0 )
@@ -3570,7 +3570,7 @@
           memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
                             child->issuer_raw.len ) != 0 ) )
     {
-        /* Check trusted CA's CRL for then chain's top crt */
+        /* Check trusted CA's CRL for the chain's top crt */
         *flags |= x509parse_verifycrl( child, trust_ca, ca_crl );
 
         if( x509parse_time_expired( &trust_ca->valid_to ) )
@@ -3936,7 +3936,7 @@
     size_t i, j;
     x509_cert cacert;
     x509_cert clicert;
-    rsa_context rsa;
+    pk_context pkey;
 #if defined(POLARSSL_DHM_C)
     dhm_context dhm;
 #endif
@@ -3974,9 +3974,9 @@
     i = strlen( test_ca_key );
     j = strlen( test_ca_pwd );
 
-    rsa_init( &rsa, RSA_PKCS_V15, 0 );
+    pk_init( &pkey );
 
-    if( ( ret = x509parse_key_rsa( &rsa,
+    if( ( ret = x509parse_key( &pkey,
                     (const unsigned char *) test_ca_key, i,
                     (const unsigned char *) test_ca_pwd, j ) ) != 0 )
     {
@@ -3989,12 +3989,14 @@
     if( verbose != 0 )
         printf( "passed\n  X.509 signature verify: ");
 
-    ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &flags, NULL, NULL );
+    ret = x509parse_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
     if( ret != 0 )
     {
         if( verbose != 0 )
             printf( "failed\n" );
 
+        printf("ret = %d, &flags = %04x\n", ret, flags);
+
         return( ret );
     }
 
@@ -4019,7 +4021,7 @@
 
     x509_free( &cacert  );
     x509_free( &clicert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
 #if defined(POLARSSL_DHM_C)
     dhm_free( &dhm );
 #endif
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 7dd11b9..0650b3a 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -257,7 +257,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     x509_cert cacert;
     x509_cert clicert;
-    rsa_context rsa;
+    pk_context pkey;
 #endif
     char *p, *q;
     const int *list;
@@ -271,7 +271,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     memset( &cacert, 0, sizeof( x509_cert ) );
     memset( &clicert, 0, sizeof( x509_cert ) );
-    memset( &rsa, 0, sizeof( rsa_context ) );
+    pk_init( &pkey );
 #endif
 
     if( argc == 0 )
@@ -626,11 +626,11 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.key_file ) )
-        ret = x509parse_keyfile_rsa( &rsa, opt.key_file, "" );
+        ret = x509parse_keyfile( &pkey, opt.key_file, "" );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_cli_key,
+        ret = x509parse_key( &pkey, (const unsigned char *) test_cli_key,
                 strlen( test_cli_key ), NULL, 0 );
 #else
     {
@@ -640,7 +640,7 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key_rsa returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
         goto exit;
     }
 
@@ -711,7 +711,7 @@
 
 #if defined(POLARSSL_X509_PARSE_C)
     ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
-    ssl_set_own_cert( &ssl, &clicert, &rsa );
+    ssl_set_own_cert( &ssl, &clicert, &pkey );
 #endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
@@ -719,7 +719,9 @@
                  strlen( opt.psk_identity ) );
 #endif
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     ssl_set_hostname( &ssl, opt.server_name );
+#endif
 
     if( opt.min_version != -1 )
         ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
@@ -859,6 +861,9 @@
     {
         --opt.reconnect;
 
+        printf( "  ! Press a key to reconnect\n" );
+        (void) getchar();
+
         printf( "  . Reconnecting with saved session..." );
         fflush( stdout );
 
@@ -908,7 +913,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     x509_free( &clicert );
     x509_free( &cacert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
 #endif
     ssl_session_free( &saved_session );
     ssl_free( &ssl );
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index 986458b..98a518c 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -104,7 +104,7 @@
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
     x509_cert srvcert;
-    rsa_context rsa;
+    pk_context pkey;
 
     ((void) argc);
     ((void) argv);
@@ -139,7 +139,7 @@
     /*
      * This demonstration program uses embedded test certificates.
      * Instead, you may want to use x509parse_crtfile() to read the
-     * server and CA certificates, as well as x509parse_keyfile_rsa().
+     * server and CA certificates, as well as x509parse_keyfile().
      */
     ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                          strlen( test_srv_crt ) );
@@ -157,12 +157,12 @@
         goto exit;
     }
 
-    rsa_init( &rsa, RSA_PKCS_V15, 0 );
-    ret =  x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key,
+    pk_init( &pkey );
+    ret =  x509parse_key( &pkey, (const unsigned char *) test_srv_key,
                           strlen( test_srv_key ), NULL, 0 );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key_rsa returned %d\n\n", ret );
+        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
         goto exit;
     }
 
@@ -265,7 +265,7 @@
                            net_send, &client_fd );
 
         ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
-        ssl_set_own_cert( &ssl, &srvcert, &rsa );
+        ssl_set_own_cert( &ssl, &srvcert, &pkey );
 
         /*
          * 5. Handshake
@@ -363,7 +363,7 @@
 
     net_close( client_fd );
     x509_free( &srvcert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
     ssl_free( &ssl );
 
 #if defined(_WIN32)
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 665cdbf..cbd1a00 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -352,7 +352,7 @@
     ssl_context ssl;
     x509_cert cacert;
     x509_cert clicert;
-    rsa_context rsa;
+    pk_context pkey;
     int i;
     size_t n;
     char *p, *q;
@@ -364,7 +364,7 @@
     server_fd = 0;
     memset( &cacert, 0, sizeof( x509_cert ) );
     memset( &clicert, 0, sizeof( x509_cert ) );
-    memset( &rsa, 0, sizeof( rsa_context ) );
+    pk_init( &pkey );
 
     if( argc == 0 )
     {
@@ -532,11 +532,11 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.key_file ) )
-        ret = x509parse_keyfile_rsa( &rsa, opt.key_file, "" );
+        ret = x509parse_keyfile( &pkey, opt.key_file, "" );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_cli_key,
+        ret = x509parse_key( &pkey, (const unsigned char *) test_cli_key,
                 strlen( test_cli_key ), NULL, 0 );
 #else
     {
@@ -546,7 +546,7 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key_rsa returned %d\n\n", ret );
+        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
         goto exit;
     }
 
@@ -594,9 +594,11 @@
         ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
 
     ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
-    ssl_set_own_cert( &ssl, &clicert, &rsa );
+    ssl_set_own_cert( &ssl, &clicert, &pkey );
 
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     ssl_set_hostname( &ssl, opt.server_name );
+#endif
 
     if( opt.mode == MODE_SSL_TLS )
     {
@@ -789,7 +791,7 @@
         net_close( server_fd );
     x509_free( &clicert );
     x509_free( &cacert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
     ssl_free( &ssl );
 
 #if defined(_WIN32)
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index dbb193b..801c0c6 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -94,7 +94,7 @@
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
     x509_cert srvcert;
-    rsa_context rsa;
+    pk_context pkey;
 #if defined(POLARSSL_SSL_CACHE_C)
     ssl_cache_context cache;
 #endif
@@ -117,7 +117,7 @@
     /*
      * This demonstration program uses embedded test certificates.
      * Instead, you may want to use x509parse_crtfile() to read the
-     * server and CA certificates, as well as x509parse_keyfile_rsa().
+     * server and CA certificates, as well as x509parse_keyfile().
      */
     ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                          strlen( test_srv_crt ) );
@@ -135,12 +135,12 @@
         goto exit;
     }
 
-    rsa_init( &rsa, RSA_PKCS_V15, 0 );
-    ret =  x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key,
+    pk_init( &pkey );
+    ret =  x509parse_key( &pkey, (const unsigned char *) test_srv_key,
                           strlen( test_srv_key ), NULL, 0 );
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key_rsa returned %d\n\n", ret );
+        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
         goto exit;
     }
 
@@ -201,7 +201,7 @@
 #endif
 
     ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
-    ssl_set_own_cert( &ssl, &srvcert, &rsa );
+    ssl_set_own_cert( &ssl, &srvcert, &pkey );
 
     printf( " ok\n" );
 
@@ -364,7 +364,7 @@
 
     net_close( client_fd );
     x509_free( &srvcert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
     ssl_free( &ssl );
 #if defined(POLARSSL_SSL_CACHE_C)
     ssl_cache_free( &cache );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 681850b..8831190 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -215,7 +215,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     x509_cert cacert;
     x509_cert srvcert;
-    rsa_context rsa;
+    pk_context pkey;
 #endif
 #if defined(POLARSSL_SSL_CACHE_C)
     ssl_cache_context cache;
@@ -239,7 +239,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     memset( &cacert, 0, sizeof( x509_cert ) );
     memset( &srvcert, 0, sizeof( x509_cert ) );
-    memset( &rsa, 0, sizeof( rsa_context ) );
+    pk_init( &pkey );
 #endif
 #if defined(POLARSSL_SSL_CACHE_C)
     ssl_cache_init( &cache );
@@ -575,11 +575,11 @@
 
 #if defined(POLARSSL_FS_IO)
     if( strlen( opt.key_file ) )
-        ret = x509parse_keyfile_rsa( &rsa, opt.key_file, "" );
+        ret = x509parse_keyfile( &pkey, opt.key_file, "" );
     else
 #endif
 #if defined(POLARSSL_CERTS_C)
-        ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key,
+        ret = x509parse_key( &pkey, (const unsigned char *) test_srv_key,
                 strlen( test_srv_key ), NULL, 0 );
 #else
     {
@@ -589,7 +589,7 @@
 #endif
     if( ret != 0 )
     {
-        printf( " failed\n  !  x509parse_key_rsa returned -0x%x\n\n", -ret );
+        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
         goto exit;
     }
 
@@ -649,7 +649,7 @@
 
 #if defined(POLARSSL_X509_PARSE_C)
     ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
-    ssl_set_own_cert( &ssl, &srvcert, &rsa );
+    ssl_set_own_cert( &ssl, &srvcert, &pkey );
 #endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
@@ -877,7 +877,7 @@
 #if defined(POLARSSL_X509_PARSE_C)
     x509_free( &srvcert );
     x509_free( &cacert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
 #endif
 
     ssl_free( &ssl );
diff --git a/programs/test/ssl_test.c b/programs/test/ssl_test.c
index ce45ccf..797226b 100644
--- a/programs/test/ssl_test.c
+++ b/programs/test/ssl_test.c
@@ -166,7 +166,7 @@
     ctr_drbg_context ctr_drbg;
     ssl_context ssl;
     x509_cert srvcert;
-    rsa_context rsa;
+    pk_context pkey;
 
     ret = 1;
 
@@ -187,7 +187,7 @@
     memset( write_state, 0, sizeof( write_state ) );
 
     memset( &srvcert, 0, sizeof( x509_cert ) );
-    memset( &rsa, 0, sizeof( rsa_context ) );
+    pk_init( &pkey );
 
     if( opt->opmode == OPMODE_CLIENT )
     {
@@ -229,11 +229,11 @@
             goto exit;
         }
 
-        ret =  x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key,
+        ret =  x509parse_key( &pkey, (const unsigned char *) test_srv_key,
                               strlen( test_srv_key ), NULL, 0 );
         if( ret != 0 )
         {
-            printf( "  !  x509parse_key_rsa returned %d\n\n", ret );
+            printf( "  !  x509parse_key returned %d\n\n", ret );
             goto exit;
         }
 #endif
@@ -262,7 +262,7 @@
 
         ssl_set_endpoint( &ssl, SSL_IS_SERVER );
         ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
-        ssl_set_own_cert( &ssl, &srvcert, &rsa );
+        ssl_set_own_cert( &ssl, &srvcert, &pkey );
     }
 
     ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
@@ -400,7 +400,7 @@
 
     ssl_close_notify( &ssl );
     x509_free( &srvcert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
     ssl_free( &ssl );
     net_close( client_fd );
 
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index d7cacdb..40d76d8 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -157,7 +157,7 @@
     ssl_context ssl;
     x509_cert cacert;
     x509_cert clicert;
-    rsa_context rsa;
+    pk_context pkey;
     int i, j, n;
     int flags, verify = 0;
     char *p, *q;
@@ -169,7 +169,7 @@
     server_fd = 0;
     memset( &cacert, 0, sizeof( x509_cert ) );
     memset( &clicert, 0, sizeof( x509_cert ) );
-    memset( &rsa, 0, sizeof( rsa_context ) );
+    pk_init( &pkey );
 
     if( argc == 0 )
     {
@@ -404,7 +404,7 @@
         ssl_set_bio( &ssl, net_recv, &server_fd,
                 net_send, &server_fd );
 
-        ssl_set_own_cert( &ssl, &clicert, &rsa );
+        ssl_set_own_cert( &ssl, &clicert, &pkey );
 
         ssl_set_hostname( &ssl, opt.server_name );
 
@@ -450,7 +450,7 @@
         net_close( server_fd );
     x509_free( &cacert );
     x509_free( &clicert );
-    rsa_free( &rsa );
+    pk_free( &pkey );
 
 #if defined(_WIN32)
     printf( "  + Press Enter to exit this program.\n" );
diff --git a/tests/compat.sh b/tests/compat.sh
index 24c08c3..ef6b0e0 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -2,8 +2,13 @@
 
 killall -q openssl ssl_server ssl_server2
 
+let "tests = 0"
+let "failed = 0"
+let "skipped = 0"
+
 MODES="ssl3 tls1 tls1_1 tls1_2"
 VERIFIES="NO YES"
+TYPES="ECDSA RSA PSK"
 OPENSSL=openssl
 FILTER=""
 VERBOSE=""
@@ -23,6 +28,16 @@
       shift
       MODES=$1
       ;;
+    -t|--types)
+      # Key exchange types
+      shift
+      TYPES=$1
+      ;;
+    -V|--verify)
+      # Verifiction modes
+      shift
+      VERIFIES=$1
+      ;;
     -v|--verbose)
       # Set verbosity
       shift
@@ -34,6 +49,8 @@
       echo -e "  -f|--filter\tFilter ciphersuites to test (Default: all)"
       echo -e "  -h|--help\t\tPrint this help."
       echo -e "  -m|--modes\tWhich modes to perform (Default: \"ssl3 tls1 tls1_1 tls1_2\")"
+      echo -e "  -t|--types\tWhich key exchange type to perform (Default: \"ECDSA RSA PSK\")"
+      echo -e "  -V|--verify\tWhich verification modes to perform (Default: \"NO YES\")"
       echo -e "  -v|--verbose\t\tSet verbose output."
       exit 1
       ;;
@@ -52,127 +69,6 @@
   fi
 }
 
-for VERIFY in $VERIFIES;
-do
-P_SERVER_ARGS="psk=6162636465666768696a6b6c6d6e6f70"
-P_CLIENT_ARGS="psk=6162636465666768696a6b6c6d6e6f70"
-O_SERVER_ARGS="-psk 6162636465666768696a6b6c6d6e6f70"
-O_CLIENT_ARGS="-psk 6162636465666768696a6b6c6d6e6f70"
-
-if [ "X$VERIFY" = "XYES" ];
-then
-    P_SERVER_ARGS="$P_SERVER_ARGS auth_mode=required crt_file=data_files/server1.crt key_file=data_files/server1.key ca_file=data_files/test-ca.crt"
-    P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=data_files/server2.crt key_file=data_files/server2.key ca_file=data_files/test-ca.crt"
-    O_SERVER_ARGS="$O_SERVER_ARGS -verify 10 -CAfile data_files/test-ca.crt -cert data_files/server1.crt -key data_files/server1.key"
-    O_CLIENT_ARGS="$O_CLIENT_ARGS -cert data_files/server2.crt -key data_files/server2.key -CAfile data_files/test-ca.crt"
-fi
-
-for MODE in $MODES;
-do
-echo "Running for $MODE (Verify: $VERIFY)"
-echo "-----------"
-
-P_CIPHERS="                                 \
-    TLS-DHE-RSA-WITH-AES-128-CBC-SHA        \
-    TLS-DHE-RSA-WITH-AES-256-CBC-SHA        \
-    TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA   \
-    TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA   \
-    TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA       \
-    TLS-RSA-WITH-AES-256-CBC-SHA            \
-    TLS-RSA-WITH-CAMELLIA-256-CBC-SHA       \
-    TLS-RSA-WITH-AES-128-CBC-SHA            \
-    TLS-RSA-WITH-CAMELLIA-128-CBC-SHA       \
-    TLS-RSA-WITH-3DES-EDE-CBC-SHA           \
-    TLS-RSA-WITH-RC4-128-SHA                \
-    TLS-RSA-WITH-RC4-128-MD5                \
-    TLS-RSA-EXPORT-WITH-RC4-40-MD5          \
-    TLS-RSA-WITH-NULL-MD5                   \
-    TLS-RSA-WITH-NULL-SHA                   \
-    TLS-RSA-WITH-DES-CBC-SHA                \
-    TLS-DHE-RSA-WITH-DES-CBC-SHA            \
-    TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA      \
-    TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA      \
-    TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA     \
-    TLS-ECDHE-RSA-WITH-RC4-128-SHA          \
-    TLS-ECDHE-RSA-WITH-NULL-SHA             \
-    TLS-PSK-WITH-RC4-128-SHA                \
-    TLS-PSK-WITH-3DES-EDE-CBC-SHA           \
-    TLS-PSK-WITH-AES-128-CBC-SHA            \
-    TLS-PSK-WITH-AES-256-CBC-SHA            \
-    "
-
-O_CIPHERS="                         \
-    DHE-RSA-AES128-SHA              \
-    DHE-RSA-AES256-SHA              \
-    DHE-RSA-CAMELLIA128-SHA         \
-    DHE-RSA-CAMELLIA256-SHA         \
-    EDH-RSA-DES-CBC3-SHA            \
-    AES256-SHA                      \
-    CAMELLIA256-SHA                 \
-    AES128-SHA                      \
-    CAMELLIA128-SHA                 \
-    DES-CBC3-SHA                    \
-    RC4-SHA                         \
-    RC4-MD5                         \
-    EXP-RC4-MD5                     \
-    NULL-MD5                        \
-    NULL-SHA                        \
-    DES-CBC-SHA                     \
-    EDH-RSA-DES-CBC-SHA             \
-    ECDHE-RSA-AES256-SHA            \
-    ECDHE-RSA-AES128-SHA            \
-    ECDHE-RSA-DES-CBC3-SHA          \
-    ECDHE-RSA-RC4-SHA               \
-    ECDHE-RSA-NULL-SHA              \
-    PSK-RC4-SHA                     \
-    PSK-3DES-EDE-CBC-SHA            \
-    PSK-AES128-CBC-SHA              \
-    PSK-AES256-CBC-SHA
-    "
-
-# Also add SHA256 ciphersuites
-#
-if [ "$MODE" = "tls1_2" ];
-then
-    P_CIPHERS="$P_CIPHERS                       \
-        TLS-RSA-WITH-NULL-SHA256                \
-        TLS-RSA-WITH-AES-128-CBC-SHA256         \
-        TLS-DHE-RSA-WITH-AES-128-CBC-SHA256     \
-        TLS-RSA-WITH-AES-256-CBC-SHA256         \
-        TLS-DHE-RSA-WITH-AES-256-CBC-SHA256     \
-        TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256   \
-        TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384   \
-        "
-
-    O_CIPHERS="$O_CIPHERS           \
-        NULL-SHA256                 \
-        AES128-SHA256               \
-        DHE-RSA-AES128-SHA256       \
-        AES256-SHA256               \
-        DHE-RSA-AES256-SHA256       \
-        ECDHE-RSA-AES128-SHA256     \
-        ECDHE-RSA-AES256-SHA384     \
-        "
-
-    P_CIPHERS="$P_CIPHERS                   \
-        TLS-RSA-WITH-AES-128-GCM-SHA256     \
-        TLS-RSA-WITH-AES-256-GCM-SHA384     \
-        TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 \
-        TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 \
-        TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 \
-        TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 \
-        "
-
-    O_CIPHERS="$O_CIPHERS           \
-        AES128-GCM-SHA256           \
-        DHE-RSA-AES128-GCM-SHA256   \
-        AES256-GCM-SHA384           \
-        DHE-RSA-AES256-GCM-SHA384   \
-        ECDHE-RSA-AES128-GCM-SHA256 \
-        ECDHE-RSA-AES256-GCM-SHA384 \
-        "
-fi
-
 filter()
 {
   LIST=$1
@@ -188,6 +84,195 @@
   echo "$NEW_LIST"
 }
 
+for VERIFY in $VERIFIES;
+do
+
+if [ "X$VERIFY" = "XYES" ];
+then
+    P_SERVER_ARGS="ca_file=data_files/test-ca_cat12.crt auth_mode=required"
+    P_CLIENT_ARGS="ca_file=data_files/test-ca_cat12.crt"
+    O_SERVER_ARGS="-CAfile data_files/test-ca_cat12.crt -Verify 10"
+    O_CLIENT_ARGS="-CAfile data_files/test-ca_cat12.crt"
+else
+    P_SERVER_ARGS=""
+    P_CLIENT_ARGS=""
+    O_SERVER_ARGS=""
+    O_CLIENT_ARGS=""
+fi
+
+
+for MODE in $MODES;
+do
+echo "-----------"
+echo "Running for $MODE (Verify: $VERIFY)"
+echo "-----------"
+
+for TYPE in $TYPES;
+do
+
+case $TYPE in
+
+    "ECDSA")
+
+        P_SERVER_ARGS="$P_SERVER_ARGS crt_file=data_files/server5.crt key_file=data_files/server5.key"
+        P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=data_files/server6.crt key_file=data_files/server6.key"
+        O_SERVER_ARGS="$O_SERVER_ARGS -cert data_files/server5.crt -key data_files/server5.key"
+        O_CLIENT_ARGS="$O_CLIENT_ARGS -cert data_files/server6.crt -key data_files/server6.key"
+
+        P_CIPHERS="                                 \
+            TLS-ECDHE-ECDSA-WITH-NULL-SHA           \
+            TLS-ECDHE-ECDSA-WITH-RC4-128-SHA        \
+            TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA   \
+            TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA    \
+            TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA    \
+            "
+
+        O_CIPHERS="                         \
+            ECDHE-ECDSA-NULL-SHA            \
+            ECDHE-ECDSA-RC4-SHA             \
+            ECDHE-ECDSA-DES-CBC3-SHA        \
+            ECDHE-ECDSA-AES128-SHA          \
+            ECDHE-ECDSA-AES256-SHA          \
+            "
+
+        if [ "$MODE" = "tls1_2" ];
+        then
+            P_CIPHERS="$P_CIPHERS                               \
+                TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256         \
+                TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384         \
+                TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256         \
+                TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384         \
+                "
+
+            O_CIPHERS="                         \
+                ECDHE-ECDSA-AES128-SHA256       \
+                ECDHE-ECDSA-AES256-SHA384       \
+                ECDHE-ECDSA-AES128-GCM-SHA256   \
+                ECDHE-ECDSA-AES256-GCM-SHA384   \
+                "
+        fi
+
+        ;;
+
+    "RSA")
+
+        P_SERVER_ARGS="$P_SERVER_ARGS crt_file=data_files/server1.crt key_file=data_files/server1.key"
+        P_CLIENT_ARGS="$P_CLIENT_ARGS crt_file=data_files/server2.crt key_file=data_files/server2.key"
+        O_SERVER_ARGS="$O_SERVER_ARGS -cert data_files/server1.crt -key data_files/server1.key"
+        O_CLIENT_ARGS="$O_CLIENT_ARGS -cert data_files/server2.crt -key data_files/server2.key"
+
+        P_CIPHERS="                                 \
+            TLS-DHE-RSA-WITH-AES-128-CBC-SHA        \
+            TLS-DHE-RSA-WITH-AES-256-CBC-SHA        \
+            TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA   \
+            TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA   \
+            TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA       \
+            TLS-RSA-WITH-AES-256-CBC-SHA            \
+            TLS-RSA-WITH-CAMELLIA-256-CBC-SHA       \
+            TLS-RSA-WITH-AES-128-CBC-SHA            \
+            TLS-RSA-WITH-CAMELLIA-128-CBC-SHA       \
+            TLS-RSA-WITH-3DES-EDE-CBC-SHA           \
+            TLS-RSA-WITH-RC4-128-SHA                \
+            TLS-RSA-WITH-RC4-128-MD5                \
+            TLS-RSA-EXPORT-WITH-RC4-40-MD5          \
+            TLS-RSA-WITH-NULL-MD5                   \
+            TLS-RSA-WITH-NULL-SHA                   \
+            TLS-RSA-WITH-DES-CBC-SHA                \
+            TLS-DHE-RSA-WITH-DES-CBC-SHA            \
+            TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA      \
+            TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA      \
+            TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA     \
+            TLS-ECDHE-RSA-WITH-RC4-128-SHA          \
+            TLS-ECDHE-RSA-WITH-NULL-SHA             \
+            "
+
+        O_CIPHERS="                         \
+            DHE-RSA-AES128-SHA              \
+            DHE-RSA-AES256-SHA              \
+            DHE-RSA-CAMELLIA128-SHA         \
+            DHE-RSA-CAMELLIA256-SHA         \
+            EDH-RSA-DES-CBC3-SHA            \
+            AES256-SHA                      \
+            CAMELLIA256-SHA                 \
+            AES128-SHA                      \
+            CAMELLIA128-SHA                 \
+            DES-CBC3-SHA                    \
+            RC4-SHA                         \
+            RC4-MD5                         \
+            EXP-RC4-MD5                     \
+            NULL-MD5                        \
+            NULL-SHA                        \
+            DES-CBC-SHA                     \
+            EDH-RSA-DES-CBC-SHA             \
+            ECDHE-RSA-AES256-SHA            \
+            ECDHE-RSA-AES128-SHA            \
+            ECDHE-RSA-DES-CBC3-SHA          \
+            ECDHE-RSA-RC4-SHA               \
+            ECDHE-RSA-NULL-SHA              \
+            "
+
+        if [ "$MODE" = "tls1_2" ];
+        then
+            P_CIPHERS="$P_CIPHERS                       \
+                TLS-RSA-WITH-NULL-SHA256                \
+                TLS-RSA-WITH-AES-128-CBC-SHA256         \
+                TLS-DHE-RSA-WITH-AES-128-CBC-SHA256     \
+                TLS-RSA-WITH-AES-256-CBC-SHA256         \
+                TLS-DHE-RSA-WITH-AES-256-CBC-SHA256     \
+                TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256   \
+                TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384   \
+                TLS-RSA-WITH-AES-128-GCM-SHA256         \
+                TLS-RSA-WITH-AES-256-GCM-SHA384         \
+                TLS-DHE-RSA-WITH-AES-128-GCM-SHA256     \
+                TLS-DHE-RSA-WITH-AES-256-GCM-SHA384     \
+                TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256   \
+                TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384   \
+                "
+
+            O_CIPHERS="$O_CIPHERS           \
+                NULL-SHA256                 \
+                AES128-SHA256               \
+                DHE-RSA-AES128-SHA256       \
+                AES256-SHA256               \
+                DHE-RSA-AES256-SHA256       \
+                ECDHE-RSA-AES128-SHA256     \
+                ECDHE-RSA-AES256-SHA384     \
+                AES128-GCM-SHA256           \
+                DHE-RSA-AES128-GCM-SHA256   \
+                AES256-GCM-SHA384           \
+                DHE-RSA-AES256-GCM-SHA384   \
+                ECDHE-RSA-AES128-GCM-SHA256 \
+                ECDHE-RSA-AES256-GCM-SHA384 \
+                "
+        fi
+
+        ;;
+
+    "PSK")
+
+        P_SERVER_ARGS="$P_SERVER_ARGS psk=6162636465666768696a6b6c6d6e6f70"
+        P_CLIENT_ARGS="$P_CLIENT_ARGS psk=6162636465666768696a6b6c6d6e6f70"
+        O_SERVER_ARGS="$O_SERVER_ARGS -psk 6162636465666768696a6b6c6d6e6f70"
+        O_CLIENT_ARGS="$O_CLIENT_ARGS -psk 6162636465666768696a6b6c6d6e6f70"
+
+        P_CIPHERS="                                 \
+            TLS-PSK-WITH-RC4-128-SHA                \
+            TLS-PSK-WITH-3DES-EDE-CBC-SHA           \
+            TLS-PSK-WITH-AES-128-CBC-SHA            \
+            TLS-PSK-WITH-AES-256-CBC-SHA            \
+            "
+
+        O_CIPHERS="                         \
+            PSK-RC4-SHA                     \
+            PSK-3DES-EDE-CBC-SHA            \
+            PSK-AES128-CBC-SHA              \
+            PSK-AES256-CBC-SHA              \
+            "
+
+        ;;
+
+esac
+
 # Filter ciphersuites
 if [ "X" != "X$FILTER" ];
 then
@@ -197,13 +282,14 @@
 
 
 log "$OPENSSL s_server -cert data_files/server2.crt -key data_files/server2.key -www -quiet -cipher NULL,ALL $O_SERVER_ARGS -$MODE"
-$OPENSSL s_server -cert data_files/server2.crt -key data_files/server2.key -www -quiet -cipher NULL,ALL $O_SERVER_ARGS -$MODE &
+$OPENSSL s_server -cert data_files/server2.crt -key data_files/server2.key -www -quiet -cipher NULL,ALL $O_SERVER_ARGS -$MODE >/dev/null 2>&1 &
 PROCESS_ID=$!
 
 sleep 1
 
 for i in $P_CIPHERS;
 do
+    let "tests++"
     log "../programs/ssl/ssl_client2 $P_CLIENT_ARGS force_ciphersuite=$i force_version=$MODE"
     RESULT="$( ../programs/ssl/ssl_client2 $P_CLIENT_ARGS force_ciphersuite=$i force_version=$MODE )"
     EXIT=$?
@@ -211,10 +297,12 @@
     if [ "$EXIT" = "2" ];
     then
         echo Ciphersuite not supported in client
+        let "skipped++"
     elif [ "$EXIT" != "0" ];
     then
         echo Failed
         echo $RESULT
+        let "failed++"
     else
         echo Success
     fi
@@ -230,6 +318,7 @@
 
 for i in $O_CIPHERS;
 do
+    let "tests++"
     log "$OPENSSL s_client -$MODE -cipher $i $O_CLIENT_ARGS"
     RESULT="$( ( echo -e 'GET HTTP/1.0'; echo; sleep 1 ) | $OPENSSL s_client -$MODE -cipher $i $O_CLIENT_ARGS 2>&1 )"
     EXIT=$?
@@ -241,11 +330,13 @@
         if [ "X$SUPPORTED" != "X" ]
         then
             echo "Ciphersuite not supported in server"
+            let "skipped++"
         else
             echo Failed
             echo ../programs/ssl/ssl_server2 $P_SERVER_ARGS 
             echo $OPENSSL s_client -$MODE -cipher $i $O_CLIENT_ARGS 
             echo $RESULT
+            let "failed++"
         fi
     else
         echo Success
@@ -261,49 +352,72 @@
 
 sleep 1
 
-# OpenSSL does not support RFC5246 and RFC6367 Camellia ciphers with SHA256
-# or SHA384
-# Add for PolarSSL only test, which does support them.
-#
-if [ "$MODE" = "tls1_2" ];
-then
-    P_CIPHERS="$P_CIPHERS                        \
-        TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256     \
-        TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 \
-        TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256     \
-        TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 \
-        TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 \
-        TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384 \
-        TLS-PSK-WITH-AES-128-CBC-SHA256          \
-        TLS-PSK-WITH-AES-256-CBC-SHA384          \
-        TLS-DHE-PSK-WITH-AES-128-CBC-SHA256      \
-        TLS-DHE-PSK-WITH-AES-256-CBC-SHA384      \
-        TLS-PSK-WITH-AES-128-GCM-SHA256          \
-        TLS-PSK-WITH-AES-256-GCM-SHA384          \
-        TLS-DHE-PSK-WITH-AES-128-GCM-SHA256      \
-        TLS-DHE-PSK-WITH-AES-256-GCM-SHA384      \
-        TLS-PSK-WITH-NULL-SHA256                 \
-        TLS-PSK-WITH-NULL-SHA384                 \
-        TLS-DHE-PSK-WITH-NULL-SHA256             \
-        TLS-DHE-PSK-WITH-NULL-SHA384             \
-        TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256     \
-        TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384     \
-        TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256 \
-        TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384 \
-        "
-fi
+# Add ciphersuites supported by PolarSSL only
 
-# OpenSSL does not support DHE-PSK ciphers
-# Add for PolarSSL only test, which does support them.
-#
-P_CIPHERS="$P_CIPHERS                        \
-    TLS-DHE-PSK-WITH-RC4-128-SHA             \
-    TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA        \
-    TLS-DHE-PSK-WITH-AES-128-CBC-SHA         \
-    TLS-DHE-PSK-WITH-AES-256-CBC-SHA         \
-    TLS-PSK-WITH-NULL-SHA                    \
-    TLS-DHE-PSK-WITH-NULL-SHA                \
-    "
+case $TYPE in
+
+    "ECDSA")
+
+        if [ "$MODE" = "tls1_2" ];
+        then
+            P_CIPHERS="$P_CIPHERS                               \
+                TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256    \
+                TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384    \
+                "
+        fi
+
+        ;;
+
+    "RSA")
+
+        if [ "$MODE" = "tls1_2" ];
+        then
+            P_CIPHERS="$P_CIPHERS                           \
+                TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256        \
+                TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256    \
+                TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256        \
+                TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256    \
+                TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256  \
+                TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384  \
+                "
+        fi
+
+        ;;
+
+    "PSK")
+
+        P_CIPHERS="$P_CIPHERS                        \
+            TLS-DHE-PSK-WITH-RC4-128-SHA             \
+            TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA        \
+            TLS-DHE-PSK-WITH-AES-128-CBC-SHA         \
+            TLS-DHE-PSK-WITH-AES-256-CBC-SHA         \
+            TLS-PSK-WITH-NULL-SHA                    \
+            TLS-DHE-PSK-WITH-NULL-SHA                \
+            "
+
+        if [ "$MODE" = "tls1_2" ];
+        then
+            P_CIPHERS="$P_CIPHERS                        \
+                TLS-PSK-WITH-AES-128-CBC-SHA256          \
+                TLS-PSK-WITH-AES-256-CBC-SHA384          \
+                TLS-DHE-PSK-WITH-AES-128-CBC-SHA256      \
+                TLS-DHE-PSK-WITH-AES-256-CBC-SHA384      \
+                TLS-PSK-WITH-AES-128-GCM-SHA256          \
+                TLS-PSK-WITH-AES-256-GCM-SHA384          \
+                TLS-DHE-PSK-WITH-AES-128-GCM-SHA256      \
+                TLS-DHE-PSK-WITH-AES-256-GCM-SHA384      \
+                TLS-PSK-WITH-NULL-SHA256                 \
+                TLS-PSK-WITH-NULL-SHA384                 \
+                TLS-DHE-PSK-WITH-NULL-SHA256             \
+                TLS-DHE-PSK-WITH-NULL-SHA384             \
+                TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256     \
+                TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384     \
+                TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256 \
+                TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384 \
+                "
+        fi
+
+esac
 
 # Filter ciphersuites
 if [ "X" != "X$FILTER" ];
@@ -314,6 +428,7 @@
 
 for i in $P_CIPHERS;
 do
+    let "tests++"
     log "../programs/ssl/ssl_client2 force_ciphersuite=$i force_version=$MODE $P_CLIENT_ARGS"
     RESULT="$( ../programs/ssl/ssl_client2 force_ciphersuite=$i force_version=$MODE $P_CLIENT_ARGS )"
     EXIT=$?
@@ -321,10 +436,12 @@
     if [ "$EXIT" = "2" ];
     then
         echo Ciphersuite not supported in client
+        let "skipped++"
     elif [ "$EXIT" != "0" ];
     then
         echo Failed
         echo $RESULT
+        let "failed++"
     else
         echo Success
     fi
@@ -334,3 +451,20 @@
 
 done
 done
+done
+
+echo ""
+echo "-------------------------------------------------------------------------"
+echo ""
+
+if (( failed != 0 ));
+then
+    echo -n "FAILED"
+else
+    echo -n "PASSED"
+fi
+
+let "passed = tests - failed"
+echo " ($passed / $tests tests ($skipped skipped))"
+
+exit $failed
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index 6acf4df..5bfd63d 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -3,7 +3,7 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:POLARSSL_ECDH_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C
+ * depends_on:POLARSSL_ECDH_C
  * END_DEPENDENCIES
  */
 
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index b4d6ffd..5ccb39d 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -3,7 +3,7 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:POLARSSL_ECDSA_C:POLARSSL_ECP_C:POLARSSL_BIGNUM_C
+ * depends_on:POLARSSL_ECDSA_C
  * END_DEPENDENCIES
  */
 
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 042077e..62c5de2 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -5,7 +5,7 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:POLARSSL_ECP_C:POLARSSL_BIGNUM_C
+ * depends_on:POLARSSL_ECP_C
  * END_DEPENDENCIES
  */
 
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 5f88ba7..8429182 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -463,23 +463,18 @@
 mpi_gcd:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"1"
 
 Base test mpi_inv_mod #1
-depends_on:POLARSSL_GENPRIME
 mpi_inv_mod:10:"3":10:"11":10:"4":0
 
 Base test mpi_inv_mod #2
-depends_on:POLARSSL_GENPRIME
 mpi_inv_mod:10:"3":10:"0":10:"0":POLARSSL_ERR_MPI_BAD_INPUT_DATA
 
 Base test mpi_inv_mod #3
-depends_on:POLARSSL_GENPRIME
 mpi_inv_mod:10:"3":10:"-11":10:"4":POLARSSL_ERR_MPI_BAD_INPUT_DATA
 
 Base test mpi_inv_mod #4
-depends_on:POLARSSL_GENPRIME
 mpi_inv_mod:10:"2":10:"4":10:"0":POLARSSL_ERR_MPI_NOT_ACCEPTABLE
 
 Test mpi_inv_mod #1
-depends_on:POLARSSL_GENPRIME
 mpi_inv_mod:16:"aa4df5cb14b4c31237f98bd1faf527c283c2d0f3eec89718664ba33f9762907c":16:"fffbbd660b94412ae61ead9c2906a344116e316a256fd387874c6c675b1d587d":16:"8d6a5c1d7adeae3e94b9bcd2c47e0d46e778bc8804a2cc25c02d775dc3d05b0c":0
 
 Base test mpi_is_prime #1
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 6a99a60..9bb5f0b 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -634,7 +634,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_GENPRIME */
 void mpi_is_prime( int radix_X, char *input_X, int div_result )
 {
     mpi X;
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index a4a5257..6822ceb 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -303,43 +303,43 @@
 x509parse_keyfile_ec:"data_files/ec_521_prv.pem":"NULL":0
 
 X509 Get Distinguished Name #1
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server1.crt":"subject":"C=NL, O=PolarSSL, CN=PolarSSL Server 1"
 
 X509 Get Distinguished Name #2
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server1.crt":"issuer":"C=NL, O=PolarSSL, CN=PolarSSL Test CA"
 
 X509 Get Distinguished Name #3
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server2.crt":"subject":"C=NL, O=PolarSSL, CN=localhost"
 
 X509 Get Distinguished Name #4
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_dn_gets:"data_files/server2.crt":"issuer":"C=NL, O=PolarSSL, CN=PolarSSL Test CA"
 
 X509 Time Expired #1
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_time_expired:"data_files/server1.crt":"valid_from":1
 
 X509 Time Expired #2
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_time_expired:"data_files/server1.crt":"valid_to":0
 
 X509 Time Expired #3
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_time_expired:"data_files/server2.crt":"valid_from":1
 
 X509 Time Expired #4
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_time_expired:"data_files/server2.crt":"valid_to":0
 
 X509 Time Expired #5
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_time_expired:"data_files/test-ca.crt":"valid_from":1
 
 X509 Time Expired #6
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C
 x509_time_expired:"data_files/test-ca.crt":"valid_to":0
 
 X509 Certificate verification #1 (Revoked Cert, Expired CRL)
@@ -686,114 +686,151 @@
 x509parse_crt:"306a3068a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743012300d06092A864886F70D0101010500030101":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid internal bitstring length)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400300000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid internal bitstring tag)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400310000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid mpi)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30743072a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301c300d06092A864886F70D0101010500030b0030080202ffff0302ffff":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, total length mismatch)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30753073a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301d300d06092A864886F70D0101010500030b0030080202ffff0202ffff00":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, check failed)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30743072a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374301c300d06092A864886F70D0101010500030b0030080202ffff0202ffff":"":POLARSSL_ERR_RSA_KEY_CHECK_FAILED
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, check failed, expanded length notation)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308183308180a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210fffffffffffffffffffffffffffffffe0202ffff":"":POLARSSL_ERR_RSA_KEY_CHECK_FAILED
 
 X509 Certificate ASN1 (TBSCertificate v3, Optional UIDs, Extensions not present)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308183308180a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, issuerID wrong tag)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308184308181a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff00":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate v3, UIDs, no ext)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308189308186a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bb":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, UIDs, invalid length)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308189308186a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa185aaa201bb":"":POLARSSL_ERR_ASN1_INVALID_LENGTH
 
 X509 Certificate ASN1 (TBSCertificate v3, ext empty)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30818b308188a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba300":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext length mismatch)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30818e30818ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba303300000":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (TBSCertificate v3, first ext invalid)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30818f30818ca0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30330023000":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, first ext invalid tag)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30819030818da0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba3043002310000":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, bool len missing)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30060603551d1301010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, data missing)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30c300a30080603551d1301010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, no octet present)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308198308195a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba30d300b30090603551d1301010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, octet data missing)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30819c308199a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba311300f300d0603551d130101010403300100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_UNEXPECTED_TAG
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, no pathlen)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30819f30819ca0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba314301230100603551d130101010406300402010102":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate v3, ext BasicContraint tag, octet len mismatch)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"3081a230819fa0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffffa101aaa201bba317301530130603551d130101010409300702010102010100":"":POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (correct pubkey, no sig_alg)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308183308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (sig_alg mismatch)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0102020500":"":POLARSSL_ERR_X509_CERT_SIG_MISMATCH
 
 X509 Certificate ASN1 (sig_alg, no sig)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (signature, invalid sig data)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308195308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030100":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (signature, data left)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308197308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff00":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
 
 X509 Certificate ASN1 (correct)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308196308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: ?\?=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (GeneralizedTime instead of UTCTime)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308198308182a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301e180e3230313030313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: ?\?=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2010-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with X520 CN)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b0603550403130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: CN=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with X520 C)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b0603550406130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: C=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with X520 L)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b0603550407130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: L=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with X520 ST)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b0603550408130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: ST=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with X520 O)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b060355040a130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: O=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with X520 OU)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b060355040b130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: OU=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with unknown X520 part)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b06035504de130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: ?\?=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with PKCS9 email)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30819f308189a0030201008204deadbeef300d06092a864886f70d010102050030153113301106092a864886f70d010901130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: emailAddress=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (Name with unknown PKCS9 part)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"30819f308189a0030201008204deadbeef300d06092a864886f70d010102050030153113301106092a864886f70d0109ab130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name   \: ?\?=Test\nsubject name  \: ?\?=Test\nissued  on    \: 2009-01-01 00\:00\:00\nexpires on    \: 2009-12-31 23\:59\:59\nsigned using  \: RSA with MD2\nRSA key size  \: 128 bits\n":0
 
 X509 Certificate ASN1 (ECDSA signature, RSA key)
+depends_on:POLARSSL_RSA_C
 x509parse_crt:"3081E630819E020103300906072A8648CE3D0401300F310D300B0603550403130454657374301E170D3133303731303039343631385A170D3233303730383039343631385A300F310D300B0603550403130454657374304C300D06092A864886F70D0101010500033B003038023100E8F546061D3B49BC2F6B7524B7EA4D73A8D5293EE8C64D9407B70B5D16BAEBC32B8205591EAB4E1EB57E9241883701250203010001300906072A8648CE3D0401033800303502186E18209AFBED14A0D9A796EFCAD68891E3CCD5F75815C833021900E92B4FD460B1994693243B9FFAD54729DE865381BDA41D25":"cert. version \: 1\nserial number \: 03\nissuer name   \: CN=Test\nsubject name  \: CN=Test\nissued  on    \: 2013-07-10 09\:46\:18\nexpires on    \: 2023-07-08 09\:46\:18\nsigned using  \: ECDSA with SHA1\nRSA key size  \: 384 bits\n":0
 
 X509 Certificate ASN1 (ECDSA signature, EC key)
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index ce27a9f..26ce8f5 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -165,7 +165,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
 void x509parse_keyfile_rsa( char *key_file, char *password, int result )
 {
     rsa_context rsa;
@@ -190,7 +190,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
 void x509parse_public_keyfile_rsa( char *key_file, int result )
 {
     rsa_context rsa;
@@ -317,7 +317,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
 void x509parse_key_rsa( char *key_data, char *result_str, int result )
 {
     rsa_context   rsa;
diff --git a/visualc/VS2010/PolarSSL.vcxproj b/visualc/VS2010/PolarSSL.vcxproj
index 84a23ee..d1adc0f 100644
--- a/visualc/VS2010/PolarSSL.vcxproj
+++ b/visualc/VS2010/PolarSSL.vcxproj
@@ -147,6 +147,7 @@
     <ClInclude Include="..\..\include\polarssl\aes.h" />

     <ClInclude Include="..\..\include\polarssl\arc4.h" />

     <ClInclude Include="..\..\include\polarssl\asn1.h" />

+    <ClInclude Include="..\..\include\polarssl\asn1write.h" />

     <ClInclude Include="..\..\include\polarssl\base64.h" />

     <ClInclude Include="..\..\include\polarssl\bignum.h" />

     <ClInclude Include="..\..\include\polarssl\blowfish.h" />

@@ -160,34 +161,48 @@
     <ClInclude Include="..\..\include\polarssl\debug.h" />

     <ClInclude Include="..\..\include\polarssl\des.h" />

     <ClInclude Include="..\..\include\polarssl\dhm.h" />

+    <ClInclude Include="..\..\include\polarssl\ecdh.h" />

+    <ClInclude Include="..\..\include\polarssl\ecdsa.h" />

+    <ClInclude Include="..\..\include\polarssl\ecp.h" />

     <ClInclude Include="..\..\include\polarssl\entropy.h" />

     <ClInclude Include="..\..\include\polarssl\entropy_poll.h" />

     <ClInclude Include="..\..\include\polarssl\error.h" />

+    <ClInclude Include="..\..\include\polarssl\gcm.h" />

     <ClInclude Include="..\..\include\polarssl\havege.h" />

-    <ClInclude Include="..\..\include\polarssl\md.h" />

     <ClInclude Include="..\..\include\polarssl\md2.h" />

     <ClInclude Include="..\..\include\polarssl\md4.h" />

     <ClInclude Include="..\..\include\polarssl\md5.h" />

+    <ClInclude Include="..\..\include\polarssl\md.h" />

     <ClInclude Include="..\..\include\polarssl\md_wrap.h" />

+    <ClInclude Include="..\..\include\polarssl\memory.h" />

     <ClInclude Include="..\..\include\polarssl\net.h" />

+    <ClInclude Include="..\..\include\polarssl\oid.h" />

     <ClInclude Include="..\..\include\polarssl\openssl.h" />

     <ClInclude Include="..\..\include\polarssl\padlock.h" />

+    <ClInclude Include="..\..\include\polarssl\pbkdf2.h" />

     <ClInclude Include="..\..\include\polarssl\pem.h" />

     <ClInclude Include="..\..\include\polarssl\pkcs11.h" />

+    <ClInclude Include="..\..\include\polarssl\pkcs12.h" />

+    <ClInclude Include="..\..\include\polarssl\pkcs5.h" />

+    <ClInclude Include="..\..\include\polarssl\pk.h" />

     <ClInclude Include="..\..\include\polarssl\rsa.h" />

     <ClInclude Include="..\..\include\polarssl\sha1.h" />

-    <ClInclude Include="..\..\include\polarssl\sha2.h" />

-    <ClInclude Include="..\..\include\polarssl\sha4.h" />

+    <ClInclude Include="..\..\include\polarssl\sha256.h" />

+    <ClInclude Include="..\..\include\polarssl\sha512.h" />

+    <ClInclude Include="..\..\include\polarssl\ssl_cache.h" />

+    <ClInclude Include="..\..\include\polarssl\ssl_ciphersuites.h" />

     <ClInclude Include="..\..\include\polarssl\ssl.h" />

     <ClInclude Include="..\..\include\polarssl\timing.h" />

     <ClInclude Include="..\..\include\polarssl\version.h" />

     <ClInclude Include="..\..\include\polarssl\x509.h" />

+    <ClInclude Include="..\..\include\polarssl\x509write.h" />

     <ClInclude Include="..\..\include\polarssl\xtea.h" />

   </ItemGroup>

   <ItemGroup>

     <ClCompile Include="..\..\library\aes.c" />

     <ClCompile Include="..\..\library\arc4.c" />

     <ClCompile Include="..\..\library\asn1parse.c" />

+    <ClCompile Include="..\..\library\asn1write.c" />

     <ClCompile Include="..\..\library\base64.c" />

     <ClCompile Include="..\..\library\bignum.c" />

     <ClCompile Include="..\..\library\blowfish.c" />

@@ -199,34 +214,46 @@
     <ClCompile Include="..\..\library\debug.c" />

     <ClCompile Include="..\..\library\des.c" />

     <ClCompile Include="..\..\library\dhm.c" />

+    <ClCompile Include="..\..\library\ecdh.c" />

+    <ClCompile Include="..\..\library\ecdsa.c" />

+    <ClCompile Include="..\..\library\ecp.c" />

     <ClCompile Include="..\..\library\entropy.c" />

     <ClCompile Include="..\..\library\entropy_poll.c" />

     <ClCompile Include="..\..\library\error.c" />

     <ClCompile Include="..\..\library\gcm.c" />

     <ClCompile Include="..\..\library\havege.c" />

-    <ClCompile Include="..\..\library\md.c" />

     <ClCompile Include="..\..\library\md2.c" />

     <ClCompile Include="..\..\library\md4.c" />

     <ClCompile Include="..\..\library\md5.c" />

+    <ClCompile Include="..\..\library\md.c" />

     <ClCompile Include="..\..\library\md_wrap.c" />

+    <ClCompile Include="..\..\library\memory_buffer_alloc.c" />

+    <ClCompile Include="..\..\library\memory.c" />

     <ClCompile Include="..\..\library\net.c" />

+    <ClCompile Include="..\..\library\oid.c" />

     <ClCompile Include="..\..\library\padlock.c" />

+    <ClCompile Include="..\..\library\pbkdf2.c" />

     <ClCompile Include="..\..\library\pem.c" />

+    <ClCompile Include="..\..\library\pk.c" />

     <ClCompile Include="..\..\library\pkcs11.c" />

+    <ClCompile Include="..\..\library\pkcs12.c" />

+    <ClCompile Include="..\..\library\pkcs5.c" />

     <ClCompile Include="..\..\library\rsa.c" />

     <ClCompile Include="..\..\library\sha1.c" />

-    <ClCompile Include="..\..\library\sha2.c" />

-    <ClCompile Include="..\..\library\sha4.c" />

+    <ClCompile Include="..\..\library\sha256.c" />

+    <ClCompile Include="..\..\library\sha512.c" />

     <ClCompile Include="..\..\library\ssl_cache.c" />

+    <ClCompile Include="..\..\library\ssl_ciphersuites.c" />

     <ClCompile Include="..\..\library\ssl_cli.c" />

     <ClCompile Include="..\..\library\ssl_srv.c" />

     <ClCompile Include="..\..\library\ssl_tls.c" />

     <ClCompile Include="..\..\library\timing.c" />

     <ClCompile Include="..\..\library\version.c" />

     <ClCompile Include="..\..\library\x509parse.c" />

+    <ClCompile Include="..\..\library\x509write.c" />

     <ClCompile Include="..\..\library\xtea.c" />

   </ItemGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

   <ImportGroup Label="ExtensionTargets">

   </ImportGroup>

-</Project>
\ No newline at end of file
+</Project>

diff --git a/visualc/VS6/polarssl.dsp b/visualc/VS6/polarssl.dsp
index 935300c..a808cda 100644
--- a/visualc/VS6/polarssl.dsp
+++ b/visualc/VS6/polarssl.dsp
@@ -97,6 +97,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\asn1write.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\base64.c

 # End Source File

 # Begin Source File

@@ -141,6 +145,18 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\ecdh.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\ecdsa.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\ecp.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\entropy.c

 # End Source File

 # Begin Source File

@@ -153,18 +169,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\gcm.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\havege.c

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\library\md.c

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\library\md_wrap.c

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\library\md2.c

 # End Source File

 # Begin Source File

@@ -177,18 +189,58 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\md.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\md_wrap.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\memory_buffer_alloc.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\memory.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\net.c

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\oid.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\padlock.c

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\pbkdf2.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\pem.c

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\pk.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\pkcs11.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\pkcs12.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\pkcs5.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\rsa.c

 # End Source File

 # Begin Source File

@@ -197,11 +249,19 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\library\sha2.c

+SOURCE=..\..\library\sha256.c

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\library\sha4.c

+SOURCE=..\..\library\sha512.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\ssl_cache.c

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\library\ssl_ciphersuites.c

 # End Source File

 # Begin Source File

 

@@ -221,10 +281,18 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\version.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\x509parse.c

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\library\x509write.c

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\library\xtea.c

 # End Source File

 # End Group

@@ -245,6 +313,10 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\asn1write.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\base64.h

 # End Source File

 # Begin Source File

@@ -297,6 +369,18 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\ecdh.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\ecdsa.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\ecp.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\entropy.h

 # End Source File

 # Begin Source File

@@ -309,18 +393,14 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\gcm.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\havege.h

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\include\polarssl\md.h

-# End Source File

-# Begin Source File

-

-SOURCE=..\..\include\polarssl\md_wrap.h

-# End Source File

-# Begin Source File

-

 SOURCE=..\..\include\polarssl\md2.h

 # End Source File

 # Begin Source File

@@ -333,18 +413,58 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\md.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\md_wrap.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\memory.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\net.h

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\oid.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\openssl.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\padlock.h

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\pbkdf2.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\pem.h

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\pkcs11.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\pkcs12.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\pkcs5.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\pk.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\rsa.h

 # End Source File

 # Begin Source File

@@ -353,11 +473,19 @@
 # End Source File

 # Begin Source File

 

-SOURCE=..\..\include\polarssl\sha2.h

+SOURCE=..\..\include\polarssl\sha256.h

 # End Source File

 # Begin Source File

 

-SOURCE=..\..\include\polarssl\sha4.h

+SOURCE=..\..\include\polarssl\sha512.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\ssl_cache.h

+# End Source File

+# Begin Source File

+

+SOURCE=..\..\include\polarssl\ssl_ciphersuites.h

 # End Source File

 # Begin Source File

 

@@ -369,10 +497,18 @@
 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\version.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\x509.h

 # End Source File

 # Begin Source File

 

+SOURCE=..\..\include\polarssl\x509write.h

+# End Source File

+# Begin Source File

+

 SOURCE=..\..\include\polarssl\xtea.h

 # End Source File

 # End Group