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