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