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