mbedtls_pk_get_psa_attributes: ECC support
Add code and unit tests for MBEDTLS_PK_ECxxx in
mbedtls_pk_get_psa_attributes().
This commit only supports built-in ECC (MBEDTLS_ECP_C). A subsequent commit
will handle driver-only ECC.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/library/pk.c b/library/pk.c
index 1485bd7..432fbcf 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -406,22 +406,28 @@
{
mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
+ psa_key_usage_t more_usage = usage;
+ if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) {
+ more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
+ } else if (usage == PSA_KEY_USAGE_SIGN_HASH) {
+ more_usage |= PSA_KEY_USAGE_VERIFY_HASH;
+ } else if (usage == PSA_KEY_USAGE_DECRYPT) {
+ more_usage |= PSA_KEY_USAGE_ENCRYPT;
+ }
+ more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
+
switch (pk_type) {
#if defined(MBEDTLS_RSA_C)
case MBEDTLS_PK_RSA:
+ {
int want_crypt = 0;
int want_private = 0;
switch (usage) {
case PSA_KEY_USAGE_SIGN_MESSAGE:
- usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
- want_private = 1;
- break;
case PSA_KEY_USAGE_SIGN_HASH:
- usage |= PSA_KEY_USAGE_VERIFY_HASH;
want_private = 1;
break;
case PSA_KEY_USAGE_DECRYPT:
- usage |= PSA_KEY_USAGE_ENCRYPT;
want_private = 1;
want_crypt = 1;
break;
@@ -448,8 +454,61 @@
psa_set_key_algorithm(attributes,
psa_algorithm_for_rsa(rsa, want_crypt));
break;
+ }
#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ case MBEDTLS_PK_ECKEY:
+ case MBEDTLS_PK_ECKEY_DH:
+ case MBEDTLS_PK_ECDSA:
+ {
+ int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH);
+ int derive_ok = (pk_type != MBEDTLS_PK_ECDSA);
+ mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
+ int has_private = (ec->d.n != 0);
+ size_t bits = 0;
+ psa_ecc_family_t family =
+ mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
+ int want_private = 0;
+ psa_algorithm_t alg = 0;
+ switch (usage) {
+ case PSA_KEY_USAGE_SIGN_MESSAGE:
+ case PSA_KEY_USAGE_SIGN_HASH:
+ want_private = 1;
+ /* FALLTHROUGH */
+ case PSA_KEY_USAGE_VERIFY_MESSAGE:
+ case PSA_KEY_USAGE_VERIFY_HASH:
+ if (!sign_ok) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
+#else
+ alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
+#endif
+ break;
+ case PSA_KEY_USAGE_DERIVE:
+ want_private = 1;
+ alg = PSA_ALG_ECDH;
+ if (!derive_ok) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ break;
+ default:
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ if (want_private && !has_private) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ psa_set_key_type(attributes, (want_private ?
+ PSA_KEY_TYPE_ECC_KEY_PAIR(family) :
+ PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)));
+ psa_set_key_bits(attributes, bits);
+ psa_set_key_algorithm(attributes, alg);
+ break;
+ }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
case MBEDTLS_PK_RSA_ALT:
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
@@ -459,8 +518,7 @@
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
- usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
- psa_set_key_usage_flags(attributes, usage);
+ psa_set_key_usage_flags(attributes, more_usage);
#if defined(MBEDTLS_PSA_CRYPTO_C)
/* Assume that we have all Mbed TLS attributes. When
* MBEDTLS_PSA_CRYPTO_CLIENT is enabled but not MBEDTLS_PSA_CRYPTO_C,