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