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