Add support for public keys encoded with PKCS#1

1) Add support for public keys encoded with PKCS#1
2) Add tests for PKCS#1 PEM and DER, and PKCS#8 DER
diff --git a/ChangeLog b/ChangeLog
index b3d4d51..f13982b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
 
 Features
    * Allow comments in test data files.
+   * Add support for public keys encoded in PKCS#1 format
 
 Bugfix
    * Fix memory leak in mbedtls_ssl_set_hostname() when called multiple times.
diff --git a/library/pkparse.c b/library/pkparse.c
index efdf437..1d573a4 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -637,11 +637,11 @@
 
 #if defined(MBEDTLS_RSA_C)
 /*
- * Parse a PKCS#1 encoded private RSA key
+ * Parse a PKCS#1 encoded private( mode 0 )/public( mode 1 ) RSA key
  */
 static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
                                    const unsigned char *key,
-                                   size_t keylen )
+                                   size_t keylen , int mode)
 {
     int ret;
     size_t len;
@@ -649,7 +649,16 @@
 
     p = (unsigned char *) key;
     end = p + keylen;
+    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+    {
+        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
 
+    end = p + len;
+
+    if( mode == 0 )
+    {
     /*
      * This function parses the RSAPrivateKey (PKCS#1)
      *
@@ -666,52 +675,77 @@
      *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
      *  }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+        {
+            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        }
+
+        if( rsa->ver != 0 )
+        {
+            return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
+        }
+
+        if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
+        {
+            mbedtls_rsa_free( rsa );
+            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        }
+
+        rsa->len = mbedtls_mpi_size( &rsa->N );
+
+        if( p != end )
+        {
+            mbedtls_rsa_free( rsa );
+            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        }
+
+        if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 )
+        {
+            mbedtls_rsa_free( rsa );
+            return( ret );
+        }
     }
-
-    end = p + len;
-
-    if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+    else /* public key*/
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+    /*
+     * This function parses the RSAPublicKey (PKCS#1)
+     *
+     *  RSAPublicKey ::= SEQUENCE {
+     *                   modulus           INTEGER,  -- n
+     *                   publicExponent    INTEGER   -- e
+     *                   }
+     */
+        if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
+            ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 )
+        {
+            mbedtls_rsa_free( rsa );
+            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        }
+
+        rsa->len = mbedtls_mpi_size( &rsa->N );
+
+        if( p != end )
+        {
+             mbedtls_rsa_free( rsa );
+             return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
+                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        }
+
+        if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 )
+        {
+             mbedtls_rsa_free( rsa );
+             return( ret );
+        }
+
     }
-
-    if( rsa->ver != 0 )
-    {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
-    }
-
-    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
-    {
-        mbedtls_rsa_free( rsa );
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
-    }
-
-    rsa->len = mbedtls_mpi_size( &rsa->N );
-
-    if( p != end )
-    {
-        mbedtls_rsa_free( rsa );
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 )
-    {
-        mbedtls_rsa_free( rsa );
-        return( ret );
-    }
-
     return( 0 );
 }
 #endif /* MBEDTLS_RSA_C */
@@ -907,7 +941,7 @@
 #if defined(MBEDTLS_RSA_C)
     if( pk_alg == MBEDTLS_PK_RSA )
     {
-        if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 )
+        if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len, 0 ) ) != 0 )
         {
             mbedtls_pk_free( pk );
             return( ret );
@@ -1086,7 +1120,7 @@
 
         if( ( ret = mbedtls_pk_setup( pk, pk_info                    ) ) != 0 ||
             ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
-                                            pem.buf, pem.buflen ) ) != 0 )
+                                            pem.buf, pem.buflen, 0 ) ) != 0 )
         {
             mbedtls_pk_free( pk );
         }
@@ -1218,7 +1252,7 @@
         return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
 
     if( ( ret = mbedtls_pk_setup( pk, pk_info                           ) ) != 0 ||
-        ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 )
+        ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen, 0 ) ) == 0 )
     {
         return( 0 );
     }
@@ -1255,12 +1289,43 @@
     mbedtls_pem_context pem;
 
     mbedtls_pem_init( &pem );
-
+#if defined(MBEDTLS_RSA_C)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
     if( keylen == 0 || key[keylen - 1] != '\0' )
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     else
         ret = mbedtls_pem_read_buffer( &pem,
+                               "-----BEGIN RSA PUBLIC KEY-----",
+                               "-----END RSA PUBLIC KEY-----",
+                               key, NULL, 0, &len );
+
+    if( ret == 0 )
+    {
+         const mbedtls_pk_info_t *pk_info;
+         if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
+              return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+
+         if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
+               return( ret );
+
+         if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *ctx ),
+                                             pem.buf, pem.buflen, 1 ) ) != 0 )
+                 mbedtls_pk_free( ctx );
+        mbedtls_pem_free( &pem );
+        return( ret );
+    }
+    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        mbedtls_pem_free( &pem );
+        return( ret );
+    }
+#endif /* MBEDTLS_RSA_C */
+
+       /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+    if( keylen == 0 || key[keylen - 1] != '\0' )
+        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    else
+        ret = mbedtls_pem_read_buffer( &pem,
                 "-----BEGIN PUBLIC KEY-----",
                 "-----END PUBLIC KEY-----",
                 key, NULL, 0, &len );
diff --git a/tests/data_files/format_gen_der.pub b/tests/data_files/format_gen_der.pub
new file mode 100644
index 0000000..fe42998
--- /dev/null
+++ b/tests/data_files/format_gen_der.pub
Binary files differ
diff --git a/tests/data_files/public_rsa_key.der b/tests/data_files/public_rsa_key.der
new file mode 100644
index 0000000..376b79a
--- /dev/null
+++ b/tests/data_files/public_rsa_key.der
Binary files differ
diff --git a/tests/data_files/public_rsa_key.pem b/tests/data_files/public_rsa_key.pem
new file mode 100644
index 0000000..3add85c
--- /dev/null
+++ b/tests/data_files/public_rsa_key.pem
@@ -0,0 +1,8 @@
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEA2UFMidUiQFATstnnSR6Q97QThcnPzkATdIM5LQ1HMLLbzmTrLRa1
+mjneNIh9jE+ZpPDEXVcUAwrvgCOb/MQeqetYNxU8FHU1Baw76ZCSe91GPK6xSdIW
+ovsrsPCKnu8qQBYGTV/OQ4Y6KvVL5NvcLsQfxGgOYtFuD6xn6oE25SwScqWD5y4Q
+zB3Rm7u23xBBcLr+zb4fVjBOGS1vIVNnxj7aDYJTB9ZO2i+5MUch0BPHhsd3gf//
+u5ECyItnc+B50apbc/7wziwX1ABMvGVIWbvEMG68Vgst2kX91ojiDPZJej/c2xLR
+gpzage6SGEIQiCDQVIudSMnzZoltyMUmNwIDAQAB
+-----END RSA PUBLIC KEY-----
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
index 9c0edbb..f34fc3c 100644
--- a/tests/suites/test_suite_pkparse.data
+++ b/tests/suites/test_suite_pkparse.data
@@ -106,6 +106,18 @@
 depends_on:MBEDTLS_MD5_C:MBEDTLS_PEM_PARSE_C
 pk_parse_public_keyfile_rsa:"data_files/format_gen.pub":0
 
+Parse Public RSA Key #1 (PKCS#8 wrapped, DER)
+depends_on:MBEDTLS_MD5_C:MBEDTLS_PEM_PARSE_C
+pk_parse_public_keyfile_rsa:"data_files/format_gen_der.pub":0
+
+Parse Public RSA Key #3 (PKCS#1 wrapped)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PEM_PARSE_C
+pk_parse_public_keyfile_rsa:"data_files/public_rsa_key.pem":0
+
+Parse Public RSA Key #4 (PKCS#1 wrapped, DER)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PEM_PARSE_C
+pk_parse_public_keyfile_rsa:"data_files/public_rsa_key.der":0
+
 Parse Public EC Key #1 (RFC 5480, DER)
 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 pk_parse_public_keyfile_ec:"data_files/ec_pub.der":0