2 * Elliptic curve J-PAKE
\r
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
\r
5 * SPDX-License-Identifier: Apache-2.0
\r
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
\r
8 * not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
\r
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
19 * This file is part of mbed TLS (https://tls.mbed.org)
\r
23 * References in the code are to the Thread v1.0 Specification,
\r
24 * available to members of the Thread Group http://threadgroup.org/
\r
27 #if !defined(MBEDTLS_CONFIG_FILE)
\r
28 #include "mbedtls/config.h"
\r
30 #include MBEDTLS_CONFIG_FILE
\r
33 #if defined(MBEDTLS_ECJPAKE_C)
\r
35 #include "mbedtls/ecjpake.h"
\r
36 #include "mbedtls/platform_util.h"
\r
40 #if !defined(MBEDTLS_ECJPAKE_ALT)
\r
42 /* Parameter validation macros based on platform_util.h */
\r
43 #define ECJPAKE_VALIDATE_RET( cond ) \
\r
44 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
\r
45 #define ECJPAKE_VALIDATE( cond ) \
\r
46 MBEDTLS_INTERNAL_VALIDATE( cond )
\r
49 * Convert a mbedtls_ecjpake_role to identifier string
\r
51 static const char * const ecjpake_id[] = {
\r
56 #define ID_MINE ( ecjpake_id[ ctx->role ] )
\r
57 #define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
\r
60 * Initialize context
\r
62 void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
\r
64 ECJPAKE_VALIDATE( ctx != NULL );
\r
66 ctx->md_info = NULL;
\r
67 mbedtls_ecp_group_init( &ctx->grp );
\r
68 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
\r
70 mbedtls_ecp_point_init( &ctx->Xm1 );
\r
71 mbedtls_ecp_point_init( &ctx->Xm2 );
\r
72 mbedtls_ecp_point_init( &ctx->Xp1 );
\r
73 mbedtls_ecp_point_init( &ctx->Xp2 );
\r
74 mbedtls_ecp_point_init( &ctx->Xp );
\r
76 mbedtls_mpi_init( &ctx->xm1 );
\r
77 mbedtls_mpi_init( &ctx->xm2 );
\r
78 mbedtls_mpi_init( &ctx->s );
\r
84 void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
\r
89 ctx->md_info = NULL;
\r
90 mbedtls_ecp_group_free( &ctx->grp );
\r
92 mbedtls_ecp_point_free( &ctx->Xm1 );
\r
93 mbedtls_ecp_point_free( &ctx->Xm2 );
\r
94 mbedtls_ecp_point_free( &ctx->Xp1 );
\r
95 mbedtls_ecp_point_free( &ctx->Xp2 );
\r
96 mbedtls_ecp_point_free( &ctx->Xp );
\r
98 mbedtls_mpi_free( &ctx->xm1 );
\r
99 mbedtls_mpi_free( &ctx->xm2 );
\r
100 mbedtls_mpi_free( &ctx->s );
\r
106 int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
\r
107 mbedtls_ecjpake_role role,
\r
108 mbedtls_md_type_t hash,
\r
109 mbedtls_ecp_group_id curve,
\r
110 const unsigned char *secret,
\r
115 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
116 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
\r
117 role == MBEDTLS_ECJPAKE_SERVER );
\r
118 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
\r
122 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
\r
123 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
\r
125 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
\r
127 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
\r
131 mbedtls_ecjpake_free( ctx );
\r
137 * Check if context is ready for use
\r
139 int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
\r
141 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
143 if( ctx->md_info == NULL ||
\r
144 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
\r
147 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
\r
154 * Write a point plus its length to a buffer
\r
156 static int ecjpake_write_len_point( unsigned char **p,
\r
157 const unsigned char *end,
\r
158 const mbedtls_ecp_group *grp,
\r
160 const mbedtls_ecp_point *P )
\r
165 /* Need at least 4 for length plus 1 for point */
\r
166 if( end < *p || end - *p < 5 )
\r
167 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
\r
169 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
\r
170 &len, *p + 4, end - ( *p + 4 ) );
\r
174 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
\r
175 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
\r
176 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
\r
177 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
\r
185 * Size of the temporary buffer for ecjpake_hash:
\r
186 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
\r
188 #define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
\r
191 * Compute hash for ZKP (7.4.2.2.2.1)
\r
193 static int ecjpake_hash( const mbedtls_md_info_t *md_info,
\r
194 const mbedtls_ecp_group *grp,
\r
196 const mbedtls_ecp_point *G,
\r
197 const mbedtls_ecp_point *V,
\r
198 const mbedtls_ecp_point *X,
\r
203 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
\r
204 unsigned char *p = buf;
\r
205 const unsigned char *end = buf + sizeof( buf );
\r
206 const size_t id_len = strlen( id );
\r
207 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
\r
209 /* Write things to temporary buffer */
\r
210 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
\r
211 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
\r
212 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
\r
215 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
\r
217 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
\r
218 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
\r
219 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
\r
220 *p++ = (unsigned char)( ( id_len ) & 0xFF );
\r
222 if( end < p || (size_t)( end - p ) < id_len )
\r
223 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
\r
225 memcpy( p, id, id_len );
\r
229 mbedtls_md( md_info, buf, p - buf, hash );
\r
231 /* Turn it into an integer mod n */
\r
232 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
\r
233 mbedtls_md_get_size( md_info ) ) );
\r
234 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
\r
241 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
\r
243 static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
\r
244 const mbedtls_ecp_group *grp,
\r
246 const mbedtls_ecp_point *G,
\r
247 const mbedtls_ecp_point *X,
\r
249 const unsigned char **p,
\r
250 const unsigned char *end )
\r
253 mbedtls_ecp_point V, VV;
\r
257 mbedtls_ecp_point_init( &V );
\r
258 mbedtls_ecp_point_init( &VV );
\r
259 mbedtls_mpi_init( &r );
\r
260 mbedtls_mpi_init( &h );
\r
265 * opaque r<1..2^8-1>;
\r
269 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
\r
271 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
\r
273 if( end < *p || (size_t)( end - *p ) < 1 )
\r
275 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
\r
281 if( end < *p || (size_t)( end - *p ) < r_len )
\r
283 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
\r
287 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
\r
293 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
\r
294 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
\r
295 &VV, &h, X, &r, G ) );
\r
297 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
\r
299 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
\r
304 mbedtls_ecp_point_free( &V );
\r
305 mbedtls_ecp_point_free( &VV );
\r
306 mbedtls_mpi_free( &r );
\r
307 mbedtls_mpi_free( &h );
\r
313 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
\r
315 static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
\r
316 const mbedtls_ecp_group *grp,
\r
318 const mbedtls_ecp_point *G,
\r
319 const mbedtls_mpi *x,
\r
320 const mbedtls_ecp_point *X,
\r
323 const unsigned char *end,
\r
324 int (*f_rng)(void *, unsigned char *, size_t),
\r
328 mbedtls_ecp_point V;
\r
330 mbedtls_mpi h; /* later recycled to hold r */
\r
334 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
\r
336 mbedtls_ecp_point_init( &V );
\r
337 mbedtls_mpi_init( &v );
\r
338 mbedtls_mpi_init( &h );
\r
340 /* Compute signature */
\r
341 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
\r
342 G, &v, &V, f_rng, p_rng ) );
\r
343 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
\r
344 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
\r
345 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
\r
346 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
\r
349 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
\r
350 pf, &len, *p, end - *p ) );
\r
353 len = mbedtls_mpi_size( &h ); /* actually r */
\r
354 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
\r
356 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
\r
360 *(*p)++ = (unsigned char)( len & 0xFF );
\r
361 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
\r
365 mbedtls_ecp_point_free( &V );
\r
366 mbedtls_mpi_free( &v );
\r
367 mbedtls_mpi_free( &h );
\r
373 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
\r
374 * Output: verified public key X
\r
376 static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
\r
377 const mbedtls_ecp_group *grp,
\r
379 const mbedtls_ecp_point *G,
\r
380 mbedtls_ecp_point *X,
\r
382 const unsigned char **p,
\r
383 const unsigned char *end )
\r
388 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
\r
393 * ECSchnorrZKP zkp;
\r
396 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
\r
397 if( mbedtls_ecp_is_zero( X ) )
\r
399 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
\r
403 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
\r
410 * Generate an ECJPAKEKeyKP
\r
411 * Output: the serialized structure, plus private/public key pair
\r
413 static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
\r
414 const mbedtls_ecp_group *grp,
\r
416 const mbedtls_ecp_point *G,
\r
418 mbedtls_ecp_point *X,
\r
421 const unsigned char *end,
\r
422 int (*f_rng)(void *, unsigned char *, size_t),
\r
429 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
\r
431 /* Generate key (7.4.2.3.1) and write it out */
\r
432 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
\r
434 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
\r
435 pf, &len, *p, end - *p ) );
\r
438 /* Generate and write proof */
\r
439 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
\r
440 p, end, f_rng, p_rng ) );
\r
447 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
\r
448 * Ouputs: verified peer public keys Xa, Xb
\r
450 static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
\r
451 const mbedtls_ecp_group *grp,
\r
453 const mbedtls_ecp_point *G,
\r
454 mbedtls_ecp_point *Xa,
\r
455 mbedtls_ecp_point *Xb,
\r
457 const unsigned char *buf,
\r
461 const unsigned char *p = buf;
\r
462 const unsigned char *end = buf + len;
\r
466 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
\r
467 * } ECJPAKEKeyKPPairList;
\r
469 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
\r
470 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
\r
473 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
\r
480 * Generate a ECJPAKEKeyKPPairList
\r
481 * Outputs: the serialized structure, plus two private/public key pairs
\r
483 static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
\r
484 const mbedtls_ecp_group *grp,
\r
486 const mbedtls_ecp_point *G,
\r
488 mbedtls_ecp_point *Xa,
\r
490 mbedtls_ecp_point *Xb,
\r
492 unsigned char *buf,
\r
495 int (*f_rng)(void *, unsigned char *, size_t),
\r
499 unsigned char *p = buf;
\r
500 const unsigned char *end = buf + len;
\r
502 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
\r
503 &p, end, f_rng, p_rng ) );
\r
504 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
\r
505 &p, end, f_rng, p_rng ) );
\r
514 * Read and process the first round message
\r
516 int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
\r
517 const unsigned char *buf,
\r
520 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
521 ECJPAKE_VALIDATE_RET( buf != NULL );
\r
523 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
\r
525 &ctx->Xp1, &ctx->Xp2, ID_PEER,
\r
530 * Generate and write the first round message
\r
532 int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
\r
533 unsigned char *buf, size_t len, size_t *olen,
\r
534 int (*f_rng)(void *, unsigned char *, size_t),
\r
537 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
538 ECJPAKE_VALIDATE_RET( buf != NULL );
\r
539 ECJPAKE_VALIDATE_RET( olen != NULL );
\r
540 ECJPAKE_VALIDATE_RET( f_rng != NULL );
\r
542 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
\r
544 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
\r
545 ID_MINE, buf, len, olen, f_rng, p_rng ) );
\r
549 * Compute the sum of three points R = A + B + C
\r
551 static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
\r
552 const mbedtls_ecp_point *A,
\r
553 const mbedtls_ecp_point *B,
\r
554 const mbedtls_ecp_point *C )
\r
559 mbedtls_mpi_init( &one );
\r
561 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
\r
562 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
\r
563 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
\r
566 mbedtls_mpi_free( &one );
\r
572 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
\r
574 int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
\r
575 const unsigned char *buf,
\r
579 const unsigned char *p = buf;
\r
580 const unsigned char *end = buf + len;
\r
581 mbedtls_ecp_group grp;
\r
582 mbedtls_ecp_point G; /* C: GB, S: GA */
\r
584 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
585 ECJPAKE_VALIDATE_RET( buf != NULL );
\r
587 mbedtls_ecp_group_init( &grp );
\r
588 mbedtls_ecp_point_init( &G );
\r
591 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
\r
592 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
\r
593 * Unified: G = Xm1 + Xm2 + Xp1
\r
594 * We need that before parsing in order to check Xp as we read it
\r
596 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
\r
597 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
\r
601 * ECParameters curve_params; // only client reading server msg
\r
602 * ECJPAKEKeyKP ecjpake_key_kp;
\r
603 * } Client/ServerECJPAKEParams;
\r
605 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
\r
607 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
\r
608 if( grp.id != ctx->grp.id )
\r
610 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
\r
615 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
\r
617 &G, &ctx->Xp, ID_PEER, &p, end ) );
\r
621 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
\r
626 mbedtls_ecp_group_free( &grp );
\r
627 mbedtls_ecp_point_free( &G );
\r
633 * Compute R = +/- X * S mod N, taking care not to leak S
\r
635 static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
\r
636 const mbedtls_mpi *X,
\r
637 const mbedtls_mpi *S,
\r
638 const mbedtls_mpi *N,
\r
639 int (*f_rng)(void *, unsigned char *, size_t),
\r
643 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
\r
645 mbedtls_mpi_init( &b );
\r
647 /* b = s + rnd-128-bit * N */
\r
648 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
\r
649 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
\r
650 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
\r
652 /* R = sign * X * b mod N */
\r
653 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
\r
655 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
\r
658 mbedtls_mpi_free( &b );
\r
664 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
\r
666 int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
\r
667 unsigned char *buf, size_t len, size_t *olen,
\r
668 int (*f_rng)(void *, unsigned char *, size_t),
\r
672 mbedtls_ecp_point G; /* C: GA, S: GB */
\r
673 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
\r
674 mbedtls_mpi xm; /* C: xc, S: xs */
\r
675 unsigned char *p = buf;
\r
676 const unsigned char *end = buf + len;
\r
679 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
680 ECJPAKE_VALIDATE_RET( buf != NULL );
\r
681 ECJPAKE_VALIDATE_RET( olen != NULL );
\r
682 ECJPAKE_VALIDATE_RET( f_rng != NULL );
\r
684 mbedtls_ecp_point_init( &G );
\r
685 mbedtls_ecp_point_init( &Xm );
\r
686 mbedtls_mpi_init( &xm );
\r
689 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
\r
691 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
\r
692 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
\r
693 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
\r
695 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
\r
696 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
\r
697 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
\r
698 &ctx->grp.N, f_rng, p_rng ) );
\r
699 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
\r
702 * Now write things out
\r
705 * ECParameters curve_params; // only server writing its message
\r
706 * ECJPAKEKeyKP ecjpake_key_kp;
\r
707 * } Client/ServerECJPAKEParams;
\r
709 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
\r
713 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
\r
716 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
\r
723 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
\r
726 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
\r
727 ctx->point_format, &ec_len, p, end - p ) );
\r
730 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
\r
732 &G, &xm, &Xm, ID_MINE,
\r
733 &p, end, f_rng, p_rng ) );
\r
738 mbedtls_ecp_point_free( &G );
\r
739 mbedtls_ecp_point_free( &Xm );
\r
740 mbedtls_mpi_free( &xm );
\r
746 * Derive PMS (7.4.2.7 / 7.4.2.8)
\r
748 int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
\r
749 unsigned char *buf, size_t len, size_t *olen,
\r
750 int (*f_rng)(void *, unsigned char *, size_t),
\r
754 mbedtls_ecp_point K;
\r
755 mbedtls_mpi m_xm2_s, one;
\r
756 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
\r
759 ECJPAKE_VALIDATE_RET( ctx != NULL );
\r
760 ECJPAKE_VALIDATE_RET( buf != NULL );
\r
761 ECJPAKE_VALIDATE_RET( olen != NULL );
\r
762 ECJPAKE_VALIDATE_RET( f_rng != NULL );
\r
764 *olen = mbedtls_md_get_size( ctx->md_info );
\r
766 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
\r
768 mbedtls_ecp_point_init( &K );
\r
769 mbedtls_mpi_init( &m_xm2_s );
\r
770 mbedtls_mpi_init( &one );
\r
772 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
\r
775 * Client: K = ( Xs - X4 * x2 * s ) * x2
\r
776 * Server: K = ( Xc - X2 * x4 * s ) * x4
\r
777 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
\r
779 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
\r
780 &ctx->grp.N, f_rng, p_rng ) );
\r
781 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
\r
783 &m_xm2_s, &ctx->Xp2 ) );
\r
784 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
\r
787 /* PMS = SHA-256( K.X ) */
\r
788 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
\r
789 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
\r
790 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
\r
793 mbedtls_ecp_point_free( &K );
\r
794 mbedtls_mpi_free( &m_xm2_s );
\r
795 mbedtls_mpi_free( &one );
\r
803 #endif /* ! MBEDTLS_ECJPAKE_ALT */
\r
805 #if defined(MBEDTLS_SELF_TEST)
\r
807 #if defined(MBEDTLS_PLATFORM_C)
\r
808 #include "mbedtls/platform.h"
\r
811 #define mbedtls_printf printf
\r
814 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
\r
815 !defined(MBEDTLS_SHA256_C)
\r
816 int mbedtls_ecjpake_self_test( int verbose )
\r
823 static const unsigned char ecjpake_test_password[] = {
\r
824 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
\r
828 static const unsigned char ecjpake_test_x1[] = {
\r
829 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
\r
830 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
\r
831 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
\r
834 static const unsigned char ecjpake_test_x2[] = {
\r
835 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
\r
836 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
\r
837 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
\r
840 static const unsigned char ecjpake_test_x3[] = {
\r
841 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
\r
842 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
\r
843 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
\r
846 static const unsigned char ecjpake_test_x4[] = {
\r
847 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
\r
848 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
\r
849 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
\r
852 static const unsigned char ecjpake_test_cli_one[] = {
\r
853 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
\r
854 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
\r
855 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
\r
856 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
\r
857 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
\r
858 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
\r
859 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
\r
860 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
\r
861 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
\r
862 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
\r
863 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
\r
864 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
\r
865 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
\r
866 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
\r
867 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
\r
868 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
\r
869 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
\r
870 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
\r
871 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
\r
872 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
\r
873 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
\r
874 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
\r
875 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
\r
876 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
\r
877 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
\r
878 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
\r
879 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
\r
880 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
\r
883 static const unsigned char ecjpake_test_srv_one[] = {
\r
884 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
\r
885 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
\r
886 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
\r
887 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
\r
888 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
\r
889 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
\r
890 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
\r
891 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
\r
892 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
\r
893 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
\r
894 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
\r
895 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
\r
896 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
\r
897 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
\r
898 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
\r
899 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
\r
900 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
\r
901 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
\r
902 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
\r
903 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
\r
904 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
\r
905 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
\r
906 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
\r
907 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
\r
908 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
\r
909 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
\r
910 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
\r
911 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
\r
914 static const unsigned char ecjpake_test_srv_two[] = {
\r
915 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
\r
916 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
\r
917 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
\r
918 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
\r
919 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
\r
920 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
\r
921 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
\r
922 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
\r
923 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
\r
924 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
\r
925 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
\r
926 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
\r
927 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
\r
928 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
\r
931 static const unsigned char ecjpake_test_cli_two[] = {
\r
932 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
\r
933 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
\r
934 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
\r
935 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
\r
936 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
\r
937 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
\r
938 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
\r
939 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
\r
940 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
\r
941 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
\r
942 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
\r
943 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
\r
944 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
\r
945 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
\r
948 static const unsigned char ecjpake_test_pms[] = {
\r
949 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
\r
950 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
\r
951 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
\r
954 /* Load my private keys and generate the corresponding public keys */
\r
955 static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
\r
956 const unsigned char *xm1, size_t len1,
\r
957 const unsigned char *xm2, size_t len2 )
\r
961 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
\r
962 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
\r
963 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
\r
964 &ctx->grp.G, NULL, NULL ) );
\r
965 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
\r
966 &ctx->grp.G, NULL, NULL ) );
\r
972 /* For tests we don't need a secure RNG;
\r
973 * use the LGC from Numerical Recipes for simplicity */
\r
974 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
\r
976 static uint32_t x = 42;
\r
981 size_t use_len = len > 4 ? 4 : len;
\r
982 x = 1664525 * x + 1013904223;
\r
983 memcpy( out, &x, use_len );
\r
991 #define TEST_ASSERT( x ) \
\r
1005 int mbedtls_ecjpake_self_test( int verbose )
\r
1008 mbedtls_ecjpake_context cli;
\r
1009 mbedtls_ecjpake_context srv;
\r
1010 unsigned char buf[512], pms[32];
\r
1011 size_t len, pmslen;
\r
1013 mbedtls_ecjpake_init( &cli );
\r
1014 mbedtls_ecjpake_init( &srv );
\r
1016 if( verbose != 0 )
\r
1017 mbedtls_printf( " ECJPAKE test #0 (setup): " );
\r
1019 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
\r
1020 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
\r
1021 ecjpake_test_password,
\r
1022 sizeof( ecjpake_test_password ) ) == 0 );
\r
1024 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
\r
1025 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
\r
1026 ecjpake_test_password,
\r
1027 sizeof( ecjpake_test_password ) ) == 0 );
\r
1029 if( verbose != 0 )
\r
1030 mbedtls_printf( "passed\n" );
\r
1032 if( verbose != 0 )
\r
1033 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
\r
1035 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
\r
1036 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1038 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
\r
1040 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
\r
1041 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1043 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
\r
1045 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
\r
1046 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1048 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
\r
1050 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
\r
1051 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
\r
1053 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
\r
1054 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1056 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
\r
1058 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
\r
1059 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1061 TEST_ASSERT( len == pmslen );
\r
1062 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
\r
1064 if( verbose != 0 )
\r
1065 mbedtls_printf( "passed\n" );
\r
1067 if( verbose != 0 )
\r
1068 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
\r
1070 /* Simulate generation of round one */
\r
1071 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
\r
1072 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
\r
1073 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
\r
1075 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
\r
1076 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
\r
1077 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
\r
1079 /* Read round one */
\r
1080 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
\r
1081 ecjpake_test_cli_one,
\r
1082 sizeof( ecjpake_test_cli_one ) ) == 0 );
\r
1084 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
\r
1085 ecjpake_test_srv_one,
\r
1086 sizeof( ecjpake_test_srv_one ) ) == 0 );
\r
1088 /* Skip generation of round two, read round two */
\r
1089 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
\r
1090 ecjpake_test_srv_two,
\r
1091 sizeof( ecjpake_test_srv_two ) ) == 0 );
\r
1093 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
\r
1094 ecjpake_test_cli_two,
\r
1095 sizeof( ecjpake_test_cli_two ) ) == 0 );
\r
1097 /* Server derives PMS */
\r
1098 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
\r
1099 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1101 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
\r
1102 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
\r
1104 memset( buf, 0, len ); /* Avoid interferences with next step */
\r
1106 /* Client derives PMS */
\r
1107 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
\r
1108 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
\r
1110 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
\r
1111 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
\r
1113 if( verbose != 0 )
\r
1114 mbedtls_printf( "passed\n" );
\r
1117 mbedtls_ecjpake_free( &cli );
\r
1118 mbedtls_ecjpake_free( &srv );
\r
1122 if( verbose != 0 )
\r
1123 mbedtls_printf( "failed\n" );
\r
1128 if( verbose != 0 )
\r
1129 mbedtls_printf( "\n" );
\r
1134 #undef TEST_ASSERT
\r
1136 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
\r
1138 #endif /* MBEDTLS_SELF_TEST */
\r
1140 #endif /* MBEDTLS_ECJPAKE_C */
\r