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