• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* Parameter validation macros based on platform_util.h */
26 #define ECJPAKE_VALIDATE_RET(cond)    \
27     MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
28 #define ECJPAKE_VALIDATE(cond)        \
29     MBEDTLS_INTERNAL_VALIDATE(cond)
30 
31 /*
32  * Convert a mbedtls_ecjpake_role to identifier string
33  */
34 static const char * const ecjpake_id[] = {
35     "client",
36     "server"
37 };
38 
39 #define ID_MINE     (ecjpake_id[ctx->role])
40 #define ID_PEER     (ecjpake_id[1 - ctx->role])
41 
42 /*
43  * Initialize context
44  */
mbedtls_ecjpake_init(mbedtls_ecjpake_context * ctx)45 void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
46 {
47     ECJPAKE_VALIDATE(ctx != NULL);
48 
49     ctx->md_info = NULL;
50     mbedtls_ecp_group_init(&ctx->grp);
51     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
52 
53     mbedtls_ecp_point_init(&ctx->Xm1);
54     mbedtls_ecp_point_init(&ctx->Xm2);
55     mbedtls_ecp_point_init(&ctx->Xp1);
56     mbedtls_ecp_point_init(&ctx->Xp2);
57     mbedtls_ecp_point_init(&ctx->Xp);
58 
59     mbedtls_mpi_init(&ctx->xm1);
60     mbedtls_mpi_init(&ctx->xm2);
61     mbedtls_mpi_init(&ctx->s);
62 }
63 
64 /*
65  * Free context
66  */
mbedtls_ecjpake_free(mbedtls_ecjpake_context * ctx)67 void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
68 {
69     if (ctx == NULL) {
70         return;
71     }
72 
73     ctx->md_info = NULL;
74     mbedtls_ecp_group_free(&ctx->grp);
75 
76     mbedtls_ecp_point_free(&ctx->Xm1);
77     mbedtls_ecp_point_free(&ctx->Xm2);
78     mbedtls_ecp_point_free(&ctx->Xp1);
79     mbedtls_ecp_point_free(&ctx->Xp2);
80     mbedtls_ecp_point_free(&ctx->Xp);
81 
82     mbedtls_mpi_free(&ctx->xm1);
83     mbedtls_mpi_free(&ctx->xm2);
84     mbedtls_mpi_free(&ctx->s);
85 }
86 
87 /*
88  * Setup context
89  */
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)90 int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
91                           mbedtls_ecjpake_role role,
92                           mbedtls_md_type_t hash,
93                           mbedtls_ecp_group_id curve,
94                           const unsigned char *secret,
95                           size_t len)
96 {
97     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
98 
99     ECJPAKE_VALIDATE_RET(ctx != NULL);
100     ECJPAKE_VALIDATE_RET(role == MBEDTLS_ECJPAKE_CLIENT ||
101                          role == MBEDTLS_ECJPAKE_SERVER);
102     ECJPAKE_VALIDATE_RET(secret != NULL || len == 0);
103 
104     ctx->role = role;
105 
106     if ((ctx->md_info = mbedtls_md_info_from_type(hash)) == NULL) {
107         return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
108     }
109 
110     MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
111 
112     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
113 
114 cleanup:
115     if (ret != 0) {
116         mbedtls_ecjpake_free(ctx);
117     }
118 
119     return ret;
120 }
121 
122 /*
123  * Check if context is ready for use
124  */
mbedtls_ecjpake_check(const mbedtls_ecjpake_context * ctx)125 int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
126 {
127     ECJPAKE_VALIDATE_RET(ctx != NULL);
128 
129     if (ctx->md_info == NULL ||
130         ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
131         ctx->s.p == NULL) {
132         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
133     }
134 
135     return 0;
136 }
137 
138 /*
139  * Write a point plus its length to a buffer
140  */
ecjpake_write_len_point(unsigned char ** p,const unsigned char * end,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * P)141 static int ecjpake_write_len_point(unsigned char **p,
142                                    const unsigned char *end,
143                                    const mbedtls_ecp_group *grp,
144                                    const int pf,
145                                    const mbedtls_ecp_point *P)
146 {
147     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
148     size_t len;
149 
150     /* Need at least 4 for length plus 1 for point */
151     if (end < *p || end - *p < 5) {
152         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
153     }
154 
155     ret = mbedtls_ecp_point_write_binary(grp, P, pf,
156                                          &len, *p + 4, end - (*p + 4));
157     if (ret != 0) {
158         return ret;
159     }
160 
161     MBEDTLS_PUT_UINT32_BE(len, *p, 0);
162 
163     *p += 4 + len;
164 
165     return 0;
166 }
167 
168 /*
169  * Size of the temporary buffer for ecjpake_hash:
170  * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
171  */
172 #define ECJPAKE_HASH_BUF_LEN    (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
173 
174 /*
175  * Compute hash for ZKP (7.4.2.2.2.1)
176  */
ecjpake_hash(const mbedtls_md_info_t * md_info,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)177 static int ecjpake_hash(const mbedtls_md_info_t *md_info,
178                         const mbedtls_ecp_group *grp,
179                         const int pf,
180                         const mbedtls_ecp_point *G,
181                         const mbedtls_ecp_point *V,
182                         const mbedtls_ecp_point *X,
183                         const char *id,
184                         mbedtls_mpi *h)
185 {
186     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
187     unsigned char buf[ECJPAKE_HASH_BUF_LEN];
188     unsigned char *p = buf;
189     const unsigned char *end = buf + sizeof(buf);
190     const size_t id_len = strlen(id);
191     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
192 
193     /* Write things to temporary buffer */
194     MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
195     MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
196     MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
197 
198     if (end - p < 4) {
199         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
200     }
201 
202     MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
203     p += 4;
204 
205     if (end < p || (size_t) (end - p) < id_len) {
206         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
207     }
208 
209     memcpy(p, id, id_len);
210     p += id_len;
211 
212     /* Compute hash */
213     MBEDTLS_MPI_CHK(mbedtls_md(md_info, buf, p - buf, hash));
214 
215     /* Turn it into an integer mod n */
216     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
217                                             mbedtls_md_get_size(md_info)));
218     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
219 
220 cleanup:
221     return ret;
222 }
223 
224 /*
225  * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
226  */
ecjpake_zkp_read(const mbedtls_md_info_t * md_info,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)227 static int ecjpake_zkp_read(const mbedtls_md_info_t *md_info,
228                             const mbedtls_ecp_group *grp,
229                             const int pf,
230                             const mbedtls_ecp_point *G,
231                             const mbedtls_ecp_point *X,
232                             const char *id,
233                             const unsigned char **p,
234                             const unsigned char *end)
235 {
236     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
237     mbedtls_ecp_point V, VV;
238     mbedtls_mpi r, h;
239     size_t r_len;
240 
241     mbedtls_ecp_point_init(&V);
242     mbedtls_ecp_point_init(&VV);
243     mbedtls_mpi_init(&r);
244     mbedtls_mpi_init(&h);
245 
246     /*
247      * struct {
248      *     ECPoint V;
249      *     opaque r<1..2^8-1>;
250      * } ECSchnorrZKP;
251      */
252     if (end < *p) {
253         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
254     }
255 
256     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
257 
258     if (end < *p || (size_t) (end - *p) < 1) {
259         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
260         goto cleanup;
261     }
262 
263     r_len = *(*p)++;
264 
265     if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
266         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
267         goto cleanup;
268     }
269 
270     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
271     *p += r_len;
272 
273     /*
274      * Verification
275      */
276     MBEDTLS_MPI_CHK(ecjpake_hash(md_info, grp, pf, G, &V, X, id, &h));
277     MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
278                                        &VV, &h, X, &r, G));
279 
280     if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
281         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
282         goto cleanup;
283     }
284 
285 cleanup:
286     mbedtls_ecp_point_free(&V);
287     mbedtls_ecp_point_free(&VV);
288     mbedtls_mpi_free(&r);
289     mbedtls_mpi_free(&h);
290 
291     return ret;
292 }
293 
294 /*
295  * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
296  */
ecjpake_zkp_write(const mbedtls_md_info_t * md_info,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)297 static int ecjpake_zkp_write(const mbedtls_md_info_t *md_info,
298                              const mbedtls_ecp_group *grp,
299                              const int pf,
300                              const mbedtls_ecp_point *G,
301                              const mbedtls_mpi *x,
302                              const mbedtls_ecp_point *X,
303                              const char *id,
304                              unsigned char **p,
305                              const unsigned char *end,
306                              int (*f_rng)(void *, unsigned char *, size_t),
307                              void *p_rng)
308 {
309     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
310     mbedtls_ecp_point V;
311     mbedtls_mpi v;
312     mbedtls_mpi h; /* later recycled to hold r */
313     size_t len;
314 
315     if (end < *p) {
316         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
317     }
318 
319     mbedtls_ecp_point_init(&V);
320     mbedtls_mpi_init(&v);
321     mbedtls_mpi_init(&h);
322 
323     /* Compute signature */
324     MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
325                                                  G, &v, &V, f_rng, p_rng));
326     MBEDTLS_MPI_CHK(ecjpake_hash(md_info, grp, pf, G, &V, X, id, &h));
327     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x));     /* x*h */
328     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h));     /* v - x*h */
329     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N));     /* r */
330 
331     /* Write it out */
332     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
333                                                 pf, &len, *p, end - *p));
334     *p += len;
335 
336     len = mbedtls_mpi_size(&h);   /* actually r */
337     if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
338         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
339         goto cleanup;
340     }
341 
342     *(*p)++ = MBEDTLS_BYTE_0(len);
343     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len));     /* r */
344     *p += len;
345 
346 cleanup:
347     mbedtls_ecp_point_free(&V);
348     mbedtls_mpi_free(&v);
349     mbedtls_mpi_free(&h);
350 
351     return ret;
352 }
353 
354 /*
355  * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
356  * Output: verified public key X
357  */
ecjpake_kkp_read(const mbedtls_md_info_t * md_info,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)358 static int ecjpake_kkp_read(const mbedtls_md_info_t *md_info,
359                             const mbedtls_ecp_group *grp,
360                             const int pf,
361                             const mbedtls_ecp_point *G,
362                             mbedtls_ecp_point *X,
363                             const char *id,
364                             const unsigned char **p,
365                             const unsigned char *end)
366 {
367     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
368 
369     if (end < *p) {
370         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
371     }
372 
373     /*
374      * struct {
375      *     ECPoint X;
376      *     ECSchnorrZKP zkp;
377      * } ECJPAKEKeyKP;
378      */
379     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
380     if (mbedtls_ecp_is_zero(X)) {
381         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
382         goto cleanup;
383     }
384 
385     MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_info, grp, pf, G, X, id, p, end));
386 
387 cleanup:
388     return ret;
389 }
390 
391 /*
392  * Generate an ECJPAKEKeyKP
393  * Output: the serialized structure, plus private/public key pair
394  */
ecjpake_kkp_write(const mbedtls_md_info_t * md_info,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)395 static int ecjpake_kkp_write(const mbedtls_md_info_t *md_info,
396                              const mbedtls_ecp_group *grp,
397                              const int pf,
398                              const mbedtls_ecp_point *G,
399                              mbedtls_mpi *x,
400                              mbedtls_ecp_point *X,
401                              const char *id,
402                              unsigned char **p,
403                              const unsigned char *end,
404                              int (*f_rng)(void *, unsigned char *, size_t),
405                              void *p_rng)
406 {
407     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
408     size_t len;
409 
410     if (end < *p) {
411         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
412     }
413 
414     /* Generate key (7.4.2.3.1) and write it out */
415     MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
416                                                  f_rng, p_rng));
417     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
418                                                 pf, &len, *p, end - *p));
419     *p += len;
420 
421     /* Generate and write proof */
422     MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_info, grp, pf, G, x, X, id,
423                                       p, end, f_rng, p_rng));
424 
425 cleanup:
426     return ret;
427 }
428 
429 /*
430  * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
431  * Outputs: verified peer public keys Xa, Xb
432  */
ecjpake_kkpp_read(const mbedtls_md_info_t * md_info,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)433 static int ecjpake_kkpp_read(const mbedtls_md_info_t *md_info,
434                              const mbedtls_ecp_group *grp,
435                              const int pf,
436                              const mbedtls_ecp_point *G,
437                              mbedtls_ecp_point *Xa,
438                              mbedtls_ecp_point *Xb,
439                              const char *id,
440                              const unsigned char *buf,
441                              size_t len)
442 {
443     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
444     const unsigned char *p = buf;
445     const unsigned char *end = buf + len;
446 
447     /*
448      * struct {
449      *     ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
450      * } ECJPAKEKeyKPPairList;
451      */
452     MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_info, grp, pf, G, Xa, id, &p, end));
453     MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_info, grp, pf, G, Xb, id, &p, end));
454 
455     if (p != end) {
456         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
457     }
458 
459 cleanup:
460     return ret;
461 }
462 
463 /*
464  * Generate a ECJPAKEKeyKPPairList
465  * Outputs: the serialized structure, plus two private/public key pairs
466  */
ecjpake_kkpp_write(const mbedtls_md_info_t * md_info,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)467 static int ecjpake_kkpp_write(const mbedtls_md_info_t *md_info,
468                               const mbedtls_ecp_group *grp,
469                               const int pf,
470                               const mbedtls_ecp_point *G,
471                               mbedtls_mpi *xm1,
472                               mbedtls_ecp_point *Xa,
473                               mbedtls_mpi *xm2,
474                               mbedtls_ecp_point *Xb,
475                               const char *id,
476                               unsigned char *buf,
477                               size_t len,
478                               size_t *olen,
479                               int (*f_rng)(void *, unsigned char *, size_t),
480                               void *p_rng)
481 {
482     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
483     unsigned char *p = buf;
484     const unsigned char *end = buf + len;
485 
486     MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_info, grp, pf, G, xm1, Xa, id,
487                                       &p, end, f_rng, p_rng));
488     MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_info, grp, pf, G, xm2, Xb, id,
489                                       &p, end, f_rng, p_rng));
490 
491     *olen = p - buf;
492 
493 cleanup:
494     return ret;
495 }
496 
497 /*
498  * Read and process the first round message
499  */
mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)500 int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
501                                    const unsigned char *buf,
502                                    size_t len)
503 {
504     ECJPAKE_VALIDATE_RET(ctx != NULL);
505     ECJPAKE_VALIDATE_RET(buf != NULL);
506 
507     return ecjpake_kkpp_read(ctx->md_info, &ctx->grp, ctx->point_format,
508                              &ctx->grp.G,
509                              &ctx->Xp1, &ctx->Xp2, ID_PEER,
510                              buf, len);
511 }
512 
513 /*
514  * Generate and write the first round message
515  */
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)516 int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
517                                     unsigned char *buf, size_t len, size_t *olen,
518                                     int (*f_rng)(void *, unsigned char *, size_t),
519                                     void *p_rng)
520 {
521     ECJPAKE_VALIDATE_RET(ctx   != NULL);
522     ECJPAKE_VALIDATE_RET(buf   != NULL);
523     ECJPAKE_VALIDATE_RET(olen  != NULL);
524     ECJPAKE_VALIDATE_RET(f_rng != NULL);
525 
526     return ecjpake_kkpp_write(ctx->md_info, &ctx->grp, ctx->point_format,
527                               &ctx->grp.G,
528                               &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
529                               ID_MINE, buf, len, olen, f_rng, p_rng);
530 }
531 
532 /*
533  * Compute the sum of three points R = A + B + C
534  */
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)535 static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
536                             const mbedtls_ecp_point *A,
537                             const mbedtls_ecp_point *B,
538                             const mbedtls_ecp_point *C)
539 {
540     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
541     mbedtls_mpi one;
542 
543     mbedtls_mpi_init(&one);
544 
545     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
546     MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
547     MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
548 
549 cleanup:
550     mbedtls_mpi_free(&one);
551 
552     return ret;
553 }
554 
555 /*
556  * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
557  */
mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)558 int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
559                                    const unsigned char *buf,
560                                    size_t len)
561 {
562     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
563     const unsigned char *p = buf;
564     const unsigned char *end = buf + len;
565     mbedtls_ecp_group grp;
566     mbedtls_ecp_point G;    /* C: GB, S: GA */
567 
568     ECJPAKE_VALIDATE_RET(ctx != NULL);
569     ECJPAKE_VALIDATE_RET(buf != NULL);
570 
571     mbedtls_ecp_group_init(&grp);
572     mbedtls_ecp_point_init(&G);
573 
574     /*
575      * Server: GA = X3  + X4  + X1      (7.4.2.6.1)
576      * Client: GB = X1  + X2  + X3      (7.4.2.5.1)
577      * Unified: G = Xm1 + Xm2 + Xp1
578      * We need that before parsing in order to check Xp as we read it
579      */
580     MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
581                                      &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
582 
583     /*
584      * struct {
585      *     ECParameters curve_params;   // only client reading server msg
586      *     ECJPAKEKeyKP ecjpake_key_kp;
587      * } Client/ServerECJPAKEParams;
588      */
589     if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
590         MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
591         if (grp.id != ctx->grp.id) {
592             ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
593             goto cleanup;
594         }
595     }
596 
597     MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_info, &ctx->grp,
598                                      ctx->point_format,
599                                      &G, &ctx->Xp, ID_PEER, &p, end));
600 
601     if (p != end) {
602         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
603         goto cleanup;
604     }
605 
606 cleanup:
607     mbedtls_ecp_group_free(&grp);
608     mbedtls_ecp_point_free(&G);
609 
610     return ret;
611 }
612 
613 /*
614  * Compute R = +/- X * S mod N, taking care not to leak S
615  */
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)616 static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
617                               const mbedtls_mpi *X,
618                               const mbedtls_mpi *S,
619                               const mbedtls_mpi *N,
620                               int (*f_rng)(void *, unsigned char *, size_t),
621                               void *p_rng)
622 {
623     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
624     mbedtls_mpi b; /* Blinding value, then s + N * blinding */
625 
626     mbedtls_mpi_init(&b);
627 
628     /* b = s + rnd-128-bit * N */
629     MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
630     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
631     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
632 
633     /* R = sign * X * b mod N */
634     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
635     R->s *= sign;
636     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
637 
638 cleanup:
639     mbedtls_mpi_free(&b);
640 
641     return ret;
642 }
643 
644 /*
645  * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
646  */
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)647 int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
648                                     unsigned char *buf, size_t len, size_t *olen,
649                                     int (*f_rng)(void *, unsigned char *, size_t),
650                                     void *p_rng)
651 {
652     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
653     mbedtls_ecp_point G;    /* C: GA, S: GB */
654     mbedtls_ecp_point Xm;   /* C: Xc, S: Xs */
655     mbedtls_mpi xm;         /* C: xc, S: xs */
656     unsigned char *p = buf;
657     const unsigned char *end = buf + len;
658     size_t ec_len;
659 
660     ECJPAKE_VALIDATE_RET(ctx   != NULL);
661     ECJPAKE_VALIDATE_RET(buf   != NULL);
662     ECJPAKE_VALIDATE_RET(olen  != NULL);
663     ECJPAKE_VALIDATE_RET(f_rng != NULL);
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_info, &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_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)726 int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
727                                   unsigned char *buf, size_t len, size_t *olen,
728                                   int (*f_rng)(void *, unsigned char *, size_t),
729                                   void *p_rng)
730 {
731     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
732     mbedtls_ecp_point K;
733     mbedtls_mpi m_xm2_s, one;
734     unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
735     size_t x_bytes;
736 
737     ECJPAKE_VALIDATE_RET(ctx   != NULL);
738     ECJPAKE_VALIDATE_RET(buf   != NULL);
739     ECJPAKE_VALIDATE_RET(olen  != NULL);
740     ECJPAKE_VALIDATE_RET(f_rng != NULL);
741 
742     *olen = mbedtls_md_get_size(ctx->md_info);
743     if (len < *olen) {
744         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
745     }
746 
747     mbedtls_ecp_point_init(&K);
748     mbedtls_mpi_init(&m_xm2_s);
749     mbedtls_mpi_init(&one);
750 
751     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
752 
753     /*
754      * Client:  K = ( Xs - X4  * x2  * s ) * x2
755      * Server:  K = ( Xc - X2  * x4  * s ) * x4
756      * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
757      */
758     MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
759                                        &ctx->grp.N, f_rng, p_rng));
760     MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, &K,
761                                        &one, &ctx->Xp,
762                                        &m_xm2_s, &ctx->Xp2));
763     MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &K, &ctx->xm2, &K,
764                                     f_rng, p_rng));
765 
766     /* PMS = SHA-256( K.X ) */
767     x_bytes = (ctx->grp.pbits + 7) / 8;
768     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
769     MBEDTLS_MPI_CHK(mbedtls_md(ctx->md_info, kx, x_bytes, buf));
770 
771 cleanup:
772     mbedtls_ecp_point_free(&K);
773     mbedtls_mpi_free(&m_xm2_s);
774     mbedtls_mpi_free(&one);
775 
776     return ret;
777 }
778 
779 #undef ID_MINE
780 #undef ID_PEER
781 
782 #endif /* ! MBEDTLS_ECJPAKE_ALT */
783 
784 #if defined(MBEDTLS_SELF_TEST)
785 
786 #include "mbedtls/platform.h"
787 
788 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
789     !defined(MBEDTLS_SHA256_C)
mbedtls_ecjpake_self_test(int verbose)790 int mbedtls_ecjpake_self_test(int verbose)
791 {
792     (void) verbose;
793     return 0;
794 }
795 #else
796 
797 static const unsigned char ecjpake_test_password[] = {
798     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
799     0x65, 0x73, 0x74
800 };
801 
802 #if !defined(MBEDTLS_ECJPAKE_ALT)
803 
804 static const unsigned char ecjpake_test_x1[] = {
805     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
806     0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
807     0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
808 };
809 
810 static const unsigned char ecjpake_test_x2[] = {
811     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
812     0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
813     0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
814 };
815 
816 static const unsigned char ecjpake_test_x3[] = {
817     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
818     0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
819     0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
820 };
821 
822 static const unsigned char ecjpake_test_x4[] = {
823     0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
824     0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
825     0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
826 };
827 
828 static const unsigned char ecjpake_test_cli_one[] = {
829     0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
830     0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
831     0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
832     0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
833     0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
834     0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
835     0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
836     0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
837     0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
838     0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
839     0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
840     0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
841     0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
842     0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
843     0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
844     0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
845     0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
846     0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
847     0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
848     0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
849     0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
850     0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
851     0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
852     0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
853     0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
854     0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
855     0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
856     0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
857 };
858 
859 static const unsigned char ecjpake_test_srv_one[] = {
860     0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
861     0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
862     0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
863     0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
864     0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
865     0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
866     0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
867     0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
868     0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
869     0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
870     0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
871     0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
872     0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
873     0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
874     0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
875     0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
876     0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
877     0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
878     0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
879     0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
880     0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
881     0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
882     0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
883     0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
884     0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
885     0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
886     0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
887     0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
888 };
889 
890 static const unsigned char ecjpake_test_srv_two[] = {
891     0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
892     0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
893     0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
894     0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
895     0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
896     0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
897     0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
898     0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
899     0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
900     0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
901     0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
902     0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
903     0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
904     0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
905 };
906 
907 static const unsigned char ecjpake_test_cli_two[] = {
908     0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
909     0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
910     0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
911     0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
912     0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
913     0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
914     0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
915     0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
916     0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
917     0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
918     0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
919     0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
920     0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
921     0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
922 };
923 
924 static const unsigned char ecjpake_test_pms[] = {
925     0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
926     0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
927     0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
928 };
929 
930 /* 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)931 static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
932                              const unsigned char *xm1, size_t len1,
933                              const unsigned char *xm2, size_t len2)
934 {
935     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
936 
937     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
938     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
939     MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
940                                     &ctx->grp.G, NULL, NULL));
941     MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
942                                     &ctx->grp.G, NULL, NULL));
943 
944 cleanup:
945     return ret;
946 }
947 
948 #endif /* ! MBEDTLS_ECJPAKE_ALT */
949 
950 /* For tests we don't need a secure RNG;
951  * use the LGC from Numerical Recipes for simplicity */
ecjpake_lgc(void * p,unsigned char * out,size_t len)952 static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
953 {
954     static uint32_t x = 42;
955     (void) p;
956 
957     while (len > 0) {
958         size_t use_len = len > 4 ? 4 : len;
959         x = 1664525 * x + 1013904223;
960         memcpy(out, &x, use_len);
961         out += use_len;
962         len -= use_len;
963     }
964 
965     return 0;
966 }
967 
968 #define TEST_ASSERT(x)    \
969     do {                    \
970         if (x)             \
971         ret = 0;        \
972         else                \
973         {                   \
974             ret = 1;        \
975             goto cleanup;   \
976         }                   \
977     } while (0)
978 
979 /*
980  * Checkup routine
981  */
mbedtls_ecjpake_self_test(int verbose)982 int mbedtls_ecjpake_self_test(int verbose)
983 {
984     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
985     mbedtls_ecjpake_context cli;
986     mbedtls_ecjpake_context srv;
987     unsigned char buf[512], pms[32];
988     size_t len, pmslen;
989 
990     mbedtls_ecjpake_init(&cli);
991     mbedtls_ecjpake_init(&srv);
992 
993     if (verbose != 0) {
994         mbedtls_printf("  ECJPAKE test #0 (setup): ");
995     }
996 
997     TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
998                                       MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
999                                       ecjpake_test_password,
1000                                       sizeof(ecjpake_test_password)) == 0);
1001 
1002     TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1003                                       MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1004                                       ecjpake_test_password,
1005                                       sizeof(ecjpake_test_password)) == 0);
1006 
1007     if (verbose != 0) {
1008         mbedtls_printf("passed\n");
1009     }
1010 
1011     if (verbose != 0) {
1012         mbedtls_printf("  ECJPAKE test #1 (random handshake): ");
1013     }
1014 
1015     TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1016                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1017 
1018     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
1019 
1020     TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1021                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1022 
1023     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
1024 
1025     TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1026                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1027 
1028     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
1029 
1030     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1031                                               pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
1032 
1033     TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1034                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1035 
1036     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
1037 
1038     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1039                                               buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1040 
1041     TEST_ASSERT(len == pmslen);
1042     TEST_ASSERT(memcmp(buf, pms, len) == 0);
1043 
1044     if (verbose != 0) {
1045         mbedtls_printf("passed\n");
1046     }
1047 
1048 #if !defined(MBEDTLS_ECJPAKE_ALT)
1049     /* 'reference handshake' tests can only be run against implementations
1050      * for which we have 100% control over how the random ephemeral keys
1051      * are generated. This is only the case for the internal Mbed TLS
1052      * implementation, so these tests are skipped in case the internal
1053      * implementation is swapped out for an alternative one. */
1054     if (verbose != 0) {
1055         mbedtls_printf("  ECJPAKE test #2 (reference handshake): ");
1056     }
1057 
1058     /* Simulate generation of round one */
1059     MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1060                                       ecjpake_test_x1, sizeof(ecjpake_test_x1),
1061                                       ecjpake_test_x2, sizeof(ecjpake_test_x2)));
1062 
1063     MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1064                                       ecjpake_test_x3, sizeof(ecjpake_test_x3),
1065                                       ecjpake_test_x4, sizeof(ecjpake_test_x4)));
1066 
1067     /* Read round one */
1068     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1069                                                ecjpake_test_cli_one,
1070                                                sizeof(ecjpake_test_cli_one)) == 0);
1071 
1072     TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1073                                                ecjpake_test_srv_one,
1074                                                sizeof(ecjpake_test_srv_one)) == 0);
1075 
1076     /* Skip generation of round two, read round two */
1077     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1078                                                ecjpake_test_srv_two,
1079                                                sizeof(ecjpake_test_srv_two)) == 0);
1080 
1081     TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1082                                                ecjpake_test_cli_two,
1083                                                sizeof(ecjpake_test_cli_two)) == 0);
1084 
1085     /* Server derives PMS */
1086     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1087                                               buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1088 
1089     TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1090     TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1091 
1092     memset(buf, 0, len);   /* Avoid interferences with next step */
1093 
1094     /* Client derives PMS */
1095     TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1096                                               buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1097 
1098     TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1099     TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1100 
1101     if (verbose != 0) {
1102         mbedtls_printf("passed\n");
1103     }
1104 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1105 
1106 cleanup:
1107     mbedtls_ecjpake_free(&cli);
1108     mbedtls_ecjpake_free(&srv);
1109 
1110     if (ret != 0) {
1111         if (verbose != 0) {
1112             mbedtls_printf("failed\n");
1113         }
1114 
1115         ret = 1;
1116     }
1117 
1118     if (verbose != 0) {
1119         mbedtls_printf("\n");
1120     }
1121 
1122     return ret;
1123 }
1124 
1125 #undef TEST_ASSERT
1126 
1127 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1128 
1129 #endif /* MBEDTLS_SELF_TEST */
1130 
1131 #endif /* MBEDTLS_ECJPAKE_C */
1132