1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-08-08 17:42:09 +03:00

Merge pull request #7719 from davidhorstmann-arm/second-jpake-state-machine-rework

Change J-PAKE internal state machine
This commit is contained in:
Janos Follath
2023-06-28 08:59:23 +01:00
committed by GitHub
6 changed files with 213 additions and 335 deletions

View File

@@ -7765,10 +7765,8 @@ psa_status_t psa_pake_setup(
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;
memset(computation_stage, 0, sizeof(*computation_stage));
computation_stage->step = PSA_PAKE_STEP_KEY_SHARE;
} else
#endif /* PSA_WANT_ALG_JPAKE */
{
@@ -7937,59 +7935,32 @@ exit:
return status;
}
/* Auxiliary function to convert core computation stage(step, sequence, state) to single driver step. */
/* Auxiliary function to convert core computation stage 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;
psa_crypto_driver_pake_step_t key_share_step;
if (stage->round == PSA_JPAKE_FIRST) {
int is_x1;
if (stage->io_mode == PSA_JPAKE_OUTPUT) {
is_x1 = (stage->outputs < 1);
} else {
is_x1 = (stage->inputs < 1);
}
key_share_step = is_x1 ?
PSA_JPAKE_X1_STEP_KEY_SHARE :
PSA_JPAKE_X2_STEP_KEY_SHARE;
} else if (stage->round == PSA_JPAKE_SECOND) {
key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ?
PSA_JPAKE_X2S_STEP_KEY_SHARE :
PSA_JPAKE_X4S_STEP_KEY_SHARE;
} else {
return PSA_JPAKE_STEP_INVALID;
}
return PSA_JPAKE_STEP_INVALID;
return key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE;
}
#endif /* PSA_WANT_ALG_JPAKE */
@@ -8028,12 +7999,6 @@ static psa_status_t psa_pake_complete_inputs(
#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 */
{
@@ -8044,9 +8009,10 @@ static psa_status_t psa_pake_complete_inputs(
}
#if defined(PSA_WANT_ALG_JPAKE)
static psa_status_t psa_jpake_output_prologue(
static psa_status_t psa_jpake_prologue(
psa_pake_operation_t *operation,
psa_pake_step_t step)
psa_pake_step_t step,
psa_jpake_io_mode_t io_mode)
{
if (step != PSA_PAKE_STEP_KEY_SHARE &&
step != PSA_PAKE_STEP_ZK_PUBLIC &&
@@ -8057,84 +8023,66 @@ static psa_status_t psa_jpake_output_prologue(
psa_jpake_computation_stage_t *computation_stage =
&operation->computation_stage.jpake;
if (computation_stage->state == PSA_PAKE_STATE_INVALID) {
if (computation_stage->round != PSA_JPAKE_FIRST &&
computation_stage->round != PSA_JPAKE_SECOND) {
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) {
/* Check that the step we are given is the one we were expecting */
if (step != computation_stage->step) {
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;
if (step == PSA_PAKE_STEP_KEY_SHARE &&
computation_stage->inputs == 0 &&
computation_stage->outputs == 0) {
/* Start of the round, so function decides whether we are inputting
* or outputting */
computation_stage->io_mode = io_mode;
} else if (computation_stage->io_mode != io_mode) {
/* Middle of the round so the mode we are in must match the function
* called by the user */
return PSA_ERROR_BAD_STATE;
}
return PSA_SUCCESS;
}
static psa_status_t psa_jpake_output_epilogue(
psa_pake_operation_t *operation)
static psa_status_t psa_jpake_epilogue(
psa_pake_operation_t *operation,
psa_jpake_io_mode_t io_mode)
{
psa_jpake_computation_stage_t *computation_stage =
psa_jpake_computation_stage_t *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;
if (stage->step == PSA_PAKE_STEP_ZK_PROOF) {
/* End of an input/output */
if (io_mode == PSA_JPAKE_INPUT) {
stage->inputs++;
if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) {
stage->io_mode = PSA_JPAKE_OUTPUT;
}
}
if (io_mode == PSA_JPAKE_OUTPUT) {
stage->outputs++;
if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {
stage->io_mode = PSA_JPAKE_INPUT;
}
}
if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) &&
stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {
/* End of a round, move to the next round */
stage->inputs = 0;
stage->outputs = 0;
stage->round++;
}
stage->step = PSA_PAKE_STEP_KEY_SHARE;
} else {
computation_stage->sequence++;
stage->step++;
}
return PSA_SUCCESS;
}
#endif /* PSA_WANT_ALG_JPAKE */
psa_status_t psa_pake_output(
@@ -8168,7 +8116,7 @@ psa_status_t psa_pake_output(
switch (operation->alg) {
#if defined(PSA_WANT_ALG_JPAKE)
case PSA_ALG_JPAKE:
status = psa_jpake_output_prologue(operation, step);
status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT);
if (status != PSA_SUCCESS) {
goto exit;
}
@@ -8192,7 +8140,7 @@ psa_status_t psa_pake_output(
switch (operation->alg) {
#if defined(PSA_WANT_ALG_JPAKE)
case PSA_ALG_JPAKE:
status = psa_jpake_output_epilogue(operation);
status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT);
if (status != PSA_SUCCESS) {
goto exit;
}
@@ -8209,100 +8157,6 @@ exit:
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,
@@ -8335,7 +8189,7 @@ psa_status_t psa_pake_input(
switch (operation->alg) {
#if defined(PSA_WANT_ALG_JPAKE)
case PSA_ALG_JPAKE:
status = psa_jpake_input_prologue(operation, step);
status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT);
if (status != PSA_SUCCESS) {
goto exit;
}
@@ -8359,7 +8213,7 @@ psa_status_t psa_pake_input(
switch (operation->alg) {
#if defined(PSA_WANT_ALG_JPAKE)
case PSA_ALG_JPAKE:
status = psa_jpake_input_epilogue(operation);
status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT);
if (status != PSA_SUCCESS) {
goto exit;
}
@@ -8394,8 +8248,7 @@ psa_status_t psa_pake_get_implicit_key(
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) {
if (computation_stage->round != PSA_JPAKE_FINISHED) {
status = PSA_ERROR_BAD_STATE;
goto exit;
}

View File

@@ -80,65 +80,37 @@
*/
/*
* 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.
* It's simpler to share the same sequences numbers of the first
* set of KEY_SHARE/ZK_PUBLIC/ZK_PROOF outputs/inputs in both PAKE steps.
* Possible sequence of calls to implementation:
*
* State sequence with step, state & sequence enums:
* => Input & Output Step = PSA_PAKE_STEP_INVALID
* => state = PSA_PAKE_STATE_INVALID
* psa_pake_setup()
* => Input & Output Step = PSA_PAKE_STEP_X1_X2
* => state = PSA_PAKE_STATE_SETUP
* => sequence = PSA_PAKE_SEQ_INVALID
* |
* |--- In any order: (First round input before or after first round output)
* | | First call of psa_pake_output() or psa_pake_input() sets
* | | state = PSA_PAKE_STATE_READY
* | |
* | |------ In Order: => state = PSA_PAKE_OUTPUT_X1_X2
* | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
* | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
* | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
* | | | psa_pake_output() => sequence = PSA_PAKE_X2_STEP_KEY_SHARE
* | | | psa_pake_output() => sequence = PSA_PAKE_X2_STEP_ZK_PUBLIC
* | | | psa_pake_output() => sequence = PSA_PAKE_X2_STEP_ZK_PROOF
* | | | => state = PSA_PAKE_STATE_READY
* | | | => sequence = PSA_PAKE_SEQ_INVALID
* | | | => Output Step = PSA_PAKE_STEP_X2S
* | |
* | |------ In Order: => state = PSA_PAKE_INPUT_X1_X2
* | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
* | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
* | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
* | | | psa_pake_input() => sequence = PSA_PAKE_X2_STEP_KEY_SHARE
* | | | psa_pake_input() => sequence = PSA_PAKE_X2_STEP_ZK_PUBLIC
* | | | psa_pake_input() => sequence = PSA_PAKE_X2_STEP_ZK_PROOF
* | | | => state = PSA_PAKE_STATE_READY
* | | | => sequence = PSA_PAKE_SEQ_INVALID
* | | | => Output Step = PSA_PAKE_INPUT_X4S
* |
* |--- In any order: (Second round input before or after second round output)
* | |
* | |------ In Order: => state = PSA_PAKE_OUTPUT_X2S
* | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
* | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
* | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
* | | | => state = PSA_PAKE_STATE_READY
* | | | => sequence = PSA_PAKE_SEQ_INVALID
* | | | => Output Step = PSA_PAKE_STEP_DERIVE
* | |
* | |------ In Order: => state = PSA_PAKE_INPUT_X4S
* | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
* | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
* | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
* | | | => state = PSA_PAKE_STATE_READY
* | | | => sequence = PSA_PAKE_SEQ_INVALID
* | | | => Output Step = PSA_PAKE_STEP_DERIVE
* |
* psa_pake_get_implicit_key()
* => Input & Output Step = PSA_PAKE_STEP_INVALID
* |--- In any order:
* | |
* | |------ In Order
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF)
* | |
* | |------ In Order:
* | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF)
* |
* |--- In any order:
* | |
* | |------ In Order
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC)
* | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF)
* | |
* | |------ In Order:
* | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC)
* | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF)
*/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)