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