1 /*
2 * Elliptic curve J-PAKE
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
6 *
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.
18 */
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
25 #include "common.h"
26
27 #if defined(MBEDTLS_ECJPAKE_C)
28
29 #include "mbedtls/ecjpake.h"
30 #include "mbedtls/platform_util.h"
31 #include "mbedtls/error.h"
32
33 /* 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
47 #include <string.h>
48
49 #if !defined(MBEDTLS_ECJPAKE_ALT)
50
51 /*
52 * Convert a mbedtls_ecjpake_role to identifier string
53 */
54 static const char * const ecjpake_id[] = {
55 "client",
56 "server"
57 };
58
59 #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 */
mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,const unsigned char * input,size_t ilen,unsigned char * output)65 static 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 }
83
84 /*
85 * Initialize context
86 */
mbedtls_ecjpake_init(mbedtls_ecjpake_context * ctx)87 void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
88 {
89 ctx->md_type = MBEDTLS_MD_NONE;
90 mbedtls_ecp_group_init(&ctx->grp);
91 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
92
93 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);
98
99 mbedtls_mpi_init(&ctx->xm1);
100 mbedtls_mpi_init(&ctx->xm2);
101 mbedtls_mpi_init(&ctx->s);
102 }
103
104 /*
105 * Free context
106 */
mbedtls_ecjpake_free(mbedtls_ecjpake_context * ctx)107 void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
108 {
109 if (ctx == NULL) {
110 return;
111 }
112
113 ctx->md_type = MBEDTLS_MD_NONE;
114 mbedtls_ecp_group_free(&ctx->grp);
115
116 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);
121
122 mbedtls_mpi_free(&ctx->xm1);
123 mbedtls_mpi_free(&ctx->xm2);
124 mbedtls_mpi_free(&ctx->s);
125 }
126
127 /*
128 * Setup context
129 */
mbedtls_ecjpake_setup(mbedtls_ecjpake_context * ctx,mbedtls_ecjpake_role role,mbedtls_md_type_t hash,mbedtls_ecp_group_id curve,const unsigned char * secret,size_t len)130 int 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)
136 {
137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
138
139 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
140 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
141 }
142
143 ctx->role = role;
144
145 #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
154
155 ctx->md_type = hash;
156
157 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
158
159 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
160
161 cleanup:
162 if (ret != 0) {
163 mbedtls_ecjpake_free(ctx);
164 }
165
166 return ret;
167 }
168
mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context * ctx,int point_format)169 int 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 }
180 }
181
182 /*
183 * Check if context is ready for use
184 */
mbedtls_ecjpake_check(const mbedtls_ecjpake_context * ctx)185 int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
186 {
187 if (ctx->md_type == MBEDTLS_MD_NONE ||
188 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
189 ctx->s.p == NULL) {
190 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
191 }
192
193 return 0;
194 }
195
196 /*
197 * Write a point plus its length to a buffer
198 */
ecjpake_write_len_point(unsigned char ** p,const unsigned char * end,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * P)199 static 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)
204 {
205 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
206 size_t len;
207
208 /* Need at least 4 for length plus 1 for point */
209 if (end < *p || end - *p < 5) {
210 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
211 }
212
213 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
214 &len, *p + 4, end - (*p + 4));
215 if (ret != 0) {
216 return ret;
217 }
218
219 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
220
221 *p += 4 + len;
222
223 return 0;
224 }
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 */
230 #define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
231
232 /*
233 * Compute hash for ZKP (7.4.2.2.2.1)
234 */
ecjpake_hash(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,const mbedtls_ecp_point * V,const mbedtls_ecp_point * X,const char * id,mbedtls_mpi * h)235 static 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)
243 {
244 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
245 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
246 unsigned char *p = buf;
247 const unsigned char *end = buf + sizeof(buf);
248 const size_t id_len = strlen(id);
249 unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
250
251 /* Write things to temporary buffer */
252 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));
255
256 if (end - p < 4) {
257 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
258 }
259
260 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
261 p += 4;
262
263 if (end < p || (size_t) (end - p) < id_len) {
264 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
265 }
266
267 memcpy(p, id, id_len);
268 p += id_len;
269
270 /* Compute hash */
271 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
272 buf, p - buf, hash));
273
274 /* Turn it into an integer mod n */
275 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));
278
279 cleanup:
280 return ret;
281 }
282
283 /*
284 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
285 */
ecjpake_zkp_read(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,const mbedtls_ecp_point * X,const char * id,const unsigned char ** p,const unsigned char * end)286 static 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)
294 {
295 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
296 mbedtls_ecp_point V, VV;
297 mbedtls_mpi r, h;
298 size_t r_len;
299
300 mbedtls_ecp_point_init(&V);
301 mbedtls_ecp_point_init(&VV);
302 mbedtls_mpi_init(&r);
303 mbedtls_mpi_init(&h);
304
305 /*
306 * struct {
307 * ECPoint V;
308 * opaque r<1..2^8-1>;
309 * } ECSchnorrZKP;
310 */
311 if (end < *p) {
312 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
313 }
314
315 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
316
317 if (end < *p || (size_t) (end - *p) < 1) {
318 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
319 goto cleanup;
320 }
321
322 r_len = *(*p)++;
323
324 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
325 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
326 goto cleanup;
327 }
328
329 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
330 *p += r_len;
331
332 /*
333 * Verification
334 */
335 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));
338
339 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
340 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
341 goto cleanup;
342 }
343
344 cleanup:
345 mbedtls_ecp_point_free(&V);
346 mbedtls_ecp_point_free(&VV);
347 mbedtls_mpi_free(&r);
348 mbedtls_mpi_free(&h);
349
350 return ret;
351 }
352
353 /*
354 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
355 */
ecjpake_zkp_write(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,const mbedtls_mpi * x,const mbedtls_ecp_point * X,const char * id,unsigned char ** p,const unsigned char * end,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)356 static 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)
367 {
368 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
369 mbedtls_ecp_point V;
370 mbedtls_mpi v;
371 mbedtls_mpi h; /* later recycled to hold r */
372 size_t len;
373
374 if (end < *p) {
375 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
376 }
377
378 mbedtls_ecp_point_init(&V);
379 mbedtls_mpi_init(&v);
380 mbedtls_mpi_init(&h);
381
382 /* Compute signature */
383 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 */
389
390 /* Write it out */
391 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
392 pf, &len, *p, end - *p));
393 *p += len;
394
395 len = mbedtls_mpi_size(&h); /* actually r */
396 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
397 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
398 goto cleanup;
399 }
400
401 *(*p)++ = MBEDTLS_BYTE_0(len);
402 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
403 *p += len;
404
405 cleanup:
406 mbedtls_ecp_point_free(&V);
407 mbedtls_mpi_free(&v);
408 mbedtls_mpi_free(&h);
409
410 return ret;
411 }
412
413 /*
414 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
415 * Output: verified public key X
416 */
ecjpake_kkp_read(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_ecp_point * X,const char * id,const unsigned char ** p,const unsigned char * end)417 static 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)
425 {
426 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
427
428 if (end < *p) {
429 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
430 }
431
432 /*
433 * struct {
434 * ECPoint X;
435 * ECSchnorrZKP zkp;
436 * } ECJPAKEKeyKP;
437 */
438 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
439 if (mbedtls_ecp_is_zero(X)) {
440 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
441 goto cleanup;
442 }
443
444 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
445
446 cleanup:
447 return ret;
448 }
449
450 /*
451 * Generate an ECJPAKEKeyKP
452 * Output: the serialized structure, plus private/public key pair
453 */
ecjpake_kkp_write(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_mpi * x,mbedtls_ecp_point * X,const char * id,unsigned char ** p,const unsigned char * end,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)454 static 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)
465 {
466 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
467 size_t len;
468
469 if (end < *p) {
470 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
471 }
472
473 /* Generate key (7.4.2.3.1) and write it out */
474 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));
478 *p += len;
479
480 /* Generate and write proof */
481 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
482 p, end, f_rng, p_rng));
483
484 cleanup:
485 return ret;
486 }
487
488 /*
489 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
490 * Outputs: verified peer public keys Xa, Xb
491 */
ecjpake_kkpp_read(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_ecp_point * Xa,mbedtls_ecp_point * Xb,const char * id,const unsigned char * buf,size_t len)492 static 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)
501 {
502 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
503 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 */
511 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));
513
514 if (p != end) {
515 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
516 }
517
518 cleanup:
519 return ret;
520 }
521
522 /*
523 * Generate a ECJPAKEKeyKPPairList
524 * Outputs: the serialized structure, plus two private/public key pairs
525 */
ecjpake_kkpp_write(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_mpi * xm1,mbedtls_ecp_point * Xa,mbedtls_mpi * xm2,mbedtls_ecp_point * Xb,const char * id,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)526 static 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)
540 {
541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
542 unsigned char *p = buf;
543 const unsigned char *end = buf + len;
544
545 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));
549
550 *olen = p - buf;
551
552 cleanup:
553 return ret;
554 }
555
556 /*
557 * Read and process the first round message
558 */
mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)559 int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
560 const unsigned char *buf,
561 size_t len)
562 {
563 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);
567 }
568
569 /*
570 * Generate and write the first round message
571 */
mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)572 int 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)
576 {
577 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);
581 }
582
583 /*
584 * Compute the sum of three points R = A + B + C
585 */
ecjpake_ecp_add3(mbedtls_ecp_group * grp,mbedtls_ecp_point * R,const mbedtls_ecp_point * A,const mbedtls_ecp_point * B,const mbedtls_ecp_point * C)586 static 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)
590 {
591 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
592 mbedtls_mpi one;
593
594 mbedtls_mpi_init(&one);
595
596 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));
599
600 cleanup:
601 mbedtls_mpi_free(&one);
602
603 return ret;
604 }
605
606 /*
607 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
608 */
mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)609 int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
610 const unsigned char *buf,
611 size_t len)
612 {
613 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
614 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
619 mbedtls_ecp_group_init(&grp);
620 mbedtls_ecp_point_init(&G);
621
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 */
628 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
629 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
630
631 /*
632 * struct {
633 * ECParameters curve_params; // only client reading server msg
634 * ECJPAKEKeyKP ecjpake_key_kp;
635 * } Client/ServerECJPAKEParams;
636 */
637 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) {
640 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
641 goto cleanup;
642 }
643 }
644
645 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
646 ctx->point_format,
647 &G, &ctx->Xp, ID_PEER, &p, end));
648
649 if (p != end) {
650 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 goto cleanup;
652 }
653
654 cleanup:
655 mbedtls_ecp_group_free(&grp);
656 mbedtls_ecp_point_free(&G);
657
658 return ret;
659 }
660
661 /*
662 * Compute R = +/- X * S mod N, taking care not to leak S
663 */
ecjpake_mul_secret(mbedtls_mpi * R,int sign,const mbedtls_mpi * X,const mbedtls_mpi * S,const mbedtls_mpi * N,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)664 static 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)
670 {
671 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
672 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
673
674 mbedtls_mpi_init(&b);
675
676 /* b = s + rnd-128-bit * N */
677 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));
680
681 /* R = sign * X * b mod N */
682 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
683 R->s *= sign;
684 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
685
686 cleanup:
687 mbedtls_mpi_free(&b);
688
689 return ret;
690 }
691
692 /*
693 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
694 */
mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)695 int 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)
699 {
700 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
701 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
708 mbedtls_ecp_point_init(&G);
709 mbedtls_ecp_point_init(&Xm);
710 mbedtls_mpi_init(&xm);
711
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 */
719 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));
724
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 */
733 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
734 if (end < p) {
735 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
736 goto cleanup;
737 }
738 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
739 p, end - p));
740 p += ec_len;
741 }
742
743 if (end < p) {
744 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
745 goto cleanup;
746 }
747 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
748 ctx->point_format, &ec_len, p, end - p));
749 p += ec_len;
750
751 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));
755
756 *olen = p - buf;
757
758 cleanup:
759 mbedtls_ecp_point_free(&G);
760 mbedtls_ecp_point_free(&Xm);
761 mbedtls_mpi_free(&xm);
762
763 return ret;
764 }
765
766 /*
767 * Derive PMS (7.4.2.7 / 7.4.2.8)
768 */
mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context * ctx,mbedtls_ecp_point * K,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)769 static 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)
773 {
774 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
775 mbedtls_mpi m_xm2_s, one;
776
777 mbedtls_mpi_init(&m_xm2_s);
778 mbedtls_mpi_init(&one);
779
780 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
781
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 */
787 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));
794
795 cleanup:
796 mbedtls_mpi_free(&m_xm2_s);
797 mbedtls_mpi_free(&one);
798
799 return ret;
800 }
801
mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)802 int 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
830 cleanup:
831 mbedtls_ecp_point_free(&K);
832
833 return ret;
834 }
835
mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)836 int 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
857 cleanup:
858 mbedtls_ecp_point_free(&K);
859
860 return ret;
861 }
862
863 #undef ID_MINE
864 #undef ID_PEER
865
866 #endif /* ! MBEDTLS_ECJPAKE_ALT */
867
868 #if defined(MBEDTLS_SELF_TEST)
869
870 #include "mbedtls/platform.h"
871
872 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
873 !defined(MBEDTLS_SHA256_C)
mbedtls_ecjpake_self_test(int verbose)874 int mbedtls_ecjpake_self_test(int verbose)
875 {
876 (void) verbose;
877 return 0;
878 }
879 #else
880
881 static 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
886 #if !defined(MBEDTLS_ECJPAKE_ALT)
887
888 static 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
894 static 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
900 static 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
906 static 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
912 static 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
943 static 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
974 static 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
991 static 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
1008 static 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
1017 static 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
1023 /*
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 */
self_test_rng(void * ctx,unsigned char * out,size_t len)1030 static 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
1044 /* Load my private keys and generate the corresponding public keys */
ecjpake_test_load(mbedtls_ecjpake_context * ctx,const unsigned char * xm1,size_t len1,const unsigned char * xm2,size_t len2)1045 static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1046 const unsigned char *xm1, size_t len1,
1047 const unsigned char *xm2, size_t len2)
1048 {
1049 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1050
1051 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));
1057
1058 cleanup:
1059 return ret;
1060 }
1061
1062 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1063
1064 /* For tests we don't need a secure RNG;
1065 * use the LGC from Numerical Recipes for simplicity */
ecjpake_lgc(void * p,unsigned char * out,size_t len)1066 static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
1067 {
1068 static uint32_t x = 42;
1069 (void) p;
1070
1071 while (len > 0) {
1072 size_t use_len = len > 4 ? 4 : len;
1073 x = 1664525 * x + 1013904223;
1074 memcpy(out, &x, use_len);
1075 out += use_len;
1076 len -= use_len;
1077 }
1078
1079 return 0;
1080 }
1081
1082 #define TEST_ASSERT(x) \
1083 do { \
1084 if (x) \
1085 ret = 0; \
1086 else \
1087 { \
1088 ret = 1; \
1089 goto cleanup; \
1090 } \
1091 } while (0)
1092
1093 /*
1094 * Checkup routine
1095 */
mbedtls_ecjpake_self_test(int verbose)1096 int mbedtls_ecjpake_self_test(int verbose)
1097 {
1098 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1099 mbedtls_ecjpake_context cli;
1100 mbedtls_ecjpake_context srv;
1101 unsigned char buf[512], pms[32];
1102 size_t len, pmslen;
1103
1104 mbedtls_ecjpake_init(&cli);
1105 mbedtls_ecjpake_init(&srv);
1106
1107 if (verbose != 0) {
1108 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1109 }
1110
1111 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);
1115
1116 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);
1120
1121 if (verbose != 0) {
1122 mbedtls_printf("passed\n");
1123 }
1124
1125 if (verbose != 0) {
1126 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1127 }
1128
1129 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1130 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1131
1132 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
1133
1134 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1135 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1136
1137 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
1138
1139 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1140 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1141
1142 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
1143
1144 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1145 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
1146
1147 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1148 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1149
1150 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
1151
1152 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1153 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1154
1155 TEST_ASSERT(len == pmslen);
1156 TEST_ASSERT(memcmp(buf, pms, len) == 0);
1157
1158 if (verbose != 0) {
1159 mbedtls_printf("passed\n");
1160 }
1161
1162 #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. */
1168 if (verbose != 0) {
1169 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1170 }
1171
1172 /* Simulate generation of round one */
1173 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1174 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1175 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
1176
1177 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1178 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1179 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
1180
1181 /* Read round one */
1182 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1183 ecjpake_test_cli_one,
1184 sizeof(ecjpake_test_cli_one)) == 0);
1185
1186 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1187 ecjpake_test_srv_one,
1188 sizeof(ecjpake_test_srv_one)) == 0);
1189
1190 /* Skip generation of round two, read round two */
1191 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1192 ecjpake_test_srv_two,
1193 sizeof(ecjpake_test_srv_two)) == 0);
1194
1195 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1196 ecjpake_test_cli_two,
1197 sizeof(ecjpake_test_cli_two)) == 0);
1198
1199 /* Server derives PMS */
1200 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1201 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1202
1203 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1204 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1205
1206 /* 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 */
1214
1215 /* Client derives PMS */
1216 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1217 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1218
1219 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1220 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1221
1222 /* 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 }
1232 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1233
1234 cleanup:
1235 mbedtls_ecjpake_free(&cli);
1236 mbedtls_ecjpake_free(&srv);
1237
1238 if (ret != 0) {
1239 if (verbose != 0) {
1240 mbedtls_printf("failed\n");
1241 }
1242
1243 ret = 1;
1244 }
1245
1246 if (verbose != 0) {
1247 mbedtls_printf("\n");
1248 }
1249
1250 return ret;
1251 }
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 */
1260