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 )
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 static const unsigned char ecjpake_test_x1[] = {
824     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
825     0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
826     0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
827 };
828 
829 static const unsigned char ecjpake_test_x2[] = {
830     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
831     0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
832     0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
833 };
834 
835 static const unsigned char ecjpake_test_x3[] = {
836     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
837     0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
838     0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
839 };
840 
841 static const unsigned char ecjpake_test_x4[] = {
842     0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
843     0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
844     0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
845 };
846 
847 static const unsigned char ecjpake_test_cli_one[] = {
848     0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
849     0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
850     0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
851     0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
852     0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
853     0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
854     0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
855     0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
856     0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
857     0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
858     0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
859     0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
860     0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
861     0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
862     0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
863     0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
864     0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
865     0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
866     0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
867     0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
868     0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
869     0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
870     0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
871     0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
872     0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
873     0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
874     0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
875     0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
876 };
877 
878 static const unsigned char ecjpake_test_srv_one[] = {
879     0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
880     0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
881     0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
882     0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
883     0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
884     0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
885     0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
886     0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
887     0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
888     0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
889     0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
890     0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
891     0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
892     0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
893     0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
894     0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
895     0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
896     0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
897     0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
898     0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
899     0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
900     0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
901     0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
902     0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
903     0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
904     0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
905     0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
906     0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
907 };
908 
909 static const unsigned char ecjpake_test_srv_two[] = {
910     0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
911     0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
912     0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
913     0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
914     0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
915     0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
916     0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
917     0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
918     0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
919     0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
920     0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
921     0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
922     0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
923     0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
924 };
925 
926 static const unsigned char ecjpake_test_cli_two[] = {
927     0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
928     0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
929     0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
930     0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
931     0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
932     0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
933     0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
934     0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
935     0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
936     0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
937     0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
938     0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
939     0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
940     0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
941 };
942 
943 static const unsigned char ecjpake_test_pms[] = {
944     0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
945     0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
946     0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
947 };
948 
949 /* 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)950 static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
951                               const unsigned char *xm1, size_t len1,
952                               const unsigned char *xm2, size_t len2 )
953 {
954     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
955 
956     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
957     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
958     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
959                                       &ctx->grp.G, NULL, NULL ) );
960     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
961                                       &ctx->grp.G, NULL, NULL ) );
962 
963 cleanup:
964     return( ret );
965 }
966 
967 /* For tests we don't need a secure RNG;
968  * use the LGC from Numerical Recipes for simplicity */
ecjpake_lgc(void * p,unsigned char * out,size_t len)969 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
970 {
971     static uint32_t x = 42;
972     (void) p;
973 
974     while( len > 0 )
975     {
976         size_t use_len = len > 4 ? 4 : len;
977         x = 1664525 * x + 1013904223;
978         memcpy( out, &x, use_len );
979         out += use_len;
980         len -= use_len;
981     }
982 
983     return( 0 );
984 }
985 
986 #define TEST_ASSERT( x )    \
987     do {                    \
988         if( x )             \
989             ret = 0;        \
990         else                \
991         {                   \
992             ret = 1;        \
993             goto cleanup;   \
994         }                   \
995     } while( 0 )
996 
997 /*
998  * Checkup routine
999  */
mbedtls_ecjpake_self_test(int verbose)1000 int mbedtls_ecjpake_self_test( int verbose )
1001 {
1002     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1003     mbedtls_ecjpake_context cli;
1004     mbedtls_ecjpake_context srv;
1005     unsigned char buf[512], pms[32];
1006     size_t len, pmslen;
1007 
1008     mbedtls_ecjpake_init( &cli );
1009     mbedtls_ecjpake_init( &srv );
1010 
1011     if( verbose != 0 )
1012         mbedtls_printf( "  ECJPAKE test #0 (setup): " );
1013 
1014     TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
1015                     MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1016                     ecjpake_test_password,
1017             sizeof( ecjpake_test_password ) ) == 0 );
1018 
1019     TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
1020                     MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1021                     ecjpake_test_password,
1022             sizeof( ecjpake_test_password ) ) == 0 );
1023 
1024     if( verbose != 0 )
1025         mbedtls_printf( "passed\n" );
1026 
1027     if( verbose != 0 )
1028         mbedtls_printf( "  ECJPAKE test #1 (random handshake): " );
1029 
1030     TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
1031                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1032 
1033     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
1034 
1035     TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
1036                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1037 
1038     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
1039 
1040     TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
1041                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1042 
1043     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
1044 
1045     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
1046                  pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1047 
1048     TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
1049                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1050 
1051     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
1052 
1053     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
1054                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1055 
1056     TEST_ASSERT( len == pmslen );
1057     TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1058 
1059     if( verbose != 0 )
1060         mbedtls_printf( "passed\n" );
1061 
1062     if( verbose != 0 )
1063         mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
1064 
1065     /* Simulate generation of round one */
1066     MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1067                 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
1068                 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
1069 
1070     MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1071                 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
1072                 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
1073 
1074     /* Read round one */
1075     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1076                                     ecjpake_test_cli_one,
1077                             sizeof( ecjpake_test_cli_one ) ) == 0 );
1078 
1079     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
1080                                     ecjpake_test_srv_one,
1081                             sizeof( ecjpake_test_srv_one ) ) == 0 );
1082 
1083     /* Skip generation of round two, read round two */
1084     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
1085                                     ecjpake_test_srv_two,
1086                             sizeof( ecjpake_test_srv_two ) ) == 0 );
1087 
1088     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
1089                                     ecjpake_test_cli_two,
1090                             sizeof( ecjpake_test_cli_two ) ) == 0 );
1091 
1092     /* Server derives PMS */
1093     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
1094                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1095 
1096     TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1097     TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1098 
1099     memset( buf, 0, len ); /* Avoid interferences with next step */
1100 
1101     /* Client derives PMS */
1102     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
1103                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1104 
1105     TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1106     TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1107 
1108     if( verbose != 0 )
1109         mbedtls_printf( "passed\n" );
1110 
1111 cleanup:
1112     mbedtls_ecjpake_free( &cli );
1113     mbedtls_ecjpake_free( &srv );
1114 
1115     if( ret != 0 )
1116     {
1117         if( verbose != 0 )
1118             mbedtls_printf( "failed\n" );
1119 
1120         ret = 1;
1121     }
1122 
1123     if( verbose != 0 )
1124         mbedtls_printf( "\n" );
1125 
1126     return( ret );
1127 }
1128 
1129 #undef TEST_ASSERT
1130 
1131 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1132 
1133 #endif /* MBEDTLS_SELF_TEST */
1134 
1135 #endif /* MBEDTLS_ECJPAKE_C */
1136