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