Skip to content

Commit 466a365

Browse files
committed
feat(mbedtls): adds support for RSA decryption with DS peripheral
1 parent 8bca0ba commit 466a365

File tree

14 files changed

+1041
-217
lines changed

14 files changed

+1041
-217
lines changed

components/esp-tls/esp_tls_mbedtls.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, const void *pki);
4040
#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */
4141

4242
#if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
43+
#include <pk_wrap.h>
4344
#include "rsa_sign_alt.h"
4445
static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki);
4546
#endif /* CONFIG_ESP_TLS_USE_DS_PERIPHERAL */
@@ -471,6 +472,28 @@ void esp_mbedtls_cleanup(esp_tls_t *tls)
471472
tls->cacert_ptr = NULL;
472473
mbedtls_x509_crt_free(&tls->cacert);
473474
mbedtls_x509_crt_free(&tls->clientcert);
475+
476+
#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
477+
if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_RSA_ALT) {
478+
mbedtls_rsa_alt_context *rsa_alt = tls->clientkey.MBEDTLS_PRIVATE(pk_ctx);
479+
if (rsa_alt && rsa_alt->key != NULL) {
480+
mbedtls_rsa_free(rsa_alt->key);
481+
mbedtls_free(rsa_alt->key);
482+
rsa_alt->key = NULL;
483+
}
484+
}
485+
486+
// Similar cleanup for server key
487+
if (mbedtls_pk_get_type(&tls->serverkey) == MBEDTLS_PK_RSA_ALT) {
488+
mbedtls_rsa_alt_context *rsa_alt = tls->serverkey.MBEDTLS_PRIVATE(pk_ctx);
489+
if (rsa_alt && rsa_alt->key != NULL) {
490+
mbedtls_rsa_free(rsa_alt->key);
491+
mbedtls_free(rsa_alt->key);
492+
rsa_alt->key = NULL;
493+
}
494+
}
495+
#endif
496+
474497
mbedtls_pk_free(&tls->clientkey);
475498
mbedtls_entropy_free(&tls->entropy);
476499
mbedtls_ssl_config_free(&tls->conf);
@@ -1273,12 +1296,18 @@ static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki)
12731296
{
12741297
int ret = -1;
12751298
/* initialize the mbedtls pk context with rsa context */
1276-
mbedtls_rsa_context rsakey;
1277-
mbedtls_rsa_init(&rsakey);
1278-
if ((ret = mbedtls_pk_setup_rsa_alt(((const esp_tls_pki_t*)pki)->pk_key, &rsakey, NULL, esp_ds_rsa_sign,
1299+
mbedtls_rsa_context *rsakey = calloc(1, sizeof(mbedtls_rsa_context));
1300+
if (rsakey == NULL) {
1301+
ESP_LOGE(TAG, "Failed to allocate memory for mbedtls_rsa_context");
1302+
return ESP_ERR_NO_MEM;
1303+
}
1304+
mbedtls_rsa_init(rsakey);
1305+
if ((ret = mbedtls_pk_setup_rsa_alt(((const esp_tls_pki_t*)pki)->pk_key, rsakey, NULL, esp_ds_rsa_sign,
12791306
esp_ds_get_keylen )) != 0) {
12801307
ESP_LOGE(TAG, "Error in mbedtls_pk_setup_rsa_alt, returned -0x%04X", -ret);
12811308
mbedtls_print_error_msg(ret);
1309+
mbedtls_rsa_free(rsakey);
1310+
free(rsakey);
12821311
ret = ESP_FAIL;
12831312
goto exit;
12841313
}
@@ -1289,7 +1318,6 @@ static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki)
12891318
}
12901319
ESP_LOGD(TAG, "DS peripheral params initialized.");
12911320
exit:
1292-
mbedtls_rsa_free(&rsakey);
12931321
return ret;
12941322
}
12951323
#endif /* CONFIG_ESP_TLS_USE_DS_PERIPHERAL */

components/mbedtls/CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,11 @@ if(CONFIG_SOC_SHA_SUPPORTED)
271271
)
272272
endif()
273273

274-
# CONFIG_ESP_TLS_USE_DS_PERIPHERAL can be enabled only for the supported targets.
275-
if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
276-
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_ds/esp_rsa_sign_alt.c")
274+
if(CONFIG_SOC_DIG_SIGN_SUPPORTED)
275+
target_sources(mbedcrypto PRIVATE
276+
"${COMPONENT_DIR}/port/esp_ds/esp_rsa_sign_alt.c"
277+
"${COMPONENT_DIR}/port/esp_ds/esp_rsa_dec_alt.c"
278+
"${COMPONENT_DIR}/port/esp_ds/esp_ds_common.c")
277279
endif()
278280

279281
# Note: some mbedTLS hardware acceleration can be enabled/disabled by config.
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "sdkconfig.h"
8+
#include "esp_ds.h"
9+
#include "esp_log.h"
10+
#include "esp_ds_common.h"
11+
#include "esp_memory_utils.h"
12+
#include "esp_ds/esp_ds_rsa.h"
13+
#include "freertos/FreeRTOS.h"
14+
#include "freertos/semphr.h"
15+
#include "mbedtls/rsa.h"
16+
17+
#ifdef SOC_DIG_SIGN_SUPPORTED
18+
#include "rom/digital_signature.h"
19+
#else
20+
#error "Selected target does not support DS peripheral"
21+
#endif
22+
23+
#define FACTOR_KEYLEN_IN_BYTES 4
24+
25+
static const char *TAG = "ESP_DS_COMMON";
26+
27+
static hmac_key_id_t s_esp_ds_hmac_key_id = -1;
28+
static esp_ds_data_t *s_ds_data = NULL;
29+
static SemaphoreHandle_t s_ds_lock = NULL;
30+
static int s_timeout_ms = 0;
31+
32+
esp_ds_data_t *esp_ds_get_data_ctx(void)
33+
{
34+
return s_ds_data;
35+
}
36+
37+
hmac_key_id_t esp_ds_get_hmac_key_id(void)
38+
{
39+
return s_esp_ds_hmac_key_id;
40+
}
41+
42+
size_t esp_ds_get_keylen(void *ctx)
43+
{
44+
if (s_ds_data == NULL) {
45+
ESP_LOGE(TAG, "s_ds_data is NULL, cannot get key length");
46+
return 0;
47+
}
48+
/* calculating the rsa_length in bytes */
49+
return ((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES);
50+
}
51+
52+
/* Lock for the DS session, other TLS connections trying to use the DS peripheral will be blocked
53+
* till this DS session is completed (i.e. TLS handshake for this connection is completed) */
54+
static void __attribute__((constructor)) esp_ds_conn_lock(void)
55+
{
56+
if ((s_ds_lock = xSemaphoreCreateMutex()) == NULL) {
57+
ESP_EARLY_LOGE(TAG, "mutex for the DS session lock could not be created");
58+
}
59+
}
60+
61+
void esp_ds_release_ds_lock(void)
62+
{
63+
if (s_ds_lock == NULL) {
64+
ESP_LOGE(TAG, "s_ds_lock is NULL, cannot release lock");
65+
return;
66+
}
67+
if (xSemaphoreGetMutexHolder(s_ds_lock) == xTaskGetCurrentTaskHandle()) {
68+
/* Give back the semaphore (DS lock) */
69+
xSemaphoreGive(s_ds_lock);
70+
}
71+
}
72+
73+
void esp_ds_set_session_timeout(int timeout)
74+
{
75+
/* add additional offset of 1000 ms to have enough time for deleting the TLS connection and free the previous ds context after exceeding timeout value (this offset also helps when timeout is set to 0) */
76+
if (timeout > s_timeout_ms) {
77+
s_timeout_ms = timeout + 1000;
78+
}
79+
}
80+
81+
esp_err_t esp_ds_init_data_ctx(esp_ds_data_ctx_t *ds_data)
82+
{
83+
if (ds_data == NULL || ds_data->esp_ds_data == NULL) {
84+
return ESP_ERR_INVALID_ARG;
85+
}
86+
/* mutex is given back when the DS context is freed after the TLS handshake is completed or in case of failure (at cleanup) */
87+
if ((xSemaphoreTake(s_ds_lock, s_timeout_ms / portTICK_PERIOD_MS) != pdTRUE)) {
88+
ESP_LOGE(TAG, "ds_lock could not be obtained in specified time");
89+
return ESP_FAIL;
90+
}
91+
s_ds_data = ds_data->esp_ds_data;
92+
ESP_LOGD(TAG, "Using DS with key block %u, RSA length %u", ds_data->efuse_key_id, ds_data->rsa_length_bits);
93+
s_esp_ds_hmac_key_id = (hmac_key_id_t) ds_data->efuse_key_id;
94+
95+
const unsigned rsa_length_int = (ds_data->rsa_length_bits / 32) - 1;
96+
if (esp_ptr_byte_accessible(s_ds_data)) {
97+
/* calculate the rsa_length in terms of esp_digital_signature_length_t which is required for the internal DS API */
98+
s_ds_data->rsa_length = rsa_length_int;
99+
} else if (s_ds_data->rsa_length != rsa_length_int) {
100+
/*
101+
* Configuration data is most likely from DROM segment and it
102+
* is not properly formatted for all parameters consideration.
103+
* Moreover, we can not modify as it is read-only and hence
104+
* the error.
105+
*/
106+
ESP_LOGE(TAG, "RSA length mismatch %u, %u", s_ds_data->rsa_length, rsa_length_int);
107+
return ESP_ERR_INVALID_ARG;
108+
}
109+
110+
return ESP_OK;
111+
}
112+
113+
esp_err_t esp_ds_deinit_data_ctx(void)
114+
{
115+
esp_ds_release_ds_lock();
116+
s_ds_data = NULL;
117+
s_esp_ds_hmac_key_id = -1;
118+
119+
return ESP_OK;
120+
}
121+
122+
int esp_ds_mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
123+
size_t slen, mbedtls_md_type_t md_alg)
124+
{
125+
unsigned char counter[4];
126+
unsigned char *p;
127+
unsigned int hlen;
128+
size_t i, use_len;
129+
unsigned char mask[MBEDTLS_MD_MAX_SIZE];
130+
int ret = 0;
131+
const mbedtls_md_info_t *md_info;
132+
mbedtls_md_context_t md_ctx;
133+
134+
mbedtls_md_init(&md_ctx);
135+
md_info = mbedtls_md_info_from_type(md_alg);
136+
if (md_info == NULL) {
137+
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
138+
}
139+
140+
if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
141+
goto exit;
142+
}
143+
144+
hlen = mbedtls_md_get_size(md_info);
145+
146+
memset(mask, 0, sizeof(mask));
147+
memset(counter, 0, 4);
148+
149+
/* Generate and apply dbMask */
150+
p = dst;
151+
152+
while (dlen > 0) {
153+
use_len = hlen;
154+
if (dlen < hlen) {
155+
use_len = dlen;
156+
}
157+
158+
if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
159+
goto exit;
160+
}
161+
if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) {
162+
goto exit;
163+
}
164+
if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) {
165+
goto exit;
166+
}
167+
if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) {
168+
goto exit;
169+
}
170+
171+
for (i = 0; i < use_len; ++i) {
172+
*p++ ^= mask[i];
173+
}
174+
175+
counter[3]++;
176+
177+
dlen -= use_len;
178+
}
179+
180+
exit:
181+
mbedtls_platform_zeroize(mask, sizeof(mask));
182+
mbedtls_md_free(&md_ctx);
183+
184+
return ret;
185+
}
186+
187+
int esp_ds_hash_mprime(const unsigned char *hash, size_t hlen,
188+
const unsigned char *salt, size_t slen,
189+
unsigned char *out, mbedtls_md_type_t md_alg)
190+
{
191+
const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
192+
193+
mbedtls_md_context_t md_ctx;
194+
int ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
195+
196+
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
197+
if (md_info == NULL) {
198+
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
199+
}
200+
201+
mbedtls_md_init(&md_ctx);
202+
if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
203+
goto exit;
204+
}
205+
if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
206+
goto exit;
207+
}
208+
if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) {
209+
goto exit;
210+
}
211+
if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) {
212+
goto exit;
213+
}
214+
if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) {
215+
goto exit;
216+
}
217+
if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) {
218+
goto exit;
219+
}
220+
221+
exit:
222+
mbedtls_md_free(&md_ctx);
223+
224+
return ret;
225+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
#include "mbedtls/md.h"
14+
15+
#define FACTOR_KEYLEN_IN_BYTES 4
16+
#define SWAP_INT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24))
17+
18+
/**
19+
* @brief Get the data context for the digital signature.
20+
*
21+
* @return esp_ds_data_t* esp ds data context pointer.
22+
*/
23+
esp_ds_data_t *esp_ds_get_data_ctx(void);
24+
25+
/**
26+
* @brief Get the HMAC key ID used for digital signature operations.
27+
*
28+
* @return hmac_key_id_t HMAC key ID.
29+
*/
30+
hmac_key_id_t esp_ds_get_hmac_key_id(void);
31+
32+
/**
33+
* @brief Mask generation function (MGF) for TLS 1.3.
34+
*
35+
* @param[in] dst Pointer to the destination buffer.
36+
* @param[in] dlen Length of the destination buffer.
37+
* @param[in] src Pointer to the source buffer.
38+
* @param[in] slen Length of the salt value.
39+
* @param[in] md_alg The message digest algorithm type.
40+
* @return int Returns 0 on success, or a negative error code on failure.
41+
*/
42+
int esp_ds_mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
43+
size_t slen, mbedtls_md_type_t md_alg);
44+
45+
/**
46+
* @brief Generates a hash using the M-Prime algorithm as specified in RFC 8446.
47+
*
48+
* @param hash Pointer to the input hash.
49+
* @param hlen Length of the input hash.
50+
* @param salt Pointer to the salt value.
51+
* @param slen Length of the salt value.
52+
* @param out Pointer to the output buffer where the hash will be stored.
53+
* @param md_alg The message digest algorithm type to use for hashing.
54+
* @return int Returns 0 on success, or a negative error code on failure.
55+
*/
56+
int esp_ds_hash_mprime(const unsigned char *hash, size_t hlen,
57+
const unsigned char *salt, size_t slen,
58+
unsigned char *out, mbedtls_md_type_t md_alg);
59+
60+
#ifdef __cplusplus
61+
}
62+
#endif

0 commit comments

Comments
 (0)