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