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