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