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/ecdsa.h b/include/polarssl/ecdsa.h index 2ad986d64..e709b405c 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 @@ -70,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/include/polarssl/ecp.h b/include/polarssl/ecp.h index 4b0218180..c1f08c9f7 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 * @@ -189,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 * @@ -398,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_privkey( const ecp_group *grp, const mpi *d ); + /** * \brief Generate a keypair * @@ -409,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/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/oid.h b/include/polarssl/oid.h index e63c169a6..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 @@ -61,6 +60,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 +72,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 +239,43 @@ #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 5480 + */ + +/* 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" + +/* + * 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 @@ -293,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/include/polarssl/pem.h b/include/polarssl/pem.h index 969faa283..cc6cba14e 100644 --- a/include/polarssl/pem.h +++ b/include/polarssl/pem.h @@ -84,6 +84,10 @@ void pem_init( pem_context *ctx ); * POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is * the length to skip) * + * \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 */ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index d9639eeed..00f8cfcb1 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 @@ -36,10 +38,44 @@ extern "C" { */ typedef enum { POLARSSL_PK_NONE=0, +#if defined(POLARSSL_RSA_C) POLARSSL_PK_RSA, - POLARSSL_PK_ECDSA, +#endif +#if defined(POLARSSL_ECP_C) + POLARSSL_PK_ECKEY, + POLARSSL_PK_ECKEY_DH, +#endif } 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, or POLARSSL_ERR_PK_MALLOC_FAILED + */ +int pk_set_type( pk_context *ctx, pk_type_t type ); + #ifdef __cplusplus } #endif diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 86624ecb0..f0c0e7aac 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" @@ -58,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 */ @@ -69,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 */ /** @@ -427,9 +429,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 +443,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 +456,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 +468,60 @@ 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 */ +/** + * \brief Parse a private key + * + * \param ctx 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( 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 key + * + * \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( pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup x509_module */ +/** + * \brief Parse a public key + * + * \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( pk_context *ctx, + const unsigned char *key, size_t keylen ); + +/** \ingroup x509_module */ +/** + * \brief Load and parse a public key + * + * \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( pk_context *ctx, const char *path ); /** \ingroup x509_module */ /** 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/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) diff --git a/library/ecp.c b/library/ecp.c index af18e5bee..9e7a96785 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 */ @@ -699,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) */ @@ -1277,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_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 ) + return( POLARSSL_ERR_ECP_GENERIC ); + + return( 0 ); +} + /* * Generate a keypair (SEC1 3.2.1) */ 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/oid.c b/library/oid.c index 5cd9a5990..449b3e1f0 100644 --- a/library/oid.c +++ b/library/oid.c @@ -248,7 +248,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) @@ -312,7 +311,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; @@ -325,6 +324,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, @@ -334,6 +341,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 @@ -521,13 +567,14 @@ 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. */ + unsigned int v = value << 7; + if ( v < value ) + return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); + value <<= 7; value += oid->p[i] & 0x7F; diff --git a/library/pem.c b/library/pem.c index c4c5cb441..3f6d330a6 100644 --- a/library/pem.c +++ b/library/pem.c @@ -332,8 +332,13 @@ 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 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 <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) { polarssl_free( buf ); return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); diff --git a/library/pk.c b/library/pk.c new file mode 100644 index 000000000..71505ed2e --- /dev/null +++ b/library/pk.c @@ -0,0 +1,117 @@ +/* + * 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/pk.h" + +#if defined(POLARSSL_RSA_C) +#include "polarssl/rsa.h" +#endif +#if defined(POLARSSL_ECP_C) +#include "polarssl/ecp.h" +#endif + +#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; + +#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 ); + + 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 = 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 ); + + memset( ctx->data, 0, size ); + ctx->type = type; + + return( 0 ); +} diff --git a/library/x509parse.c b/library/x509parse.c index ea3a24abc..c5f9049df 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -164,15 +164,105 @@ 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 ); +} + +/* 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 ); +} + +/* + * 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 ); } @@ -422,7 +512,12 @@ 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 ) + { 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 ); @@ -1146,9 +1241,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 +1395,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 +1718,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 +1823,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 ); @@ -1817,7 +1912,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 +2026,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 ); @@ -1945,19 +2040,19 @@ 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; unsigned char *buf; - if ( (ret = load_file( path, &buf, &n ) ) != 0 ) + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) 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 +2064,28 @@ 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; + unsigned char *buf; + + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509parse_public_key_rsa( rsa, buf, n ); + + memset( buf, 0, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} + +/* + * Load and parse a private key + */ +int x509parse_keyfile( pk_context *ctx, + const char *path, const char *pwd ) { int ret; size_t n; @@ -1978,13 +2094,38 @@ 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 ); + if( pwd == NULL ) + ret = x509parse_key( ctx, buf, n, NULL, 0 ); + else + ret = x509parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); memset( buf, 0, n + 1 ); - polarssl_free( buf ); + free( buf ); return( ret ); } + +/* + * Load and parse a public key + */ +int x509parse_public_keyfile( pk_context *ctx, 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( ctx, buf, n ); + + memset( buf, 0, n + 1 ); + free( buf ); + + return( ret ); +} + #endif /* POLARSSL_FS_IO */ /* @@ -2032,7 +2173,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 || @@ -2120,7 +2261,12 @@ 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 ) + { 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 @@ -2143,26 +2289,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; @@ -2198,8 +2341,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 ); /* @@ -2252,14 +2394,37 @@ 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 ) ); } /* * 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; @@ -2330,12 +2495,13 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen, ((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 ) { @@ -2365,7 +2531,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; @@ -2453,6 +2620,500 @@ int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t key return( 0 ); } +#if defined(POLARSSL_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int x509parse_key_sec1_der( ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version; + size_t len; + ecp_group_id grp_id; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + + /* + * RFC 5915, orf SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( POLARSSL_ERR_X509_KEY_INVALID_VERSION ); + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* + * Is 'parameters' present? + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = x509_get_ecparams( &p, p + len, &grp_id) ) != 0 ) + return( ret ); + + /* + * If we're wrapped in a bigger structure (eg PKCS#8), grp may have been + * defined externally. In this case, make sure both definitions match. + */ + if( eck->grp.id != 0 ) + { + if( eck->grp.id != grp_id ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + } + else + { + if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + } + } + else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + /* + * Is 'publickey' present? + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + if( ( ret = x509_get_subpubkey_ec( &p, p + len, &eck->grp, &eck->Q ) ) + != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = ecp_check_pubkey( &eck->grp, &eck->Q ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + } + else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return 0; +} + +/* + * Parse an unencrypted PKCS#8 encoded private EC key + */ +static int x509parse_key_pkcs8_unencrypted_der_ec( + ecp_keypair *eck, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + x509_buf pk_alg_oid; + ecp_group_id grp_id; + const unsigned char *params_end; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + pk_type_t pk_alg = POLARSSL_PK_NONE; + + /* + * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); + + if( ( ret = x509_get_alg( &p, end, &pk_alg_oid, ¶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_CERT_INVALID_ALG ); + + if( pk_alg == POLARSSL_PK_ECKEY_DH ) + eck->alg = POLARSSL_ECP_KEY_ALG_ECDH; + + if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = ecp_use_known_dp( &eck->grp, grp_id ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = x509parse_key_sec1_der( eck, p, len ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + ecp_keypair_free( eck ); + return( ret ); + } + + return 0; +} + +/* + * Parse an encrypted PKCS#8 encoded private EC key + */ +static int x509parse_key_pkcs8_encrypted_der_ec( + ecp_keypair *eck, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + unsigned char buf[2048]; + size_t len = 0; + + if( ( ret = x509parse_pkcs8_decrypt( buf, sizeof( buf ), &len, + key, keylen, pwd, pwdlen ) ) != 0 ) + { + return( ret ); + } + + return( x509parse_key_pkcs8_unencrypted_der_ec( eck, buf, len ) ); +} + +/* + * Parse a private EC key + */ +static int x509parse_key_ec( ecp_keypair *eck, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + +#if defined(POLARSSL_PEM_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( ret = x509parse_key_sec1_der( eck, pem.buf, pem.buflen ) ) != 0 ) + { + ecp_keypair_free( eck ); + } + + pem_free( &pem ); + return( ret ); + } + else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH ) + return( POLARSSL_ERR_X509_PASSWORD_MISMATCH ); + else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED ) + return( POLARSSL_ERR_X509_PASSWORD_REQUIRED ); + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + + ret = pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = x509parse_key_pkcs8_unencrypted_der_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 */ + + /* + * 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( eck ); + + if( ret == POLARSSL_ERR_X509_PASSWORD_MISMATCH ) + { + return( ret ); + } + + if( ( ret = x509parse_key_pkcs8_unencrypted_der_ec( eck, + key, keylen ) ) == 0 ) + return( 0 ); + + 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 ); +} + +/* + * 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_CERT_INVALID_ALG ); + + if( alg == POLARSSL_PK_ECKEY_DH ) + key->alg = POLARSSL_ECP_KEY_ALG_ECDH; + + if( ( ret = x509_get_ecparams( &p, params_end, &grp_id ) ) != 0 ) + return( ret ); + + if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_subpubkey_ec( &p, end, &key->grp, &key->Q ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Parse a public EC key + */ +static int x509parse_public_key_ec( ecp_keypair *eckey, + const unsigned char *key, size_t keylen ) +{ + int ret; +#if defined(POLARSSL_PEM_C) + size_t len; + pem_context pem; + + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + key = pem.buf; + keylen = pem.buflen; + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } +#endif + + if( ( ret = x509parse_public_key_ec_der ( eckey, key, keylen ) ) != 0 || + ( ret = ecp_check_pubkey( &eckey->grp, &eckey->Q ) ) != 0 ) + { + ecp_keypair_free( eckey ); + } + +#if defined(POLARSSL_PEM_C) + pem_free( &pem ); +#endif + + return( ret ); +} +#endif /* defined(POLARSSL_ECP_C) */ + +/* + * 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 @@ -2539,7 +3200,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 ) { @@ -3562,7 +4223,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/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 $/; diff --git a/tests/data_files/ec_prv.pk8.der b/tests/data_files/ec_prv.pk8.der new file mode 100644 index 000000000..f2bd2a927 Binary files /dev/null and b/tests/data_files/ec_prv.pk8.der differ 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 000000000..db0b5bdcc Binary files /dev/null and b/tests/data_files/ec_prv.pk8.pw.der differ 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..7413d1ea9 --- /dev/null +++ b/tests/data_files/ec_prv.pk8.pw.pem @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGRMBwGCiqGSIb3DQEMAQEwDgQIIrlmCCSpJzcCAggABHGm2LyJ60ojfilRRp8h +Xf+sWL3lJq6wlj4Nk41SHVnZ2RiVtP5NVK908/WxnXkridd6Qpjnq/14woWVmQxT +IzhKFVi22YmQyBsNj+bEGDAE4c9qaby8u6zbzs7Qj29F90f/PiYsaIEGcNn/W88e +XarNDw== +-----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 000000000..fe336b710 Binary files /dev/null and b/tests/data_files/ec_prv.sec1.der differ 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/data_files/ec_pub.der b/tests/data_files/ec_pub.der new file mode 100644 index 000000000..74c5951f6 Binary files /dev/null and b/tests/data_files/ec_pub.der differ diff --git a/tests/data_files/ec_pub.pem b/tests/data_files/ec_pub.pem new file mode 100644 index 000000000..d677d27eb --- /dev/null +++ b/tests/data_files/ec_pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEvHl9s65/COw9SWtPtBGz9iClWKUB +4CItCM/g3Irsixp78kvpKVHMW6G+uyR0kJrg +-----END PUBLIC KEY----- diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 30fc4614d..73acb4fb3 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 privkey +ecp_check_privkey: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..543175f30 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_privkey: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_privkey( &grp, &d ) == POLARSSL_ERR_ECP_GENERIC ); + + TEST_ASSERT( mpi_copy( &d, &grp.N ) == 0 ); + TEST_ASSERT( ecp_check_privkey( &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_privkey( &grp, &d ) == 0 ); ecp_group_free( &grp ); ecp_point_free( &Q ); diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 570513be4..def0021d4 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -78,113 +78,149 @@ 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 Parse Public EC Key #1 (RFC 5480, DER) +depends_on:POLARSSL_ECP_C:POLARSSL_FS_IO +x509parse_public_keyfile_ec:"data_files/ec_pub.der":0 + +X509 Parse Public EC Key #2 (RFC 5480, PEM) +depends_on:POLARSSL_PEM_C:POLARSSL_ECP_C:POLARSSL_FS_IO +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 @@ -652,22 +688,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..b6383d734 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} ); @@ -179,6 +179,54 @@ x509parse_public_keyfile:key_file:result } END_CASE +BEGIN_CASE +x509parse_public_keyfile_ec:key_file:result +{ + pk_context ctx; + int res; + + pk_init( &ctx ); + + res = x509parse_public_keyfile( &ctx, {key_file} ); + + TEST_ASSERT( res == {result} ); + + if( res == 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 ); + } + + pk_free( &ctx ); +} +END_CASE + +BEGIN_CASE +x509parse_keyfile_ec:key_file:password:result +{ + pk_context ctx; + int res; + + pk_init( &ctx ); + + res = x509parse_keyfile( &ctx, {key_file}, {password} ); + + TEST_ASSERT( res == {result} ); + + if( res == 0 ) + { + ecp_keypair *eckey; + TEST_ASSERT( ctx.type == POLARSSL_PK_ECKEY ); + eckey = (ecp_keypair *) ctx.data; + TEST_ASSERT( ecp_check_privkey( &eckey->grp, &eckey->d ) == 0 ); + } + + pk_free( &ctx ); +} +END_CASE + BEGIN_CASE x509parse_crt:crt_data:result_str:result { @@ -238,7 +286,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 +299,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;