Add EC support to x509write_pubkey
diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h
index 6116502..1eb7e69 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 ad31bff..c7689c1 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -133,6 +133,7 @@
  */
 #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 b0e781f..6981237 100644
--- a/include/polarssl/oid.h
+++ b/include/polarssl/oid.h
@@ -370,8 +370,9 @@
  */
 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_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 f37bbf6..1aaf8e8 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -369,6 +369,7 @@
 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 @@
 
 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 3aeb795..6be1bc4 100644
--- a/library/x509write.c
+++ b/library/x509write.c
@@ -117,6 +117,7 @@
     return( ret );
 }
 
+#if defined(POLARSSL_RSA_C)
 /*
  *  RSAPublicKey ::= SEQUENCE {
  *      modulus           INTEGER,  -- n
@@ -137,6 +138,56 @@
 
     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 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 @@
     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 5a65976..22d338c 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -33,3 +33,7 @@
 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"