mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-03-24 01:43:33 +00:00
Improve & test legacy mbedtls_pkcs12_pbe
* Prevent pkcs12_pbe encryption when PKCS7 padding has been disabled since this not part of the specs. * Allow decryption when PKCS7 padding is disabled for legacy reasons, However, invalid padding is not checked. * Document new behaviour, known limitations and possible security concerns. * Add tests to check these scenarios. Test data has been generated by the below code using OpenSSL as a reference: #include <openssl/pkcs12.h> #include <openssl/evp.h> #include <openssl/des.h> #include <openssl/asn1.h> #include "crypto/asn1.h" #include <string.h> int main() { char pass[] = "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"; unsigned char salt[] = "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"; unsigned char plaintext[] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; unsigned char *ciphertext = NULL; int iter = 10; X509_ALGOR *alg = X509_ALGOR_new(); int ciphertext_len = 0; int alg_nid = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; alg->parameter = ASN1_TYPE_new(); struct asn1_object_st * aobj; PKCS5_pbe_set0_algor(alg, alg_nid, iter, salt, sizeof(salt)-1); aobj = alg->algorithm; printf("\"30%.2X", 2 + aobj->length + alg->parameter->value.asn1_string->length); printf("06%.2X", aobj->length); for (int i = 0; i < aobj->length; i++) { printf("%.2X", aobj->data[i]); } for (int i = 0; i < alg->parameter->value.asn1_string->length; i++) { printf("%.2X", alg->parameter->value.asn1_string->data[i]); } printf("\":\""); for (int i = 0; i < sizeof(pass)-1; i++) { printf("%.2X", pass[i] & 0xFF); } printf("\":\""); for (int i = 0; i < sizeof(plaintext)-1; i++) { printf("%.2X", plaintext[i]); } printf("\":"); printf("0"); printf(":\""); unsigned char * res = PKCS12_pbe_crypt(alg, pass, sizeof(pass)-1, plaintext, sizeof(plaintext)-1, &ciphertext, &ciphertext_len, 1); if (res == NULL) printf("Encryption failed!\n"); for (int i = 0; i < ciphertext_len; i++) { printf("%.2X", res[i]); } printf("\"\n"); return 0; } Signed-off-by: Waleed Elmelegy <waleed.elmelegy@arm.com> #
This commit is contained in:
parent
1a8ebe39bf
commit
255db80910
@ -56,6 +56,21 @@ extern "C" {
|
||||
* \brief PKCS12 Password Based function (encryption / decryption)
|
||||
* for cipher-based and mbedtls_md-based PBE's
|
||||
*
|
||||
* \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must
|
||||
* be enabled at compile time.
|
||||
*
|
||||
* \warning When decrypting:
|
||||
* - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile
|
||||
* time, this function validates the CBC padding and returns
|
||||
* #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is
|
||||
* invalid. Note that this can help active adversaries
|
||||
* attempting to brute-forcing the password. Note also that
|
||||
* there is no guarantee that an invalid password will be
|
||||
* detected (the chances of a valid padding with a random
|
||||
* password are about 1/255).
|
||||
* - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile
|
||||
* time, this function does not validate the CBC padding.
|
||||
*
|
||||
* \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure
|
||||
* \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or
|
||||
* #MBEDTLS_PKCS12_PBE_DECRYPT
|
||||
@ -66,7 +81,15 @@ extern "C" {
|
||||
* \param pwdlen length of the password (may be 0)
|
||||
* \param input the input data
|
||||
* \param len data length
|
||||
* \param output the output buffer
|
||||
* \param output Output buffer.
|
||||
* On success, it contains the encrypted or decrypted data,
|
||||
* possibly followed by the CBC padding.
|
||||
* On failure, the content is indeterminate.
|
||||
* For decryption, there must be enough room for \p len
|
||||
* bytes.
|
||||
* For encryption, there must be enough room for
|
||||
* \p len + 1 bytes, rounded up to the block size of
|
||||
* the block cipher identified by \p pbe_params.
|
||||
*
|
||||
* \return 0 if successful, or a MBEDTLS_ERR_XXX code
|
||||
*/
|
||||
|
@ -171,6 +171,25 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
|
||||
/* PKCS12 uses CBC with PKCS7 padding */
|
||||
|
||||
mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
|
||||
#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
|
||||
/* For historical reasons, when decrypting, this function works when
|
||||
* decrypting even when support for PKCS7 padding is disabled. In this
|
||||
* case, it ignores the padding, and so will never report a
|
||||
* password mismatch.
|
||||
*/
|
||||
if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {
|
||||
padding = MBEDTLS_PADDING_NONE;
|
||||
}
|
||||
#endif
|
||||
if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
|
||||
|
||||
if ((ret =
|
||||
mbedtls_cipher_set_iv(&cipher_ctx, iv,
|
||||
mbedtls_cipher_info_get_iv_size(cipher_info))) != 0) {
|
||||
|
@ -33,3 +33,32 @@ pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"01234567
|
||||
PKCS#12 derive key: MD5: Valid password and salt
|
||||
depends_on:MBEDTLS_MD_CAN_MD5
|
||||
pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"46559deeee036836ab1b633ec620178d4c70eacf42f72a2ad7360c812efa09ca3d7567b489a109050345c2dc6a262995":0
|
||||
|
||||
PBE Encrypt, pad = 7 (OK)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_encrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"AAAAAAAAAAAAAAAAAA":0:"5F2C15056A36F3A78856E9E662DD27CB"
|
||||
|
||||
PBE Encrypt, pad = 8 (OK)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_encrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"AAAAAAAAAAAAAAAA":0:"5F2C15056A36F3A70F70A3D4EC4004A8"
|
||||
|
||||
PBE Encrypt, pad = 8 (PKCS7 padding disabled)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_encrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"AAAAAAAAAAAAAAAA":MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:""
|
||||
|
||||
PBE Decrypt, pad = 7 (OK)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_decrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"5F2C15056A36F3A78856E9E662DD27CB":0:"AAAAAAAAAAAAAAAAAA07070707070707"
|
||||
|
||||
PBE Decrypt, pad = 8 (OK)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_decrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"5F2C15056A36F3A70F70A3D4EC4004A8":0:"AAAAAAAAAAAAAAAA0808080808080808"
|
||||
|
||||
|
||||
PBE Decrypt, (Invalid padding & PKCS7 padding disabled)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_decrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"5F2C15056A36F3A79F2B90F1428110E2":0:"AAAAAAAAAAAAAAAAAA07070707070708"
|
||||
|
||||
PBE Decrypt, (Invalid padding & PKCS7 padding enabled)
|
||||
depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
pkcs12_pbe_decrypt:"301C060A2A864886F70D010C0103300E0409CCCCCCCCCCCCCCCCCC02010A":"BBBBBBBBBBBBBBBBBB":"5F2C15056A36F3A79F2B90F1428110E2":MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH:"AAAAAAAAAAAAAAAAAA07070707070708"
|
@ -1,5 +1,6 @@
|
||||
/* BEGIN_HEADER */
|
||||
#include "mbedtls/pkcs12.h"
|
||||
#include "mbedtls/oid.h"
|
||||
#include "common.h"
|
||||
|
||||
typedef enum {
|
||||
@ -14,7 +15,7 @@ typedef enum {
|
||||
* END_DEPENDENCIES
|
||||
*/
|
||||
|
||||
/* BEGIN_CASE */
|
||||
/* BEGIN_CASE MBEDTLS_ASN1_PARSE_C*/
|
||||
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,
|
||||
@ -44,7 +45,7 @@ void pkcs12_derive_key(int md_type, int key_size_arg,
|
||||
|
||||
salt_len = salt_arg->len;
|
||||
|
||||
TEST_CALLOC(output_data, key_size);
|
||||
ASSERT_ALLOC(output_data, key_size);
|
||||
|
||||
int ret = mbedtls_pkcs12_derivation(output_data,
|
||||
key_size,
|
||||
@ -59,8 +60,8 @@ void pkcs12_derive_key(int md_type, int key_size_arg,
|
||||
TEST_EQUAL(ret, expected_status);
|
||||
|
||||
if (expected_status == 0) {
|
||||
TEST_MEMORY_COMPARE(expected_output->x, expected_output->len,
|
||||
output_data, key_size);
|
||||
ASSERT_COMPARE(expected_output->x, expected_output->len,
|
||||
output_data, key_size);
|
||||
}
|
||||
|
||||
exit:
|
||||
@ -68,3 +69,85 @@ exit:
|
||||
MD_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
|
||||
void pkcs12_pbe_encrypt(data_t *params_hex, data_t *pw,
|
||||
data_t *data, int ref_ret, data_t *ref_out)
|
||||
{
|
||||
int my_ret;
|
||||
mbedtls_asn1_buf pbe_alg_oid, pbe_params;
|
||||
unsigned char *my_out = NULL;
|
||||
unsigned char *p, *end;
|
||||
mbedtls_cipher_type_t cipher_alg;
|
||||
mbedtls_md_type_t md_alg;
|
||||
|
||||
MD_PSA_INIT();
|
||||
|
||||
p = params_hex->x;
|
||||
end = p + params_hex->len;
|
||||
|
||||
my_ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params);
|
||||
if (my_ret) {
|
||||
TEST_FAIL("Invalid test paramaters");
|
||||
}
|
||||
my_ret = mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg);
|
||||
if (my_ret) {
|
||||
TEST_FAIL("Invalid test paramaters");
|
||||
}
|
||||
|
||||
ASSERT_ALLOC(my_out, ref_out->len);
|
||||
|
||||
my_ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_ENCRYPT, cipher_alg,
|
||||
md_alg, pw->x, pw->len, data->x, data->len, my_out);
|
||||
TEST_EQUAL(my_ret, ref_ret);
|
||||
if (ref_ret == 0) {
|
||||
ASSERT_COMPARE(my_out, ref_out->len,
|
||||
ref_out->x, ref_out->len);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_free(my_out);
|
||||
MD_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */
|
||||
void pkcs12_pbe_decrypt(data_t *params_hex, data_t *pw,
|
||||
data_t *data, int ref_ret, data_t *ref_out)
|
||||
{
|
||||
int my_ret;
|
||||
mbedtls_asn1_buf pbe_alg_oid, pbe_params;
|
||||
unsigned char *my_out = NULL;
|
||||
unsigned char *p, *end;
|
||||
mbedtls_cipher_type_t cipher_alg;
|
||||
mbedtls_md_type_t md_alg;
|
||||
|
||||
MD_PSA_INIT();
|
||||
|
||||
p = params_hex->x;
|
||||
end = p + params_hex->len;
|
||||
|
||||
my_ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params);
|
||||
if (my_ret) {
|
||||
TEST_FAIL("Invalid test paramaters");
|
||||
}
|
||||
my_ret = mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg);
|
||||
if (my_ret) {
|
||||
TEST_FAIL("Invalid test paramaters");
|
||||
}
|
||||
|
||||
ASSERT_ALLOC(my_out, ref_out->len);
|
||||
|
||||
my_ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, cipher_alg,
|
||||
md_alg, pw->x, pw->len, data->x, data->len, my_out);
|
||||
TEST_EQUAL(my_ret, ref_ret);
|
||||
if (ref_ret == 0) {
|
||||
ASSERT_COMPARE(my_out, ref_out->len,
|
||||
ref_out->x, ref_out->len);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_free(my_out);
|
||||
MD_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
Loading…
x
Reference in New Issue
Block a user