• 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     size_t i;
971 
972     (void) ctx;
973 
974     for( i = 0; i < len; i++ )
975     {
976         state = state * 1664525u + 1013904223u;
977         out[i] = (unsigned char) state;
978     }
979 
980     return( 0 );
981 }
982 
983 /* 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)984 static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
985                               const unsigned char *xm1, size_t len1,
986                               const unsigned char *xm2, size_t len2 )
987 {
988     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
989 
990     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
991     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
992     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
993                                       &ctx->grp.G, self_test_rng, NULL ) );
994     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
995                                       &ctx->grp.G, self_test_rng, NULL ) );
996 
997 cleanup:
998     return( ret );
999 }
1000 
1001 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1002 
1003 /* For tests we don't need a secure RNG;
1004  * use the LGC from Numerical Recipes for simplicity */
ecjpake_lgc(void * p,unsigned char * out,size_t len)1005 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1006 {
1007     static uint32_t x = 42;
1008     (void) p;
1009 
1010     while( len > 0 )
1011     {
1012         size_t use_len = len > 4 ? 4 : len;
1013         x = 1664525 * x + 1013904223;
1014         memcpy( out, &x, use_len );
1015         out += use_len;
1016         len -= use_len;
1017     }
1018 
1019     return( 0 );
1020 }
1021 
1022 #define TEST_ASSERT( x )    \
1023     do {                    \
1024         if( x )             \
1025             ret = 0;        \
1026         else                \
1027         {                   \
1028             ret = 1;        \
1029             goto cleanup;   \
1030         }                   \
1031     } while( 0 )
1032 
1033 /*
1034  * Checkup routine
1035  */
mbedtls_ecjpake_self_test(int verbose)1036 int mbedtls_ecjpake_self_test( int verbose )
1037 {
1038     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1039     mbedtls_ecjpake_context cli;
1040     mbedtls_ecjpake_context srv;
1041     unsigned char buf[512], pms[32];
1042     size_t len, pmslen;
1043 
1044     mbedtls_ecjpake_init( &cli );
1045     mbedtls_ecjpake_init( &srv );
1046 
1047     if( verbose != 0 )
1048         mbedtls_printf( "  ECJPAKE test #0 (setup): " );
1049 
1050     TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
1051                     MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1052                     ecjpake_test_password,
1053             sizeof( ecjpake_test_password ) ) == 0 );
1054 
1055     TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
1056                     MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1057                     ecjpake_test_password,
1058             sizeof( ecjpake_test_password ) ) == 0 );
1059 
1060     if( verbose != 0 )
1061         mbedtls_printf( "passed\n" );
1062 
1063     if( verbose != 0 )
1064         mbedtls_printf( "  ECJPAKE test #1 (random handshake): " );
1065 
1066     TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
1067                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1068 
1069     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
1070 
1071     TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
1072                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1073 
1074     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
1075 
1076     TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
1077                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1078 
1079     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
1080 
1081     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
1082                  pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1083 
1084     TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
1085                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1086 
1087     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
1088 
1089     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
1090                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1091 
1092     TEST_ASSERT( len == pmslen );
1093     TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1094 
1095     if( verbose != 0 )
1096         mbedtls_printf( "passed\n" );
1097 
1098 #if !defined(MBEDTLS_ECJPAKE_ALT)
1099     /* 'reference handshake' tests can only be run against implementations
1100      * for which we have 100% control over how the random ephemeral keys
1101      * are generated. This is only the case for the internal mbed TLS
1102      * implementation, so these tests are skipped in case the internal
1103      * implementation is swapped out for an alternative one. */
1104     if( verbose != 0 )
1105         mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
1106 
1107     /* Simulate generation of round one */
1108     MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1109                 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
1110                 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
1111 
1112     MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1113                 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
1114                 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
1115 
1116     /* Read round one */
1117     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1118                                     ecjpake_test_cli_one,
1119                             sizeof( ecjpake_test_cli_one ) ) == 0 );
1120 
1121     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
1122                                     ecjpake_test_srv_one,
1123                             sizeof( ecjpake_test_srv_one ) ) == 0 );
1124 
1125     /* Skip generation of round two, read round two */
1126     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
1127                                     ecjpake_test_srv_two,
1128                             sizeof( ecjpake_test_srv_two ) ) == 0 );
1129 
1130     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
1131                                     ecjpake_test_cli_two,
1132                             sizeof( ecjpake_test_cli_two ) ) == 0 );
1133 
1134     /* Server derives PMS */
1135     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
1136                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1137 
1138     TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1139     TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1140 
1141     memset( buf, 0, len ); /* Avoid interferences with next step */
1142 
1143     /* Client derives PMS */
1144     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
1145                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1146 
1147     TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1148     TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1149 
1150     if( verbose != 0 )
1151         mbedtls_printf( "passed\n" );
1152 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1153 
1154 cleanup:
1155     mbedtls_ecjpake_free( &cli );
1156     mbedtls_ecjpake_free( &srv );
1157 
1158     if( ret != 0 )
1159     {
1160         if( verbose != 0 )
1161             mbedtls_printf( "failed\n" );
1162 
1163         ret = 1;
1164     }
1165 
1166     if( verbose != 0 )
1167         mbedtls_printf( "\n" );
1168 
1169     return( ret );
1170 }
1171 
1172 #undef TEST_ASSERT
1173 
1174 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1175 
1176 #endif /* MBEDTLS_SELF_TEST */
1177 
1178 #endif /* MBEDTLS_ECJPAKE_C */
1179