From bec2f45cfc080ebf60287d96737d6d3d8705fc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Jun 2013 10:17:07 +0200 Subject: [PATCH 01/33] Add ecdsa_context structure --- include/polarssl/ecdsa.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h index 2ad986d64..f6b1e784c 100644 --- a/include/polarssl/ecdsa.h +++ b/include/polarssl/ecdsa.h @@ -29,6 +29,20 @@ #include "polarssl/ecp.h" +/** + * \brief ECDSA context structure + */ +typedef struct +{ + ecp_group grp; /*!< ellipitic curve used */ + mpi d; /*!< secret signature key */ + ecp_point Q; /*!< public signature key */ + mpi r; /*!< first integer from signature */ + mpi s; /*!< second integer from signature */ + int point_format; /*!< format for point export */ +} +ecdsa_context; + #ifdef __cplusplus extern "C" { #endif From 7c8934ea0eb63906874aca1622ffdba1c06b519e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Jun 2013 12:54:02 +0200 Subject: [PATCH 02/33] Add ecdsa_init and ecdsa_free --- include/polarssl/ecdsa.h | 14 ++++++++++++++ library/ecdsa.c | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h index f6b1e784c..e709b405c 100644 --- a/include/polarssl/ecdsa.h +++ b/include/polarssl/ecdsa.h @@ -84,6 +84,20 @@ int ecdsa_verify( const ecp_group *grp, const unsigned char *buf, size_t blen, const ecp_point *Q, const mpi *r, const mpi *s); +/** + * \brief Initialize context + * + * \param ctx Context to initialize + */ +void ecdsa_init( ecdsa_context *ctx ); + +/** + * \brief Free context + * + * \param ctx Context to free + */ +void ecdsa_free( ecdsa_context *ctx ); + /** * \brief Checkup routine * diff --git a/library/ecdsa.c b/library/ecdsa.c index d6834574d..11b7f5e49 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -174,6 +174,33 @@ cleanup: return( ret ); } +/* + * Initialize context + */ +void ecdsa_init( ecdsa_context *ctx ) +{ + ecp_group_init( &ctx->grp ); + mpi_init( &ctx->d ); + ecp_point_init( &ctx->Q ); + mpi_init( &ctx->r ); + mpi_init( &ctx->s ); + mpi_init( &ctx->d ); + ctx->point_format = POLARSSL_ECP_PF_UNCOMPRESSED; +} + +/* + * Free context + */ +void ecdsa_free( ecdsa_context *ctx ) +{ + ecp_group_free( &ctx->grp ); + mpi_free( &ctx->d ); + ecp_point_free( &ctx->Q ); + mpi_free( &ctx->r ); + mpi_free( &ctx->s ); + mpi_free( &ctx->d ); + ctx->point_format = POLARSSL_ECP_PF_UNCOMPRESSED; +} #if defined(POLARSSL_SELF_TEST) From b8c6e0e3e9eee83c481aef30d78296d612301e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 1 Jul 2013 13:40:52 +0200 Subject: [PATCH 03/33] Add ecp_keypair struct, init/free and constants --- include/polarssl/ecp.h | 39 +++++++++++++++++++++++++++++++++++++++ library/ecp.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 4b0218180..db59a9350 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -91,6 +91,25 @@ typedef struct } 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; + /** * RFC 5114 defines a number of standardized ECP groups for use with TLS. * @@ -139,6 +158,16 @@ ecp_group; */ #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 + /** * \brief Initialize a point (as zero) */ @@ -149,6 +178,11 @@ void ecp_point_init( ecp_point *pt ); */ void ecp_group_init( ecp_group *grp ); +/** + * \brief Initialize a key pair (as an invalid one) + */ +void ecp_keypair_init( ecp_keypair *key ); + /** * \brief Free the components of a point */ @@ -159,6 +193,11 @@ void ecp_point_free( ecp_point *pt ); */ void ecp_group_free( ecp_group *grp ); +/** + * \brief Free the components of a key pair + */ +void ecp_keypair_free( ecp_keypair *key ); + /** * \brief Set a point to zero * diff --git a/library/ecp.c b/library/ecp.c index af18e5bee..216fc4330 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -90,6 +90,20 @@ void ecp_group_init( ecp_group *grp ) grp->modp = NULL; } +/* + * Initialize (the components of) a key pair + */ +void ecp_keypair_init( ecp_keypair *key ) +{ + if ( key == NULL ) + return; + + ecp_group_init( &key->grp ); + mpi_init( &key->d ); + ecp_point_init( &key->Q ); + key->alg = POLARSSL_ECP_KEY_ALG_UNRESTRICTED; +} + /* * Unallocate (the components of) a point */ @@ -117,6 +131,20 @@ void ecp_group_free( ecp_group *grp ) mpi_free( &grp->N ); } +/* + * Unallocate (the components of) a key pair + */ +void ecp_keypair_free( ecp_keypair *key ) +{ + if ( key == NULL ) + return; + + ecp_group_free( &key->grp ); + mpi_free( &key->d ); + ecp_point_free( &key->Q ); + key->alg = POLARSSL_ECP_KEY_ALG_UNRESTRICTED; +} + /* * Set point to zero */ From c8dc295e8363deacb511f051d01bd13280b752be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 1 Jul 2013 14:06:13 +0200 Subject: [PATCH 04/33] Add ecp_check_prvkey, with test Also group key checking and generation functions in ecp.h and ecp.c. --- include/polarssl/ecp.h | 61 +++++++++++----- library/ecp.c | 102 +++++++++++++++------------ tests/suites/test_suite_ecp.data | 3 + tests/suites/test_suite_ecp.function | 26 ++++++- 4 files changed, 126 insertions(+), 66 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index db59a9350..707d04028 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -228,25 +228,6 @@ int ecp_is_zero( ecp_point *pt ); */ int ecp_copy( ecp_point *P, const ecp_point *Q ); -/** - * \brief Check that a point is a valid public key on this curve - * - * \param grp Curve/group the point should belong to - * \param pt Point to check - * - * \return 0 if point is a valid public key, - * POLARSSL_ERR_ECP_GENERIC otherwise. - * - * \note This function only checks the point is non-zero, has valid - * coordinates and lies on the curve, but not that it is - * indeed a multiple of G. This is additional check is more - * expensive, isn't required by standards, and shouldn't be - * necessary if the group used has a small cofactor. In - * particular, it is useless for the NIST groups which all - * have a cofactor of 1. - */ -int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ); - /** * \brief Import a non-zero point from two ASCII strings * @@ -437,6 +418,44 @@ int ecp_sub( const ecp_group *grp, ecp_point *R, int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * POLARSSL_ERR_ECP_GENERIC otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ); + +/** + * \brief Check that an mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * POLARSSL_ERR_ECP_GENERIC otherwise. + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. + */ +int ecp_check_prvkey( const ecp_group *grp, const mpi *d ); + /** * \brief Generate a keypair * @@ -448,6 +467,10 @@ int ecp_mul( const ecp_group *grp, ecp_point *R, * * \return 0 if successful, * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + * + * \note Uses bare components rather than an ecp_keypair structure + * in order to ease use with other structures such as + * ecdh_context of ecdsa_context. */ int ecp_gen_keypair( const ecp_group *grp, mpi *d, ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), diff --git a/library/ecp.c b/library/ecp.c index 216fc4330..29cfce5a3 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -727,51 +727,6 @@ int ecp_tls_write_group( const ecp_group *grp, size_t *olen, while( mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) ) -/* - * Check that a point is valid as a public key (SEC1 3.2.3.1) - */ -int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ) -{ - int ret; - mpi YY, RHS; - - if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) - return( POLARSSL_ERR_ECP_GENERIC ); - - /* - * pt coordinates must be normalized for our checks - */ - if( mpi_cmp_int( &pt->Z, 1 ) != 0 ) - return( POLARSSL_ERR_ECP_GENERIC ); - - if( mpi_cmp_int( &pt->X, 0 ) < 0 || - mpi_cmp_int( &pt->Y, 0 ) < 0 || - mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || - mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) - return( POLARSSL_ERR_ECP_GENERIC ); - - mpi_init( &YY ); mpi_init( &RHS ); - - /* - * YY = Y^2 - * RHS = X (X^2 - 3) + B = X^3 - 3X + B - */ - MPI_CHK( mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); - MPI_CHK( mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); - MPI_CHK( mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); - MPI_CHK( mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); - MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); - - if( mpi_cmp_mpi( &YY, &RHS ) != 0 ) - ret = POLARSSL_ERR_ECP_GENERIC; - -cleanup: - - mpi_free( &YY ); mpi_free( &RHS ); - - return( ret ); -} - /* * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) */ @@ -1305,6 +1260,63 @@ cleanup: return( ret ); } +/* + * Check that a point is valid as a public key (SEC1 3.2.3.1) + */ +int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ) +{ + int ret; + mpi YY, RHS; + + if( mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + /* + * pt coordinates must be normalized for our checks + */ + if( mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + if( mpi_cmp_int( &pt->X, 0 ) < 0 || + mpi_cmp_int( &pt->Y, 0 ) < 0 || + mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + mpi_init( &YY ); mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 - 3) + B = X^3 - 3X + B + */ + MPI_CHK( mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MPI_CHK( mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + MPI_CHK( mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + MPI_CHK( mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = POLARSSL_ERR_ECP_GENERIC; + +cleanup: + + mpi_free( &YY ); mpi_free( &RHS ); + + return( ret ); +} + +/* + * Check that an mpi is valid as a private key (SEC1 3.2) + */ +int ecp_check_prvkey( const ecp_group *grp, const mpi *d ) +{ + /* We want 1 <= d <= N-1 */ + if ( mpi_cmp_int( d, 1 ) < 0 || mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + return( 0 ); +} + /* * Generate a keypair (SEC1 3.2.1) */ diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 30fc4614d..d19e41863 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -245,6 +245,9 @@ ECP tls write-read group #2 depends_on:POLARSSL_ECP_DP_SECP521R1_ENABLED ecp_tls_write_read_group:SECP521R1 +ECP check prvkey +ecp_check_prvkey:SECP192R1 + ECP gen keypair depends_on:POLARSSL_ECP_DP_SECP192R1_ENABLED ecp_gen_keypair:SECP192R1 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index a051bd74d..1d3d3dfc2 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -437,6 +437,28 @@ ecp_tls_write_read_group:id } END_CASE +BEGIN_CASE +ecp_check_prvkey:id +{ + ecp_group grp; + mpi d; + + ecp_group_init( &grp ); + mpi_init( &d ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( mpi_lset( &d, 0 ) == 0 ); + TEST_ASSERT( ecp_check_prvkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); + + TEST_ASSERT( mpi_copy( &d, &grp.N ) == 0 ); + TEST_ASSERT( ecp_check_prvkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); + + ecp_group_free( &grp ); + mpi_free( &d ); +} +END_CASE + BEGIN_CASE ecp_gen_keypair:id { @@ -455,8 +477,8 @@ ecp_gen_keypair:id TEST_ASSERT( ecp_gen_keypair( &grp, &d, &Q, &rnd_pseudo_rand, &rnd_info ) == 0 ); - TEST_ASSERT( mpi_cmp_mpi( &d, &grp.N ) < 0 ); - TEST_ASSERT( mpi_cmp_int( &d, 1 ) >= 0 ); + TEST_ASSERT( ecp_check_pubkey( &grp, &Q ) == 0 ); + TEST_ASSERT( ecp_check_prvkey( &grp, &d ) == 0 ); ecp_group_free( &grp ); ecp_point_free( &Q ); From ba4878aa6478cca39ec1f583b17fc1d8d4f0b656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Jun 2013 10:51:01 +0200 Subject: [PATCH 05/33] Rename x509parse_key & co with _rsa suffix --- doxygen/input/doc_x509.h | 4 +- include/polarssl/x509.h | 16 +-- library/x509parse.c | 20 ++-- programs/pkey/key_app.c | 8 +- programs/pkey/key_app_writer.c | 8 +- programs/pkey/rsa_sign_pss.c | 2 +- programs/pkey/rsa_verify_pss.c | 4 +- programs/ssl/ssl_client2.c | 6 +- programs/ssl/ssl_fork_server.c | 6 +- programs/ssl/ssl_mail_client.c | 6 +- programs/ssl/ssl_server.c | 6 +- programs/ssl/ssl_server2.c | 6 +- programs/test/o_p_test.c | 2 +- programs/test/ssl_cert_test.c | 4 +- programs/test/ssl_test.c | 4 +- programs/x509/cert_req.c | 4 +- tests/suites/test_suite_x509parse.data | 122 ++++++++++----------- tests/suites/test_suite_x509parse.function | 12 +- tests/suites/test_suite_x509write.function | 2 +- 19 files changed, 122 insertions(+), 120 deletions(-) diff --git a/doxygen/input/doc_x509.h b/doxygen/input/doc_x509.h index 56bb49b4d..16fe75a2b 100644 --- a/doxygen/input/doc_x509.h +++ b/doxygen/input/doc_x509.h @@ -11,8 +11,8 @@ * \c x509parse_crtfile()). * - X.509 certificate revocation list (CRL) reading (see \c x509parse_crl() * and\c x509parse_crlfile()). - * - X.509 (RSA) private key reading (see \c x509parse_key() and - * \c x509parse_keyfile()). + * - X.509 (RSA) private key reading (see \c x509parse_key_rsa() and + * \c x509parse_keyfile_rsa()). * - X.509 certificate signature verification (see \c x509parse_verify()) * * This module can be used to build a certificate authority (CA) chain and diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 86624ecb0..d7f144387 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -427,9 +427,9 @@ int x509parse_crlfile( x509_crl *chain, const char *path ); * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_key( rsa_context *rsa, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ); +int x509parse_key_rsa( rsa_context *rsa, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); /** \ingroup x509_module */ /** @@ -441,8 +441,8 @@ int x509parse_key( rsa_context *rsa, * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_keyfile( rsa_context *rsa, const char *path, - const char *password ); +int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, + const char *password ); /** \ingroup x509_module */ /** @@ -454,8 +454,8 @@ int x509parse_keyfile( rsa_context *rsa, const char *path, * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_public_key( rsa_context *rsa, - const unsigned char *key, size_t keylen ); +int x509parse_public_key_rsa( rsa_context *rsa, + const unsigned char *key, size_t keylen ); /** \ingroup x509_module */ /** @@ -466,7 +466,7 @@ int x509parse_public_key( rsa_context *rsa, * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_public_keyfile( rsa_context *rsa, const char *path ); +int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ); /** \ingroup x509_module */ /** diff --git a/library/x509parse.c b/library/x509parse.c index ea3a24abc..7c7ee29fb 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -1945,7 +1945,7 @@ int x509parse_crlfile( x509_crl *chain, const char *path ) /* * Load and parse a private RSA key */ -int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd ) +int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd ) { int ret; size_t n; @@ -1955,9 +1955,9 @@ int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd ) return( ret ); if( pwd == NULL ) - ret = x509parse_key( rsa, buf, n, NULL, 0 ); + ret = x509parse_key_rsa( rsa, buf, n, NULL, 0 ); else - ret = x509parse_key( rsa, buf, n, + ret = x509parse_key_rsa( rsa, buf, n, (const unsigned char *) pwd, strlen( pwd ) ); memset( buf, 0, n + 1 ); @@ -1969,7 +1969,7 @@ int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd ) /* * Load and parse a public RSA key */ -int x509parse_public_keyfile( rsa_context *rsa, const char *path ) +int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ) { int ret; size_t n; @@ -1978,7 +1978,7 @@ int x509parse_public_keyfile( rsa_context *rsa, const char *path ) if ( (ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); - ret = x509parse_public_key( rsa, buf, n ); + ret = x509parse_public_key_rsa( rsa, buf, n ); memset( buf, 0, n + 1 ); polarssl_free( buf ); @@ -2258,8 +2258,9 @@ static int x509parse_key_pkcs8_encrypted_der( /* * Parse a private RSA key */ -int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) +int x509parse_key_rsa( rsa_context *rsa, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { int ret; @@ -2365,7 +2366,8 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen, /* * Parse a public RSA key */ -int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t keylen ) +int x509parse_public_key_rsa( rsa_context *rsa, + const unsigned char *key, size_t keylen ) { int ret; size_t len; @@ -3562,7 +3564,7 @@ int x509_self_test( int verbose ) rsa_init( &rsa, RSA_PKCS_V15, 0 ); - if( ( ret = x509parse_key( &rsa, + if( ( ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_ca_key, i, (const unsigned char *) test_ca_pwd, j ) ) != 0 ) { diff --git a/programs/pkey/key_app.c b/programs/pkey/key_app.c index 2f906c4ec..bea996aab 100644 --- a/programs/pkey/key_app.c +++ b/programs/pkey/key_app.c @@ -164,14 +164,14 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the private key ..." ); fflush( stdout ); - ret = x509parse_keyfile( &rsa, opt.filename, opt.password ); + ret = x509parse_keyfile_rsa( &rsa, opt.filename, opt.password ); if( ret != 0 ) { #ifdef POLARSSL_ERROR_C polarssl_strerror( ret, buf, 1024 ); #endif - printf( " failed\n ! x509parse_key returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); rsa_free( &rsa ); goto exit; } @@ -199,14 +199,14 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the public key ..." ); fflush( stdout ); - ret = x509parse_public_keyfile( &rsa, opt.filename ); + ret = x509parse_public_keyfile_rsa( &rsa, opt.filename ); if( ret != 0 ) { #ifdef POLARSSL_ERROR_C polarssl_strerror( ret, buf, 1024 ); #endif - printf( " failed\n ! x509parse_public_key returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_public_key_rsa returned %d - %s\n\n", ret, buf ); rsa_free( &rsa ); goto exit; } diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c index feb2ecc53..88cb9071c 100644 --- a/programs/pkey/key_app_writer.c +++ b/programs/pkey/key_app_writer.c @@ -238,14 +238,14 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the private key ..." ); fflush( stdout ); - ret = x509parse_keyfile( &rsa, opt.filename, NULL ); + ret = x509parse_keyfile_rsa( &rsa, opt.filename, NULL ); if( ret != 0 ) { #ifdef POLARSSL_ERROR_C polarssl_strerror( ret, buf, 1024 ); #endif - printf( " failed\n ! x509parse_key returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); rsa_free( &rsa ); goto exit; } @@ -274,14 +274,14 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the public key ..." ); fflush( stdout ); - ret = x509parse_public_keyfile( &rsa, opt.filename ); + ret = x509parse_public_keyfile_rsa( &rsa, opt.filename ); if( ret != 0 ) { #ifdef POLARSSL_ERROR_C polarssl_strerror( ret, buf, 1024 ); #endif - printf( " failed\n ! x509parse_public_key returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_public_key_rsa returned %d - %s\n\n", ret, buf ); rsa_free( &rsa ); goto exit; } diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c index 82387080d..e848f545f 100644 --- a/programs/pkey/rsa_sign_pss.c +++ b/programs/pkey/rsa_sign_pss.c @@ -101,7 +101,7 @@ int main( int argc, char *argv[] ) rsa_init( &rsa, RSA_PKCS_V21, POLARSSL_MD_SHA1 ); - if( ( ret = x509parse_keyfile( &rsa, argv[1], "" ) ) != 0 ) + if( ( ret = x509parse_keyfile_rsa( &rsa, argv[1], "" ) ) != 0 ) { ret = 1; printf( " failed\n ! Could not open '%s'\n", argv[1] ); diff --git a/programs/pkey/rsa_verify_pss.c b/programs/pkey/rsa_verify_pss.c index b44daa078..00d73781f 100644 --- a/programs/pkey/rsa_verify_pss.c +++ b/programs/pkey/rsa_verify_pss.c @@ -83,9 +83,9 @@ int main( int argc, char *argv[] ) rsa_init( &rsa, RSA_PKCS_V21, POLARSSL_MD_SHA1 ); - if( ( ret = x509parse_public_keyfile( &rsa, argv[1] ) ) != 0 ) + if( ( ret = x509parse_public_keyfile_rsa( &rsa, argv[1] ) ) != 0 ) { - printf( " failed\n ! x509parse_public_key returned %d\n\n", ret ); + printf( " failed\n ! x509parse_public_key_rsa returned %d\n\n", ret ); goto exit; } diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 1ddb86d9f..036cc67ae 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -533,11 +533,11 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.key_file ) ) - ret = x509parse_keyfile( &rsa, opt.key_file, "" ); + ret = x509parse_keyfile_rsa( &rsa, opt.key_file, "" ); else #endif #if defined(POLARSSL_CERTS_C) - ret = x509parse_key( &rsa, (const unsigned char *) test_cli_key, + ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_cli_key, strlen( test_cli_key ), NULL, 0 ); #else { @@ -547,7 +547,7 @@ int main( int argc, char *argv[] ) #endif if( ret != 0 ) { - printf( " failed\n ! x509parse_key returned -0x%x\n\n", -ret ); + printf( " failed\n ! x509parse_key_rsa returned -0x%x\n\n", -ret ); goto exit; } diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c index e021ebbd6..986458b5e 100644 --- a/programs/ssl/ssl_fork_server.c +++ b/programs/ssl/ssl_fork_server.c @@ -139,7 +139,7 @@ int main( int argc, char *argv[] ) /* * This demonstration program uses embedded test certificates. * Instead, you may want to use x509parse_crtfile() to read the - * server and CA certificates, as well as x509parse_keyfile(). + * server and CA certificates, as well as x509parse_keyfile_rsa(). */ ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt, strlen( test_srv_crt ) ); @@ -158,11 +158,11 @@ int main( int argc, char *argv[] ) } rsa_init( &rsa, RSA_PKCS_V15, 0 ); - ret = x509parse_key( &rsa, (const unsigned char *) test_srv_key, + ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key, strlen( test_srv_key ), NULL, 0 ); if( ret != 0 ) { - printf( " failed\n ! x509parse_key returned %d\n\n", ret ); + printf( " failed\n ! x509parse_key_rsa returned %d\n\n", ret ); goto exit; } diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c index 4b5d177a5..665cdbfe8 100644 --- a/programs/ssl/ssl_mail_client.c +++ b/programs/ssl/ssl_mail_client.c @@ -532,11 +532,11 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.key_file ) ) - ret = x509parse_keyfile( &rsa, opt.key_file, "" ); + ret = x509parse_keyfile_rsa( &rsa, opt.key_file, "" ); else #endif #if defined(POLARSSL_CERTS_C) - ret = x509parse_key( &rsa, (const unsigned char *) test_cli_key, + ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_cli_key, strlen( test_cli_key ), NULL, 0 ); #else { @@ -546,7 +546,7 @@ int main( int argc, char *argv[] ) #endif if( ret != 0 ) { - printf( " failed\n ! x509parse_key returned %d\n\n", ret ); + printf( " failed\n ! x509parse_key_rsa returned %d\n\n", ret ); goto exit; } diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c index 3059236ec..dbb193ba4 100644 --- a/programs/ssl/ssl_server.c +++ b/programs/ssl/ssl_server.c @@ -117,7 +117,7 @@ int main( int argc, char *argv[] ) /* * This demonstration program uses embedded test certificates. * Instead, you may want to use x509parse_crtfile() to read the - * server and CA certificates, as well as x509parse_keyfile(). + * server and CA certificates, as well as x509parse_keyfile_rsa(). */ ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt, strlen( test_srv_crt ) ); @@ -136,11 +136,11 @@ int main( int argc, char *argv[] ) } rsa_init( &rsa, RSA_PKCS_V15, 0 ); - ret = x509parse_key( &rsa, (const unsigned char *) test_srv_key, + ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key, strlen( test_srv_key ), NULL, 0 ); if( ret != 0 ) { - printf( " failed\n ! x509parse_key returned %d\n\n", ret ); + printf( " failed\n ! x509parse_key_rsa returned %d\n\n", ret ); goto exit; } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 6197cda4a..db2d123a2 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -501,11 +501,11 @@ int main( int argc, char *argv[] ) #if defined(POLARSSL_FS_IO) if( strlen( opt.key_file ) ) - ret = x509parse_keyfile( &rsa, opt.key_file, "" ); + ret = x509parse_keyfile_rsa( &rsa, opt.key_file, "" ); else #endif #if defined(POLARSSL_CERTS_C) - ret = x509parse_key( &rsa, (const unsigned char *) test_srv_key, + ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key, strlen( test_srv_key ), NULL, 0 ); #else { @@ -515,7 +515,7 @@ int main( int argc, char *argv[] ) #endif if( ret != 0 ) { - printf( " failed\n ! x509parse_key returned -0x%x\n\n", -ret ); + printf( " failed\n ! x509parse_key_rsa returned -0x%x\n\n", -ret ); goto exit; } diff --git a/programs/test/o_p_test.c b/programs/test/o_p_test.c index 97262825e..84dd38bac 100644 --- a/programs/test/o_p_test.c +++ b/programs/test/o_p_test.c @@ -104,7 +104,7 @@ int main( int argc, char *argv[] ) fflush( stdout ); rsa_init( &p_rsa, RSA_PKCS_V15, 0 ); - if( x509parse_keyfile( &p_rsa, argv[1], NULL ) != 0 ) + if( x509parse_keyfile_rsa( &p_rsa, argv[1], NULL ) != 0 ) { ret = 1; printf( " failed\n ! Could not load key.\n\n" ); diff --git a/programs/test/ssl_cert_test.c b/programs/test/ssl_cert_test.c index 83a2a0123..bf4684b2f 100644 --- a/programs/test/ssl_cert_test.c +++ b/programs/test/ssl_cert_test.c @@ -196,10 +196,10 @@ int main( int argc, char *argv[] ) printf( " . Loading the client private key %s...", name ); fflush( stdout ); - ret = x509parse_keyfile( &rsa, name, NULL ); + ret = x509parse_keyfile_rsa( &rsa, name, NULL ); if( ret != 0 ) { - printf( " failed\n ! x509parse_key returned %d\n\n", ret ); + printf( " failed\n ! x509parse_key_rsa returned %d\n\n", ret ); goto exit; } diff --git a/programs/test/ssl_test.c b/programs/test/ssl_test.c index 607b09250..ce45ccf87 100644 --- a/programs/test/ssl_test.c +++ b/programs/test/ssl_test.c @@ -229,11 +229,11 @@ static int ssl_test( struct options *opt ) goto exit; } - ret = x509parse_key( &rsa, (const unsigned char *) test_srv_key, + ret = x509parse_key_rsa( &rsa, (const unsigned char *) test_srv_key, strlen( test_srv_key ), NULL, 0 ); if( ret != 0 ) { - printf( " ! x509parse_key returned %d\n\n", ret ); + printf( " ! x509parse_key_rsa returned %d\n\n", ret ); goto exit; } #endif diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 20418abb5..cbd62521d 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -267,14 +267,14 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the private key ..." ); fflush( stdout ); - ret = x509parse_keyfile( &rsa, opt.filename, NULL ); + ret = x509parse_keyfile_rsa( &rsa, opt.filename, NULL ); if( ret != 0 ) { #ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); #endif - printf( " failed\n ! x509parse_key returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); rsa_free( &rsa ); goto exit; } diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 570513be4..c82465f88 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -78,113 +78,113 @@ X509 CRL Information SHA512 Digest depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO x509_crl_info:"data_files/crl_sha512.pem":"CRL version \: 1\nissuer name \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update \: 2011-02-12 14\:44\:07\nnext update \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using \: RSA with SHA-512\n" -X509 Parse Key #1 (No password when required) +X509 Parse RSA Key #1 (No password when required) depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/test-ca.key":NULL:POLARSSL_ERR_X509_PASSWORD_REQUIRED +x509parse_keyfile_rsa:"data_files/test-ca.key":NULL:POLARSSL_ERR_X509_PASSWORD_REQUIRED -X509 Parse Key #2 (Correct password) +X509 Parse RSA Key #2 (Correct password) depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/test-ca.key":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/test-ca.key":"PolarSSLTest":0 -X509 Parse Key #3 (Wrong password) +X509 Parse RSA Key #3 (Wrong password) depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/test-ca.key":"PolarSSLWRONG":POLARSSL_ERR_X509_PASSWORD_MISMATCH +x509parse_keyfile_rsa:"data_files/test-ca.key":"PolarSSLWRONG":POLARSSL_ERR_X509_PASSWORD_MISMATCH -X509 Parse Key #4 (DES Encrypted) +X509 Parse RSA Key #4 (DES Encrypted) depends_on:POLARSSL_MD5_C:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/keyfile.des":"testkey":0 +x509parse_keyfile_rsa:"data_files/keyfile.des":"testkey":0 -X509 Parse Key #5 (3DES Encrypted) +X509 Parse RSA Key #5 (3DES Encrypted) depends_on:POLARSSL_MD5_C:POLARSSL_DES_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/keyfile.3des":"testkey":0 +x509parse_keyfile_rsa:"data_files/keyfile.3des":"testkey":0 -X509 Parse Key #6 (AES-128 Encrypted) +X509 Parse RSA Key #6 (AES-128 Encrypted) depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/keyfile.aes128":"testkey":0 +x509parse_keyfile_rsa:"data_files/keyfile.aes128":"testkey":0 -X509 Parse Key #7 (AES-192 Encrypted) +X509 Parse RSA Key #7 (AES-192 Encrypted) depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/keyfile.aes192":"testkey":0 +x509parse_keyfile_rsa:"data_files/keyfile.aes192":"testkey":0 -X509 Parse Key #8 (AES-256 Encrypted) +X509 Parse RSA Key #8 (AES-256 Encrypted) depends_on:POLARSSL_MD5_C:POLARSSL_AES_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/keyfile.aes256":"testkey":0 +x509parse_keyfile_rsa:"data_files/keyfile.aes256":"testkey":0 -X509 Parse Key #9 (PKCS#8 wrapped) +X509 Parse RSA Key #9 (PKCS#8 wrapped) depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_keyfile:"data_files/format_gen.key":"":0 +x509parse_keyfile_rsa:"data_files/format_gen.key":"":0 -X509 Parse Key #10 (PKCS#8 encrypted SHA1-3DES) +X509 Parse RSA Key #10 (PKCS#8 encrypted SHA1-3DES) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTest":0 -X509 Parse Key #10.1 (PKCS#8 encrypted SHA1-3DES, wrong PW) +X509 Parse RSA Key #10.1 (PKCS#8 encrypted SHA1-3DES, wrong PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH -X509 Parse Key #10.2 (PKCS#8 encrypted SHA1-3DES, no PW) +X509 Parse RSA Key #10.2 (PKCS#8 encrypted SHA1-3DES, no PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_3des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED -X509 Parse Key #11 (PKCS#8 encrypted SHA1-3DES DER) +X509 Parse RSA Key #11 (PKCS#8 encrypted SHA1-3DES DER) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_3des.der":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_3des.der":"PolarSSLTest":0 -X509 Parse Key #12 (PKCS#8 encrypted SHA1-2DES) +X509 Parse RSA Key #12 (PKCS#8 encrypted SHA1-2DES) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSSLTest":0 -X509 Parse Key #12.1 (PKCS#8 encrypted SHA1-2DES, wrong PW) +X509 Parse RSA Key #12.1 (PKCS#8 encrypted SHA1-2DES, wrong PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSLTest":POLARSSL_ERR_X509_PASSWORD_MISMATCH +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"PolarSLTest":POLARSSL_ERR_X509_PASSWORD_MISMATCH -X509 Parse Key #12.2 (PKCS#8 encrypted SHA1-2DES, no PW) +X509 Parse RSA Key #12.2 (PKCS#8 encrypted SHA1-2DES, no PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_2des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_2des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED -X509 Parse Key #13 (PKCS#8 encrypted SHA1-RC4-128) +X509 Parse RSA Key #13 (PKCS#8 encrypted SHA1-RC4-128) depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTest":0 -X509 Parse Key #13.1 (PKCS#8 encrypted SHA1-RC4-128, wrong PW) +X509 Parse RSA Key #13.1 (PKCS#8 encrypted SHA1-RC4-128, wrong PW) depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTe":POLARSSL_ERR_X509_PASSWORD_MISMATCH +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"PolarSSLTe":POLARSSL_ERR_X509_PASSWORD_MISMATCH -X509 Parse Key #13.2 (PKCS#8 encrypted SHA1-RC4-128, no PW) +X509 Parse RSA Key #13.2 (PKCS#8 encrypted SHA1-RC4-128, no PW) depends_on:POLARSSL_ARC4_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS12_C -x509parse_keyfile:"data_files/pkcs8_pbe_sha1_rc4_128.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED +x509parse_keyfile_rsa:"data_files/pkcs8_pbe_sha1_rc4_128.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED -X509 Parse Key #14 (PKCS#8 encrypted v2 PBDFK2 3DES) +X509 Parse RSA Key #14 (PKCS#8 encrypted v2 PBDFK2 3DES) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTest":0 -X509 Parse Key #15 (PKCS#8 encrypted v2 PBDFK2 3DES, wrong PW) +X509 Parse RSA Key #15 (PKCS#8 encrypted v2 PBDFK2 3DES, wrong PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH -X509 Parse Key #16 (PKCS#8 encrypted v2 PBDFK2 3DES, no PW) +X509 Parse RSA Key #16 (PKCS#8 encrypted v2 PBDFK2 3DES, no PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.key":"":POLARSSL_ERR_X509_PASSWORD_REQUIRED -X509 Parse Key #17 (PKCS#8 encrypted v2 PBDFK2 3DES DER) +X509 Parse RSA Key #17 (PKCS#8 encrypted v2 PBDFK2 3DES DER) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTest":0 -X509 Parse Key #18 (PKCS#8 encrypted v2 PBDFK2 3DES DER, wrong PW) +X509 Parse RSA Key #18 (PKCS#8 encrypted v2 PBDFK2 3DES DER, wrong PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"PolarSSLTes":POLARSSL_ERR_X509_PASSWORD_MISMATCH -X509 Parse Key #19 (PKCS#8 encrypted v2 PBDFK2 3DES DER, no PW) +X509 Parse RSA Key #19 (PKCS#8 encrypted v2 PBDFK2 3DES DER, no PW) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_3des.der":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT -X509 Parse Key #20 (PKCS#8 encrypted v2 PBDFK2 DES) +X509 Parse RSA Key #20 (PKCS#8 encrypted v2 PBDFK2 DES) depends_on:POLARSSL_DES_C:POLARSSL_SHA1_C:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_PKCS5_C -x509parse_keyfile:"data_files/pkcs8_pbes2_pbkdf2_des.key":"PolarSSLTest":0 +x509parse_keyfile_rsa:"data_files/pkcs8_pbes2_pbkdf2_des.key":"PolarSSLTest":0 -X509 Parse Public Key #1 (PKCS#8 wrapped) +X509 Parse Public RSA Key #1 (PKCS#8 wrapped) depends_on:POLARSSL_MD5_C:POLARSSL_PEM_C:POLARSSL_FS_IO -x509parse_public_keyfile:"data_files/format_gen.pub":0 +x509parse_public_keyfile_rsa:"data_files/format_gen.pub":0 X509 Get Distinguished Name #1 depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO @@ -652,22 +652,22 @@ X509 CRL ASN1 (TBSCertList, no entries) x509parse_crl:"30463031020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030300d06092a864886f70d01010e050003020001":"CRL version \: 1\nissuer name \: CN=ABCD\nthis update \: 2009-01-01 00\:00\:00\nnext update \: 0000-00-00 00\:00\:00\nRevoked certificates\:\nsigned using \: RSA with SHA-224\n":0 X509 Key ASN1 (Incorrect first tag) -x509parse_key:"":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT X509 Key ASN1 (RSAPrivateKey, incorrect version tag) -x509parse_key:"300100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"300100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT X509 Key ASN1 (RSAPrivateKey, version tag missing) -x509parse_key:"3000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"3000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT X509 Key ASN1 (RSAPrivateKey, invalid version) -x509parse_key:"3003020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"3003020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT X509 Key ASN1 (RSAPrivateKey, correct version, incorrect tag) -x509parse_key:"300402010000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"300402010000":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT X509 Key ASN1 (RSAPrivateKey, values present, length mismatch) -x509parse_key:"301c02010002010102010102010102010102010102010102010102010100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"301c02010002010102010102010102010102010102010102010102010100":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT X509 Key ASN1 (RSAPrivateKey, values present, check_privkey fails) -x509parse_key:"301b020100020101020101020101020101020101020101020101020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT +x509parse_key_rsa:"301b020100020101020101020101020101020101020101020101020101":"":POLARSSL_ERR_X509_KEY_INVALID_FORMAT diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 8b69327ff..9b422f0ac 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -138,14 +138,14 @@ x509_time_expired:crt_file:entity:result END_CASE BEGIN_CASE -x509parse_keyfile:key_file:password:result +x509parse_keyfile_rsa:key_file:password:result { rsa_context rsa; int res; memset( &rsa, 0, sizeof( rsa_context ) ); - res = x509parse_keyfile( &rsa, {key_file}, {password} ); + res = x509parse_keyfile_rsa( &rsa, {key_file}, {password} ); TEST_ASSERT( res == {result} ); @@ -159,14 +159,14 @@ x509parse_keyfile:key_file:password:result END_CASE BEGIN_CASE -x509parse_public_keyfile:key_file:result +x509parse_public_keyfile_rsa:key_file:result { rsa_context rsa; int res; memset( &rsa, 0, sizeof( rsa_context ) ); - res = x509parse_public_keyfile( &rsa, {key_file} ); + res = x509parse_public_keyfile_rsa( &rsa, {key_file} ); TEST_ASSERT( res == {result} ); @@ -238,7 +238,7 @@ x509parse_crl:crl_data:result_str:result END_CASE BEGIN_CASE -x509parse_key:key_data:result_str:result +x509parse_key_rsa:key_data:result_str:result { rsa_context rsa; unsigned char buf[2000]; @@ -251,7 +251,7 @@ x509parse_key:key_data:result_str:result data_len = unhexify( buf, {key_data} ); - TEST_ASSERT( x509parse_key( &rsa, buf, data_len, NULL, 0 ) == ( {result} ) ); + TEST_ASSERT( x509parse_key_rsa( &rsa, buf, data_len, NULL, 0 ) == ( {result} ) ); if( ( {result} ) == 0 ) { TEST_ASSERT( 1 ); diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 8ce3e712f..e3bf12f72 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -41,7 +41,7 @@ x509_cert_req_check:key_file:md_type:cert_req_check_file strcpy( cur->name, "NL" ); memset( &rsa, 0, sizeof(rsa_context) ); - ret = x509parse_keyfile( &rsa, {key_file}, NULL ); + ret = x509parse_keyfile_rsa( &rsa, {key_file}, NULL ); TEST_ASSERT( ret == 0 ); if( ret != 0 ) return 0; From 4250a1f8185766086bc6c5d13a1e472bca88462c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Jun 2013 13:00:00 +0200 Subject: [PATCH 06/33] Fix a comment and some whitespace --- library/x509parse.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 7c7ee29fb..935147bfd 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -1817,7 +1817,7 @@ int x509parse_crtfile( x509_cert *chain, const char *path ) size_t n; unsigned char *buf; - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = x509parse_crt( chain, buf, n ); @@ -1931,7 +1931,7 @@ int x509parse_crlfile( x509_crl *chain, const char *path ) size_t n; unsigned char *buf; - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = x509parse_crl( chain, buf, n ); @@ -1951,7 +1951,7 @@ int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *pwd ) size_t n; unsigned char *buf; - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); if( pwd == NULL ) @@ -1975,7 +1975,7 @@ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ) size_t n; unsigned char *buf; - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = x509parse_public_key_rsa( rsa, buf, n ); @@ -2541,7 +2541,7 @@ int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen #if defined(POLARSSL_FS_IO) /* - * Load and parse a private RSA key + * Load and parse DHM parameters */ int x509parse_dhmfile( dhm_context *dhm, const char *path ) { From 26833c2fc69caee58acdb6b59ebb308a3a890804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Jun 2013 11:27:58 +0200 Subject: [PATCH 07/33] Add stubs for x509parse_key_ec and co. --- include/polarssl/x509.h | 54 ++++++++++++ library/x509parse.c | 182 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index d7f144387..9f4fc9f8a 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -32,6 +32,7 @@ #if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C) #include "asn1.h" #include "rsa.h" +#include "ecp.h" #include "dhm.h" #include "md.h" #include "pk.h" @@ -468,6 +469,59 @@ int x509parse_public_key_rsa( rsa_context *rsa, */ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ); +/** \ingroup x509_module */ +/** + * \brief Parse a private EC key + * + * \param eckey EC key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509parse_key_ec( ecp_keypair *eckey, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup x509_module */ +/** + * \brief Load and parse a private EC key + * + * \param eckey EC key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509parse_keyfile_ec( ecp_keypair *eckey, + const char *path, const char *password ); + +/** \ingroup x509_module */ +/** + * \brief Parse a public EC key + * + * \param eckey EC key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509parse_public_key_ec( ecp_keypair *eckey, + const unsigned char *key, size_t keylen ); + +/** \ingroup x509_module */ +/** + * \brief Load and parse a public EC key + * + * \param eckey EC key to be initialized + * \param path filename to read the private key from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509parse_public_keyfile_ec( ecp_keypair *eckey, const char *path ); + /** \ingroup x509_module */ /** * \brief Parse DHM parameters diff --git a/library/x509parse.c b/library/x509parse.c index 935147bfd..adbc75a9d 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -1985,6 +1985,53 @@ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ) return( ret ); } + +#if defined(POLARSSL_ECP_C) +/* + * Load and parse a private EC key + */ +int x509parse_keyfile_ec( ecp_keypair *eckey, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = x509parse_key_ec( eckey, buf, n, NULL, 0 ); + else + ret = x509parse_key_ec( eckey, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + memset( buf, 0, n + 1 ); + free( buf ); + + return( ret ); +} + +/* + * Load and parse a public EC key + */ +int x509parse_public_keyfile_ec( ecp_keypair *eckey, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509parse_public_key_ec( eckey, buf, n ); + + memset( buf, 0, n + 1 ); + free( buf ); + + return( ret ); +} +#endif /* defined(POLARSSL_ECP_C) */ #endif /* POLARSSL_FS_IO */ /* @@ -2455,6 +2502,141 @@ int x509parse_public_key_rsa( rsa_context *rsa, return( 0 ); } +#if defined(POLARSSL_ECP_C) +/* + * Parse a private EC key + */ +int x509parse_key_ec( ecp_keypair *eckey, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + +#if defined(POLARSSL_PEM_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + /* TODO: get list of correct PEM headers */ + ret = pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + /* TODO: write der decoding function + if( ( ret = x509parse_key_pkcs8_encrypted_der( eckey, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + ecp_keypair_free( eckey ); + } + */ + + 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 ); + + /* TODO: now repeat with other valid PEM headers */ + +#else + ((void) pwd); + ((void) pwdlen); +#endif /* POLARSSL_PEM_C */ + + ((void) keylen); + /* TODO: write der decoding functions (encrypted, unencnrypted) + if( ( ret = x509parse_key_pkcs8_encrypted_der( eckey, key, keylen, + pwd, pwdlen ) ) == 0 ) + { + return( 0 ); + } + + ecp_keypair_free( eckey ); + + if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH ) + { + return( ret ); + } + + if( ( ret = x509parse_key_pkcs8_unencrypted_der( eckey, key, keylen ) ) + == 0 ) + { + return( 0 ); + } + */ + + ecp_keypair_free( eckey ); + + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public EC key + */ +int x509parse_public_key_ec( ecp_keypair *eckey, + const unsigned char *key, size_t keylen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + x509_buf alg_oid; +#if defined(POLARSSL_PEM_C) + pem_context pem; + + pem_init( &pem ); + ret = pem_read_buffer( &pem, /* TODO: check header */ + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + keylen = pem.buflen; + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) key; +#else + p = (unsigned char *) key; +#endif + end = p + keylen; + + /* TODO: parse key */ + (void) alg_oid; + (void) end; + (void) eckey; + + if( ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 ) + { +#if defined(POLARSSL_PEM_C) + pem_free( &pem ); +#endif + ecp_keypair_free( eckey ); + return( ret ); + } + +#if defined(POLARSSL_PEM_C) + pem_free( &pem ); +#endif + + return( 0 ); +} +#endif /* defined(POLARSSL_ECP_C) */ + #if defined(POLARSSL_DHM_C) /* * Parse DHM parameters From 1bc6931f8c07626350749628cb27fa9dfd6f843e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Jun 2013 15:33:04 +0200 Subject: [PATCH 08/33] Add test for x509parse_public_keyfile_ec --- tests/data_files/ec_pub.der | Bin 0 -> 80 bytes tests/data_files/ec_pub.pem | 4 ++++ tests/suites/test_suite_x509parse.data | 8 ++++++++ tests/suites/test_suite_x509parse.function | 21 +++++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 tests/data_files/ec_pub.der create mode 100644 tests/data_files/ec_pub.pem diff --git a/tests/data_files/ec_pub.der b/tests/data_files/ec_pub.der new file mode 100644 index 0000000000000000000000000000000000000000..954bf3b29f43091f52625b01d9f8b40ac774b1dd GIT binary patch literal 80 zcmV-W0I&ZrPB0J#2P%e0&OHJF1_djD1OOoeIsgQ3af+$uKqqhY2^V3EgkeDMxO%eq m^l3;!uwd=_%38NNX1U{mcpV Date: Mon, 1 Jul 2013 15:27:48 +0200 Subject: [PATCH 09/33] Optionally allow parameters in x509_get_tag() --- library/x509parse.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index adbc75a9d..b51881a9a 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -164,16 +164,40 @@ static int x509_get_serial( unsigned char **p, * 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 ) + x509_buf *alg, const unsigned char **params_end ) { int ret; + size_t len; - if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 ) + 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 ) return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); + alg->p = *p; + *p += alg->len; + + *params_end = end; return( 0 ); } @@ -1146,9 +1170,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 ) ) != 0 ) + 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 ) { x509_free( crt ); return( ret ); @@ -1300,7 +1324,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 ) ) != 0 ) + if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2, NULL ) ) != 0 ) { x509_free( crt ); return( ret ); @@ -1623,7 +1647,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 ) ) != 0 ) + ( ret = x509_get_alg( &p, end, &crl->sig_oid1, NULL ) ) != 0 ) { x509_crl_free( crl ); return( ret ); @@ -1728,7 +1752,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 ) ) != 0 ) + if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, NULL ) ) != 0 ) { x509_crl_free( crl ); return( ret ); From dffba8f63eb833c4c7347a62042237203da80f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 1 Jul 2013 17:33:31 +0200 Subject: [PATCH 10/33] Fix bug in oid_get_numeric_string() Overflow check was done too early, causing many false positives. --- library/oid.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/oid.c b/library/oid.c index 5cd9a5990..2de7806d2 100644 --- a/library/oid.c +++ b/library/oid.c @@ -33,6 +33,7 @@ #include "polarssl/rsa.h" #include +#include /* * Macro to generate an internal function for oid_XXX_from_asn1() (used by @@ -521,13 +522,13 @@ int oid_get_numeric_string( char *buf, size_t size, SAFE_SNPRINTF(); } - /* Prevent overflow in value. */ - if( oid->len > sizeof(value) ) - return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); - value = 0; for( i = 1; i < oid->len; i++ ) { + /* Prevent overflow in value. */ + if (value > (UINT_MAX >> 7) ) + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); + value <<= 7; value += oid->p[i] & 0x7F; From 5a9b82e2347f002e32cd16ddd905874f79d23469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 1 Jul 2013 16:57:44 +0200 Subject: [PATCH 11/33] Make oid_get_pk_alg handle EC algorithms --- include/polarssl/oid.h | 18 ++++++++++++++++++ include/polarssl/pk.h | 2 ++ include/polarssl/x509.h | 2 +- library/oid.c | 10 +++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index e63c169a6..d9a1f8f79 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -61,6 +61,9 @@ #define OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ #define OID_RSA_COMPANY OID_ISO_MEMBER_BODIES OID_COUNTRY_US \ OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define OID_ANSI_X9_62 OID_ISO_MEMBER_BODIES OID_COUNTRY_US \ + OID_ORG_ANSI_X9_62 /* * ISO Identified organization OID parts @@ -70,6 +73,8 @@ #define OID_OIW_SECSIG OID_ORG_OIW "\x03" #define OID_OIW_SECSIG_ALG OID_OIW_SECSIG "\x02" #define OID_OIW_SECSIG_SHA1 OID_OIW_SECSIG_ALG "\x1a" +#define OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define OID_CERTICOM OID_ISO_IDENTIFIED_ORG OID_ORG_CERTICOM /* * ISO ITU OID parts @@ -235,6 +240,19 @@ #define OID_PKCS12_PBE_SHA1_RC2_128_CBC OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ #define OID_PKCS12_PBE_SHA1_RC2_40_CBC OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ +/* + * EC key algorithms from RFC 5420 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define OID_EC_ALG_UNRESTRICTED OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define OID_EC_ALG_ECDH OID_CERTICOM "\x01\x0c" + #ifdef __cplusplus extern "C" { #endif diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index d9639eeed..169753de4 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -38,6 +38,8 @@ typedef enum { POLARSSL_PK_NONE=0, POLARSSL_PK_RSA, POLARSSL_PK_ECDSA, + POLARSSL_PK_ECKEY, + POLARSSL_PK_ECKEY_DH, } pk_type_t; #ifdef __cplusplus diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 9f4fc9f8a..62c8a931c 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -59,7 +59,7 @@ #define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x2580 /**< The extension tag or value is invalid. */ #define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x2600 /**< Certificate or CRL has an unsupported version number. */ #define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x2680 /**< Signature algorithm (oid) is unsupported. */ -#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG -0x2700 /**< Key algorithm is unsupported (only RSA is supported). */ +#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG -0x2700 /**< Key algorithm is unsupported (only RSA and EC are supported). */ #define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x2780 /**< Certificate signature algorithms do not match. (see \c ::x509_cert sig_oid) */ #define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x2800 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ #define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x2880 /**< Unsupported RSA key version */ diff --git a/library/oid.c b/library/oid.c index 2de7806d2..3f7857d0a 100644 --- a/library/oid.c +++ b/library/oid.c @@ -313,7 +313,7 @@ FN_OID_GET_OID_BY_ATTR2(oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, pk_t #endif /* POLARSSL_MD_C */ /* - * For PublicKeyInfo + * For PublicKeyInfo (PKCS1, RFC 5480) */ typedef struct { oid_descriptor_t descriptor; @@ -326,6 +326,14 @@ static const oid_pk_alg_t oid_pk_alg[] = { OID_PKCS1_RSA, "rsaEncryption", "RSA" }, POLARSSL_PK_RSA, }, + { + { OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key" }, + POLARSSL_PK_ECKEY, + }, + { + { OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH" }, + POLARSSL_PK_ECKEY_DH, + }, { { NULL, NULL, NULL }, 0, From f0b30d05421af91d1348207c80d6f07802a40704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 1 Jul 2013 17:34:57 +0200 Subject: [PATCH 12/33] Add oid_get_ec_grp() and associated data --- include/polarssl/oid.h | 37 +++++++++++++++++++++++++++++++++++-- library/oid.c | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index d9a1f8f79..a39055b06 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -31,7 +31,6 @@ #include "config.h" #include "asn1.h" #include "pk.h" - #if defined(POLARSSL_CIPHER_C) #include "cipher.h" #endif @@ -241,7 +240,7 @@ #define OID_PKCS12_PBE_SHA1_RC2_40_CBC OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ /* - * EC key algorithms from RFC 5420 + * EC key algorithms from RFC 5480 */ /* id-ecPublicKey OBJECT IDENTIFIER ::= { @@ -253,6 +252,30 @@ * schemes(1) ecdh(12) } */ #define OID_EC_ALG_ECDH OID_CERTICOM "\x01\x0c" +/* + * ECParameters namedCurve identifiers, from RFC 5480 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define OID_EC_GRP_SECP192R1 OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define OID_EC_GRP_SECP224R1 OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define OID_EC_GRP_SECP256R1 OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define OID_EC_GRP_SECP384R1 OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define OID_EC_GRP_SECP521R1 OID_CERTICOM "\x00\x23" + #ifdef __cplusplus extern "C" { #endif @@ -311,6 +334,16 @@ int oid_get_attr_short_name( const asn1_buf *oid, const char **short_name ); */ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); +/** + * \brief Translate ECParameters OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id ); + #if defined(POLARSSL_MD_C) /** * \brief Translate SignatureAlgorithm OID into md_type and pk_type diff --git a/library/oid.c b/library/oid.c index 3f7857d0a..dd4cbf037 100644 --- a/library/oid.c +++ b/library/oid.c @@ -249,7 +249,6 @@ static const oid_descriptor_t oid_ext_key_usage[] = FN_OID_TYPED_FROM_ASN1(oid_descriptor_t, ext_key_usage, oid_ext_key_usage); FN_OID_GET_ATTR1(oid_get_extended_key_usage, oid_descriptor_t, ext_key_usage, const char *, description); - #endif /* POLARSSL_X509_PARSE_C || POLARSSL_X509_WRITE_C */ #if defined(POLARSSL_MD_C) @@ -343,6 +342,45 @@ static const oid_pk_alg_t oid_pk_alg[] = FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg); FN_OID_GET_ATTR1(oid_get_pk_alg, oid_pk_alg_t, pk_alg, pk_type_t, pk_alg); +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + oid_descriptor_t descriptor; + ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ + { + { OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1" }, + POLARSSL_ECP_DP_SECP192R1, + }, + { + { OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1" }, + POLARSSL_ECP_DP_SECP224R1, + }, + { + { OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1" }, + POLARSSL_ECP_DP_SECP256R1, + }, + { + { OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1" }, + POLARSSL_ECP_DP_SECP384R1, + }, + { + { OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1" }, + POLARSSL_ECP_DP_SECP521R1, + }, + { + { NULL, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp); +FN_OID_GET_ATTR1(oid_get_ec_grp, oid_ecp_grp_t, grp_id, ecp_group_id, grp_id); + #if defined(POLARSSL_CIPHER_C) /* * For PKCS#5 PBES2 encryption algorithm From f838eeda09778ec51fbc002b62f5881f0795dcb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 2 Jul 2013 14:56:43 +0200 Subject: [PATCH 13/33] Add x509_get_ecparams() --- include/polarssl/x509.h | 1 + library/x509parse.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 62c8a931c..240b9bbba 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -70,6 +70,7 @@ #define POLARSSL_ERR_X509_FILE_IO_ERROR -0x2B00 /**< Read/write of file failed. */ #define POLARSSL_ERR_X509_PASSWORD_REQUIRED -0x2B80 /**< Private key password can't be empty. */ #define POLARSSL_ERR_X509_PASSWORD_MISMATCH -0x2C00 /**< Given private key password does not allow for correct decryption. */ +#define POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE -0x2C80 /**< Elliptic curve is unsupported (only NIST curves are supported). */ /* \} name */ /** diff --git a/library/x509parse.c b/library/x509parse.c index b51881a9a..840319f43 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -201,6 +201,38 @@ 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_get_ecparams( unsigned char **p, const unsigned char *end, + ecp_group_id *grp_id ) +{ + int ret; + x509_buf curve; + + curve.tag = **p; + + if( ( ret = asn1_get_tag( p, end, &curve.len, ASN1_OID ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + curve.p = *p; + *p += curve.len; + + if( *p != end ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = oid_get_ec_grp( &curve, grp_id ) ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE ); + + return( 0 ); +} + /* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, From 73c0cda34638f48cc9f052be2b354898f3ded252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 1 Jul 2013 19:45:45 +0200 Subject: [PATCH 14/33] Complete x509parse_public_key_ec() Warning: due to a bug in oid_descriptor_from_buf(), keys associated to some curves (secp224r1, secp384r1, secp521r1) are incorrectly rejected, since their namedCurve OID contains a nul byte. --- library/x509parse.c | 113 +++++++++++++++++++++++++++++------- tests/data_files/ec_pub.der | Bin 80 -> 75 bytes tests/data_files/ec_pub.pem | 4 +- 3 files changed, 95 insertions(+), 22 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 840319f43..e04d56b0e 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -233,6 +233,40 @@ static int x509_get_ecparams( unsigned char **p, const unsigned char *end, 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 ); + + /* + * 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( ( ret = ecp_point_read_binary( grp, pt, + (const unsigned char *) *p, len ) ) != 0 ) + { + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + return( 0 ); +} + /* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, @@ -2633,6 +2667,59 @@ int x509parse_key_ec( ecp_keypair *eckey, 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_oid; + pk_type_t alg = POLARSSL_PK_NONE; + unsigned char *p = (unsigned char *) buf; + unsigned char *end = p + len; + const unsigned char *params_end; + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * -- algorithm parameters are ECParameters + * -- subjectPublicKey is an ECPoint + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_alg( &p, end, &alg_oid, ¶ms_end ) ) != 0 ) + return( ret ); + + if( oid_get_pk_alg( &alg_oid, &alg ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + + if( alg != POLARSSL_PK_ECKEY && alg != POLARSSL_PK_ECKEY_DH ) + return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + + if ( alg == POLARSSL_PK_ECKEY_DH ) + key->alg = POLARSSL_ECP_KEY_ALG_ECDH; + + if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 ) + return( ret ); + + if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_subpubkey_ec( &p, end, &key->grp, &key->Q ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + /* * Parse a public EC key */ @@ -2640,14 +2727,12 @@ int x509parse_public_key_ec( ecp_keypair *eckey, const unsigned char *key, size_t keylen ) { int ret; - size_t len; - unsigned char *p, *end; - x509_buf alg_oid; #if defined(POLARSSL_PEM_C) + size_t len; pem_context pem; pem_init( &pem ); - ret = pem_read_buffer( &pem, /* TODO: check header */ + ret = pem_read_buffer( &pem, "-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----", key, NULL, 0, &len ); @@ -2657,6 +2742,7 @@ int x509parse_public_key_ec( ecp_keypair *eckey, /* * Was PEM encoded */ + key = pem.buf; keylen = pem.buflen; } else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) @@ -2664,32 +2750,19 @@ int x509parse_public_key_ec( ecp_keypair *eckey, pem_free( &pem ); return( ret ); } - - p = ( ret == 0 ) ? pem.buf : (unsigned char *) key; -#else - p = (unsigned char *) key; #endif - end = p + keylen; - /* TODO: parse key */ - (void) alg_oid; - (void) end; - (void) eckey; - - if( ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 ) + if( ( ret = x509parse_public_key_ec_der ( eckey, key, keylen ) ) != 0 || + ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 ) { -#if defined(POLARSSL_PEM_C) - pem_free( &pem ); -#endif ecp_keypair_free( eckey ); - return( ret ); } #if defined(POLARSSL_PEM_C) pem_free( &pem ); #endif - return( 0 ); + return( ret ); } #endif /* defined(POLARSSL_ECP_C) */ diff --git a/tests/data_files/ec_pub.der b/tests/data_files/ec_pub.der index 954bf3b29f43091f52625b01d9f8b40ac774b1dd..74c5951f60c2c13c29369f85c95958c4af70dc3c 100644 GIT binary patch literal 75 zcmXr;G!SNE*J|@PXUoLM#sOw9Gcqz8F|h2Ztlhk>p5u+JXSV+q!Oh Date: Wed, 3 Jul 2013 11:56:37 +0200 Subject: [PATCH 15/33] Fill in x509parse_key_ec using stub function --- library/x509parse.c | 162 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 134 insertions(+), 28 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index e04d56b0e..decac2697 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2468,12 +2468,13 @@ int x509parse_key_rsa( rsa_context *rsa, ((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 - // + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ if( ( ret = x509parse_key_pkcs8_encrypted_der( rsa, key, keylen, pwd, pwdlen ) ) == 0 ) { @@ -2593,12 +2594,81 @@ int x509parse_public_key_rsa( rsa_context *rsa, } #if defined(POLARSSL_ECP_C) +/* + * Parse an unencrypted PKCS#8 encoded private EC key + */ +static int x509parse_key_pkcs8_unencrypted_der_ec( + ecp_keypair *eck, + const unsigned char* key, + size_t keylen ) +{ + int ret; + + (void) key; + (void) keylen; + + if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) == 0 ) + return 0; + +cleanup: + ecp_keypair_free( eck ); + + return( ret ); +} + +/* + * Parse an encrypted PKCS#8 encoded private EC key + */ +static int x509parse_key_pkcs8_encrypted_der_ec( + ecp_keypair *eck, + const unsigned char *key, + size_t keylen, + const unsigned char *pwd, + size_t pwdlen ) +{ + int ret; + + (void) key; + (void) keylen; + (void) pwd; + (void) pwdlen; + + if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) == 0 ) + return 0; + +cleanup: + ecp_keypair_free( eck ); + + return( ret ); +} + +/* + * Parse a PKCS#1 encoded private EC key + */ +static int x509parse_key_sec1_der( ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + + (void) key; + (void) keylen; + + if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) == 0 ) + return 0; + +cleanup: + ecp_keypair_free( eck ); + + return( ret ); +} + /* * Parse a private EC key */ -int x509parse_key_ec( ecp_keypair *eckey, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) +int x509parse_key_ec( ecp_keypair *eck, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { int ret; @@ -2607,21 +2677,16 @@ int x509parse_key_ec( ecp_keypair *eckey, pem_context pem; pem_init( &pem ); - /* TODO: get list of correct PEM headers */ ret = pem_read_buffer( &pem, "-----BEGIN EC PRIVATE KEY-----", "-----END EC PRIVATE KEY-----", key, pwd, pwdlen, &len ); if( ret == 0 ) { - /* TODO: write der decoding function - if( ( ret = x509parse_key_pkcs8_encrypted_der( eckey, - pem.buf, pem.buflen, - pwd, pwdlen ) ) != 0 ) + if( ( ret = x509parse_key_sec1_der( eck, pem.buf, pem.buflen ) ) != 0 ) { - ecp_keypair_free( eckey ); + ecp_keypair_free( eck ); } - */ pem_free( &pem ); return( ret ); @@ -2633,36 +2698,77 @@ int x509parse_key_ec( ecp_keypair *eckey, else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); - /* TODO: now repeat with other valid PEM headers */ + 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_ec( eck, + pem.buf, pem.buflen ) ) != 0 ) + { + ecp_keypair_free( eck ); + } + 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_ec( eck, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + ecp_keypair_free( eck ); + } + + 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 */ - ((void) keylen); - /* TODO: write der decoding functions (encrypted, unencnrypted) - if( ( ret = x509parse_key_pkcs8_encrypted_der( eckey, key, keylen, - pwd, pwdlen ) ) == 0 ) + /* + * 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_ec( eck, key, keylen, + pwd, pwdlen ) ) == 0 ) { return( 0 ); } - ecp_keypair_free( eckey ); + ecp_keypair_free( eck ); if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH ) { return( ret ); } - if( ( ret = x509parse_key_pkcs8_unencrypted_der( eckey, key, keylen ) ) - == 0 ) - { + if( ( ret = x509parse_key_pkcs8_unencrypted_der_ec( eck, + key, keylen ) ) == 0 ) return( 0 ); - } - */ - ecp_keypair_free( eckey ); + ecp_keypair_free( eck ); + + if( ( ret = x509parse_key_sec1_der( eck, key, keylen ) ) == 0 ) + return( 0 ); + + ecp_keypair_free( eck ); return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); } From 2b9252cd8f3d480ab3f0fa756aed47d39f7ba7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 3 Jul 2013 12:13:56 +0200 Subject: [PATCH 16/33] Add tests for x509parse_key_ec() Test files were generated as follows: openssl ecparam -name prime192v1 -genkey > key.pem openssl ec -in key.pem -pubout -outform PEM > pub.pem openssl ec -in key.pem -pubout -outform DER > pub.der openssl ec -in key.pem -outform pem > prv.sec1.pem openssl ec -in key.pem -outform der > prv.sec1.der openssl ec -in key.pem -des -passout pass:polar -outform pem > prv.sec1.pw.pem openssl pkcs8 -topk8 -in key.pem -nocrypt -outform pem > prv.pk8.pem openssl pkcs8 -topk8 -in key.pem -nocrypt -outform der > prv.pk8.der openssl pkcs8 -topk8 -in key.pem -passout pass:polar -outform der \ > prv.pk8.pw.der openssl pkcs8 -topk8 -in key.pem -passout pass:polar -outform pem \ > prv.pk8.pw.pem --- tests/data_files/ec_prv.pk8.der | Bin 0 -> 113 bytes tests/data_files/ec_prv.pk8.pem | 5 ++++ tests/data_files/ec_prv.pk8.pw.der | Bin 0 -> 154 bytes tests/data_files/ec_prv.pk8.pw.pem | 6 +++++ tests/data_files/ec_prv.sec1.der | Bin 0 -> 97 bytes tests/data_files/ec_prv.sec1.pem | 5 ++++ tests/data_files/ec_prv.sec1.pw.pem | 8 ++++++ tests/suites/test_suite_x509parse.data | 28 +++++++++++++++++++++ tests/suites/test_suite_x509parse.function | 21 ++++++++++++++++ 9 files changed, 73 insertions(+) create mode 100644 tests/data_files/ec_prv.pk8.der create mode 100644 tests/data_files/ec_prv.pk8.pem create mode 100644 tests/data_files/ec_prv.pk8.pw.der create mode 100644 tests/data_files/ec_prv.pk8.pw.pem create mode 100644 tests/data_files/ec_prv.sec1.der create mode 100644 tests/data_files/ec_prv.sec1.pem create mode 100644 tests/data_files/ec_prv.sec1.pw.pem diff --git a/tests/data_files/ec_prv.pk8.der b/tests/data_files/ec_prv.pk8.der new file mode 100644 index 0000000000000000000000000000000000000000..f2bd2a9271ffd2601625ab95996180139b18b5b3 GIT binary patch literal 113 zcmXrWXJTY95N2c7YV$Z}%f!gW0cJ2WGO~mk1Tz6C3FE%D6^)N9zIyJ>XASoBE`EGX z(BSW}ler5`n2i`%0!#PYH&|Tod2aCJXF^3CHyG2me%Z3U>{!Y7W1mB|Us7Syk?*IS* literal 0 HcmV?d00001 diff --git a/tests/data_files/ec_prv.pk8.pem b/tests/data_files/ec_prv.pk8.pem new file mode 100644 index 000000000..dbeab7c2f --- /dev/null +++ b/tests/data_files/ec_prv.pk8.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBgzjoaogeI49Um9bwVT +SUtz49YRMP3GyW2hNAMyAARRdbzfMKNw851Tk+YScojYAWe19LS3dsZ098bzVLfS +JAYsH2hUtaevD+V46vJY8Cc= +-----END PRIVATE KEY----- diff --git a/tests/data_files/ec_prv.pk8.pw.der b/tests/data_files/ec_prv.pk8.pw.der new file mode 100644 index 0000000000000000000000000000000000000000..efcd809ab35e77ac406ba51efaf9b63353679f97 GIT binary patch literal 154 zcmV;L0A>F$ftN5F1_>&LNQU5$Zk+N00tf&Ec+#97{g|(I5l0|{ zyBiBVy|MkoobG;Ew0OHu32#4nbX3cP6Ig(S4CuKX%z>5HUK>cW;;H}|-t9#)hxi3r zEn{}y9_S$cazhjHd!n%W{+IQq!FfBZgnR8KYK#PF>`}L}^IenZyt$Vf0iY7vvIJs7 IValeP+&SDv^#A|> literal 0 HcmV?d00001 diff --git a/tests/data_files/ec_prv.pk8.pw.pem b/tests/data_files/ec_prv.pk8.pw.pem new file mode 100644 index 000000000..0b50cd7b0 --- /dev/null +++ b/tests/data_files/ec_prv.pk8.pw.pem @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGXMBsGCSqGSIb3DQEFAzAOBAiO5a+OuKjOdwICCAAEeGEBv8oxHZy3GvR28QHJ +Xq1Fq/UZrWklH6RI8VTx4WS6UK88PzJSmLMxO3pl4L/CUNfJ4RI9+YHFRZyf8Tcr +5di4xMQaEqh08PXwyErqOerBGc9DsFpcpFAsn6Sa9KLG5aritGrSkPyDACloHyKR +lJyTE6fTVwG5xQ== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/data_files/ec_prv.sec1.der b/tests/data_files/ec_prv.sec1.der new file mode 100644 index 0000000000000000000000000000000000000000..fe336b71055afccfda17798c806c7b94a5cabbea GIT binary patch literal 97 zcmV-n0G|IaUjhLE1Q;`phNyw!IQ2=rZv|6HOLODa5itG6$!(wt1_&yKNX|V20Rf>j z12O;vQFXlEFr#quol}$M5^{*x0cW-Jw6}J~boa*dRJYP31}quXE DZeJ@@ literal 0 HcmV?d00001 diff --git a/tests/data_files/ec_prv.sec1.pem b/tests/data_files/ec_prv.sec1.pem new file mode 100644 index 000000000..a8a7990fd --- /dev/null +++ b/tests/data_files/ec_prv.sec1.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MF8CAQEEGDOOhqiB4jj1Sb1vBVNJS3Pj1hEw/cbJbaAKBggqhkjOPQMBAaE0AzIA +BFF1vN8wo3DznVOT5hJyiNgBZ7X0tLd2xnT3xvNUt9IkBiwfaFS1p68P5Xjq8ljw +Jw== +-----END EC PRIVATE KEY----- diff --git a/tests/data_files/ec_prv.sec1.pw.pem b/tests/data_files/ec_prv.sec1.pw.pem new file mode 100644 index 000000000..62a0860bd --- /dev/null +++ b/tests/data_files/ec_prv.sec1.pw.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,AA94892A169FA426 + +gSkFuUENNke5MvkWHc11/w1NQWBxaIxGT+d5oRcqs44D3tltVOwtdnYexoD9uSIL +wMFFRLL6I5ii1Naa38nPOMaa7kLU2J3jY8SeIH1rQ43X6tlpv9WFGqDn/m6X7oKo +RMMfGdicPZg= +-----END EC PRIVATE KEY----- diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 824d92828..def0021d4 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -194,6 +194,34 @@ X509 Parse Public EC Key #2 (RFC 5480, PEM) depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C: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 +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 +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 +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 +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 +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 +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 +x509parse_keyfile_ec:"data_files/ec_prv.pk8.pw.pem":"polar":0 + X509 Get Distinguished Name #1 depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO x509_dn_gets:"data_files/server1.crt":subject:"C=NL, O=PolarSSL, CN=PolarSSL Server 1" diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index ebb534a50..57653f798 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -200,6 +200,27 @@ x509parse_public_keyfile_ec:key_file:result } END_CASE +BEGIN_CASE +x509parse_keyfile_ec:key_file:password:result +{ + ecp_keypair eckey; + int res; + + ecp_keypair_init( &eckey ); + + res = x509parse_keyfile_ec( &eckey, {key_file}, {password} ); + + TEST_ASSERT( res == {result} ); + + if( res == 0 ) + { + TEST_ASSERT( ecp_check_prvkey( &eckey.grp, &eckey.d ) == 0 ); + } + + ecp_keypair_free( &eckey ); +} +END_CASE + BEGIN_CASE x509parse_crt:crt_data:result_str:result { From e36634223384257e243cbeeaa1be011873948e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 3 Jul 2013 18:56:37 +0200 Subject: [PATCH 17/33] Implement x509parse_key_sec1_der() --- library/x509parse.c | 103 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index decac2697..20c86071b 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2169,7 +2169,7 @@ static int x509parse_key_pkcs1_der( rsa_context *rsa, if( rsa->ver != 0 ) { - return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); + return( POLARSSL_ERR_X509_KEY_INVALID_VERSION ); } if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || @@ -2643,24 +2643,109 @@ cleanup: } /* - * Parse a PKCS#1 encoded private EC key + * Parse a SEC1 encoded private EC key */ static int x509parse_key_sec1_der( ecp_keypair *eck, const unsigned char *key, size_t keylen ) { int ret; + int version; + size_t len; + ecp_group_id grp_id; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; - (void) key; - (void) keylen; + /* + * RFC 5915, orf SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } - if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) == 0 ) - return 0; + end = p + len; -cleanup: - ecp_keypair_free( eck ); + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - return( ret ); + if( version != 1 ) + return( POLARSSL_ERR_X509_KEY_INVALID_VERSION ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* + * Is 'parameters' present? + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = x509_get_ecparams( &p, p + len, &grp_id) ) != 0 ) + return( ret ); + + /* TODO: grp may not be empty at this point, + * if we're wrapped inside a PKCS#8 structure: check consistency */ + if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + } + else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + /* + * Is 'publickey' present? + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + if( ( ret = x509_get_subpubkey_ec( &p, p + len, &eck->grp, &eck->Q ) ) + != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = ecp_check_pubkey( &eck->grp, &eck->Q ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + } + else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return 0; } /* From f8648d51b13efff1d829efe84f590ea3ea3159b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 3 Jul 2013 21:01:35 +0200 Subject: [PATCH 18/33] Fix undocumented feature of pem_read_buffer() Used to work only for RSAPrivateKey content, now accepts ECPrivateKey too, and may even work with similar enough structures when they appear. --- include/polarssl/pem.h | 3 +++ library/pem.c | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/polarssl/pem.h b/include/polarssl/pem.h index 969faa283..782b235d9 100644 --- a/include/polarssl/pem.h +++ b/include/polarssl/pem.h @@ -84,6 +84,9 @@ void pem_init( pem_context *ctx ); * POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is * the length to skip) * + * \note Checks password correctness by verifying if the decrypted + * text looks like a RSAPrivateKey or ECPrivateKey structure + * * \return 0 on success, ior a specific PEM error code */ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, diff --git a/library/pem.c b/library/pem.c index c4c5cb441..3e3e96df3 100644 --- a/library/pem.c +++ b/library/pem.c @@ -332,8 +332,22 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); #endif /* POLARSSL_AES_C */ - if( buf[0] != 0x30 || buf[1] != 0x82 || - buf[4] != 0x02 || buf[5] != 0x01 ) + /* + * The result should look like RSAPrivateKey or ECPrivateKey + * We use the following heuristic: + * len must be more than 6 + * byte 1 must be 0x30 (SEQUENCE tag) + * then allow for one to 3 length bytes + * then we must have 0x02 0x01 (INTEGER tag + length, for version) + * version must be less than 4 (leaves some room) + */ + if( ! ( len > 6 && buf[0] == 0x30 && ( + ( buf[1] <= 0x7f && /* 1 length byte */ + buf[2] == 0x02 && buf[3] == 0x01 && buf[4] < 4 ) || + ( buf[1] == 0x81 && /* 2 length bytes */ + buf[3] == 0x02 && buf[4] == 0x01 && buf[5] < 4 ) || + ( buf[1] == 0x82 && /* 2 length bytes */ + buf[4] == 0x02 && buf[5] == 0x01 && buf[6] < 4 ) ) ) ) { polarssl_free( buf ); return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); From 416fa8fde5f5d930487ae6acd4111bac1a1001fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 10:46:23 +0200 Subject: [PATCH 19/33] Implement x509parse_key_pkcs8_unencrypted_der_ec() --- library/x509parse.c | 168 +++++++++++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 49 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 20c86071b..e704c48db 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2594,54 +2594,6 @@ int x509parse_public_key_rsa( rsa_context *rsa, } #if defined(POLARSSL_ECP_C) -/* - * Parse an unencrypted PKCS#8 encoded private EC key - */ -static int x509parse_key_pkcs8_unencrypted_der_ec( - ecp_keypair *eck, - const unsigned char* key, - size_t keylen ) -{ - int ret; - - (void) key; - (void) keylen; - - if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) == 0 ) - return 0; - -cleanup: - ecp_keypair_free( eck ); - - return( ret ); -} - -/* - * Parse an encrypted PKCS#8 encoded private EC key - */ -static int x509parse_key_pkcs8_encrypted_der_ec( - ecp_keypair *eck, - const unsigned char *key, - size_t keylen, - const unsigned char *pwd, - size_t pwdlen ) -{ - int ret; - - (void) key; - (void) keylen; - (void) pwd; - (void) pwdlen; - - if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) == 0 ) - return 0; - -cleanup: - ecp_keypair_free( eck ); - - return( ret ); -} - /* * Parse a SEC1 encoded private EC key */ @@ -2748,6 +2700,124 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, return 0; } +/* + * Parse an unencrypted PKCS#8 encoded private EC key + */ +static int x509parse_key_pkcs8_unencrypted_der_ec( + ecp_keypair *eck, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + x509_buf pk_alg_oid; + ecp_group_id grp_id; + const unsigned char *params_end; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + pk_type_t pk_alg = POLARSSL_PK_NONE; + + /* + * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); + + if( ( ret = x509_get_alg( &p, end, &pk_alg_oid, ¶ms_end ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 ) + return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + + if( pk_alg != POLARSSL_PK_ECKEY && pk_alg != POLARSSL_PK_ECKEY_DH ) + return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + + if( pk_alg == POLARSSL_PK_ECKEY_DH ) + eck->alg = POLARSSL_ECP_KEY_ALG_ECDH; + + if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = x509parse_key_sec1_der( eck, p, len ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return 0; +} + +/* + * Parse an encrypted PKCS#8 encoded private EC key + */ +static int x509parse_key_pkcs8_encrypted_der_ec( + ecp_keypair *eck, + const unsigned char *key, + size_t keylen, + const unsigned char *pwd, + size_t pwdlen ) +{ + int ret; + + (void) key; + (void) keylen; + (void) pwd; + (void) pwdlen; + + if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return 0; +} + /* * Parse a private EC key */ @@ -2894,7 +2964,7 @@ static int x509parse_public_key_ec_der( ecp_keypair *key, if( alg != POLARSSL_PK_ECKEY && alg != POLARSSL_PK_ECKEY_DH ) return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); - if ( alg == POLARSSL_PK_ECKEY_DH ) + if( alg == POLARSSL_PK_ECKEY_DH ) key->alg = POLARSSL_ECP_KEY_ALG_ECDH; if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 ) From a5d9974423867750d8a4ded6c97fae69ba30ae4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 11:08:31 +0200 Subject: [PATCH 20/33] Split up x509_parse_pkcs8_encrypted_der() --- library/x509parse.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index e704c48db..caf59c433 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2280,26 +2280,23 @@ static int x509parse_key_pkcs8_unencrypted_der( } /* - * Parse an encrypted PKCS#8 encoded private RSA key + * Decrypt the content of a PKCS#8 EncryptedPrivateKeyInfo */ -static int x509parse_key_pkcs8_encrypted_der( - rsa_context *rsa, - const unsigned char *key, - size_t keylen, - const unsigned char *pwd, - size_t pwdlen ) +static int x509parse_pkcs8_decrypt( unsigned char *buf, size_t buflen, + size_t *used_len, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { int ret; size_t len; unsigned char *p, *end; x509_buf pbe_alg_oid, pbe_params; - unsigned char buf[2048]; #if defined(POLARSSL_PKCS12_C) cipher_type_t cipher_alg; md_type_t md_alg; #endif - memset(buf, 0, 2048); + memset(buf, 0, buflen); p = (unsigned char *) key; end = p + keylen; @@ -2335,8 +2332,7 @@ static int x509parse_key_pkcs8_encrypted_der( if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - // buf has been sized to 2048 bytes - if( len > 2048 ) + if( len > buflen ) return( POLARSSL_ERR_X509_INVALID_INPUT ); /* @@ -2389,7 +2385,29 @@ static int x509parse_key_pkcs8_encrypted_der( #endif /* POLARSSL_PKCS5_C */ return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - return x509parse_key_pkcs8_unencrypted_der( rsa, buf, len ); + *used_len = len; + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private RSA key + */ +static int x509parse_key_pkcs8_encrypted_der( + rsa_context *rsa, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + unsigned char buf[2048]; + size_t len = 0; + + if( ( ret = x509parse_pkcs8_decrypt( buf, sizeof( buf ), &len, + key, keylen, pwd, pwdlen ) ) != 0 ) + { + return( ret ); + } + + return( x509parse_key_pkcs8_unencrypted_der( rsa, buf, len ) ); } /* From 9c1cf459dd249c49bb9598ae3322662f5b470a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 11:20:24 +0200 Subject: [PATCH 21/33] Implement x509parse_key_pkcs8_encrypted_der_ec() --- library/x509parse.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index caf59c433..b231f8001 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2815,25 +2815,20 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( */ static int x509parse_key_pkcs8_encrypted_der_ec( ecp_keypair *eck, - const unsigned char *key, - size_t keylen, - const unsigned char *pwd, - size_t pwdlen ) + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { int ret; + unsigned char buf[2048]; + size_t len = 0; - (void) key; - (void) keylen; - (void) pwd; - (void) pwdlen; - - if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) != 0 ) + if( ( ret = x509parse_pkcs8_decrypt( buf, sizeof( buf ), &len, + key, keylen, pwd, pwdlen ) ) != 0 ) { - ecp_keypair_free( eck ); return( ret ); } - return 0; + return( x509parse_key_pkcs8_unencrypted_der_ec( eck, buf, len ) ); } /* From a9e54129b5b7fc9c690fd12cb7c20fcf014b12b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 11:41:39 +0200 Subject: [PATCH 22/33] Adapt test files to supported PKCS#8 modes openssl pkcs8 -topk8 -in ec_prv.sec1.pem -passout pass:polar \ -v1 PBE-SHA1-RC4-128 -outform der -out ec_prv.pk8.pw.der openssl pkcs8 -topk8 -in ec_prv.sec1.pem -passout pass:polar \ -v1 PBE-SHA1-RC4-128 -outform pem -out ec_prv.pk8.pw.pem --- tests/data_files/ec_prv.pk8.pw.der | Bin 154 -> 148 bytes tests/data_files/ec_prv.pk8.pw.pem | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/data_files/ec_prv.pk8.pw.der b/tests/data_files/ec_prv.pk8.pw.der index efcd809ab35e77ac406ba51efaf9b63353679f97..db0b5bdcc1e5968d6039da050329a4655450b70a 100644 GIT binary patch literal 148 zcmV;F0Bip+fsrsA1_~;MNQUQ00s;sC1aY=dO>V08rMojg zy}s5dmLWj|5RT&{O7fC_@-7`5hng0Hy)*?UdFgBfZG5)PKx%-7VT?&&PwBBo+X18@ zrJ}BIdWXNmQ-TDdU9Z9JVAxdA^WrGnj&B`sf=1PHrop=H2wm8ZhmEI@J1;(tx}>Oc CK0xLG literal 154 zcmV;L0A>F$ftN5F1_>&LNQU5$Zk+N00tf&Ec+#97{g|(I5l0|{ zyBiBVy|MkoobG;Ew0OHu32#4nbX3cP6Ig(S4CuKX%z>5HUK>cW;;H}|-t9#)hxi3r zEn{}y9_S$cazhjHd!n%W{+IQq!FfBZgnR8KYK#PF>`}L}^IenZyt$Vf0iY7vvIJs7 IValeP+&SDv^#A|> diff --git a/tests/data_files/ec_prv.pk8.pw.pem b/tests/data_files/ec_prv.pk8.pw.pem index 0b50cd7b0..7413d1ea9 100644 --- a/tests/data_files/ec_prv.pk8.pw.pem +++ b/tests/data_files/ec_prv.pk8.pw.pem @@ -1,6 +1,6 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIGXMBsGCSqGSIb3DQEFAzAOBAiO5a+OuKjOdwICCAAEeGEBv8oxHZy3GvR28QHJ -Xq1Fq/UZrWklH6RI8VTx4WS6UK88PzJSmLMxO3pl4L/CUNfJ4RI9+YHFRZyf8Tcr -5di4xMQaEqh08PXwyErqOerBGc9DsFpcpFAsn6Sa9KLG5aritGrSkPyDACloHyKR -lJyTE6fTVwG5xQ== +MIGRMBwGCiqGSIb3DQEMAQEwDgQIIrlmCCSpJzcCAggABHGm2LyJ60ojfilRRp8h +Xf+sWL3lJq6wlj4Nk41SHVnZ2RiVtP5NVK908/WxnXkridd6Qpjnq/14woWVmQxT +IzhKFVi22YmQyBsNj+bEGDAE4c9qaby8u6zbzs7Qj29F90f/PiYsaIEGcNn/W88e +XarNDw== -----END ENCRYPTED PRIVATE KEY----- From 80300ad0d91ae6807bbe0379afcc4ee0c58a2a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 11:57:13 +0200 Subject: [PATCH 23/33] Add checks for pk_alg. Used to be implicitly done by oid_get_pk_alg(). --- library/x509parse.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index b231f8001..a2ab08500 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -511,8 +511,11 @@ static int x509_get_pubkey( unsigned char **p, /* * 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 || + pk_alg != POLARSSL_PK_RSA ) + { return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + } if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); @@ -2256,8 +2259,11 @@ static int x509parse_key_pkcs8_unencrypted_der( /* * only RSA 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 || + pk_alg != POLARSSL_PK_RSA ) + { return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + } /* * Get the OCTET STRING and parse the PKCS#1 format inside From d4ec21dd470cb21f27e37fe208bd872e22617830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 12:04:57 +0200 Subject: [PATCH 24/33] Add a check for multiple curve specification --- library/x509parse.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index a2ab08500..55149e48b 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2676,12 +2676,25 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, if( ( ret = x509_get_ecparams( &p, p + len, &grp_id) ) != 0 ) return( ret ); - /* TODO: grp may not be empty at this point, - * if we're wrapped inside a PKCS#8 structure: check consistency */ - if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 ) + /* + * 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 ) { - ecp_keypair_free( eck ); - return( ret ); + 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 ) From 12e0ed9115b2075092e722489775028b97ad4bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 13:31:32 +0200 Subject: [PATCH 25/33] Add pk_context and associated functions --- include/polarssl/pk.h | 31 +++++++++++++- library/CMakeLists.txt | 1 + library/Makefile | 1 + library/pk.c | 93 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 library/pk.c diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 169753de4..16aac4349 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -37,11 +37,40 @@ extern "C" { typedef enum { POLARSSL_PK_NONE=0, POLARSSL_PK_RSA, - POLARSSL_PK_ECDSA, POLARSSL_PK_ECKEY, POLARSSL_PK_ECKEY_DH, } pk_type_t; +/** + * \brief Public key container + */ +typedef struct +{ + pk_type_t type; /**< Public key type */ + void * data; /**< Public key data */ +} pk_context; + +/** + * \brief Initialize a pk_context (as NONE) + */ +void pk_init( pk_context *ctx ); + +/** + * \brief Free a pk_context + */ +void pk_free( pk_context *ctx ); + +/** + * \brief Set a pk_context to a given type + * + * \param ctx Context to initialize + * \param type Type of key + * + * \return O on success, -1 on memory allocation error + * TODO: use appropriate error constant + */ +int pk_set_type( pk_context *ctx, pk_type_t type ); + #ifdef __cplusplus } #endif diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 948737d81..3fa76a972 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -39,6 +39,7 @@ set(src pkcs5.c pkcs11.c pkcs12.c + pk.c rsa.c sha1.c sha256.c diff --git a/library/Makefile b/library/Makefile index f670dcc47..48c3bdcbb 100644 --- a/library/Makefile +++ b/library/Makefile @@ -49,6 +49,7 @@ OBJS= aes.o arc4.o asn1parse.o \ oid.o \ padlock.o pbkdf2.o pem.o \ pkcs5.o pkcs11.o pkcs12.o \ + pk.o \ rsa.o sha1.o sha256.o \ sha512.o ssl_cache.o ssl_cli.o \ ssl_srv.o ssl_ciphersuites.o \ diff --git a/library/pk.c b/library/pk.c new file mode 100644 index 000000000..a5f8d6b9b --- /dev/null +++ b/library/pk.c @@ -0,0 +1,93 @@ +/* + * Public Key abstraction layer + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "polarssl/config.h" + +#include "polarssl/rsa.h" +#include "polarssl/ecp.h" +#include "polarssl/pk.h" + +#include + +/* + * Initialise a pk_context + */ +void pk_init( pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->type = POLARSSL_PK_NONE; + ctx->data = NULL; +} + +/* + * Free (the components of) a pk_context + */ +void pk_free( pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + switch( ctx->type ) + { + case POLARSSL_PK_NONE: + break; + + case POLARSSL_PK_RSA: + rsa_free( ctx->data ); + break; + + case POLARSSL_PK_ECKEY: + case POLARSSL_PK_ECKEY_DH: + ecp_keypair_free( ctx->data ); + break; + } + + ctx->type = POLARSSL_PK_NONE; + ctx->data = NULL; +} + +/* + * Set a pk_context to a given type + */ +int pk_set_type( pk_context *ctx, pk_type_t type ) +{ + size_t size = type == POLARSSL_PK_RSA ? sizeof( rsa_context ) + : type == POLARSSL_PK_ECKEY ? sizeof( ecp_keypair ) + : type == POLARSSL_PK_ECKEY_DH ? sizeof( ecp_keypair ) + : 0; + + if( size == 0 ) + return( 0 ); + + if( ( ctx->data = malloc( size ) ) == NULL ) + return( -1 ); + + memset( ctx->data, 0, size ); + ctx->type = type; + + return( 0 ); +} From 8838099330a238dc88d6f62aad1d9584ac6f256e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 4 Jul 2013 14:09:57 +0200 Subject: [PATCH 26/33] Add x509parse_{,public}_key{,file}() Also make previously public *_ec functions private. --- include/polarssl/x509.h | 32 +++---- library/x509parse.c | 97 +++++++++++++++++----- tests/suites/test_suite_x509parse.function | 26 +++--- 3 files changed, 108 insertions(+), 47 deletions(-) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 240b9bbba..f0c0e7aac 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -472,9 +472,9 @@ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ); /** \ingroup x509_module */ /** - * \brief Parse a private EC key + * \brief Parse a private key * - * \param eckey EC key to be initialized + * \param ctx key to be initialized * \param key input buffer * \param keylen size of the buffer * \param pwd password for decryption (optional) @@ -482,46 +482,46 @@ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ); * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_key_ec( ecp_keypair *eckey, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ); +int x509parse_key( pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); /** \ingroup x509_module */ /** - * \brief Load and parse a private EC key + * \brief Load and parse a private key * - * \param eckey EC key to be initialized + * \param ctx key to be initialized * \param path filename to read the private key from * \param password password to decrypt the file (can be NULL) * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_keyfile_ec( ecp_keypair *eckey, - const char *path, const char *password ); +int x509parse_keyfile( pk_context *ctx, + const char *path, const char *password ); /** \ingroup x509_module */ /** - * \brief Parse a public EC key + * \brief Parse a public key * - * \param eckey EC key to be initialized + * \param ctx key to be initialized * \param key input buffer * \param keylen size of the buffer * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_public_key_ec( ecp_keypair *eckey, - const unsigned char *key, size_t keylen ); +int x509parse_public_key( pk_context *ctx, + const unsigned char *key, size_t keylen ); /** \ingroup x509_module */ /** - * \brief Load and parse a public EC key + * \brief Load and parse a public key * - * \param eckey EC key to be initialized + * \param ctx key to be initialized * \param path filename to read the private key from * * \return 0 if successful, or a specific X509 or PEM error code */ -int x509parse_public_keyfile_ec( ecp_keypair *eckey, const char *path ); +int x509parse_public_keyfile( pk_context *ctx, const char *path ); /** \ingroup x509_module */ /** diff --git a/library/x509parse.c b/library/x509parse.c index 55149e48b..179ff959d 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -511,12 +511,14 @@ static int x509_get_pubkey( unsigned char **p, /* * only RSA public keys handled at this time */ - if( oid_get_pk_alg( pk_alg_oid, &pk_alg ) != 0 || - pk_alg != POLARSSL_PK_RSA ) + 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 ); @@ -2079,12 +2081,11 @@ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ) return( ret ); } -#if defined(POLARSSL_ECP_C) /* - * Load and parse a private EC key + * Load and parse a private key */ -int x509parse_keyfile_ec( ecp_keypair *eckey, - const char *path, const char *pwd ) +int x509parse_keyfile( pk_context *ctx, + const char *path, const char *pwd ) { int ret; size_t n; @@ -2094,9 +2095,9 @@ int x509parse_keyfile_ec( ecp_keypair *eckey, return( ret ); if( pwd == NULL ) - ret = x509parse_key_ec( eckey, buf, n, NULL, 0 ); + ret = x509parse_key( ctx, buf, n, NULL, 0 ); else - ret = x509parse_key_ec( eckey, buf, n, + ret = x509parse_key( ctx, buf, n, (const unsigned char *) pwd, strlen( pwd ) ); memset( buf, 0, n + 1 ); @@ -2106,9 +2107,9 @@ int x509parse_keyfile_ec( ecp_keypair *eckey, } /* - * Load and parse a public EC key + * Load and parse a public key */ -int x509parse_public_keyfile_ec( ecp_keypair *eckey, const char *path ) +int x509parse_public_keyfile( pk_context *ctx, const char *path ) { int ret; size_t n; @@ -2117,14 +2118,14 @@ int x509parse_public_keyfile_ec( ecp_keypair *eckey, const char *path ) if ( (ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); - ret = x509parse_public_key_ec( eckey, buf, n ); + ret = x509parse_public_key( ctx, buf, n ); memset( buf, 0, n + 1 ); free( buf ); return( ret ); } -#endif /* defined(POLARSSL_ECP_C) */ + #endif /* POLARSSL_FS_IO */ /* @@ -2259,12 +2260,14 @@ static int x509parse_key_pkcs8_unencrypted_der( /* * only RSA keys handled at this time */ - if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 || - pk_alg != POLARSSL_PK_RSA ) + if( oid_get_pk_alg( &pk_alg_oid, &pk_alg ) != 0 ) { return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); } + if (pk_alg != POLARSSL_PK_RSA ) + return( POLARSSL_ERR_X509_CERT_INVALID_ALG ); + /* * Get the OCTET STRING and parse the PKCS#1 format inside */ @@ -2791,7 +2794,7 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); if( pk_alg != POLARSSL_PK_ECKEY && pk_alg != POLARSSL_PK_ECKEY_DH ) - return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + return( POLARSSL_ERR_X509_CERT_INVALID_ALG ); if( pk_alg == POLARSSL_PK_ECKEY_DH ) eck->alg = POLARSSL_ECP_KEY_ALG_ECDH; @@ -2853,9 +2856,9 @@ static int x509parse_key_pkcs8_encrypted_der_ec( /* * Parse a private EC key */ -int x509parse_key_ec( ecp_keypair *eck, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) +static int x509parse_key_ec( ecp_keypair *eck, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) { int ret; @@ -2994,7 +2997,7 @@ static int x509parse_public_key_ec_der( ecp_keypair *key, return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); if( alg != POLARSSL_PK_ECKEY && alg != POLARSSL_PK_ECKEY_DH ) - return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG ); + return( POLARSSL_ERR_X509_CERT_INVALID_ALG ); if( alg == POLARSSL_PK_ECKEY_DH ) key->alg = POLARSSL_ECP_KEY_ALG_ECDH; @@ -3016,8 +3019,8 @@ static int x509parse_public_key_ec_der( ecp_keypair *key, /* * Parse a public EC key */ -int x509parse_public_key_ec( ecp_keypair *eckey, - const unsigned char *key, size_t keylen ) +static int x509parse_public_key_ec( ecp_keypair *eckey, + const unsigned char *key, size_t keylen ) { int ret; #if defined(POLARSSL_PEM_C) @@ -3059,6 +3062,58 @@ int x509parse_public_key_ec( ecp_keypair *eckey, } #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 ); + } + + if ( ( ret = pk_set_type( ctx, POLARSSL_PK_ECKEY ) ) != 0 ) + return( ret ); + + if( ( ret = x509parse_key_ec( ctx->data, key, keylen, pwd, pwdlen ) ) == 0 ) + { + return( 0 ); + } + + return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); +} + +/* + * Parse a public key + */ +int x509parse_public_key( pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + + if ( ( ret = pk_set_type( ctx, POLARSSL_PK_RSA ) ) != 0 ) + return( ret ); + + if( ( ret = x509parse_public_key_rsa( ctx->data, key, keylen ) ) == 0 ) + return( 0 ); + + if ( ( ret = pk_set_type( ctx, POLARSSL_PK_ECKEY ) ) != 0 ) + return( ret ); + + if( ( ret = x509parse_public_key_ec( ctx->data, key, keylen ) ) == 0 ) + return( 0 ); + + return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); +} + #if defined(POLARSSL_DHM_C) /* * Parse DHM parameters diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 57653f798..2baf76416 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -182,42 +182,48 @@ END_CASE BEGIN_CASE x509parse_public_keyfile_ec:key_file:result { - ecp_keypair eckey; + pk_context ctx; int res; - ecp_keypair_init( &eckey ); + pk_init( &ctx ); - res = x509parse_public_keyfile_ec( &eckey, {key_file} ); + res = x509parse_public_keyfile( &ctx, {key_file} ); TEST_ASSERT( res == {result} ); if( res == 0 ) { - TEST_ASSERT( ecp_check_pubkey( &eckey.grp, &eckey.Q ) == 0 ); + ecp_keypair *eckey; + TEST_ASSERT( ctx.type == POLARSSL_PK_ECKEY ); + eckey = (ecp_keypair *) ctx.data; + TEST_ASSERT( ecp_check_pubkey( &eckey->grp, &eckey->Q ) == 0 ); } - ecp_keypair_free( &eckey ); + pk_free( &ctx ); } END_CASE BEGIN_CASE x509parse_keyfile_ec:key_file:password:result { - ecp_keypair eckey; + pk_context ctx; int res; - ecp_keypair_init( &eckey ); + pk_init( &ctx ); - res = x509parse_keyfile_ec( &eckey, {key_file}, {password} ); + res = x509parse_keyfile( &ctx, {key_file}, {password} ); TEST_ASSERT( res == {result} ); if( res == 0 ) { - TEST_ASSERT( ecp_check_prvkey( &eckey.grp, &eckey.d ) == 0 ); + ecp_keypair *eckey; + TEST_ASSERT( ctx.type == POLARSSL_PK_ECKEY ); + eckey = (ecp_keypair *) ctx.data; + TEST_ASSERT( ecp_check_prvkey( &eckey->grp, &eckey->d ) == 0 ); } - ecp_keypair_free( &eckey ); + pk_free( &ctx ); } END_CASE From 7a6c946446e67b49196b7ba6c9a6a16cdb50180f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 10:04:07 +0200 Subject: [PATCH 27/33] Fix error code in pk.h --- include/polarssl/error.h | 3 ++- include/polarssl/pk.h | 5 +++-- library/error.c | 13 ++++++++++++- library/pk.c | 2 +- scripts/generate_errors.pl | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/include/polarssl/error.h b/include/polarssl/error.h index c32615493..f8c23e686 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -76,7 +76,8 @@ * Name ID Nr of Errors * PEM 1 9 * PKCS#12 1 4 (Started from top) - * X509 2 23 + * X509 2 25 + * PK 2 1 (Started from top) * DHM 3 6 * PKCS5 3 4 (Started from top) * RSA 4 9 diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 16aac4349..3806027b4 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -27,6 +27,8 @@ #ifndef POLARSSL_PK_H #define POLARSSL_PK_H +#define POLARSSL_ERR_PK_MALLOC_FAILED -0x2F80 /**< Memory alloation failed. */ + #ifdef __cplusplus extern "C" { #endif @@ -66,8 +68,7 @@ void pk_free( pk_context *ctx ); * \param ctx Context to initialize * \param type Type of key * - * \return O on success, -1 on memory allocation error - * TODO: use appropriate error constant + * \return O on success, or POLARSSL_ERR_PK_MALLOC_FAILED */ int pk_set_type( pk_context *ctx, pk_type_t type ); diff --git a/library/error.c b/library/error.c index 7042bbd1b..0a739b5d5 100644 --- a/library/error.c +++ b/library/error.c @@ -113,6 +113,10 @@ #include "polarssl/pem.h" #endif +#if defined(POLARSSL_PK_C) +#include "polarssl/pk.h" +#endif + #if defined(POLARSSL_PKCS12_C) #include "polarssl/pkcs12.h" #endif @@ -243,6 +247,11 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "PEM - Bad input parameters to function" ); #endif /* POLARSSL_PEM_C */ +#if defined(POLARSSL_PK_C) + if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) ) + snprintf( buf, buflen, "PK - Memory alloation failed" ); +#endif /* POLARSSL_PK_C */ + #if defined(POLARSSL_PKCS12_C) if( use_ret == -(POLARSSL_ERR_PKCS12_BAD_INPUT_DATA) ) snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); @@ -388,7 +397,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) ) snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) ) - snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA is supported)" ); + snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA and EC are supported)" ); if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) ) snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" ); if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) ) @@ -409,6 +418,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "X509 - Private key password can't be empty" ); if( use_ret == -(POLARSSL_ERR_X509_PASSWORD_MISMATCH) ) snprintf( buf, buflen, "X509 - Given private key password does not allow for correct decryption" ); + if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_NAMED_CURVE) ) + snprintf( buf, buflen, "X509 - Elliptic curve is unsupported (only NIST curves are supported)" ); #endif /* POLARSSL_X509_PARSE_C */ if( strlen( buf ) == 0 ) diff --git a/library/pk.c b/library/pk.c index a5f8d6b9b..ca99fc633 100644 --- a/library/pk.c +++ b/library/pk.c @@ -84,7 +84,7 @@ int pk_set_type( pk_context *ctx, pk_type_t type ) return( 0 ); if( ( ctx->data = malloc( size ) ) == NULL ) - return( -1 ); + return( POLARSSL_ERR_PK_MALLOC_FAILED ); memset( ctx->data, 0, size ); ctx->type = type; diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 009107b6e..7257ae670 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -13,7 +13,7 @@ my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "MD2", "MD4", "MD5", "SHA1", "SHA256", "SHA512", "GCM" ); my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL", - "PKCS12", "PKCS5" ); + "PK", "PKCS12", "PKCS5" ); my $line_separator = $/; undef $/; From 1f73a65c06d92e7768ff4c4a3831423dcf0f437d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 10:26:41 +0200 Subject: [PATCH 28/33] Fix ommission in pk_free(). --- library/pk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/pk.c b/library/pk.c index ca99fc633..edbbf5037 100644 --- a/library/pk.c +++ b/library/pk.c @@ -66,6 +66,8 @@ void pk_free( pk_context *ctx ) break; } + free( ctx-> data ); + ctx->type = POLARSSL_PK_NONE; ctx->data = NULL; } From 81c313ccc6a732771d6121eeb6962060dd379548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 10:35:54 +0200 Subject: [PATCH 29/33] Add #ifdef's on RSA and EC in PK --- include/polarssl/pk.h | 4 ++++ library/pk.c | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 3806027b4..00f8cfcb1 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -38,9 +38,13 @@ 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 } pk_type_t; /** diff --git a/library/pk.c b/library/pk.c index edbbf5037..71505ed2e 100644 --- a/library/pk.c +++ b/library/pk.c @@ -25,10 +25,15 @@ #include "polarssl/config.h" -#include "polarssl/rsa.h" -#include "polarssl/ecp.h" #include "polarssl/pk.h" +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + #include /* @@ -56,14 +61,18 @@ void pk_free( pk_context *ctx ) case POLARSSL_PK_NONE: break; +#if defined(POLARSSL_RSA_C) case POLARSSL_PK_RSA: rsa_free( ctx->data ); break; +#endif +#if defined(POLARSSL_ECP_C) case POLARSSL_PK_ECKEY: case POLARSSL_PK_ECKEY_DH: ecp_keypair_free( ctx->data ); break; +#endif } free( ctx-> data ); @@ -77,13 +86,26 @@ void pk_free( pk_context *ctx ) */ int pk_set_type( pk_context *ctx, pk_type_t type ) { - size_t size = type == POLARSSL_PK_RSA ? sizeof( rsa_context ) - : type == POLARSSL_PK_ECKEY ? sizeof( ecp_keypair ) - : type == POLARSSL_PK_ECKEY_DH ? sizeof( ecp_keypair ) - : 0; + size_t size = 0; - if( size == 0 ) - return( 0 ); + switch( type ) + { +#if defined(POLARSSL_RSA_C) + case POLARSSL_PK_RSA: + size = sizeof( rsa_context ); + break; +#endif + +#if defined(POLARSSL_ECP_C) + case POLARSSL_PK_ECKEY: + case POLARSSL_PK_ECKEY_DH: + size = sizeof( ecp_keypair ); + break; +#endif + + case POLARSSL_PK_NONE: + ; /* Should not happen */ + } if( ( ctx->data = malloc( size ) ) == NULL ) return( POLARSSL_ERR_PK_MALLOC_FAILED ); From de44a4aecf96796a59721942ffcf551eb14bd228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 16:05:52 +0200 Subject: [PATCH 30/33] Rename ecp_check_prvkey with a 'i' for consistency --- include/polarssl/ecp.h | 2 +- library/ecp.c | 2 +- library/x509parse.c | 4 ++-- tests/suites/test_suite_x509parse.function | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 707d04028..c1f08c9f7 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -454,7 +454,7 @@ int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt ); * in order to ease use with other structures such as * ecdh_context of ecdsa_context. */ -int ecp_check_prvkey( const ecp_group *grp, const mpi *d ); +int ecp_check_privkey( const ecp_group *grp, const mpi *d ); /** * \brief Generate a keypair diff --git a/library/ecp.c b/library/ecp.c index 29cfce5a3..9e7a96785 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1308,7 +1308,7 @@ cleanup: /* * Check that an mpi is valid as a private key (SEC1 3.2) */ -int ecp_check_prvkey( const ecp_group *grp, const mpi *d ) +int ecp_check_privkey( const ecp_group *grp, const mpi *d ) { /* We want 1 <= d <= N-1 */ if ( mpi_cmp_int( d, 1 ) < 0 || mpi_cmp_mpi( d, &grp->N ) >= 0 ) diff --git a/library/x509parse.c b/library/x509parse.c index 179ff959d..c5f9049df 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2731,7 +2731,7 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); } - if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) != 0 ) + if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) { ecp_keypair_free( eck ); return( ret ); @@ -2823,7 +2823,7 @@ static int x509parse_key_pkcs8_unencrypted_der_ec( return( ret ); } - if( ( ret = ecp_check_prvkey( &eck->grp, &eck->d ) ) != 0 ) + if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) { ecp_keypair_free( eck ); return( ret ); diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 2baf76416..b6383d734 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -220,7 +220,7 @@ x509parse_keyfile_ec:key_file:password:result ecp_keypair *eckey; TEST_ASSERT( ctx.type == POLARSSL_PK_ECKEY ); eckey = (ecp_keypair *) ctx.data; - TEST_ASSERT( ecp_check_prvkey( &eckey->grp, &eckey->d ) == 0 ); + TEST_ASSERT( ecp_check_privkey( &eckey->grp, &eckey->d ) == 0 ); } pk_free( &ctx ); From 791eed3f339f50df99e52aaf4ded9891b76995cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 16:26:08 +0200 Subject: [PATCH 31/33] Fix portability issue in oid_get_numeric_string() --- library/oid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/oid.c b/library/oid.c index dd4cbf037..449b3e1f0 100644 --- a/library/oid.c +++ b/library/oid.c @@ -33,7 +33,6 @@ #include "polarssl/rsa.h" #include -#include /* * Macro to generate an internal function for oid_XXX_from_asn1() (used by @@ -572,7 +571,8 @@ int oid_get_numeric_string( char *buf, size_t size, for( i = 1; i < oid->len; i++ ) { /* Prevent overflow in value. */ - if (value > (UINT_MAX >> 7) ) + unsigned int v = value << 7; + if ( v < value ) return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); value <<= 7; From 7d4e5b739e47502d3175f0616e00e7c7e6c2b58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2013 16:35:23 +0200 Subject: [PATCH 32/33] Simplify password check in pem_read_buffer() --- include/polarssl/pem.h | 5 +++-- library/pem.c | 19 +++++-------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/include/polarssl/pem.h b/include/polarssl/pem.h index 782b235d9..cc6cba14e 100644 --- a/include/polarssl/pem.h +++ b/include/polarssl/pem.h @@ -84,8 +84,9 @@ void pem_init( pem_context *ctx ); * POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is * the length to skip) * - * \note Checks password correctness by verifying if the decrypted - * text looks like a RSAPrivateKey or ECPrivateKey structure + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length * * \return 0 on success, ior a specific PEM error code */ diff --git a/library/pem.c b/library/pem.c index 3e3e96df3..3f6d330a6 100644 --- a/library/pem.c +++ b/library/pem.c @@ -333,21 +333,12 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, #endif /* POLARSSL_AES_C */ /* - * The result should look like RSAPrivateKey or ECPrivateKey - * We use the following heuristic: - * len must be more than 6 - * byte 1 must be 0x30 (SEQUENCE tag) - * then allow for one to 3 length bytes - * then we must have 0x02 0x01 (INTEGER tag + length, for version) - * version must be less than 4 (leaves some room) + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as heurisitic to try detecting password mismatchs. */ - if( ! ( len > 6 && buf[0] == 0x30 && ( - ( buf[1] <= 0x7f && /* 1 length byte */ - buf[2] == 0x02 && buf[3] == 0x01 && buf[4] < 4 ) || - ( buf[1] == 0x81 && /* 2 length bytes */ - buf[3] == 0x02 && buf[4] == 0x01 && buf[5] < 4 ) || - ( buf[1] == 0x82 && /* 2 length bytes */ - buf[4] == 0x02 && buf[5] == 0x01 && buf[6] < 4 ) ) ) ) + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) { polarssl_free( buf ); return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); From 8ea6c6147794477a88cd981ef0634bb46cd16b25 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Tue, 16 Jul 2013 17:15:03 +0200 Subject: [PATCH 33/33] Rename of prvkey -> privkey fix in test suite files --- tests/suites/test_suite_ecp.data | 4 ++-- tests/suites/test_suite_ecp.function | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index d19e41863..73acb4fb3 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -245,8 +245,8 @@ ECP tls write-read group #2 depends_on:POLARSSL_ECP_DP_SECP521R1_ENABLED ecp_tls_write_read_group:SECP521R1 -ECP check prvkey -ecp_check_prvkey:SECP192R1 +ECP check privkey +ecp_check_privkey:SECP192R1 ECP gen keypair depends_on:POLARSSL_ECP_DP_SECP192R1_ENABLED diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 1d3d3dfc2..543175f30 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -438,7 +438,7 @@ ecp_tls_write_read_group:id END_CASE BEGIN_CASE -ecp_check_prvkey:id +ecp_check_privkey:id { ecp_group grp; mpi d; @@ -449,10 +449,10 @@ ecp_check_prvkey:id TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); TEST_ASSERT( mpi_lset( &d, 0 ) == 0 ); - TEST_ASSERT( ecp_check_prvkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); + TEST_ASSERT( ecp_check_privkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); TEST_ASSERT( mpi_copy( &d, &grp.N ) == 0 ); - TEST_ASSERT( ecp_check_prvkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); + TEST_ASSERT( ecp_check_privkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); ecp_group_free( &grp ); mpi_free( &d ); @@ -478,7 +478,7 @@ ecp_gen_keypair:id == 0 ); TEST_ASSERT( ecp_check_pubkey( &grp, &Q ) == 0 ); - TEST_ASSERT( ecp_check_prvkey( &grp, &d ) == 0 ); + TEST_ASSERT( ecp_check_privkey( &grp, &d ) == 0 ); ecp_group_free( &grp ); ecp_point_free( &Q );