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 */ 40 static 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 90 psa_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; 189 exit: 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 209 psa_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); 243 exit: 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 251 psa_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 290 psa_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) 320 psa_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_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( 325 attributes->type); 326 mbedtls_ecp_group_id grp_id = 327 mbedtls_ecc_group_from_psa(curve, attributes->bits); 328 if (grp_id == MBEDTLS_ECP_DP_NONE) { 329 return PSA_ERROR_NOT_SUPPORTED; 330 } 331 332 mbedtls_ecp_keypair ecp; 333 mbedtls_ecp_keypair_init(&ecp); 334 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 335 336 ret = mbedtls_ecp_group_load(&ecp.grp, grp_id); 337 if (ret != 0) { 338 goto exit; 339 } 340 341 ret = mbedtls_ecp_gen_privkey(&ecp.grp, &ecp.d, 342 mbedtls_psa_get_random, 343 MBEDTLS_PSA_RANDOM_STATE); 344 if (ret != 0) { 345 goto exit; 346 } 347 348 ret = mbedtls_ecp_write_key_ext(&ecp, key_buffer_length, 349 key_buffer, key_buffer_size); 350 351 exit: 352 mbedtls_ecp_keypair_free(&ecp); 353 return mbedtls_to_psa_error(ret); 354 } 355 #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ 356 357 /****************************************************************/ 358 /* ECDSA sign/verify */ 359 /****************************************************************/ 360 361 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ 362 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) 363 psa_status_t mbedtls_psa_ecdsa_sign_hash( 364 const psa_key_attributes_t *attributes, 365 const uint8_t *key_buffer, size_t key_buffer_size, 366 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, 367 uint8_t *signature, size_t signature_size, size_t *signature_length) 368 { 369 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 370 mbedtls_ecp_keypair *ecp = NULL; 371 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 372 size_t curve_bytes; 373 mbedtls_mpi r, s; 374 375 status = mbedtls_psa_ecp_load_representation(attributes->type, 376 attributes->bits, 377 key_buffer, 378 key_buffer_size, 379 &ecp); 380 if (status != PSA_SUCCESS) { 381 return status; 382 } 383 384 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); 385 mbedtls_mpi_init(&r); 386 mbedtls_mpi_init(&s); 387 388 if (signature_size < 2 * curve_bytes) { 389 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; 390 goto cleanup; 391 } 392 393 if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) { 394 #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) 395 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); 396 mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); 397 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext( 398 &ecp->grp, &r, &s, 399 &ecp->d, hash, 400 hash_length, md_alg, 401 mbedtls_psa_get_random, 402 MBEDTLS_PSA_RANDOM_STATE)); 403 #else 404 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 405 goto cleanup; 406 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ 407 } else { 408 (void) alg; 409 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d, 410 hash, hash_length, 411 mbedtls_psa_get_random, 412 MBEDTLS_PSA_RANDOM_STATE)); 413 } 414 415 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r, 416 signature, 417 curve_bytes)); 418 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s, 419 signature + curve_bytes, 420 curve_bytes)); 421 cleanup: 422 mbedtls_mpi_free(&r); 423 mbedtls_mpi_free(&s); 424 if (ret == 0) { 425 *signature_length = 2 * curve_bytes; 426 } 427 428 mbedtls_ecp_keypair_free(ecp); 429 mbedtls_free(ecp); 430 431 return mbedtls_to_psa_error(ret); 432 } 433 434 psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp) 435 { 436 int ret = 0; 437 438 /* Check whether the public part is loaded. If not, load it. */ 439 if (mbedtls_ecp_is_zero(&ecp->Q)) { 440 ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q, 441 &ecp->d, &ecp->grp.G, 442 mbedtls_psa_get_random, 443 MBEDTLS_PSA_RANDOM_STATE); 444 } 445 446 return mbedtls_to_psa_error(ret); 447 } 448 449 psa_status_t mbedtls_psa_ecdsa_verify_hash( 450 const psa_key_attributes_t *attributes, 451 const uint8_t *key_buffer, size_t key_buffer_size, 452 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, 453 const uint8_t *signature, size_t signature_length) 454 { 455 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 456 mbedtls_ecp_keypair *ecp = NULL; 457 size_t curve_bytes; 458 mbedtls_mpi r, s; 459 460 (void) alg; 461 462 status = mbedtls_psa_ecp_load_representation(attributes->type, 463 attributes->bits, 464 key_buffer, 465 key_buffer_size, 466 &ecp); 467 if (status != PSA_SUCCESS) { 468 return status; 469 } 470 471 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); 472 mbedtls_mpi_init(&r); 473 mbedtls_mpi_init(&s); 474 475 if (signature_length != 2 * curve_bytes) { 476 status = PSA_ERROR_INVALID_SIGNATURE; 477 goto cleanup; 478 } 479 480 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r, 481 signature, 482 curve_bytes)); 483 if (status != PSA_SUCCESS) { 484 goto cleanup; 485 } 486 487 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s, 488 signature + curve_bytes, 489 curve_bytes)); 490 if (status != PSA_SUCCESS) { 491 goto cleanup; 492 } 493 494 status = mbedtls_psa_ecp_load_public_part(ecp); 495 if (status != PSA_SUCCESS) { 496 goto cleanup; 497 } 498 499 status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash, 500 hash_length, &ecp->Q, 501 &r, &s)); 502 cleanup: 503 mbedtls_mpi_free(&r); 504 mbedtls_mpi_free(&s); 505 mbedtls_ecp_keypair_free(ecp); 506 mbedtls_free(ecp); 507 508 return status; 509 } 510 511 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ 512 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ 513 514 /****************************************************************/ 515 /* ECDH Key Agreement */ 516 /****************************************************************/ 517 518 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) 519 psa_status_t mbedtls_psa_key_agreement_ecdh( 520 const psa_key_attributes_t *attributes, 521 const uint8_t *key_buffer, size_t key_buffer_size, 522 psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, 523 uint8_t *shared_secret, size_t shared_secret_size, 524 size_t *shared_secret_length) 525 { 526 psa_status_t status; 527 if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) || 528 !PSA_ALG_IS_ECDH(alg)) { 529 return PSA_ERROR_INVALID_ARGUMENT; 530 } 531 mbedtls_ecp_keypair *ecp = NULL; 532 status = mbedtls_psa_ecp_load_representation( 533 attributes->type, 534 attributes->bits, 535 key_buffer, 536 key_buffer_size, 537 &ecp); 538 if (status != PSA_SUCCESS) { 539 return status; 540 } 541 mbedtls_ecp_keypair *their_key = NULL; 542 mbedtls_ecdh_context ecdh; 543 size_t bits = 0; 544 psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits); 545 mbedtls_ecdh_init(&ecdh); 546 547 status = mbedtls_psa_ecp_load_representation( 548 PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), 549 bits, 550 peer_key, 551 peer_key_length, 552 &their_key); 553 if (status != PSA_SUCCESS) { 554 goto exit; 555 } 556 557 status = mbedtls_to_psa_error( 558 mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); 559 if (status != PSA_SUCCESS) { 560 goto exit; 561 } 562 status = mbedtls_to_psa_error( 563 mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS)); 564 if (status != PSA_SUCCESS) { 565 goto exit; 566 } 567 568 status = mbedtls_to_psa_error( 569 mbedtls_ecdh_calc_secret(&ecdh, 570 shared_secret_length, 571 shared_secret, shared_secret_size, 572 mbedtls_psa_get_random, 573 MBEDTLS_PSA_RANDOM_STATE)); 574 if (status != PSA_SUCCESS) { 575 goto exit; 576 } 577 if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { 578 status = PSA_ERROR_CORRUPTION_DETECTED; 579 } 580 exit: 581 if (status != PSA_SUCCESS) { 582 mbedtls_platform_zeroize(shared_secret, shared_secret_size); 583 } 584 mbedtls_ecdh_free(&ecdh); 585 mbedtls_ecp_keypair_free(their_key); 586 mbedtls_free(their_key); 587 mbedtls_ecp_keypair_free(ecp); 588 mbedtls_free(ecp); 589 return status; 590 } 591 #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ 592 593 594 #endif /* MBEDTLS_PSA_CRYPTO_C */ 595