blob: cdf5d7ea46e5dd2a3ac4ffd1ac677c49b852ec02 [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
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * References in the code are to the Thread v1.0 Specification,
10 * available to members of the Thread Group http://threadgroup.org/
11 */
12
Jerome Forissier79013242021-07-28 10:24:04 +020013#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020014
15#if defined(MBEDTLS_ECJPAKE_C)
16
17#include "mbedtls/ecjpake.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010018#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020019#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020020
21#include <string.h>
22
Jens Wiklander3d3b0592019-03-20 15:30:29 +010023#if !defined(MBEDTLS_ECJPAKE_ALT)
24
Jens Wiklander817466c2018-05-22 13:49:31 +020025/*
26 * Convert a mbedtls_ecjpake_role to identifier string
27 */
28static const char * const ecjpake_id[] = {
29 "client",
30 "server"
31};
32
Jens Wiklander32b31802023-10-06 16:59:46 +020033#define ID_MINE (ecjpake_id[ctx->role])
34#define ID_PEER (ecjpake_id[1 - ctx->role])
35
36/**
37 * Helper to Compute a hash from md_type
38 */
39static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
40 const unsigned char *input, size_t ilen,
41 unsigned char *output)
42{
Jens Wiklander32b31802023-10-06 16:59:46 +020043 return mbedtls_md(mbedtls_md_info_from_type(md_type),
44 input, ilen, output);
Jens Wiklander32b31802023-10-06 16:59:46 +020045}
Jens Wiklander817466c2018-05-22 13:49:31 +020046
47/*
48 * Initialize context
49 */
Jens Wiklander32b31802023-10-06 16:59:46 +020050void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020051{
Jens Wiklander32b31802023-10-06 16:59:46 +020052 ctx->md_type = MBEDTLS_MD_NONE;
53 mbedtls_ecp_group_init(&ctx->grp);
Jens Wiklander817466c2018-05-22 13:49:31 +020054 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
55
Jens Wiklander32b31802023-10-06 16:59:46 +020056 mbedtls_ecp_point_init(&ctx->Xm1);
57 mbedtls_ecp_point_init(&ctx->Xm2);
58 mbedtls_ecp_point_init(&ctx->Xp1);
59 mbedtls_ecp_point_init(&ctx->Xp2);
60 mbedtls_ecp_point_init(&ctx->Xp);
Jens Wiklander817466c2018-05-22 13:49:31 +020061
Jens Wiklander32b31802023-10-06 16:59:46 +020062 mbedtls_mpi_init(&ctx->xm1);
63 mbedtls_mpi_init(&ctx->xm2);
64 mbedtls_mpi_init(&ctx->s);
Jens Wiklander817466c2018-05-22 13:49:31 +020065}
66
67/*
68 * Free context
69 */
Jens Wiklander32b31802023-10-06 16:59:46 +020070void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020071{
Jens Wiklander32b31802023-10-06 16:59:46 +020072 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +020073 return;
Jens Wiklander32b31802023-10-06 16:59:46 +020074 }
Jens Wiklander817466c2018-05-22 13:49:31 +020075
Jens Wiklander32b31802023-10-06 16:59:46 +020076 ctx->md_type = MBEDTLS_MD_NONE;
77 mbedtls_ecp_group_free(&ctx->grp);
Jens Wiklander817466c2018-05-22 13:49:31 +020078
Jens Wiklander32b31802023-10-06 16:59:46 +020079 mbedtls_ecp_point_free(&ctx->Xm1);
80 mbedtls_ecp_point_free(&ctx->Xm2);
81 mbedtls_ecp_point_free(&ctx->Xp1);
82 mbedtls_ecp_point_free(&ctx->Xp2);
83 mbedtls_ecp_point_free(&ctx->Xp);
Jens Wiklander817466c2018-05-22 13:49:31 +020084
Jens Wiklander32b31802023-10-06 16:59:46 +020085 mbedtls_mpi_free(&ctx->xm1);
86 mbedtls_mpi_free(&ctx->xm2);
87 mbedtls_mpi_free(&ctx->s);
Jens Wiklander817466c2018-05-22 13:49:31 +020088}
89
90/*
91 * Setup context
92 */
Jens Wiklander32b31802023-10-06 16:59:46 +020093int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
94 mbedtls_ecjpake_role role,
95 mbedtls_md_type_t hash,
96 mbedtls_ecp_group_id curve,
97 const unsigned char *secret,
98 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +020099{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200101
Jens Wiklander32b31802023-10-06 16:59:46 +0200102 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
103 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
104 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100105
Jens Wiklander817466c2018-05-22 13:49:31 +0200106 ctx->role = role;
107
Jens Wiklander32b31802023-10-06 16:59:46 +0200108 if ((mbedtls_md_info_from_type(hash)) == NULL) {
109 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
110 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200111
Jens Wiklander32b31802023-10-06 16:59:46 +0200112 ctx->md_type = hash;
Jens Wiklander817466c2018-05-22 13:49:31 +0200113
Jens Wiklander32b31802023-10-06 16:59:46 +0200114 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
115
116 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Jens Wiklander817466c2018-05-22 13:49:31 +0200117
118cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200119 if (ret != 0) {
120 mbedtls_ecjpake_free(ctx);
121 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200122
Jens Wiklander32b31802023-10-06 16:59:46 +0200123 return ret;
124}
125
126int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
127 int point_format)
128{
129 switch (point_format) {
130 case MBEDTLS_ECP_PF_UNCOMPRESSED:
131 case MBEDTLS_ECP_PF_COMPRESSED:
132 ctx->point_format = point_format;
133 return 0;
134 default:
135 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
136 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200137}
138
139/*
140 * Check if context is ready for use
141 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200142int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200143{
Jens Wiklander32b31802023-10-06 16:59:46 +0200144 if (ctx->md_type == MBEDTLS_MD_NONE ||
Jens Wiklander817466c2018-05-22 13:49:31 +0200145 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Jens Wiklander32b31802023-10-06 16:59:46 +0200146 ctx->s.p == NULL) {
147 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Jens Wiklander817466c2018-05-22 13:49:31 +0200148 }
149
Jens Wiklander32b31802023-10-06 16:59:46 +0200150 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200151}
152
153/*
154 * Write a point plus its length to a buffer
155 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200156static int ecjpake_write_len_point(unsigned char **p,
157 const unsigned char *end,
158 const mbedtls_ecp_group *grp,
159 const int pf,
160 const mbedtls_ecp_point *P)
Jens Wiklander817466c2018-05-22 13:49:31 +0200161{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200162 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200163 size_t len;
164
165 /* Need at least 4 for length plus 1 for point */
Jens Wiklander32b31802023-10-06 16:59:46 +0200166 if (end < *p || end - *p < 5) {
167 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
168 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200169
Jens Wiklander32b31802023-10-06 16:59:46 +0200170 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200171 &len, *p + 4, (size_t) (end - (*p + 4)));
Jens Wiklander32b31802023-10-06 16:59:46 +0200172 if (ret != 0) {
173 return ret;
174 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200175
Jens Wiklander32b31802023-10-06 16:59:46 +0200176 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200177
178 *p += 4 + len;
179
Jens Wiklander32b31802023-10-06 16:59:46 +0200180 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200181}
182
183/*
184 * Size of the temporary buffer for ecjpake_hash:
185 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
186 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200187#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Jens Wiklander817466c2018-05-22 13:49:31 +0200188
189/*
190 * Compute hash for ZKP (7.4.2.2.2.1)
191 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200192static int ecjpake_hash(const mbedtls_md_type_t md_type,
193 const mbedtls_ecp_group *grp,
194 const int pf,
195 const mbedtls_ecp_point *G,
196 const mbedtls_ecp_point *V,
197 const mbedtls_ecp_point *X,
198 const char *id,
199 mbedtls_mpi *h)
Jens Wiklander817466c2018-05-22 13:49:31 +0200200{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200201 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200202 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203 unsigned char *p = buf;
Jens Wiklander32b31802023-10-06 16:59:46 +0200204 const unsigned char *end = buf + sizeof(buf);
205 const size_t id_len = strlen(id);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200206 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200207
208 /* Write things to temporary buffer */
Jens Wiklander32b31802023-10-06 16:59:46 +0200209 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
210 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
211 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200212
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 if (end - p < 4) {
214 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
215 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200216
Jens Wiklander32b31802023-10-06 16:59:46 +0200217 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Jerome Forissier039e02d2022-08-09 17:10:15 +0200218 p += 4;
Jens Wiklander817466c2018-05-22 13:49:31 +0200219
Jens Wiklander32b31802023-10-06 16:59:46 +0200220 if (end < p || (size_t) (end - p) < id_len) {
221 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
222 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200223
Jens Wiklander32b31802023-10-06 16:59:46 +0200224 memcpy(p, id, id_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200225 p += id_len;
226
227 /* Compute hash */
Jens Wiklander32b31802023-10-06 16:59:46 +0200228 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200229 buf, (size_t) (p - buf), hash));
Jens Wiklander817466c2018-05-22 13:49:31 +0200230
231 /* Turn it into an integer mod n */
Jens Wiklander32b31802023-10-06 16:59:46 +0200232 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200233 mbedtls_md_get_size_from_type(md_type)));
Jens Wiklander32b31802023-10-06 16:59:46 +0200234 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200235
236cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200237 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200238}
239
240/*
241 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200243static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
244 const mbedtls_ecp_group *grp,
245 const int pf,
246 const mbedtls_ecp_point *G,
247 const mbedtls_ecp_point *X,
248 const char *id,
249 const unsigned char **p,
250 const unsigned char *end)
Jens Wiklander817466c2018-05-22 13:49:31 +0200251{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200252 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200253 mbedtls_ecp_point V, VV;
254 mbedtls_mpi r, h;
255 size_t r_len;
256
Jens Wiklander32b31802023-10-06 16:59:46 +0200257 mbedtls_ecp_point_init(&V);
258 mbedtls_ecp_point_init(&VV);
259 mbedtls_mpi_init(&r);
260 mbedtls_mpi_init(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200261
262 /*
263 * struct {
264 * ECPoint V;
265 * opaque r<1..2^8-1>;
266 * } ECSchnorrZKP;
267 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200268 if (end < *p) {
269 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
270 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200271
Tom Van Eyckc1633172024-04-09 18:44:13 +0200272 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200273
Jens Wiklander32b31802023-10-06 16:59:46 +0200274 if (end < *p || (size_t) (end - *p) < 1) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200275 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276 goto cleanup;
277 }
278
279 r_len = *(*p)++;
280
Jens Wiklander32b31802023-10-06 16:59:46 +0200281 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200282 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283 goto cleanup;
284 }
285
Jens Wiklander32b31802023-10-06 16:59:46 +0200286 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Jens Wiklander817466c2018-05-22 13:49:31 +0200287 *p += r_len;
288
289 /*
290 * Verification
291 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200292 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
293 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
294 &VV, &h, X, &r, G));
Jens Wiklander817466c2018-05-22 13:49:31 +0200295
Jens Wiklander32b31802023-10-06 16:59:46 +0200296 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200297 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298 goto cleanup;
299 }
300
301cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200302 mbedtls_ecp_point_free(&V);
303 mbedtls_ecp_point_free(&VV);
304 mbedtls_mpi_free(&r);
305 mbedtls_mpi_free(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200306
Jens Wiklander32b31802023-10-06 16:59:46 +0200307 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200308}
309
310/*
311 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
312 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200313static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
314 const mbedtls_ecp_group *grp,
315 const int pf,
316 const mbedtls_ecp_point *G,
317 const mbedtls_mpi *x,
318 const mbedtls_ecp_point *X,
319 const char *id,
320 unsigned char **p,
321 const unsigned char *end,
322 int (*f_rng)(void *, unsigned char *, size_t),
323 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200324{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200325 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200326 mbedtls_ecp_point V;
327 mbedtls_mpi v;
328 mbedtls_mpi h; /* later recycled to hold r */
329 size_t len;
330
Jens Wiklander32b31802023-10-06 16:59:46 +0200331 if (end < *p) {
332 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
333 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200334
Jens Wiklander32b31802023-10-06 16:59:46 +0200335 mbedtls_ecp_point_init(&V);
336 mbedtls_mpi_init(&v);
337 mbedtls_mpi_init(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200338
339 /* Compute signature */
Jens Wiklander32b31802023-10-06 16:59:46 +0200340 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
341 G, &v, &V, f_rng, p_rng));
342 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
343 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
344 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
345 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Jens Wiklander817466c2018-05-22 13:49:31 +0200346
347 /* Write it out */
Jens Wiklander32b31802023-10-06 16:59:46 +0200348 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200349 pf, &len, *p, (size_t) (end - *p)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200350 *p += len;
351
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 len = mbedtls_mpi_size(&h); /* actually r */
353 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200354 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355 goto cleanup;
356 }
357
Jens Wiklander32b31802023-10-06 16:59:46 +0200358 *(*p)++ = MBEDTLS_BYTE_0(len);
359 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Jens Wiklander817466c2018-05-22 13:49:31 +0200360 *p += len;
361
362cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 mbedtls_ecp_point_free(&V);
364 mbedtls_mpi_free(&v);
365 mbedtls_mpi_free(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200366
Jens Wiklander32b31802023-10-06 16:59:46 +0200367 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200368}
369
370/*
371 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
372 * Output: verified public key X
373 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200374static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
375 const mbedtls_ecp_group *grp,
376 const int pf,
377 const mbedtls_ecp_point *G,
378 mbedtls_ecp_point *X,
379 const char *id,
380 const unsigned char **p,
381 const unsigned char *end)
Jens Wiklander817466c2018-05-22 13:49:31 +0200382{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200383 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200384
Jens Wiklander32b31802023-10-06 16:59:46 +0200385 if (end < *p) {
386 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
387 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200388
389 /*
390 * struct {
391 * ECPoint X;
392 * ECSchnorrZKP zkp;
393 * } ECJPAKEKeyKP;
394 */
Tom Van Eyckc1633172024-04-09 18:44:13 +0200395 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
Jens Wiklander32b31802023-10-06 16:59:46 +0200396 if (mbedtls_ecp_is_zero(X)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200397 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398 goto cleanup;
399 }
400
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Jens Wiklander817466c2018-05-22 13:49:31 +0200402
403cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200404 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200405}
406
407/*
408 * Generate an ECJPAKEKeyKP
409 * Output: the serialized structure, plus private/public key pair
410 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200411static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
412 const mbedtls_ecp_group *grp,
413 const int pf,
414 const mbedtls_ecp_point *G,
415 mbedtls_mpi *x,
416 mbedtls_ecp_point *X,
417 const char *id,
418 unsigned char **p,
419 const unsigned char *end,
420 int (*f_rng)(void *, unsigned char *, size_t),
421 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200422{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200424 size_t len;
425
Jens Wiklander32b31802023-10-06 16:59:46 +0200426 if (end < *p) {
427 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
428 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200429
430 /* Generate key (7.4.2.3.1) and write it out */
Jens Wiklander32b31802023-10-06 16:59:46 +0200431 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
432 f_rng, p_rng));
433 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200434 pf, &len, *p, (size_t) (end - *p)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200435 *p += len;
436
437 /* Generate and write proof */
Jens Wiklander32b31802023-10-06 16:59:46 +0200438 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
439 p, end, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200440
441cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200442 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200443}
444
445/*
446 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Jerome Forissier039e02d2022-08-09 17:10:15 +0200447 * Outputs: verified peer public keys Xa, Xb
Jens Wiklander817466c2018-05-22 13:49:31 +0200448 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200449static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
450 const mbedtls_ecp_group *grp,
451 const int pf,
452 const mbedtls_ecp_point *G,
453 mbedtls_ecp_point *Xa,
454 mbedtls_ecp_point *Xb,
455 const char *id,
456 const unsigned char *buf,
457 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200458{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200459 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200460 const unsigned char *p = buf;
461 const unsigned char *end = buf + len;
462
463 /*
464 * struct {
465 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
466 * } ECJPAKEKeyKPPairList;
467 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200468 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
469 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Jens Wiklander817466c2018-05-22 13:49:31 +0200470
Jens Wiklander32b31802023-10-06 16:59:46 +0200471 if (p != end) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200472 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Jens Wiklander32b31802023-10-06 16:59:46 +0200473 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200474
475cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200476 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200477}
478
479/*
480 * Generate a ECJPAKEKeyKPPairList
481 * Outputs: the serialized structure, plus two private/public key pairs
482 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200483static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
484 const mbedtls_ecp_group *grp,
485 const int pf,
486 const mbedtls_ecp_point *G,
487 mbedtls_mpi *xm1,
488 mbedtls_ecp_point *Xa,
489 mbedtls_mpi *xm2,
490 mbedtls_ecp_point *Xb,
491 const char *id,
492 unsigned char *buf,
493 size_t len,
494 size_t *olen,
495 int (*f_rng)(void *, unsigned char *, size_t),
496 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200497{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200498 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200499 unsigned char *p = buf;
500 const unsigned char *end = buf + len;
501
Jens Wiklander32b31802023-10-06 16:59:46 +0200502 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
503 &p, end, f_rng, p_rng));
504 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
505 &p, end, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200506
Tom Van Eyckc1633172024-04-09 18:44:13 +0200507 *olen = (size_t) (p - buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200508
509cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200510 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200511}
512
513/*
514 * Read and process the first round message
515 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200516int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
517 const unsigned char *buf,
518 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200519{
Jens Wiklander32b31802023-10-06 16:59:46 +0200520 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
521 &ctx->grp.G,
522 &ctx->Xp1, &ctx->Xp2, ID_PEER,
523 buf, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200524}
525
526/*
527 * Generate and write the first round message
528 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200529int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
530 unsigned char *buf, size_t len, size_t *olen,
531 int (*f_rng)(void *, unsigned char *, size_t),
532 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200533{
Jens Wiklander32b31802023-10-06 16:59:46 +0200534 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
535 &ctx->grp.G,
536 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
537 ID_MINE, buf, len, olen, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +0200538}
539
540/*
541 * Compute the sum of three points R = A + B + C
542 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200543static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
544 const mbedtls_ecp_point *A,
545 const mbedtls_ecp_point *B,
546 const mbedtls_ecp_point *C)
Jens Wiklander817466c2018-05-22 13:49:31 +0200547{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200548 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200549 mbedtls_mpi one;
550
Jens Wiklander32b31802023-10-06 16:59:46 +0200551 mbedtls_mpi_init(&one);
Jens Wiklander817466c2018-05-22 13:49:31 +0200552
Jens Wiklander32b31802023-10-06 16:59:46 +0200553 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
554 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
555 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Jens Wiklander817466c2018-05-22 13:49:31 +0200556
557cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200558 mbedtls_mpi_free(&one);
Jens Wiklander817466c2018-05-22 13:49:31 +0200559
Jens Wiklander32b31802023-10-06 16:59:46 +0200560 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200561}
562
563/*
564 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
565 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200566int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
567 const unsigned char *buf,
568 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200569{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200570 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200571 const unsigned char *p = buf;
572 const unsigned char *end = buf + len;
573 mbedtls_ecp_group grp;
574 mbedtls_ecp_point G; /* C: GB, S: GA */
575
Jens Wiklander32b31802023-10-06 16:59:46 +0200576 mbedtls_ecp_group_init(&grp);
577 mbedtls_ecp_point_init(&G);
Jens Wiklander817466c2018-05-22 13:49:31 +0200578
579 /*
580 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
581 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
582 * Unified: G = Xm1 + Xm2 + Xp1
583 * We need that before parsing in order to check Xp as we read it
584 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200585 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
586 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Jens Wiklander817466c2018-05-22 13:49:31 +0200587
588 /*
589 * struct {
590 * ECParameters curve_params; // only client reading server msg
591 * ECJPAKEKeyKP ecjpake_key_kp;
592 * } Client/ServerECJPAKEParams;
593 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200594 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
595 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
596 if (grp.id != ctx->grp.id) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200597 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598 goto cleanup;
599 }
600 }
601
Jens Wiklander32b31802023-10-06 16:59:46 +0200602 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
603 ctx->point_format,
604 &G, &ctx->Xp, ID_PEER, &p, end));
Jens Wiklander817466c2018-05-22 13:49:31 +0200605
Jens Wiklander32b31802023-10-06 16:59:46 +0200606 if (p != end) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200607 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608 goto cleanup;
609 }
610
611cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200612 mbedtls_ecp_group_free(&grp);
613 mbedtls_ecp_point_free(&G);
Jens Wiklander817466c2018-05-22 13:49:31 +0200614
Jens Wiklander32b31802023-10-06 16:59:46 +0200615 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200616}
617
618/*
619 * Compute R = +/- X * S mod N, taking care not to leak S
620 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200621static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
622 const mbedtls_mpi *X,
623 const mbedtls_mpi *S,
624 const mbedtls_mpi *N,
625 int (*f_rng)(void *, unsigned char *, size_t),
626 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200627{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200628 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200629 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630
Jens Wiklander32b31802023-10-06 16:59:46 +0200631 mbedtls_mpi_init(&b);
Jens Wiklander817466c2018-05-22 13:49:31 +0200632
633 /* b = s + rnd-128-bit * N */
Jens Wiklander32b31802023-10-06 16:59:46 +0200634 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
635 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
636 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Jens Wiklander817466c2018-05-22 13:49:31 +0200637
638 /* R = sign * X * b mod N */
Jens Wiklander32b31802023-10-06 16:59:46 +0200639 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Jens Wiklander817466c2018-05-22 13:49:31 +0200640 R->s *= sign;
Jens Wiklander32b31802023-10-06 16:59:46 +0200641 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200642
643cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200644 mbedtls_mpi_free(&b);
Jens Wiklander817466c2018-05-22 13:49:31 +0200645
Jens Wiklander32b31802023-10-06 16:59:46 +0200646 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200647}
648
649/*
650 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
651 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200652int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
653 unsigned char *buf, size_t len, size_t *olen,
654 int (*f_rng)(void *, unsigned char *, size_t),
655 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200656{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200657 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200658 mbedtls_ecp_point G; /* C: GA, S: GB */
659 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
660 mbedtls_mpi xm; /* C: xc, S: xs */
661 unsigned char *p = buf;
662 const unsigned char *end = buf + len;
663 size_t ec_len;
664
Jens Wiklander32b31802023-10-06 16:59:46 +0200665 mbedtls_ecp_point_init(&G);
666 mbedtls_ecp_point_init(&Xm);
667 mbedtls_mpi_init(&xm);
Jens Wiklander817466c2018-05-22 13:49:31 +0200668
669 /*
670 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
671 *
672 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
673 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
674 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
675 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200676 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
677 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
678 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
679 &ctx->grp.N, f_rng, p_rng));
680 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200681
682 /*
683 * Now write things out
684 *
685 * struct {
686 * ECParameters curve_params; // only server writing its message
687 * ECJPAKEKeyKP ecjpake_key_kp;
688 * } Client/ServerECJPAKEParams;
689 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200690 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
691 if (end < p) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200692 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693 goto cleanup;
694 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200695 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200696 p, (size_t) (end - p)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200697 p += ec_len;
698 }
699
Jens Wiklander32b31802023-10-06 16:59:46 +0200700 if (end < p) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200701 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
702 goto cleanup;
703 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200704 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200705 ctx->point_format, &ec_len, p, (size_t) (end - p)));
Jens Wiklander817466c2018-05-22 13:49:31 +0200706 p += ec_len;
707
Jens Wiklander32b31802023-10-06 16:59:46 +0200708 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
709 ctx->point_format,
710 &G, &xm, &Xm, ID_MINE,
711 &p, end, f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200712
Tom Van Eyckc1633172024-04-09 18:44:13 +0200713 *olen = (size_t) (p - buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200714
715cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200716 mbedtls_ecp_point_free(&G);
717 mbedtls_ecp_point_free(&Xm);
718 mbedtls_mpi_free(&xm);
Jens Wiklander817466c2018-05-22 13:49:31 +0200719
Jens Wiklander32b31802023-10-06 16:59:46 +0200720 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200721}
722
723/*
724 * Derive PMS (7.4.2.7 / 7.4.2.8)
725 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200726static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
727 mbedtls_ecp_point *K,
728 int (*f_rng)(void *, unsigned char *, size_t),
729 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200730{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200731 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200732 mbedtls_mpi m_xm2_s, one;
Jens Wiklander817466c2018-05-22 13:49:31 +0200733
Jens Wiklander32b31802023-10-06 16:59:46 +0200734 mbedtls_mpi_init(&m_xm2_s);
735 mbedtls_mpi_init(&one);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100736
Jens Wiklander32b31802023-10-06 16:59:46 +0200737 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Jens Wiklander817466c2018-05-22 13:49:31 +0200738
739 /*
740 * Client: K = ( Xs - X4 * x2 * s ) * x2
741 * Server: K = ( Xc - X2 * x4 * s ) * x4
742 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
743 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200744 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
745 &ctx->grp.N, f_rng, p_rng));
746 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
747 &one, &ctx->Xp,
748 &m_xm2_s, &ctx->Xp2));
749 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
750 f_rng, p_rng));
Jens Wiklander817466c2018-05-22 13:49:31 +0200751
752cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200753 mbedtls_mpi_free(&m_xm2_s);
754 mbedtls_mpi_free(&one);
Jens Wiklander817466c2018-05-22 13:49:31 +0200755
Jens Wiklander32b31802023-10-06 16:59:46 +0200756 return ret;
757}
758
759int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
760 unsigned char *buf, size_t len, size_t *olen,
761 int (*f_rng)(void *, unsigned char *, size_t),
762 void *p_rng)
763{
764 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
765 mbedtls_ecp_point K;
766 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
767 size_t x_bytes;
768
Tom Van Eyckc1633172024-04-09 18:44:13 +0200769 *olen = mbedtls_md_get_size_from_type(ctx->md_type);
Jens Wiklander32b31802023-10-06 16:59:46 +0200770 if (len < *olen) {
771 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
772 }
773
774 mbedtls_ecp_point_init(&K);
775
776 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
777 if (ret) {
778 goto cleanup;
779 }
780
781 /* PMS = SHA-256( K.X ) */
782 x_bytes = (ctx->grp.pbits + 7) / 8;
783 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
784 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
785 kx, x_bytes, buf));
786
787cleanup:
788 mbedtls_ecp_point_free(&K);
789
790 return ret;
791}
792
793int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
794 unsigned char *buf, size_t len, size_t *olen,
795 int (*f_rng)(void *, unsigned char *, size_t),
796 void *p_rng)
797{
798 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
799 mbedtls_ecp_point K;
800
801 mbedtls_ecp_point_init(&K);
802
803 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
804 if (ret) {
805 goto cleanup;
806 }
807
808 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
809 olen, buf, len);
810 if (ret != 0) {
811 goto cleanup;
812 }
813
814cleanup:
815 mbedtls_ecp_point_free(&K);
816
817 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200818}
819
820#undef ID_MINE
821#undef ID_PEER
822
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100823#endif /* ! MBEDTLS_ECJPAKE_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200824
825#if defined(MBEDTLS_SELF_TEST)
826
Jens Wiklander817466c2018-05-22 13:49:31 +0200827#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +0200828
829#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
Tom Van Eyckc1633172024-04-09 18:44:13 +0200830 !defined(MBEDTLS_MD_CAN_SHA256)
Jens Wiklander32b31802023-10-06 16:59:46 +0200831int mbedtls_ecjpake_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200832{
833 (void) verbose;
Jens Wiklander32b31802023-10-06 16:59:46 +0200834 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200835}
836#else
837
838static const unsigned char ecjpake_test_password[] = {
839 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
840 0x65, 0x73, 0x74
841};
842
Jerome Forissier79013242021-07-28 10:24:04 +0200843#if !defined(MBEDTLS_ECJPAKE_ALT)
844
Jens Wiklander817466c2018-05-22 13:49:31 +0200845static const unsigned char ecjpake_test_x1[] = {
846 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
847 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
848 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
849};
850
851static const unsigned char ecjpake_test_x2[] = {
852 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
853 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
854 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
855};
856
857static const unsigned char ecjpake_test_x3[] = {
858 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
859 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
860 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
861};
862
863static const unsigned char ecjpake_test_x4[] = {
864 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
865 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
866 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
867};
868
869static const unsigned char ecjpake_test_cli_one[] = {
870 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
871 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
872 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
873 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
874 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
875 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
876 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
877 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
878 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
879 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
880 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
881 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
882 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
883 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
884 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
885 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
886 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
887 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
888 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
889 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
890 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
891 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
892 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
893 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
894 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
895 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
896 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
897 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
898};
899
900static const unsigned char ecjpake_test_srv_one[] = {
901 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
902 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
903 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
904 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
905 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
906 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
907 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
908 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
909 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
910 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
911 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
912 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
913 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
914 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
915 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
916 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
917 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
918 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
919 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
920 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
921 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
922 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
923 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
924 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
925 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
926 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
927 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
928 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
929};
930
931static const unsigned char ecjpake_test_srv_two[] = {
932 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
933 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
934 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
935 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
936 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
937 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
938 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
939 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
940 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
941 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
942 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
943 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
944 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
945 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
946};
947
948static const unsigned char ecjpake_test_cli_two[] = {
949 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
950 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
951 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
952 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
953 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
954 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
955 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
956 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
957 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
958 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
959 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
960 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
961 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
962 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
963};
964
Jens Wiklander32b31802023-10-06 16:59:46 +0200965static const unsigned char ecjpake_test_shared_key[] = {
966 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
967 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
968 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
969 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
970 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
971 0x17, 0xc3, 0xde, 0x27, 0xb4,
972};
973
Jens Wiklander817466c2018-05-22 13:49:31 +0200974static const unsigned char ecjpake_test_pms[] = {
975 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
976 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
977 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
978};
979
Jens Wiklander32b31802023-10-06 16:59:46 +0200980/*
981 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
982 *
983 * This is the linear congruential generator from numerical recipes,
984 * except we only use the low byte as the output. See
985 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
986 */
987static int self_test_rng(void *ctx, unsigned char *out, size_t len)
988{
989 static uint32_t state = 42;
990
991 (void) ctx;
992
993 for (size_t i = 0; i < len; i++) {
994 state = state * 1664525u + 1013904223u;
995 out[i] = (unsigned char) state;
996 }
997
998 return 0;
999}
1000
Jerome Forissier5b25c762020-04-07 11:18:49 +02001001/* Load my private keys and generate the corresponding public keys */
Jens Wiklander32b31802023-10-06 16:59:46 +02001002static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1003 const unsigned char *xm1, size_t len1,
1004 const unsigned char *xm2, size_t len2)
Jens Wiklander817466c2018-05-22 13:49:31 +02001005{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001006 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001007
Jens Wiklander32b31802023-10-06 16:59:46 +02001008 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1009 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1010 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1011 &ctx->grp.G, self_test_rng, NULL));
1012 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1013 &ctx->grp.G, self_test_rng, NULL));
Jens Wiklander817466c2018-05-22 13:49:31 +02001014
1015cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001016 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001017}
1018
Jerome Forissier79013242021-07-28 10:24:04 +02001019#endif /* ! MBEDTLS_ECJPAKE_ALT */
1020
Jens Wiklander817466c2018-05-22 13:49:31 +02001021/* For tests we don't need a secure RNG;
1022 * use the LGC from Numerical Recipes for simplicity */
Jens Wiklander32b31802023-10-06 16:59:46 +02001023static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +02001024{
1025 static uint32_t x = 42;
1026 (void) p;
1027
Jens Wiklander32b31802023-10-06 16:59:46 +02001028 while (len > 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +02001029 size_t use_len = len > 4 ? 4 : len;
1030 x = 1664525 * x + 1013904223;
Jens Wiklander32b31802023-10-06 16:59:46 +02001031 memcpy(out, &x, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +02001032 out += use_len;
1033 len -= use_len;
1034 }
1035
Jens Wiklander32b31802023-10-06 16:59:46 +02001036 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +02001037}
1038
Jens Wiklander32b31802023-10-06 16:59:46 +02001039#define TEST_ASSERT(x) \
Jens Wiklander817466c2018-05-22 13:49:31 +02001040 do { \
Jens Wiklander32b31802023-10-06 16:59:46 +02001041 if (x) \
1042 ret = 0; \
Jens Wiklander817466c2018-05-22 13:49:31 +02001043 else \
1044 { \
1045 ret = 1; \
1046 goto cleanup; \
1047 } \
Jens Wiklander32b31802023-10-06 16:59:46 +02001048 } while (0)
Jens Wiklander817466c2018-05-22 13:49:31 +02001049
1050/*
1051 * Checkup routine
1052 */
Jens Wiklander32b31802023-10-06 16:59:46 +02001053int mbedtls_ecjpake_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +02001054{
Jerome Forissier11fa71b2020-04-20 17:17:56 +02001055 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +02001056 mbedtls_ecjpake_context cli;
1057 mbedtls_ecjpake_context srv;
1058 unsigned char buf[512], pms[32];
1059 size_t len, pmslen;
1060
Jens Wiklander32b31802023-10-06 16:59:46 +02001061 mbedtls_ecjpake_init(&cli);
1062 mbedtls_ecjpake_init(&srv);
Jens Wiklander817466c2018-05-22 13:49:31 +02001063
Jens Wiklander32b31802023-10-06 16:59:46 +02001064 if (verbose != 0) {
1065 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1066 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001067
Jens Wiklander32b31802023-10-06 16:59:46 +02001068 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1069 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1070 ecjpake_test_password,
1071 sizeof(ecjpake_test_password)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001072
Jens Wiklander32b31802023-10-06 16:59:46 +02001073 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1074 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1075 ecjpake_test_password,
1076 sizeof(ecjpake_test_password)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001077
Jens Wiklander32b31802023-10-06 16:59:46 +02001078 if (verbose != 0) {
1079 mbedtls_printf("passed\n");
1080 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001081
Jens Wiklander32b31802023-10-06 16:59:46 +02001082 if (verbose != 0) {
1083 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1084 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001085
Jens Wiklander32b31802023-10-06 16:59:46 +02001086 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1087 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001088
Jens Wiklander32b31802023-10-06 16:59:46 +02001089 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001090
Jens Wiklander32b31802023-10-06 16:59:46 +02001091 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1092 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001093
Jens Wiklander32b31802023-10-06 16:59:46 +02001094 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001095
Jens Wiklander32b31802023-10-06 16:59:46 +02001096 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1097 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001098
Jens Wiklander32b31802023-10-06 16:59:46 +02001099 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001100
Jens Wiklander32b31802023-10-06 16:59:46 +02001101 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1102 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001103
Jens Wiklander32b31802023-10-06 16:59:46 +02001104 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1105 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001106
Jens Wiklander32b31802023-10-06 16:59:46 +02001107 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001108
Jens Wiklander32b31802023-10-06 16:59:46 +02001109 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1110 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001111
Jens Wiklander32b31802023-10-06 16:59:46 +02001112 TEST_ASSERT(len == pmslen);
1113 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001114
Jens Wiklander32b31802023-10-06 16:59:46 +02001115 if (verbose != 0) {
1116 mbedtls_printf("passed\n");
1117 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001118
Jerome Forissier79013242021-07-28 10:24:04 +02001119#if !defined(MBEDTLS_ECJPAKE_ALT)
1120 /* 'reference handshake' tests can only be run against implementations
1121 * for which we have 100% control over how the random ephemeral keys
Tom Van Eyckc1633172024-04-09 18:44:13 +02001122 * are generated. This is only the case for the internal Mbed TLS
Jerome Forissier79013242021-07-28 10:24:04 +02001123 * implementation, so these tests are skipped in case the internal
1124 * implementation is swapped out for an alternative one. */
Jens Wiklander32b31802023-10-06 16:59:46 +02001125 if (verbose != 0) {
1126 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1127 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001128
1129 /* Simulate generation of round one */
Jens Wiklander32b31802023-10-06 16:59:46 +02001130 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1131 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1132 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001133
Jens Wiklander32b31802023-10-06 16:59:46 +02001134 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1135 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1136 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Jens Wiklander817466c2018-05-22 13:49:31 +02001137
1138 /* Read round one */
Jens Wiklander32b31802023-10-06 16:59:46 +02001139 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1140 ecjpake_test_cli_one,
1141 sizeof(ecjpake_test_cli_one)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001142
Jens Wiklander32b31802023-10-06 16:59:46 +02001143 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1144 ecjpake_test_srv_one,
1145 sizeof(ecjpake_test_srv_one)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001146
1147 /* Skip generation of round two, read round two */
Jens Wiklander32b31802023-10-06 16:59:46 +02001148 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1149 ecjpake_test_srv_two,
1150 sizeof(ecjpake_test_srv_two)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001151
Jens Wiklander32b31802023-10-06 16:59:46 +02001152 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1153 ecjpake_test_cli_two,
1154 sizeof(ecjpake_test_cli_two)) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001155
1156 /* Server derives PMS */
Jens Wiklander32b31802023-10-06 16:59:46 +02001157 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1158 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001159
Jens Wiklander32b31802023-10-06 16:59:46 +02001160 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1161 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001162
Jens Wiklander32b31802023-10-06 16:59:46 +02001163 /* Server derives K as unsigned binary data */
1164 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1165 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1166
1167 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1168 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1169
1170 memset(buf, 0, len); /* Avoid interferences with next step */
Jens Wiklander817466c2018-05-22 13:49:31 +02001171
1172 /* Client derives PMS */
Jens Wiklander32b31802023-10-06 16:59:46 +02001173 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1174 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001175
Jens Wiklander32b31802023-10-06 16:59:46 +02001176 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1177 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +02001178
Jens Wiklander32b31802023-10-06 16:59:46 +02001179 /* Client derives K as unsigned binary data */
1180 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1181 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1182
1183 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1184 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1185
1186 if (verbose != 0) {
1187 mbedtls_printf("passed\n");
1188 }
Jerome Forissier79013242021-07-28 10:24:04 +02001189#endif /* ! MBEDTLS_ECJPAKE_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +02001190
1191cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +02001192 mbedtls_ecjpake_free(&cli);
1193 mbedtls_ecjpake_free(&srv);
Jens Wiklander817466c2018-05-22 13:49:31 +02001194
Jens Wiklander32b31802023-10-06 16:59:46 +02001195 if (ret != 0) {
1196 if (verbose != 0) {
1197 mbedtls_printf("failed\n");
1198 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001199
1200 ret = 1;
1201 }
1202
Jens Wiklander32b31802023-10-06 16:59:46 +02001203 if (verbose != 0) {
1204 mbedtls_printf("\n");
1205 }
Jens Wiklander817466c2018-05-22 13:49:31 +02001206
Jens Wiklander32b31802023-10-06 16:59:46 +02001207 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +02001208}
1209
1210#undef TEST_ASSERT
1211
Tom Van Eyckc1633172024-04-09 18:44:13 +02001212#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
Jens Wiklander817466c2018-05-22 13:49:31 +02001213
1214#endif /* MBEDTLS_SELF_TEST */
1215
1216#endif /* MBEDTLS_ECJPAKE_C */