From 0a64e8f1fd82bbd32647e2f5cb9ddd93408a4d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 8 Jul 2013 18:26:18 +0200 Subject: [PATCH 01/33] Rework algorithmIdentifier parsing --- library/x509parse.c | 76 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index c5f9049df..12f06ca20 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -160,6 +160,40 @@ static int x509_get_serial( unsigned char **p, return( 0 ); } +/* Get an algorithm identifier and its parameters + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int x509_get_algid( unsigned char **p, + const unsigned char *end, + pk_type_t *pk_alg, x509_buf *params ) +{ + int ret; + x509_buf alg_oid; + + memset( params, 0, sizeof(asn1_buf) ); + + if( ( ret = asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); + + 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 ); + } + + return( 0 ); +} + /* * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, @@ -201,6 +235,23 @@ static int x509_get_alg( unsigned char **p, return( 0 ); } +/* Get an EC group id from an ECParameters buffer + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * -- implicitCurve NULL + * -- specifiedCurve SpecifiedECDomain + * } + */ +static int x509_ecparams_get_grp_id( const x509_buf *params, + ecp_group_id *grp_id ) +{ + if( oid_get_ec_grp( params, grp_id ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE ); + + return( 0 ); +} + /* Get an EC group id from an ECParameters buffer * * ECParameters ::= CHOICE { @@ -227,10 +278,7 @@ static int x509_get_ecparams( unsigned char **p, const unsigned char *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 ); + return( x509_ecparams_get_grp_id( &curve, grp_id ) ); } /* @@ -2750,9 +2798,8 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( { int ret, version; size_t len; - x509_buf pk_alg_oid; + x509_buf alg_params; 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; @@ -2787,19 +2834,16 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( if( version != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); - if( ( ret = x509_get_alg( &p, end, &pk_alg_oid, ¶ms_end ) ) != 0 ) + if( ( ret = x509_get_algid( &p, end, &pk_alg, &alg_params ) ) != 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 ) + if( ( ret = x509_ecparams_get_grp_id( &alg_params, &grp_id ) ) != 0 ) { ecp_keypair_free( eck ); return( ret ); @@ -2971,11 +3015,10 @@ static int x509parse_public_key_ec_der( ecp_keypair *key, { int ret; ecp_group_id grp_id; - x509_buf alg_oid; + x509_buf alg_params; 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, @@ -2990,19 +3033,16 @@ static int x509parse_public_key_ec_der( ecp_keypair *key, return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); } - if( ( ret = x509_get_alg( &p, end, &alg_oid, ¶ms_end ) ) != 0 ) + if( ( ret = x509_get_algid( &p, end, &alg, &alg_params ) ) != 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 ) + if( ( ret = x509_ecparams_get_grp_id( &alg_params, &grp_id ) ) != 0 ) return( ret ); if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) From 374e4b87d43c81ca0c869445bd43454376cc6478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 10:21:34 +0200 Subject: [PATCH 02/33] pk_set_type() cannot be used to reset key type --- include/polarssl/pk.h | 8 +++++++- library/error.c | 2 ++ library/pk.c | 8 +++++++- library/x509parse.c | 8 ++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 00f8cfcb1..707f138d4 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -28,6 +28,7 @@ #define POLARSSL_PK_H #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 */ #ifdef __cplusplus extern "C" { @@ -72,7 +73,12 @@ void pk_free( pk_context *ctx ); * \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 ); diff --git a/library/error.c b/library/error.c index 0a739b5d5..560c54cff 100644 --- a/library/error.c +++ b/library/error.c @@ -250,6 +250,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) #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/pk.c b/library/pk.c index 71505ed2e..0591b3f1c 100644 --- a/library/pk.c +++ b/library/pk.c @@ -88,6 +88,12 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) { size_t size = 0; + if( ctx->type == type ) + return( 0 ); + + if( ctx->type != POLARSSL_PK_NONE ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + switch( type ) { #if defined(POLARSSL_RSA_C) @@ -104,7 +110,7 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) #endif case POLARSSL_PK_NONE: - ; /* Should not happen */ + ; /* Cannot happen, but the cmpiler doesn't know */ } if( ( ctx->data = malloc( size ) ) == NULL ) diff --git a/library/x509parse.c b/library/x509parse.c index 12f06ca20..c801967b1 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -3120,6 +3120,8 @@ int x509parse_key( pk_context *ctx, return( 0 ); } + pk_free( ctx ); + if ( ( ret = pk_set_type( ctx, POLARSSL_PK_ECKEY ) ) != 0 ) return( ret ); @@ -3128,6 +3130,8 @@ int x509parse_key( pk_context *ctx, return( 0 ); } + pk_free( ctx ); + return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); } @@ -3145,12 +3149,16 @@ int x509parse_public_key( pk_context *ctx, if( ( ret = x509parse_public_key_rsa( ctx->data, key, keylen ) ) == 0 ) return( 0 ); + pk_free( ctx ); + 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 ); + pk_free( ctx ); + return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); } From 788db112a5b85d9cdbf5c30323482a26bd52b3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 11:26:17 +0200 Subject: [PATCH 03/33] Get rid of x509_cert.pkoid Unused, comment did not match reality, and will soon be superseeded by the 'type' field of the pk_context which will replace rsa_context. --- include/polarssl/x509.h | 1 - library/x509parse.c | 11 +++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index f0c0e7aac..61c784641 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -211,7 +211,6 @@ typedef struct _x509_cert 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. */ x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ diff --git a/library/x509parse.c b/library/x509parse.c index c801967b1..813158d8c 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -545,21 +545,21 @@ static int x509_get_dates( unsigned char **p, */ static int x509_get_pubkey( unsigned char **p, const unsigned char *end, - x509_buf *pk_alg_oid, mpi *N, mpi *E ) { int ret; size_t len; + x509_buf pk_alg_oid; unsigned char *end2; pk_type_t pk_alg = POLARSSL_PK_NONE; - if( ( ret = asn1_get_alg_null( p, end, pk_alg_oid ) ) != 0 ) + 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( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 ) { return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); } @@ -1377,7 +1377,7 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); } - if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid, + if( ( ret = x509_get_pubkey( &p, p + len, &crt->rsa.N, &crt->rsa.E ) ) != 0 ) { x509_free( crt ); @@ -2585,7 +2585,6 @@ int x509parse_public_key_rsa( rsa_context *rsa, int ret; size_t len; unsigned char *p, *end; - x509_buf alg_oid; #if defined(POLARSSL_PEM_C) pem_context pem; @@ -2641,7 +2640,7 @@ int x509parse_public_key_rsa( rsa_context *rsa, return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); } - if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 ) + if( ( ret = x509_get_pubkey( &p, end, &rsa->N, &rsa->E ) ) != 0 ) { #if defined(POLARSSL_PEM_C) pem_free( &pem ); From 20c12f6b5fe4ce73abcf001785056a085f746577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 12:13:24 +0200 Subject: [PATCH 04/33] Factor more code into x509_get_pubkey() --- library/x509parse.c | 85 ++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 62 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 813158d8c..a284fd122 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -545,7 +545,7 @@ static int x509_get_dates( unsigned char **p, */ static int x509_get_pubkey( unsigned char **p, const unsigned char *end, - mpi *N, mpi *E ) + rsa_context *rsa ) { int ret; size_t len; @@ -553,6 +553,14 @@ static int x509_get_pubkey( unsigned char **p, unsigned char *end2; pk_type_t pk_alg = POLARSSL_PK_NONE; + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); + } + + end = *p + len; + if( ( ret = asn1_get_alg_null( p, end, &pk_alg_oid ) ) != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); @@ -593,14 +601,19 @@ static int x509_get_pubkey( unsigned char **p, 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 ) + if( ( ret = asn1_get_mpi( p, end2, &rsa->N ) ) != 0 || + ( ret = asn1_get_mpi( p, end2, &rsa->E ) ) != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); if( *p != end ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + if( ( ret = rsa_check_pubkey( rsa ) ) != 0 ) + return( ret ); + + rsa->len = mpi_size( &rsa->N ); + return( 0 ); } @@ -1366,32 +1379,15 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, 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->rsa.N, &crt->rsa.E ) ) != 0 ) + if( ( ret = x509_get_pubkey( &p, end, + &crt->rsa ) ) != 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 @@ -1440,6 +1436,9 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, end = crt_end; /* + * } + * -- end of TBSCertificate + * * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ @@ -2613,43 +2612,7 @@ int x509parse_public_key_rsa( rsa_context *rsa, #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, &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( ( ret = x509_get_pubkey( &p, end, rsa ) ) != 0 ) { #if defined(POLARSSL_PEM_C) pem_free( &pem ); @@ -2658,8 +2621,6 @@ int x509parse_public_key_rsa( rsa_context *rsa, return( ret ); } - rsa->len = mpi_size( &rsa->N ); - #if defined(POLARSSL_PEM_C) pem_free( &pem ); #endif From f16ac763f631fed2627ad501cf30540e950a154d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 12:26:00 +0200 Subject: [PATCH 05/33] Simplify length mismatch check in x509_get_pubkey --- library/x509parse.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index a284fd122..72cdf8dbc 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -550,7 +550,6 @@ static int x509_get_pubkey( unsigned char **p, int ret; size_t len; x509_buf pk_alg_oid; - unsigned char *end2; pk_type_t pk_alg = POLARSSL_PK_NONE; if( ( ret = asn1_get_tag( p, end, &len, @@ -582,7 +581,9 @@ static int x509_get_pubkey( unsigned char **p, return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_OUT_OF_DATA ); - end2 = *p + len; + if( *p + len != end ) + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( *(*p)++ != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); @@ -593,22 +594,18 @@ static int x509_get_pubkey( unsigned char **p, * publicExponent INTEGER -- e * } */ - if( ( ret = asn1_get_tag( p, end2, &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 != end2 ) + if( *p + len != end ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - if( ( ret = asn1_get_mpi( p, end2, &rsa->N ) ) != 0 || - ( ret = asn1_get_mpi( p, end2, &rsa->E ) ) != 0 ) + 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( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - if( ( ret = rsa_check_pubkey( rsa ) ) != 0 ) return( ret ); From 094ad9e51288c8c334dc33dc4efc3e4840cd502d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 12:32:51 +0200 Subject: [PATCH 06/33] Rename x509_get_pubkey to _rsa and split it up --- library/x509parse.c | 69 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 72cdf8dbc..e3c363a39 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -538,14 +538,47 @@ static int x509_get_dates( unsigned char **p, return( 0 ); } +/* + * 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 ); +} + /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ -static int x509_get_pubkey( unsigned char **p, - const unsigned char *end, - rsa_context *rsa ) +static int x509_get_pubkey_rsa( unsigned char **p, + const unsigned char *end, + rsa_context *rsa ) { int ret; size_t len; @@ -588,30 +621,7 @@ static int x509_get_pubkey( unsigned char **p, if( *(*p)++ != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - /* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ - 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 ); + return( x509_get_rsapubkey( p, end, rsa ) ); } static int x509_get_sig( unsigned char **p, @@ -1378,8 +1388,7 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, /* * SubjectPublicKeyInfo */ - if( ( ret = x509_get_pubkey( &p, end, - &crt->rsa ) ) != 0 ) + if( ( ret = x509_get_pubkey_rsa( &p, end, &crt->rsa ) ) != 0 ) { x509_free( crt ); return( ret ); @@ -2609,7 +2618,7 @@ int x509parse_public_key_rsa( rsa_context *rsa, #endif end = p + keylen; - if( ( ret = x509_get_pubkey( &p, end, rsa ) ) != 0 ) + if( ( ret = x509_get_pubkey_rsa( &p, end, rsa ) ) != 0 ) { #if defined(POLARSSL_PEM_C) pem_free( &pem ); From c296c5925e006fa4245dc498d9f969b9af985204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 12:54:04 +0200 Subject: [PATCH 07/33] Introduce generic x509_get_pubkey() --- library/x509parse.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/library/x509parse.c b/library/x509parse.c index e3c363a39..6f2091955 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -571,6 +571,84 @@ static int x509_get_rsapubkey( unsigned char **p, return( 0 ); } +static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, + x509_buf *alg_params, ecp_keypair *key ) +{ + int ret; + ecp_group_id grp_id; + + if( ( ret = x509_ecparams_get_grp_id( alg_params, &grp_id ) ) != 0 ) + return( ret ); + + if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) != 0 ) + { + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +static int x509_get_pubkey( unsigned char **p, + const unsigned char *end, + pk_context *pk ) +{ + int ret; + size_t len; + x509_buf alg_params; + pk_type_t pk_alg = POLARSSL_PK_NONE; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = x509_get_algid( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 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 ); + + if( *p + len != end ) + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( *(*p)++ != 0 ) + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); + + pk_set_type( pk, pk_alg ); + + switch( pk_alg ) + { + case POLARSSL_PK_NONE: + return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + + case POLARSSL_PK_RSA: + return( x509_get_rsapubkey( p, end, pk->data ) ); + + case POLARSSL_PK_ECKEY_DH: + ((ecp_keypair *) pk->data)->alg = POLARSSL_ECP_KEY_ALG_ECDH; + /* FALLTHROUGH */ + case POLARSSL_PK_ECKEY: + return( x509_get_ecpubkey( p, end, &alg_params, pk->data ) ); + } +} + /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, From 4fa047667571a8fde7ddd23d46b04fb11db0e87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 13:10:49 +0200 Subject: [PATCH 08/33] Use new x509_get_pubkey() in x509parse_public_key() --- library/x509parse.c | 156 +++++++++++++------------------------------- 1 file changed, 44 insertions(+), 112 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 6f2091955..605e40c42 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -586,7 +586,7 @@ static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, (const unsigned char *) *p, end - *p ) ) != 0 ) { - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); } return( 0 ); @@ -631,22 +631,32 @@ static int x509_get_pubkey( unsigned char **p, if( *(*p)++ != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - pk_set_type( pk, pk_alg ); + if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 ) + return( ret ); switch( pk_alg ) { case POLARSSL_PK_NONE: - return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + ret = POLARSSL_ERR_X509_UNKNOWN_PK_ALG; + break; case POLARSSL_PK_RSA: - return( x509_get_rsapubkey( p, end, pk->data ) ); + ret = x509_get_rsapubkey( p, end, pk->data ); + break; case POLARSSL_PK_ECKEY_DH: ((ecp_keypair *) pk->data)->alg = POLARSSL_ECP_KEY_ALG_ECDH; /* FALLTHROUGH */ + case POLARSSL_PK_ECKEY: - return( x509_get_ecpubkey( p, end, &alg_params, pk->data ) ); + ret = x509_get_ecpubkey( p, end, &alg_params, pk->data ); + break; } + + if( ret != 0 ) + pk_free( pk ); + + return( ret ); } /* @@ -3050,100 +3060,6 @@ static int x509parse_key_ec( ecp_keypair *eck, return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); } - -/* - * Parse a public EC key in RFC 5480 format, der-encoded - */ -static int x509parse_public_key_ec_der( ecp_keypair *key, - const unsigned char *buf, size_t len ) -{ - int ret; - ecp_group_id grp_id; - x509_buf alg_params; - pk_type_t alg = POLARSSL_PK_NONE; - unsigned char *p = (unsigned char *) buf; - unsigned char *end = p + len; - /* - * 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_algid( &p, end, &alg, &alg_params ) ) != 0 ) - return( ret ); - - 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_ecparams_get_grp_id( &alg_params, &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; -#if defined(POLARSSL_PEM_C) - size_t len; - 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 - */ - key = pem.buf; - keylen = pem.buflen; - } - else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - pem_free( &pem ); - return( ret ); - } -#endif - - if( ( ret = x509parse_public_key_ec_der ( eckey, key, keylen ) ) != 0 || - ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 ) - { - ecp_keypair_free( eckey ); - } - -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - - return( ret ); -} #endif /* defined(POLARSSL_ECP_C) */ /* @@ -3186,24 +3102,40 @@ int x509parse_public_key( pk_context *ctx, const unsigned char *key, size_t keylen ) { int ret; + unsigned char *p; +#if defined(POLARSSL_PEM_C) + size_t len; + pem_context pem; - if ( ( ret = pk_set_type( ctx, POLARSSL_PK_RSA ) ) != 0 ) + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + key = pem.buf; + keylen = pem.buflen; + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); return( ret ); + } +#endif + p = (unsigned char *) key; - if( ( ret = x509parse_public_key_rsa( ctx->data, key, keylen ) ) == 0 ) - return( 0 ); + ret = x509_get_pubkey( &p, p + keylen, ctx ); - pk_free( ctx ); +#if defined(POLARSSL_PEM_C) + pem_free( &pem ); +#endif - 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 ); - - pk_free( ctx ); - - return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); + return( ret ); } #if defined(POLARSSL_DHM_C) From 244569f4b1575d6922d44d84c8e91ebe47106d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 09:46:30 +0200 Subject: [PATCH 09/33] Use generic x509_get_pubkey() for RSA functions --- include/polarssl/pk.h | 26 ++++++- library/pk.c | 21 +++++- library/x509parse.c | 95 +++----------------------- tests/suites/test_suite_x509parse.data | 2 +- 4 files changed, 54 insertions(+), 90 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 707f138d4..4e52a75d2 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -27,6 +27,12 @@ #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 */ @@ -53,8 +59,9 @@ typedef enum { */ 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; /** @@ -82,6 +89,21 @@ void pk_free( pk_context *ctx ); */ 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 + #ifdef __cplusplus } #endif diff --git a/library/pk.c b/library/pk.c index 0591b3f1c..6762c75bb 100644 --- a/library/pk.c +++ b/library/pk.c @@ -46,6 +46,7 @@ void pk_init( pk_context *ctx ) ctx->type = POLARSSL_PK_NONE; ctx->data = NULL; + ctx->dont_free = 0; } /* @@ -75,7 +76,8 @@ void pk_free( pk_context *ctx ) #endif } - free( ctx-> data ); + if( ! ctx->dont_free ) + free( ctx->data ); ctx->type = POLARSSL_PK_NONE; ctx->data = NULL; @@ -121,3 +123,20 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) 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/x509parse.c b/library/x509parse.c index 605e40c42..9e05f98cb 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -660,56 +660,18 @@ static int x509_get_pubkey( unsigned char **p, } /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } + * Get an RSA public key (compatibility wrapper) */ static int x509_get_pubkey_rsa( unsigned char **p, const unsigned char *end, rsa_context *rsa ) { - int ret; - size_t len; - x509_buf pk_alg_oid; - pk_type_t pk_alg = POLARSSL_PK_NONE; + pk_context pk_ctx; - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); - } + pk_init( &pk_ctx ); + pk_wrap_rsa( &pk_ctx, rsa ); - end = *p + len; - - 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 ) - { - return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); - } - - if (pk_alg != POLARSSL_PK_RSA ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG ); - - if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 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 ); - - if( *p + len != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - - if( *(*p)++ != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - - return( x509_get_rsapubkey( p, end, rsa ) ); + return( x509_get_pubkey( p, end, &pk_ctx ) ); } static int x509_get_sig( unsigned char **p, @@ -2675,51 +2637,12 @@ int x509parse_key_rsa( rsa_context *rsa, int x509parse_public_key_rsa( rsa_context *rsa, const unsigned char *key, size_t keylen ) { - int ret; - size_t len; - unsigned char *p, *end; -#if defined(POLARSSL_PEM_C) - pem_context pem; + pk_context pk_ctx; - pem_init( &pem ); - ret = pem_read_buffer( &pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", - key, NULL, 0, &len ); + pk_init( &pk_ctx ); + pk_wrap_rsa( &pk_ctx, rsa ); - 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; - - if( ( ret = x509_get_pubkey_rsa( &p, end, rsa ) ) != 0 ) - { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - rsa_free( rsa ); - return( ret ); - } - -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif - - return( 0 ); + return( x509parse_public_key( &pk_ctx, key, keylen ) ); } #if defined(POLARSSL_ECP_C) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index def0021d4..0f95e1027 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -511,7 +511,7 @@ X509 Certificate ASN1 (TBSCertificate, valid subject, no pubkeyinfo) 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 From 1e60cd09b084add46037e24af6ab6b5b9c7de180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 10:28:53 +0200 Subject: [PATCH 10/33] Expand oid_get_sig_alg() for ECDSA-based algs --- include/polarssl/oid.h | 30 ++++++++++++++++++++++++++++++ include/polarssl/pk.h | 3 +++ library/oid.c | 20 ++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index a39055b06..0c3dab216 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 4e52a75d2..29aec309f 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -52,6 +52,9 @@ typedef enum { POLARSSL_PK_ECKEY, POLARSSL_PK_ECKEY_DH, #endif +#if defined(POLARSSL_ECDSA_C) + POLARSSL_PK_ECDSA, +#endif } pk_type_t; /** diff --git a/library/oid.c b/library/oid.c index 449b3e1f0..366720ec0 100644 --- a/library/oid.c +++ b/library/oid.c @@ -298,6 +298,26 @@ static const oid_sig_alg_t oid_sig_alg[] = { OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1" }, 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, From 2692a30c1b510ecb815d683b5ab0a4bf9e6b5ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 10:30:15 +0200 Subject: [PATCH 11/33] Relax ifdef's in pk.h by analogy with md.h --- include/polarssl/pk.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 29aec309f..7a54c7142 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -45,16 +45,10 @@ extern "C" { */ 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 -#if defined(POLARSSL_ECDSA_C) POLARSSL_PK_ECDSA, -#endif } pk_type_t; /** From 72ef0b775d9979c7d4eb5492bd623843005514f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 12:20:54 +0200 Subject: [PATCH 12/33] Add test certificate signed with ECDSA --- tests/suites/test_suite_x509parse.data | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 0f95e1027..3c21b8b92 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -633,6 +633,9 @@ x509parse_crt:"30819f308189a0030201008204deadbeef300d06092a864886f70d01010205003 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 ASN (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 CRL ASN1 (Incorrect first tag) x509parse_crl:"":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT From 7c5819eb1e6a7ce146b65f599c5cf29905121b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 12:29:57 +0200 Subject: [PATCH 13/33] Fix warnings (enum value missing from switch/case) --- library/pk.c | 17 ++++++++++++++++- library/x509parse.c | 4 +++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/library/pk.c b/library/pk.c index 6762c75bb..3ea600ac9 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 @@ -74,6 +77,12 @@ void pk_free( pk_context *ctx ) ecp_keypair_free( ctx->data ); break; #endif + +#if defined(POLARSSL_ECDSA_C) + case POLARSSL_PK_ECDSA: + ecdsa_free( ctx->data ); + break; +#endif } if( ! ctx->dont_free ) @@ -111,8 +120,14 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) break; #endif +#if defined(POLARSSL_ECDSA_C) + case POLARSSL_PK_ECDSA: + size = sizeof( ecdsa_context ); + break; +#endif + case POLARSSL_PK_NONE: - ; /* Cannot happen, but the cmpiler doesn't know */ + ; /* Cannot happen, but the compiler doesn't know */ } if( ( ctx->data = malloc( size ) ) == NULL ) diff --git a/library/x509parse.c b/library/x509parse.c index 9e05f98cb..62396987b 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -637,7 +637,9 @@ static int x509_get_pubkey( unsigned char **p, switch( pk_alg ) { case POLARSSL_PK_NONE: - ret = POLARSSL_ERR_X509_UNKNOWN_PK_ALG; + case POLARSSL_PK_ECDSA: + /* Should never happen */ + ret = POLARSSL_ERR_X509_CERT_INVALID_ALG; break; case POLARSSL_PK_RSA: From 7a287c409e56d1f70ff885291e264097a7ceb23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 12:55:08 +0200 Subject: [PATCH 14/33] Rename x509_get_algid() to x509_get_pk_alg() --- library/x509parse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 62396987b..e70cee98e 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -166,7 +166,7 @@ static int x509_get_serial( unsigned char **p, * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ -static int x509_get_algid( unsigned char **p, +static int x509_get_pk_alg( unsigned char **p, const unsigned char *end, pk_type_t *pk_alg, x509_buf *params ) { @@ -614,7 +614,7 @@ static int x509_get_pubkey( unsigned char **p, end = *p + len; - if( ( ret = x509_get_algid( p, end, &pk_alg, &alg_params ) ) != 0 ) + if( ( ret = x509_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) return( ret ); if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 ) @@ -2813,7 +2813,7 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( if( version != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); - if( ( ret = x509_get_algid( &p, end, &pk_alg, &alg_params ) ) != 0 ) + if( ( ret = x509_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); if( pk_alg != POLARSSL_PK_ECKEY && pk_alg != POLARSSL_PK_ECKEY_DH ) From a155513e7bcee8cc9f0567b1687e8562a4cb125d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 13:18:41 +0200 Subject: [PATCH 15/33] Rationalize use of x509_get_alg variants --- library/x509parse.c | 63 ++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 46 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index e70cee98e..a2a866047 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -160,15 +160,15 @@ static int x509_get_serial( unsigned char **p, return( 0 ); } -/* Get an algorithm identifier and its parameters +/* Get a PK algorithm identifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ static int x509_get_pk_alg( unsigned char **p, - const unsigned char *end, - pk_type_t *pk_alg, x509_buf *params ) + const unsigned char *end, + pk_type_t *pk_alg, x509_buf *params ) { int ret; x509_buf alg_oid; @@ -194,44 +194,20 @@ static int x509_get_pk_alg( unsigned char **p, return( 0 ); } -/* +/* Get an algorithm identifier without parameters (eg for signatures) + * * 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_alg_null( unsigned char **p, const unsigned char *end, + x509_buf *alg ) { int ret; - size_t len; - if( params_end == NULL ) { - if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - - return( 0 ); - } - - /* TODO: use asn1_get_alg */ - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - } - - end = *p + len; - alg->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) + if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - alg->p = *p; - *p += alg->len; - - *params_end = end; return( 0 ); } @@ -1361,9 +1337,9 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, * * 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 ); @@ -1500,7 +1476,7 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, * 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 ); @@ -1823,7 +1799,7 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) * 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 ); @@ -1928,7 +1904,7 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) * 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 ); @@ -2323,7 +2299,7 @@ static int x509parse_key_pkcs8_unencrypted_der( int ret; size_t len; unsigned char *p, *end; - x509_buf pk_alg_oid; + x509_buf alg_params; pk_type_t pk_alg = POLARSSL_PK_NONE; p = (unsigned char *) key; @@ -2359,17 +2335,12 @@ static int x509parse_key_pkcs8_unencrypted_der( if( rsa->ver != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); - if( ( ret = asn1_get_alg_null( &p, end, &pk_alg_oid ) ) != 0 ) + if( ( ret = x509_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); /* - * only RSA keys handled at this time + * We explicitly want RSA keys only */ - 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 ); From 674b2243ebdddb146bc2c72c9fe265d1ed14e3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 14:32:58 +0200 Subject: [PATCH 16/33] Prepare transition from x509_cert.rsa to pk --- include/polarssl/x509.h | 3 ++- library/x509parse.c | 29 +++++++++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 61c784641..24e345356 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -211,7 +211,8 @@ typedef struct _x509_cert x509_time valid_from; /**< Start time of certificate validity. */ x509_time valid_to; /**< End time of certificate validity. */ - 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. */ + rsa_context rsa; /**< Container for the RSA context. Kept for compatibility while transitioning to generic PK */ x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ diff --git a/library/x509parse.c b/library/x509parse.c index a2a866047..7c69aa2e7 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -637,21 +637,6 @@ static int x509_get_pubkey( unsigned char **p, return( ret ); } -/* - * Get an RSA public key (compatibility wrapper) - */ -static int x509_get_pubkey_rsa( unsigned char **p, - const unsigned char *end, - rsa_context *rsa ) -{ - pk_context pk_ctx; - - pk_init( &pk_ctx ); - pk_wrap_rsa( &pk_ctx, rsa ); - - return( x509_get_pubkey( p, end, &pk_ctx ) ); -} - static int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig ) @@ -1416,12 +1401,23 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, /* * SubjectPublicKeyInfo */ - if( ( ret = x509_get_pubkey_rsa( &p, end, &crt->rsa ) ) != 0 ) + if( ( ret = x509_get_pubkey( &p, end, &crt->pk ) ) != 0 ) { x509_free( crt ); return( ret ); } + /* + * Temporary hack for compatibility while transitioning to PK abstraction + * (Cannot use rsa_wrap above since it would force RSA key type.) + */ + if( crt->pk.type == POLARSSL_PK_RSA ) { + memcpy( &crt->rsa, pk_rsa( crt->pk ), sizeof( rsa_context ) ); + free( crt->pk.data ); + crt->pk.data = &crt->rsa; + crt->pk.dont_free = 1; + } + /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 @@ -3969,6 +3965,7 @@ void x509_free( x509_cert *crt ) do { + pk_free( &cert_cur->pk ); rsa_free( &cert_cur->rsa ); name_cur = cert_cur->issuer.next; From 360a5830299599f5099e4dd39c06d5a12c1a4b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 14:56:36 +0200 Subject: [PATCH 17/33] Adapt x509parse_cert_info() for EC --- include/polarssl/pk.h | 21 +++++++++++++++++++++ library/x509parse.c | 19 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 7a54c7142..f5797f373 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -36,6 +36,27 @@ #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 + +#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 + + #ifdef __cplusplus extern "C" { #endif diff --git a/library/x509parse.c b/library/x509parse.c index 7c69aa2e7..8abbd0ec8 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -3341,8 +3341,23 @@ int x509parse_cert_info( char *buf, size_t size, const char *prefix, 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 ); + switch( crt->pk.type ) + { + case POLARSSL_PK_NONE: + case POLARSSL_PK_ECDSA: + ret = snprintf(p, n, "\n%sPK type looks wrong!", prefix); + break; + + case 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 ); + break; + + case POLARSSL_PK_ECKEY: + case POLARSSL_PK_ECKEY_DH: + ret = snprintf( p, n, "\n%sEC key size : %d bits\n", prefix, + (int) pk_ec( crt->pk )->grp.pbits ); + } SAFE_SNPRINTF(); return( (int) ( size - n ) ); From 5b18fb04ca9d1b99cfff92842d44ed27df269316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 16:07:25 +0200 Subject: [PATCH 18/33] Fix bug in x509_get_{ecpubkey,subpubkey}() - 'p' was not properly updated - also add a few more checks while at it --- library/x509parse.c | 46 ++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 8abbd0ec8..ab33c318b 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -275,17 +275,20 @@ static int x509_get_subpubkey_ec( unsigned char **p, const unsigned char *end, return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - /* - * 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. - */ - ++*p; - --len; + if( --len < 1 || *(*p)++ != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); if( ( ret = ecp_point_read_binary( grp, pt, (const unsigned char *) *p, len ) ) != 0 ) { - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); + } + + *p += len; + + if( ( ret = ecp_check_pubkey( grp, pt ) ) != 0 ) + { + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); } return( 0 ); @@ -562,7 +565,15 @@ static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, (const unsigned char *) *p, end - *p ) ) != 0 ) { - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); + } + + *p = (unsigned char *) end; + + if( ( ret = ecp_check_pubkey( &key->grp, &key->Q ) ) != 0 ) + { + ecp_keypair_free( key ); + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); } return( 0 ); @@ -604,7 +615,7 @@ static int x509_get_pubkey( unsigned char **p, return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - if( *(*p)++ != 0 ) + if( --len < 1 || *(*p)++ != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 ) @@ -631,6 +642,10 @@ static int x509_get_pubkey( unsigned char **p, break; } + if( ret == 0 && *p != end ) + ret = POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH; + if( ret != 0 ) pk_free( pk ); @@ -2628,6 +2643,7 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, ecp_group_id grp_id; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; + unsigned char *end2; /* * RFC 5915, orf SEC1 Appendix C.4 @@ -2706,18 +2722,18 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, 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 ) ) + end2 = p + len; + + if( ( ret = x509_get_subpubkey_ec( &p, end2, &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 ); - } + if( p != end2 ) + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) { From a3c86c334cd3f6204d286f8b45adcc2be67d4aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2013 16:54:29 +0200 Subject: [PATCH 19/33] Certificates with EC key and/or sig parsed --- tests/suites/test_suite_x509parse.data | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 3c21b8b92..bbfbed40b 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -633,9 +633,15 @@ x509parse_crt:"30819f308189a0030201008204deadbeef300d06092a864886f70d01010205003 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 ASN (ECDSA signature, RSA key) +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) +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) +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 From 893879adbd7d00939b2dbb7d31060d9196aab821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 10:31:57 +0200 Subject: [PATCH 20/33] Adapt debug_print_crt() for EC keys --- library/debug.c | 24 ++++++++++++++++++++---- tests/data_files/test-ca2.crt | Bin 0 -> 238 bytes tests/data_files/test-ca2.key | 8 ++++++++ tests/suites/test_suite_debug.data | 6 +++++- 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 tests/data_files/test-ca2.crt create mode 100644 tests/data_files/test-ca2.key diff --git a/library/debug.c b/library/debug.c index 23b901996..b6babe6fc 100644 --- a/library/debug.c +++ b/library/debug.c @@ -250,11 +250,27 @@ void debug_print_crt( const ssl_context *ssl, int level, str[maxlen] = '\0'; ssl->f_dbg( ssl->p_dbg, level, str ); - debug_print_mpi( ssl, level, file, line, - "crt->rsa.N", &crt->rsa.N ); + switch( crt->pk.type ) + { + case POLARSSL_PK_NONE: + case POLARSSL_PK_ECDSA: + debug_print_msg( ssl, level, file, line, + "crt->pk.type is not valid" ); + break; - debug_print_mpi( ssl, level, file, line, - "crt->rsa.E", &crt->rsa.E ); + case 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 ); + break; + + case POLARSSL_PK_ECKEY: + case POLARSSL_PK_ECKEY_DH: + debug_print_ecp( ssl, level, file, line, + "crt->eckey.Q", &pk_ec( crt->pk )->Q ); + break; + } crt = crt->next; } diff --git a/tests/data_files/test-ca2.crt b/tests/data_files/test-ca2.crt new file mode 100644 index 0000000000000000000000000000000000000000..c47c496bffeb66fdd4df15a927c5090af5d72ef2 GIT binary patch literal 238 zcmXqLd~MLUn2D3&i>OJO-tm`02Api{T5TTZY*`o$_zigtxY?LPS(t@cLQ;!M4CKUl z4UG-V4Gjz|O$-bzqr`cQfLsF$C>K+Mr-3lkI3`9m4zRh*jEu}i3@nP~)8?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 +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" From ff56da3a26cd7f5bfac1610413f0982a6233ba12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 10:46:21 +0200 Subject: [PATCH 21/33] Fix direct uses of x509_cert.rsa, now use pk_rsa() --- library/ssl_cli.c | 29 ++++++++++++++++++----------- library/ssl_srv.c | 11 ++++++++--- library/x509parse.c | 22 ++++++++++++++++++---- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 66ebcefcb..aeba799cb 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1072,8 +1072,12 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) 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 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) 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 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) 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 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) 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 c6a827320..2aef9c415 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1968,7 +1968,11 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) 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 @@ static int ssl_parse_certificate_verify( ssl_context *ssl ) 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 ab33c318b..6c848b7ab 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -3625,7 +3625,11 @@ static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca, 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 ) { /* @@ -3743,7 +3747,11 @@ static int x509parse_verify_top( 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; @@ -3819,9 +3827,15 @@ static int x509parse_verify_child( { 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 */ From 991d0f5aca0576a7561f2f63adf4d432bd0388c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 11:14:55 +0200 Subject: [PATCH 22/33] Remove rsa member from x509_cert structure --- include/polarssl/x509.h | 1 - library/x509parse.c | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 24e345356..47b5ab85b 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -212,7 +212,6 @@ typedef struct _x509_cert x509_time valid_to; /**< End time of certificate validity. */ pk_context pk; /**< Container for the public key context. */ - rsa_context rsa; /**< Container for the RSA context. Kept for compatibility while transitioning to generic PK */ x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ diff --git a/library/x509parse.c b/library/x509parse.c index 6c848b7ab..f03652694 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -1422,17 +1422,6 @@ static int x509parse_crt_der_core( x509_cert *crt, const unsigned char *buf, return( ret ); } - /* - * Temporary hack for compatibility while transitioning to PK abstraction - * (Cannot use rsa_wrap above since it would force RSA key type.) - */ - if( crt->pk.type == POLARSSL_PK_RSA ) { - memcpy( &crt->rsa, pk_rsa( crt->pk ), sizeof( rsa_context ) ); - free( crt->pk.data ); - crt->pk.data = &crt->rsa; - crt->pk.dont_free = 1; - } - /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 @@ -4011,7 +4000,6 @@ void x509_free( x509_cert *crt ) do { pk_free( &cert_cur->pk ); - rsa_free( &cert_cur->rsa ); name_cur = cert_cur->issuer.next; while( name_cur != NULL ) From be50680a8cdd4d972278015a4be86750f4a4af8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 13:17:21 +0200 Subject: [PATCH 23/33] Fix use of x509_cert.rsa in programs --- programs/test/ssl_cert_test.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/programs/test/ssl_cert_test.c b/programs/test/ssl_cert_test.c index bf4684b2f..ec824c9eb 100644 --- a/programs/test/ssl_cert_test.c +++ b/programs/test/ssl_cert_test.c @@ -206,19 +206,28 @@ int main( int argc, char *argv[] ) 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 ); From 1c808a011ce7d105d61cca2abad2b5909a870599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 13:17:43 +0200 Subject: [PATCH 24/33] Refactor some EC key parsing code --- include/polarssl/ecp.h | 4 +- library/x509parse.c | 98 ++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 62 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index c1f08c9f7..e6f28e652 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -121,8 +121,10 @@ ecp_keypair; * 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 diff --git a/library/x509parse.c b/library/x509parse.c index f03652694..ee9fe24b4 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -211,23 +211,6 @@ static int x509_get_alg_null( unsigned char **p, const unsigned char *end, return( 0 ); } -/* Get an EC group id from an ECParameters buffer - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * -- implicitCurve NULL - * -- specifiedCurve SpecifiedECDomain - * } - */ -static int x509_ecparams_get_grp_id( const x509_buf *params, - ecp_group_id *grp_id ) -{ - if( oid_get_ec_grp( params, grp_id ) != 0 ) - return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE ); - - return( 0 ); -} - /* Get an EC group id from an ECParameters buffer * * ECParameters ::= CHOICE { @@ -237,24 +220,46 @@ static int x509_ecparams_get_grp_id( const x509_buf *params, * } */ 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, ¶ms->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 ); - return( x509_ecparams_get_grp_id( &curve, grp_id ) ); + return( 0 ); +} + +/* + * Use EC parameters to initialise an EC group + */ +static int x509_use_ecparams( const x509_buf *params, ecp_group *grp ) +{ + int ret; + ecp_group_id grp_id; + + if( oid_get_ec_grp( params, &grp_id ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE ); + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != POLARSSL_ECP_DP_NONE && grp->id != grp_id ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); + + if( ( ret = ecp_use_known_dp( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); } /* @@ -554,12 +559,8 @@ static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, x509_buf *alg_params, ecp_keypair *key ) { int ret; - ecp_group_id grp_id; - if( ( ret = x509_ecparams_get_grp_id( alg_params, &grp_id ) ) != 0 ) - return( ret ); - - if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) + if( ( ret = x509_use_ecparams( alg_params, &key->grp ) ) != 0 ) return( ret ); if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, @@ -2287,7 +2288,6 @@ static int x509parse_key_pkcs1_der( rsa_context *rsa, return( 0 ); } - /* * Parse an unencrypted PKCS#8 encoded private RSA key */ @@ -2629,7 +2629,7 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, int ret; int version; size_t len; - ecp_group_id grp_id; + x509_buf params; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; unsigned char *end2; @@ -2675,31 +2675,14 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, 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 ) + if( ( ret = x509_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = x509_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + ecp_keypair_free( eck ); 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 ) + else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) { ecp_keypair_free( eck ); return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); @@ -2750,7 +2733,6 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( int ret, version; size_t len; x509_buf alg_params; - ecp_group_id grp_id; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; pk_type_t pk_alg = POLARSSL_PK_NONE; @@ -2794,13 +2776,7 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( if( pk_alg == POLARSSL_PK_ECKEY_DH ) eck->alg = POLARSSL_ECP_KEY_ALG_ECDH; - if( ( ret = x509_ecparams_get_grp_id( &alg_params, &grp_id ) ) != 0 ) - { - ecp_keypair_free( eck ); - return( ret ); - } - - if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 ) + if( ( ret = x509_use_ecparams( &alg_params, &eck->grp ) ) != 0 ) { ecp_keypair_free( eck ); return( ret ); From a2d4e644ac5092ca240f1355b8d0b5c16930e048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 13:59:02 +0200 Subject: [PATCH 25/33] Some more EC pubkey parsing refactoring Fix a bug in pk_rsa() and pk_ec() along the way --- include/polarssl/asn1.h | 13 ++++ include/polarssl/pk.h | 4 +- library/asn1parse.c | 18 ++++++ library/x509parse.c | 90 ++++++-------------------- tests/suites/test_suite_x509parse.data | 4 +- 5 files changed, 54 insertions(+), 75 deletions(-) diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index ae498d0cd..195ebcb84 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -212,6 +212,19 @@ int asn1_get_int( unsigned char **p, int asn1_get_bitstring( unsigned char **p, const unsigned char *end, 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 " * Updated the pointer to immediately behind the full sequence tag. diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index f5797f373..48bff9b01 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -43,7 +43,7 @@ * \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 ) +#define pk_rsa( pk ) ( (rsa_context *) (pk).data ) #endif #if defined(POLARSSL_ECP_C) @@ -53,7 +53,7 @@ * \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 ) +#define pk_ec( pk ) ( (ecp_keypair *) (pk).data ) #endif diff --git a/library/asn1parse.c b/library/asn1parse.c index 5b86aa60e..f6b79efd7 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -209,6 +209,24 @@ int asn1_get_bitstring( unsigned char **p, const unsigned char *end, 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 " diff --git a/library/x509parse.c b/library/x509parse.c index ee9fe24b4..4eafd7edb 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -262,43 +262,6 @@ static int x509_use_ecparams( const x509_buf *params, ecp_group *grp ) return( 0 ); } -/* - * subjectPublicKey BIT STRING - * -- which, in our case, contains - * ECPoint ::= octet string (not ASN.1) - */ -static int x509_get_subpubkey_ec( unsigned char **p, const unsigned char *end, - const ecp_group *grp, ecp_point *pt ) -{ - int ret; - size_t len; - - 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( --len < 1 || *(*p)++ != 0 ) - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - - if( ( ret = ecp_point_read_binary( grp, pt, - (const unsigned char *) *p, len ) ) != 0 ) - { - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - } - - *p += len; - - if( ( ret = ecp_check_pubkey( grp, pt ) ) != 0 ) - { - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - } - - return( 0 ); -} - /* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, @@ -556,27 +519,23 @@ static int x509_get_rsapubkey( unsigned char **p, } static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, - x509_buf *alg_params, ecp_keypair *key ) + ecp_keypair *key ) { int ret; - if( ( ret = x509_use_ecparams( alg_params, &key->grp ) ) != 0 ) - return( ret ); - if( ( ret = ecp_point_read_binary( &key->grp, &key->Q, - (const unsigned char *) *p, end - *p ) ) != 0 ) - { - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - } - - *p = (unsigned char *) end; - - if( ( ret = ecp_check_pubkey( &key->grp, &key->Q ) ) != 0 ) + (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 ); } @@ -605,20 +564,13 @@ static int x509_get_pubkey( unsigned char **p, if( ( ret = x509_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) return( ret ); - 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_PUBKEY + ret ); - if( ( end - *p ) < 1 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + - POLARSSL_ERR_ASN1_OUT_OF_DATA ); - if( *p + len != end ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - if( --len < 1 || *(*p)++ != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY ); - if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 ) return( ret ); @@ -639,7 +591,8 @@ static int x509_get_pubkey( unsigned char **p, /* FALLTHROUGH */ case POLARSSL_PK_ECKEY: - ret = x509_get_ecpubkey( p, end, &alg_params, pk->data ); + ret = x509_use_ecparams( &alg_params, &pk_ec( *pk )->grp ) || + x509_get_ecpubkey( p, end, pk->data ); break; } @@ -666,13 +619,9 @@ static int x509_get_sig( unsigned char **p, 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; @@ -2696,16 +2645,15 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, { end2 = p + len; - if( ( ret = x509_get_subpubkey_ec( &p, end2, &eck->grp, &eck->Q ) ) - != 0 ) - { - ecp_keypair_free( eck ); - return( ret ); - } + if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - if( p != end2 ) - return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + + 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 ) { diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index bbfbed40b..77f31d42b 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -523,7 +523,7 @@ X509 Certificate ASN1 (TBSCertificate, pubkey, no bitstring data) 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 @@ X509 Certificate ASN1 (sig_alg, no sig) 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 From 6e88202a95a349eab0efc7bad81c629c0e17172b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 14:55:43 +0200 Subject: [PATCH 26/33] Merge EC & RSA versions of parse_pkcs8_unencrypted --- library/x509parse.c | 404 ++++++++++++++++++++------------------------ 1 file changed, 182 insertions(+), 222 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 4eafd7edb..3fb970344 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2237,38 +2237,31 @@ static int x509parse_key_pkcs1_der( rsa_context *rsa, return( 0 ); } + /* - * 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 alg_params; - 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 ) @@ -2278,39 +2271,172 @@ static int x509parse_key_pkcs8_unencrypted_der( 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 = x509_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - - /* - * We explicitly want RSA keys only - */ - 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, ¶ms) ) != 0 || + ( ret = x509_use_ecparams( ¶ms, &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; +} + +/* + * 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, ¶ms ) ) != 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( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH ) + { + if( pk_alg == POLARSSL_PK_ECKEY_DH ) + pk_ec( *pk )->alg = POLARSSL_ECP_KEY_ALG_ECDH; + + if( ( ret = x509_use_ecparams( ¶ms, &pk_ec( *pk )->grp ) ) != 0 || + ( ret = x509parse_key_sec1_der( pk_ec( *pk ), p, len ) ) != 0 ) + { + pk_free( pk ); + return( ret ); + } + } else + if( pk_alg == POLARSSL_PK_RSA ) + { + if( ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 ) + { + pk_free( pk ); + return( ret ); + } + } else + return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + + return 0; +} + +/* + * Parse an unencrypted PKCS#8 encoded private RSA key + */ +static int x509parse_key_pkcs8_unencrypted_der_rsa( + rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + pk_context pk; + + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); + + return( x509parse_key_pkcs8_unencrypted_der( &pk, key, keylen ) ); } /* @@ -2426,7 +2552,7 @@ static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen, /* * Parse an encrypted PKCS#8 encoded private RSA key */ -static int x509parse_key_pkcs8_encrypted_der( +static int x509parse_key_pkcs8_encrypted_der_rsa( rsa_context *rsa, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) @@ -2441,7 +2567,7 @@ static int x509parse_key_pkcs8_encrypted_der( return( ret ); } - return( x509parse_key_pkcs8_unencrypted_der( rsa, buf, len ) ); + return( x509parse_key_pkcs8_unencrypted_der_rsa( rsa, buf, len ) ); } /* @@ -2485,7 +2611,7 @@ int x509parse_key_rsa( rsa_context *rsa, key, NULL, 0, &len ); if( ret == 0 ) { - if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa, + if( ( ret = x509parse_key_pkcs8_unencrypted_der_rsa( rsa, pem.buf, pem.buflen ) ) != 0 ) { rsa_free( rsa ); @@ -2503,7 +2629,7 @@ int x509parse_key_rsa( rsa_context *rsa, key, NULL, 0, &len ); if( ret == 0 ) { - if( ( ret = x509parse_key_pkcs8_encrypted_der( rsa, + if( ( ret = x509parse_key_pkcs8_encrypted_der_rsa( rsa, pem.buf, pem.buflen, pwd, pwdlen ) ) != 0 ) { @@ -2527,7 +2653,7 @@ int x509parse_key_rsa( rsa_context *rsa, * We try the different DER format parsers to see if one passes without * error */ - if( ( ret = x509parse_key_pkcs8_encrypted_der( rsa, key, keylen, + if( ( ret = x509parse_key_pkcs8_encrypted_der_rsa( rsa, key, keylen, pwd, pwdlen ) ) == 0 ) { return( 0 ); @@ -2540,7 +2666,7 @@ int x509parse_key_rsa( rsa_context *rsa, return( ret ); } - if( ( ret = x509parse_key_pkcs8_unencrypted_der( rsa, key, keylen ) ) == 0 ) + if( ( ret = x509parse_key_pkcs8_unencrypted_der_rsa( rsa, key, keylen ) ) == 0 ) return( 0 ); rsa_free( rsa ); @@ -2568,187 +2694,21 @@ int x509parse_public_key_rsa( rsa_context *rsa, } #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; - x509_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - unsigned char *end2; - - /* - * 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, ¶ms) ) != 0 || - ( ret = x509_use_ecparams( ¶ms, &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; -} - /* * Parse an unencrypted PKCS#8 encoded private EC key */ static int x509parse_key_pkcs8_unencrypted_der_ec( - ecp_keypair *eck, + ecp_keypair *ec, const unsigned char* key, size_t keylen ) { - int ret, version; - size_t len; - x509_buf alg_params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - pk_type_t pk_alg = POLARSSL_PK_NONE; + pk_context pk; - /* - * 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 - */ + pk.type = POLARSSL_PK_ECKEY; + pk.data = ec; + pk.dont_free = 1; - 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_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - - 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_use_ecparams( &alg_params, &eck->grp ) ) != 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; + return( x509parse_key_pkcs8_unencrypted_der( &pk, key, keylen ) ); } /* From 8b863cd6417fec773f7fef4531bd0ca67db403ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 15:32:03 +0200 Subject: [PATCH 27/33] Merge EC & RSA versions of x509_parse_key() --- library/x509parse.c | 316 +++++++++++--------------------------------- 1 file changed, 78 insertions(+), 238 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 3fb970344..1dca19d42 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -518,6 +518,9 @@ static int x509_get_rsapubkey( unsigned char **p, return( 0 ); } +/* + * EC public key is an EC point + */ static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, ecp_keypair *key ) { @@ -2073,23 +2076,12 @@ int x509parse_crlfile( x509_crl *chain, const char *path ) */ int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd ) { - int ret; - size_t n; - unsigned char *buf; + pk_context pk; - if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); - 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 ); + return( x509parse_keyfile( &pk, path, pwd ) ); } /* @@ -2097,19 +2089,12 @@ int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd ) */ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ) { - int ret; - size_t n; - unsigned char *buf; + pk_context pk; - if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); - ret = x509parse_public_key_rsa( rsa, buf, n ); - - memset( buf, 0, n + 1 ); - polarssl_free( buf ); - - return( ret ); + return( x509parse_public_keyfile( &pk, path ) ); } /* @@ -2423,22 +2408,6 @@ static int x509parse_key_pkcs8_unencrypted_der( return 0; } -/* - * Parse an unencrypted PKCS#8 encoded private RSA key - */ -static int x509parse_key_pkcs8_unencrypted_der_rsa( - rsa_context *rsa, - const unsigned char *key, - size_t keylen ) -{ - pk_context pk; - - pk_init( &pk ); - pk_wrap_rsa( &pk, rsa ); - - return( x509parse_key_pkcs8_unencrypted_der( &pk, key, keylen ) ); -} - /* * Decrypt the content of a PKCS#8 EncryptedPrivateKeyInfo */ @@ -2549,27 +2518,6 @@ static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen, return( 0 ); } -/* - * Parse an encrypted PKCS#8 encoded private RSA key - */ -static int x509parse_key_pkcs8_encrypted_der_rsa( - 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( rsa, buf, len ) ); -} - /* * Parse a private RSA key */ @@ -2577,106 +2525,12 @@ 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 defined(POLARSSL_PEM_C) - size_t len; - pem_context pem; + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); - pem_init( &pem ); - 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 ) - { - rsa_free( rsa ); - } - - pem_free( &pem ); - return( ret ); - } - else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) - return( POLARSSL_ERR_X509_PASSWORD_MISMATCH ); - else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) - 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( 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( 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( 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( 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 ); + return( x509parse_key( &pk, key, keylen, pwd, pwdlen ) ); } /* @@ -2685,37 +2539,20 @@ int x509parse_key_rsa( rsa_context *rsa, int x509parse_public_key_rsa( rsa_context *rsa, const unsigned char *key, size_t keylen ) { - pk_context pk_ctx; + pk_context pk; - pk_init( &pk_ctx ); - pk_wrap_rsa( &pk_ctx, rsa ); + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); - return( x509parse_public_key( &pk_ctx, key, keylen ) ); + return( x509parse_public_key( &pk, key, keylen ) ); } #if defined(POLARSSL_ECP_C) /* - * Parse an unencrypted PKCS#8 encoded private EC key + * Parse an encrypted PKCS#8 encoded private key */ -static int x509parse_key_pkcs8_unencrypted_der_ec( - ecp_keypair *ec, - const unsigned char* key, - size_t keylen ) -{ - pk_context pk; - - pk.type = POLARSSL_PK_ECKEY; - pk.data = ec; - pk.dont_free = 1; - - return( x509parse_key_pkcs8_unencrypted_der( &pk, key, keylen ) ); -} - -/* - * Parse an encrypted PKCS#8 encoded private EC key - */ -static int x509parse_key_pkcs8_encrypted_der_ec( - ecp_keypair *eck, +static int x509parse_key_pkcs8_encrypted_der( + pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { @@ -2729,15 +2566,16 @@ static int x509parse_key_pkcs8_encrypted_der_ec( return( ret ); } - return( x509parse_key_pkcs8_unencrypted_der_ec( eck, buf, len ) ); + return( x509parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); } +#endif /* defined(POLARSSL_ECP_C) */ /* - * Parse a private EC key + * Parse a private key */ -static int x509parse_key_ec( ecp_keypair *eck, - 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; @@ -2746,15 +2584,41 @@ static int x509parse_key_ec( ecp_keypair *eck, pem_context pem; pem_init( &pem ); + + ret = pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( ret = pk_set_type( pk, POLARSSL_PK_RSA ) ) != 0 || + ( ret = x509parse_key_pkcs1_der( pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + pk_free( pk ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_X509_PASSWORD_MISMATCH ); + else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) + return( POLARSSL_ERR_X509_PASSWORD_REQUIRED ); + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + 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 ); @@ -2773,10 +2637,10 @@ static int x509parse_key_ec( ecp_keypair *eck, 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 ); @@ -2791,11 +2655,11 @@ static int x509parse_key_ec( ecp_keypair *eck, 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 ); @@ -2815,66 +2679,42 @@ static int x509parse_key_ec( ecp_keypair *eck, * 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( ( 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 ); + + 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 ); return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); } -#endif /* defined(POLARSSL_ECP_C) */ - -/* - * Parse a private key - */ -int x509parse_key( pk_context *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret; - - if ( ( ret = pk_set_type( ctx, POLARSSL_PK_RSA ) ) != 0 ) - return( ret ); - - if( ( ret = x509parse_key_rsa( ctx->data, key, keylen, pwd, pwdlen ) ) - == 0 ) - { - return( 0 ); - } - - pk_free( ctx ); - - 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 ); - } - - pk_free( ctx ); - - return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); -} /* * Parse a public key From 96f3a4e1b308bb9a44f997effeae9d6f2967a88e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 15:55:14 +0200 Subject: [PATCH 28/33] Rm ecp_keypair.alg Avoid duplicating information already present in pk_context. --- include/polarssl/ecp.h | 12 ------------ library/ecp.c | 2 -- library/x509parse.c | 6 ------ 3 files changed, 20 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index e6f28e652..7bd9bd587 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -95,18 +95,12 @@ ecp_group; * \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; @@ -160,12 +154,6 @@ ecp_keypair; */ #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/library/ecp.c b/library/ecp.c index 9e7a96785..14683120a 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -101,7 +101,6 @@ void ecp_keypair_init( ecp_keypair *key ) 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 @@ void ecp_keypair_free( ecp_keypair *key ) 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/x509parse.c b/library/x509parse.c index 1dca19d42..4fba038d5 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -590,9 +590,6 @@ static int x509_get_pubkey( unsigned char **p, break; case POLARSSL_PK_ECKEY_DH: - ((ecp_keypair *) pk->data)->alg = POLARSSL_ECP_KEY_ALG_ECDH; - /* FALLTHROUGH */ - case POLARSSL_PK_ECKEY: ret = x509_use_ecparams( &alg_params, &pk_ec( *pk )->grp ) || x509_get_ecpubkey( p, end, pk->data ); @@ -2385,9 +2382,6 @@ static int x509parse_key_pkcs8_unencrypted_der( if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH ) { - if( pk_alg == POLARSSL_PK_ECKEY_DH ) - pk_ec( *pk )->alg = POLARSSL_ECP_KEY_ALG_ECDH; - if( ( ret = x509_use_ecparams( ¶ms, &pk_ec( *pk )->grp ) ) != 0 || ( ret = x509parse_key_sec1_der( pk_ec( *pk ), p, len ) ) != 0 ) { From ab2d9836b4dec6e36f189ac2548db7af7bc21f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 16:17:23 +0200 Subject: [PATCH 29/33] Fix some ifdef's in x509parse While at it: - move _rsa variants systematically after generic functions - unsplit x509parse_key_pkcs8_encrypted_der() (reverts a5d9974) --- include/polarssl/x509.h | 2 + library/x509parse.c | 248 ++++++++++++++++++++-------------------- 2 files changed, 124 insertions(+), 126 deletions(-) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 47b5ab85b..331553527 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -416,6 +416,7 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ); */ int x509parse_crlfile( x509_crl *chain, const char *path ); +#if defined(POLARSSL_RSA_C) /** \ingroup x509_module */ /** * \brief Parse a private RSA key @@ -468,6 +469,7 @@ int x509parse_public_key_rsa( rsa_context *rsa, * \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/x509parse.c b/library/x509parse.c index 4fba038d5..a11c06488 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -211,6 +211,8 @@ static int x509_get_alg_null( unsigned char **p, const unsigned char *end, return( 0 ); } + +#if defined(POLARSSL_ECP_C) /* Get an EC group id from an ECParameters buffer * * ECParameters ::= CHOICE { @@ -261,6 +263,7 @@ static int x509_use_ecparams( const x509_buf *params, ecp_group *grp ) return( 0 ); } +#endif /* POLARSSL_ECP_C */ /* * AttributeTypeAndValue ::= SEQUENCE { @@ -485,6 +488,7 @@ static int x509_get_dates( unsigned char **p, return( 0 ); } +#if defined(POLARSSL_RSA_C) /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n @@ -517,7 +521,9 @@ static int x509_get_rsapubkey( unsigned char **p, return( 0 ); } +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) /* * EC public key is an EC point */ @@ -541,6 +547,7 @@ static int x509_get_ecpubkey( unsigned char **p, const unsigned char *end, return( 0 ); } +#endif /* POLARSSL_ECP_C */ /* * SubjectPublicKeyInfo ::= SEQUENCE { @@ -577,24 +584,20 @@ static int x509_get_pubkey( unsigned char **p, if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 ) return( ret ); - switch( pk_alg ) +#if defined(POLARSSL_RSA_C) + if( pk_alg == POLARSSL_PK_RSA ) { - case POLARSSL_PK_NONE: - case POLARSSL_PK_ECDSA: - /* Should never happen */ - ret = POLARSSL_ERR_X509_CERT_INVALID_ALG; - break; - - case POLARSSL_PK_RSA: - ret = x509_get_rsapubkey( p, end, pk->data ); - break; - - case POLARSSL_PK_ECKEY_DH: - case POLARSSL_PK_ECKEY: - ret = x509_use_ecparams( &alg_params, &pk_ec( *pk )->grp ) || - x509_get_ecpubkey( p, end, pk->data ); - break; - } + 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; if( ret == 0 && *p != end ) ret = POLARSSL_ERR_X509_CERT_INVALID_PUBKEY @@ -2068,32 +2071,6 @@ int x509parse_crlfile( x509_crl *chain, const char *path ) return( ret ); } -/* - * 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 ) ); -} - /* * Load and parse a private key */ @@ -2139,8 +2116,36 @@ int x509parse_public_keyfile( pk_context *ctx, const char *path ) 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 */ @@ -2219,7 +2224,9 @@ static int x509parse_key_pkcs1_der( rsa_context *rsa, return( 0 ); } +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) /* * Parse a SEC1 encoded private EC key */ @@ -2321,6 +2328,7 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, return 0; } +#endif /* POLARSSL_ECP_C */ /* * Parse an unencrypted PKCS#8 encoded private key @@ -2380,6 +2388,17 @@ static int x509parse_key_pkcs8_unencrypted_der( if( ( ret = pk_set_type( pk, pk_alg ) ) != 0 ) return( ret ); +#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( ¶ms, &pk_ec( *pk )->grp ) ) != 0 || @@ -2389,29 +2408,23 @@ static int x509parse_key_pkcs8_unencrypted_der( return( ret ); } } else - 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_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) @@ -2419,7 +2432,7 @@ static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen, md_type_t md_alg; #endif - memset(buf, 0, buflen); + memset( buf, 0, sizeof( buf ) ); p = (unsigned char *) key; end = p + keylen; @@ -2455,7 +2468,7 @@ static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen, 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 ); /* @@ -2508,61 +2521,8 @@ static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen, #endif /* POLARSSL_PKCS5_C */ return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - *used_len = len; - return( 0 ); -} - -/* - * 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 ) -{ - pk_context pk; - - pk_init( &pk ); - pk_wrap_rsa( &pk, rsa ); - - return( x509parse_key( &pk, key, keylen, pwd, pwdlen ) ); -} - -/* - * Parse a public RSA key - */ -int x509parse_public_key_rsa( rsa_context *rsa, - const unsigned char *key, size_t keylen ) -{ - pk_context pk; - - pk_init( &pk ); - pk_wrap_rsa( &pk, rsa ); - - return( x509parse_public_key( &pk, key, keylen ) ); -} - -#if defined(POLARSSL_ECP_C) -/* - * Parse an encrypted PKCS#8 encoded private key - */ -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; - 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( pk, buf, len ) ); } -#endif /* defined(POLARSSL_ECP_C) */ /* * Parse a private key @@ -2579,6 +2539,7 @@ int x509parse_key( pk_context *pk, pem_init( &pem ); +#if defined(POLARSSL_RSA_C) ret = pem_read_buffer( &pem, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", @@ -2601,7 +2562,9 @@ int x509parse_key( pk_context *pk, return( POLARSSL_ERR_X509_PASSWORD_REQUIRED ); else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); +#endif /* POLARSSL_RSA_C */ +#if defined(POLARSSL_ECP_C) ret = pem_read_buffer( &pem, "-----BEGIN EC PRIVATE KEY-----", "-----END EC PRIVATE KEY-----", @@ -2624,6 +2587,7 @@ int x509parse_key( pk_context *pk, 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-----", @@ -2691,6 +2655,7 @@ int x509parse_key( pk_context *pk, pk_free( pk ); +#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 ) { @@ -2698,7 +2663,9 @@ int x509parse_key( pk_context *pk, } 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 ) { @@ -2706,6 +2673,7 @@ int x509parse_key( pk_context *pk, } pk_free( pk ); +#endif /* POLARSSL_ECP_C */ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); } @@ -2753,6 +2721,37 @@ int x509parse_public_key( pk_context *ctx, return( ret ); } +#if defined(POLARSSL_RSA_C) +/* + * 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 ) +{ + pk_context pk; + + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); + + return( x509parse_key( &pk, key, keylen, pwd, pwdlen ) ); +} + +/* + * Parse a public RSA key + */ +int x509parse_public_key_rsa( rsa_context *rsa, + const unsigned char *key, size_t keylen ) +{ + pk_context pk; + + pk_init( &pk ); + pk_wrap_rsa( &pk, rsa ); + + return( x509parse_public_key( &pk, key, keylen ) ); +} +#endif /* POLARSSL_RSA_C */ + #if defined(POLARSSL_DHM_C) /* * Parse DHM parameters @@ -3064,23 +3063,20 @@ int x509parse_cert_info( char *buf, size_t size, const char *prefix, ret = snprintf( p, n, desc ); SAFE_SNPRINTF(); - switch( crt->pk.type ) - { - case POLARSSL_PK_NONE: - case POLARSSL_PK_ECDSA: - ret = snprintf(p, n, "\n%sPK type looks wrong!", prefix); - break; - - case 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 ); - break; - - case POLARSSL_PK_ECKEY: - case POLARSSL_PK_ECKEY_DH: - ret = snprintf( p, n, "\n%sEC key size : %d bits\n", prefix, - (int) pk_ec( crt->pk )->grp.pbits ); - } +#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 ) ); From fd5164e28388a467f8edff5ddf235403c958a2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 16:39:05 +0200 Subject: [PATCH 30/33] Fix some more ifdef's RSA/EC, in pk and debug --- include/polarssl/pk.h | 6 ++--- library/debug.c | 38 ++++++++++++++-------------- library/pk.c | 58 ++++++++++++++++--------------------------- 3 files changed, 43 insertions(+), 59 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 48bff9b01..df3fc44de 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -44,7 +44,7 @@ * before using this macro! */ #define pk_rsa( pk ) ( (rsa_context *) (pk).data ) -#endif +#endif /* POLARSSL_RSA_C */ #if defined(POLARSSL_ECP_C) /** @@ -54,7 +54,7 @@ * before using this macro! */ #define pk_ec( pk ) ( (ecp_keypair *) (pk).data ) -#endif +#endif /* POLARSSL_ECP_C */ #ifdef __cplusplus @@ -120,7 +120,7 @@ int pk_set_type( pk_context *ctx, pk_type_t type ); * POLARSSL_ERR_PK_TYPE_MISMATCH if ctx was not empty. */ int pk_wrap_rsa( pk_context *ctx, const rsa_context *rsa); -#endif +#endif /* POLARSSL_RSA_C */ #ifdef __cplusplus } diff --git a/library/debug.c b/library/debug.c index b6babe6fc..8e3dd03a9 100644 --- a/library/debug.c +++ b/library/debug.c @@ -250,27 +250,25 @@ void debug_print_crt( const ssl_context *ssl, int level, str[maxlen] = '\0'; ssl->f_dbg( ssl->p_dbg, level, str ); - switch( crt->pk.type ) +#if defined(POLARSSL_RSA_C) + if( crt->pk.type == POLARSSL_PK_RSA ) { - case POLARSSL_PK_NONE: - case POLARSSL_PK_ECDSA: - debug_print_msg( ssl, level, file, line, - "crt->pk.type is not valid" ); - break; - - case 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 ); - break; - - case POLARSSL_PK_ECKEY: - case POLARSSL_PK_ECKEY_DH: - debug_print_ecp( ssl, level, file, line, - "crt->eckey.Q", &pk_ec( crt->pk )->Q ); - break; - } + 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/pk.c b/library/pk.c index 3ea600ac9..18db95ade 100644 --- a/library/pk.c +++ b/library/pk.c @@ -60,29 +60,23 @@ void pk_free( pk_context *ctx ) 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) - case POLARSSL_PK_ECDSA: - ecdsa_free( ctx->data ); - break; + if( ctx->type == POLARSSL_PK_ECDSA ) + ecdsa_free( ctx->data ); + else #endif + { + ; /* guard for the else's above */ } if( ! ctx->dont_free ) @@ -97,7 +91,7 @@ void pk_free( pk_context *ctx ) */ int pk_set_type( pk_context *ctx, pk_type_t type ) { - size_t size = 0; + size_t size; if( ctx->type == type ) return( 0 ); @@ -105,30 +99,22 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) if( ctx->type != POLARSSL_PK_NONE ) return( POLARSSL_ERR_PK_TYPE_MISMATCH ); - switch( type ) - { #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 - #if defined(POLARSSL_ECDSA_C) - case POLARSSL_PK_ECDSA: - size = sizeof( ecdsa_context ); - break; + if( type == POLARSSL_PK_ECDSA ) + size = sizeof( ecdsa_context ); + else #endif - - case POLARSSL_PK_NONE: - ; /* Cannot happen, but the compiler doesn't know */ - } + size = 0; /* should never be executed */ if( ( ctx->data = malloc( size ) ) == NULL ) return( POLARSSL_ERR_PK_MALLOC_FAILED ); From 4f47538ad8c186cae1bc2f06ee143183bb6961c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2013 16:47:11 +0200 Subject: [PATCH 31/33] Fix some 'depends' in tests --- tests/suites/test_suite_debug.data | 2 +- tests/suites/test_suite_x509parse.data | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/suites/test_suite_debug.data b/tests/suites/test_suite_debug.data index e28b1b9e0..7a309cef7 100644 --- a/tests/suites/test_suite_debug.data +++ b/tests/suites/test_suite_debug.data @@ -3,7 +3,7 @@ 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 +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 diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 77f31d42b..bf13719b3 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -187,39 +187,39 @@ depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO 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 @@ -637,9 +637,11 @@ 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) From 14d85644020ff2858e60b179f7952f5d37b98bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2013 11:01:14 +0200 Subject: [PATCH 32/33] Fix overflow check in oid_get_numeric_string() (The fix in 791eed3 was wrong.) --- library/oid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/oid.c b/library/oid.c index 366720ec0..750ece8e3 100644 --- a/library/oid.c +++ b/library/oid.c @@ -591,8 +591,7 @@ int oid_get_numeric_string( char *buf, size_t size, 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; From c2c90031ecd3c1a26369ad89b99fad3264542ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2013 11:04:58 +0200 Subject: [PATCH 33/33] Fix pk_set_type() behaviour for unkown type --- library/pk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/pk.c b/library/pk.c index 18db95ade..78ff5e97c 100644 --- a/library/pk.c +++ b/library/pk.c @@ -114,7 +114,7 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) size = sizeof( ecdsa_context ); else #endif - size = 0; /* should never be executed */ + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); if( ( ctx->data = malloc( size ) ) == NULL ) return( POLARSSL_ERR_PK_MALLOC_FAILED );