1 /*
2 * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "esp_ds.h"
8 #include "rsa_sign_alt.h"
9 #include "esp_memory_utils.h"
10
11 #ifdef CONFIG_IDF_TARGET_ESP32S2
12 #include "esp32s2/rom/digital_signature.h"
13 #elif CONFIG_IDF_TARGET_ESP32C3
14 #include "esp32c3/rom/digital_signature.h"
15 #elif CONFIG_IDF_TARGET_ESP32S3
16 #include "esp32s3/rom/digital_signature.h"
17 #elif CONFIG_IDF_TARGET_ESP32C6
18 #include "esp32c6/rom/digital_signature.h"
19 #elif CONFIG_IDF_TARGET_ESP32H2
20 #include "esp32h2/rom/digital_signature.h"
21 #else
22 #error "Selected target does not support esp_rsa_sign_alt (for DS)"
23 #endif
24
25 #include "esp_log.h"
26 #include "esp_heap_caps.h"
27 #include "freertos/FreeRTOS.h"
28 #include "freertos/semphr.h"
29 #include <mbedtls/build_info.h>
30 static const char *TAG = "ESP_RSA_SIGN_ALT";
31 #define SWAP_INT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24))
32
33 #include "mbedtls/rsa.h"
34 #include "mbedtls/oid.h"
35 #include "mbedtls/platform_util.h"
36 #include <string.h>
37
38 static hmac_key_id_t s_esp_ds_hmac_key_id;
39 static esp_ds_data_t *s_ds_data;
40 static SemaphoreHandle_t s_ds_lock;
41 static int s_timeout_ms = 0;
42
43 /* key length in bytes = (esp_digital_signature_length_t key + 1 ) * FACTOR_KEYLEN_IN_BYTES */
44 #define FACTOR_KEYLEN_IN_BYTES 4
45
46 /* Lock for the DS session, other TLS connections trying to use the DS peripheral will be blocked
47 * till this DS session is completed (i.e. TLS handshake for this connection is completed) */
esp_ds_conn_lock(void)48 static void __attribute__((constructor)) esp_ds_conn_lock (void)
49 {
50 if ((s_ds_lock = xSemaphoreCreateMutex()) == NULL) {
51 ESP_EARLY_LOGE(TAG, "mutex for the DS session lock could not be created");
52 }
53 }
54
esp_ds_set_session_timeout(int timeout)55 void esp_ds_set_session_timeout(int timeout)
56 {
57 /* 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) */
58 if (timeout > s_timeout_ms) {
59 s_timeout_ms = timeout + 1000;
60 }
61 }
62
esp_ds_init_data_ctx(esp_ds_data_ctx_t * ds_data)63 esp_err_t esp_ds_init_data_ctx(esp_ds_data_ctx_t *ds_data)
64 {
65 if (ds_data == NULL || ds_data->esp_ds_data == NULL) {
66 return ESP_ERR_INVALID_ARG;
67 }
68 /* mutex is given back when the DS context is freed after the TLS handshake is completed or in case of failure (at cleanup) */
69 if ((xSemaphoreTake(s_ds_lock, s_timeout_ms / portTICK_PERIOD_MS) != pdTRUE)) {
70 ESP_LOGE(TAG, "ds_lock could not be obtained in specified time");
71 return ESP_FAIL;
72 }
73 s_ds_data = ds_data->esp_ds_data;
74 ESP_LOGD(TAG, "Using DS with key block %u, RSA length %u", ds_data->efuse_key_id, ds_data->rsa_length_bits);
75 s_esp_ds_hmac_key_id = (hmac_key_id_t) ds_data->efuse_key_id;
76
77 const unsigned rsa_length_int = (ds_data->rsa_length_bits / 32) - 1;
78 if (esp_ptr_byte_accessible(s_ds_data)) {
79 /* calculate the rsa_length in terms of esp_digital_signature_length_t which is required for the internal DS API */
80 s_ds_data->rsa_length = rsa_length_int;
81 } else if (s_ds_data->rsa_length != rsa_length_int) {
82 /*
83 * Configuration data is most likely from DROM segment and it
84 * is not properly formatted for all parameters consideration.
85 * Moreover, we can not modify as it is read-only and hence
86 * the error.
87 */
88 ESP_LOGE(TAG, "RSA length mismatch %u, %u", s_ds_data->rsa_length, rsa_length_int);
89 return ESP_ERR_INVALID_ARG;
90 }
91
92 return ESP_OK;
93 }
94
esp_ds_release_ds_lock(void)95 void esp_ds_release_ds_lock(void)
96 {
97 if (xSemaphoreGetMutexHolder(s_ds_lock) == xTaskGetCurrentTaskHandle()) {
98 /* Give back the semaphore (DS lock) */
99 xSemaphoreGive(s_ds_lock);
100 }
101 }
102
esp_ds_get_keylen(void * ctx)103 size_t esp_ds_get_keylen(void *ctx)
104 {
105 /* calculating the rsa_length in bytes */
106 return ((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES);
107 }
108
rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg,unsigned int hashlen,const unsigned char * hash,size_t dst_len,unsigned char * dst)109 static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg,
110 unsigned int hashlen,
111 const unsigned char *hash,
112 size_t dst_len,
113 unsigned char *dst )
114 {
115 size_t oid_size = 0;
116 size_t nb_pad = dst_len;
117 unsigned char *p = dst;
118 const char *oid = NULL;
119
120 /* Are we signing hashed or raw data? */
121 if ( md_alg != MBEDTLS_MD_NONE ) {
122 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
123 if ( md_info == NULL ) {
124 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
125 }
126
127 if ( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) {
128 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
129 }
130
131 hashlen = mbedtls_md_get_size( md_info );
132
133 /* Double-check that 8 + hashlen + oid_size can be used as a
134 * 1-byte ASN.1 length encoding and that there's no overflow. */
135 if ( 8 + hashlen + oid_size >= 0x80 ||
136 10 + hashlen < hashlen ||
137 10 + hashlen + oid_size < 10 + hashlen ) {
138 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
139 }
140
141 /*
142 * Static bounds check:
143 * - Need 10 bytes for five tag-length pairs.
144 * (Insist on 1-byte length encodings to protect against variants of
145 * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
146 * - Need hashlen bytes for hash
147 * - Need oid_size bytes for hash alg OID.
148 */
149 if ( nb_pad < 10 + hashlen + oid_size ) {
150 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
151 }
152 nb_pad -= 10 + hashlen + oid_size;
153 } else {
154 if ( nb_pad < hashlen ) {
155 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
156 }
157
158 nb_pad -= hashlen;
159 }
160
161 /* Need space for signature header and padding delimiter (3 bytes),
162 * and 8 bytes for the minimal padding */
163 if ( nb_pad < 3 + 8 ) {
164 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
165 }
166 nb_pad -= 3;
167
168 /* Now nb_pad is the amount of memory to be filled
169 * with padding, and at least 8 bytes long. */
170
171 /* Write signature header and padding */
172 *p++ = 0;
173 *p++ = MBEDTLS_RSA_SIGN;
174 memset( p, 0xFF, nb_pad );
175 p += nb_pad;
176 *p++ = 0;
177
178 /* Are we signing raw data? */
179 if ( md_alg == MBEDTLS_MD_NONE ) {
180 memcpy( p, hash, hashlen );
181 return ( 0 );
182 }
183
184 /* Signing hashed data, add corresponding ASN.1 structure
185 *
186 * DigestInfo ::= SEQUENCE {
187 * digestAlgorithm DigestAlgorithmIdentifier,
188 * digest Digest }
189 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
190 * Digest ::= OCTET STRING
191 *
192 * Schematic:
193 * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ]
194 * TAG-NULL + LEN [ NULL ] ]
195 * TAG-OCTET + LEN [ HASH ] ]
196 */
197 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
198 *p++ = (unsigned char)( 0x08 + oid_size + hashlen );
199 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
200 *p++ = (unsigned char)( 0x04 + oid_size );
201 *p++ = MBEDTLS_ASN1_OID;
202 *p++ = (unsigned char) oid_size;
203 memcpy( p, oid, oid_size );
204 p += oid_size;
205 *p++ = MBEDTLS_ASN1_NULL;
206 *p++ = 0x00;
207 *p++ = MBEDTLS_ASN1_OCTET_STRING;
208 *p++ = (unsigned char) hashlen;
209 memcpy( p, hash, hashlen );
210 p += hashlen;
211
212 /* Just a sanity-check, should be automatic
213 * after the initial bounds check. */
214 if ( p != dst + dst_len ) {
215 mbedtls_platform_zeroize( dst, dst_len );
216 return ( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
217 }
218
219 return ( 0 );
220 }
221
222
esp_ds_rsa_sign(void * ctx,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,mbedtls_md_type_t md_alg,unsigned int hashlen,const unsigned char * hash,unsigned char * sig)223 int esp_ds_rsa_sign( void *ctx,
224 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
225 mbedtls_md_type_t md_alg, unsigned int hashlen,
226 const unsigned char *hash, unsigned char *sig )
227 {
228 esp_ds_context_t *esp_ds_ctx;
229 esp_err_t ds_r;
230 int ret = -1;
231 uint32_t *signature = heap_caps_malloc_prefer((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES, 2, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
232 if (signature == NULL) {
233 ESP_LOGE(TAG, "Could not allocate memory for internal DS operations");
234 return -1;
235 }
236
237 if ((ret = (rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, ((s_ds_data->rsa_length + 1) * FACTOR_KEYLEN_IN_BYTES), sig ))) != 0) {
238 ESP_LOGE(TAG, "Error in pkcs1_v15 encoding, returned %d", ret);
239 heap_caps_free(signature);
240 return -1;
241 }
242
243 for (unsigned int i = 0; i < (s_ds_data->rsa_length + 1); i++) {
244 signature[i] = SWAP_INT32(((uint32_t *)sig)[(s_ds_data->rsa_length + 1) - (i + 1)]);
245 }
246
247 ds_r = esp_ds_start_sign((const void *)signature,
248 s_ds_data,
249 s_esp_ds_hmac_key_id,
250 &esp_ds_ctx);
251 if (ds_r != ESP_OK) {
252 ESP_LOGE(TAG, "Error in esp_ds_start_sign, returned %d ", ds_r);
253 heap_caps_free(signature);
254 return -1;
255 }
256
257 ds_r = esp_ds_finish_sign((void *)signature, esp_ds_ctx);
258 if (ds_r != ESP_OK) {
259 if (ds_r == ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST) {
260 ESP_LOGE(TAG, "Invalid digest in DS data reported by esp_ds_finish_sign");
261 } else {
262 ESP_LOGE(TAG, "Error in esp_ds_finish_sign, returned %d ", ds_r);
263 }
264 heap_caps_free(signature);
265 return -1;
266 }
267
268 for (unsigned int i = 0; i < (s_ds_data->rsa_length + 1); i++) {
269 ((uint32_t *)sig)[i] = SWAP_INT32(((uint32_t *)signature)[(s_ds_data->rsa_length + 1) - (i + 1)]);
270 }
271 heap_caps_free(signature);
272 return 0;
273 }
274