Fix use of pem_read_buffer() in PK, DHM and X509
diff --git a/library/pkparse.c b/library/pkparse.c
index f5a9853..edf6e31 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -69,6 +69,10 @@
 
 /*
  * Load all data from a file into a given buffer.
+ *
+ * The file is expected to contain either PEM or DER encoded data.
+ * A terminating null byte is always appended. It is included in the announced
+ * length only if the data looks like it is PEM encoded.
  */
 int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
 {
@@ -106,6 +110,9 @@
 
     (*buf)[*n] = '\0';
 
+    if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
+        ++*n;
+
     return( 0 );
 }
 
@@ -128,7 +135,7 @@
         ret = mbedtls_pk_parse_key( ctx, buf, n,
                 (const unsigned char *) pwd, strlen( pwd ) );
 
-    mbedtls_zeroize( buf, n + 1 );
+    mbedtls_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -148,7 +155,7 @@
 
     ret = mbedtls_pk_parse_public_key( ctx, buf, n );
 
-    mbedtls_zeroize( buf, n + 1 );
+    mbedtls_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -1064,10 +1071,15 @@
     mbedtls_pem_init( &pem );
 
 #if defined(MBEDTLS_RSA_C)
-    ret = mbedtls_pem_read_buffer( &pem,
-                           "-----BEGIN RSA PRIVATE KEY-----",
-                           "-----END RSA PRIVATE KEY-----",
-                           key, pwd, pwdlen, &len );
+    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+    if( key[keylen - 1] != '\0' )
+        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    else
+        ret = mbedtls_pem_read_buffer( &pem,
+                               "-----BEGIN RSA PRIVATE KEY-----",
+                               "-----END RSA PRIVATE KEY-----",
+                               key, pwd, pwdlen, &len );
+
     if( ret == 0 )
     {
         if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
@@ -1092,10 +1104,14 @@
 #endif /* MBEDTLS_RSA_C */
 
 #if defined(MBEDTLS_ECP_C)
-    ret = mbedtls_pem_read_buffer( &pem,
-                           "-----BEGIN EC PRIVATE KEY-----",
-                           "-----END EC PRIVATE KEY-----",
-                           key, pwd, pwdlen, &len );
+    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+    if( key[keylen - 1] != '\0' )
+        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    else
+        ret = mbedtls_pem_read_buffer( &pem,
+                               "-----BEGIN EC PRIVATE KEY-----",
+                               "-----END EC PRIVATE KEY-----",
+                               key, pwd, pwdlen, &len );
     if( ret == 0 )
     {
         if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL )
@@ -1119,10 +1135,14 @@
         return( ret );
 #endif /* MBEDTLS_ECP_C */
 
-    ret = mbedtls_pem_read_buffer( &pem,
-                           "-----BEGIN PRIVATE KEY-----",
-                           "-----END PRIVATE KEY-----",
-                           key, NULL, 0, &len );
+    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+    if( key[keylen - 1] != '\0' )
+        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    else
+        ret = mbedtls_pem_read_buffer( &pem,
+                               "-----BEGIN PRIVATE KEY-----",
+                               "-----END PRIVATE KEY-----",
+                               key, NULL, 0, &len );
     if( ret == 0 )
     {
         if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
@@ -1138,10 +1158,14 @@
         return( ret );
 
 #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
-    ret = mbedtls_pem_read_buffer( &pem,
-                           "-----BEGIN ENCRYPTED PRIVATE KEY-----",
-                           "-----END ENCRYPTED PRIVATE KEY-----",
-                           key, NULL, 0, &len );
+    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+    if( key[keylen - 1] != '\0' )
+        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    else
+        ret = mbedtls_pem_read_buffer( &pem,
+                               "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+                               "-----END ENCRYPTED PRIVATE KEY-----",
+                               key, NULL, 0, &len );
     if( ret == 0 )
     {
         if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
@@ -1231,10 +1255,15 @@
     mbedtls_pem_context pem;
 
     mbedtls_pem_init( &pem );
-    ret = mbedtls_pem_read_buffer( &pem,
-            "-----BEGIN PUBLIC KEY-----",
-            "-----END PUBLIC KEY-----",
-            key, NULL, 0, &len );
+
+    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+    if( 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 );
 
     if( ret == 0 )
     {