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