mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-08-01 10:06:53 +03:00
Merge pull request #6567 from mprse/ecjpake-driver-dispatch
This commit is contained in:
@ -916,14 +916,27 @@ static psa_status_t psa_restrict_key_policy(
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_get_and_lock_key_slot_with_policy(
|
||||
/** Get the description of a key given its identifier and policy constraints
|
||||
* and lock it.
|
||||
*
|
||||
* The key must have allow all the usage flags set in \p usage. If \p alg is
|
||||
* nonzero, the key must allow operations with this algorithm. If \p alg is
|
||||
* zero, the algorithm is not checked.
|
||||
*
|
||||
* In case of a persistent key, the function loads the description of the key
|
||||
* into a key slot if not already done.
|
||||
*
|
||||
* On success, the returned key slot is locked. It is the responsibility of
|
||||
* the caller to unlock the key slot when it does not access it anymore.
|
||||
*/
|
||||
static psa_status_t psa_get_and_lock_key_slot_with_policy(
|
||||
mbedtls_svc_key_id_t key,
|
||||
psa_key_slot_t **p_slot,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot;
|
||||
psa_key_slot_t *slot = NULL;
|
||||
|
||||
status = psa_get_and_lock_key_slot(key, p_slot);
|
||||
if (status != PSA_SUCCESS) {
|
||||
@ -5061,13 +5074,13 @@ psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation)
|
||||
operation->ctx.tls12_prf.label_length);
|
||||
mbedtls_free(operation->ctx.tls12_prf.label);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
|
||||
if (operation->ctx.tls12_prf.other_secret != NULL) {
|
||||
mbedtls_platform_zeroize(operation->ctx.tls12_prf.other_secret,
|
||||
operation->ctx.tls12_prf.other_secret_length);
|
||||
mbedtls_free(operation->ctx.tls12_prf.other_secret);
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
|
||||
status = PSA_SUCCESS;
|
||||
|
||||
/* We leave the fields Ai and output_block to be erased safely by the
|
||||
@ -7152,4 +7165,736 @@ exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_crypto_driver_pake_get_password_len(
|
||||
const psa_crypto_driver_pake_inputs_t *inputs,
|
||||
size_t *password_len)
|
||||
{
|
||||
if (inputs->password_len == 0) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
*password_len = inputs->password_len;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_crypto_driver_pake_get_password(
|
||||
const psa_crypto_driver_pake_inputs_t *inputs,
|
||||
uint8_t *buffer, size_t buffer_size, size_t *buffer_length)
|
||||
{
|
||||
if (inputs->password_len == 0) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (buffer_size < inputs->password_len) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
memcpy(buffer, inputs->password, inputs->password_len);
|
||||
*buffer_length = inputs->password_len;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_crypto_driver_pake_get_role(
|
||||
const psa_crypto_driver_pake_inputs_t *inputs,
|
||||
psa_pake_role_t *role)
|
||||
{
|
||||
if (inputs->role == PSA_PAKE_ROLE_NONE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
*role = inputs->role;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_crypto_driver_pake_get_cipher_suite(
|
||||
const psa_crypto_driver_pake_inputs_t *inputs,
|
||||
psa_pake_cipher_suite_t *cipher_suite)
|
||||
{
|
||||
if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
*cipher_suite = inputs->cipher_suite;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_setup(
|
||||
psa_pake_operation_t *operation,
|
||||
const psa_pake_cipher_suite_t *cipher_suite)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 ||
|
||||
PSA_ALG_IS_HASH(cipher_suite->hash) == 0) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(&operation->data.inputs, 0, sizeof(operation->data.inputs));
|
||||
|
||||
operation->alg = cipher_suite->algorithm;
|
||||
operation->data.inputs.cipher_suite = *cipher_suite;
|
||||
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
|
||||
computation_stage->state = PSA_PAKE_STATE_SETUP;
|
||||
computation_stage->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
computation_stage->input_step = PSA_PAKE_STEP_X1_X2;
|
||||
computation_stage->output_step = PSA_PAKE_STEP_X1_X2;
|
||||
} else
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
{
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
exit:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_password_key(
|
||||
psa_pake_operation_t *operation,
|
||||
mbedtls_svc_key_id_t password)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot = NULL;
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_get_and_lock_key_slot_with_policy(password, &slot,
|
||||
PSA_KEY_USAGE_DERIVE,
|
||||
operation->alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psa_key_attributes_t attributes = {
|
||||
.core = slot->attr
|
||||
};
|
||||
|
||||
psa_key_type_t type = psa_get_key_type(&attributes);
|
||||
|
||||
if (type != PSA_KEY_TYPE_PASSWORD &&
|
||||
type != PSA_KEY_TYPE_PASSWORD_HASH) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes);
|
||||
if (operation->data.inputs.password == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes);
|
||||
operation->data.inputs.password_len = slot->key.bytes;
|
||||
operation->data.inputs.attributes = attributes;
|
||||
exit:
|
||||
if (status != PSA_SUCCESS) {
|
||||
psa_pake_abort(operation);
|
||||
}
|
||||
unlock_status = psa_unlock_key_slot(slot);
|
||||
return (status == PSA_SUCCESS) ? unlock_status : status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_user(
|
||||
psa_pake_operation_t *operation,
|
||||
const uint8_t *user_id,
|
||||
size_t user_id_len)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
(void) user_id;
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (user_id_len == 0) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
exit:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_peer(
|
||||
psa_pake_operation_t *operation,
|
||||
const uint8_t *peer_id,
|
||||
size_t peer_id_len)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
(void) peer_id;
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (peer_id_len == 0) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
exit:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_role(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_role_t role)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (role != PSA_PAKE_ROLE_NONE &&
|
||||
role != PSA_PAKE_ROLE_FIRST &&
|
||||
role != PSA_PAKE_ROLE_SECOND &&
|
||||
role != PSA_PAKE_ROLE_CLIENT &&
|
||||
role != PSA_PAKE_ROLE_SERVER) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
operation->data.inputs.role = role;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
exit:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Auxiliary function to convert core computation stage(step, sequence, state) to single driver step. */
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step(
|
||||
psa_jpake_computation_stage_t *stage)
|
||||
{
|
||||
switch (stage->state) {
|
||||
case PSA_PAKE_OUTPUT_X1_X2:
|
||||
case PSA_PAKE_INPUT_X1_X2:
|
||||
switch (stage->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
return PSA_JPAKE_X1_STEP_KEY_SHARE;
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
return PSA_JPAKE_X1_STEP_ZK_PUBLIC;
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
return PSA_JPAKE_X1_STEP_ZK_PROOF;
|
||||
case PSA_PAKE_X2_STEP_KEY_SHARE:
|
||||
return PSA_JPAKE_X2_STEP_KEY_SHARE;
|
||||
case PSA_PAKE_X2_STEP_ZK_PUBLIC:
|
||||
return PSA_JPAKE_X2_STEP_ZK_PUBLIC;
|
||||
case PSA_PAKE_X2_STEP_ZK_PROOF:
|
||||
return PSA_JPAKE_X2_STEP_ZK_PROOF;
|
||||
default:
|
||||
return PSA_JPAKE_STEP_INVALID;
|
||||
}
|
||||
break;
|
||||
case PSA_PAKE_OUTPUT_X2S:
|
||||
switch (stage->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
return PSA_JPAKE_X2S_STEP_KEY_SHARE;
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
return PSA_JPAKE_X2S_STEP_ZK_PUBLIC;
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
return PSA_JPAKE_X2S_STEP_ZK_PROOF;
|
||||
default:
|
||||
return PSA_JPAKE_STEP_INVALID;
|
||||
}
|
||||
break;
|
||||
case PSA_PAKE_INPUT_X4S:
|
||||
switch (stage->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
return PSA_JPAKE_X4S_STEP_KEY_SHARE;
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
return PSA_JPAKE_X4S_STEP_ZK_PUBLIC;
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
return PSA_JPAKE_X4S_STEP_ZK_PROOF;
|
||||
default:
|
||||
return PSA_JPAKE_STEP_INVALID;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return PSA_JPAKE_STEP_INVALID;
|
||||
}
|
||||
return PSA_JPAKE_STEP_INVALID;
|
||||
}
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
|
||||
static psa_status_t psa_pake_complete_inputs(
|
||||
psa_pake_operation_t *operation)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
/* Create copy of the inputs on stack as inputs share memory
|
||||
with the driver context which will be setup by the driver. */
|
||||
psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs;
|
||||
|
||||
if (inputs.password_len == 0 ||
|
||||
inputs.role == PSA_PAKE_ROLE_NONE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (operation->alg == PSA_ALG_JPAKE &&
|
||||
inputs.role != PSA_PAKE_ROLE_CLIENT &&
|
||||
inputs.role != PSA_PAKE_ROLE_SERVER) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Clear driver context */
|
||||
mbedtls_platform_zeroize(&operation->data, sizeof(operation->data));
|
||||
|
||||
status = psa_driver_wrapper_pake_setup(operation, &inputs);
|
||||
|
||||
/* Driver is responsible for creating its own copy of the password. */
|
||||
mbedtls_platform_zeroize(inputs.password, inputs.password_len);
|
||||
mbedtls_free(inputs.password);
|
||||
|
||||
if (status == PSA_SUCCESS) {
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION;
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
computation_stage->state = PSA_PAKE_STATE_READY;
|
||||
computation_stage->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
computation_stage->input_step = PSA_PAKE_STEP_X1_X2;
|
||||
computation_stage->output_step = PSA_PAKE_STEP_X1_X2;
|
||||
} else
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
{
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
static psa_status_t psa_jpake_output_prologue(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step)
|
||||
{
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE &&
|
||||
step != PSA_PAKE_STEP_ZK_PUBLIC &&
|
||||
step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
|
||||
if (computation_stage->state == PSA_PAKE_STATE_INVALID) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (computation_stage->state != PSA_PAKE_STATE_READY &&
|
||||
computation_stage->state != PSA_PAKE_OUTPUT_X1_X2 &&
|
||||
computation_stage->state != PSA_PAKE_OUTPUT_X2S) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (computation_stage->state == PSA_PAKE_STATE_READY) {
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
switch (computation_stage->output_step) {
|
||||
case PSA_PAKE_STEP_X1_X2:
|
||||
computation_stage->state = PSA_PAKE_OUTPUT_X1_X2;
|
||||
break;
|
||||
case PSA_PAKE_STEP_X2S:
|
||||
computation_stage->state = PSA_PAKE_OUTPUT_X2S;
|
||||
break;
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
computation_stage->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
|
||||
}
|
||||
|
||||
/* Check if step matches current sequence */
|
||||
switch (computation_stage->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
case PSA_PAKE_X2_STEP_KEY_SHARE:
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
case PSA_PAKE_X2_STEP_ZK_PUBLIC:
|
||||
if (step != PSA_PAKE_STEP_ZK_PUBLIC) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
case PSA_PAKE_X2_STEP_ZK_PROOF:
|
||||
if (step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t psa_jpake_output_epilogue(
|
||||
psa_pake_operation_t *operation)
|
||||
{
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
|
||||
if ((computation_stage->state == PSA_PAKE_OUTPUT_X1_X2 &&
|
||||
computation_stage->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) ||
|
||||
(computation_stage->state == PSA_PAKE_OUTPUT_X2S &&
|
||||
computation_stage->sequence == PSA_PAKE_X1_STEP_ZK_PROOF)) {
|
||||
computation_stage->state = PSA_PAKE_STATE_READY;
|
||||
computation_stage->output_step++;
|
||||
computation_stage->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
} else {
|
||||
computation_stage->sequence++;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
|
||||
psa_status_t psa_pake_output(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
|
||||
*output_length = 0;
|
||||
|
||||
if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
|
||||
status = psa_pake_complete_inputs(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (output_size == 0) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (operation->alg) {
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
case PSA_ALG_JPAKE:
|
||||
status = psa_jpake_output_prologue(operation, step);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
driver_step = convert_jpake_computation_stage_to_driver_step(
|
||||
&operation->computation_stage.jpake);
|
||||
break;
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
default:
|
||||
(void) step;
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_driver_wrapper_pake_output(operation, driver_step,
|
||||
output, output_size, output_length);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (operation->alg) {
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
case PSA_ALG_JPAKE:
|
||||
status = psa_jpake_output_epilogue(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
default:
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
exit:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
static psa_status_t psa_jpake_input_prologue(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step)
|
||||
{
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE &&
|
||||
step != PSA_PAKE_STEP_ZK_PUBLIC &&
|
||||
step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
|
||||
if (computation_stage->state == PSA_PAKE_STATE_INVALID) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (computation_stage->state != PSA_PAKE_STATE_READY &&
|
||||
computation_stage->state != PSA_PAKE_INPUT_X1_X2 &&
|
||||
computation_stage->state != PSA_PAKE_INPUT_X4S) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (computation_stage->state == PSA_PAKE_STATE_READY) {
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
switch (computation_stage->input_step) {
|
||||
case PSA_PAKE_STEP_X1_X2:
|
||||
computation_stage->state = PSA_PAKE_INPUT_X1_X2;
|
||||
break;
|
||||
case PSA_PAKE_STEP_X2S:
|
||||
computation_stage->state = PSA_PAKE_INPUT_X4S;
|
||||
break;
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
computation_stage->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
|
||||
}
|
||||
|
||||
/* Check if step matches current sequence */
|
||||
switch (computation_stage->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
case PSA_PAKE_X2_STEP_KEY_SHARE:
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
case PSA_PAKE_X2_STEP_ZK_PUBLIC:
|
||||
if (step != PSA_PAKE_STEP_ZK_PUBLIC) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
case PSA_PAKE_X2_STEP_ZK_PROOF:
|
||||
if (step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t psa_jpake_input_epilogue(
|
||||
psa_pake_operation_t *operation)
|
||||
{
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
|
||||
if ((computation_stage->state == PSA_PAKE_INPUT_X1_X2 &&
|
||||
computation_stage->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) ||
|
||||
(computation_stage->state == PSA_PAKE_INPUT_X4S &&
|
||||
computation_stage->sequence == PSA_PAKE_X1_STEP_ZK_PROOF)) {
|
||||
computation_stage->state = PSA_PAKE_STATE_READY;
|
||||
computation_stage->input_step++;
|
||||
computation_stage->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
} else {
|
||||
computation_stage->sequence++;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
|
||||
psa_status_t psa_pake_input(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step,
|
||||
const uint8_t *input,
|
||||
size_t input_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
|
||||
|
||||
if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
|
||||
status = psa_pake_complete_inputs(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (input_length == 0 || input_length > PSA_PAKE_INPUT_MAX_SIZE) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (operation->alg) {
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
case PSA_ALG_JPAKE:
|
||||
status = psa_jpake_input_prologue(operation, step);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
driver_step = convert_jpake_computation_stage_to_driver_step(
|
||||
&operation->computation_stage.jpake);
|
||||
break;
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
default:
|
||||
(void) step;
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_driver_wrapper_pake_input(operation, driver_step,
|
||||
input, input_length);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (operation->alg) {
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
case PSA_ALG_JPAKE:
|
||||
status = psa_jpake_input_epilogue(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
default:
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
exit:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_get_implicit_key(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_key_derivation_operation_t *output)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE];
|
||||
size_t shared_key_len = 0;
|
||||
|
||||
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(PSA_WANT_ALG_JPAKE)
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
psa_jpake_computation_stage_t *computation_stage =
|
||||
&operation->computation_stage.jpake;
|
||||
if (computation_stage->input_step != PSA_PAKE_STEP_DERIVE ||
|
||||
computation_stage->output_step != PSA_PAKE_STEP_DERIVE) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto exit;
|
||||
}
|
||||
} else
|
||||
#endif /* PSA_WANT_ALG_JPAKE */
|
||||
{
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_driver_wrapper_pake_get_implicit_key(operation,
|
||||
shared_key,
|
||||
sizeof(shared_key),
|
||||
&shared_key_len);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_key_derivation_input_bytes(output,
|
||||
PSA_KEY_DERIVATION_INPUT_SECRET,
|
||||
shared_key,
|
||||
shared_key_len);
|
||||
|
||||
mbedtls_platform_zeroize(shared_key, sizeof(shared_key));
|
||||
exit:
|
||||
abort_status = psa_pake_abort(operation);
|
||||
return status == PSA_SUCCESS ? abort_status : status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_abort(
|
||||
psa_pake_operation_t *operation)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
|
||||
if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
|
||||
status = psa_driver_wrapper_pake_abort(operation);
|
||||
}
|
||||
|
||||
if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS &&
|
||||
operation->data.inputs.password != NULL) {
|
||||
mbedtls_platform_zeroize(operation->data.inputs.password,
|
||||
operation->data.inputs.password_len);
|
||||
mbedtls_free(operation->data.inputs.password);
|
||||
}
|
||||
|
||||
memset(operation, 0, sizeof(psa_pake_operation_t));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_C */
|
||||
|
@ -182,24 +182,6 @@ static inline psa_key_slot_number_t psa_key_slot_get_slot_number(
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Get the description of a key given its identifier and policy constraints
|
||||
* and lock it.
|
||||
*
|
||||
* The key must have allow all the usage flags set in \p usage. If \p alg is
|
||||
* nonzero, the key must allow operations with this algorithm. If \p alg is
|
||||
* zero, the algorithm is not checked.
|
||||
*
|
||||
* In case of a persistent key, the function loads the description of the key
|
||||
* into a key slot if not already done.
|
||||
*
|
||||
* On success, the returned key slot is locked. It is the responsibility of
|
||||
* the caller to unlock the key slot when it does not access it anymore.
|
||||
*/
|
||||
psa_status_t psa_get_and_lock_key_slot_with_policy(mbedtls_svc_key_id_t key,
|
||||
psa_key_slot_t **p_slot,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg);
|
||||
|
||||
/** Completely wipe a slot in memory, including its policy.
|
||||
*
|
||||
* Persistent storage is not affected.
|
||||
|
@ -408,6 +408,34 @@ psa_status_t psa_driver_wrapper_key_agreement(
|
||||
size_t shared_secret_size,
|
||||
size_t *shared_secret_length);
|
||||
|
||||
/*
|
||||
* PAKE functions.
|
||||
*/
|
||||
psa_status_t psa_driver_wrapper_pake_setup(
|
||||
psa_pake_operation_t *operation,
|
||||
const psa_crypto_driver_pake_inputs_t *inputs);
|
||||
|
||||
psa_status_t psa_driver_wrapper_pake_output(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t psa_driver_wrapper_pake_input(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
const uint8_t *input,
|
||||
size_t input_length);
|
||||
|
||||
psa_status_t psa_driver_wrapper_pake_get_implicit_key(
|
||||
psa_pake_operation_t *operation,
|
||||
uint8_t *output, size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t psa_driver_wrapper_pake_abort(
|
||||
psa_pake_operation_t *operation);
|
||||
|
||||
#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
|
||||
|
||||
/* End of automatically generated file. */
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <psa/crypto.h>
|
||||
#include "psa_crypto_core.h"
|
||||
#include "psa_crypto_pake.h"
|
||||
#include "psa_crypto_slot_management.h"
|
||||
|
||||
#include <mbedtls/ecjpake.h>
|
||||
@ -78,23 +79,6 @@
|
||||
* psa_pake_abort()
|
||||
*/
|
||||
|
||||
enum psa_pake_step {
|
||||
PSA_PAKE_STEP_INVALID = 0,
|
||||
PSA_PAKE_STEP_X1_X2 = 1,
|
||||
PSA_PAKE_STEP_X2S = 2,
|
||||
PSA_PAKE_STEP_DERIVE = 3,
|
||||
};
|
||||
|
||||
enum psa_pake_state {
|
||||
PSA_PAKE_STATE_INVALID = 0,
|
||||
PSA_PAKE_STATE_SETUP = 1,
|
||||
PSA_PAKE_STATE_READY = 2,
|
||||
PSA_PAKE_OUTPUT_X1_X2 = 3,
|
||||
PSA_PAKE_OUTPUT_X2S = 4,
|
||||
PSA_PAKE_INPUT_X1_X2 = 5,
|
||||
PSA_PAKE_INPUT_X4S = 6,
|
||||
};
|
||||
|
||||
/*
|
||||
* The first PAKE step shares the same sequences of the second PAKE step
|
||||
* but with a second set of KEY_SHARE/ZK_PUBLIC/ZK_PROOF outputs/inputs.
|
||||
@ -156,16 +140,6 @@ enum psa_pake_state {
|
||||
* psa_pake_get_implicit_key()
|
||||
* => Input & Output Step = PSA_PAKE_STEP_INVALID
|
||||
*/
|
||||
enum psa_pake_sequence {
|
||||
PSA_PAKE_SEQ_INVALID = 0,
|
||||
PSA_PAKE_X1_STEP_KEY_SHARE = 1, /* also X2S & X4S KEY_SHARE */
|
||||
PSA_PAKE_X1_STEP_ZK_PUBLIC = 2, /* also X2S & X4S ZK_PUBLIC */
|
||||
PSA_PAKE_X1_STEP_ZK_PROOF = 3, /* also X2S & X4S ZK_PROOF */
|
||||
PSA_PAKE_X2_STEP_KEY_SHARE = 4,
|
||||
PSA_PAKE_X2_STEP_ZK_PUBLIC = 5,
|
||||
PSA_PAKE_X2_STEP_ZK_PROOF = 6,
|
||||
PSA_PAKE_SEQ_END = 7,
|
||||
};
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
static psa_status_t mbedtls_ecjpake_to_psa_error(int ret)
|
||||
@ -190,232 +164,16 @@ static psa_status_t mbedtls_ecjpake_to_psa_error(int ret)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
|
||||
psa_status_t psa_pake_setup(psa_pake_operation_t *operation,
|
||||
const psa_pake_cipher_suite_t *cipher_suite)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
/* A context must be freshly initialized before it can be set up. */
|
||||
if (operation->alg != PSA_ALG_NONE) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (cipher_suite == NULL ||
|
||||
PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 ||
|
||||
(cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_ECC &&
|
||||
cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_DH) ||
|
||||
PSA_ALG_IS_HASH(cipher_suite->hash) == 0) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
if (cipher_suite->algorithm == PSA_ALG_JPAKE) {
|
||||
if (cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_ECC ||
|
||||
cipher_suite->family != PSA_ECC_FAMILY_SECP_R1 ||
|
||||
cipher_suite->bits != 256 ||
|
||||
cipher_suite->hash != PSA_ALG_SHA_256) {
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
operation->alg = cipher_suite->algorithm;
|
||||
|
||||
mbedtls_ecjpake_init(&operation->ctx.ecjpake);
|
||||
|
||||
operation->state = PSA_PAKE_STATE_SETUP;
|
||||
operation->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
operation->input_step = PSA_PAKE_STEP_X1_X2;
|
||||
operation->output_step = PSA_PAKE_STEP_X1_X2;
|
||||
|
||||
mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
|
||||
operation->buffer_length = 0;
|
||||
operation->buffer_offset = 0;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
} else
|
||||
#endif
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
error:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation,
|
||||
mbedtls_svc_key_id_t password)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_attributes_t attributes = psa_key_attributes_init();
|
||||
psa_key_type_t type;
|
||||
psa_key_usage_t usage;
|
||||
psa_key_slot_t *slot = NULL;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state != PSA_PAKE_STATE_SETUP) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = psa_get_key_attributes(password, &attributes);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
type = psa_get_key_type(&attributes);
|
||||
usage = psa_get_key_usage_flags(&attributes);
|
||||
|
||||
psa_reset_key_attributes(&attributes);
|
||||
|
||||
if (type != PSA_KEY_TYPE_PASSWORD &&
|
||||
type != PSA_KEY_TYPE_PASSWORD_HASH) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((usage & PSA_KEY_USAGE_DERIVE) == 0) {
|
||||
status = PSA_ERROR_NOT_PERMITTED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (operation->password != NULL) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
status = psa_get_and_lock_key_slot_with_policy(password, &slot,
|
||||
PSA_KEY_USAGE_DERIVE,
|
||||
PSA_ALG_JPAKE);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
operation->password = mbedtls_calloc(1, slot->key.bytes);
|
||||
if (operation->password == NULL) {
|
||||
psa_unlock_key_slot(slot);
|
||||
return PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
memcpy(operation->password, slot->key.data, slot->key.bytes);
|
||||
operation->password_len = slot->key.bytes;
|
||||
|
||||
status = psa_unlock_key_slot(slot);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_user(psa_pake_operation_t *operation,
|
||||
const uint8_t *user_id,
|
||||
size_t user_id_len)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state != PSA_PAKE_STATE_SETUP) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (user_id_len == 0 || user_id == NULL) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
error:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation,
|
||||
const uint8_t *peer_id,
|
||||
size_t peer_id_len)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state != PSA_PAKE_STATE_SETUP) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (peer_id_len == 0 || peer_id == NULL) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
error:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_set_role(psa_pake_operation_t *operation,
|
||||
psa_pake_role_t role)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state != PSA_PAKE_STATE_SETUP) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (role != PSA_PAKE_ROLE_NONE &&
|
||||
role != PSA_PAKE_ROLE_FIRST &&
|
||||
role != PSA_PAKE_ROLE_SECOND &&
|
||||
role != PSA_PAKE_ROLE_CLIENT &&
|
||||
role != PSA_PAKE_ROLE_SERVER) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
if (role != PSA_PAKE_ROLE_CLIENT &&
|
||||
role != PSA_PAKE_ROLE_SERVER) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
operation->role = role;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
} else
|
||||
#endif
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
error:
|
||||
psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
static psa_status_t psa_pake_ecjpake_setup(psa_pake_operation_t *operation)
|
||||
static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_ecjpake_role role;
|
||||
mbedtls_ecjpake_role role = (operation->role == PSA_PAKE_ROLE_CLIENT) ?
|
||||
MBEDTLS_ECJPAKE_CLIENT : MBEDTLS_ECJPAKE_SERVER;
|
||||
|
||||
if (operation->role == PSA_PAKE_ROLE_CLIENT) {
|
||||
role = MBEDTLS_ECJPAKE_CLIENT;
|
||||
} else if (operation->role == PSA_PAKE_ROLE_SERVER) {
|
||||
role = MBEDTLS_ECJPAKE_SERVER;
|
||||
} else {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
mbedtls_ecjpake_init(&operation->ctx.jpake);
|
||||
|
||||
if (operation->password_len == 0) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
ret = mbedtls_ecjpake_setup(&operation->ctx.ecjpake,
|
||||
ret = mbedtls_ecjpake_setup(&operation->ctx.jpake,
|
||||
role,
|
||||
MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_ECP_DP_SECP256R1,
|
||||
@ -423,39 +181,101 @@ static psa_status_t psa_pake_ecjpake_setup(psa_pake_operation_t *operation)
|
||||
operation->password_len);
|
||||
|
||||
mbedtls_platform_zeroize(operation->password, operation->password_len);
|
||||
mbedtls_free(operation->password);
|
||||
operation->password = NULL;
|
||||
operation->password_len = 0;
|
||||
|
||||
if (ret != 0) {
|
||||
return mbedtls_ecjpake_to_psa_error(ret);
|
||||
}
|
||||
|
||||
operation->state = PSA_PAKE_STATE_READY;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static psa_status_t psa_pake_output_internal(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step,
|
||||
psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,
|
||||
const psa_crypto_driver_pake_inputs_t *inputs)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t password_len = 0;
|
||||
psa_pake_role_t role = PSA_PAKE_ROLE_NONE;
|
||||
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
|
||||
size_t actual_password_len = 0;
|
||||
|
||||
status = psa_crypto_driver_pake_get_password_len(inputs, &password_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = psa_crypto_driver_pake_get_role(inputs, &role);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
operation->password = mbedtls_calloc(1, password_len);
|
||||
if (operation->password == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
status = psa_crypto_driver_pake_get_password(inputs, operation->password,
|
||||
password_len, &actual_password_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
operation->password_len = actual_password_len;
|
||||
operation->alg = cipher_suite.algorithm;
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
if (cipher_suite.algorithm == PSA_ALG_JPAKE) {
|
||||
if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC ||
|
||||
cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 ||
|
||||
cipher_suite.bits != 256 ||
|
||||
cipher_suite.hash != PSA_ALG_SHA_256) {
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
operation->role = role;
|
||||
|
||||
operation->buffer_length = 0;
|
||||
operation->buffer_offset = 0;
|
||||
|
||||
status = psa_pake_ecjpake_setup(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
} else
|
||||
#else
|
||||
(void) operation;
|
||||
(void) inputs;
|
||||
#endif
|
||||
{ status = PSA_ERROR_NOT_SUPPORTED; }
|
||||
|
||||
error:
|
||||
/* In case of failure of the setup of a multipart operation, the PSA driver interface
|
||||
* specifies that the core does not call any other driver entry point thus does not
|
||||
* call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean
|
||||
* up like freeing the memory that may have been allocated to store the password.
|
||||
*/
|
||||
mbedtls_psa_pake_abort(operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t mbedtls_psa_pake_output_internal(
|
||||
mbedtls_psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t length;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state == PSA_PAKE_STATE_INVALID) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (output == NULL || output_size == 0 || output_length == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
(void) step; // Unused parameter
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
/*
|
||||
@ -473,77 +293,11 @@ static psa_status_t psa_pake_output_internal(
|
||||
* to return the right parts on each step.
|
||||
*/
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE &&
|
||||
step != PSA_PAKE_STEP_ZK_PUBLIC &&
|
||||
step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (operation->state == PSA_PAKE_STATE_SETUP) {
|
||||
status = psa_pake_ecjpake_setup(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation->state != PSA_PAKE_STATE_READY &&
|
||||
operation->state != PSA_PAKE_OUTPUT_X1_X2 &&
|
||||
operation->state != PSA_PAKE_OUTPUT_X2S) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (operation->state == PSA_PAKE_STATE_READY) {
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
switch (operation->output_step) {
|
||||
case PSA_PAKE_STEP_X1_X2:
|
||||
operation->state = PSA_PAKE_OUTPUT_X1_X2;
|
||||
break;
|
||||
case PSA_PAKE_STEP_X2S:
|
||||
operation->state = PSA_PAKE_OUTPUT_X2S;
|
||||
break;
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
operation->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
|
||||
}
|
||||
|
||||
/* Check if step matches current sequence */
|
||||
switch (operation->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
case PSA_PAKE_X2_STEP_KEY_SHARE:
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
case PSA_PAKE_X2_STEP_ZK_PUBLIC:
|
||||
if (step != PSA_PAKE_STEP_ZK_PUBLIC) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
case PSA_PAKE_X2_STEP_ZK_PROOF:
|
||||
if (step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
/* Initialize & write round on KEY_SHARE sequences */
|
||||
if (operation->state == PSA_PAKE_OUTPUT_X1_X2 &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE) {
|
||||
ret = mbedtls_ecjpake_write_round_one(&operation->ctx.ecjpake,
|
||||
if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) {
|
||||
ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake,
|
||||
operation->buffer,
|
||||
MBEDTLS_PSA_PAKE_BUFFER_SIZE,
|
||||
sizeof(operation->buffer),
|
||||
&operation->buffer_length,
|
||||
mbedtls_psa_get_random,
|
||||
MBEDTLS_PSA_RANDOM_STATE);
|
||||
@ -552,11 +306,10 @@ static psa_status_t psa_pake_output_internal(
|
||||
}
|
||||
|
||||
operation->buffer_offset = 0;
|
||||
} else if (operation->state == PSA_PAKE_OUTPUT_X2S &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE) {
|
||||
ret = mbedtls_ecjpake_write_round_two(&operation->ctx.ecjpake,
|
||||
} else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) {
|
||||
ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake,
|
||||
operation->buffer,
|
||||
MBEDTLS_PSA_PAKE_BUFFER_SIZE,
|
||||
sizeof(operation->buffer),
|
||||
&operation->buffer_length,
|
||||
mbedtls_psa_get_random,
|
||||
MBEDTLS_PSA_RANDOM_STATE);
|
||||
@ -578,8 +331,7 @@ static psa_status_t psa_pake_output_internal(
|
||||
* output with a length byte, even less a curve identifier, as that
|
||||
* information is already available.
|
||||
*/
|
||||
if (operation->state == PSA_PAKE_OUTPUT_X2S &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE &&
|
||||
if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE &&
|
||||
operation->role == PSA_PAKE_ROLE_SERVER) {
|
||||
/* Skip ECParameters, with is 3 bytes (RFC 8422) */
|
||||
operation->buffer_offset += 3;
|
||||
@ -605,60 +357,44 @@ static psa_status_t psa_pake_output_internal(
|
||||
operation->buffer_offset += length;
|
||||
|
||||
/* Reset buffer after ZK_PROOF sequence */
|
||||
if ((operation->state == PSA_PAKE_OUTPUT_X1_X2 &&
|
||||
operation->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) ||
|
||||
(operation->state == PSA_PAKE_OUTPUT_X2S &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF)) {
|
||||
mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
|
||||
if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) ||
|
||||
(step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) {
|
||||
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
|
||||
operation->buffer_length = 0;
|
||||
operation->buffer_offset = 0;
|
||||
|
||||
operation->state = PSA_PAKE_STATE_READY;
|
||||
operation->output_step++;
|
||||
operation->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
} else {
|
||||
operation->sequence++;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
} else
|
||||
#else
|
||||
(void) step;
|
||||
(void) output;
|
||||
(void) output_size;
|
||||
(void) output_length;
|
||||
#endif
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
{ return PSA_ERROR_NOT_SUPPORTED; }
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_output(psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
psa_status_t status = psa_pake_output_internal(
|
||||
psa_status_t status = mbedtls_psa_pake_output_internal(
|
||||
operation, step, output, output_size, output_length);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
psa_pake_abort(operation);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t psa_pake_input_internal(
|
||||
psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step,
|
||||
static psa_status_t mbedtls_psa_pake_input_internal(
|
||||
mbedtls_psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
const uint8_t *input,
|
||||
size_t input_length)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state == PSA_PAKE_STATE_INVALID) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (input == NULL || input_length == 0) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
(void) step; // Unused parameter
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
/*
|
||||
@ -677,77 +413,6 @@ static psa_status_t psa_pake_input_internal(
|
||||
* This causes any input error to be only detected on the last step.
|
||||
*/
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE &&
|
||||
step != PSA_PAKE_STEP_ZK_PUBLIC &&
|
||||
step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
const psa_pake_primitive_t prim = PSA_PAKE_PRIMITIVE(
|
||||
PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256);
|
||||
if (input_length > (size_t) PSA_PAKE_INPUT_SIZE(PSA_ALG_JPAKE, prim, step)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (operation->state == PSA_PAKE_STATE_SETUP) {
|
||||
status = psa_pake_ecjpake_setup(operation);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation->state != PSA_PAKE_STATE_READY &&
|
||||
operation->state != PSA_PAKE_INPUT_X1_X2 &&
|
||||
operation->state != PSA_PAKE_INPUT_X4S) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (operation->state == PSA_PAKE_STATE_READY) {
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
switch (operation->input_step) {
|
||||
case PSA_PAKE_STEP_X1_X2:
|
||||
operation->state = PSA_PAKE_INPUT_X1_X2;
|
||||
break;
|
||||
case PSA_PAKE_STEP_X2S:
|
||||
operation->state = PSA_PAKE_INPUT_X4S;
|
||||
break;
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
operation->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
|
||||
}
|
||||
|
||||
/* Check if step matches current sequence */
|
||||
switch (operation->sequence) {
|
||||
case PSA_PAKE_X1_STEP_KEY_SHARE:
|
||||
case PSA_PAKE_X2_STEP_KEY_SHARE:
|
||||
if (step != PSA_PAKE_STEP_KEY_SHARE) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PUBLIC:
|
||||
case PSA_PAKE_X2_STEP_ZK_PUBLIC:
|
||||
if (step != PSA_PAKE_STEP_ZK_PUBLIC) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_PAKE_X1_STEP_ZK_PROOF:
|
||||
case PSA_PAKE_X2_STEP_ZK_PROOF:
|
||||
if (step != PSA_PAKE_STEP_ZK_PROOF) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy input to local buffer and format it as the Mbed TLS API
|
||||
* expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7.
|
||||
@ -757,8 +422,7 @@ static psa_status_t psa_pake_input_internal(
|
||||
* ECParameters structure - which means we have to prepend that when
|
||||
* we're a client.
|
||||
*/
|
||||
if (operation->state == PSA_PAKE_INPUT_X4S &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE &&
|
||||
if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE &&
|
||||
operation->role == PSA_PAKE_ROLE_CLIENT) {
|
||||
/* We only support secp256r1. */
|
||||
/* This is the ECParameters structure defined by RFC 8422. */
|
||||
@ -766,11 +430,26 @@ static psa_status_t psa_pake_input_internal(
|
||||
3, /* named_curve */
|
||||
0, 23 /* secp256r1 */
|
||||
};
|
||||
|
||||
if (operation->buffer_length + sizeof(ecparameters) >
|
||||
sizeof(operation->buffer)) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
memcpy(operation->buffer + operation->buffer_length,
|
||||
ecparameters, sizeof(ecparameters));
|
||||
operation->buffer_length += sizeof(ecparameters);
|
||||
}
|
||||
|
||||
/*
|
||||
* The core checks that input_length is smaller than
|
||||
* PSA_PAKE_INPUT_MAX_SIZE.
|
||||
* Thus no risk of integer overflow here.
|
||||
*/
|
||||
if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Write the length byte */
|
||||
operation->buffer[operation->buffer_length] = (uint8_t) input_length;
|
||||
operation->buffer_length += 1;
|
||||
@ -781,25 +460,23 @@ static psa_status_t psa_pake_input_internal(
|
||||
operation->buffer_length += input_length;
|
||||
|
||||
/* Load buffer at each last round ZK_PROOF */
|
||||
if (operation->state == PSA_PAKE_INPUT_X1_X2 &&
|
||||
operation->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) {
|
||||
ret = mbedtls_ecjpake_read_round_one(&operation->ctx.ecjpake,
|
||||
if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) {
|
||||
ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake,
|
||||
operation->buffer,
|
||||
operation->buffer_length);
|
||||
|
||||
mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
|
||||
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
|
||||
operation->buffer_length = 0;
|
||||
|
||||
if (ret != 0) {
|
||||
return mbedtls_ecjpake_to_psa_error(ret);
|
||||
}
|
||||
} else if (operation->state == PSA_PAKE_INPUT_X4S &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF) {
|
||||
ret = mbedtls_ecjpake_read_round_two(&operation->ctx.ecjpake,
|
||||
} else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) {
|
||||
ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake,
|
||||
operation->buffer,
|
||||
operation->buffer_length);
|
||||
|
||||
mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
|
||||
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
|
||||
operation->buffer_length = 0;
|
||||
|
||||
if (ret != 0) {
|
||||
@ -807,113 +484,72 @@ static psa_status_t psa_pake_input_internal(
|
||||
}
|
||||
}
|
||||
|
||||
if ((operation->state == PSA_PAKE_INPUT_X1_X2 &&
|
||||
operation->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) ||
|
||||
(operation->state == PSA_PAKE_INPUT_X4S &&
|
||||
operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF)) {
|
||||
operation->state = PSA_PAKE_STATE_READY;
|
||||
operation->input_step++;
|
||||
operation->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
} else {
|
||||
operation->sequence++;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
} else
|
||||
#else
|
||||
(void) step;
|
||||
(void) input;
|
||||
(void) input_length;
|
||||
#endif
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
{ return PSA_ERROR_NOT_SUPPORTED; }
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_input(psa_pake_operation_t *operation,
|
||||
psa_pake_step_t step,
|
||||
const uint8_t *input,
|
||||
size_t input_length)
|
||||
psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
const uint8_t *input,
|
||||
size_t input_length)
|
||||
{
|
||||
psa_status_t status = psa_pake_input_internal(
|
||||
psa_status_t status = mbedtls_psa_pake_input_internal(
|
||||
operation, step, input, input_length);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
psa_pake_abort(operation);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,
|
||||
psa_key_derivation_operation_t *output)
|
||||
psa_status_t mbedtls_psa_pake_get_implicit_key(
|
||||
mbedtls_psa_pake_operation_t *operation,
|
||||
uint8_t *output, size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation->alg == PSA_ALG_NONE ||
|
||||
operation->state != PSA_PAKE_STATE_READY ||
|
||||
operation->input_step != PSA_PAKE_STEP_DERIVE ||
|
||||
operation->output_step != PSA_PAKE_STEP_DERIVE) {
|
||||
status = PSA_ERROR_BAD_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.ecjpake,
|
||||
operation->buffer,
|
||||
MBEDTLS_PSA_PAKE_BUFFER_SIZE,
|
||||
&operation->buffer_length,
|
||||
ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake,
|
||||
output,
|
||||
output_size,
|
||||
output_length,
|
||||
mbedtls_psa_get_random,
|
||||
MBEDTLS_PSA_RANDOM_STATE);
|
||||
if (ret != 0) {
|
||||
psa_pake_abort(operation);
|
||||
return mbedtls_ecjpake_to_psa_error(ret);
|
||||
}
|
||||
|
||||
status = psa_key_derivation_input_bytes(output,
|
||||
PSA_KEY_DERIVATION_INPUT_SECRET,
|
||||
operation->buffer,
|
||||
operation->buffer_length);
|
||||
|
||||
mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
|
||||
|
||||
psa_pake_abort(operation);
|
||||
|
||||
return status;
|
||||
return PSA_SUCCESS;
|
||||
} else
|
||||
#else
|
||||
(void) output;
|
||||
#endif
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
error:
|
||||
psa_key_derivation_abort(output);
|
||||
psa_pake_abort(operation);
|
||||
|
||||
return status;
|
||||
{ return PSA_ERROR_NOT_SUPPORTED; }
|
||||
}
|
||||
|
||||
psa_status_t psa_pake_abort(psa_pake_operation_t *operation)
|
||||
psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation)
|
||||
{
|
||||
if (operation->alg == PSA_ALG_NONE) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
mbedtls_platform_zeroize(operation->password, operation->password_len);
|
||||
mbedtls_free(operation->password);
|
||||
operation->password = NULL;
|
||||
operation->password_len = 0;
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
|
||||
if (operation->alg == PSA_ALG_JPAKE) {
|
||||
operation->input_step = PSA_PAKE_STEP_INVALID;
|
||||
operation->output_step = PSA_PAKE_STEP_INVALID;
|
||||
if (operation->password_len > 0) {
|
||||
mbedtls_platform_zeroize(operation->password, operation->password_len);
|
||||
}
|
||||
mbedtls_free(operation->password);
|
||||
operation->password = NULL;
|
||||
operation->password_len = 0;
|
||||
operation->role = PSA_PAKE_ROLE_NONE;
|
||||
mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
|
||||
mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
|
||||
operation->buffer_length = 0;
|
||||
operation->buffer_offset = 0;
|
||||
mbedtls_ecjpake_free(&operation->ctx.ecjpake);
|
||||
mbedtls_ecjpake_free(&operation->ctx.jpake);
|
||||
}
|
||||
#endif
|
||||
|
||||
operation->alg = PSA_ALG_NONE;
|
||||
operation->state = PSA_PAKE_STATE_INVALID;
|
||||
operation->sequence = PSA_PAKE_SEQ_INVALID;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
171
library/psa_crypto_pake.h
Normal file
171
library/psa_crypto_pake.h
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* PSA PAKE layer on top of Mbed TLS software crypto
|
||||
*/
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PSA_CRYPTO_PAKE_H
|
||||
#define PSA_CRYPTO_PAKE_H
|
||||
|
||||
#include <psa/crypto.h>
|
||||
|
||||
/** Set the session information for a password-authenticated key exchange.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* pake_setup entry point. This function behaves as a pake_setup
|
||||
* entry point as defined in the PSA driver interface specification for
|
||||
* transparent drivers.
|
||||
*
|
||||
* \param[in,out] operation The operation object to set up. It must have
|
||||
* been initialized but not set up yet.
|
||||
* \param[in] inputs Inputs required for PAKE operation (role, password,
|
||||
* key lifetime, cipher suite)
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* The algorithm in \p cipher_suite is not a supported PAKE algorithm,
|
||||
* or the PAKE primitive in \p cipher_suite is not supported or not
|
||||
* compatible with the PAKE algorithm, or the hash algorithm in
|
||||
* \p cipher_suite is not supported or not compatible with the PAKE
|
||||
* algorithm and primitive.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
*/
|
||||
psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,
|
||||
const psa_crypto_driver_pake_inputs_t *inputs);
|
||||
|
||||
|
||||
/** Get output for a step of a password-authenticated key exchange.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* pake_output entry point. This function behaves as a pake_output
|
||||
* entry point as defined in the PSA driver interface specification for
|
||||
* transparent drivers.
|
||||
*
|
||||
* \param[in,out] operation Active PAKE operation.
|
||||
* \param step The step of the algorithm for which the output is
|
||||
* requested.
|
||||
* \param[out] output Buffer where the output is to be written in the
|
||||
* format appropriate for this driver \p step. Refer to
|
||||
* the documentation of psa_crypto_driver_pake_step_t for
|
||||
* more information.
|
||||
* \param output_size Size of the \p output buffer in bytes. This must
|
||||
* be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p
|
||||
* primitive, \p step) where \p alg and
|
||||
* \p primitive are the PAKE algorithm and primitive
|
||||
* in the operation's cipher suite, and \p step is
|
||||
* the output step.
|
||||
*
|
||||
* \param[out] output_length On success, the number of bytes of the returned
|
||||
* output.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p output buffer is too small.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_DATA_CORRUPT
|
||||
* \retval #PSA_ERROR_DATA_INVALID
|
||||
*/
|
||||
psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
/** Provide input for a step of a password-authenticated key exchange.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* pake_input entry point. This function behaves as a pake_input
|
||||
* entry point as defined in the PSA driver interface specification for
|
||||
* transparent drivers.
|
||||
*
|
||||
* \note The core checks that input_length is smaller than PSA_PAKE_INPUT_MAX_SIZE.
|
||||
*
|
||||
* \param[in,out] operation Active PAKE operation.
|
||||
* \param step The driver step for which the input is provided.
|
||||
* \param[in] input Buffer containing the input in the format
|
||||
* appropriate for this \p step. Refer to the
|
||||
* documentation of psa_crypto_driver_pake_step_t
|
||||
* for more information.
|
||||
* \param input_length Size of the \p input buffer in bytes.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_INVALID_SIGNATURE
|
||||
* The verification fails for a zero-knowledge input step.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* the \p input is not valid for the \p operation's algorithm, cipher suite
|
||||
* or \p step.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* the \p input is not supported for the \p operation's algorithm, cipher
|
||||
* suite or \p step.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_DATA_CORRUPT
|
||||
* \retval #PSA_ERROR_DATA_INVALID
|
||||
*/
|
||||
psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,
|
||||
psa_crypto_driver_pake_step_t step,
|
||||
const uint8_t *input,
|
||||
size_t input_length);
|
||||
|
||||
/** Get implicitly confirmed shared secret from a PAKE.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* pake_get_implicit_key entry point. This function behaves as a
|
||||
* pake_get_implicit_key entry point as defined in the PSA driver
|
||||
* interface specification for transparent drivers.
|
||||
*
|
||||
* \param[in,out] operation Active PAKE operation.
|
||||
* \param[out] output Output buffer for implicit key.
|
||||
* \param output_size Size of the output buffer in bytes.
|
||||
* \param[out] output_length On success, the number of bytes of the implicit key.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* Input from a PAKE is not supported by the algorithm in the \p output
|
||||
* key derivation operation.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_DATA_CORRUPT
|
||||
* \retval #PSA_ERROR_DATA_INVALID
|
||||
*/
|
||||
psa_status_t mbedtls_psa_pake_get_implicit_key(
|
||||
mbedtls_psa_pake_operation_t *operation,
|
||||
uint8_t *output, size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
/** Abort a PAKE operation.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* pake_abort entry point. This function behaves as a pake_abort
|
||||
* entry point as defined in the PSA driver interface specification for
|
||||
* transparent drivers.
|
||||
*
|
||||
* \param[in,out] operation The operation to abort.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
*/
|
||||
psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation);
|
||||
|
||||
#endif /* PSA_CRYPTO_PAKE_H */
|
Reference in New Issue
Block a user