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