1 /* 2 * ECC setters for PK. 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 8 #include "common.h" 9 10 #include "mbedtls/pk.h" 11 #include "mbedtls/error.h" 12 #include "mbedtls/ecp.h" 13 #include "pk_internal.h" 14 15 #if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS) 16 17 int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id) 18 { 19 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) 20 size_t ec_bits; 21 psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits); 22 23 /* group may already be initialized; if so, make sure IDs match */ 24 if ((pk->ec_family != 0 && pk->ec_family != ec_family) || 25 (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) { 26 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 27 } 28 29 /* set group */ 30 pk->ec_family = ec_family; 31 pk->ec_bits = ec_bits; 32 33 return 0; 34 #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ 35 mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk); 36 37 /* grp may already be initialized; if so, make sure IDs match */ 38 if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE && 39 mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) { 40 return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; 41 } 42 43 /* set group */ 44 return mbedtls_ecp_group_load(&(ecp->grp), grp_id); 45 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ 46 } 47 48 int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len) 49 { 50 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) 51 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 52 psa_key_usage_t flags; 53 psa_status_t status; 54 55 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); 56 if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) { 57 /* Do not set algorithm here because Montgomery keys cannot do ECDSA and 58 * the PK module cannot do ECDH. When the key will be used in TLS for 59 * ECDH, it will be exported and then re-imported with proper flags 60 * and algorithm. */ 61 flags = PSA_KEY_USAGE_EXPORT; 62 } else { 63 psa_set_key_algorithm(&attributes, 64 MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH)); 65 flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | 66 PSA_KEY_USAGE_EXPORT; 67 } 68 psa_set_key_usage_flags(&attributes, flags); 69 70 status = psa_import_key(&attributes, key, key_len, &pk->priv_id); 71 return psa_pk_status_to_mbedtls(status); 72 73 #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ 74 75 mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); 76 int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len); 77 if (ret != 0) { 78 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); 79 } 80 return 0; 81 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ 82 } 83 84 int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, 85 const unsigned char *prv, size_t prv_len, 86 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) 87 { 88 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) 89 90 (void) f_rng; 91 (void) p_rng; 92 (void) prv; 93 (void) prv_len; 94 psa_status_t status; 95 96 status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw), 97 &pk->pub_raw_len); 98 return psa_pk_status_to_mbedtls(status); 99 100 #elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */ 101 102 (void) f_rng; 103 (void) p_rng; 104 psa_status_t status; 105 106 mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; 107 size_t curve_bits; 108 psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits); 109 110 /* Import private key into PSA, from serialized input */ 111 mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; 112 psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; 113 psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); 114 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); 115 status = psa_import_key(&key_attr, prv, prv_len, &key_id); 116 if (status != PSA_SUCCESS) { 117 return psa_pk_status_to_mbedtls(status); 118 } 119 120 /* Export public key from PSA */ 121 unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; 122 size_t pub_len; 123 status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len); 124 psa_status_t destruction_status = psa_destroy_key(key_id); 125 if (status != PSA_SUCCESS) { 126 return psa_pk_status_to_mbedtls(status); 127 } else if (destruction_status != PSA_SUCCESS) { 128 return psa_pk_status_to_mbedtls(destruction_status); 129 } 130 131 /* Load serialized public key into ecp_keypair structure */ 132 return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len); 133 134 #else /* MBEDTLS_USE_PSA_CRYPTO */ 135 136 (void) prv; 137 (void) prv_len; 138 139 mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; 140 return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng); 141 142 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 143 } 144 145 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) 146 /* 147 * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case. 148 * 149 * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA 150 * functions to handle keys. However, currently psa_import_key() does not 151 * support compressed points. In case that support was explicitly requested, 152 * this fallback uses ECP functions to get the job done. This is the reason 153 * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT. 154 * 155 * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group(). 156 * out: will have the public key set. 157 * [in] pub, pub_len: the public key as an ECPoint, 158 * in any format supported by ECP. 159 * 160 * Return: 161 * - 0 on success; 162 * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid 163 * but not supported; 164 * - another error code otherwise. 165 */ 166 static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk, 167 const unsigned char *pub, 168 size_t pub_len) 169 { 170 #if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) 171 (void) pk; 172 (void) pub; 173 (void) pub_len; 174 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 175 #else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ 176 mbedtls_ecp_keypair ecp_key; 177 mbedtls_ecp_group_id ecp_group_id; 178 int ret; 179 180 ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); 181 182 mbedtls_ecp_keypair_init(&ecp_key); 183 ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id); 184 if (ret != 0) { 185 goto exit; 186 } 187 ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q, 188 pub, pub_len); 189 if (ret != 0) { 190 goto exit; 191 } 192 ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q, 193 MBEDTLS_ECP_PF_UNCOMPRESSED, 194 &pk->pub_raw_len, pk->pub_raw, 195 sizeof(pk->pub_raw)); 196 197 exit: 198 mbedtls_ecp_keypair_free(&ecp_key); 199 return ret; 200 #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ 201 } 202 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ 203 204 int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len) 205 { 206 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) 207 208 /* Load the key */ 209 if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) { 210 /* Format directly supported by PSA: 211 * - non-Weierstrass curves that only have one format; 212 * - uncompressed format for Weierstrass curves. */ 213 if (pub_len > sizeof(pk->pub_raw)) { 214 return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; 215 } 216 memcpy(pk->pub_raw, pub, pub_len); 217 pk->pub_raw_len = pub_len; 218 } else { 219 /* Other format, try the fallback */ 220 int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len); 221 if (ret != 0) { 222 return ret; 223 } 224 } 225 226 /* Validate the key by trying to import it */ 227 mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; 228 psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; 229 230 psa_set_key_usage_flags(&key_attrs, 0); 231 psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)); 232 psa_set_key_bits(&key_attrs, pk->ec_bits); 233 234 if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len, 235 &key_id) != PSA_SUCCESS) || 236 (psa_destroy_key(key_id) != PSA_SUCCESS)) { 237 return MBEDTLS_ERR_PK_INVALID_PUBKEY; 238 } 239 240 return 0; 241 242 #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ 243 244 int ret; 245 mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx; 246 ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len); 247 if (ret != 0) { 248 return ret; 249 } 250 return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q); 251 252 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ 253 } 254 255 #endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */ 256