Skip to content

Commit 8bfaafb

Browse files
PavelVPVclaude
andcommitted
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. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
1 parent ac744d4 commit 8bfaafb

2 files changed

Lines changed: 98 additions & 1 deletion

File tree

include/zephyr/net/tls_credentials.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,17 @@ enum tls_credential_type {
5757
/** Pre-shared key identity. Should be registered together with a
5858
* corresponding PSK. Used with PSK-based ciphersuites.
5959
*/
60-
TLS_CREDENTIAL_PSK_ID
60+
TLS_CREDENTIAL_PSK_ID,
61+
62+
/** Private key resident in PSA. The credential buffer holds a
63+
* @c psa_key_id_t referencing a key already present in PSA (for example
64+
* one generated on-device with @c psa_generate_key()), not the key
65+
* material itself. The key never leaves PSA: handshake signatures are
66+
* performed through @c psa_sign_hash(). Should be registered together
67+
* with a corresponding public certificate, in place of
68+
* @ref TLS_CREDENTIAL_PRIVATE_KEY.
69+
*/
70+
TLS_CREDENTIAL_PRIVATE_KEY_PSA
6171
};
6272

6373
/** Secure tag, a reference to TLS credential

subsys/net/lib/sockets/sockets_tls.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ LOG_MODULE_REGISTER(net_sock_tls, CONFIG_NET_SOCKETS_LOG_LEVEL);
4242
#include <mbedtls/error.h>
4343
#include <mbedtls/platform.h>
4444
#include <mbedtls/ssl_cache.h>
45+
#include <mbedtls/pk.h>
46+
#if defined(MBEDTLS_PSA_CRYPTO_C) || defined(MBEDTLS_PSA_CRYPTO_CLIENT)
47+
#include <psa/crypto.h>
48+
/* Support for referencing a private key resident in PSA (TLS_CREDENTIAL_PRIVATE_KEY_PSA),
49+
* so that the key material never has to be exported into the credential store.
50+
*/
51+
#define TLS_PRIV_KEY_PSA_ENABLED 1
52+
#endif
4553
#endif /* CONFIG_MBEDTLS */
4654

4755
#include "sockets_internal.h"
@@ -1565,6 +1573,39 @@ static int tls_set_private_key(struct tls_context *tls,
15651573
return -ENOTSUP;
15661574
}
15671575

1576+
static int tls_set_private_key_psa(struct tls_context *tls,
1577+
struct tls_credential *priv_key)
1578+
{
1579+
#if defined(CONFIG_MBEDTLS_X509_CRT_PARSE_C) && defined(TLS_PRIV_KEY_PSA_ENABLED)
1580+
psa_key_id_t key_id;
1581+
mbedtls_svc_key_id_t svc_key_id;
1582+
int err;
1583+
1584+
if (priv_key->len != sizeof(key_id)) {
1585+
return -EINVAL;
1586+
}
1587+
1588+
memcpy(&key_id, priv_key->buf, sizeof(key_id));
1589+
1590+
/* The private key lives in PSA and is never exported - we only hold its
1591+
* key id. Wrap that id into an opaque PK context (mbedtls_pk_wrap_psa)
1592+
* so mbedTLS delegates every signature back to PSA instead of needing
1593+
* the raw key. mbedtls_pk_wrap_psa() takes an mbedtls_svc_key_id_t, so
1594+
* build one from the key id with owner 0 (the local/default owner).
1595+
*/
1596+
svc_key_id = mbedtls_svc_key_id_make(0, key_id);
1597+
1598+
err = mbedtls_pk_wrap_psa(&tls->priv_key, svc_key_id);
1599+
if (err != 0) {
1600+
return -EINVAL;
1601+
}
1602+
1603+
return 0;
1604+
#else
1605+
return -ENOTSUP;
1606+
#endif /* CONFIG_MBEDTLS_X509_CRT_PARSE_C && TLS_PRIV_KEY_PSA_ENABLED */
1607+
}
1608+
15681609
static int tls_set_psk(struct tls_context *tls,
15691610
struct tls_credential *psk,
15701611
struct tls_credential *psk_id)
@@ -1598,6 +1639,10 @@ static int tls_set_credential(struct tls_context *tls,
15981639
return tls_set_private_key(tls, cred);
15991640
break;
16001641

1642+
case TLS_CREDENTIAL_PRIVATE_KEY_PSA:
1643+
return tls_set_private_key_psa(tls, cred);
1644+
break;
1645+
16011646
case TLS_CREDENTIAL_PSK:
16021647
{
16031648
struct tls_credential *psk_id =
@@ -2079,6 +2124,41 @@ static int tls_check_priv_key(struct tls_credential *priv_key)
20792124
#endif /* CONFIG_MBEDTLS_X509_CRT_PARSE_C */
20802125
}
20812126

2127+
static int tls_check_private_key_psa(struct tls_credential *priv_key)
2128+
{
2129+
#if defined(CONFIG_MBEDTLS_X509_CRT_PARSE_C) && defined(TLS_PRIV_KEY_PSA_ENABLED)
2130+
psa_key_id_t key_id;
2131+
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
2132+
psa_status_t status;
2133+
2134+
if (priv_key->len != sizeof(key_id)) {
2135+
NET_ERR("Bad PSA key id length on tag %d", priv_key->tag);
2136+
return -EINVAL;
2137+
}
2138+
2139+
memcpy(&key_id, priv_key->buf, sizeof(key_id));
2140+
2141+
/* Validate that the referenced key exists and is usable, without
2142+
* touching the key material.
2143+
*/
2144+
status = psa_get_key_attributes(key_id, &attr);
2145+
if (status != PSA_SUCCESS) {
2146+
NET_ERR("PSA key %u not found for tag %d, status: %d",
2147+
key_id, priv_key->tag, status);
2148+
return -EINVAL;
2149+
}
2150+
2151+
psa_reset_key_attributes(&attr);
2152+
2153+
return 0;
2154+
#else
2155+
NET_ERR("TLS with PSA-resident private keys disabled. "
2156+
"Reconfigure mbed TLS to support PSA crypto.");
2157+
2158+
return -ENOTSUP;
2159+
#endif /* CONFIG_MBEDTLS_X509_CRT_PARSE_C && TLS_PRIV_KEY_PSA_ENABLED */
2160+
}
2161+
20822162
static int tls_check_psk(struct tls_credential *psk)
20832163
{
20842164
#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)
21342214
goto exit;
21352215
}
21362216

2217+
break;
2218+
case TLS_CREDENTIAL_PRIVATE_KEY_PSA:
2219+
err = tls_check_private_key_psa(cred);
2220+
if (err != 0) {
2221+
goto exit;
2222+
}
2223+
21372224
break;
21382225
case TLS_CREDENTIAL_PSK:
21392226
err = tls_check_psk(cred);

0 commit comments

Comments
 (0)