mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-29 11:41:15 +03:00
Merge pull request #7547 from silabs-Kusumit/PBKDF2_input_validation
PBKDF2: Input Validation
This commit is contained in:
@ -5030,7 +5030,8 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
|
||||
#if defined(BUILTIN_ALG_ANY_HKDF) || \
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
#define AT_LEAST_ONE_BUILTIN_KDF
|
||||
#endif /* At least one builtin KDF */
|
||||
|
||||
@ -5134,6 +5135,17 @@ psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation)
|
||||
sizeof(operation->ctx.tls12_ecjpake_to_pms.data));
|
||||
} else
|
||||
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
|
||||
if (operation->ctx.pbkdf2.salt != NULL) {
|
||||
mbedtls_platform_zeroize(operation->ctx.pbkdf2.salt,
|
||||
operation->ctx.pbkdf2.salt_length);
|
||||
mbedtls_free(operation->ctx.pbkdf2.salt);
|
||||
}
|
||||
|
||||
status = PSA_SUCCESS;
|
||||
} else
|
||||
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) */
|
||||
{
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
@ -5513,6 +5525,15 @@ psa_status_t psa_key_derivation_output_bytes(
|
||||
&operation->ctx.tls12_ecjpake_to_pms, output, output_length);
|
||||
} else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
|
||||
/* As output functionality is not added yet return
|
||||
* PSA_ERROR_NOT_SUPPORTED for now if inputs are passed correctly.
|
||||
* If input validation fails operation is aborted and output_bytes
|
||||
* will return PSA_ERROR_BAD_STATE */
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
} else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
|
||||
|
||||
{
|
||||
(void) kdf_alg;
|
||||
@ -5930,6 +5951,11 @@ static int is_kdf_alg_supported(psa_algorithm_t kdf_alg)
|
||||
if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -6424,6 +6450,130 @@ static psa_status_t psa_tls12_ecjpake_to_pms_input(
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
static psa_status_t psa_pbkdf2_set_input_cost(
|
||||
psa_pbkdf2_key_derivation_t *pbkdf2,
|
||||
psa_key_derivation_step_t step,
|
||||
uint64_t data)
|
||||
{
|
||||
if (step != PSA_KEY_DERIVATION_INPUT_COST) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (data == 0) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
pbkdf2->input_cost = data;
|
||||
pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2,
|
||||
const uint8_t *data,
|
||||
size_t data_length)
|
||||
{
|
||||
if (pbkdf2->state != PSA_PBKDF2_STATE_INPUT_COST_SET &&
|
||||
pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) {
|
||||
pbkdf2->salt = mbedtls_calloc(1, data_length);
|
||||
if (pbkdf2->salt == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(pbkdf2->salt, data, data_length);
|
||||
pbkdf2->salt_length = data_length;
|
||||
} else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) {
|
||||
uint8_t *next_salt;
|
||||
|
||||
next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length);
|
||||
if (next_salt == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length);
|
||||
memcpy(next_salt + pbkdf2->salt_length, data, data_length);
|
||||
pbkdf2->salt_length += data_length;
|
||||
mbedtls_free(pbkdf2->salt);
|
||||
pbkdf2->salt = next_salt;
|
||||
}
|
||||
|
||||
pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg,
|
||||
const uint8_t *input,
|
||||
size_t input_len,
|
||||
uint8_t *output,
|
||||
size_t *output_len)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) {
|
||||
status = psa_hash_compute(hash_alg, input, input_len, output,
|
||||
PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);
|
||||
} else {
|
||||
memcpy(output, input, input_len);
|
||||
*output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2,
|
||||
psa_algorithm_t kdf_alg,
|
||||
const uint8_t *data,
|
||||
size_t data_length)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (data_length != 0) {
|
||||
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
|
||||
psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg);
|
||||
status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length,
|
||||
pbkdf2->password,
|
||||
&pbkdf2->password_length);
|
||||
}
|
||||
}
|
||||
|
||||
pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2,
|
||||
psa_algorithm_t kdf_alg,
|
||||
psa_key_derivation_step_t step,
|
||||
const uint8_t *data,
|
||||
size_t data_length)
|
||||
{
|
||||
switch (step) {
|
||||
case PSA_KEY_DERIVATION_INPUT_SALT:
|
||||
return psa_pbkdf2_set_salt(pbkdf2, data, data_length);
|
||||
case PSA_KEY_DERIVATION_INPUT_PASSWORD:
|
||||
return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length);
|
||||
default:
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
|
||||
|
||||
/** Check whether the given key type is acceptable for the given
|
||||
* input step of a key derivation.
|
||||
*
|
||||
@ -6465,6 +6615,17 @@ static int psa_key_derivation_check_input_type(
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case PSA_KEY_DERIVATION_INPUT_PASSWORD:
|
||||
if (key_type == PSA_KEY_TYPE_PASSWORD) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (key_type == PSA_KEY_TYPE_DERIVE) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (key_type == PSA_KEY_TYPE_NONE) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
@ -6508,6 +6669,12 @@ static psa_status_t psa_key_derivation_input_internal(
|
||||
&operation->ctx.tls12_ecjpake_to_pms, step, data, data_length);
|
||||
} else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
|
||||
status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg,
|
||||
step, data, data_length);
|
||||
} else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
|
||||
{
|
||||
/* This can't happen unless the operation object was not initialized */
|
||||
(void) data;
|
||||
@ -6531,6 +6698,12 @@ static psa_status_t psa_key_derivation_input_integer_internal(
|
||||
psa_status_t status;
|
||||
psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
|
||||
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
|
||||
status = psa_pbkdf2_set_input_cost(
|
||||
&operation->ctx.pbkdf2, step, value);
|
||||
} else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
|
||||
{
|
||||
(void) step;
|
||||
(void) value;
|
||||
@ -6579,9 +6752,10 @@ psa_status_t psa_key_derivation_input_key(
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Passing a key object as a SECRET input unlocks the permission
|
||||
* to output to a key object. */
|
||||
if (step == PSA_KEY_DERIVATION_INPUT_SECRET) {
|
||||
/* Passing a key object as a SECRET or PASSWORD input unlocks the
|
||||
* permission to output to a key object. */
|
||||
if (step == PSA_KEY_DERIVATION_INPUT_SECRET ||
|
||||
step == PSA_KEY_DERIVATION_INPUT_PASSWORD) {
|
||||
operation->can_output_key = 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user