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