Merge pull request #7700 from silabs-Kusumit/PBKDF2_output_bytes

PBKDF2: Output bytes
This commit is contained in:
Gilles Peskine 2023-06-16 10:08:02 +02:00 committed by GitHub
commit f45a5a0ddd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 227 additions and 14 deletions

View file

@ -5474,6 +5474,137 @@ static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read(
}
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
static psa_status_t psa_key_derivation_pbkdf2_generate_block(
psa_pbkdf2_key_derivation_t *pbkdf2,
psa_algorithm_t prf_alg,
uint8_t prf_output_length,
psa_key_attributes_t *attributes)
{
psa_status_t status;
psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT;
size_t mac_output_length;
uint8_t U_i[PSA_MAC_MAX_SIZE];
uint8_t *U_accumulator = pbkdf2->output_block;
uint64_t i;
uint8_t block_counter[4];
mac_operation.is_sign = 1;
mac_operation.mac_size = prf_output_length;
MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0);
status = psa_driver_wrapper_mac_sign_setup(&mac_operation,
attributes,
pbkdf2->password,
pbkdf2->password_length,
prf_alg);
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length);
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter));
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i),
&mac_output_length);
if (status != PSA_SUCCESS) {
goto cleanup;
}
if (mac_output_length != prf_output_length) {
status = PSA_ERROR_CORRUPTION_DETECTED;
goto cleanup;
}
memcpy(U_accumulator, U_i, prf_output_length);
for (i = 1; i < pbkdf2->input_cost; i++) {
status = psa_driver_wrapper_mac_compute(attributes,
pbkdf2->password,
pbkdf2->password_length,
prf_alg, U_i, prf_output_length,
U_i, sizeof(U_i),
&mac_output_length);
if (status != PSA_SUCCESS) {
goto cleanup;
}
mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length);
}
cleanup:
/* Zeroise buffers to clear sensitive data from memory. */
mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE);
return status;
}
static psa_status_t psa_key_derivation_pbkdf2_read(
psa_pbkdf2_key_derivation_t *pbkdf2,
psa_algorithm_t kdf_alg,
uint8_t *output,
size_t output_length)
{
psa_status_t status;
psa_algorithm_t prf_alg;
uint8_t prf_output_length;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length));
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg));
prf_output_length = PSA_HASH_LENGTH(prf_alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
switch (pbkdf2->state) {
case PSA_PBKDF2_STATE_PASSWORD_SET:
/* Initially we need a new block so bytes_used is equal to block size*/
pbkdf2->bytes_used = prf_output_length;
pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT;
break;
case PSA_PBKDF2_STATE_OUTPUT:
break;
default:
return PSA_ERROR_BAD_STATE;
}
while (output_length != 0) {
uint8_t n = prf_output_length - pbkdf2->bytes_used;
if (n > output_length) {
n = (uint8_t) output_length;
}
memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n);
output += n;
output_length -= n;
pbkdf2->bytes_used += n;
if (output_length == 0) {
break;
}
/* We need a new block */
pbkdf2->bytes_used = 0;
pbkdf2->block_number++;
status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg,
prf_output_length,
&attributes);
if (status != PSA_SUCCESS) {
return status;
}
}
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
psa_status_t psa_key_derivation_output_bytes(
psa_key_derivation_operation_t *operation,
uint8_t *output,
@ -5529,11 +5660,8 @@ psa_status_t psa_key_derivation_output_bytes(
#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;
status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg,
output, output_length);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */