Add missing ret code checks in PEM module

Add missing return code checks in the functions pem_des_decrypt(),
pem_3des_decrypt() and pem_aes_decrypt() so that the calling function
mbedtls_pem_read_buffer() is notified of errors reported by the crypto
primitives AES, DES and 3DES.
This commit is contained in:
Andres AG 2017-02-22 16:23:26 +00:00
parent cef21e4cd9
commit 4590955b96
2 changed files with 49 additions and 20 deletions

View file

@ -14,6 +14,12 @@ Bugfix
in RFC 6347 Section 4.3.1. This could cause the execution of the in RFC 6347 Section 4.3.1. This could cause the execution of the
renegotiation routines at unexpected times when the protocol is DTLS. Found renegotiation routines at unexpected times when the protocol is DTLS. Found
by wariua. #687 by wariua. #687
* Fix unchecked return codes from AES, DES and 3DES functions in
pem_aes_decrypt(), pem_des_decrypt() and pem_des3_decrypt() respectively.
If a call to one of the functions of the cryptographic primitive modules
failed, the error may not be noticed by the function
mbedtls_pem_read_buffer() causing it to return invalid values. Found by
Guido Vranken. #756
= mbed TLS 2.4.1 branch released 2016-12-13 = mbed TLS 2.4.1 branch released 2016-12-13

View file

@ -134,45 +134,55 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
/* /*
* Decrypt with DES-CBC, using PBKDF1 for key derivation * Decrypt with DES-CBC, using PBKDF1 for key derivation
*/ */
static void pem_des_decrypt( unsigned char des_iv[8], static int pem_des_decrypt( unsigned char des_iv[8],
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_des_context des_ctx; mbedtls_des_context des_ctx;
unsigned char des_key[8]; unsigned char des_key[8];
int ret;
mbedtls_des_init( &des_ctx ); mbedtls_des_init( &des_ctx );
pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
mbedtls_des_setkey_dec( &des_ctx, des_key ); if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, goto exit;
ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
des_iv, buf, buf ); des_iv, buf, buf );
exit:
mbedtls_des_free( &des_ctx ); mbedtls_des_free( &des_ctx );
mbedtls_zeroize( des_key, 8 ); mbedtls_zeroize( des_key, 8 );
return( ret );
} }
/* /*
* Decrypt with 3DES-CBC, using PBKDF1 for key derivation * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
*/ */
static void pem_des3_decrypt( unsigned char des3_iv[8], static int pem_des3_decrypt( unsigned char des3_iv[8],
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_des3_context des3_ctx; mbedtls_des3_context des3_ctx;
unsigned char des3_key[24]; unsigned char des3_key[24];
int ret;
mbedtls_des3_init( &des3_ctx ); mbedtls_des3_init( &des3_ctx );
pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, goto exit;
ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
des3_iv, buf, buf ); des3_iv, buf, buf );
exit:
mbedtls_des3_free( &des3_ctx ); mbedtls_des3_free( &des3_ctx );
mbedtls_zeroize( des3_key, 24 ); mbedtls_zeroize( des3_key, 24 );
return( ret );
} }
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
@ -180,23 +190,28 @@ static void pem_des3_decrypt( unsigned char des3_iv[8],
/* /*
* Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
*/ */
static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_aes_context aes_ctx; mbedtls_aes_context aes_ctx;
unsigned char aes_key[32]; unsigned char aes_key[32];
int ret;
mbedtls_aes_init( &aes_ctx ); mbedtls_aes_init( &aes_ctx );
pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, goto exit;
ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
aes_iv, buf, buf ); aes_iv, buf, buf );
exit:
mbedtls_aes_free( &aes_ctx ); mbedtls_aes_free( &aes_ctx );
mbedtls_zeroize( aes_key, keylen ); mbedtls_zeroize( aes_key, keylen );
return( ret );
} }
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
@ -343,22 +358,30 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
} }
ret = 0;
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_AES_C)
if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
if( ret != 0 )
{
mbedtls_free( buf );
return( ret );
}
/* /*
* The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
* length bytes (allow 4 to be sure) in all known use cases. * length bytes (allow 4 to be sure) in all known use cases.