Merge branch 'parse-ec-key' into development
diff --git a/doxygen/input/doc_x509.h b/doxygen/input/doc_x509.h
index 56bb49b..16fe75a 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 2ad986d..e709b40 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
@@ -71,6 +85,20 @@
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
*
* \return 0 if successful, or 1 if the test failed
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index 4b02181..c1f08c9 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -92,6 +92,25 @@
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.
*
* These also are the NIST-recommended ECP groups, are the random ECP groups
@@ -139,6 +158,16 @@
*/
#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)
*/
@@ -150,6 +179,11 @@
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
*/
void ecp_point_free( ecp_point *pt );
@@ -160,6 +194,11 @@
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
*
* \param pt Destination point
@@ -190,25 +229,6 @@
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
*
* \param P Destination point
@@ -399,6 +419,44 @@
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
*
* \param grp ECP group
@@ -409,6 +467,10 @@
*
* \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 c326154..f8c23e6 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 e63c169..a39055b 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_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 969faa2..cc6cba1 100644
--- a/include/polarssl/pem.h
+++ b/include/polarssl/pem.h
@@ -84,6 +84,10 @@
* 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 d9639ee..00f8cfc 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 @@
*/
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 86624ec..f0c0e7a 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 @@
*
* \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 @@
*
* \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 @@
*
* \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 @@
*
* \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 948737d..3fa76a9 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -39,6 +39,7 @@
pkcs5.c
pkcs11.c
pkcs12.c
+ pk.c
rsa.c
sha1.c
sha256.c
diff --git a/library/Makefile b/library/Makefile
index f670dcc..48c3bdc 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -49,6 +49,7 @@
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 d683457..11b7f5e 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -174,6 +174,33 @@
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 af18e5b..9e7a967 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -91,6 +91,20 @@
}
/*
+ * 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
*/
void ecp_point_free( ecp_point *pt )
@@ -118,6 +132,20 @@
}
/*
+ * 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
*/
int ecp_set_zero( ecp_point *pt )
@@ -700,51 +728,6 @@
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)
*/
static int ecp_normalize( const ecp_group *grp, ecp_point *pt )
@@ -1278,6 +1261,63 @@
}
/*
+ * 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)
*/
int ecp_gen_keypair( const ecp_group *grp, mpi *d, ecp_point *Q,
diff --git a/library/error.c b/library/error.c
index 7042bbd..0a739b5 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 @@
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 @@
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 @@
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 5cd9a59..449b3e1 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -248,7 +248,6 @@
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 @@
#endif /* POLARSSL_MD_C */
/*
- * For PublicKeyInfo
+ * For PublicKeyInfo (PKCS1, RFC 5480)
*/
typedef struct {
oid_descriptor_t descriptor;
@@ -326,6 +325,14 @@
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 @@
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 @@
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 c4c5cb4..3f6d330 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -332,8 +332,13 @@
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 0000000..71505ed
--- /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 <polarssl_maintainer at polarssl.org>
+ *
+ * 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 <stdlib.h>
+
+/*
+ * 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 ea3a24a..c5f9049 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -164,15 +164,105 @@
* 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 @@
* 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 @@
*
* 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 @@
* 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 @@
* 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 @@
* 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 @@
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 @@
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 @@
/*
* 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 @@
/*
* 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 @@
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 @@
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 @@
* 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 @@
}
/*
- * 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 @@
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 @@
#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 @@
((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 @@
/*
* 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 @@
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 @@
#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 @@
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 2f906c4..bea996a 100644
--- a/programs/pkey/key_app.c
+++ b/programs/pkey/key_app.c
@@ -164,14 +164,14 @@
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 @@
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 feb2ecc..88cb907 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -238,14 +238,14 @@
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 @@
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 8238708..e848f54 100644
--- a/programs/pkey/rsa_sign_pss.c
+++ b/programs/pkey/rsa_sign_pss.c
@@ -101,7 +101,7 @@
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 b44daa0..00d7378 100644
--- a/programs/pkey/rsa_verify_pss.c
+++ b/programs/pkey/rsa_verify_pss.c
@@ -83,9 +83,9 @@
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 1ddb86d..036cc67 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -533,11 +533,11 @@
#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 @@
#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 e021ebb..986458b 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -139,7 +139,7 @@
/*
* This demonstration program uses embedded test certificates.
* Instead, you may want to use x509parse_crtfile() to read the
- * server and CA certificates, as well as x509parse_keyfile().
+ * 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 @@
}
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 4b5d177..665cdbf 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -532,11 +532,11 @@
#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 @@
#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 3059236..dbb193b 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -117,7 +117,7 @@
/*
* This demonstration program uses embedded test certificates.
* Instead, you may want to use x509parse_crtfile() to read the
- * server and CA certificates, as well as x509parse_keyfile().
+ * 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 @@
}
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 6197cda..db2d123 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -501,11 +501,11 @@
#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 @@
#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 9726282..84dd38b 100644
--- a/programs/test/o_p_test.c
+++ b/programs/test/o_p_test.c
@@ -104,7 +104,7 @@
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 83a2a01..bf4684b 100644
--- a/programs/test/ssl_cert_test.c
+++ b/programs/test/ssl_cert_test.c
@@ -196,10 +196,10 @@
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 607b092..ce45ccf 100644
--- a/programs/test/ssl_test.c
+++ b/programs/test/ssl_test.c
@@ -229,11 +229,11 @@
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 20418ab..cbd6252 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -267,14 +267,14 @@
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 009107b..7257ae6 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -13,7 +13,7 @@
"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 0000000..f2bd2a9
--- /dev/null
+++ b/tests/data_files/ec_prv.pk8.der
Binary files differ
diff --git a/tests/data_files/ec_prv.pk8.pem b/tests/data_files/ec_prv.pk8.pem
new file mode 100644
index 0000000..dbeab7c
--- /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 0000000..db0b5bd
--- /dev/null
+++ b/tests/data_files/ec_prv.pk8.pw.der
Binary files 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 0000000..7413d1e
--- /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 0000000..fe336b7
--- /dev/null
+++ b/tests/data_files/ec_prv.sec1.der
Binary files differ
diff --git a/tests/data_files/ec_prv.sec1.pem b/tests/data_files/ec_prv.sec1.pem
new file mode 100644
index 0000000..a8a7990
--- /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 0000000..62a0860
--- /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 0000000..74c5951
--- /dev/null
+++ b/tests/data_files/ec_pub.der
Binary files differ
diff --git a/tests/data_files/ec_pub.pem b/tests/data_files/ec_pub.pem
new file mode 100644
index 0000000..d677d27
--- /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 30fc461..73acb4f 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -245,6 +245,9 @@
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 a051bd7..543175f 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -438,6 +438,28 @@
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
{
ecp_group grp;
@@ -455,8 +477,8 @@
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 570513b..def0021 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -78,113 +78,149 @@
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 @@
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 8b69327..b6383d7 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -138,14 +138,14 @@
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 @@
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} );
@@ -180,6 +180,54 @@
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
{
x509_cert crt;
@@ -238,7 +286,7 @@
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 @@
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 8ce3e71..e3bf12f 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -41,7 +41,7 @@
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;