1 /*
2  *  Elliptic curve J-PAKE
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
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 
13 #include "common.h"
14 
15 #if defined(MBEDTLS_ECJPAKE_C)
16 
17 #include "mbedtls/ecjpake.h"
18 #include "mbedtls/platform_util.h"
19 #include "mbedtls/error.h"
20 
21 #include <string.h>
22 
23 #if !defined(MBEDTLS_ECJPAKE_ALT)
24 
25 /*
26  * Convert a mbedtls_ecjpake_role to identifier string
27  */
28 static const char * const ecjpake_id[] = {
29     "client",
30     "server"
31 };
32 
33 #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  */
mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,const unsigned char * input,size_t ilen,unsigned char * output)39 static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
40                                         const unsigned char *input, size_t ilen,
41                                         unsigned char *output)
42 {
43     return mbedtls_md(mbedtls_md_info_from_type(md_type),
44                       input, ilen, output);
45 }
46 
47 /*
48  * Initialize context
49  */
mbedtls_ecjpake_init(mbedtls_ecjpake_context * ctx)50 void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
51 {
52     ctx->md_type = MBEDTLS_MD_NONE;
53     mbedtls_ecp_group_init(&ctx->grp);
54     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
55 
56     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);
61 
62     mbedtls_mpi_init(&ctx->xm1);
63     mbedtls_mpi_init(&ctx->xm2);
64     mbedtls_mpi_init(&ctx->s);
65 }
66 
67 /*
68  * Free context
69  */
mbedtls_ecjpake_free(mbedtls_ecjpake_context * ctx)70 void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
71 {
72     if (ctx == NULL) {
73         return;
74     }
75 
76     ctx->md_type = MBEDTLS_MD_NONE;
77     mbedtls_ecp_group_free(&ctx->grp);
78 
79     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);
84 
85     mbedtls_mpi_free(&ctx->xm1);
86     mbedtls_mpi_free(&ctx->xm2);
87     mbedtls_mpi_free(&ctx->s);
88 }
89 
90 /*
91  * Setup context
92  */
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)93 int 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)
99 {
100     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101 
102     if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
103         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
104     }
105 
106     ctx->role = role;
107 
108     if ((mbedtls_md_info_from_type(hash)) == NULL) {
109         return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
110     }
111 
112     ctx->md_type = hash;
113 
114     MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
115 
116     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
117 
118 cleanup:
119     if (ret != 0) {
120         mbedtls_ecjpake_free(ctx);
121     }
122 
123     return ret;
124 }
125 
mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context * ctx,int point_format)126 int 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     }
137 }
138 
139 /*
140  * Check if context is ready for use
141  */
mbedtls_ecjpake_check(const mbedtls_ecjpake_context * ctx)142 int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
143 {
144     if (ctx->md_type == MBEDTLS_MD_NONE ||
145         ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
146         ctx->s.p == NULL) {
147         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
148     }
149 
150     return 0;
151 }
152 
153 /*
154  * Write a point plus its length to a buffer
155  */
ecjpake_write_len_point(unsigned char ** p,const unsigned char * end,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * P)156 static 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)
161 {
162     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
163     size_t len;
164 
165     /* Need at least 4 for length plus 1 for point */
166     if (end < *p || end - *p < 5) {
167         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
168     }
169 
170     ret = mbedtls_ecp_point_write_binary(grp, P, pf,
171                                          &len, *p + 4, end - (*p + 4));
172     if (ret != 0) {
173         return ret;
174     }
175 
176     MBEDTLS_PUT_UINT32_BE(len, *p, 0);
177 
178     *p += 4 + len;
179 
180     return 0;
181 }
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  */
187 #define ECJPAKE_HASH_BUF_LEN    (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
188 
189 /*
190  * Compute hash for ZKP (7.4.2.2.2.1)
191  */
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)192 static 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)
200 {
201     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
202     unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203     unsigned char *p = buf;
204     const unsigned char *end = buf + sizeof(buf);
205     const size_t id_len = strlen(id);
206     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
207 
208     /* Write things to temporary buffer */
209     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));
212 
213     if (end - p < 4) {
214         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
215     }
216 
217     MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
218     p += 4;
219 
220     if (end < p || (size_t) (end - p) < id_len) {
221         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
222     }
223 
224     memcpy(p, id, id_len);
225     p += id_len;
226 
227     /* Compute hash */
228     MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
229                                                  buf, p - buf, hash));
230 
231     /* Turn it into an integer mod n */
232     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
233                                             mbedtls_md_get_size_from_type(md_type)));
234     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
235 
236 cleanup:
237     return ret;
238 }
239 
240 /*
241  * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242  */
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)243 static 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)
251 {
252     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253     mbedtls_ecp_point V, VV;
254     mbedtls_mpi r, h;
255     size_t r_len;
256 
257     mbedtls_ecp_point_init(&V);
258     mbedtls_ecp_point_init(&VV);
259     mbedtls_mpi_init(&r);
260     mbedtls_mpi_init(&h);
261 
262     /*
263      * struct {
264      *     ECPoint V;
265      *     opaque r<1..2^8-1>;
266      * } ECSchnorrZKP;
267      */
268     if (end < *p) {
269         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
270     }
271 
272     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
273 
274     if (end < *p || (size_t) (end - *p) < 1) {
275         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276         goto cleanup;
277     }
278 
279     r_len = *(*p)++;
280 
281     if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
282         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283         goto cleanup;
284     }
285 
286     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
287     *p += r_len;
288 
289     /*
290      * Verification
291      */
292     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));
295 
296     if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
297         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298         goto cleanup;
299     }
300 
301 cleanup:
302     mbedtls_ecp_point_free(&V);
303     mbedtls_ecp_point_free(&VV);
304     mbedtls_mpi_free(&r);
305     mbedtls_mpi_free(&h);
306 
307     return ret;
308 }
309 
310 /*
311  * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
312  */
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)313 static 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)
324 {
325     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326     mbedtls_ecp_point V;
327     mbedtls_mpi v;
328     mbedtls_mpi h; /* later recycled to hold r */
329     size_t len;
330 
331     if (end < *p) {
332         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
333     }
334 
335     mbedtls_ecp_point_init(&V);
336     mbedtls_mpi_init(&v);
337     mbedtls_mpi_init(&h);
338 
339     /* Compute signature */
340     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 */
346 
347     /* Write it out */
348     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
349                                                 pf, &len, *p, end - *p));
350     *p += len;
351 
352     len = mbedtls_mpi_size(&h);   /* actually r */
353     if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
354         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355         goto cleanup;
356     }
357 
358     *(*p)++ = MBEDTLS_BYTE_0(len);
359     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len));     /* r */
360     *p += len;
361 
362 cleanup:
363     mbedtls_ecp_point_free(&V);
364     mbedtls_mpi_free(&v);
365     mbedtls_mpi_free(&h);
366 
367     return ret;
368 }
369 
370 /*
371  * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
372  * Output: verified public key X
373  */
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)374 static 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)
382 {
383     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
384 
385     if (end < *p) {
386         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
387     }
388 
389     /*
390      * struct {
391      *     ECPoint X;
392      *     ECSchnorrZKP zkp;
393      * } ECJPAKEKeyKP;
394      */
395     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
396     if (mbedtls_ecp_is_zero(X)) {
397         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398         goto cleanup;
399     }
400 
401     MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
402 
403 cleanup:
404     return ret;
405 }
406 
407 /*
408  * Generate an ECJPAKEKeyKP
409  * Output: the serialized structure, plus private/public key pair
410  */
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)411 static 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)
422 {
423     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
424     size_t len;
425 
426     if (end < *p) {
427         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
428     }
429 
430     /* Generate key (7.4.2.3.1) and write it out */
431     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,
434                                                 pf, &len, *p, end - *p));
435     *p += len;
436 
437     /* Generate and write proof */
438     MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
439                                       p, end, f_rng, p_rng));
440 
441 cleanup:
442     return ret;
443 }
444 
445 /*
446  * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
447  * Outputs: verified peer public keys Xa, Xb
448  */
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)449 static 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)
458 {
459     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
460     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      */
468     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));
470 
471     if (p != end) {
472         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
473     }
474 
475 cleanup:
476     return ret;
477 }
478 
479 /*
480  * Generate a ECJPAKEKeyKPPairList
481  * Outputs: the serialized structure, plus two private/public key pairs
482  */
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)483 static 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)
497 {
498     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
499     unsigned char *p = buf;
500     const unsigned char *end = buf + len;
501 
502     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));
506 
507     *olen = p - buf;
508 
509 cleanup:
510     return ret;
511 }
512 
513 /*
514  * Read and process the first round message
515  */
mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)516 int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
517                                    const unsigned char *buf,
518                                    size_t len)
519 {
520     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);
524 }
525 
526 /*
527  * Generate and write the first round message
528  */
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)529 int 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)
533 {
534     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);
538 }
539 
540 /*
541  * Compute the sum of three points R = A + B + C
542  */
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)543 static 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)
547 {
548     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
549     mbedtls_mpi one;
550 
551     mbedtls_mpi_init(&one);
552 
553     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));
556 
557 cleanup:
558     mbedtls_mpi_free(&one);
559 
560     return ret;
561 }
562 
563 /*
564  * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
565  */
mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)566 int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
567                                    const unsigned char *buf,
568                                    size_t len)
569 {
570     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
571     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 
576     mbedtls_ecp_group_init(&grp);
577     mbedtls_ecp_point_init(&G);
578 
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      */
585     MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
586                                      &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
587 
588     /*
589      * struct {
590      *     ECParameters curve_params;   // only client reading server msg
591      *     ECJPAKEKeyKP ecjpake_key_kp;
592      * } Client/ServerECJPAKEParams;
593      */
594     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) {
597             ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598             goto cleanup;
599         }
600     }
601 
602     MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
603                                      ctx->point_format,
604                                      &G, &ctx->Xp, ID_PEER, &p, end));
605 
606     if (p != end) {
607         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608         goto cleanup;
609     }
610 
611 cleanup:
612     mbedtls_ecp_group_free(&grp);
613     mbedtls_ecp_point_free(&G);
614 
615     return ret;
616 }
617 
618 /*
619  * Compute R = +/- X * S mod N, taking care not to leak S
620  */
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)621 static 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)
627 {
628     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
629     mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630 
631     mbedtls_mpi_init(&b);
632 
633     /* b = s + rnd-128-bit * N */
634     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));
637 
638     /* R = sign * X * b mod N */
639     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
640     R->s *= sign;
641     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
642 
643 cleanup:
644     mbedtls_mpi_free(&b);
645 
646     return ret;
647 }
648 
649 /*
650  * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
651  */
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)652 int 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)
656 {
657     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
658     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 
665     mbedtls_ecp_point_init(&G);
666     mbedtls_ecp_point_init(&Xm);
667     mbedtls_mpi_init(&xm);
668 
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      */
676     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));
681 
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      */
690     if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
691         if (end < p) {
692             ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693             goto cleanup;
694         }
695         MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
696                                                     p, end - p));
697         p += ec_len;
698     }
699 
700     if (end < p) {
701         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
702         goto cleanup;
703     }
704     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
705                                                 ctx->point_format, &ec_len, p, end - p));
706     p += ec_len;
707 
708     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));
712 
713     *olen = p - buf;
714 
715 cleanup:
716     mbedtls_ecp_point_free(&G);
717     mbedtls_ecp_point_free(&Xm);
718     mbedtls_mpi_free(&xm);
719 
720     return ret;
721 }
722 
723 /*
724  * Derive PMS (7.4.2.7 / 7.4.2.8)
725  */
mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context * ctx,mbedtls_ecp_point * K,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)726 static 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)
730 {
731     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
732     mbedtls_mpi m_xm2_s, one;
733 
734     mbedtls_mpi_init(&m_xm2_s);
735     mbedtls_mpi_init(&one);
736 
737     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
738 
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      */
744     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));
751 
752 cleanup:
753     mbedtls_mpi_free(&m_xm2_s);
754     mbedtls_mpi_free(&one);
755 
756     return ret;
757 }
758 
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)759 int 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 
769     *olen = mbedtls_md_get_size_from_type(ctx->md_type);
770     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 
787 cleanup:
788     mbedtls_ecp_point_free(&K);
789 
790     return ret;
791 }
792 
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)793 int 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 
814 cleanup:
815     mbedtls_ecp_point_free(&K);
816 
817     return ret;
818 }
819 
820 #undef ID_MINE
821 #undef ID_PEER
822 
823 #endif /* ! MBEDTLS_ECJPAKE_ALT */
824 
825 #if defined(MBEDTLS_SELF_TEST)
826 
827 #include "mbedtls/platform.h"
828 
829 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
830     !defined(MBEDTLS_MD_CAN_SHA256)
mbedtls_ecjpake_self_test(int verbose)831 int mbedtls_ecjpake_self_test(int verbose)
832 {
833     (void) verbose;
834     return 0;
835 }
836 #else
837 
838 static 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 
843 #if !defined(MBEDTLS_ECJPAKE_ALT)
844 
845 static 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 
851 static 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 
857 static 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 
863 static 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 
869 static 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 
900 static 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 
931 static 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 
948 static 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 
965 static 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 
974 static 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 
980 /*
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  */
self_test_rng(void * ctx,unsigned char * out,size_t len)987 static 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 
1001 /* 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)1002 static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1003                              const unsigned char *xm1, size_t len1,
1004                              const unsigned char *xm2, size_t len2)
1005 {
1006     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1007 
1008     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));
1014 
1015 cleanup:
1016     return ret;
1017 }
1018 
1019 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1020 
1021 /* For tests we don't need a secure RNG;
1022  * use the LGC from Numerical Recipes for simplicity */
ecjpake_lgc(void * p,unsigned char * out,size_t len)1023 static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
1024 {
1025     static uint32_t x = 42;
1026     (void) p;
1027 
1028     while (len > 0) {
1029         size_t use_len = len > 4 ? 4 : len;
1030         x = 1664525 * x + 1013904223;
1031         memcpy(out, &x, use_len);
1032         out += use_len;
1033         len -= use_len;
1034     }
1035 
1036     return 0;
1037 }
1038 
1039 #define TEST_ASSERT(x)    \
1040     do {                    \
1041         if (x)             \
1042         ret = 0;        \
1043         else                \
1044         {                   \
1045             ret = 1;        \
1046             goto cleanup;   \
1047         }                   \
1048     } while (0)
1049 
1050 /*
1051  * Checkup routine
1052  */
mbedtls_ecjpake_self_test(int verbose)1053 int mbedtls_ecjpake_self_test(int verbose)
1054 {
1055     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1056     mbedtls_ecjpake_context cli;
1057     mbedtls_ecjpake_context srv;
1058     unsigned char buf[512], pms[32];
1059     size_t len, pmslen;
1060 
1061     mbedtls_ecjpake_init(&cli);
1062     mbedtls_ecjpake_init(&srv);
1063 
1064     if (verbose != 0) {
1065         mbedtls_printf("  ECJPAKE test #0 (setup): ");
1066     }
1067 
1068     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);
1072 
1073     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);
1077 
1078     if (verbose != 0) {
1079         mbedtls_printf("passed\n");
1080     }
1081 
1082     if (verbose != 0) {
1083         mbedtls_printf("  ECJPAKE test #1 (random handshake): ");
1084     }
1085 
1086     TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1087                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1088 
1089     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
1090 
1091     TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1092                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1093 
1094     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
1095 
1096     TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1097                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1098 
1099     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
1100 
1101     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1102                                               pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
1103 
1104     TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1105                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1106 
1107     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
1108 
1109     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1110                                               buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1111 
1112     TEST_ASSERT(len == pmslen);
1113     TEST_ASSERT(memcmp(buf, pms, len) == 0);
1114 
1115     if (verbose != 0) {
1116         mbedtls_printf("passed\n");
1117     }
1118 
1119 #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
1122      * are generated. This is only the case for the internal Mbed TLS
1123      * implementation, so these tests are skipped in case the internal
1124      * implementation is swapped out for an alternative one. */
1125     if (verbose != 0) {
1126         mbedtls_printf("  ECJPAKE test #2 (reference handshake): ");
1127     }
1128 
1129     /* Simulate generation of round one */
1130     MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1131                                       ecjpake_test_x1, sizeof(ecjpake_test_x1),
1132                                       ecjpake_test_x2, sizeof(ecjpake_test_x2)));
1133 
1134     MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1135                                       ecjpake_test_x3, sizeof(ecjpake_test_x3),
1136                                       ecjpake_test_x4, sizeof(ecjpake_test_x4)));
1137 
1138     /* Read round one */
1139     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1140                                                ecjpake_test_cli_one,
1141                                                sizeof(ecjpake_test_cli_one)) == 0);
1142 
1143     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1144                                                ecjpake_test_srv_one,
1145                                                sizeof(ecjpake_test_srv_one)) == 0);
1146 
1147     /* Skip generation of round two, read round two */
1148     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1149                                                ecjpake_test_srv_two,
1150                                                sizeof(ecjpake_test_srv_two)) == 0);
1151 
1152     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1153                                                ecjpake_test_cli_two,
1154                                                sizeof(ecjpake_test_cli_two)) == 0);
1155 
1156     /* Server derives PMS */
1157     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1158                                               buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1159 
1160     TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1161     TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1162 
1163     /* 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 */
1171 
1172     /* Client derives PMS */
1173     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1174                                               buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1175 
1176     TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1177     TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1178 
1179     /* 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     }
1189 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1190 
1191 cleanup:
1192     mbedtls_ecjpake_free(&cli);
1193     mbedtls_ecjpake_free(&srv);
1194 
1195     if (ret != 0) {
1196         if (verbose != 0) {
1197             mbedtls_printf("failed\n");
1198         }
1199 
1200         ret = 1;
1201     }
1202 
1203     if (verbose != 0) {
1204         mbedtls_printf("\n");
1205     }
1206 
1207     return ret;
1208 }
1209 
1210 #undef TEST_ASSERT
1211 
1212 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
1213 
1214 #endif /* MBEDTLS_SELF_TEST */
1215 
1216 #endif /* MBEDTLS_ECJPAKE_C */
1217