mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-03-08 10:09:54 +00:00
Merge pull request #5310 from paul-elliott-arm/pkcs12_fix_2.x
Backport 2.x: Fixes for pkcs12 with NULL and/or zero length password
This commit is contained in:
commit
384b98bdae
5
ChangeLog.d/fix-pkcs12-null-password.txt
Normal file
5
ChangeLog.d/fix-pkcs12-null-password.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
Bugfix
|
||||||
|
* Fix a potential invalid pointer dereference and infinite loop bugs in
|
||||||
|
pkcs12 functions when the password is empty. Fix the documentation to
|
||||||
|
better describe the inputs to these functions and their possible values.
|
||||||
|
Fixes #5136.
|
|
@ -79,11 +79,13 @@ int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode,
|
||||||
* \brief PKCS12 Password Based function (encryption / decryption)
|
* \brief PKCS12 Password Based function (encryption / decryption)
|
||||||
* for cipher-based and mbedtls_md-based PBE's
|
* for cipher-based and mbedtls_md-based PBE's
|
||||||
*
|
*
|
||||||
* \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
|
* \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure
|
||||||
* \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT
|
* \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or
|
||||||
|
* #MBEDTLS_PKCS12_PBE_DECRYPT
|
||||||
* \param cipher_type the cipher used
|
* \param cipher_type the cipher used
|
||||||
* \param md_type the mbedtls_md used
|
* \param md_type the mbedtls_md used
|
||||||
* \param pwd the password used (may be NULL if no password is used)
|
* \param pwd Latin1-encoded password used. This may only be \c NULL when
|
||||||
|
* \p pwdlen is 0. No null terminator should be used.
|
||||||
* \param pwdlen length of the password (may be 0)
|
* \param pwdlen length of the password (may be 0)
|
||||||
* \param input the input data
|
* \param input the input data
|
||||||
* \param len data length
|
* \param len data length
|
||||||
|
@ -104,18 +106,24 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
|
||||||
* to produce pseudo-random bits for a particular "purpose".
|
* to produce pseudo-random bits for a particular "purpose".
|
||||||
*
|
*
|
||||||
* Depending on the given id, this function can produce an
|
* Depending on the given id, this function can produce an
|
||||||
* encryption/decryption key, an nitialization vector or an
|
* encryption/decryption key, an initialization vector or an
|
||||||
* integrity key.
|
* integrity key.
|
||||||
*
|
*
|
||||||
* \param data buffer to store the derived data in
|
* \param data buffer to store the derived data in
|
||||||
* \param datalen length to fill
|
* \param datalen length of buffer to fill
|
||||||
* \param pwd password to use (may be NULL if no password is used)
|
* \param pwd The password to use. For compliance with PKCS#12 §B.1, this
|
||||||
* \param pwdlen length of the password (may be 0)
|
* should be a BMPString, i.e. a Unicode string where each
|
||||||
* \param salt salt buffer to use
|
* character is encoded as 2 bytes in big-endian order, with
|
||||||
* \param saltlen length of the salt
|
* no byte order mark and with a null terminator (i.e. the
|
||||||
|
* last two bytes should be 0x00 0x00).
|
||||||
|
* \param pwdlen length of the password (may be 0).
|
||||||
|
* \param salt Salt buffer to use This may only be \c NULL when
|
||||||
|
* \p saltlen is 0.
|
||||||
|
* \param saltlen length of the salt (may be zero)
|
||||||
* \param mbedtls_md mbedtls_md type to use during the derivation
|
* \param mbedtls_md mbedtls_md type to use during the derivation
|
||||||
* \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY,
|
* \param id id that describes the purpose (can be
|
||||||
* MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY)
|
* #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or
|
||||||
|
* #MBEDTLS_PKCS12_DERIVE_MAC_KEY)
|
||||||
* \param iterations number of iterations
|
* \param iterations number of iterations
|
||||||
*
|
*
|
||||||
* \return 0 if successful, or a MD, BIGNUM type error.
|
* \return 0 if successful, or a MD, BIGNUM type error.
|
||||||
|
|
|
@ -179,6 +179,9 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
|
||||||
mbedtls_cipher_context_t cipher_ctx;
|
mbedtls_cipher_context_t cipher_ctx;
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
|
|
||||||
|
if( pwd == NULL && pwdlen != 0 )
|
||||||
|
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
|
||||||
|
|
||||||
cipher_info = mbedtls_cipher_info_from_type( cipher_type );
|
cipher_info = mbedtls_cipher_info_from_type( cipher_type );
|
||||||
if( cipher_info == NULL )
|
if( cipher_info == NULL )
|
||||||
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
|
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
|
||||||
|
@ -231,6 +234,8 @@ static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
|
||||||
unsigned char *p = data;
|
unsigned char *p = data;
|
||||||
size_t use_len;
|
size_t use_len;
|
||||||
|
|
||||||
|
if( filler != NULL && fill_len != 0 )
|
||||||
|
{
|
||||||
while( data_len > 0 )
|
while( data_len > 0 )
|
||||||
{
|
{
|
||||||
use_len = ( data_len > fill_len ) ? fill_len : data_len;
|
use_len = ( data_len > fill_len ) ? fill_len : data_len;
|
||||||
|
@ -238,6 +243,15 @@ static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
|
||||||
p += use_len;
|
p += use_len;
|
||||||
data_len -= use_len;
|
data_len -= use_len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If either of the above are not true then clearly there is nothing
|
||||||
|
* that this function can do. The function should *not* be called
|
||||||
|
* under either of those circumstances, as you could end up with an
|
||||||
|
* incorrect output but for safety's sake, leaving the check in as
|
||||||
|
* otherwise we could end up with memory corruption.*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
|
@ -253,6 +267,8 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
|
unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
int use_password = 0;
|
||||||
|
int use_salt = 0;
|
||||||
|
|
||||||
size_t hlen, use_len, v, i;
|
size_t hlen, use_len, v, i;
|
||||||
|
|
||||||
|
@ -263,6 +279,15 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
|
if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
|
||||||
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
|
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
|
||||||
|
|
||||||
|
if( pwd == NULL && pwdlen != 0 )
|
||||||
|
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
|
||||||
|
|
||||||
|
if( salt == NULL && saltlen != 0 )
|
||||||
|
return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
|
||||||
|
|
||||||
|
use_password = ( pwd && pwdlen != 0 );
|
||||||
|
use_salt = ( salt && saltlen != 0 );
|
||||||
|
|
||||||
md_info = mbedtls_md_info_from_type( md_type );
|
md_info = mbedtls_md_info_from_type( md_type );
|
||||||
if( md_info == NULL )
|
if( md_info == NULL )
|
||||||
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
|
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
|
||||||
|
@ -280,8 +305,15 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
|
|
||||||
memset( diversifier, (unsigned char) id, v );
|
memset( diversifier, (unsigned char) id, v );
|
||||||
|
|
||||||
|
if( use_salt != 0 )
|
||||||
|
{
|
||||||
pkcs12_fill_buffer( salt_block, v, salt, saltlen );
|
pkcs12_fill_buffer( salt_block, v, salt, saltlen );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( use_password != 0 )
|
||||||
|
{
|
||||||
pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
|
pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
|
||||||
|
}
|
||||||
|
|
||||||
p = data;
|
p = data;
|
||||||
while( datalen > 0 )
|
while( datalen > 0 )
|
||||||
|
@ -293,11 +325,17 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 )
|
if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 )
|
if( use_salt != 0 )
|
||||||
|
{
|
||||||
|
if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v )) != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 )
|
if( use_password != 0)
|
||||||
|
{
|
||||||
|
if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v )) != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 )
|
if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -325,6 +363,8 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
if( ++hash_block[i - 1] != 0 )
|
if( ++hash_block[i - 1] != 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if( use_salt != 0 )
|
||||||
|
{
|
||||||
// salt_block += B
|
// salt_block += B
|
||||||
c = 0;
|
c = 0;
|
||||||
for( i = v; i > 0; i-- )
|
for( i = v; i > 0; i-- )
|
||||||
|
@ -333,7 +373,10 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
c = MBEDTLS_BYTE_1( j );
|
c = MBEDTLS_BYTE_1( j );
|
||||||
salt_block[i - 1] = MBEDTLS_BYTE_0( j );
|
salt_block[i - 1] = MBEDTLS_BYTE_0( j );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( use_password != 0 )
|
||||||
|
{
|
||||||
// pwd_block += B
|
// pwd_block += B
|
||||||
c = 0;
|
c = 0;
|
||||||
for( i = v; i > 0; i-- )
|
for( i = v; i > 0; i-- )
|
||||||
|
@ -343,6 +386,7 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
|
||||||
pwd_block[i - 1] = MBEDTLS_BYTE_0( j );
|
pwd_block[i - 1] = MBEDTLS_BYTE_0( j );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,7 @@ add_test_suite(pk)
|
||||||
add_test_suite(pkcs1_v15)
|
add_test_suite(pkcs1_v15)
|
||||||
add_test_suite(pkcs1_v21)
|
add_test_suite(pkcs1_v21)
|
||||||
add_test_suite(pkcs5)
|
add_test_suite(pkcs5)
|
||||||
|
add_test_suite(pkcs12)
|
||||||
add_test_suite(pkparse)
|
add_test_suite(pkparse)
|
||||||
add_test_suite(pkwrite)
|
add_test_suite(pkwrite)
|
||||||
add_test_suite(poly1305)
|
add_test_suite(poly1305)
|
||||||
|
|
|
@ -2940,6 +2940,36 @@ component_test_valgrind () {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
support_test_cmake_out_of_source () {
|
||||||
|
distrib_id=""
|
||||||
|
distrib_ver=""
|
||||||
|
distrib_ver_minor=""
|
||||||
|
distrib_ver_major=""
|
||||||
|
|
||||||
|
# Attempt to parse lsb-release to find out distribution and version. If not
|
||||||
|
# found this should fail safe (test is supported).
|
||||||
|
if [[ -f /etc/lsb-release ]]; then
|
||||||
|
|
||||||
|
while read -r lsb_line; do
|
||||||
|
case "$lsb_line" in
|
||||||
|
"DISTRIB_ID"*) distrib_id=${lsb_line/#DISTRIB_ID=};;
|
||||||
|
"DISTRIB_RELEASE"*) distrib_ver=${lsb_line/#DISTRIB_RELEASE=};;
|
||||||
|
esac
|
||||||
|
done < /etc/lsb-release
|
||||||
|
|
||||||
|
distrib_ver_major="${distrib_ver%%.*}"
|
||||||
|
distrib_ver="${distrib_ver#*.}"
|
||||||
|
distrib_ver_minor="${distrib_ver%%.*}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Running the out of source CMake test on Ubuntu 16.04 using more than one
|
||||||
|
# processor (as the CI does) can create a race condition whereby the build
|
||||||
|
# fails to see a generated file, despite that file actually having been
|
||||||
|
# generated. This problem appears to go away with 18.04 or newer, so make
|
||||||
|
# the out of source tests unsupported on Ubuntu 16.04.
|
||||||
|
[ "$distrib_id" != "Ubuntu" ] || [ "$distrib_ver_major" -gt 16 ]
|
||||||
|
}
|
||||||
|
|
||||||
component_test_cmake_out_of_source () {
|
component_test_cmake_out_of_source () {
|
||||||
msg "build: cmake 'out-of-source' build"
|
msg "build: cmake 'out-of-source' build"
|
||||||
MBEDTLS_ROOT_DIR="$PWD"
|
MBEDTLS_ROOT_DIR="$PWD"
|
||||||
|
|
35
tests/suites/test_suite_pkcs12.data
Normal file
35
tests/suites/test_suite_pkcs12.data
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
PKCS#12 derive key : MD5: Zero length password and hash
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_GIVEN_INPUT:"":USE_GIVEN_INPUT:3:"6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b":0
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: NULL password and hash
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_NULL_INPUT:"":USE_NULL_INPUT:3:"6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b":0
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: Zero length password
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_GIVEN_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: NULL password
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_NULL_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: Invalid length NULL password
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_NULL_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"":MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: Zero length salt
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"":USE_GIVEN_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: NULL salt
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"":USE_NULL_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: Invalid length NULL salt
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"0123456789abcdef":USE_NULL_INPUT:3:"":MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA
|
||||||
|
|
||||||
|
PKCS#12 derive key: MD5: Valid password and salt
|
||||||
|
depends_on:MBEDTLS_MD5_C
|
||||||
|
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"46559deeee036836ab1b633ec620178d4c70eacf42f72a2ad7360c812efa09ca3d7567b489a109050345c2dc6a262995":0
|
69
tests/suites/test_suite_pkcs12.function
Normal file
69
tests/suites/test_suite_pkcs12.function
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* BEGIN_HEADER */
|
||||||
|
#include "mbedtls/pkcs12.h"
|
||||||
|
#include "mbedtls/error.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
USE_NULL_INPUT = 0,
|
||||||
|
USE_GIVEN_INPUT = 1,
|
||||||
|
} input_usage_method_t;
|
||||||
|
|
||||||
|
/* END_HEADER */
|
||||||
|
|
||||||
|
/* BEGIN_DEPENDENCIES
|
||||||
|
* depends_on:MBEDTLS_PKCS12_C
|
||||||
|
* END_DEPENDENCIES
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* BEGIN_CASE */
|
||||||
|
void pkcs12_derive_key( int md_type, int key_size_arg,
|
||||||
|
data_t *password_arg, int password_usage,
|
||||||
|
data_t *salt_arg, int salt_usage,
|
||||||
|
int iterations,
|
||||||
|
data_t* expected_output, int expected_status )
|
||||||
|
|
||||||
|
{
|
||||||
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||||
|
unsigned char *output_data = NULL;
|
||||||
|
|
||||||
|
unsigned char *password = NULL;
|
||||||
|
size_t password_len = 0;
|
||||||
|
unsigned char *salt = NULL;
|
||||||
|
size_t salt_len = 0;
|
||||||
|
size_t key_size = key_size_arg;
|
||||||
|
|
||||||
|
if( password_usage == USE_GIVEN_INPUT )
|
||||||
|
password = password_arg->x;
|
||||||
|
|
||||||
|
password_len = password_arg->len;
|
||||||
|
|
||||||
|
if( salt_usage == USE_GIVEN_INPUT )
|
||||||
|
salt = salt_arg->x;
|
||||||
|
|
||||||
|
salt_len = salt_arg->len;
|
||||||
|
|
||||||
|
ASSERT_ALLOC( output_data, key_size );
|
||||||
|
|
||||||
|
ret = mbedtls_pkcs12_derivation( output_data,
|
||||||
|
key_size,
|
||||||
|
password,
|
||||||
|
password_len,
|
||||||
|
salt,
|
||||||
|
salt_len,
|
||||||
|
md_type,
|
||||||
|
MBEDTLS_PKCS12_DERIVE_KEY,
|
||||||
|
iterations );
|
||||||
|
|
||||||
|
TEST_EQUAL( ret, expected_status );
|
||||||
|
|
||||||
|
if( expected_status == 0 )
|
||||||
|
{
|
||||||
|
ASSERT_COMPARE( expected_output->x, expected_output->len,
|
||||||
|
output_data, key_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mbedtls_free( output_data );
|
||||||
|
|
||||||
|
}
|
||||||
|
/* END_CASE */
|
Loading…
Reference in a new issue