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