1 /*
2  * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include "esp_mbedtls_dynamic_impl.h"
9 
10 #define COUNTER_SIZE (8)
11 #define CACHE_IV_SIZE (16)
12 #define CACHE_BUFFER_SIZE (CACHE_IV_SIZE + COUNTER_SIZE)
13 
14 #define TX_IDLE_BUFFER_SIZE (MBEDTLS_SSL_HEADER_LEN + CACHE_BUFFER_SIZE)
15 
16 static const char *TAG = "Dynamic Impl";
17 
esp_mbedtls_set_buf_state(unsigned char * buf,esp_mbedtls_ssl_buf_states state)18 static void esp_mbedtls_set_buf_state(unsigned char *buf, esp_mbedtls_ssl_buf_states state)
19 {
20     struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]);
21     temp->state = state;
22 }
23 
esp_mbedtls_get_buf_state(unsigned char * buf)24 static esp_mbedtls_ssl_buf_states esp_mbedtls_get_buf_state(unsigned char *buf)
25 {
26     struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]);
27     return temp->state;
28 }
29 
esp_mbedtls_free_buf(unsigned char * buf)30 void esp_mbedtls_free_buf(unsigned char *buf)
31 {
32     struct esp_mbedtls_ssl_buf *temp = __containerof(buf, struct esp_mbedtls_ssl_buf, buf[0]);
33     ESP_LOGV(TAG, "free buffer @ %p", temp);
34     mbedtls_free(temp);
35 }
36 
esp_mbedtls_init_ssl_buf(struct esp_mbedtls_ssl_buf * buf,unsigned int len)37 static void esp_mbedtls_init_ssl_buf(struct esp_mbedtls_ssl_buf *buf, unsigned int len)
38 {
39     if (buf) {
40         buf->state = ESP_MBEDTLS_SSL_BUF_CACHED;
41         buf->len = len;
42     }
43 }
44 
esp_mbedtls_parse_record_header(mbedtls_ssl_context * ssl)45 static void esp_mbedtls_parse_record_header(mbedtls_ssl_context *ssl)
46 {
47     ssl->in_msgtype =  ssl->in_hdr[0];
48     ssl->in_msglen = (ssl->in_len[0] << 8) | ssl->in_len[1];
49 }
50 
tx_buffer_len(mbedtls_ssl_context * ssl,int len)51 static int tx_buffer_len(mbedtls_ssl_context *ssl, int len)
52 {
53     (void)ssl;
54 
55     if (!len) {
56         return MBEDTLS_SSL_OUT_BUFFER_LEN;
57     } else {
58         return len + MBEDTLS_SSL_HEADER_LEN
59                    + MBEDTLS_SSL_COMPRESSION_ADD
60                    + MBEDTLS_MAX_IV_LENGTH
61                    + MBEDTLS_SSL_MAC_ADD
62                    + MBEDTLS_SSL_PADDING_ADD;
63     }
64 }
65 
init_tx_buffer(mbedtls_ssl_context * ssl,unsigned char * buf)66 static void init_tx_buffer(mbedtls_ssl_context *ssl, unsigned char *buf)
67 {
68     /**
69      * In mbedtls, ssl->out_msg = ssl->out_buf + offset;
70      */
71     if (!buf) {
72         int out_msg_off = (int)ssl->out_msg - (int)ssl->out_buf;
73 
74         if (!out_msg_off) {
75             out_msg_off = MBEDTLS_SSL_HEADER_LEN;
76         }
77 
78         ssl->out_buf = NULL;
79         ssl->out_ctr = NULL;
80         ssl->out_hdr = NULL;
81         ssl->out_len = NULL;
82         ssl->out_iv  = NULL;
83         ssl->out_msg = (unsigned char *)out_msg_off;
84     } else {
85         int out_msg_off = (int)ssl->out_msg;
86 
87         ssl->out_buf = buf;
88         ssl->out_ctr = ssl->out_buf;
89         ssl->out_hdr = ssl->out_buf +  8;
90         ssl->out_len = ssl->out_buf + 11;
91         ssl->out_iv  = ssl->out_buf + MBEDTLS_SSL_HEADER_LEN;
92         ssl->out_msg = ssl->out_buf + out_msg_off;
93 
94         ESP_LOGV(TAG, "out msg offset is %d", out_msg_off);
95     }
96 
97     ssl->out_msgtype = 0;
98     ssl->out_msglen = 0;
99     ssl->out_left = 0;
100 }
101 
init_rx_buffer(mbedtls_ssl_context * ssl,unsigned char * buf)102 static void init_rx_buffer(mbedtls_ssl_context *ssl, unsigned char *buf)
103 {
104     /**
105      * In mbedtls, ssl->in_msg = ssl->in_buf + offset;
106      */
107     if (!buf) {
108         int in_msg_off = (int)ssl->in_msg - (int)ssl->in_buf;
109 
110         if (!in_msg_off) {
111             in_msg_off = MBEDTLS_SSL_HEADER_LEN;
112         }
113 
114         ssl->in_buf = NULL;
115         ssl->in_ctr = NULL;
116         ssl->in_hdr = NULL;
117         ssl->in_len = NULL;
118         ssl->in_iv  = NULL;
119         ssl->in_msg = (unsigned char *)in_msg_off;
120     } else {
121         int in_msg_off = (int)ssl->in_msg;
122 
123         ssl->in_buf = buf;
124         ssl->in_ctr = ssl->in_buf;
125         ssl->in_hdr = ssl->in_buf +  8;
126         ssl->in_len = ssl->in_buf + 11;
127         ssl->in_iv  = ssl->in_buf + MBEDTLS_SSL_HEADER_LEN;
128         ssl->in_msg = ssl->in_buf + in_msg_off;
129 
130         ESP_LOGV(TAG, "in msg offset is %d", in_msg_off);
131     }
132 
133     ssl->in_msgtype = 0;
134     ssl->in_msglen = 0;
135     ssl->in_left = 0;
136 }
137 
esp_mbedtls_alloc_tx_buf(mbedtls_ssl_context * ssl,int len)138 static int esp_mbedtls_alloc_tx_buf(mbedtls_ssl_context *ssl, int len)
139 {
140     struct esp_mbedtls_ssl_buf *esp_buf;
141 
142     if (ssl->out_buf) {
143         esp_mbedtls_free_buf(ssl->out_buf);
144         ssl->out_buf = NULL;
145     }
146 
147     esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + len);
148     if (!esp_buf) {
149         ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + len);
150         return MBEDTLS_ERR_SSL_ALLOC_FAILED;
151     }
152 
153     ESP_LOGV(TAG, "add out buffer %d bytes @ %p", len, esp_buf->buf);
154 
155     esp_mbedtls_init_ssl_buf(esp_buf, len);
156     /**
157      * Mark the out_msg offset from ssl->out_buf.
158      *
159      * In mbedtls, ssl->out_msg = ssl->out_buf + offset;
160      */
161     ssl->out_msg = (unsigned char *)MBEDTLS_SSL_HEADER_LEN;
162 
163     init_tx_buffer(ssl, esp_buf->buf);
164 
165     return 0;
166 }
167 
esp_mbedtls_setup_tx_buffer(mbedtls_ssl_context * ssl)168 int esp_mbedtls_setup_tx_buffer(mbedtls_ssl_context *ssl)
169 {
170     CHECK_OK(esp_mbedtls_alloc_tx_buf(ssl, TX_IDLE_BUFFER_SIZE));
171 
172     /* mark the out buffer has no data cached */
173     esp_mbedtls_set_buf_state(ssl->out_buf, ESP_MBEDTLS_SSL_BUF_NO_CACHED);
174 
175     return 0;
176 }
177 
esp_mbedtls_setup_rx_buffer(mbedtls_ssl_context * ssl)178 void esp_mbedtls_setup_rx_buffer(mbedtls_ssl_context *ssl)
179 {
180     ssl->in_msg = ssl->in_buf = NULL;
181     init_rx_buffer(ssl, NULL);
182 }
183 
esp_mbedtls_reset_add_tx_buffer(mbedtls_ssl_context * ssl)184 int esp_mbedtls_reset_add_tx_buffer(mbedtls_ssl_context *ssl)
185 {
186     return esp_mbedtls_alloc_tx_buf(ssl, MBEDTLS_SSL_OUT_BUFFER_LEN);
187 }
188 
esp_mbedtls_reset_free_tx_buffer(mbedtls_ssl_context * ssl)189 int esp_mbedtls_reset_free_tx_buffer(mbedtls_ssl_context *ssl)
190 {
191     esp_mbedtls_free_buf(ssl->out_buf);
192     init_tx_buffer(ssl, NULL);
193 
194     CHECK_OK(esp_mbedtls_setup_tx_buffer(ssl));
195 
196     return 0;
197 }
198 
esp_mbedtls_reset_add_rx_buffer(mbedtls_ssl_context * ssl)199 int esp_mbedtls_reset_add_rx_buffer(mbedtls_ssl_context *ssl)
200 {
201     struct esp_mbedtls_ssl_buf *esp_buf;
202 
203     if (ssl->in_buf) {
204         esp_mbedtls_free_buf(ssl->in_buf);
205         ssl->in_buf = NULL;
206     }
207 
208     esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + MBEDTLS_SSL_IN_BUFFER_LEN);
209     if (!esp_buf) {
210         ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + MBEDTLS_SSL_IN_BUFFER_LEN);
211         return MBEDTLS_ERR_SSL_ALLOC_FAILED;
212     }
213 
214     ESP_LOGV(TAG, "add in buffer %d bytes @ %p", MBEDTLS_SSL_IN_BUFFER_LEN, esp_buf->buf);
215 
216     esp_mbedtls_init_ssl_buf(esp_buf, MBEDTLS_SSL_IN_BUFFER_LEN);
217     /**
218      * Mark the in_msg offset from ssl->in_buf.
219      *
220      * In mbedtls, ssl->in_msg = ssl->in_buf + offset;
221      */
222     ssl->in_msg = (unsigned char *)MBEDTLS_SSL_HEADER_LEN;
223 
224     init_rx_buffer(ssl, esp_buf->buf);
225 
226     return 0;
227 }
228 
esp_mbedtls_reset_free_rx_buffer(mbedtls_ssl_context * ssl)229 void esp_mbedtls_reset_free_rx_buffer(mbedtls_ssl_context *ssl)
230 {
231     esp_mbedtls_free_buf(ssl->in_buf);
232     init_rx_buffer(ssl, NULL);
233 }
234 
esp_mbedtls_add_tx_buffer(mbedtls_ssl_context * ssl,size_t buffer_len)235 int esp_mbedtls_add_tx_buffer(mbedtls_ssl_context *ssl, size_t buffer_len)
236 {
237     int ret = 0;
238     int cached = 0;
239     struct esp_mbedtls_ssl_buf *esp_buf;
240     unsigned char cache_buf[CACHE_BUFFER_SIZE];
241 
242     ESP_LOGV(TAG, "--> add out");
243 
244     if (ssl->out_buf) {
245         if (esp_mbedtls_get_buf_state(ssl->out_buf) == ESP_MBEDTLS_SSL_BUF_CACHED) {
246             ESP_LOGV(TAG, "out buffer is not empty");
247             ret = 0;
248             goto exit;
249         } else {
250             memcpy(cache_buf, ssl->out_buf, CACHE_BUFFER_SIZE);
251             esp_mbedtls_free_buf(ssl->out_buf);
252             init_tx_buffer(ssl, NULL);
253             cached = 1;
254         }
255     }
256 
257     buffer_len = tx_buffer_len(ssl, buffer_len);
258 
259     esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len);
260     if (!esp_buf) {
261         ESP_LOGE(TAG, "alloc(%zu bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len);
262         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
263         goto exit;
264     }
265 
266     ESP_LOGV(TAG, "add out buffer %zu bytes @ %p", buffer_len, esp_buf->buf);
267 
268     esp_mbedtls_init_ssl_buf(esp_buf, buffer_len);
269     init_tx_buffer(ssl, esp_buf->buf);
270 
271     if (cached) {
272         memcpy(ssl->out_ctr, cache_buf, COUNTER_SIZE);
273         memcpy(ssl->out_iv, cache_buf + COUNTER_SIZE, CACHE_IV_SIZE);
274     }
275 
276     ESP_LOGV(TAG, "ssl->out_buf=%p ssl->out_msg=%p", ssl->out_buf, ssl->out_msg);
277 
278 exit:
279     ESP_LOGV(TAG, "<-- add out");
280 
281     return ret;
282 }
283 
284 
esp_mbedtls_free_tx_buffer(mbedtls_ssl_context * ssl)285 int esp_mbedtls_free_tx_buffer(mbedtls_ssl_context *ssl)
286 {
287     int ret = 0;
288     unsigned char buf[CACHE_BUFFER_SIZE];
289     struct esp_mbedtls_ssl_buf *esp_buf;
290 
291     ESP_LOGV(TAG, "--> free out");
292 
293     if (!ssl->out_buf || (ssl->out_buf && (esp_mbedtls_get_buf_state(ssl->out_buf) == ESP_MBEDTLS_SSL_BUF_NO_CACHED))) {
294         ret = 0;
295         goto exit;
296     }
297 
298     memcpy(buf, ssl->out_ctr, COUNTER_SIZE);
299     memcpy(buf + COUNTER_SIZE, ssl->out_iv, CACHE_IV_SIZE);
300 
301     esp_mbedtls_free_buf(ssl->out_buf);
302     init_tx_buffer(ssl, NULL);
303 
304     esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + TX_IDLE_BUFFER_SIZE);
305     if (!esp_buf) {
306         ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + TX_IDLE_BUFFER_SIZE);
307         return MBEDTLS_ERR_SSL_ALLOC_FAILED;
308     }
309 
310     esp_mbedtls_init_ssl_buf(esp_buf, TX_IDLE_BUFFER_SIZE);
311     memcpy(esp_buf->buf, buf, CACHE_BUFFER_SIZE);
312     init_tx_buffer(ssl, esp_buf->buf);
313     esp_mbedtls_set_buf_state(ssl->out_buf, ESP_MBEDTLS_SSL_BUF_NO_CACHED);
314 exit:
315     ESP_LOGV(TAG, "<-- free out");
316 
317     return ret;
318 }
319 
esp_mbedtls_add_rx_buffer(mbedtls_ssl_context * ssl)320 int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl)
321 {
322     int cached = 0;
323     int ret = 0;
324     int buffer_len;
325     struct esp_mbedtls_ssl_buf *esp_buf;
326     unsigned char cache_buf[16];
327     unsigned char msg_head[5];
328     size_t in_msglen, in_left;
329 
330     ESP_LOGV(TAG, "--> add rx");
331 
332     if (ssl->in_buf) {
333         if (esp_mbedtls_get_buf_state(ssl->in_buf) == ESP_MBEDTLS_SSL_BUF_CACHED) {
334             ESP_LOGV(TAG, "in buffer is not empty");
335             ret = 0;
336             goto exit;
337         } else {
338             cached = 1;
339         }
340     }
341 
342     ssl->in_hdr = msg_head;
343     ssl->in_len = msg_head + 3;
344 
345     if ((ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl))) != 0) {
346         if (ret == MBEDTLS_ERR_SSL_TIMEOUT) {
347             ESP_LOGD(TAG, "mbedtls_ssl_fetch_input reads data times out");
348         } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
349             ESP_LOGD(TAG, "mbedtls_ssl_fetch_input wants to read more data");
350         } else {
351             ESP_LOGE(TAG, "mbedtls_ssl_fetch_input error=%d", -ret);
352         }
353 
354         goto exit;
355     }
356 
357     esp_mbedtls_parse_record_header(ssl);
358 
359     in_left = ssl->in_left;
360     in_msglen = ssl->in_msglen;
361     buffer_len = tx_buffer_len(ssl, in_msglen);
362 
363     ESP_LOGV(TAG, "message length is %d RX buffer length should be %d left is %d",
364                 (int)in_msglen, (int)buffer_len, (int)ssl->in_left);
365 
366     if (cached) {
367         memcpy(cache_buf, ssl->in_buf, 16);
368         esp_mbedtls_free_buf(ssl->in_buf);
369         init_rx_buffer(ssl, NULL);
370     }
371 
372     esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len);
373     if (!esp_buf) {
374         ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len);
375         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
376         goto exit;
377     }
378 
379     ESP_LOGV(TAG, "add in buffer %d bytes @ %p", buffer_len, esp_buf->buf);
380 
381     esp_mbedtls_init_ssl_buf(esp_buf, buffer_len);
382     init_rx_buffer(ssl, esp_buf->buf);
383 
384     if (cached) {
385         memcpy(ssl->in_ctr, cache_buf, 8);
386         memcpy(ssl->in_iv, cache_buf + 8, 8);
387     }
388 
389     memcpy(ssl->in_hdr, msg_head, in_left);
390     ssl->in_left = in_left;
391     ssl->in_msglen = 0;
392 
393 exit:
394     ESP_LOGV(TAG, "<-- add rx");
395 
396     return ret;
397 }
398 
esp_mbedtls_free_rx_buffer(mbedtls_ssl_context * ssl)399 int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl)
400 {
401     int ret = 0;
402     unsigned char buf[16];
403     struct esp_mbedtls_ssl_buf *esp_buf;
404 
405     ESP_LOGV(TAG, "--> free rx");
406 
407     /**
408      * When have read multi messages once, can't free the input buffer directly.
409      */
410     if (!ssl->in_buf || (ssl->in_hslen && (ssl->in_hslen < ssl->in_msglen)) ||
411         (ssl->in_buf && (esp_mbedtls_get_buf_state(ssl->in_buf) == ESP_MBEDTLS_SSL_BUF_NO_CACHED))) {
412         ret = 0;
413         goto exit;
414     }
415 
416     /**
417      * The previous processing is just skipped, so "ssl->in_msglen = 0"
418      */
419     if (!ssl->in_msgtype) {
420         goto exit;
421     }
422 
423     memcpy(buf, ssl->in_ctr, 8);
424     memcpy(buf + 8, ssl->in_iv, 8);
425 
426     esp_mbedtls_free_buf(ssl->in_buf);
427     init_rx_buffer(ssl, NULL);
428 
429     esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + 16);
430     if (!esp_buf) {
431         ESP_LOGE(TAG, "alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + 16);
432         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
433         goto exit;
434     }
435 
436     esp_mbedtls_init_ssl_buf(esp_buf, 16);
437     memcpy(esp_buf->buf, buf, 16);
438     init_rx_buffer(ssl, esp_buf->buf);
439     esp_mbedtls_set_buf_state(ssl->in_buf, ESP_MBEDTLS_SSL_BUF_NO_CACHED);
440 exit:
441     ESP_LOGV(TAG, "<-- free rx");
442 
443     return ret;
444 }
445 
esp_mbedtls_get_crt_size(mbedtls_x509_crt * cert,size_t * num)446 size_t esp_mbedtls_get_crt_size(mbedtls_x509_crt *cert, size_t *num)
447 {
448     size_t n = 0;
449     size_t bytes = 0;
450 
451     while (cert) {
452         bytes += cert->raw.len;
453         n++;
454 
455         cert = cert->next;
456     }
457 
458     *num = n;
459 
460     return bytes;
461 }
462 
463 #ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA
esp_mbedtls_free_dhm(mbedtls_ssl_context * ssl)464 void esp_mbedtls_free_dhm(mbedtls_ssl_context *ssl)
465 {
466     mbedtls_mpi_free((mbedtls_mpi *)&ssl->conf->dhm_P);
467     mbedtls_mpi_free((mbedtls_mpi *)&ssl->conf->dhm_G);
468 }
469 
esp_mbedtls_free_keycert(mbedtls_ssl_context * ssl)470 void esp_mbedtls_free_keycert(mbedtls_ssl_context *ssl)
471 {
472     mbedtls_ssl_config *conf = (mbedtls_ssl_config *)ssl->conf;
473     mbedtls_ssl_key_cert *keycert = conf->key_cert, *next;
474 
475     while (keycert) {
476         next = keycert->next;
477 
478         if (keycert) {
479             mbedtls_free(keycert);
480         }
481 
482         keycert = next;
483     }
484 
485     conf->key_cert = NULL;
486 }
487 
esp_mbedtls_free_keycert_key(mbedtls_ssl_context * ssl)488 void esp_mbedtls_free_keycert_key(mbedtls_ssl_context *ssl)
489 {
490     mbedtls_ssl_key_cert *keycert = ssl->conf->key_cert;
491 
492     while (keycert) {
493         if (keycert->key) {
494             mbedtls_pk_free(keycert->key);
495             keycert->key = NULL;
496         }
497         keycert = keycert->next;
498     }
499 }
500 
esp_mbedtls_free_keycert_cert(mbedtls_ssl_context * ssl)501 void esp_mbedtls_free_keycert_cert(mbedtls_ssl_context *ssl)
502 {
503     mbedtls_ssl_key_cert *keycert = ssl->conf->key_cert;
504 
505     while (keycert) {
506         if (keycert->cert) {
507             mbedtls_x509_crt_free(keycert->cert);
508             keycert->cert = NULL;
509         }
510         keycert = keycert->next;
511     }
512 }
513 #endif /* CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA */
514 
515 #ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT
esp_mbedtls_free_cacert(mbedtls_ssl_context * ssl)516 void esp_mbedtls_free_cacert(mbedtls_ssl_context *ssl)
517 {
518     if (ssl->conf->ca_chain) {
519         mbedtls_ssl_config *conf = (mbedtls_ssl_config *)ssl->conf;
520 
521         mbedtls_x509_crt_free(conf->ca_chain);
522         conf->ca_chain = NULL;
523     }
524 }
525 #endif /* CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT */
526