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