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