Fix use of pem_read_buffer() in PK, DHM and X509
diff --git a/library/dhm.c b/library/dhm.c
index c5e41a3..92fd611 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -421,10 +421,14 @@
mbedtls_pem_init( &pem );
- ret = mbedtls_pem_read_buffer( &pem,
- "-----BEGIN DH PARAMETERS-----",
- "-----END DH PARAMETERS-----",
- dhmin, NULL, 0, &dhminlen );
+ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+ if( dhmin[dhminlen - 1] != '\0' )
+ ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedtls_pem_read_buffer( &pem,
+ "-----BEGIN DH PARAMETERS-----",
+ "-----END DH PARAMETERS-----",
+ dhmin, NULL, 0, &dhminlen );
if( ret == 0 )
{
@@ -503,6 +507,10 @@
#if defined(MBEDTLS_FS_IO)
/*
* 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.
*/
static int load_file( const char *path, unsigned char **buf, size_t *n )
{
@@ -540,6 +548,9 @@
(*buf)[*n] = '\0';
+ if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
+ ++*n;
+
return( 0 );
}
@@ -557,7 +568,7 @@
ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
- mbedtls_zeroize( buf, n + 1 );
+ mbedtls_zeroize( buf, n );
mbedtls_free( buf );
return( ret );
@@ -584,7 +595,7 @@
mbedtls_printf( " DHM parameter load: " );
if( ( ret = mbedtls_dhm_parse_dhm( &dhm, (const unsigned char *) mbedtls_test_dhm_params,
- strlen( mbedtls_test_dhm_params ) ) ) != 0 )
+ mbedtls_test_dhm_params_len ) ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
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 )
{
diff --git a/library/x509.c b/library/x509.c
index 55daf74..08a1ec3 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -1008,7 +1008,7 @@
mbedtls_x509_crt_init( &clicert );
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
- strlen( mbedtls_test_cli_crt ) );
+ mbedtls_test_cli_crt_len );
if( ret != 0 )
{
if( verbose != 0 )
@@ -1020,7 +1020,7 @@
mbedtls_x509_crt_init( &cacert );
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
- strlen( mbedtls_test_ca_crt ) );
+ mbedtls_test_ca_crt_len );
if( ret != 0 )
{
if( verbose != 0 )
diff --git a/library/x509_crl.c b/library/x509_crl.c
index a915aba..fc4b2df 100644
--- a/library/x509_crl.c
+++ b/library/x509_crl.c
@@ -503,6 +503,11 @@
do
{
mbedtls_pem_init( &pem );
+
+ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+ if( buf[buflen - 1] != '\0' )
+ ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN X509 CRL-----",
"-----END X509 CRL-----",
@@ -532,7 +537,9 @@
return( ret );
}
}
- while( is_pem && buflen > 0 );
+ /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
+ * And a valid CRL cannot be less than 1 byte anyway. */
+ while( is_pem && buflen > 1 );
if( is_pem )
return( 0 );
@@ -556,7 +563,7 @@
ret = mbedtls_x509_crl_parse( chain, buf, n );
- mbedtls_zeroize( buf, n + 1 );
+ mbedtls_zeroize( buf, n );
mbedtls_free( buf );
return( ret );
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 4ebae77..059b60f 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -852,8 +852,11 @@
* one or more PEM certificates.
*/
#if defined(MBEDTLS_PEM_PARSE_C)
- if( strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
+ if( buf[buflen - 1] == '\0' &&
+ strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
+ {
buf_format = MBEDTLS_X509_FORMAT_PEM;
+ }
#endif
if( buf_format == MBEDTLS_X509_FORMAT_DER )
@@ -865,11 +868,13 @@
int ret;
mbedtls_pem_context pem;
- while( buflen > 0 )
+ /* 1 rather than 0 since the terminating NULL byte is counted in */
+ while( buflen > 1 )
{
size_t use_len;
mbedtls_pem_init( &pem );
+ /* If we get there, we know the string is null-terminated */
ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN CERTIFICATE-----",
"-----END CERTIFICATE-----",
@@ -953,7 +958,7 @@
ret = mbedtls_x509_crt_parse( chain, buf, n );
- mbedtls_zeroize( buf, n + 1 );
+ mbedtls_zeroize( buf, n );
mbedtls_free( buf );
return( ret );
diff --git a/library/x509_csr.c b/library/x509_csr.c
index f6afa1e..5ec1b86 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -274,10 +274,15 @@
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init( &pem );
- ret = mbedtls_pem_read_buffer( &pem,
- "-----BEGIN CERTIFICATE REQUEST-----",
- "-----END CERTIFICATE REQUEST-----",
- buf, NULL, 0, &use_len );
+
+ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
+ if( buf[buflen - 1] != '\0' )
+ ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedtls_pem_read_buffer( &pem,
+ "-----BEGIN CERTIFICATE REQUEST-----",
+ "-----END CERTIFICATE REQUEST-----",
+ buf, NULL, 0, &use_len );
if( ret == 0 )
{
@@ -315,7 +320,7 @@
ret = mbedtls_x509_csr_parse( csr, buf, n );
- mbedtls_zeroize( buf, n + 1 );
+ mbedtls_zeroize( buf, n );
mbedtls_free( buf );
return( ret );