Merge branch 'parse-ec-crt' into development
diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h
index ae498d0..195ebcb 100644
--- a/include/polarssl/asn1.h
+++ b/include/polarssl/asn1.h
@@ -213,6 +213,19 @@
                         asn1_bitstring *bs);
 
 /**
+ * Retrieve a bitstring ASN.1 tag without unused bits and its value.
+ * Updates the pointer to the beginning of the bit/octet string.
+ *
+ * \param p     The position in the ASN.1 data
+ * \param end   End of data
+ * \param len   Length of the actual bit/octect string in bytes
+ *
+ * \return      0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+                             size_t *len );
+
+/**
  * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
  * Updated the pointer to immediately behind the full sequence tag.
  *
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index c1f08c9..7bd9bd5 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -95,18 +95,12 @@
  * \brief           ECP key pair structure
  *
  * A generic key pair that could be used for ECDSA, fixed ECDH, etc.
- * Usage can be restricted to a particular algorithm by the 'alg' field,
- * see POLARSSL_ECP_KEY_ALG_* constants (default: unrestricted).
- *
- * \sa ecdh_context
- * \sa ecdsa_context
  */
 typedef struct
 {
     ecp_group grp;      /*!<  Elliptic curve and base point     */
     mpi d;              /*!<  our secret value                  */
     ecp_point Q;        /*!<  our public value                  */
-    int alg;            /*!<  algorithm to use this key with    */
 }
 ecp_keypair;
 
@@ -121,8 +115,10 @@
  * parameters. Therefore, only well-known domain parameters from trusted
  * sources should be used. See ecp_use_known_dp().
  *
- * \note The values are taken from RFC 4492's enum NamedCurve.
+ * \note The values are taken from RFC 4492's enum NamedCurve,
+ * except NONE which is used to denote uninitialized groups.
  */
+#define POLARSSL_ECP_DP_NONE        0
 #define POLARSSL_ECP_DP_SECP192R1   19
 #define POLARSSL_ECP_DP_SECP224R1   21
 #define POLARSSL_ECP_DP_SECP256R1   23
@@ -158,12 +154,6 @@
  */
 #define POLARSSL_ECP_TLS_NAMED_CURVE    3   /**< ECCurveType's named_curve */
 
-/*
- * Algorithm identifiers from RFC 5480 for use with EC keys
- */
-#define POLARSSL_ECP_KEY_ALG_UNRESTRICTED   0   /**< RFC 5480 2.1.1 */
-#define POLARSSL_ECP_KEY_ALG_ECDH           1   /**< RFC 5480 2.1.2 */
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h
index a39055b..0c3dab2 100644
--- a/include/polarssl/oid.h
+++ b/include/polarssl/oid.h
@@ -276,6 +276,36 @@
  *   iso(1) identified-organization(3) certicom(132) curve(0) 35 } */
 #define OID_EC_GRP_SECP521R1        OID_CERTICOM "\x00\x23"
 
+/*
+ * ECDSA signature identifers, from RFC 5480
+ */
+#define OID_ANSI_X9_62_SIG          OID_ANSI_X9_62 "\x04" /* signatures(4) */
+#define OID_ANSI_X9_62_SIG_SHA2     OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */
+
+/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */
+#define OID_ECDSA_SHA1              OID_ANSI_X9_62_SIG "\x01"
+
+/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 1 } */
+#define OID_ECDSA_SHA224            OID_ANSI_X9_62_SIG_SHA2 "\x01"
+
+/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 2 } */
+#define OID_ECDSA_SHA256            OID_ANSI_X9_62_SIG_SHA2 "\x02"
+
+/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 3 } */
+#define OID_ECDSA_SHA384            OID_ANSI_X9_62_SIG_SHA2 "\x03"
+
+/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
+ *   iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ *   ecdsa-with-SHA2(3) 4 } */
+#define OID_ECDSA_SHA512            OID_ANSI_X9_62_SIG_SHA2 "\x04"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index 00f8cfc..df3fc44 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -27,7 +27,35 @@
 #ifndef POLARSSL_PK_H
 #define POLARSSL_PK_H
 
+#include "config.h"
+
+#if defined(POLARSSL_RSA_C)
+#include "rsa.h"
+#endif
+
 #define POLARSSL_ERR_PK_MALLOC_FAILED       -0x2F80  /**< Memory alloation failed. */
+#define POLARSSL_ERR_PK_TYPE_MISMATCH       -0x2F00  /**< Type mismatch, eg attempt to use a RSA key as EC, or to modify key type */
+
+#if defined(POLARSSL_RSA_C)
+/**
+ * Quick access to an RSA context inside a PK context.
+ *
+ * \warning You must make sure the PK context actually holds an RSA context
+ * before using this macro!
+ */
+#define pk_rsa( pk )        ( (rsa_context *) (pk).data )
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/**
+ * Quick access to an EC context inside a PK context.
+ *
+ * \warning You must make sure the PK context actually holds an EC context
+ * before using this macro!
+ */
+#define pk_ec( pk )         ( (ecp_keypair *) (pk).data )
+#endif /* POLARSSL_ECP_C */
+
 
 #ifdef __cplusplus
 extern "C" {
@@ -38,13 +66,10 @@
  */
 typedef enum {
     POLARSSL_PK_NONE=0,
-#if defined(POLARSSL_RSA_C)
     POLARSSL_PK_RSA,
-#endif
-#if defined(POLARSSL_ECP_C)
     POLARSSL_PK_ECKEY,
     POLARSSL_PK_ECKEY_DH,
-#endif
+    POLARSSL_PK_ECDSA,
 } pk_type_t;
 
 /**
@@ -52,8 +77,9 @@
  */
 typedef struct
 {
-    pk_type_t   type;   /**< Public key type */
-    void *      data;   /**< Public key data */
+    pk_type_t   type;       /**< Public key type */
+    void *      data;       /**< Public key data */
+    int         dont_free;  /**< True if data must not be freed */
 } pk_context;
 
 /**
@@ -72,10 +98,30 @@
  * \param ctx       Context to initialize
  * \param type      Type of key
  *
- * \return          O on success, or POLARSSL_ERR_PK_MALLOC_FAILED
+ * \note            Once the type of a key has been set, it cannot be reset.
+ *                  If you want to do so, you need to use pk_free() first.
+ *
+ * \return          O on success,
+ *                  POLARSSL_ERR_PK_MALLOC_FAILED on memory allocation fail,
+ *                  POLARSSL_ERR_PK_TYPE_MISMATCH on attempts to reset type.
  */
 int pk_set_type( pk_context *ctx, pk_type_t type );
 
+#if defined(POLARSSL_RSA_C)
+/**
+ * \brief           Wrap a RSA context in a PK context
+ *
+ * \param ctx       PK context to initiliaze
+ * \param rsa       RSA context to use
+ *
+ * \note            The PK context must be freshly initialized.
+ *
+ * \return          O on success,
+ *                  POLARSSL_ERR_PK_TYPE_MISMATCH if ctx was not empty.
+ */
+int pk_wrap_rsa( pk_context *ctx, const rsa_context *rsa);
+#endif /* POLARSSL_RSA_C */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index f0c0e7a..3315535 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -211,8 +211,7 @@
     x509_time valid_from;       /**< Start time of certificate validity. */
     x509_time valid_to;         /**< End time of certificate validity. */
 
-    x509_buf pk_oid;            /**< Subject public key info. Includes the public key algorithm and the key itself. */
-    rsa_context rsa;            /**< Container for the RSA context. Only RSA is supported for public keys at this time. */
+    pk_context pk;              /**< Container for the public key context. */
 
     x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
     x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
@@ -417,6 +416,7 @@
  */
 int x509parse_crlfile( x509_crl *chain, const char *path );
 
+#if defined(POLARSSL_RSA_C)
 /** \ingroup x509_module */
 /**
  * \brief          Parse a private RSA key
@@ -469,6 +469,7 @@
  * \return         0 if successful, or a specific X509 or PEM error code
  */
 int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path );
+#endif /* POLARSSL_RSA_C */
 
 /** \ingroup x509_module */
 /**
diff --git a/library/asn1parse.c b/library/asn1parse.c
index 5b86aa6..f6b79ef 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -209,6 +209,24 @@
     return 0;
 }
 
+/*
+ * Get a bit string without unused bits
+ */
+int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+                             size_t *len )
+{
+    int ret;
+
+    if( ( ret = asn1_get_tag( p, end, len, ASN1_BIT_STRING ) ) != 0 )
+        return( ret );
+
+    if( --*len < 1 || *(*p)++ != 0 )
+        return( POLARSSL_ERR_ASN1_INVALID_DATA );
+
+    return( 0 );
+}
+
+
 
 /*
  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
diff --git a/library/debug.c b/library/debug.c
index 23b9019..8e3dd03 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -250,11 +250,25 @@
         str[maxlen] = '\0';
         ssl->f_dbg( ssl->p_dbg, level, str );
 
-        debug_print_mpi( ssl, level, file, line,
-                         "crt->rsa.N", &crt->rsa.N );
-
-        debug_print_mpi( ssl, level, file, line,
-                         "crt->rsa.E", &crt->rsa.E );
+#if defined(POLARSSL_RSA_C)
+        if( crt->pk.type == POLARSSL_PK_RSA )
+        {
+            debug_print_mpi( ssl, level, file, line,
+                    "crt->rsa.N", &pk_rsa( crt->pk )->N );
+            debug_print_mpi( ssl, level, file, line,
+                    "crt->rsa.E", &pk_rsa( crt->pk )->E );
+        } else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+        if( crt->pk.type == POLARSSL_PK_ECKEY ||
+            crt->pk.type == POLARSSL_PK_ECKEY_DH )
+        {
+            debug_print_ecp( ssl, level, file, line,
+                    "crt->eckey.Q", &pk_ec( crt->pk )->Q );
+        } else
+#endif /* POLARSSL_ECP_C */
+            debug_print_msg( ssl, level, file, line,
+                    "crt->pk.type is not valid" );
 
         crt = crt->next;
     }
diff --git a/library/ecp.c b/library/ecp.c
index 9e7a967..1468312 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -101,7 +101,6 @@
     ecp_group_init( &key->grp );
     mpi_init( &key->d );
     ecp_point_init( &key->Q );
-    key->alg = POLARSSL_ECP_KEY_ALG_UNRESTRICTED;
 }
 
 /*
@@ -142,7 +141,6 @@
     ecp_group_free( &key->grp );
     mpi_free( &key->d );
     ecp_point_free( &key->Q );
-    key->alg = POLARSSL_ECP_KEY_ALG_UNRESTRICTED;
 }
 
 /*
diff --git a/library/error.c b/library/error.c
index 0a739b5..560c54c 100644
--- a/library/error.c
+++ b/library/error.c
@@ -250,6 +250,8 @@
 #if defined(POLARSSL_PK_C)
         if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) )
             snprintf( buf, buflen, "PK - Memory alloation failed" );
+        if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) )
+            snprintf( buf, buflen, "PK - Type mismatch, eg attempt to use a RSA key as EC, or to modify key type" );
 #endif /* POLARSSL_PK_C */
 
 #if defined(POLARSSL_PKCS12_C)
diff --git a/library/oid.c b/library/oid.c
index 449b3e1..750ece8 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -299,6 +299,26 @@
         POLARSSL_MD_SHA1,     POLARSSL_PK_RSA,
     },
     {
+        { OID_ECDSA_SHA1,       "ecdsa-with-SHA1",      "ECDSA with SHA1" },
+        POLARSSL_MD_SHA1,     POLARSSL_PK_ECDSA,
+    },
+    {
+        { OID_ECDSA_SHA224,     "ecdsa-with-SHA224",    "ECDSA with SHA224" },
+        POLARSSL_MD_SHA224,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { OID_ECDSA_SHA256,     "ecdsa-with-SHA256",    "ECDSA with SHA256" },
+        POLARSSL_MD_SHA256,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { OID_ECDSA_SHA384,     "ecdsa-with-SHA384",    "ECDSA with SHA384" },
+        POLARSSL_MD_SHA384,   POLARSSL_PK_ECDSA,
+    },
+    {
+        { OID_ECDSA_SHA512,     "ecdsa-with-SHA512",    "ECDSA with SHA512" },
+        POLARSSL_MD_SHA512,   POLARSSL_PK_ECDSA,
+    },
+    {
         { NULL, NULL, NULL },
         0, 0,
     },
@@ -571,8 +591,7 @@
     for( i = 1; i < oid->len; i++ )
     {
         /* Prevent overflow in value. */
-        unsigned int v = value << 7;
-        if ( v < value )
+        if ( ( ( value << 7 ) >> 7 ) != value )
             return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
 
         value <<= 7;
diff --git a/library/pk.c b/library/pk.c
index 71505ed..78ff5e9 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -33,6 +33,9 @@
 #if defined(POLARSSL_ECP_C)
 #include "polarssl/ecp.h"
 #endif
+#if defined(POLARSSL_ECDSA_C)
+#include "polarssl/ecdsa.h"
+#endif
 
 #include <stdlib.h>
 
@@ -46,6 +49,7 @@
 
     ctx->type = POLARSSL_PK_NONE;
     ctx->data = NULL;
+    ctx->dont_free = 0;
 }
 
 /*
@@ -56,26 +60,27 @@
     if( ctx == NULL )
         return;
 
-    switch( ctx->type )
-    {
-        case POLARSSL_PK_NONE:
-            break;
-
 #if defined(POLARSSL_RSA_C)
-        case POLARSSL_PK_RSA:
-            rsa_free( ctx->data );
-            break;
+    if( ctx->type == POLARSSL_PK_RSA )
+        rsa_free( ctx->data );
+    else
 #endif
-
 #if defined(POLARSSL_ECP_C)
-        case POLARSSL_PK_ECKEY:
-        case POLARSSL_PK_ECKEY_DH:
-            ecp_keypair_free( ctx->data );
-            break;
+    if( ctx->type == POLARSSL_PK_ECKEY || ctx->type == POLARSSL_PK_ECKEY_DH )
+        ecp_keypair_free( ctx->data );
+    else
 #endif
+#if defined(POLARSSL_ECDSA_C)
+    if( ctx->type == POLARSSL_PK_ECDSA )
+        ecdsa_free( ctx->data );
+    else
+#endif
+    {
+        ; /* guard for the else's above */
     }
 
-    free( ctx-> data );
+    if( ! ctx->dont_free )
+        free( ctx->data );
 
     ctx->type = POLARSSL_PK_NONE;
     ctx->data = NULL;
@@ -86,26 +91,30 @@
  */
 int pk_set_type( pk_context *ctx, pk_type_t type )
 {
-    size_t size = 0;
+    size_t size;
 
-    switch( type )
-    {
+    if( ctx->type == type )
+        return( 0 );
+
+    if( ctx->type != POLARSSL_PK_NONE )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
 #if defined(POLARSSL_RSA_C)
-        case POLARSSL_PK_RSA:
-            size = sizeof( rsa_context );
-            break;
+    if( type == POLARSSL_PK_RSA )
+        size = sizeof( rsa_context );
+    else
 #endif
-
 #if defined(POLARSSL_ECP_C)
-        case POLARSSL_PK_ECKEY:
-        case POLARSSL_PK_ECKEY_DH:
-            size = sizeof( ecp_keypair );
-            break;
+    if( type == POLARSSL_PK_ECKEY || type == POLARSSL_PK_ECKEY_DH )
+        size = sizeof( ecp_keypair );
+    else
 #endif
-
-        case POLARSSL_PK_NONE:
-            ; /* Should not happen */
-    }
+#if defined(POLARSSL_ECDSA_C)
+    if( type == POLARSSL_PK_ECDSA )
+        size = sizeof( ecdsa_context );
+    else
+#endif
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
 
     if( ( ctx->data = malloc( size ) ) == NULL )
         return( POLARSSL_ERR_PK_MALLOC_FAILED );
@@ -115,3 +124,20 @@
 
     return( 0 );
 }
+
+#if defined(POLARSSL_RSA_C)
+/*
+ * Wrap an RSA context in a PK context
+ */
+int pk_wrap_rsa( pk_context *ctx, const rsa_context *rsa)
+{
+    if( ctx->type != POLARSSL_PK_NONE )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    ctx->type = POLARSSL_PK_RSA;
+    ctx->data = (rsa_context *) rsa;
+    ctx->dont_free = 1;
+
+    return( 0 );
+}
+#endif
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 66ebcef..aeba799 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1072,8 +1072,12 @@
             return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
         }
 
+        /* EC NOT IMPLEMENTED YET */
+        if( ssl->session_negotiate->peer_cert->pk.type != POLARSSL_PK_RSA )
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+
         if( (unsigned int)( end - p ) !=
-            ssl->session_negotiate->peer_cert->rsa.len )
+            pk_rsa( ssl->session_negotiate->peer_cert->pk )->len )
         {
             SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
             return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
@@ -1139,9 +1143,9 @@
 
         SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
 
-        if( ( ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa,
-                                      RSA_PUBLIC,
-                                      md_alg, hashlen, hash, p ) ) != 0 )
+        if( ( ret = rsa_pkcs1_verify(
+                        pk_rsa( ssl->session_negotiate->peer_cert->pk ),
+                        RSA_PUBLIC, md_alg, hashlen, hash, p ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
             return( ret );
@@ -1516,8 +1520,12 @@
         if( ret != 0 )
             return( ret );
 
+        /* EC NOT IMPLEMENTED YET */
+        if( ssl->session_negotiate->peer_cert->pk.type != POLARSSL_PK_RSA )
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+
         i = 4;
-        n = ssl->session_negotiate->peer_cert->rsa.len;
+        n = pk_rsa( ssl->session_negotiate->peer_cert->pk )->len;
 
         if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
         {
@@ -1526,12 +1534,11 @@
             ssl->out_msg[5] = (unsigned char)( n      );
         }
 
-        ret = rsa_pkcs1_encrypt( &ssl->session_negotiate->peer_cert->rsa,
-                                  ssl->f_rng, ssl->p_rng,
-                                  RSA_PUBLIC,
-                                  ssl->handshake->pmslen,
-                                  ssl->handshake->premaster,
-                                  ssl->out_msg + i );
+        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 );
         if( ret != 0 )
         {
             SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index c6a8273..2aef9c4 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1968,7 +1968,11 @@
         md_alg = POLARSSL_MD_NONE;
     }
 
-    n1 = ssl->session_negotiate->peer_cert->rsa.len;
+    /* EC NOT IMPLEMENTED YET */
+    if( ssl->session_negotiate->peer_cert->pk.type != POLARSSL_PK_RSA )
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+
+    n1 = pk_rsa( ssl->session_negotiate->peer_cert->pk )->len;
     n2 = ( ssl->in_msg[4 + n] << 8 ) | ssl->in_msg[5 + n];
 
     if( n + n1 + 6 != ssl->in_hslen || n1 != n2 )
@@ -1977,8 +1981,9 @@
         return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
     }
 
-    ret = rsa_pkcs1_verify( &ssl->session_negotiate->peer_cert->rsa, RSA_PUBLIC,
-                            md_alg, hashlen, hash, ssl->in_msg + 6 + n );
+    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 )
     {
         SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
diff --git a/library/x509parse.c b/library/x509parse.c
index c5f9049..a11c064 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -160,47 +160,59 @@
     return( 0 );
 }
 
-/*
+/* Get a PK algorithm identifier
+ *
  *  AlgorithmIdentifier  ::=  SEQUENCE  {
  *       algorithm               OBJECT IDENTIFIER,
  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
- *
- * If params_end is NULL, then parameters must be absent or ANS.1 NULL
  */
-static int x509_get_alg( unsigned char **p,
-                         const unsigned char *end,
-                         x509_buf *alg, const unsigned char **params_end )
+static int x509_get_pk_alg( unsigned char **p,
+                            const unsigned char *end,
+                            pk_type_t *pk_alg, x509_buf *params )
 {
     int ret;
-    size_t len;
+    x509_buf alg_oid;
 
-    if( params_end == NULL ) {
-        if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
-            return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
+    memset( params, 0, sizeof(asn1_buf) );
 
-        return( 0 );
-    }
+    if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
+        return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
 
-    /* TODO: use asn1_get_alg */
-    if( ( ret = asn1_get_tag( p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    if( oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
+        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+
+    /*
+     * No parameters with RSA (only for EC)
+     */
+    if( *pk_alg == POLARSSL_PK_RSA &&
+            ( ( params->tag != ASN1_NULL && params->tag != 0 ) ||
+                params->len != 0 ) )
     {
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
+        return( POLARSSL_ERR_X509_CERT_INVALID_ALG );
     }
 
-    end = *p + len;
-    alg->tag = **p;
-
-    if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
-
-    alg->p = *p;
-    *p += alg->len;
-
-    *params_end = end;
     return( 0 );
 }
 
+/* Get an algorithm identifier without parameters (eg for signatures)
+ *
+ *  AlgorithmIdentifier  ::=  SEQUENCE  {
+ *       algorithm               OBJECT IDENTIFIER,
+ *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ */
+static int x509_get_alg_null( unsigned char **p, const unsigned char *end,
+                              x509_buf *alg )
+{
+    int ret;
+
+    if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
+        return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
+
+    return( 0 );
+}
+
+
+#if defined(POLARSSL_ECP_C)
 /* Get an EC group id from an ECParameters buffer
  *
  * ECParameters ::= CHOICE {
@@ -210,62 +222,48 @@
  * }
  */
 static int x509_get_ecparams( unsigned char **p, const unsigned char *end,
-                              ecp_group_id *grp_id )
+                              x509_buf *params )
 {
     int ret;
-    x509_buf curve;
 
-    curve.tag = **p;
+    params->tag = **p;
 
-    if( ( ret = asn1_get_tag( p, end, &curve.len, ASN1_OID ) ) != 0 )
+    if( ( ret = asn1_get_tag( p, end, &params->len, ASN1_OID ) ) != 0 )
         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
 
-    curve.p = *p;
-    *p += curve.len;
+    params->p = *p;
+    *p += params->len;
 
     if( *p != end )
         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
 
-    if( ( ret = oid_get_ec_grp( &curve, grp_id ) ) != 0 )
-        return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE );
-
     return( 0 );
 }
 
 /*
- * subjectPublicKey  BIT STRING
- * -- which, in our case, contains
- * ECPoint ::= octet string (not ASN.1)
+ * Use EC parameters to initialise an EC group
  */
-static int x509_get_subpubkey_ec( unsigned char **p, const unsigned char *end,
-                                  const ecp_group *grp, ecp_point *pt )
+static int x509_use_ecparams( const x509_buf *params, ecp_group *grp )
 {
     int ret;
-    size_t len;
+    ecp_group_id grp_id;
 
-    if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( *p + len != end )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    if( oid_get_ec_grp( params, &grp_id ) != 0 )
+        return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE );
 
     /*
-     * First byte in the content of BIT STRING is the nummber of padding bit.
-     * Here it is always 0 since ECPoint is an octet string, so skip it.
+     * grp may already be initilialized; if so, make sure IDs match
      */
-    ++*p;
-    --len;
+    if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id )
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
 
-    if( ( ret = ecp_point_read_binary( grp, pt,
-                    (const unsigned char *) *p, len ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
+    if( ( ret = ecp_use_known_dp( grp, grp_id ) ) != 0 )
+        return( ret );
 
     return( 0 );
 }
+#endif /* POLARSSL_ECP_C */
 
 /*
  *  AttributeTypeAndValue ::= SEQUENCE {
@@ -490,6 +488,67 @@
     return( 0 );
 }
 
+#if defined(POLARSSL_RSA_C)
+/*
+ *  RSAPublicKey ::= SEQUENCE {
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER   -- e
+ *  }
+ */
+static int x509_get_rsapubkey( unsigned char **p,
+                               const unsigned char *end,
+                               rsa_context *rsa )
+{
+    int ret;
+    size_t len;
+
+    if( ( ret = asn1_get_tag( p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
+
+    if( *p + len != end )
+        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 ||
+        ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 )
+        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
+
+    if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
+        return( ret );
+
+    rsa->len = mpi_size( &rsa->N );
+
+    return( 0 );
+}
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+/*
+ * EC public key is an EC point
+ */
+static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end,
+                              ecp_keypair *key )
+{
+    int ret;
+
+    if( ( ret = ecp_point_read_binary( &key->grp, &key->Q,
+                    (const unsigned char *) *p, end - *p ) ) != 0 ||
+        ( ret = ecp_check_pubkey( &key->grp, &key->Q ) ) != 0 )
+    {
+        ecp_keypair_free( key );
+        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
+    }
+
+    /*
+     * We know ecp_point_read_binary consumed all bytes
+     */
+    *p = (unsigned char *) end;
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECP_C */
+
 /*
  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
  *       algorithm            AlgorithmIdentifier,
@@ -497,63 +556,57 @@
  */
 static int x509_get_pubkey( unsigned char **p,
                             const unsigned char *end,
-                            x509_buf *pk_alg_oid,
-                            mpi *N, mpi *E )
+                            pk_context *pk )
 {
     int ret;
     size_t len;
-    unsigned char *end2;
+    x509_buf alg_params;
     pk_type_t pk_alg = POLARSSL_PK_NONE;
 
-    if( ( ret = asn1_get_alg_null( p, end, pk_alg_oid ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
-    /*
-     * only RSA public keys handled at this time
-     */
-    if( oid_get_pk_alg( pk_alg_oid, &pk_alg ) != 0 )
+    if( ( ret = asn1_get_tag( p, end, &len,
+                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
     {
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
     }
 
-    if (pk_alg != POLARSSL_PK_RSA )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG );
+    end = *p + len;
 
-    if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
+    if( ( ret = x509_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
+        return( ret );
+
+    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
         return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
 
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    end2 = *p + len;
-
-    if( *(*p)++ != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
-
-    /*
-     *  RSAPublicKey ::= SEQUENCE {
-     *      modulus           INTEGER,  -- n
-     *      publicExponent    INTEGER   -- e
-     *  }
-     */
-    if( ( ret = asn1_get_tag( p, end2, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
-
-    if( *p + len != end2 )
+    if( *p + len != end )
         return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
 
-    if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
-        ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
+    if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 )
+        return( ret );
 
-    if( *p != end )
-        return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+#if defined(POLARSSL_RSA_C)
+    if( pk_alg == POLARSSL_PK_RSA )
+    {
+        ret = x509_get_rsapubkey( p, end, pk_rsa( *pk ) );
+    } else
+#endif /* POLARSSL_RSA_C */
+#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 ) );
+    } else
+#endif /* POLARSSL_ECP_C */
+        ret = POLARSSL_ERR_X509_UNKNOWN_PK_ALG;
 
-    return( 0 );
+    if( ret == 0 && *p != end )
+        ret = POLARSSL_ERR_X509_CERT_INVALID_PUBKEY
+              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+    if( ret != 0 )
+        pk_free( pk );
+
+    return( ret );
 }
 
 static int x509_get_sig( unsigned char **p,
@@ -569,13 +622,9 @@
 
     sig->tag = **p;
 
-    if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
+    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
         return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret );
 
-
-    if( --len < 1 || *(*p)++ != 0 )
-        return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
-
     sig->len = len;
     sig->p = *p;
 
@@ -1241,9 +1290,9 @@
      *
      * signature            AlgorithmIdentifier
      */
-    if( ( ret = x509_get_version( &p, end, &crt->version    ) ) != 0 ||
-        ( ret = x509_get_serial(  &p, end, &crt->serial     ) ) != 0 ||
-        ( ret = x509_get_alg( &p, end, &crt->sig_oid1, NULL ) ) != 0 )
+    if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
+        ( ret = x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
+        ( ret = x509_get_alg_null( &p, end, &crt->sig_oid1 ) ) != 0 )
     {
         x509_free( crt );
         return( ret );
@@ -1318,32 +1367,14 @@
     crt->subject_raw.len = p - crt->subject_raw.p;
 
     /*
-     * SubjectPublicKeyInfo  ::=  SEQUENCE
-     *      algorithm            AlgorithmIdentifier,
-     *      subjectPublicKey     BIT STRING  }
+     * SubjectPublicKeyInfo
      */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        x509_free( crt );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
-                                 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
+    if( ( ret = x509_get_pubkey( &p, end, &crt->pk ) ) != 0 )
     {
         x509_free( crt );
         return( ret );
     }
 
-    if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
-    {
-        x509_free( crt );
-        return( ret );
-    }
-
-    crt->rsa.len = mpi_size( &crt->rsa.N );
-
     /*
      *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
      *                       -- If present, version shall be v2 or v3
@@ -1392,10 +1423,13 @@
     end = crt_end;
 
     /*
+     *  }
+     *  -- end of TBSCertificate
+     *
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signatureValue       BIT STRING
      */
-    if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2, NULL ) ) != 0 )
+    if( ( ret = x509_get_alg_null( &p, end, &crt->sig_oid2 ) ) != 0 )
     {
         x509_free( crt );
         return( ret );
@@ -1718,7 +1752,7 @@
      * signature            AlgorithmIdentifier
      */
     if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
-        ( ret = x509_get_alg(  &p, end, &crl->sig_oid1, NULL ) ) != 0 )
+        ( ret = x509_get_alg_null( &p, end, &crl->sig_oid1   ) ) != 0 )
     {
         x509_crl_free( crl );
         return( ret );
@@ -1823,7 +1857,7 @@
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signatureValue       BIT STRING
      */
-    if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, NULL ) ) != 0 )
+    if( ( ret = x509_get_alg_null( &p, end, &crl->sig_oid2 ) ) != 0 )
     {
         x509_crl_free( crl );
         return( ret );
@@ -2038,50 +2072,6 @@
 }
 
 /*
- * Load and parse a private RSA key
- */
-int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    if( pwd == NULL )
-        ret = x509parse_key_rsa( rsa, buf, n, NULL, 0 );
-    else
-        ret = x509parse_key_rsa( rsa, buf, n,
-                (const unsigned char *) pwd, strlen( pwd ) );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-
-/*
- * Load and parse a public RSA key
- */
-int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    ret = x509parse_public_key_rsa( rsa, buf, n );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-
-/*
  * Load and parse a private key
  */
 int x509parse_keyfile( pk_context *ctx,
@@ -2126,8 +2116,36 @@
     return( ret );
 }
 
+#if defined(POLARSSL_RSA_C)
+/*
+ * Load and parse a private RSA key
+ */
+int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd )
+{
+    pk_context pk;
+
+    pk_init( &pk );
+    pk_wrap_rsa( &pk, rsa );
+
+    return( x509parse_keyfile( &pk, path, pwd ) );
+}
+
+/*
+ * Load and parse a public RSA key
+ */
+int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path )
+{
+    pk_context pk;
+
+    pk_init( &pk );
+    pk_wrap_rsa( &pk, rsa );
+
+    return( x509parse_public_keyfile( &pk, path ) );
+}
+#endif /* POLARSSL_RSA_C */
 #endif /* POLARSSL_FS_IO */
 
+#if defined(POLARSSL_RSA_C)
 /*
  * Parse a PKCS#1 encoded private RSA key
  */
@@ -2206,39 +2224,33 @@
 
     return( 0 );
 }
+#endif /* POLARSSL_RSA_C */
 
+#if defined(POLARSSL_ECP_C)
 /*
- * Parse an unencrypted PKCS#8 encoded private RSA key
+ * Parse a SEC1 encoded private EC key
  */
-static int x509parse_key_pkcs8_unencrypted_der(
-                                    rsa_context *rsa,
-                                    const unsigned char *key,
-                                    size_t keylen )
+static int x509parse_key_sec1_der( ecp_keypair *eck,
+                                   const unsigned char *key,
+                                   size_t keylen )
 {
     int ret;
+    int version;
     size_t len;
-    unsigned char *p, *end;
-    x509_buf pk_alg_oid;
-    pk_type_t pk_alg = POLARSSL_PK_NONE;
-
-    p = (unsigned char *) key;
-    end = p + keylen;
+    x509_buf params;
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = p + keylen;
+    unsigned char *end2;
 
     /*
-     * This function parses the PrivatKeyInfo object (PKCS#8)
+     * RFC 5915, orf SEC1 Appendix C.4
      *
-     *  PrivateKeyInfo ::= SEQUENCE {
-     *    version           Version,
-     *    algorithm       AlgorithmIdentifier,
-     *    PrivateKey      BIT STRING
-     *  }
-     *
-     *  AlgorithmIdentifier ::= SEQUENCE {
-     *    algorithm       OBJECT IDENTIFIER,
-     *    parameters      ANY DEFINED BY algorithm OPTIONAL
-     *  }
-     *
-     *  The PrivateKey BIT STRING is a PKCS#1 RSAPrivateKey
+     * ECPrivateKey ::= SEQUENCE {
+     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+     *      privateKey     OCTET STRING,
+     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+     *      publicKey  [1] BIT STRING OPTIONAL
+     *    }
      */
     if( ( ret = asn1_get_tag( &p, end, &len,
             ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
@@ -2248,56 +2260,171 @@
 
     end = p + len;
 
-    if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
 
-    if( rsa->ver != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
+    if( version != 1 )
+        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION );
 
-    if( ( ret = asn1_get_alg_null( &p, end, &pk_alg_oid ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    /*
-     * only RSA keys handled at this time
-     */
-    if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-    }
-
-    if (pk_alg != POLARSSL_PK_RSA )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG );
-
-    /*
-     * Get the OCTET STRING and parse the PKCS#1 format inside
-     */
     if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
 
-    if( ( end - p ) < 1 )
+    if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 )
     {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    /*
+     * Is 'parameters' present?
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
+    {
+        if( ( ret = x509_get_ecparams( &p, p + len, &params) ) != 0 ||
+            ( ret = x509_use_ecparams( &params, &eck->grp )  ) != 0 )
+        {
+            ecp_keypair_free( eck );
+            return( ret );
+        }
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+    }
+
+    /*
+     * Is 'publickey' present?
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
+            return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+
+        if( p + len != end2 )
+            return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        if( ( ret = x509_get_ecpubkey( &p, end2, eck ) ) != 0 )
+            return( ret );
+    }
+    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    {
+        ecp_keypair_free( eck );
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+    }
+
+    if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
+    {
+        ecp_keypair_free( eck );
+        return( ret );
+    }
+
+    return 0;
+}
+#endif /* POLARSSL_ECP_C */
+
+/*
+ * Parse an unencrypted PKCS#8 encoded private key
+ */
+static int x509parse_key_pkcs8_unencrypted_der(
+                                    pk_context *pk,
+                                    const unsigned char* key,
+                                    size_t keylen )
+{
+    int ret, version;
+    size_t len;
+    x509_buf params;
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = p + keylen;
+    pk_type_t pk_alg = POLARSSL_PK_NONE;
+
+    /*
+     * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
+     *
+     *    PrivateKeyInfo ::= SEQUENCE {
+     *      version                   Version,
+     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
+     *      privateKey                PrivateKey,
+     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
+     *
+     *    Version ::= INTEGER
+     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+     *    PrivateKey ::= OCTET STRING
+     *
+     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
+     */
+
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
     }
 
     end = p + len;
 
-    if( ( ret = x509parse_key_pkcs1_der( rsa, p, end - p ) ) != 0 )
+    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+
+    if( version != 0 )
+        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
+
+    if( ( ret = x509_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+
+    if( len < 1 )
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 )
         return( ret );
 
-    return( 0 );
+#if defined(POLARSSL_RSA_C)
+    if( pk_alg == POLARSSL_PK_RSA )
+    {
+        if( ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 )
+        {
+            pk_free( pk );
+            return( ret );
+        }
+    } else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH )
+    {
+        if( ( ret = x509_use_ecparams( &params, &pk_ec( *pk )->grp ) ) != 0 ||
+            ( ret = x509parse_key_sec1_der( pk_ec( *pk ), p, len )  ) != 0 )
+        {
+            pk_free( pk );
+            return( ret );
+        }
+    } else
+#endif /* POLARSSL_ECP_C */
+        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+
+    return 0;
 }
 
 /*
- * Decrypt the content of a PKCS#8 EncryptedPrivateKeyInfo
+ * Parse an encrypted PKCS#8 encoded private key
  */
-static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen,
-                                    size_t *used_len,
+static int x509parse_key_pkcs8_encrypted_der(
+                                    pk_context *pk,
                                     const unsigned char *key, size_t keylen,
                                     const unsigned char *pwd, size_t pwdlen )
 {
     int ret;
     size_t len;
+    unsigned char buf[2048];
     unsigned char *p, *end;
     x509_buf pbe_alg_oid, pbe_params;
 #if defined(POLARSSL_PKCS12_C)
@@ -2305,7 +2432,7 @@
     md_type_t md_alg;
 #endif
 
-    memset(buf, 0, buflen);
+    memset( buf, 0, sizeof( buf ) );
 
     p = (unsigned char *) key;
     end = p + keylen;
@@ -2341,7 +2468,7 @@
     if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
 
-    if( len > buflen )
+    if( len > sizeof( buf ) )
         return( POLARSSL_ERR_X509_INVALID_INPUT );
 
     /*
@@ -2394,37 +2521,15 @@
 #endif /* POLARSSL_PKCS5_C */
         return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
 
-    *used_len = len;
-    return( 0 );
+    return( x509parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
 }
 
 /*
- * Parse an encrypted PKCS#8 encoded private RSA key
+ * Parse a private key
  */
-static int x509parse_key_pkcs8_encrypted_der(
-                                    rsa_context *rsa,
-                                    const unsigned char *key, size_t keylen,
-                                    const unsigned char *pwd, size_t pwdlen )
-{
-    int ret;
-    unsigned char buf[2048];
-    size_t len = 0;
-
-    if( ( ret = x509parse_pkcs8_decrypt( buf, sizeof( buf ), &len,
-            key, keylen, pwd, pwdlen ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( x509parse_key_pkcs8_unencrypted_der( rsa, buf, len ) );
-}
-
-/*
- * Parse a private RSA key
- */
-int x509parse_key_rsa( rsa_context *rsa,
-                       const unsigned char *key, size_t keylen,
-                       const unsigned char *pwd, size_t pwdlen )
+int x509parse_key( pk_context *pk,
+                   const unsigned char *key, size_t keylen,
+                   const unsigned char *pwd, size_t pwdlen )
 {
     int ret;
 
@@ -2433,15 +2538,19 @@
     pem_context pem;
 
     pem_init( &pem );
+
+#if defined(POLARSSL_RSA_C)
     ret = pem_read_buffer( &pem,
                            "-----BEGIN RSA PRIVATE KEY-----",
                            "-----END RSA PRIVATE KEY-----",
                            key, pwd, pwdlen, &len );
     if( ret == 0 )
     {
-        if( ( ret = x509parse_key_pkcs1_der( rsa, pem.buf, pem.buflen ) ) != 0 )
+        if( ( ret = pk_set_type( pk, POLARSSL_PK_RSA             ) ) != 0 ||
+            ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ),
+                                             pem.buf, pem.buflen ) ) != 0 )
         {
-            rsa_free( rsa );
+            pk_free( pk );
         }
 
         pem_free( &pem );
@@ -2453,429 +2562,20 @@
         return( POLARSSL_ERR_X509_PASSWORD_REQUIRED );
     else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
         return( ret );
-
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN PRIVATE KEY-----",
-                           "-----END PRIVATE KEY-----",
-                           key, NULL, 0, &len );
-    if( ret == 0 )
-    {
-        if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa,
-                                                pem.buf, pem.buflen ) ) != 0 )
-        {
-            rsa_free( rsa );
-        }
-
-        pem_free( &pem );
-        return( ret );
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
-
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN ENCRYPTED PRIVATE KEY-----",
-                           "-----END ENCRYPTED PRIVATE KEY-----",
-                           key, NULL, 0, &len );
-    if( ret == 0 )
-    {
-        if( ( ret = x509parse_key_pkcs8_encrypted_der( rsa,
-                                                pem.buf, pem.buflen,
-                                                pwd, pwdlen ) ) != 0 )
-        {
-            rsa_free( rsa );
-        }
-
-        pem_free( &pem );
-        return( ret );
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
-#else
-    ((void) pwd);
-    ((void) pwdlen);
-#endif /* POLARSSL_PEM_C */
-
-    /*
-    * At this point we only know it's not a PEM formatted key. Could be any
-    * of the known DER encoded private key formats
-    *
-    * We try the different DER format parsers to see if one passes without
-    * error
-    */
-    if( ( ret = x509parse_key_pkcs8_encrypted_der( rsa, key, keylen,
-                                                   pwd, pwdlen ) ) == 0 )
-    {
-        return( 0 );
-    }
-
-    rsa_free( rsa );
-
-    if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH )
-    {
-        return( ret );
-    }
-
-    if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa, key, keylen ) ) == 0 )
-        return( 0 );
-
-    rsa_free( rsa );
-
-    if( ( ret = x509parse_key_pkcs1_der( rsa, key, keylen ) ) == 0 )
-        return( 0 );
-
-    rsa_free( rsa );
-
-    return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
-}
-
-/*
- * Parse a public RSA key
- */
-int x509parse_public_key_rsa( rsa_context *rsa,
-                              const unsigned char *key, size_t keylen )
-{
-    int ret;
-    size_t len;
-    unsigned char *p, *end;
-    x509_buf alg_oid;
-#if defined(POLARSSL_PEM_C)
-    pem_context pem;
-
-    pem_init( &pem );
-    ret = pem_read_buffer( &pem,
-            "-----BEGIN PUBLIC KEY-----",
-            "-----END PUBLIC KEY-----",
-            key, NULL, 0, &len );
-
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded
-         */
-        keylen = pem.buflen;
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        pem_free( &pem );
-        return( ret );
-    }
-
-    p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
-#else
-    p = (unsigned char *) key;
-#endif
-    end = p + keylen;
-
-    /*
-     *  PublicKeyInfo ::= SEQUENCE {
-     *    algorithm       AlgorithmIdentifier,
-     *    PublicKey       BIT STRING
-     *  }
-     *
-     *  AlgorithmIdentifier ::= SEQUENCE {
-     *    algorithm       OBJECT IDENTIFIER,
-     *    parameters      ANY DEFINED BY algorithm OPTIONAL
-     *  }
-     *
-     *  RSAPublicKey ::= SEQUENCE {
-     *      modulus           INTEGER,  -- n
-     *      publicExponent    INTEGER   -- e
-     *  }
-     */
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        rsa_free( rsa );
-        return( ret );
-    }
-
-    rsa->len = mpi_size( &rsa->N );
-
-#if defined(POLARSSL_PEM_C)
-    pem_free( &pem );
-#endif
-
-    return( 0 );
-}
+#endif /* POLARSSL_RSA_C */
 
 #if defined(POLARSSL_ECP_C)
-/*
- * Parse a SEC1 encoded private EC key
- */
-static int x509parse_key_sec1_der( ecp_keypair *eck,
-                                   const unsigned char *key,
-                                   size_t keylen )
-{
-    int ret;
-    int version;
-    size_t len;
-    ecp_group_id grp_id;
-    unsigned char *p = (unsigned char *) key;
-    unsigned char *end = p + keylen;
-
-    /*
-     * RFC 5915, orf SEC1 Appendix C.4
-     *
-     * ECPrivateKey ::= SEQUENCE {
-     *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
-     *      privateKey     OCTET STRING,
-     *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
-     *      publicKey  [1] BIT STRING OPTIONAL
-     *    }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( version != 1 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION );
-
-    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    p += len;
-
-    /*
-     * Is 'parameters' present?
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
-    {
-        if( ( ret = x509_get_ecparams( &p, p + len, &grp_id) ) != 0 )
-            return( ret );
-
-        /*
-         * If we're wrapped in a bigger structure (eg PKCS#8), grp may have been
-         * defined externally. In this case, make sure both definitions match.
-         */
-        if( eck->grp.id != 0 )
-        {
-            if( eck->grp.id != grp_id )
-            {
-                ecp_keypair_free( eck );
-                return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-            }
-        }
-        else
-        {
-            if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 )
-            {
-                ecp_keypair_free( eck );
-                return( ret );
-            }
-        }
-    }
-    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    /*
-     * Is 'publickey' present?
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
-    {
-        if( ( ret = x509_get_subpubkey_ec( &p, p + len, &eck->grp, &eck->Q ) )
-                != 0 )
-        {
-            ecp_keypair_free( eck );
-            return( ret );
-        }
-
-        if( ( ret = ecp_check_pubkey( &eck->grp, &eck->Q ) ) != 0 )
-        {
-            ecp_keypair_free( eck );
-            return( ret );
-        }
-    }
-    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( ret );
-    }
-
-    return 0;
-}
-
-/*
- * Parse an unencrypted PKCS#8 encoded private EC key
- */
-static int x509parse_key_pkcs8_unencrypted_der_ec(
-                                    ecp_keypair *eck,
-                                    const unsigned char* key,
-                                    size_t keylen )
-{
-    int ret, version;
-    size_t len;
-    x509_buf pk_alg_oid;
-    ecp_group_id grp_id;
-    const unsigned char *params_end;
-    unsigned char *p = (unsigned char *) key;
-    unsigned char *end = p + keylen;
-    pk_type_t pk_alg = POLARSSL_PK_NONE;
-
-    /*
-     * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
-     *
-     *    PrivateKeyInfo ::= SEQUENCE {
-     *      version                   Version,
-     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
-     *      privateKey                PrivateKey,
-     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
-     *
-     *    Version ::= INTEGER
-     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
-     *    PrivateKey ::= OCTET STRING
-     *
-     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
-     */
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( version != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
-
-    if( ( ret = x509_get_alg( &p, end, &pk_alg_oid, &params_end ) ) != 0 )
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-
-    if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    if( pk_alg != POLARSSL_PK_ECKEY && pk_alg != POLARSSL_PK_ECKEY_DH )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG );
-
-    if( pk_alg == POLARSSL_PK_ECKEY_DH )
-        eck->alg = POLARSSL_ECP_KEY_ALG_ECDH;
-
-    if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( ret );
-    }
-
-    if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( ret );
-    }
-
-    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = x509parse_key_sec1_der( eck, p, len ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( ret );
-    }
-
-    if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
-    {
-        ecp_keypair_free( eck );
-        return( ret );
-    }
-
-    return 0;
-}
-
-/*
- * Parse an encrypted PKCS#8 encoded private EC key
- */
-static int x509parse_key_pkcs8_encrypted_der_ec(
-                                    ecp_keypair *eck,
-                                    const unsigned char *key, size_t keylen,
-                                    const unsigned char *pwd, size_t pwdlen )
-{
-    int ret;
-    unsigned char buf[2048];
-    size_t len = 0;
-
-    if( ( ret = x509parse_pkcs8_decrypt( buf, sizeof( buf ), &len,
-            key, keylen, pwd, pwdlen ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( x509parse_key_pkcs8_unencrypted_der_ec( eck, buf, len ) );
-}
-
-/*
- * Parse a private EC key
- */
-static int x509parse_key_ec( ecp_keypair *eck,
-                             const unsigned char *key, size_t keylen,
-                             const unsigned char *pwd, size_t pwdlen )
-{
-    int ret;
-
-#if defined(POLARSSL_PEM_C)
-    size_t len;
-    pem_context pem;
-
-    pem_init( &pem );
     ret = pem_read_buffer( &pem,
                            "-----BEGIN EC PRIVATE KEY-----",
                            "-----END EC PRIVATE KEY-----",
                            key, pwd, pwdlen, &len );
     if( ret == 0 )
     {
-        if( ( ret = x509parse_key_sec1_der( eck, pem.buf, pem.buflen ) ) != 0 )
+        if( ( ret = pk_set_type( pk, POLARSSL_PK_ECKEY          ) ) != 0 ||
+            ( ret = x509parse_key_sec1_der( pk_ec( *pk ),
+                                            pem.buf, pem.buflen ) ) != 0 )
         {
-            ecp_keypair_free( eck );
+            pk_free( pk );
         }
 
         pem_free( &pem );
@@ -2887,6 +2587,7 @@
         return( POLARSSL_ERR_X509_PASSWORD_REQUIRED );
     else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
         return( ret );
+#endif /* POLARSSL_ECP_C */
 
     ret = pem_read_buffer( &pem,
                            "-----BEGIN PRIVATE KEY-----",
@@ -2894,10 +2595,10 @@
                            key, NULL, 0, &len );
     if( ret == 0 )
     {
-        if( ( ret = x509parse_key_pkcs8_unencrypted_der_ec( eck,
+        if( ( ret = x509parse_key_pkcs8_unencrypted_der( pk,
                                                 pem.buf, pem.buflen ) ) != 0 )
         {
-            ecp_keypair_free( eck );
+            pk_free( pk );
         }
 
         pem_free( &pem );
@@ -2912,11 +2613,11 @@
                            key, NULL, 0, &len );
     if( ret == 0 )
     {
-        if( ( ret = x509parse_key_pkcs8_encrypted_der_ec( eck,
+        if( ( ret = x509parse_key_pkcs8_encrypted_der( pk,
                                                 pem.buf, pem.buflen,
                                                 pwd, pwdlen ) ) != 0 )
         {
-            ecp_keypair_free( eck );
+            pk_free( pk );
         }
 
         pem_free( &pem );
@@ -2936,93 +2637,55 @@
     * We try the different DER format parsers to see if one passes without
     * error
     */
-    if( ( ret = x509parse_key_pkcs8_encrypted_der_ec( eck, key, keylen,
-                                                      pwd, pwdlen ) ) == 0 )
+    if( ( ret = x509parse_key_pkcs8_encrypted_der( pk, key, keylen,
+                                                   pwd, pwdlen ) ) == 0 )
     {
         return( 0 );
     }
 
-    ecp_keypair_free( eck );
+    pk_free( pk );
 
     if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH )
     {
         return( ret );
     }
 
-    if( ( ret = x509parse_key_pkcs8_unencrypted_der_ec( eck,
-                                                        key, keylen ) ) == 0 )
+    if( ( ret = x509parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
         return( 0 );
 
-    ecp_keypair_free( eck );
+    pk_free( pk );
 
-    if( ( ret = x509parse_key_sec1_der( eck, key, keylen ) ) == 0 )
+#if defined(POLARSSL_RSA_C)
+    if( ( ret = pk_set_type( pk, POLARSSL_PK_RSA                    ) ) == 0 &&
+        ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 )
+    {
         return( 0 );
+    }
 
-    ecp_keypair_free( eck );
+    pk_free( pk );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_ECP_C)
+    if( ( ret = pk_set_type( pk, POLARSSL_PK_ECKEY                ) ) == 0 &&
+        ( ret = x509parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 )
+    {
+        return( 0 );
+    }
+
+    pk_free( pk );
+#endif /* POLARSSL_ECP_C */
 
     return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
 }
 
 /*
- * Parse a public EC key in RFC 5480 format, der-encoded
+ * Parse a public key
  */
-static int x509parse_public_key_ec_der( ecp_keypair *key,
-                                        const unsigned char *buf, size_t len )
+int x509parse_public_key( pk_context *ctx,
+                          const unsigned char *key, size_t keylen )
 {
     int ret;
-    ecp_group_id grp_id;
-    x509_buf alg_oid;
-    pk_type_t alg = POLARSSL_PK_NONE;
-    unsigned char *p = (unsigned char *) buf;
-    unsigned char *end = p + len;
-    const unsigned char *params_end;
-    /*
-     * SubjectPublicKeyInfo  ::=  SEQUENCE  {
-     *   algorithm         AlgorithmIdentifier,
-     *   subjectPublicKey  BIT STRING
-     * }
-     * -- algorithm parameters are ECParameters
-     * -- subjectPublicKey is an ECPoint
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( ( ret = x509_get_alg( &p, end, &alg_oid, &params_end ) ) != 0 )
-        return( ret );
-
-    if( oid_get_pk_alg( &alg_oid, &alg ) != 0 )
-        return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
-
-    if( alg != POLARSSL_PK_ECKEY && alg != POLARSSL_PK_ECKEY_DH )
-        return( POLARSSL_ERR_X509_CERT_INVALID_ALG );
-
-    if( alg == POLARSSL_PK_ECKEY_DH )
-        key->alg = POLARSSL_ECP_KEY_ALG_ECDH;
-
-    if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 )
-        return( ret );
-
-    if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 )
-        return( ret );
-
-    if( ( ret = x509_get_subpubkey_ec( &p, end, &key->grp, &key->Q ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    return( 0 );
-}
-
-/*
- * Parse a public EC key
- */
-static int x509parse_public_key_ec( ecp_keypair *eckey,
-                                    const unsigned char *key, size_t keylen )
-{
-    int ret;
+    unsigned char *p;
 #if defined(POLARSSL_PEM_C)
     size_t len;
     pem_context pem;
@@ -3047,12 +2710,9 @@
         return( ret );
     }
 #endif
+    p = (unsigned char *) key;
 
-    if( ( ret = x509parse_public_key_ec_der ( eckey, key, keylen )  ) != 0 ||
-        ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q )          ) != 0 )
-    {
-        ecp_keypair_free( eckey );
-    }
+    ret = x509_get_pubkey( &p, p + keylen, ctx );
 
 #if defined(POLARSSL_PEM_C)
     pem_free( &pem );
@@ -3060,59 +2720,37 @@
 
     return( ret );
 }
-#endif /* defined(POLARSSL_ECP_C) */
 
+#if defined(POLARSSL_RSA_C)
 /*
- * Parse a private key
+ * Parse a private RSA key
  */
-int x509parse_key( pk_context *ctx,
-                   const unsigned char *key, size_t keylen,
-                   const unsigned char *pwd, size_t pwdlen )
+int x509parse_key_rsa( rsa_context *rsa,
+                       const unsigned char *key, size_t keylen,
+                       const unsigned char *pwd, size_t pwdlen )
 {
-    int ret;
+    pk_context pk;
 
-    if ( ( ret = pk_set_type( ctx, POLARSSL_PK_RSA ) ) != 0 )
-        return( ret );
+    pk_init( &pk );
+    pk_wrap_rsa( &pk, rsa );
 
-    if( ( ret = x509parse_key_rsa( ctx->data, key, keylen, pwd, pwdlen ) )
-            == 0 )
-    {
-        return( 0 );
-    }
-
-    if ( ( ret = pk_set_type( ctx, POLARSSL_PK_ECKEY ) ) != 0 )
-        return( ret );
-
-    if( ( ret = x509parse_key_ec( ctx->data, key, keylen, pwd, pwdlen ) ) == 0 )
-    {
-        return( 0 );
-    }
-
-    return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
+    return( x509parse_key( &pk, key, keylen, pwd, pwdlen ) );
 }
 
 /*
- * Parse a public key
+ * Parse a public RSA key
  */
-int x509parse_public_key( pk_context *ctx,
-                          const unsigned char *key, size_t keylen )
+int x509parse_public_key_rsa( rsa_context *rsa,
+                              const unsigned char *key, size_t keylen )
 {
-    int ret;
+    pk_context pk;
 
-    if ( ( ret = pk_set_type( ctx, POLARSSL_PK_RSA ) ) != 0 )
-        return( ret );
+    pk_init( &pk );
+    pk_wrap_rsa( &pk, rsa );
 
-    if( ( ret = x509parse_public_key_rsa( ctx->data, key, keylen ) ) == 0 )
-        return( 0 );
-
-    if ( ( ret = pk_set_type( ctx, POLARSSL_PK_ECKEY ) ) != 0 )
-        return( ret );
-
-    if( ( ret = x509parse_public_key_ec( ctx->data, key, keylen ) ) == 0 )
-        return( 0 );
-
-    return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
+    return( x509parse_public_key( &pk, key, keylen ) );
 }
+#endif /* POLARSSL_RSA_C */
 
 #if defined(POLARSSL_DHM_C)
 /*
@@ -3425,8 +3063,20 @@
         ret = snprintf( p, n, desc );
     SAFE_SNPRINTF();
 
-    ret = snprintf( p, n, "\n%sRSA key size  : %d bits\n", prefix,
-                   (int) crt->rsa.N.n * (int) sizeof( t_uint ) * 8 );
+#if defined(POLARSSL_RSA_C)
+    if( crt->pk.type == POLARSSL_PK_RSA )
+        ret = snprintf( p, n, "\n%sRSA key size  : %d bits\n", prefix,
+                (int) pk_rsa( crt->pk )->N.n * (int) sizeof( t_uint ) * 8 );
+    else
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+    if( crt->pk.type == POLARSSL_PK_ECKEY ||
+        crt->pk.type == POLARSSL_PK_ECKEY_DH )
+        ret = snprintf( p, n, "\n%sEC key size   : %d bits\n", prefix,
+                (int) pk_ec( crt->pk )->grp.pbits );
+    else
+#endif /* POLARSSL_ECP_C */
+        ret = snprintf(p, n, "\n%sPK type looks wrong!", prefix);
     SAFE_SNPRINTF();
 
     return( (int) ( size - n ) );
@@ -3678,7 +3328,11 @@
 
         md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
 
-        if( !rsa_pkcs1_verify( &ca->rsa, RSA_PUBLIC, crl_list->sig_md,
+        /* EC NOT IMPLEMENTED YET */
+        if( ca->pk.type != POLARSSL_PK_RSA )
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+
+        if( !rsa_pkcs1_verify( pk_rsa( ca->pk ), RSA_PUBLIC, crl_list->sig_md,
                               0, hash, crl_list->sig.p ) == 0 )
         {
             /*
@@ -3796,7 +3450,11 @@
 
         md( md_info, child->tbs.p, child->tbs.len, hash );
 
-        if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, child->sig_md,
+        /* EC NOT IMPLEMENTED YET */
+        if( trust_ca->pk.type != POLARSSL_PK_RSA )
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+
+        if( rsa_pkcs1_verify( pk_rsa( trust_ca->pk ), RSA_PUBLIC, child->sig_md,
                     0, hash, child->sig.p ) != 0 )
         {
             trust_ca = trust_ca->next;
@@ -3872,9 +3530,15 @@
     {
         md( md_info, child->tbs.p, child->tbs.len, hash );
 
-        if( rsa_pkcs1_verify( &parent->rsa, RSA_PUBLIC, child->sig_md, 0, hash,
-                               child->sig.p ) != 0 )
+        /* EC NOT IMPLEMENTED YET */
+        if( parent->pk.type != POLARSSL_PK_RSA )
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+
+        if( rsa_pkcs1_verify( pk_rsa( parent->pk ), RSA_PUBLIC, child->sig_md,
+                              0, hash, child->sig.p ) != 0 )
+        {
             *flags |= BADCERT_NOT_TRUSTED;
+        }
     }
 
     /* Check trusted CA's CRL for the given crt */
@@ -4049,7 +3713,7 @@
 
     do
     {
-        rsa_free( &cert_cur->rsa );
+        pk_free( &cert_cur->pk );
 
         name_cur = cert_cur->issuer.next;
         while( name_cur != NULL )
diff --git a/programs/test/ssl_cert_test.c b/programs/test/ssl_cert_test.c
index bf4684b..ec824c9 100644
--- a/programs/test/ssl_cert_test.c
+++ b/programs/test/ssl_cert_test.c
@@ -206,19 +206,28 @@
         printf( " ok\n" );
 
         /*
-         * 1.5. Verify certificate validity with private key
+         * 1.6. Verify certificate validity with private key
          */
         printf( "  . Verify the client certificate with private key..." );
         fflush( stdout );
 
-        ret = mpi_cmp_mpi(&rsa.N, &clicert.rsa.N);
+
+        /* EC NOT IMPLEMENTED YET */
+        if( clicert.pk.type != POLARSSL_PK_RSA )
+        {
+            printf( " failed\n  !  certificate's key is not RSA\n\n" );
+            ret = POLARSSL_ERR_X509_FEATURE_UNAVAILABLE;
+            goto exit;
+        }
+
+        ret = mpi_cmp_mpi(&rsa.N, &pk_rsa( clicert.pk )->N);
         if( ret != 0 )
         {
             printf( " failed\n  !  mpi_cmp_mpi for N returned %d\n\n", ret );
             goto exit;
         }
 
-        ret = mpi_cmp_mpi(&rsa.E, &clicert.rsa.E);
+        ret = mpi_cmp_mpi(&rsa.E, &pk_rsa( clicert.pk )->E);
         if( ret != 0 )
         {
             printf( " failed\n  !  mpi_cmp_mpi for E returned %d\n\n", ret );
diff --git a/tests/data_files/test-ca2.crt b/tests/data_files/test-ca2.crt
new file mode 100644
index 0000000..c47c496
--- /dev/null
+++ b/tests/data_files/test-ca2.crt
Binary files differ
diff --git a/tests/data_files/test-ca2.key b/tests/data_files/test-ca2.key
new file mode 100644
index 0000000..2725398
--- /dev/null
+++ b/tests/data_files/test-ca2.key
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBAQ==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MF8CAQEEGKHCq9vcqkdzGdKSIUP2M9o/vu1rja5jxqAKBggqhkjOPQMBAaE0AzIA
+BCE3lp+r1ONwYkoOGjPjecq5UMzgDvjDw+KtrrcnHI8HZZ1l09d33PIWFDY65Lbm
+Fw==
+-----END EC PRIVATE KEY-----
diff --git a/tests/suites/test_suite_debug.data b/tests/suites/test_suite_debug.data
index 824db64..7a309ce 100644
--- a/tests/suites/test_suite_debug.data
+++ b/tests/suites/test_suite_debug.data
@@ -1,7 +1,11 @@
-Debug print certificate #1
+Debug print certificate #1 (RSA)
 depends_on:POLARSSL_FS_IO:POLARSSL_PEM_C:POLARSSL_BASE64_C
 debug_print_crt:"data_files/server1.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version \: 3\nMyFile(0999)\: serial number \: 01\nMyFile(0999)\: issuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nMyFile(0999)\: subject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nMyFile(0999)\: issued  on    \: 2011-02-12 14\:44\:06\nMyFile(0999)\: expires on    \: 2021-02-12 14\:44\:06\nMyFile(0999)\: signed using  \: RSA with SHA1\nMyFile(0999)\: RSA key size  \: 2048 bits\nMyFile(0999)\: value of 'crt->rsa.N' (2048 bits) is\:\nMyFile(0999)\:  a9 02 1f 3d 40 6a d5 55 53 8b fd 36 ee 82 65 2e\nMyFile(0999)\:  15 61 5e 89 bf b8 e8 45 90 db ee 88 16 52 d3 f1\nMyFile(0999)\:  43 50 47 96 12 59 64 87 6b fd 2b e0 46 f9 73 be\nMyFile(0999)\:  dd cf 92 e1 91 5b ed 66 a0 6f 89 29 79 45 80 d0\nMyFile(0999)\:  83 6a d5 41 43 77 5f 39 7c 09 04 47 82 b0 57 39\nMyFile(0999)\:  70 ed a3 ec 15 19 1e a8 33 08 47 c1 05 42 a9 fd\nMyFile(0999)\:  4c c3 b4 df dd 06 1f 4d 10 51 40 67 73 13 0f 40\nMyFile(0999)\:  f8 6d 81 25 5f 0a b1 53 c6 30 7e 15 39 ac f9 5a\nMyFile(0999)\:  ee 7f 92 9e a6 05 5b e7 13 97 85 b5 23 92 d9 d4\nMyFile(0999)\:  24 06 d5 09 25 89 75 07 dd a6 1a 8f 3f 09 19 be\nMyFile(0999)\:  ad 65 2c 64 eb 95 9b dc fe 41 5e 17 a6 da 6c 5b\nMyFile(0999)\:  69 cc 02 ba 14 2c 16 24 9c 4a dc cd d0 f7 52 67\nMyFile(0999)\:  73 f1 2d a0 23 fd 7e f4 31 ca 2d 70 ca 89 0b 04\nMyFile(0999)\:  db 2e a6 4f 70 6e 9e ce bd 58 89 e2 53 59 9e 6e\nMyFile(0999)\:  5a 92 65 e2 88 3f 0c 94 19 a3 dd e5 e8 9d 95 13\nMyFile(0999)\:  ed 29 db ab 70 12 dc 5a ca 6b 17 ab 52 82 54 b1\nMyFile(0999)\: value of 'crt->rsa.E' (17 bits) is\:\nMyFile(0999)\:  01 00 01\n"
 
+Debug print certificate #2 (EC)
+depends_on:POLARSSL_FS_IO:POLARSSL_PEM_C:POLARSSL_BASE64_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+debug_print_crt:"data_files/test-ca2.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version \: 1\nMyFile(0999)\: serial number \: F4\:15\:34\:66\:2E\:C7\:E9\:12\nMyFile(0999)\: issuer name   \: CN=Test\nMyFile(0999)\: subject name  \: CN=Test\nMyFile(0999)\: issued  on    \: 2013-07-10 09\:40\:19\nMyFile(0999)\: expires on    \: 2023-07-08 09\:40\:19\nMyFile(0999)\: signed using  \: ECDSA with SHA1\nMyFile(0999)\: EC key size   \: 192 bits\nMyFile(0999)\: value of 'crt->eckey.Q(X)' (190 bits) is\:\nMyFile(0999)\:  21 37 96 9f ab d4 e3 70 62 4a 0e 1a 33 e3 79 ca\nMyFile(0999)\:  b9 50 cc e0 0e f8 c3 c3\nMyFile(0999)\: value of 'crt->eckey.Q(Y)' (192 bits) is\:\nMyFile(0999)\:  e2 ad ae b7 27 1c 8f 07 65 9d 65 d3 d7 77 dc f2\nMyFile(0999)\:  16 14 36 3a e4 b6 e6 17\nMyFile(0999)\: value of 'crt->eckey.Q(Z)' (1 bits) is\:\nMyFile(0999)\:  01\n"
+
 Debug print mpi #1
 debug_print_mpi:16:"01020304050607":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (49 bits) is\:\nMyFile(0999)\:  01 02 03 04 05 06 07\n"
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index def0021..bf13719 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -187,39 +187,39 @@
 x509parse_public_keyfile_rsa:"data_files/format_gen.pub":0
 
 X509 Parse Public EC Key #1 (RFC 5480, DER)
-depends_on:POLARSSL_ECP_C:POLARSSL_FS_IO
+depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_FS_IO
 x509parse_public_keyfile_ec:"data_files/ec_pub.der":0
 
 X509 Parse Public EC Key #2 (RFC 5480, PEM)
-depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_FS_IO
+depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED:POLARSSL_FS_IO
 x509parse_public_keyfile_ec:"data_files/ec_pub.pem":0
 
 X509 Parse EC Key #1 (SEC1 DER)
-depends_on:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.sec1.der":NULL:0
 
 X509 Parse EC Key #2 (SEC1 PEM)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.sec1.pem":NULL:0
 
 X509 Parse EC Key #3 (SEC1 PEM encrypted)
-depends_on:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.sec1.pw.pem":"polar":0
 
 X509 Parse EC Key #4 (PKCS8 DER)
-depends_on:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.pk8.der":NULL:0
 
 X509 Parse EC Key #5 (PKCS8 PEM)
-depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.pk8.pem":NULL:0
 
 X509 Parse EC Key #6 (PKCS8 encrypted DER)
-depends_on:POLARSSL_DES_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_DES_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.pk8.pw.der":"polar":0
 
 X509 Parse EC Key #7 (PKCS8 encrypted PEM)
-depends_on:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C
+depends_on:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
 x509parse_keyfile_ec:"data_files/ec_prv.pk8.pw.pem":"polar":0
 
 X509 Get Distinguished Name #1
@@ -511,7 +511,7 @@
 x509parse_crt:"30563054a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, no alg)
-x509parse_crt:"30583056a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"30583056a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743000":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, valid subject, unknown pk alg)
 x509parse_crt:"30673065a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374300f300d06092A864886F70D0101000500":"":POLARSSL_ERR_X509_UNKNOWN_PK_ALG
@@ -523,7 +523,7 @@
 x509parse_crt:"30693067a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743011300d06092A864886F70D01010105000300":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid bitstring start)
-x509parse_crt:"306a3068a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743012300d06092A864886F70D0101010500030101":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY
+x509parse_crt:"306a3068a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743012300d06092A864886F70D0101010500030101":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (TBSCertificate, pubkey, invalid internal bitstring length)
 x509parse_crt:"306d306ba0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400300000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
@@ -595,7 +595,7 @@
 x509parse_crt:"308192308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_OUT_OF_DATA
 
 X509 Certificate ASN1 (signature, invalid sig data)
-x509parse_crt:"308195308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030100":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE
+x509parse_crt:"308195308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030100":"":POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + POLARSSL_ERR_ASN1_INVALID_DATA
 
 X509 Certificate ASN1 (signature, data left)
 x509parse_crt:"308197308180a0030201008204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff00":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH
@@ -633,6 +633,17 @@
 X509 Certificate ASN1 (Name with unknown PKCS9 part)
 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)
+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)
+depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+x509parse_crt:"3081EB3081A3020900F41534662EC7E912300906072A8648CE3D0401300F310D300B0603550403130454657374301E170D3133303731303039343031395A170D3233303730383039343031395A300F310D300B06035504031304546573743049301306072A8648CE3D020106082A8648CE3D030101033200042137969FABD4E370624A0E1A33E379CAB950CCE00EF8C3C3E2ADAEB7271C8F07659D65D3D777DCF21614363AE4B6E617300906072A8648CE3D04010338003035021858CC0F957946FE6A303D92885A456AA74C743C7B708CBD37021900FE293CAC21AF352D16B82EB8EA54E9410B3ABAADD9F05DD6":"cert. version \: 1\nserial number \: F4\:15\:34\:66\:2E\:C7\:E9\:12\nissuer name   \: CN=Test\nsubject name  \: CN=Test\nissued  on    \: 2013-07-10 09\:40\:19\nexpires on    \: 2023-07-08 09\:40\:19\nsigned using  \: ECDSA with SHA1\nEC key size   \: 192 bits\n":0
+
+X509 Certificate ASN1 (RSA signature, EC key)
+depends_on:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP192R1_ENABLED
+x509parse_crt:"3081E430819F020104300D06092A864886F70D0101050500300F310D300B0603550403130454657374301E170D3133303731303135303233375A170D3233303730383135303233375A300F310D300B06035504031304546573743049301306072A8648CE3D020106082A8648CE3D03010103320004E962551A325B21B50CF6B990E33D4318FD16677130726357A196E3EFE7107BCB6BDC6D9DB2A4DF7C964ACFE81798433D300D06092A864886F70D01010505000331001A6C18CD1E457474B2D3912743F44B571341A7859A0122774A8E19A671680878936949F904C9255BDD6FFFDB33A7E6D8":"cert. version \: 1\nserial number \: 04\nissuer name   \: CN=Test\nsubject name  \: CN=Test\nissued  on    \: 2013-07-10 15\:02\:37\nexpires on    \: 2023-07-08 15\:02\:37\nsigned using  \: RSA with SHA1\nEC key size   \: 192 bits\n":0
+
 X509 CRL ASN1 (Incorrect first tag)
 x509parse_crl:"":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT