blob: 36c1327bd52b6e2d0b6e30932df952f98773d128 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Elliptic curve J-PAKE
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jens Wiklander817466c2018-05-22 13:49:31 +020018 */
19
20/*
21 * References in the code are to the Thread v1.0 Specification,
22 * available to members of the Thread Group http://threadgroup.org/
23 */
24
Jerome Forissier79013242021-07-28 10:24:04 +020025#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020026
27#if defined(MBEDTLS_ECJPAKE_C)
28
29#include "mbedtls/ecjpake.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010030#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020031#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020032
Jens Wiklander32b31802023-10-06 16:59:46 +020033/* We use MD first if it's available (for compatibility reasons)
34 * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
35#if !defined(MBEDTLS_MD_C)
36#include "psa/crypto.h"
37#include "mbedtls/psa_util.h"
38#if !defined(MBEDTLS_ECJPAKE_ALT)
39#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
40 psa_to_md_errors, \
41 psa_generic_status_to_mbedtls)
42#endif /* !MBEDTLS_ECJPAKE_ALT */
43#endif /* !MBEDTLS_MD_C */
44
45#include "hash_info.h"
46
Jens Wiklander817466c2018-05-22 13:49:31 +020047#include <string.h>
48
Jens Wiklander3d3b0592019-03-20 15:30:29 +010049#if !defined(MBEDTLS_ECJPAKE_ALT)
50
Jens Wiklander817466c2018-05-22 13:49:31 +020051/*
52 * Convert a mbedtls_ecjpake_role to identifier string
53 */
54static const char * const ecjpake_id[] = {
55 "client",
56 "server"
57};
58
Jens Wiklander32b31802023-10-06 16:59:46 +020059#define ID_MINE (ecjpake_id[ctx->role])
60#define ID_PEER (ecjpake_id[1 - ctx->role])
61
62/**
63 * Helper to Compute a hash from md_type
64 */
65static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
66 const unsigned char *input, size_t ilen,
67 unsigned char *output)
68{
69#if defined(MBEDTLS_MD_C)
70 return mbedtls_md(mbedtls_md_info_from_type(md_type),
71 input, ilen, output);
72#else
73 psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
74 psa_status_t status;
75 size_t out_size = PSA_HASH_LENGTH(alg);
76 size_t out_len;
77
78 status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
79
80 return PSA_TO_MBEDTLS_ERR(status);
81#endif /* !MBEDTLS_MD_C */
82}
Jens Wiklander817466c2018-05-22 13:49:31 +020083
84/*
85 * Initialize context
86 */
Jens Wiklander32b31802023-10-06 16:59:46 +020087void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020088{
Jens Wiklander32b31802023-10-06 16:59:46 +020089 ctx->md_type = MBEDTLS_MD_NONE;
90 mbedtls_ecp_group_init(&ctx->grp);
Jens Wiklander817466c2018-05-22 13:49:31 +020091 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
92
Jens Wiklander32b31802023-10-06 16:59:46 +020093 mbedtls_ecp_point_init(&ctx->Xm1);
94 mbedtls_ecp_point_init(&ctx->Xm2);
95 mbedtls_ecp_point_init(&ctx->Xp1);
96 mbedtls_ecp_point_init(&ctx->Xp2);
97 mbedtls_ecp_point_init(&ctx->Xp);
Jens Wiklander817466c2018-05-22 13:49:31 +020098
Jens Wiklander32b31802023-10-06 16:59:46 +020099 mbedtls_mpi_init(&ctx->xm1);
100 mbedtls_mpi_init(&ctx->xm2);
101 mbedtls_mpi_init(&ctx->s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200102}
103
104/*
105 * Free context
106 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200107void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200108{
Jens Wiklander32b31802023-10-06 16:59:46 +0200109 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200110 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200111 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200112
Jens Wiklander32b31802023-10-06 16:59:46 +0200113 ctx->md_type = MBEDTLS_MD_NONE;
114 mbedtls_ecp_group_free(&ctx->grp);
Jens Wiklander817466c2018-05-22 13:49:31 +0200115
Jens Wiklander32b31802023-10-06 16:59:46 +0200116 mbedtls_ecp_point_free(&ctx->Xm1);
117 mbedtls_ecp_point_free(&ctx->Xm2);
118 mbedtls_ecp_point_free(&ctx->Xp1);
119 mbedtls_ecp_point_free(&ctx->Xp2);
120 mbedtls_ecp_point_free(&ctx->Xp);
Jens Wiklander817466c2018-05-22 13:49:31 +0200121
Jens Wiklander32b31802023-10-06 16:59:46 +0200122 mbedtls_mpi_free(&ctx->xm1);
123 mbedtls_mpi_free(&ctx->xm2);
124 mbedtls_mpi_free(&ctx->s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200125}
126
127/*
128 * Setup context
129 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200130int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
131 mbedtls_ecjpake_role role,
132 mbedtls_md_type_t hash,
133 mbedtls_ecp_group_id curve,
134 const unsigned char *secret,
135 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200136{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200138
Jens Wiklander32b31802023-10-06 16:59:46 +0200139 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
140 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
141 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100142
Jens Wiklander817466c2018-05-22 13:49:31 +0200143 ctx->role = role;
144
Jens Wiklander32b31802023-10-06 16:59:46 +0200145#if defined(MBEDTLS_MD_C)
146 if ((mbedtls_md_info_from_type(hash)) == NULL) {
147 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
148 }
149#else
150 if (mbedtls_psa_translate_md(hash) == MBEDTLS_MD_NONE) {
151 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
152 }
153#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200154
Jens Wiklander32b31802023-10-06 16:59:46 +0200155 ctx->md_type = hash;
Jens Wiklander817466c2018-05-22 13:49:31 +0200156
Jens Wiklander32b31802023-10-06 16:59:46 +0200157 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
158
159 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Jens Wiklander817466c2018-05-22 13:49:31 +0200160
161cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200162 if (ret != 0) {
163 mbedtls_ecjpake_free(ctx);
164 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200165
Jens Wiklander32b31802023-10-06 16:59:46 +0200166 return ret;
167}
168
169int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
170 int point_format)
171{
172 switch (point_format) {
173 case MBEDTLS_ECP_PF_UNCOMPRESSED:
174 case MBEDTLS_ECP_PF_COMPRESSED:
175 ctx->point_format = point_format;
176 return 0;
177 default:
178 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
179 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200180}
181
182/*
183 * Check if context is ready for use
184 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200185int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200186{
Jens Wiklander32b31802023-10-06 16:59:46 +0200187 if (ctx->md_type == MBEDTLS_MD_NONE ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200188 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Jens Wiklander32b31802023-10-06 16:59:46 +0200189 ctx->s.p == NULL) {
190 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200191 }
192
Jens Wiklander32b31802023-10-06 16:59:46 +0200193 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200194}
195
196/*
197 * Write a point plus its length to a buffer
198 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200199static int ecjpake_write_len_point(unsigned char **p,
200 const unsigned char *end,
201 const mbedtls_ecp_group *grp,
202 const int pf,
203 const mbedtls_ecp_point *P)
Jens Wiklander817466c2018-05-22 13:49:31 +0200204{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200205 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200206 size_t len;
207
208 /* Need at least 4 for length plus 1 for point */
Jens Wiklander32b31802023-10-06 16:59:46 +0200209 if (end < *p || end - *p < 5) {
210 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
211 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200212
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
214 &len, *p + 4, end - (*p + 4));
215 if (ret != 0) {
216 return ret;
217 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200218
Jens Wiklander32b31802023-10-06 16:59:46 +0200219 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200220
221 *p += 4 + len;
222
Jens Wiklander32b31802023-10-06 16:59:46 +0200223 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200224}
225
226/*
227 * Size of the temporary buffer for ecjpake_hash:
228 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
229 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200230#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Jens Wiklander817466c2018-05-22 13:49:31 +0200231
232/*
233 * Compute hash for ZKP (7.4.2.2.2.1)
234 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200235static int ecjpake_hash(const mbedtls_md_type_t md_type,
236 const mbedtls_ecp_group *grp,
237 const int pf,
238 const mbedtls_ecp_point *G,
239 const mbedtls_ecp_point *V,
240 const mbedtls_ecp_point *X,
241 const char *id,
242 mbedtls_mpi *h)
Jens Wiklander817466c2018-05-22 13:49:31 +0200243{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200244 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200245 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
246 unsigned char *p = buf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200247 const unsigned char *end = buf + sizeof(buf);
248 const size_t id_len = strlen(id);
249 unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200250
251 /* Write things to temporary buffer */
Jens Wiklander32b31802023-10-06 16:59:46 +0200252 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
253 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
254 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200255
Jens Wiklander32b31802023-10-06 16:59:46 +0200256 if (end - p < 4) {
257 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
258 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200259
Jens Wiklander32b31802023-10-06 16:59:46 +0200260 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Jerome Forissier039e02d2022-08-09 17:10:15 +0200261 p += 4;
Jens Wiklander817466c2018-05-22 13:49:31 +0200262
Jens Wiklander32b31802023-10-06 16:59:46 +0200263 if (end < p || (size_t) (end - p) < id_len) {
264 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
265 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200266
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 memcpy(p, id, id_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200268 p += id_len;
269
270 /* Compute hash */
Jens Wiklander32b31802023-10-06 16:59:46 +0200271 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
272 buf, p - buf, hash));
Jens Wiklander817466c2018-05-22 13:49:31 +0200273
274 /* Turn it into an integer mod n */
Jens Wiklander32b31802023-10-06 16:59:46 +0200275 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
276 mbedtls_hash_info_get_size(md_type)));
277 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200278
279cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200280 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200281}
282
283/*
284 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
285 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200286static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
287 const mbedtls_ecp_group *grp,
288 const int pf,
289 const mbedtls_ecp_point *G,
290 const mbedtls_ecp_point *X,
291 const char *id,
292 const unsigned char **p,
293 const unsigned char *end)
Jens Wiklander817466c2018-05-22 13:49:31 +0200294{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200295 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200296 mbedtls_ecp_point V, VV;
297 mbedtls_mpi r, h;
298 size_t r_len;
299
Jens Wiklander32b31802023-10-06 16:59:46 +0200300 mbedtls_ecp_point_init(&V);
301 mbedtls_ecp_point_init(&VV);
302 mbedtls_mpi_init(&r);
303 mbedtls_mpi_init(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200304
305 /*
306 * struct {
307 * ECPoint V;
308 * opaque r<1..2^8-1>;
309 * } ECSchnorrZKP;
310 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200311 if (end < *p) {
312 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
313 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200314
Jens Wiklander32b31802023-10-06 16:59:46 +0200315 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
Jens Wiklander817466c2018-05-22 13:49:31 +0200316
Jens Wiklander32b31802023-10-06 16:59:46 +0200317 if (end < *p || (size_t) (end - *p) < 1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200318 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
319 goto cleanup;
320 }
321
322 r_len = *(*p)++;
323
Jens Wiklander32b31802023-10-06 16:59:46 +0200324 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200325 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
326 goto cleanup;
327 }
328
Jens Wiklander32b31802023-10-06 16:59:46 +0200329 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Jens Wiklander817466c2018-05-22 13:49:31 +0200330 *p += r_len;
331
332 /*
333 * Verification
334 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200335 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
336 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
337 &VV, &h, X, &r, G));
Jens Wiklander817466c2018-05-22 13:49:31 +0200338
Jens Wiklander32b31802023-10-06 16:59:46 +0200339 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200340 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
341 goto cleanup;
342 }
343
344cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200345 mbedtls_ecp_point_free(&V);
346 mbedtls_ecp_point_free(&VV);
347 mbedtls_mpi_free(&r);
348 mbedtls_mpi_free(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200349
Jens Wiklander32b31802023-10-06 16:59:46 +0200350 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200351}
352
353/*
354 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
355 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200356static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
357 const mbedtls_ecp_group *grp,
358 const int pf,
359 const mbedtls_ecp_point *G,
360 const mbedtls_mpi *x,
361 const mbedtls_ecp_point *X,
362 const char *id,
363 unsigned char **p,
364 const unsigned char *end,
365 int (*f_rng)(void *, unsigned char *, size_t),
366 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200367{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200368 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200369 mbedtls_ecp_point V;
370 mbedtls_mpi v;
371 mbedtls_mpi h; /* later recycled to hold r */
372 size_t len;
373
Jens Wiklander32b31802023-10-06 16:59:46 +0200374 if (end < *p) {
375 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
376 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200377
Jens Wiklander32b31802023-10-06 16:59:46 +0200378 mbedtls_ecp_point_init(&V);
379 mbedtls_mpi_init(&v);
380 mbedtls_mpi_init(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200381
382 /* Compute signature */
Jens Wiklander32b31802023-10-06 16:59:46 +0200383 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
384 G, &v, &V, f_rng, p_rng));
385 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
386 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
387 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
388 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Jens Wiklander817466c2018-05-22 13:49:31 +0200389
390 /* Write it out */
Jens Wiklander32b31802023-10-06 16:59:46 +0200391 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
392 pf, &len, *p, end - *p));
Jens Wiklander817466c2018-05-22 13:49:31 +0200393 *p += len;
394
Jens Wiklander32b31802023-10-06 16:59:46 +0200395 len = mbedtls_mpi_size(&h); /* actually r */
396 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200397 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
398 goto cleanup;
399 }
400
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 *(*p)++ = MBEDTLS_BYTE_0(len);
402 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Jens Wiklander817466c2018-05-22 13:49:31 +0200403 *p += len;
404
405cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200406 mbedtls_ecp_point_free(&V);
407 mbedtls_mpi_free(&v);
408 mbedtls_mpi_free(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200409
Jens Wiklander32b31802023-10-06 16:59:46 +0200410 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200411}
412
413/*
414 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
415 * Output: verified public key X
416 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200417static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
418 const mbedtls_ecp_group *grp,
419 const int pf,
420 const mbedtls_ecp_point *G,
421 mbedtls_ecp_point *X,
422 const char *id,
423 const unsigned char **p,
424 const unsigned char *end)
Jens Wiklander817466c2018-05-22 13:49:31 +0200425{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200426 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200427
Jens Wiklander32b31802023-10-06 16:59:46 +0200428 if (end < *p) {
429 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
430 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200431
432 /*
433 * struct {
434 * ECPoint X;
435 * ECSchnorrZKP zkp;
436 * } ECJPAKEKeyKP;
437 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200438 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
439 if (mbedtls_ecp_is_zero(X)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200440 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
441 goto cleanup;
442 }
443
Jens Wiklander32b31802023-10-06 16:59:46 +0200444 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Jens Wiklander817466c2018-05-22 13:49:31 +0200445
446cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200447 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200448}
449
450/*
451 * Generate an ECJPAKEKeyKP
452 * Output: the serialized structure, plus private/public key pair
453 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200454static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
455 const mbedtls_ecp_group *grp,
456 const int pf,
457 const mbedtls_ecp_point *G,
458 mbedtls_mpi *x,
459 mbedtls_ecp_point *X,
460 const char *id,
461 unsigned char **p,
462 const unsigned char *end,
463 int (*f_rng)(void *, unsigned char *, size_t),
464 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200465{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200466 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200467 size_t len;
468
Jens Wiklander32b31802023-10-06 16:59:46 +0200469 if (end < *p) {
470 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
471 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200472
473 /* Generate key (7.4.2.3.1) and write it out */
Jens Wiklander32b31802023-10-06 16:59:46 +0200474 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
475 f_rng, p_rng));
476 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
477 pf, &len, *p, end - *p));
Jens Wiklander817466c2018-05-22 13:49:31 +0200478 *p += len;
479
480 /* Generate and write proof */
Jens Wiklander32b31802023-10-06 16:59:46 +0200481 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
482 p, end, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200483
484cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200485 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200486}
487
488/*
489 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Jerome Forissier039e02d2022-08-09 17:10:15 +0200490 * Outputs: verified peer public keys Xa, Xb
Jens Wiklander817466c2018-05-22 13:49:31 +0200491 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200492static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
493 const mbedtls_ecp_group *grp,
494 const int pf,
495 const mbedtls_ecp_point *G,
496 mbedtls_ecp_point *Xa,
497 mbedtls_ecp_point *Xb,
498 const char *id,
499 const unsigned char *buf,
500 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200501{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200502 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200503 const unsigned char *p = buf;
504 const unsigned char *end = buf + len;
505
506 /*
507 * struct {
508 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
509 * } ECJPAKEKeyKPPairList;
510 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200511 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
512 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Jens Wiklander817466c2018-05-22 13:49:31 +0200513
Jens Wiklander32b31802023-10-06 16:59:46 +0200514 if (p != end) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200515 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Jens Wiklander32b31802023-10-06 16:59:46 +0200516 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200517
518cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200519 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200520}
521
522/*
523 * Generate a ECJPAKEKeyKPPairList
524 * Outputs: the serialized structure, plus two private/public key pairs
525 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200526static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
527 const mbedtls_ecp_group *grp,
528 const int pf,
529 const mbedtls_ecp_point *G,
530 mbedtls_mpi *xm1,
531 mbedtls_ecp_point *Xa,
532 mbedtls_mpi *xm2,
533 mbedtls_ecp_point *Xb,
534 const char *id,
535 unsigned char *buf,
536 size_t len,
537 size_t *olen,
538 int (*f_rng)(void *, unsigned char *, size_t),
539 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200540{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200542 unsigned char *p = buf;
543 const unsigned char *end = buf + len;
544
Jens Wiklander32b31802023-10-06 16:59:46 +0200545 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
546 &p, end, f_rng, p_rng));
547 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
548 &p, end, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200549
550 *olen = p - buf;
551
552cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200553 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200554}
555
556/*
557 * Read and process the first round message
558 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200559int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
560 const unsigned char *buf,
561 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200562{
Jens Wiklander32b31802023-10-06 16:59:46 +0200563 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
564 &ctx->grp.G,
565 &ctx->Xp1, &ctx->Xp2, ID_PEER,
566 buf, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200567}
568
569/*
570 * Generate and write the first round message
571 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200572int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
573 unsigned char *buf, size_t len, size_t *olen,
574 int (*f_rng)(void *, unsigned char *, size_t),
575 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200576{
Jens Wiklander32b31802023-10-06 16:59:46 +0200577 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
578 &ctx->grp.G,
579 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
580 ID_MINE, buf, len, olen, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +0200581}
582
583/*
584 * Compute the sum of three points R = A + B + C
585 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200586static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
587 const mbedtls_ecp_point *A,
588 const mbedtls_ecp_point *B,
589 const mbedtls_ecp_point *C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200590{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200591 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200592 mbedtls_mpi one;
593
Jens Wiklander32b31802023-10-06 16:59:46 +0200594 mbedtls_mpi_init(&one);
Jens Wiklander817466c2018-05-22 13:49:31 +0200595
Jens Wiklander32b31802023-10-06 16:59:46 +0200596 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
597 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
598 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Jens Wiklander817466c2018-05-22 13:49:31 +0200599
600cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200601 mbedtls_mpi_free(&one);
Jens Wiklander817466c2018-05-22 13:49:31 +0200602
Jens Wiklander32b31802023-10-06 16:59:46 +0200603 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200604}
605
606/*
607 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
608 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200609int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
610 const unsigned char *buf,
611 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200612{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200613 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200614 const unsigned char *p = buf;
615 const unsigned char *end = buf + len;
616 mbedtls_ecp_group grp;
617 mbedtls_ecp_point G; /* C: GB, S: GA */
618
Jens Wiklander32b31802023-10-06 16:59:46 +0200619 mbedtls_ecp_group_init(&grp);
620 mbedtls_ecp_point_init(&G);
Jens Wiklander817466c2018-05-22 13:49:31 +0200621
622 /*
623 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
624 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
625 * Unified: G = Xm1 + Xm2 + Xp1
626 * We need that before parsing in order to check Xp as we read it
627 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200628 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
629 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Jens Wiklander817466c2018-05-22 13:49:31 +0200630
631 /*
632 * struct {
633 * ECParameters curve_params; // only client reading server msg
634 * ECJPAKEKeyKP ecjpake_key_kp;
635 * } Client/ServerECJPAKEParams;
636 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200637 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
638 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
639 if (grp.id != ctx->grp.id) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200640 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
641 goto cleanup;
642 }
643 }
644
Jens Wiklander32b31802023-10-06 16:59:46 +0200645 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
646 ctx->point_format,
647 &G, &ctx->Xp, ID_PEER, &p, end));
Jens Wiklander817466c2018-05-22 13:49:31 +0200648
Jens Wiklander32b31802023-10-06 16:59:46 +0200649 if (p != end) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200650 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 goto cleanup;
652 }
653
654cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200655 mbedtls_ecp_group_free(&grp);
656 mbedtls_ecp_point_free(&G);
Jens Wiklander817466c2018-05-22 13:49:31 +0200657
Jens Wiklander32b31802023-10-06 16:59:46 +0200658 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200659}
660
661/*
662 * Compute R = +/- X * S mod N, taking care not to leak S
663 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200664static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
665 const mbedtls_mpi *X,
666 const mbedtls_mpi *S,
667 const mbedtls_mpi *N,
668 int (*f_rng)(void *, unsigned char *, size_t),
669 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200670{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200671 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200672 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
673
Jens Wiklander32b31802023-10-06 16:59:46 +0200674 mbedtls_mpi_init(&b);
Jens Wiklander817466c2018-05-22 13:49:31 +0200675
676 /* b = s + rnd-128-bit * N */
Jens Wiklander32b31802023-10-06 16:59:46 +0200677 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
678 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
679 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Jens Wiklander817466c2018-05-22 13:49:31 +0200680
681 /* R = sign * X * b mod N */
Jens Wiklander32b31802023-10-06 16:59:46 +0200682 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Jens Wiklander817466c2018-05-22 13:49:31 +0200683 R->s *= sign;
Jens Wiklander32b31802023-10-06 16:59:46 +0200684 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200685
686cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200687 mbedtls_mpi_free(&b);
Jens Wiklander817466c2018-05-22 13:49:31 +0200688
Jens Wiklander32b31802023-10-06 16:59:46 +0200689 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200690}
691
692/*
693 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
694 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200695int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
696 unsigned char *buf, size_t len, size_t *olen,
697 int (*f_rng)(void *, unsigned char *, size_t),
698 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200699{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200700 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200701 mbedtls_ecp_point G; /* C: GA, S: GB */
702 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
703 mbedtls_mpi xm; /* C: xc, S: xs */
704 unsigned char *p = buf;
705 const unsigned char *end = buf + len;
706 size_t ec_len;
707
Jens Wiklander32b31802023-10-06 16:59:46 +0200708 mbedtls_ecp_point_init(&G);
709 mbedtls_ecp_point_init(&Xm);
710 mbedtls_mpi_init(&xm);
Jens Wiklander817466c2018-05-22 13:49:31 +0200711
712 /*
713 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
714 *
715 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
716 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
717 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
718 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200719 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
720 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
721 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
722 &ctx->grp.N, f_rng, p_rng));
723 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200724
725 /*
726 * Now write things out
727 *
728 * struct {
729 * ECParameters curve_params; // only server writing its message
730 * ECJPAKEKeyKP ecjpake_key_kp;
731 * } Client/ServerECJPAKEParams;
732 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200733 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
734 if (end < p) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200735 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
736 goto cleanup;
737 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200738 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
739 p, end - p));
Jens Wiklander817466c2018-05-22 13:49:31 +0200740 p += ec_len;
741 }
742
Jens Wiklander32b31802023-10-06 16:59:46 +0200743 if (end < p) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200744 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
745 goto cleanup;
746 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200747 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
748 ctx->point_format, &ec_len, p, end - p));
Jens Wiklander817466c2018-05-22 13:49:31 +0200749 p += ec_len;
750
Jens Wiklander32b31802023-10-06 16:59:46 +0200751 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
752 ctx->point_format,
753 &G, &xm, &Xm, ID_MINE,
754 &p, end, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200755
756 *olen = p - buf;
757
758cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200759 mbedtls_ecp_point_free(&G);
760 mbedtls_ecp_point_free(&Xm);
761 mbedtls_mpi_free(&xm);
Jens Wiklander817466c2018-05-22 13:49:31 +0200762
Jens Wiklander32b31802023-10-06 16:59:46 +0200763 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200764}
765
766/*
767 * Derive PMS (7.4.2.7 / 7.4.2.8)
768 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200769static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
770 mbedtls_ecp_point *K,
771 int (*f_rng)(void *, unsigned char *, size_t),
772 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200773{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200774 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200775 mbedtls_mpi m_xm2_s, one;
Jens Wiklander817466c2018-05-22 13:49:31 +0200776
Jens Wiklander32b31802023-10-06 16:59:46 +0200777 mbedtls_mpi_init(&m_xm2_s);
778 mbedtls_mpi_init(&one);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100779
Jens Wiklander32b31802023-10-06 16:59:46 +0200780 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +0200781
782 /*
783 * Client: K = ( Xs - X4 * x2 * s ) * x2
784 * Server: K = ( Xc - X2 * x4 * s ) * x4
785 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
786 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200787 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
788 &ctx->grp.N, f_rng, p_rng));
789 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
790 &one, &ctx->Xp,
791 &m_xm2_s, &ctx->Xp2));
792 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
793 f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200794
795cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200796 mbedtls_mpi_free(&m_xm2_s);
797 mbedtls_mpi_free(&one);
Jens Wiklander817466c2018-05-22 13:49:31 +0200798
Jens Wiklander32b31802023-10-06 16:59:46 +0200799 return ret;
800}
801
802int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
803 unsigned char *buf, size_t len, size_t *olen,
804 int (*f_rng)(void *, unsigned char *, size_t),
805 void *p_rng)
806{
807 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
808 mbedtls_ecp_point K;
809 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
810 size_t x_bytes;
811
812 *olen = mbedtls_hash_info_get_size(ctx->md_type);
813 if (len < *olen) {
814 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
815 }
816
817 mbedtls_ecp_point_init(&K);
818
819 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
820 if (ret) {
821 goto cleanup;
822 }
823
824 /* PMS = SHA-256( K.X ) */
825 x_bytes = (ctx->grp.pbits + 7) / 8;
826 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
827 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
828 kx, x_bytes, buf));
829
830cleanup:
831 mbedtls_ecp_point_free(&K);
832
833 return ret;
834}
835
836int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
837 unsigned char *buf, size_t len, size_t *olen,
838 int (*f_rng)(void *, unsigned char *, size_t),
839 void *p_rng)
840{
841 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
842 mbedtls_ecp_point K;
843
844 mbedtls_ecp_point_init(&K);
845
846 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
847 if (ret) {
848 goto cleanup;
849 }
850
851 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
852 olen, buf, len);
853 if (ret != 0) {
854 goto cleanup;
855 }
856
857cleanup:
858 mbedtls_ecp_point_free(&K);
859
860 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200861}
862
863#undef ID_MINE
864#undef ID_PEER
865
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100866#endif /* ! MBEDTLS_ECJPAKE_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200867
868#if defined(MBEDTLS_SELF_TEST)
869
Jens Wiklander817466c2018-05-22 13:49:31 +0200870#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +0200871
872#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
873 !defined(MBEDTLS_SHA256_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200874int mbedtls_ecjpake_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200875{
876 (void) verbose;
Jens Wiklander32b31802023-10-06 16:59:46 +0200877 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200878}
879#else
880
881static const unsigned char ecjpake_test_password[] = {
882 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
883 0x65, 0x73, 0x74
884};
885
Jerome Forissier79013242021-07-28 10:24:04 +0200886#if !defined(MBEDTLS_ECJPAKE_ALT)
887
Jens Wiklander817466c2018-05-22 13:49:31 +0200888static const unsigned char ecjpake_test_x1[] = {
889 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
890 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
891 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
892};
893
894static const unsigned char ecjpake_test_x2[] = {
895 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
896 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
897 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
898};
899
900static const unsigned char ecjpake_test_x3[] = {
901 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
902 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
903 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
904};
905
906static const unsigned char ecjpake_test_x4[] = {
907 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
908 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
909 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
910};
911
912static const unsigned char ecjpake_test_cli_one[] = {
913 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
914 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
915 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
916 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
917 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
918 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
919 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
920 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
921 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
922 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
923 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
924 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
925 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
926 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
927 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
928 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
929 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
930 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
931 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
932 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
933 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
934 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
935 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
936 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
937 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
938 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
939 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
940 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
941};
942
943static const unsigned char ecjpake_test_srv_one[] = {
944 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
945 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
946 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
947 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
948 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
949 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
950 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
951 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
952 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
953 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
954 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
955 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
956 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
957 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
958 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
959 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
960 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
961 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
962 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
963 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
964 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
965 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
966 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
967 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
968 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
969 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
970 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
971 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
972};
973
974static const unsigned char ecjpake_test_srv_two[] = {
975 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
976 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
977 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
978 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
979 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
980 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
981 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
982 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
983 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
984 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
985 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
986 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
987 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
988 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
989};
990
991static const unsigned char ecjpake_test_cli_two[] = {
992 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
993 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
994 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
995 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
996 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
997 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
998 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
999 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
1000 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
1001 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
1002 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
1003 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
1004 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
1005 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
1006};
1007
Jens Wiklander32b31802023-10-06 16:59:46 +02001008static const unsigned char ecjpake_test_shared_key[] = {
1009 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
1010 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
1011 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
1012 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
1013 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
1014 0x17, 0xc3, 0xde, 0x27, 0xb4,
1015};
1016
Jens Wiklander817466c2018-05-22 13:49:31 +02001017static const unsigned char ecjpake_test_pms[] = {
1018 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
1019 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
1020 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
1021};
1022
Jens Wiklander32b31802023-10-06 16:59:46 +02001023/*
1024 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
1025 *
1026 * This is the linear congruential generator from numerical recipes,
1027 * except we only use the low byte as the output. See
1028 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
1029 */
1030static int self_test_rng(void *ctx, unsigned char *out, size_t len)
1031{
1032 static uint32_t state = 42;
1033
1034 (void) ctx;
1035
1036 for (size_t i = 0; i < len; i++) {
1037 state = state * 1664525u + 1013904223u;
1038 out[i] = (unsigned char) state;
1039 }
1040
1041 return 0;
1042}
1043
Jerome Forissier5b25c762020-04-07 11:18:49 +02001044/* Load my private keys and generate the corresponding public keys */
Jens Wiklander32b31802023-10-06 16:59:46 +02001045static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1046 const unsigned char *xm1, size_t len1,
1047 const unsigned char *xm2, size_t len2)
Jens Wiklander817466c2018-05-22 13:49:31 +02001048{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001049 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001050
Jens Wiklander32b31802023-10-06 16:59:46 +02001051 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1052 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1053 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1054 &ctx->grp.G, self_test_rng, NULL));
1055 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1056 &ctx->grp.G, self_test_rng, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02001057
1058cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001059 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001060}
1061
Jerome Forissier79013242021-07-28 10:24:04 +02001062#endif /* ! MBEDTLS_ECJPAKE_ALT */
1063
Jens Wiklander817466c2018-05-22 13:49:31 +02001064/* For tests we don't need a secure RNG;
1065 * use the LGC from Numerical Recipes for simplicity */
Jens Wiklander32b31802023-10-06 16:59:46 +02001066static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +02001067{
1068 static uint32_t x = 42;
1069 (void) p;
1070
Jens Wiklander32b31802023-10-06 16:59:46 +02001071 while (len > 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001072 size_t use_len = len > 4 ? 4 : len;
1073 x = 1664525 * x + 1013904223;
Jens Wiklander32b31802023-10-06 16:59:46 +02001074 memcpy(out, &x, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +02001075 out += use_len;
1076 len -= use_len;
1077 }
1078
Jens Wiklander32b31802023-10-06 16:59:46 +02001079 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001080}
1081
Jens Wiklander32b31802023-10-06 16:59:46 +02001082#define TEST_ASSERT(x) \
Jens Wiklander817466c2018-05-22 13:49:31 +02001083 do { \
Jens Wiklander32b31802023-10-06 16:59:46 +02001084 if (x) \
1085 ret = 0; \
Jens Wiklander817466c2018-05-22 13:49:31 +02001086 else \
1087 { \
1088 ret = 1; \
1089 goto cleanup; \
1090 } \
Jens Wiklander32b31802023-10-06 16:59:46 +02001091 } while (0)
Jens Wiklander817466c2018-05-22 13:49:31 +02001092
1093/*
1094 * Checkup routine
1095 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001096int mbedtls_ecjpake_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02001097{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001098 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001099 mbedtls_ecjpake_context cli;
1100 mbedtls_ecjpake_context srv;
1101 unsigned char buf[512], pms[32];
1102 size_t len, pmslen;
1103
Jens Wiklander32b31802023-10-06 16:59:46 +02001104 mbedtls_ecjpake_init(&cli);
1105 mbedtls_ecjpake_init(&srv);
Jens Wiklander817466c2018-05-22 13:49:31 +02001106
Jens Wiklander32b31802023-10-06 16:59:46 +02001107 if (verbose != 0) {
1108 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1109 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001110
Jens Wiklander32b31802023-10-06 16:59:46 +02001111 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1112 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1113 ecjpake_test_password,
1114 sizeof(ecjpake_test_password)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001115
Jens Wiklander32b31802023-10-06 16:59:46 +02001116 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1117 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1118 ecjpake_test_password,
1119 sizeof(ecjpake_test_password)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001120
Jens Wiklander32b31802023-10-06 16:59:46 +02001121 if (verbose != 0) {
1122 mbedtls_printf("passed\n");
1123 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001124
Jens Wiklander32b31802023-10-06 16:59:46 +02001125 if (verbose != 0) {
1126 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1127 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001128
Jens Wiklander32b31802023-10-06 16:59:46 +02001129 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1130 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001131
Jens Wiklander32b31802023-10-06 16:59:46 +02001132 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001133
Jens Wiklander32b31802023-10-06 16:59:46 +02001134 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1135 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001136
Jens Wiklander32b31802023-10-06 16:59:46 +02001137 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001138
Jens Wiklander32b31802023-10-06 16:59:46 +02001139 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1140 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001141
Jens Wiklander32b31802023-10-06 16:59:46 +02001142 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001143
Jens Wiklander32b31802023-10-06 16:59:46 +02001144 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1145 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001146
Jens Wiklander32b31802023-10-06 16:59:46 +02001147 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1148 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001149
Jens Wiklander32b31802023-10-06 16:59:46 +02001150 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001151
Jens Wiklander32b31802023-10-06 16:59:46 +02001152 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1153 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001154
Jens Wiklander32b31802023-10-06 16:59:46 +02001155 TEST_ASSERT(len == pmslen);
1156 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001157
Jens Wiklander32b31802023-10-06 16:59:46 +02001158 if (verbose != 0) {
1159 mbedtls_printf("passed\n");
1160 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001161
Jerome Forissier79013242021-07-28 10:24:04 +02001162#if !defined(MBEDTLS_ECJPAKE_ALT)
1163 /* 'reference handshake' tests can only be run against implementations
1164 * for which we have 100% control over how the random ephemeral keys
1165 * are generated. This is only the case for the internal mbed TLS
1166 * implementation, so these tests are skipped in case the internal
1167 * implementation is swapped out for an alternative one. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001168 if (verbose != 0) {
1169 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1170 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001171
1172 /* Simulate generation of round one */
Jens Wiklander32b31802023-10-06 16:59:46 +02001173 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1174 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1175 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001176
Jens Wiklander32b31802023-10-06 16:59:46 +02001177 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1178 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1179 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001180
1181 /* Read round one */
Jens Wiklander32b31802023-10-06 16:59:46 +02001182 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1183 ecjpake_test_cli_one,
1184 sizeof(ecjpake_test_cli_one)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001185
Jens Wiklander32b31802023-10-06 16:59:46 +02001186 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1187 ecjpake_test_srv_one,
1188 sizeof(ecjpake_test_srv_one)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001189
1190 /* Skip generation of round two, read round two */
Jens Wiklander32b31802023-10-06 16:59:46 +02001191 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1192 ecjpake_test_srv_two,
1193 sizeof(ecjpake_test_srv_two)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001194
Jens Wiklander32b31802023-10-06 16:59:46 +02001195 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1196 ecjpake_test_cli_two,
1197 sizeof(ecjpake_test_cli_two)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001198
1199 /* Server derives PMS */
Jens Wiklander32b31802023-10-06 16:59:46 +02001200 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1201 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001202
Jens Wiklander32b31802023-10-06 16:59:46 +02001203 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1204 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001205
Jens Wiklander32b31802023-10-06 16:59:46 +02001206 /* Server derives K as unsigned binary data */
1207 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1208 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1209
1210 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1211 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1212
1213 memset(buf, 0, len); /* Avoid interferences with next step */
Jens Wiklander817466c2018-05-22 13:49:31 +02001214
1215 /* Client derives PMS */
Jens Wiklander32b31802023-10-06 16:59:46 +02001216 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1217 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001218
Jens Wiklander32b31802023-10-06 16:59:46 +02001219 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1220 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001221
Jens Wiklander32b31802023-10-06 16:59:46 +02001222 /* Client derives K as unsigned binary data */
1223 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1224 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1225
1226 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1227 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1228
1229 if (verbose != 0) {
1230 mbedtls_printf("passed\n");
1231 }
Jerome Forissier79013242021-07-28 10:24:04 +02001232#endif /* ! MBEDTLS_ECJPAKE_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +02001233
1234cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001235 mbedtls_ecjpake_free(&cli);
1236 mbedtls_ecjpake_free(&srv);
Jens Wiklander817466c2018-05-22 13:49:31 +02001237
Jens Wiklander32b31802023-10-06 16:59:46 +02001238 if (ret != 0) {
1239 if (verbose != 0) {
1240 mbedtls_printf("failed\n");
1241 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001242
1243 ret = 1;
1244 }
1245
Jens Wiklander32b31802023-10-06 16:59:46 +02001246 if (verbose != 0) {
1247 mbedtls_printf("\n");
1248 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001249
Jens Wiklander32b31802023-10-06 16:59:46 +02001250 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001251}
1252
1253#undef TEST_ASSERT
1254
1255#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1256
1257#endif /* MBEDTLS_SELF_TEST */
1258
1259#endif /* MBEDTLS_ECJPAKE_C */