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