From 713c9e187f2db498b74d9719f16fec04fce7ff2e Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Sep 2017 16:46:24 +0100 Subject: [PATCH] Use in-place decryption in pk_parse_pkcs8_encrypted_der The stack buffer used to hold the decrypted key in pk_parse_pkcs8_encrypted_der was statically sized to 2048 bytes, which is not enough for DER encoded 4096bit RSA keys. This commit resolves the problem by performing the key-decryption in-place, circumventing the introduction of another stack or heap copy of the key. There are two situations where pk_parse_pkcs8_encrypted_der is invoked: 1. When processing a PEM-encoded encrypted key in pk_parse_key. This does not need adaption since the PEM context used to hold the decoded key is already constructed and owned by pk_parse_key. 2. When processing a DER-encoded encrypted key in pk_parse_key. In this case, pk_parse_key calls pk_parse_pkcs8_encrypted_der with the buffer provided by the user, which is declared const. The commit therefore adds a small code paths making a copy of the keybuffer before calling pk_parse_pkcs8_encrypted_der. --- library/pkparse.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/library/pkparse.c b/library/pkparse.c index 39c51f6485..ea68a3d3c5 100644 --- a/library/pkparse.c +++ b/library/pkparse.c @@ -930,12 +930,12 @@ static int pk_parse_key_pkcs8_unencrypted_der( #if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) static int pk_parse_key_pkcs8_encrypted_der( pk_context *pk, - const unsigned char *key, size_t keylen, + unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { int ret, decrypted = 0; size_t len; - unsigned char buf[2048]; + unsigned char *buf; unsigned char *p, *end; asn1_buf pbe_alg_oid, pbe_params; #if defined(POLARSSL_PKCS12_C) @@ -943,8 +943,6 @@ static int pk_parse_key_pkcs8_encrypted_der( md_type_t md_alg; #endif - memset( buf, 0, sizeof( buf ) ); - p = (unsigned char *) key; end = p + keylen; @@ -979,8 +977,7 @@ static int pk_parse_key_pkcs8_encrypted_der( if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); - if( len > sizeof( buf ) ) - return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + buf = p; /* * Decrypt EncryptedData with appropriate PDE @@ -1073,7 +1070,7 @@ int pk_parse_key( pk_context *pk, if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); - if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), pem.buf, pem.buflen ) ) != 0 ) { @@ -1101,7 +1098,7 @@ int pk_parse_key( pk_context *pk, if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); - if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), pem.buf, pem.buflen ) ) != 0 ) { @@ -1170,12 +1167,24 @@ int pk_parse_key( pk_context *pk, * error */ #if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C) - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, - pwd, pwdlen ) ) == 0 ) { - return( 0 ); + unsigned char *key_copy; + + if( ( key_copy = polarssl_malloc( keylen ) ) == NULL ) + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + polarssl_zeroize( key_copy, keylen ); + polarssl_free( key_copy ); } + if( ret == 0 ) + return( 0 ); + pk_free( pk ); if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH ) @@ -1193,7 +1202,7 @@ int pk_parse_key( pk_context *pk, if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); - if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 ) { return( 0 ); @@ -1206,7 +1215,7 @@ int pk_parse_key( pk_context *pk, if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL ) return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG ); - if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || + if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 ) { return( 0 );