1/* 2 * PSA ECP layer on top of Mbed TLS crypto 3 */ 4/* 5 * Copyright The Mbed TLS Contributors 6 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 7 */ 8 9#include "common.h" 10 11#if defined(MBEDTLS_PSA_CRYPTO_C) 12 13#include <psa/crypto.h> 14#include "psa_crypto_core.h" 15#include "psa_crypto_ecp.h" 16#include "psa_crypto_random_impl.h" 17#include "mbedtls/psa_util.h" 18 19#include <stdlib.h> 20#include <string.h> 21#include "mbedtls/platform.h" 22 23#include <mbedtls/ecdsa.h> 24#include <mbedtls/ecdh.h> 25#include <mbedtls/ecp.h> 26#include <mbedtls/error.h> 27 28#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ 29 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ 30 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ 31 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ 32 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ 33 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ 34 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) 35/* Helper function to verify if the provided EC's family and key bit size are valid. 36 * 37 * Note: "bits" parameter is used both as input and output and it might be updated 38 * in case provided input value is not multiple of 8 ("sloppy" bits). 39 */ 40static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits) 41{ 42 switch (family) { 43 case PSA_ECC_FAMILY_SECP_R1: 44 switch (*bits) { 45 case 192: 46 case 224: 47 case 256: 48 case 384: 49 case 521: 50 return PSA_SUCCESS; 51 case 528: 52 *bits = 521; 53 return PSA_SUCCESS; 54 } 55 break; 56 57 case PSA_ECC_FAMILY_BRAINPOOL_P_R1: 58 switch (*bits) { 59 case 256: 60 case 384: 61 case 512: 62 return PSA_SUCCESS; 63 } 64 break; 65 66 case PSA_ECC_FAMILY_MONTGOMERY: 67 switch (*bits) { 68 case 448: 69 case 255: 70 return PSA_SUCCESS; 71 case 256: 72 *bits = 255; 73 return PSA_SUCCESS; 74 } 75 break; 76 77 case PSA_ECC_FAMILY_SECP_K1: 78 switch (*bits) { 79 case 192: 80 /* secp224k1 is not and will not be supported in PSA (#3541). */ 81 case 256: 82 return PSA_SUCCESS; 83 } 84 break; 85 } 86 87 return PSA_ERROR_INVALID_ARGUMENT; 88} 89 90psa_status_t mbedtls_psa_ecp_load_representation( 91 psa_key_type_t type, size_t curve_bits, 92 const uint8_t *data, size_t data_length, 93 mbedtls_ecp_keypair **p_ecp) 94{ 95 mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; 96 psa_status_t status; 97 mbedtls_ecp_keypair *ecp = NULL; 98 size_t curve_bytes = data_length; 99 int explicit_bits = (curve_bits != 0); 100 101 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && 102 PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) { 103 /* A Weierstrass public key is represented as: 104 * - The byte 0x04; 105 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; 106 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. 107 * So its data length is 2m+1 where m is the curve size in bits. 108 */ 109 if ((data_length & 1) == 0) { 110 return PSA_ERROR_INVALID_ARGUMENT; 111 } 112 curve_bytes = data_length / 2; 113 114 /* Montgomery public keys are represented in compressed format, meaning 115 * their curve_bytes is equal to the amount of input. */ 116 117 /* Private keys are represented in uncompressed private random integer 118 * format, meaning their curve_bytes is equal to the amount of input. */ 119 } 120 121 if (explicit_bits) { 122 /* With an explicit bit-size, the data must have the matching length. */ 123 if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) { 124 return PSA_ERROR_INVALID_ARGUMENT; 125 } 126 } else { 127 /* We need to infer the bit-size from the data. Since the only 128 * information we have is the length in bytes, the value of curve_bits 129 * at this stage is rounded up to the nearest multiple of 8. */ 130 curve_bits = PSA_BYTES_TO_BITS(curve_bytes); 131 } 132 133 /* Allocate and initialize a key representation. */ 134 ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); 135 if (ecp == NULL) { 136 return PSA_ERROR_INSUFFICIENT_MEMORY; 137 } 138 mbedtls_ecp_keypair_init(ecp); 139 140 status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits); 141 if (status != PSA_SUCCESS) { 142 goto exit; 143 } 144 145 /* Load the group. */ 146 grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), 147 curve_bits); 148 if (grp_id == MBEDTLS_ECP_DP_NONE) { 149 status = PSA_ERROR_NOT_SUPPORTED; 150 goto exit; 151 } 152 153 status = mbedtls_to_psa_error( 154 mbedtls_ecp_group_load(&ecp->grp, grp_id)); 155 if (status != PSA_SUCCESS) { 156 goto exit; 157 } 158 159 /* Load the key material. */ 160 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { 161 /* Load the public value. */ 162 status = mbedtls_to_psa_error( 163 mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q, 164 data, 165 data_length)); 166 if (status != PSA_SUCCESS) { 167 goto exit; 168 } 169 170 /* Check that the point is on the curve. */ 171 status = mbedtls_to_psa_error( 172 mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q)); 173 if (status != PSA_SUCCESS) { 174 goto exit; 175 } 176 } else { 177 /* Load and validate the secret value. */ 178 status = mbedtls_to_psa_error( 179 mbedtls_ecp_read_key(ecp->grp.id, 180 ecp, 181 data, 182 data_length)); 183 if (status != PSA_SUCCESS) { 184 goto exit; 185 } 186 } 187 188 *p_ecp = ecp; 189exit: 190 if (status != PSA_SUCCESS) { 191 mbedtls_ecp_keypair_free(ecp); 192 mbedtls_free(ecp); 193 } 194 195 return status; 196} 197#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || 198 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || 199 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || 200 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || 201 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || 202 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || 203 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ 204 205#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ 206 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ 207 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) 208 209psa_status_t mbedtls_psa_ecp_import_key( 210 const psa_key_attributes_t *attributes, 211 const uint8_t *data, size_t data_length, 212 uint8_t *key_buffer, size_t key_buffer_size, 213 size_t *key_buffer_length, size_t *bits) 214{ 215 psa_status_t status; 216 mbedtls_ecp_keypair *ecp = NULL; 217 218 /* Parse input */ 219 status = mbedtls_psa_ecp_load_representation(attributes->type, 220 attributes->bits, 221 data, 222 data_length, 223 &ecp); 224 if (status != PSA_SUCCESS) { 225 goto exit; 226 } 227 228 if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) == 229 PSA_ECC_FAMILY_MONTGOMERY) { 230 *bits = ecp->grp.nbits + 1; 231 } else { 232 *bits = ecp->grp.nbits; 233 } 234 235 /* Re-export the data to PSA export format. There is currently no support 236 * for other input formats then the export format, so this is a 1-1 237 * copy operation. */ 238 status = mbedtls_psa_ecp_export_key(attributes->type, 239 ecp, 240 key_buffer, 241 key_buffer_size, 242 key_buffer_length); 243exit: 244 /* Always free the PK object (will also free contained ECP context) */ 245 mbedtls_ecp_keypair_free(ecp); 246 mbedtls_free(ecp); 247 248 return status; 249} 250 251psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, 252 mbedtls_ecp_keypair *ecp, 253 uint8_t *data, 254 size_t data_size, 255 size_t *data_length) 256{ 257 psa_status_t status; 258 259 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { 260 /* Check whether the public part is loaded */ 261 if (mbedtls_ecp_is_zero(&ecp->Q)) { 262 /* Calculate the public key */ 263 status = mbedtls_to_psa_error( 264 mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, 265 mbedtls_psa_get_random, 266 MBEDTLS_PSA_RANDOM_STATE)); 267 if (status != PSA_SUCCESS) { 268 return status; 269 } 270 } 271 272 status = mbedtls_to_psa_error( 273 mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q, 274 MBEDTLS_ECP_PF_UNCOMPRESSED, 275 data_length, 276 data, 277 data_size)); 278 if (status != PSA_SUCCESS) { 279 memset(data, 0, data_size); 280 } 281 282 return status; 283 } else { 284 status = mbedtls_to_psa_error( 285 mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size)); 286 return status; 287 } 288} 289 290psa_status_t mbedtls_psa_ecp_export_public_key( 291 const psa_key_attributes_t *attributes, 292 const uint8_t *key_buffer, size_t key_buffer_size, 293 uint8_t *data, size_t data_size, size_t *data_length) 294{ 295 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 296 mbedtls_ecp_keypair *ecp = NULL; 297 298 status = mbedtls_psa_ecp_load_representation( 299 attributes->type, attributes->bits, 300 key_buffer, key_buffer_size, &ecp); 301 if (status != PSA_SUCCESS) { 302 return status; 303 } 304 305 status = mbedtls_psa_ecp_export_key( 306 PSA_KEY_TYPE_ECC_PUBLIC_KEY( 307 PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)), 308 ecp, data, data_size, data_length); 309 310 mbedtls_ecp_keypair_free(ecp); 311 mbedtls_free(ecp); 312 313 return status; 314} 315#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || 316 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || 317 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ 318 319#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) 320psa_status_t mbedtls_psa_ecp_generate_key( 321 const psa_key_attributes_t *attributes, 322 uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) 323{ 324 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 325 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 326 327 psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( 328 attributes->type); 329 mbedtls_ecp_group_id grp_id = 330 mbedtls_ecc_group_from_psa(curve, attributes->bits); 331 332 const mbedtls_ecp_curve_info *curve_info = 333 mbedtls_ecp_curve_info_from_grp_id(grp_id); 334 mbedtls_ecp_keypair ecp; 335 336 if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) { 337 return PSA_ERROR_NOT_SUPPORTED; 338 } 339 340 mbedtls_ecp_keypair_init(&ecp); 341 ret = mbedtls_ecp_gen_key(grp_id, &ecp, 342 mbedtls_psa_get_random, 343 MBEDTLS_PSA_RANDOM_STATE); 344 if (ret != 0) { 345 mbedtls_ecp_keypair_free(&ecp); 346 return mbedtls_to_psa_error(ret); 347 } 348 349 status = mbedtls_to_psa_error( 350 mbedtls_ecp_write_key_ext(&ecp, key_buffer_length, 351 key_buffer, key_buffer_size)); 352 353 mbedtls_ecp_keypair_free(&ecp); 354 355 return status; 356} 357#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ 358 359/****************************************************************/ 360/* ECDSA sign/verify */ 361/****************************************************************/ 362 363#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ 364 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) 365psa_status_t mbedtls_psa_ecdsa_sign_hash( 366 const psa_key_attributes_t *attributes, 367 const uint8_t *key_buffer, size_t key_buffer_size, 368 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, 369 uint8_t *signature, size_t signature_size, size_t *signature_length) 370{ 371 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 372 mbedtls_ecp_keypair *ecp = NULL; 373 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 374 size_t curve_bytes; 375 mbedtls_mpi r, s; 376 377 status = mbedtls_psa_ecp_load_representation(attributes->type, 378 attributes->bits, 379 key_buffer, 380 key_buffer_size, 381 &ecp); 382 if (status != PSA_SUCCESS) { 383 return status; 384 } 385 386 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); 387 mbedtls_mpi_init(&r); 388 mbedtls_mpi_init(&s); 389 390 if (signature_size < 2 * curve_bytes) { 391 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; 392 goto cleanup; 393 } 394 395 if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) { 396#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) 397 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); 398 mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); 399 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext( 400 &ecp->grp, &r, &s, 401 &ecp->d, hash, 402 hash_length, md_alg, 403 mbedtls_psa_get_random, 404 MBEDTLS_PSA_RANDOM_STATE)); 405#else 406 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 407 goto cleanup; 408#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ 409 } else { 410 (void) alg; 411 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d, 412 hash, hash_length, 413 mbedtls_psa_get_random, 414 MBEDTLS_PSA_RANDOM_STATE)); 415 } 416 417 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r, 418 signature, 419 curve_bytes)); 420 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s, 421 signature + curve_bytes, 422 curve_bytes)); 423cleanup: 424 mbedtls_mpi_free(&r); 425 mbedtls_mpi_free(&s); 426 if (ret == 0) { 427 *signature_length = 2 * curve_bytes; 428 } 429 430 mbedtls_ecp_keypair_free(ecp); 431 mbedtls_free(ecp); 432 433 return mbedtls_to_psa_error(ret); 434} 435 436psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp) 437{ 438 int ret = 0; 439 440 /* Check whether the public part is loaded. If not, load it. */ 441 if (mbedtls_ecp_is_zero(&ecp->Q)) { 442 ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q, 443 &ecp->d, &ecp->grp.G, 444 mbedtls_psa_get_random, 445 MBEDTLS_PSA_RANDOM_STATE); 446 } 447 448 return mbedtls_to_psa_error(ret); 449} 450 451psa_status_t mbedtls_psa_ecdsa_verify_hash( 452 const psa_key_attributes_t *attributes, 453 const uint8_t *key_buffer, size_t key_buffer_size, 454 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, 455 const uint8_t *signature, size_t signature_length) 456{ 457 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 458 mbedtls_ecp_keypair *ecp = NULL; 459 size_t curve_bytes; 460 mbedtls_mpi r, s; 461 462 (void) alg; 463 464 status = mbedtls_psa_ecp_load_representation(attributes->type, 465 attributes->bits, 466 key_buffer, 467 key_buffer_size, 468 &ecp); 469 if (status != PSA_SUCCESS) { 470 return status; 471 } 472 473 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); 474 mbedtls_mpi_init(&r); 475 mbedtls_mpi_init(&s); 476 477 if (signature_length != 2 * curve_bytes) { 478 status = PSA_ERROR_INVALID_SIGNATURE; 479 goto cleanup; 480 } 481 482 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r, 483 signature, 484 curve_bytes)); 485 if (status != PSA_SUCCESS) { 486 goto cleanup; 487 } 488 489 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s, 490 signature + curve_bytes, 491 curve_bytes)); 492 if (status != PSA_SUCCESS) { 493 goto cleanup; 494 } 495 496 status = mbedtls_psa_ecp_load_public_part(ecp); 497 if (status != PSA_SUCCESS) { 498 goto cleanup; 499 } 500 501 status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash, 502 hash_length, &ecp->Q, 503 &r, &s)); 504cleanup: 505 mbedtls_mpi_free(&r); 506 mbedtls_mpi_free(&s); 507 mbedtls_ecp_keypair_free(ecp); 508 mbedtls_free(ecp); 509 510 return status; 511} 512 513#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ 514 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ 515 516/****************************************************************/ 517/* ECDH Key Agreement */ 518/****************************************************************/ 519 520#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) 521psa_status_t mbedtls_psa_key_agreement_ecdh( 522 const psa_key_attributes_t *attributes, 523 const uint8_t *key_buffer, size_t key_buffer_size, 524 psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, 525 uint8_t *shared_secret, size_t shared_secret_size, 526 size_t *shared_secret_length) 527{ 528 psa_status_t status; 529 if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) || 530 !PSA_ALG_IS_ECDH(alg)) { 531 return PSA_ERROR_INVALID_ARGUMENT; 532 } 533 mbedtls_ecp_keypair *ecp = NULL; 534 status = mbedtls_psa_ecp_load_representation( 535 attributes->type, 536 attributes->bits, 537 key_buffer, 538 key_buffer_size, 539 &ecp); 540 if (status != PSA_SUCCESS) { 541 return status; 542 } 543 mbedtls_ecp_keypair *their_key = NULL; 544 mbedtls_ecdh_context ecdh; 545 size_t bits = 0; 546 psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits); 547 mbedtls_ecdh_init(&ecdh); 548 549 status = mbedtls_psa_ecp_load_representation( 550 PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), 551 bits, 552 peer_key, 553 peer_key_length, 554 &their_key); 555 if (status != PSA_SUCCESS) { 556 goto exit; 557 } 558 559 status = mbedtls_to_psa_error( 560 mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); 561 if (status != PSA_SUCCESS) { 562 goto exit; 563 } 564 status = mbedtls_to_psa_error( 565 mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS)); 566 if (status != PSA_SUCCESS) { 567 goto exit; 568 } 569 570 status = mbedtls_to_psa_error( 571 mbedtls_ecdh_calc_secret(&ecdh, 572 shared_secret_length, 573 shared_secret, shared_secret_size, 574 mbedtls_psa_get_random, 575 MBEDTLS_PSA_RANDOM_STATE)); 576 if (status != PSA_SUCCESS) { 577 goto exit; 578 } 579 if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { 580 status = PSA_ERROR_CORRUPTION_DETECTED; 581 } 582exit: 583 if (status != PSA_SUCCESS) { 584 mbedtls_platform_zeroize(shared_secret, shared_secret_size); 585 } 586 mbedtls_ecdh_free(&ecdh); 587 mbedtls_ecp_keypair_free(their_key); 588 mbedtls_free(their_key); 589 mbedtls_ecp_keypair_free(ecp); 590 mbedtls_free(ecp); 591 return status; 592} 593#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ 594 595 596#endif /* MBEDTLS_PSA_CRYPTO_C */ 597