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