diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 611650204..1eb7e69ed 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -29,7 +29,7 @@ #include "asn1.h" -#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret +#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else g += ret; } while( 0 ) #ifdef __cplusplus extern "C" { diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index ad31bff66..c7689c1ab 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -133,6 +133,7 @@ ecp_keypair; */ #define POLARSSL_ECP_MAX_BITS 521 #define POLARSSL_ECP_MAX_BYTES ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 ) +#define POLARSSL_ECP_MAX_PT_LEN ( 2 * POLARSSL_ECP_MAX_BYTES + 1 ) /* * Maximum window size (actually, NAF width) used for point multipliation. diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index b0e781fc1..6981237f7 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -370,8 +370,9 @@ 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 ); +#if defined(POLARSSL_ECP_C) /** - * \brief Translate ECParameters OID into an EC group identifier + * \brief Translate NamedCurve OID into an EC group identifier * * \param oid OID to use * \param grp_id place to store group id @@ -380,6 +381,19 @@ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); */ int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id ); +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_ec_grp( ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* POLARSSL_ECP_C */ + #if defined(POLARSSL_MD_C) /** * \brief Translate SignatureAlgorithm OID into md_type and pk_type diff --git a/library/oid.c b/library/oid.c index f37bbf6e7..1aaf8e887 100644 --- a/library/oid.c +++ b/library/oid.c @@ -369,6 +369,7 @@ 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); +#if defined(POLARSSL_ECP_C) /* * For namedCurve (RFC 5480) */ @@ -407,6 +408,8 @@ static const oid_ecp_grp_t oid_ecp_grp[] = 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); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, ecp_group_id, grp_id); +#endif /* POLARSSL_ECP_C */ #if defined(POLARSSL_CIPHER_C) /* diff --git a/library/x509write.c b/library/x509write.c index 3aeb79526..6be1bc48e 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -117,6 +117,7 @@ exit: return( ret ); } +#if defined(POLARSSL_RSA_C) /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n @@ -137,6 +138,56 @@ static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start, return( len ); } +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * EC public key is an EC point + */ +static int x509_write_ec_pubkey( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[POLARSSL_ECP_MAX_PT_LEN]; + + if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q, + POLARSSL_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p - start < (int) len ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int x509_write_ec_algparam( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + return( len ); +} +#endif /* POLARSSL_ECP_C */ void x509write_csr_init( x509write_csr *ctx ) { @@ -439,16 +490,20 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) int ret; unsigned char *c; size_t len = 0; - rsa_context *rsa; - - if( !pk_can_do( key, POLARSSL_PK_RSA ) ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - - rsa = pk_rsa( *key ); c = buf + size; - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) ); +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, pk_rsa( *key ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + ASN1_CHK_ADD( len, x509_write_ec_pubkey( &c, buf, pk_ec( *key ) ) ); + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); if( c - buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); @@ -464,8 +519,32 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + size_t alg_len = 0; + + ASN1_CHK_ADD( alg_len, x509_write_ec_algparam( &c, buf, + pk_ec( *key ) ) ); + + ASN1_CHK_ADD( alg_len, asn1_write_oid( &c, buf, + OID_EC_ALG_UNRESTRICTED, OID_SIZE( OID_EC_ALG_UNRESTRICTED ) ) ); + + ASN1_CHK_ADD( alg_len, asn1_write_len( &c, buf, alg_len ) ); + ASN1_CHK_ADD( alg_len, asn1_write_tag( &c, buf, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + len += alg_len; + } + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 5a6597665..22d338c41 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -33,3 +33,7 @@ x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1 Public key write check RSA depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C x509_pubkey_check:"data_files/server1.pubkey" + +Public key write check EC +depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C +x509_pubkey_check:"data_files/ec_pub.pem"