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