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