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