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