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