blob: 1f9a8cb339e1b2b21f35c296e606658dc0f16760 [file] [log] [blame]
Neil Armstronga4cc7d62022-05-25 11:30:48 +02001/*
2 * PSA PAKE layer on top of Mbed TLS software crypto
3 */
4/*
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include "common.h"
22
23#if defined(MBEDTLS_PSA_CRYPTO_C)
24
25#include <psa/crypto.h>
26#include "psa_crypto_core.h"
27#include "psa_crypto_slot_management.h"
28
29#include <mbedtls/ecjpake.h>
30#include <mbedtls/psa_util.h>
31
32#include <mbedtls/platform.h>
33#include <mbedtls/error.h>
34#include <string.h>
35
Neil Armstronga4cc7d62022-05-25 11:30:48 +020036/*
37 * State sequence:
38 *
39 * psa_pake_setup()
40 * |
41 * |-- In any order:
42 * | | psa_pake_set_password_key()
43 * | | psa_pake_set_user()
44 * | | psa_pake_set_peer()
Neil Armstrongc29f8472022-06-08 13:34:49 +020045 * | | psa_pake_set_role()
Neil Armstronga4cc7d62022-05-25 11:30:48 +020046 * |
47 * |--- In any order: (First round input before or after first round output)
48 * | |
49 * | |------ In Order
50 * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
51 * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
52 * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
53 * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
54 * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
55 * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
56 * | |
57 * | |------ In Order:
58 * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
59 * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
60 * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
61 * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
62 * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
63 * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
64 * |
65 * |--- In any order: (Second round input before or after second round output)
66 * | |
67 * | |------ In Order
68 * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
69 * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
70 * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
71 * | |
72 * | |------ In Order:
73 * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
74 * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
75 * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
76 * |
77 * psa_pake_get_implicit_key()
78 * psa_pake_abort()
79 */
80
Gilles Peskine449bd832023-01-11 14:50:10 +010081enum psa_pake_step {
Neil Armstronga4cc7d62022-05-25 11:30:48 +020082 PSA_PAKE_STEP_INVALID = 0,
83 PSA_PAKE_STEP_X1_X2 = 1,
84 PSA_PAKE_STEP_X2S = 2,
85 PSA_PAKE_STEP_DERIVE = 3,
86};
87
Gilles Peskine449bd832023-01-11 14:50:10 +010088enum psa_pake_state {
Neil Armstronga4cc7d62022-05-25 11:30:48 +020089 PSA_PAKE_STATE_INVALID = 0,
90 PSA_PAKE_STATE_SETUP = 1,
91 PSA_PAKE_STATE_READY = 2,
92 PSA_PAKE_OUTPUT_X1_X2 = 3,
93 PSA_PAKE_OUTPUT_X2S = 4,
94 PSA_PAKE_INPUT_X1_X2 = 5,
95 PSA_PAKE_INPUT_X4S = 6,
96};
97
Neil Armstrongbcd5bd92022-09-05 18:33:23 +020098/*
99 * The first PAKE step shares the same sequences of the second PAKE step
100 * but with a second set of KEY_SHARE/ZK_PUBLIC/ZK_PROOF outputs/inputs.
Neil Armstrongb39833c2022-09-06 11:36:02 +0200101 * It's simpler to share the same sequences numbers of the first
Neil Armstrongbcd5bd92022-09-05 18:33:23 +0200102 * set of KEY_SHARE/ZK_PUBLIC/ZK_PROOF outputs/inputs in both PAKE steps.
103 *
104 * State sequence with step, state & sequence enums:
105 * => Input & Output Step = PSA_PAKE_STEP_INVALID
106 * => state = PSA_PAKE_STATE_INVALID
107 * psa_pake_setup()
108 * => Input & Output Step = PSA_PAKE_STEP_X1_X2
109 * => state = PSA_PAKE_STATE_SETUP
110 * => sequence = PSA_PAKE_SEQ_INVALID
111 * |
112 * |--- In any order: (First round input before or after first round output)
113 * | | First call of psa_pake_output() or psa_pake_input() sets
114 * | | state = PSA_PAKE_STATE_READY
115 * | |
116 * | |------ In Order: => state = PSA_PAKE_OUTPUT_X1_X2
117 * | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
118 * | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
119 * | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
120 * | | | psa_pake_output() => sequence = PSA_PAKE_X2_STEP_KEY_SHARE
121 * | | | psa_pake_output() => sequence = PSA_PAKE_X2_STEP_ZK_PUBLIC
122 * | | | psa_pake_output() => sequence = PSA_PAKE_X2_STEP_ZK_PROOF
123 * | | | => state = PSA_PAKE_STATE_READY
124 * | | | => sequence = PSA_PAKE_SEQ_INVALID
Neil Armstrong9720b882022-09-06 11:39:21 +0200125 * | | | => Output Step = PSA_PAKE_STEP_X2S
Neil Armstrongbcd5bd92022-09-05 18:33:23 +0200126 * | |
127 * | |------ In Order: => state = PSA_PAKE_INPUT_X1_X2
128 * | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
129 * | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
130 * | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
131 * | | | psa_pake_input() => sequence = PSA_PAKE_X2_STEP_KEY_SHARE
132 * | | | psa_pake_input() => sequence = PSA_PAKE_X2_STEP_ZK_PUBLIC
133 * | | | psa_pake_input() => sequence = PSA_PAKE_X2_STEP_ZK_PROOF
134 * | | | => state = PSA_PAKE_STATE_READY
135 * | | | => sequence = PSA_PAKE_SEQ_INVALID
Neil Armstrong9720b882022-09-06 11:39:21 +0200136 * | | | => Output Step = PSA_PAKE_INPUT_X4S
Neil Armstrongbcd5bd92022-09-05 18:33:23 +0200137 * |
138 * |--- In any order: (Second round input before or after second round output)
139 * | |
140 * | |------ In Order: => state = PSA_PAKE_OUTPUT_X2S
141 * | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
142 * | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
143 * | | | psa_pake_output() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
144 * | | | => state = PSA_PAKE_STATE_READY
145 * | | | => sequence = PSA_PAKE_SEQ_INVALID
Neil Armstrong9720b882022-09-06 11:39:21 +0200146 * | | | => Output Step = PSA_PAKE_STEP_DERIVE
Neil Armstrongbcd5bd92022-09-05 18:33:23 +0200147 * | |
148 * | |------ In Order: => state = PSA_PAKE_INPUT_X4S
149 * | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_KEY_SHARE
150 * | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PUBLIC
151 * | | | psa_pake_input() => sequence = PSA_PAKE_X1_STEP_ZK_PROOF
152 * | | | => state = PSA_PAKE_STATE_READY
153 * | | | => sequence = PSA_PAKE_SEQ_INVALID
Neil Armstrong9720b882022-09-06 11:39:21 +0200154 * | | | => Output Step = PSA_PAKE_STEP_DERIVE
Neil Armstrongbcd5bd92022-09-05 18:33:23 +0200155 * |
156 * psa_pake_get_implicit_key()
157 * => Input & Output Step = PSA_PAKE_STEP_INVALID
158 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100159enum psa_pake_sequence {
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200160 PSA_PAKE_SEQ_INVALID = 0,
161 PSA_PAKE_X1_STEP_KEY_SHARE = 1, /* also X2S & X4S KEY_SHARE */
162 PSA_PAKE_X1_STEP_ZK_PUBLIC = 2, /* also X2S & X4S ZK_PUBLIC */
163 PSA_PAKE_X1_STEP_ZK_PROOF = 3, /* also X2S & X4S ZK_PROOF */
164 PSA_PAKE_X2_STEP_KEY_SHARE = 4,
165 PSA_PAKE_X2_STEP_ZK_PUBLIC = 5,
166 PSA_PAKE_X2_STEP_ZK_PROOF = 6,
167 PSA_PAKE_SEQ_END = 7,
168};
169
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200170#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100171static psa_status_t mbedtls_ecjpake_to_psa_error(int ret)
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200172{
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 switch (ret) {
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200174 case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
175 case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
176 case MBEDTLS_ERR_ECP_INVALID_KEY:
177 case MBEDTLS_ERR_ECP_VERIFY_FAILED:
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return PSA_ERROR_DATA_INVALID;
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200179 case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
180 case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
Gilles Peskine449bd832023-01-11 14:50:10 +0100181 return PSA_ERROR_BUFFER_TOO_SMALL;
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200182 case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 return PSA_ERROR_NOT_SUPPORTED;
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200184 case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 return PSA_ERROR_CORRUPTION_DETECTED;
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200186 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 return PSA_ERROR_GENERIC_ERROR;
Neil Armstrongdb05cbf2022-06-15 15:25:45 +0200188 }
189}
190#endif
191
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200192#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100193psa_status_t psa_pake_setup(psa_pake_operation_t *operation,
194 const psa_pake_cipher_suite_t *cipher_suite)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200195{
Valerio Setti6d4e75f2022-11-21 14:56:56 +0100196 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Valerio Settifdb77cd2022-11-11 12:02:24 +0100197
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200198 /* A context must be freshly initialized before it can be set up. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 if (operation->alg != PSA_ALG_NONE) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100200 status = PSA_ERROR_BAD_STATE;
201 goto error;
202 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200203
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 if (cipher_suite == NULL ||
205 PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 ||
206 (cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_ECC &&
207 cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_DH) ||
208 PSA_ALG_IS_HASH(cipher_suite->hash) == 0) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100209 status = PSA_ERROR_INVALID_ARGUMENT;
210 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200211 }
212
Neil Armstronga557cb82022-06-10 08:58:32 +0200213#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 if (cipher_suite->algorithm == PSA_ALG_JPAKE) {
215 if (cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_ECC ||
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200216 cipher_suite->family != PSA_ECC_FAMILY_SECP_R1 ||
217 cipher_suite->bits != 256 ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 cipher_suite->hash != PSA_ALG_SHA_256) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100219 status = PSA_ERROR_NOT_SUPPORTED;
220 goto error;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200221 }
222
223 operation->alg = cipher_suite->algorithm;
224
Gilles Peskine449bd832023-01-11 14:50:10 +0100225 mbedtls_ecjpake_init(&operation->ctx.ecjpake);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200226
227 operation->state = PSA_PAKE_STATE_SETUP;
228 operation->sequence = PSA_PAKE_SEQ_INVALID;
229 operation->input_step = PSA_PAKE_STEP_X1_X2;
230 operation->output_step = PSA_PAKE_STEP_X1_X2;
231
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200233 operation->buffer_length = 0;
234 operation->buffer_offset = 0;
235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 return PSA_SUCCESS;
237 } else
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200238#endif
Valerio Settifdb77cd2022-11-11 12:02:24 +0100239 status = PSA_ERROR_NOT_SUPPORTED;
240
241error:
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 psa_pake_abort(operation);
Valerio Settifdb77cd2022-11-11 12:02:24 +0100243 return status;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200244}
245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation,
247 mbedtls_svc_key_id_t password)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200248{
249 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
250 psa_key_attributes_t attributes = psa_key_attributes_init();
251 psa_key_type_t type;
252 psa_key_usage_t usage;
Przemek Stekiel348410f2022-11-15 22:22:07 +0100253 psa_key_slot_t *slot = NULL;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 if (operation->alg == PSA_ALG_NONE ||
256 operation->state != PSA_PAKE_STATE_SETUP) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100257 status = PSA_ERROR_BAD_STATE;
258 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200259 }
260
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 status = psa_get_key_attributes(password, &attributes);
262 if (status != PSA_SUCCESS) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100263 goto error;
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200265
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 type = psa_get_key_type(&attributes);
267 usage = psa_get_key_usage_flags(&attributes);
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 psa_reset_key_attributes(&attributes);
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 if (type != PSA_KEY_TYPE_PASSWORD &&
272 type != PSA_KEY_TYPE_PASSWORD_HASH) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100273 status = PSA_ERROR_INVALID_ARGUMENT;
274 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200275 }
276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 if ((usage & PSA_KEY_USAGE_DERIVE) == 0) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100278 status = PSA_ERROR_NOT_PERMITTED;
279 goto error;
280 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200281
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 if (operation->password != NULL) {
283 return PSA_ERROR_BAD_STATE;
Przemek Stekiel348410f2022-11-15 22:22:07 +0100284 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100285
286 status = psa_get_and_lock_key_slot_with_policy(password, &slot,
287 PSA_KEY_USAGE_DERIVE,
288 PSA_ALG_JPAKE);
289 if (status != PSA_SUCCESS) {
290 return status;
291 }
292
293 operation->password = mbedtls_calloc(1, slot->key.bytes);
294 if (operation->password == NULL) {
295 psa_unlock_key_slot(slot);
296 return PSA_ERROR_INSUFFICIENT_MEMORY;
297 }
298 memcpy(operation->password, slot->key.data, slot->key.bytes);
Przemek Stekiel152ae072022-11-17 13:24:36 +0100299 operation->password_len = slot->key.bytes;
Przemek Stekiel348410f2022-11-15 22:22:07 +0100300
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 status = psa_unlock_key_slot(slot);
302 if (status != PSA_SUCCESS) {
303 return status;
304 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200305
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 return PSA_SUCCESS;
Valerio Settifdb77cd2022-11-11 12:02:24 +0100307
308error:
309 psa_pake_abort(operation);
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 return status;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200311}
312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313psa_status_t psa_pake_set_user(psa_pake_operation_t *operation,
314 const uint8_t *user_id,
315 size_t user_id_len)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200316{
Valerio Setti6d4e75f2022-11-21 14:56:56 +0100317 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Valerio Settifdb77cd2022-11-11 12:02:24 +0100318
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 if (operation->alg == PSA_ALG_NONE ||
320 operation->state != PSA_PAKE_STATE_SETUP) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100321 status = PSA_ERROR_BAD_STATE;
322 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200323 }
324
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 if (user_id_len == 0 || user_id == NULL) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100326 status = PSA_ERROR_INVALID_ARGUMENT;
327 goto error;
328 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200329
Valerio Settifdb77cd2022-11-11 12:02:24 +0100330 status = PSA_ERROR_NOT_SUPPORTED;
331
332error:
333 psa_pake_abort(operation);
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 return status;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200335}
336
Gilles Peskine449bd832023-01-11 14:50:10 +0100337psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation,
338 const uint8_t *peer_id,
339 size_t peer_id_len)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200340{
Valerio Setti6d4e75f2022-11-21 14:56:56 +0100341 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Valerio Settifdb77cd2022-11-11 12:02:24 +0100342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (operation->alg == PSA_ALG_NONE ||
344 operation->state != PSA_PAKE_STATE_SETUP) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100345 status = PSA_ERROR_BAD_STATE;
346 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200347 }
348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 if (peer_id_len == 0 || peer_id == NULL) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100350 status = PSA_ERROR_INVALID_ARGUMENT;
351 goto error;
352 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200353
Valerio Settifdb77cd2022-11-11 12:02:24 +0100354 status = PSA_ERROR_NOT_SUPPORTED;
355
356error:
357 psa_pake_abort(operation);
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 return status;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200359}
360
Gilles Peskine449bd832023-01-11 14:50:10 +0100361psa_status_t psa_pake_set_role(psa_pake_operation_t *operation,
362 psa_pake_role_t role)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200363{
Valerio Setti6d4e75f2022-11-21 14:56:56 +0100364 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Valerio Settifdb77cd2022-11-11 12:02:24 +0100365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 if (operation->alg == PSA_ALG_NONE ||
367 operation->state != PSA_PAKE_STATE_SETUP) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100368 status = PSA_ERROR_BAD_STATE;
369 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200370 }
371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 if (role != PSA_PAKE_ROLE_NONE &&
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200373 role != PSA_PAKE_ROLE_FIRST &&
374 role != PSA_PAKE_ROLE_SECOND &&
375 role != PSA_PAKE_ROLE_CLIENT &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 role != PSA_PAKE_ROLE_SERVER) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100377 status = PSA_ERROR_INVALID_ARGUMENT;
378 goto error;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200379 }
380
Neil Armstronga557cb82022-06-10 08:58:32 +0200381#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 if (operation->alg == PSA_ALG_JPAKE) {
383 if (role != PSA_PAKE_ROLE_CLIENT &&
384 role != PSA_PAKE_ROLE_SERVER) {
385 return PSA_ERROR_NOT_SUPPORTED;
386 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200387
388 operation->role = role;
389
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 return PSA_SUCCESS;
391 } else
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200392#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 status = PSA_ERROR_NOT_SUPPORTED;
Valerio Settifdb77cd2022-11-11 12:02:24 +0100394
395error:
396 psa_pake_abort(operation);
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 return status;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200398}
399
Neil Armstronga557cb82022-06-10 08:58:32 +0200400#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100401static psa_status_t psa_pake_ecjpake_setup(psa_pake_operation_t *operation)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200402{
403 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200404 mbedtls_ecjpake_role role;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200405
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 if (operation->role == PSA_PAKE_ROLE_CLIENT) {
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200407 role = MBEDTLS_ECJPAKE_CLIENT;
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 } else if (operation->role == PSA_PAKE_ROLE_SERVER) {
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200409 role = MBEDTLS_ECJPAKE_SERVER;
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 } else {
411 return PSA_ERROR_BAD_STATE;
412 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 if (operation->password_len == 0) {
415 return PSA_ERROR_BAD_STATE;
416 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200417
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 ret = mbedtls_ecjpake_setup(&operation->ctx.ecjpake,
419 role,
420 MBEDTLS_MD_SHA256,
421 MBEDTLS_ECP_DP_SECP256R1,
422 operation->password,
423 operation->password_len);
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200424
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 mbedtls_platform_zeroize(operation->password, operation->password_len);
426 mbedtls_free(operation->password);
Przemek Stekielad0f3572022-11-21 15:04:37 +0100427 operation->password = NULL;
428 operation->password_len = 0;
429
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 if (ret != 0) {
431 return mbedtls_ecjpake_to_psa_error(ret);
432 }
Przemek Stekiel0bdec192022-11-22 09:10:35 +0100433
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200434 operation->state = PSA_PAKE_STATE_READY;
435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 return PSA_SUCCESS;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200437}
438#endif
439
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200440static psa_status_t psa_pake_output_internal(
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 psa_pake_operation_t *operation,
442 psa_pake_step_t step,
443 uint8_t *output,
444 size_t output_size,
445 size_t *output_length)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200446{
447 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
448 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
449 size_t length;
450
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 if (operation->alg == PSA_ALG_NONE ||
452 operation->state == PSA_PAKE_STATE_INVALID) {
453 return PSA_ERROR_BAD_STATE;
454 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 if (output == NULL || output_size == 0 || output_length == NULL) {
457 return PSA_ERROR_INVALID_ARGUMENT;
458 }
Neil Armstrong0d001ef2022-06-08 17:42:52 +0200459
Neil Armstronga557cb82022-06-10 08:58:32 +0200460#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Neil Armstrongfa849622022-09-13 15:10:46 +0200461 /*
462 * The PSA CRYPTO PAKE and MbedTLS JPAKE API have a different
463 * handling of output sequencing.
464 *
Neil Armstrong6a12a772022-09-14 12:17:42 +0200465 * The MbedTLS JPAKE API outputs the whole X1+X2 and X2S steps data
Neil Armstrongfa849622022-09-13 15:10:46 +0200466 * at once, on the other side the PSA CRYPTO PAKE api requires
467 * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be
468 * retrieved in sequence.
469 *
470 * In order to achieve API compatibility, the whole X1+X2 or X2S steps
471 * data is stored in an intermediate buffer at first step output call,
472 * and data is sliced down by parsing the ECPoint records in order
473 * to return the right parts on each step.
474 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 if (operation->alg == PSA_ALG_JPAKE) {
476 if (step != PSA_PAKE_STEP_KEY_SHARE &&
Neil Armstrong3d4966a2022-09-13 14:54:15 +0200477 step != PSA_PAKE_STEP_ZK_PUBLIC &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 step != PSA_PAKE_STEP_ZK_PROOF) {
479 return PSA_ERROR_INVALID_ARGUMENT;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200480 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200481
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 if (operation->state == PSA_PAKE_STATE_SETUP) {
483 status = psa_pake_ecjpake_setup(operation);
484 if (status != PSA_SUCCESS) {
485 return status;
486 }
487 }
488
489 if (operation->state != PSA_PAKE_STATE_READY &&
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200490 operation->state != PSA_PAKE_OUTPUT_X1_X2 &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 operation->state != PSA_PAKE_OUTPUT_X2S) {
492 return PSA_ERROR_BAD_STATE;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200493 }
494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 if (operation->state == PSA_PAKE_STATE_READY) {
496 if (step != PSA_PAKE_STEP_KEY_SHARE) {
497 return PSA_ERROR_BAD_STATE;
498 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 switch (operation->output_step) {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200501 case PSA_PAKE_STEP_X1_X2:
502 operation->state = PSA_PAKE_OUTPUT_X1_X2;
503 break;
504 case PSA_PAKE_STEP_X2S:
505 operation->state = PSA_PAKE_OUTPUT_X2S;
506 break;
507 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 return PSA_ERROR_BAD_STATE;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200509 }
510
511 operation->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
512 }
513
514 /* Check if step matches current sequence */
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 switch (operation->sequence) {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200516 case PSA_PAKE_X1_STEP_KEY_SHARE:
517 case PSA_PAKE_X2_STEP_KEY_SHARE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 if (step != PSA_PAKE_STEP_KEY_SHARE) {
519 return PSA_ERROR_BAD_STATE;
520 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200521 break;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200522
523 case PSA_PAKE_X1_STEP_ZK_PUBLIC:
524 case PSA_PAKE_X2_STEP_ZK_PUBLIC:
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 if (step != PSA_PAKE_STEP_ZK_PUBLIC) {
526 return PSA_ERROR_BAD_STATE;
527 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200528 break;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200529
530 case PSA_PAKE_X1_STEP_ZK_PROOF:
531 case PSA_PAKE_X2_STEP_ZK_PROOF:
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 if (step != PSA_PAKE_STEP_ZK_PROOF) {
533 return PSA_ERROR_BAD_STATE;
534 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200535 break;
536
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200537 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 return PSA_ERROR_BAD_STATE;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200539 }
540
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200541 /* Initialize & write round on KEY_SHARE sequences */
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 if (operation->state == PSA_PAKE_OUTPUT_X1_X2 &&
543 operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE) {
544 ret = mbedtls_ecjpake_write_round_one(&operation->ctx.ecjpake,
545 operation->buffer,
546 MBEDTLS_PSA_PAKE_BUFFER_SIZE,
547 &operation->buffer_length,
548 mbedtls_psa_get_random,
549 MBEDTLS_PSA_RANDOM_STATE);
550 if (ret != 0) {
551 return mbedtls_ecjpake_to_psa_error(ret);
552 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200553
554 operation->buffer_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 } else if (operation->state == PSA_PAKE_OUTPUT_X2S &&
556 operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE) {
557 ret = mbedtls_ecjpake_write_round_two(&operation->ctx.ecjpake,
558 operation->buffer,
559 MBEDTLS_PSA_PAKE_BUFFER_SIZE,
560 &operation->buffer_length,
561 mbedtls_psa_get_random,
562 MBEDTLS_PSA_RANDOM_STATE);
563 if (ret != 0) {
564 return mbedtls_ecjpake_to_psa_error(ret);
565 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200566
567 operation->buffer_offset = 0;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200568 }
569
Neil Armstrong1d0294f2022-09-13 14:49:24 +0200570 /*
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200571 * mbedtls_ecjpake_write_round_xxx() outputs thing in the format
572 * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is
573 * that the data for each step is prepended with a length byte, and
574 * then they're concatenated. Additionally, the server's second round
575 * output is prepended with a 3-bytes ECParameters structure.
Neil Armstrong1d0294f2022-09-13 14:49:24 +0200576 *
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200577 * In PSA, we output each step separately, and don't prepend the
578 * output with a length byte, even less a curve identifier, as that
579 * information is already available.
Neil Armstrong1d0294f2022-09-13 14:49:24 +0200580 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100581 if (operation->state == PSA_PAKE_OUTPUT_X2S &&
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200582 operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 operation->role == PSA_PAKE_ROLE_SERVER) {
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200584 /* Skip ECParameters, with is 3 bytes (RFC 8422) */
585 operation->buffer_offset += 3;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200586 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200587
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200588 /* Read the length byte then move past it to the data */
589 length = operation->buffer[operation->buffer_offset];
590 operation->buffer_offset += 1;
591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 if (operation->buffer_offset + length > operation->buffer_length) {
593 return PSA_ERROR_DATA_CORRUPT;
594 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200595
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 if (output_size < length) {
597 return PSA_ERROR_BUFFER_TOO_SMALL;
598 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200599
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 memcpy(output,
601 operation->buffer + operation->buffer_offset,
602 length);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200603 *output_length = length;
604
605 operation->buffer_offset += length;
606
607 /* Reset buffer after ZK_PROOF sequence */
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 if ((operation->state == PSA_PAKE_OUTPUT_X1_X2 &&
609 operation->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) ||
610 (operation->state == PSA_PAKE_OUTPUT_X2S &&
611 operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF)) {
612 mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200613 operation->buffer_length = 0;
614 operation->buffer_offset = 0;
615
616 operation->state = PSA_PAKE_STATE_READY;
617 operation->output_step++;
Neil Armstrongcb679f22022-09-13 14:43:07 +0200618 operation->sequence = PSA_PAKE_SEQ_INVALID;
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 } else {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200620 operation->sequence++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200622
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 return PSA_SUCCESS;
624 } else
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200625#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 return PSA_ERROR_NOT_SUPPORTED;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200627}
628
Gilles Peskine449bd832023-01-11 14:50:10 +0100629psa_status_t psa_pake_output(psa_pake_operation_t *operation,
630 psa_pake_step_t step,
631 uint8_t *output,
632 size_t output_size,
633 size_t *output_length)
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200634{
635 psa_status_t status = psa_pake_output_internal(
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 operation, step, output, output_size, output_length);
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200637
Gilles Peskine449bd832023-01-11 14:50:10 +0100638 if (status != PSA_SUCCESS) {
639 psa_pake_abort(operation);
640 }
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200641
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 return status;
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200643}
644
645static psa_status_t psa_pake_input_internal(
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 psa_pake_operation_t *operation,
647 psa_pake_step_t step,
648 const uint8_t *input,
649 size_t input_length)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200650{
651 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
652 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200653
Gilles Peskine449bd832023-01-11 14:50:10 +0100654 if (operation->alg == PSA_ALG_NONE ||
655 operation->state == PSA_PAKE_STATE_INVALID) {
656 return PSA_ERROR_BAD_STATE;
657 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200658
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 if (input == NULL || input_length == 0) {
660 return PSA_ERROR_INVALID_ARGUMENT;
661 }
Neil Armstrong0d001ef2022-06-08 17:42:52 +0200662
Neil Armstronga557cb82022-06-10 08:58:32 +0200663#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Neil Armstrongfa849622022-09-13 15:10:46 +0200664 /*
665 * The PSA CRYPTO PAKE and MbedTLS JPAKE API have a different
666 * handling of input sequencing.
667 *
668 * The MbedTLS JPAKE API takes the whole X1+X2 or X4S steps data
669 * at once as input, on the other side the PSA CRYPTO PAKE api requires
670 * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be
671 * given in sequence.
672 *
673 * In order to achieve API compatibility, each X1+X2 or X4S step data
674 * is stored sequentially in an intermediate buffer and given to the
675 * MbedTLS JPAKE API on the last step.
676 *
677 * This causes any input error to be only detected on the last step.
678 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 if (operation->alg == PSA_ALG_JPAKE) {
680 if (step != PSA_PAKE_STEP_KEY_SHARE &&
Neil Armstrong3d4966a2022-09-13 14:54:15 +0200681 step != PSA_PAKE_STEP_ZK_PUBLIC &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 step != PSA_PAKE_STEP_ZK_PROOF) {
683 return PSA_ERROR_INVALID_ARGUMENT;
684 }
Neil Armstrong3d4966a2022-09-13 14:54:15 +0200685
Manuel Pégourié-Gonnard0771d412022-10-06 09:30:34 +0200686 const psa_pake_primitive_t prim = PSA_PAKE_PRIMITIVE(
Gilles Peskine449bd832023-01-11 14:50:10 +0100687 PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256);
688 if (input_length > (size_t) PSA_PAKE_INPUT_SIZE(PSA_ALG_JPAKE, prim, step)) {
689 return PSA_ERROR_INVALID_ARGUMENT;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200690 }
691
Gilles Peskine449bd832023-01-11 14:50:10 +0100692 if (operation->state == PSA_PAKE_STATE_SETUP) {
693 status = psa_pake_ecjpake_setup(operation);
694 if (status != PSA_SUCCESS) {
695 return status;
696 }
697 }
698
699 if (operation->state != PSA_PAKE_STATE_READY &&
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200700 operation->state != PSA_PAKE_INPUT_X1_X2 &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100701 operation->state != PSA_PAKE_INPUT_X4S) {
702 return PSA_ERROR_BAD_STATE;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200703 }
704
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 if (operation->state == PSA_PAKE_STATE_READY) {
706 if (step != PSA_PAKE_STEP_KEY_SHARE) {
707 return PSA_ERROR_BAD_STATE;
708 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200709
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 switch (operation->input_step) {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200711 case PSA_PAKE_STEP_X1_X2:
712 operation->state = PSA_PAKE_INPUT_X1_X2;
713 break;
714 case PSA_PAKE_STEP_X2S:
715 operation->state = PSA_PAKE_INPUT_X4S;
716 break;
717 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 return PSA_ERROR_BAD_STATE;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200719 }
720
721 operation->sequence = PSA_PAKE_X1_STEP_KEY_SHARE;
722 }
723
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200724 /* Check if step matches current sequence */
Gilles Peskine449bd832023-01-11 14:50:10 +0100725 switch (operation->sequence) {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200726 case PSA_PAKE_X1_STEP_KEY_SHARE:
727 case PSA_PAKE_X2_STEP_KEY_SHARE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 if (step != PSA_PAKE_STEP_KEY_SHARE) {
729 return PSA_ERROR_BAD_STATE;
730 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200731 break;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200732
733 case PSA_PAKE_X1_STEP_ZK_PUBLIC:
734 case PSA_PAKE_X2_STEP_ZK_PUBLIC:
Gilles Peskine449bd832023-01-11 14:50:10 +0100735 if (step != PSA_PAKE_STEP_ZK_PUBLIC) {
736 return PSA_ERROR_BAD_STATE;
737 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200738 break;
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200739
740 case PSA_PAKE_X1_STEP_ZK_PROOF:
741 case PSA_PAKE_X2_STEP_ZK_PROOF:
Gilles Peskine449bd832023-01-11 14:50:10 +0100742 if (step != PSA_PAKE_STEP_ZK_PROOF) {
743 return PSA_ERROR_BAD_STATE;
744 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200745 break;
746
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200747 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 return PSA_ERROR_BAD_STATE;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200749 }
750
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200751 /*
752 * Copy input to local buffer and format it as the Mbed TLS API
753 * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7.
754 * The summary is that the data for each step is prepended with a
755 * length byte, and then they're concatenated. Additionally, the
756 * server's second round output is prepended with a 3-bytes
757 * ECParameters structure - which means we have to prepend that when
758 * we're a client.
759 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100760 if (operation->state == PSA_PAKE_INPUT_X4S &&
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200761 operation->sequence == PSA_PAKE_X1_STEP_KEY_SHARE &&
Gilles Peskine449bd832023-01-11 14:50:10 +0100762 operation->role == PSA_PAKE_ROLE_CLIENT) {
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200763 /* We only support secp256r1. */
764 /* This is the ECParameters structure defined by RFC 8422. */
765 unsigned char ecparameters[3] = {
766 3, /* named_curve */
767 0, 23 /* secp256r1 */
768 };
Gilles Peskine449bd832023-01-11 14:50:10 +0100769 memcpy(operation->buffer + operation->buffer_length,
770 ecparameters, sizeof(ecparameters));
771 operation->buffer_length += sizeof(ecparameters);
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200772 }
773
774 /* Write the length byte */
Manuel Pégourié-Gonnard0771d412022-10-06 09:30:34 +0200775 operation->buffer[operation->buffer_length] = (uint8_t) input_length;
Manuel Pégourié-Gonnardec7012d2022-10-05 12:17:34 +0200776 operation->buffer_length += 1;
777
778 /* Finally copy the data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100779 memcpy(operation->buffer + operation->buffer_length,
780 input, input_length);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200781 operation->buffer_length += input_length;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200782
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200783 /* Load buffer at each last round ZK_PROOF */
Gilles Peskine449bd832023-01-11 14:50:10 +0100784 if (operation->state == PSA_PAKE_INPUT_X1_X2 &&
785 operation->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) {
786 ret = mbedtls_ecjpake_read_round_one(&operation->ctx.ecjpake,
787 operation->buffer,
788 operation->buffer_length);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200789
Gilles Peskine449bd832023-01-11 14:50:10 +0100790 mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200791 operation->buffer_length = 0;
792
Gilles Peskine449bd832023-01-11 14:50:10 +0100793 if (ret != 0) {
794 return mbedtls_ecjpake_to_psa_error(ret);
795 }
796 } else if (operation->state == PSA_PAKE_INPUT_X4S &&
797 operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF) {
798 ret = mbedtls_ecjpake_read_round_two(&operation->ctx.ecjpake,
799 operation->buffer,
800 operation->buffer_length);
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200801
Gilles Peskine449bd832023-01-11 14:50:10 +0100802 mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200803 operation->buffer_length = 0;
804
Gilles Peskine449bd832023-01-11 14:50:10 +0100805 if (ret != 0) {
806 return mbedtls_ecjpake_to_psa_error(ret);
807 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200808 }
809
Gilles Peskine449bd832023-01-11 14:50:10 +0100810 if ((operation->state == PSA_PAKE_INPUT_X1_X2 &&
811 operation->sequence == PSA_PAKE_X2_STEP_ZK_PROOF) ||
812 (operation->state == PSA_PAKE_INPUT_X4S &&
813 operation->sequence == PSA_PAKE_X1_STEP_ZK_PROOF)) {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200814 operation->state = PSA_PAKE_STATE_READY;
815 operation->input_step++;
Neil Armstrongcb679f22022-09-13 14:43:07 +0200816 operation->sequence = PSA_PAKE_SEQ_INVALID;
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 } else {
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200818 operation->sequence++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100819 }
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200820
Gilles Peskine449bd832023-01-11 14:50:10 +0100821 return PSA_SUCCESS;
822 } else
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200823#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100824 return PSA_ERROR_NOT_SUPPORTED;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200825}
826
Gilles Peskine449bd832023-01-11 14:50:10 +0100827psa_status_t psa_pake_input(psa_pake_operation_t *operation,
828 psa_pake_step_t step,
829 const uint8_t *input,
830 size_t input_length)
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200831{
832 psa_status_t status = psa_pake_input_internal(
Gilles Peskine449bd832023-01-11 14:50:10 +0100833 operation, step, input, input_length);
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200834
Gilles Peskine449bd832023-01-11 14:50:10 +0100835 if (status != PSA_SUCCESS) {
836 psa_pake_abort(operation);
837 }
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200838
Gilles Peskine449bd832023-01-11 14:50:10 +0100839 return status;
Manuel Pégourié-Gonnardf155ab92022-10-13 13:11:52 +0200840}
841
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200842psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,
843 psa_key_derivation_operation_t *output)
844{
845 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
846 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
847
Gilles Peskine449bd832023-01-11 14:50:10 +0100848 if (operation->alg == PSA_ALG_NONE ||
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200849 operation->state != PSA_PAKE_STATE_READY ||
Neil Armstrong1e855602022-06-15 11:32:11 +0200850 operation->input_step != PSA_PAKE_STEP_DERIVE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100851 operation->output_step != PSA_PAKE_STEP_DERIVE) {
Valerio Settifdb77cd2022-11-11 12:02:24 +0100852 status = PSA_ERROR_BAD_STATE;
853 goto error;
854 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200855
Neil Armstronga557cb82022-06-10 08:58:32 +0200856#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100857 if (operation->alg == PSA_ALG_JPAKE) {
858 ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.ecjpake,
859 operation->buffer,
860 MBEDTLS_PSA_PAKE_BUFFER_SIZE,
861 &operation->buffer_length,
862 mbedtls_psa_get_random,
863 MBEDTLS_PSA_RANDOM_STATE);
864 if (ret != 0) {
865 psa_pake_abort(operation);
866 return mbedtls_ecjpake_to_psa_error(ret);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200867 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200868
Gilles Peskine449bd832023-01-11 14:50:10 +0100869 status = psa_key_derivation_input_bytes(output,
870 PSA_KEY_DERIVATION_INPUT_SECRET,
871 operation->buffer,
872 operation->buffer_length);
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200873
Gilles Peskine449bd832023-01-11 14:50:10 +0100874 mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200875
Gilles Peskine449bd832023-01-11 14:50:10 +0100876 psa_pake_abort(operation);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200877
Gilles Peskine449bd832023-01-11 14:50:10 +0100878 return status;
879 } else
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200880#endif
Valerio Settifdb77cd2022-11-11 12:02:24 +0100881 status = PSA_ERROR_NOT_SUPPORTED;
882
883error:
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 psa_key_derivation_abort(output);
885 psa_pake_abort(operation);
Valerio Settifdb77cd2022-11-11 12:02:24 +0100886
Gilles Peskine449bd832023-01-11 14:50:10 +0100887 return status;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200888}
889
Gilles Peskine449bd832023-01-11 14:50:10 +0100890psa_status_t psa_pake_abort(psa_pake_operation_t *operation)
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200891{
Gilles Peskine449bd832023-01-11 14:50:10 +0100892 if (operation->alg == PSA_ALG_NONE) {
893 return PSA_SUCCESS;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200894 }
895
Neil Armstronga557cb82022-06-10 08:58:32 +0200896#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100897 if (operation->alg == PSA_ALG_JPAKE) {
Neil Armstrongcb679f22022-09-13 14:43:07 +0200898 operation->input_step = PSA_PAKE_STEP_INVALID;
899 operation->output_step = PSA_PAKE_STEP_INVALID;
Gilles Peskine449bd832023-01-11 14:50:10 +0100900 if (operation->password_len > 0) {
901 mbedtls_platform_zeroize(operation->password, operation->password_len);
902 }
903 mbedtls_free(operation->password);
Przemek Stekiel152ae072022-11-17 13:24:36 +0100904 operation->password = NULL;
905 operation->password_len = 0;
Neil Armstrongcb679f22022-09-13 14:43:07 +0200906 operation->role = PSA_PAKE_ROLE_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100907 mbedtls_platform_zeroize(operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200908 operation->buffer_length = 0;
909 operation->buffer_offset = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100910 mbedtls_ecjpake_free(&operation->ctx.ecjpake);
Neil Armstrong4efd7a42022-06-08 17:18:31 +0200911 }
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200912#endif
913
Neil Armstrongcb679f22022-09-13 14:43:07 +0200914 operation->alg = PSA_ALG_NONE;
915 operation->state = PSA_PAKE_STATE_INVALID;
916 operation->sequence = PSA_PAKE_SEQ_INVALID;
Neil Armstrongfbc4b4a2022-06-10 08:54:53 +0200917
Gilles Peskine449bd832023-01-11 14:50:10 +0100918 return PSA_SUCCESS;
Neil Armstronga4cc7d62022-05-25 11:30:48 +0200919}
920
921#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
922
923#endif /* MBEDTLS_PSA_CRYPTO_C */