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