From 586aa4ddac83efffc5f9da5e44ec940a49344ee9 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Fri, 19 Jun 2026 12:59:55 +0200 Subject: [PATCH] net: sockets: tls: support PSA-resident private keys Add a TLS_CREDENTIAL_PRIVATE_KEY_PSA credential type so a private key already resident in PSA can be referenced by its psa_key_id_t instead of being supplied as exported key material. When this credential type is used, the TLS socket builds an opaque Mbed TLS PK context with mbedtls_pk_wrap_psa() rather than parsing raw key bytes. As a result the private key never leaves PSA: handshake signatures are performed through psa_sign_hash(). This enables flows where the key is generated on-device (non-exportable, stored in ITS) and used for TLS client authentication without ever exporting it. The credential buffer holds a psa_key_id_t; the public certificate is still registered as TLS_CREDENTIAL_PUBLIC_CERTIFICATE and paired with the opaque key by sec tag, unchanged. Assisted-by: Claude:claude-opus-4.8 Signed-off-by: Pavel Vasilyev --- include/zephyr/net/tls_credentials.h | 12 ++- subsys/net/lib/sockets/sockets_tls.c | 87 +++++++++++++++++++ .../tls_credentials/tls_credentials_shell.c | 3 + 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/include/zephyr/net/tls_credentials.h b/include/zephyr/net/tls_credentials.h index ee762566b5c66..d967f25cc5dc8 100644 --- a/include/zephyr/net/tls_credentials.h +++ b/include/zephyr/net/tls_credentials.h @@ -57,7 +57,17 @@ enum tls_credential_type { /** Pre-shared key identity. Should be registered together with a * corresponding PSK. Used with PSK-based ciphersuites. */ - TLS_CREDENTIAL_PSK_ID + TLS_CREDENTIAL_PSK_ID, + + /** Private key resident in PSA. The credential buffer holds a + * @c psa_key_id_t referencing a key already present in PSA (for example + * one generated on-device with @c psa_generate_key()), not the key + * material itself. The key never leaves PSA: handshake signatures are + * performed through @c psa_sign_hash(). Should be registered together + * with a corresponding public certificate, in place of + * @ref TLS_CREDENTIAL_PRIVATE_KEY. + */ + TLS_CREDENTIAL_PRIVATE_KEY_PSA }; /** Secure tag, a reference to TLS credential diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index c2e3b688bfa86..cc7c52dcc105d 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -42,6 +42,14 @@ LOG_MODULE_REGISTER(net_sock_tls, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include +#include +#if defined(MBEDTLS_PSA_CRYPTO_C) || defined(MBEDTLS_PSA_CRYPTO_CLIENT) +#include +/* Support for referencing a private key resident in PSA (TLS_CREDENTIAL_PRIVATE_KEY_PSA), + * so that the key material never has to be exported into the credential store. + */ +#define TLS_PRIV_KEY_PSA_ENABLED 1 +#endif #endif /* CONFIG_MBEDTLS */ #include "sockets_internal.h" @@ -1565,6 +1573,39 @@ static int tls_set_private_key(struct tls_context *tls, return -ENOTSUP; } +static int tls_set_private_key_psa(struct tls_context *tls, + struct tls_credential *priv_key) +{ +#if defined(CONFIG_MBEDTLS_X509_CRT_PARSE_C) && defined(TLS_PRIV_KEY_PSA_ENABLED) + psa_key_id_t key_id; + mbedtls_svc_key_id_t svc_key_id; + int err; + + if (priv_key->len != sizeof(key_id)) { + return -EINVAL; + } + + memcpy(&key_id, priv_key->buf, sizeof(key_id)); + + /* The private key lives in PSA and is never exported - we only hold its + * key id. Wrap that id into an opaque PK context (mbedtls_pk_wrap_psa) + * so mbedTLS delegates every signature back to PSA instead of needing + * the raw key. mbedtls_pk_wrap_psa() takes an mbedtls_svc_key_id_t, so + * build one from the key id with owner 0 (the local/default owner). + */ + svc_key_id = mbedtls_svc_key_id_make(0, key_id); + + err = mbedtls_pk_wrap_psa(&tls->priv_key, svc_key_id); + if (err != 0) { + return -EINVAL; + } + + return 0; +#else + return -ENOTSUP; +#endif /* CONFIG_MBEDTLS_X509_CRT_PARSE_C && TLS_PRIV_KEY_PSA_ENABLED */ +} + static int tls_set_psk(struct tls_context *tls, struct tls_credential *psk, struct tls_credential *psk_id) @@ -1598,6 +1639,10 @@ static int tls_set_credential(struct tls_context *tls, return tls_set_private_key(tls, cred); break; + case TLS_CREDENTIAL_PRIVATE_KEY_PSA: + return tls_set_private_key_psa(tls, cred); + break; + case TLS_CREDENTIAL_PSK: { struct tls_credential *psk_id = @@ -2079,6 +2124,41 @@ static int tls_check_priv_key(struct tls_credential *priv_key) #endif /* CONFIG_MBEDTLS_X509_CRT_PARSE_C */ } +static int tls_check_private_key_psa(struct tls_credential *priv_key) +{ +#if defined(CONFIG_MBEDTLS_X509_CRT_PARSE_C) && defined(TLS_PRIV_KEY_PSA_ENABLED) + psa_key_id_t key_id; + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + if (priv_key->len != sizeof(key_id)) { + NET_ERR("Bad PSA key id length on tag %d", priv_key->tag); + return -EINVAL; + } + + memcpy(&key_id, priv_key->buf, sizeof(key_id)); + + /* Validate that the referenced key exists and is usable, without + * touching the key material. + */ + status = psa_get_key_attributes(key_id, &attr); + if (status != PSA_SUCCESS) { + NET_ERR("PSA key %u not found for tag %d, status: %d", + key_id, priv_key->tag, status); + return -EINVAL; + } + + psa_reset_key_attributes(&attr); + + return 0; +#else + NET_ERR("TLS with PSA-resident private keys disabled. " + "Reconfigure mbed TLS to support PSA crypto."); + + return -ENOTSUP; +#endif /* CONFIG_MBEDTLS_X509_CRT_PARSE_C && TLS_PRIV_KEY_PSA_ENABLED */ +} + static int tls_check_psk(struct tls_credential *psk) { #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) @@ -2134,6 +2214,13 @@ static int tls_check_credentials(const sec_tag_t *sec_tags, int sec_tag_count) goto exit; } + break; + case TLS_CREDENTIAL_PRIVATE_KEY_PSA: + err = tls_check_private_key_psa(cred); + if (err != 0) { + goto exit; + } + break; case TLS_CREDENTIAL_PSK: err = tls_check_psk(cred); diff --git a/subsys/net/lib/tls_credentials/tls_credentials_shell.c b/subsys/net/lib/tls_credentials/tls_credentials_shell.c index 9736715d477a9..373c352b6edd9 100644 --- a/subsys/net/lib/tls_credentials/tls_credentials_shell.c +++ b/subsys/net/lib/tls_credentials/tls_credentials_shell.c @@ -50,6 +50,9 @@ static const struct cred_type_string type_strings[] = { {"PRIVATE_KEY", TLS_CREDENTIAL_PRIVATE_KEY}, {"PK", TLS_CREDENTIAL_PRIVATE_KEY}, + {"PRIVATE_KEY_PSA", TLS_CREDENTIAL_PRIVATE_KEY_PSA}, + {"PK_PSA", TLS_CREDENTIAL_PRIVATE_KEY_PSA}, + {"PRE_SHARED_KEY", TLS_CREDENTIAL_PSK}, {"PSK", TLS_CREDENTIAL_PSK},