1 /**
2 * \brief AES block cipher, ESP DMA hardware accelerated version
3 * Based on mbedTLS FIPS-197 compliant version.
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
6 * Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 */
22 /*
23 * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
24 *
25 * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
26 * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
27 */
28
29 #include <string.h>
30 #include "mbedtls/aes.h"
31 #include "esp_intr_alloc.h"
32 #include "esp_private/periph_ctrl.h"
33 #include "esp_log.h"
34 #include "esp_attr.h"
35 #include "soc/lldesc.h"
36 #include "esp_heap_caps.h"
37 #include "esp_memory_utils.h"
38 #include "sys/param.h"
39 #if CONFIG_PM_ENABLE
40 #include "esp_pm.h"
41 #endif
42 #include "esp_crypto_lock.h"
43 #include "hal/aes_hal.h"
44 #include "aes/esp_aes_internal.h"
45 #include "esp_aes_dma_priv.h"
46
47 #if CONFIG_IDF_TARGET_ESP32S2
48 #include "esp32s2/rom/cache.h"
49 #elif CONFIG_IDF_TARGET_ESP32S3
50 #include "esp32s3/rom/cache.h"
51 #endif
52
53 #include "freertos/FreeRTOS.h"
54 #include "freertos/semphr.h"
55
56 #if SOC_AES_GDMA
57 #define AES_LOCK() esp_crypto_sha_aes_lock_acquire()
58 #define AES_RELEASE() esp_crypto_sha_aes_lock_release()
59 #elif SOC_AES_CRYPTO_DMA
60 #define AES_LOCK() esp_crypto_dma_lock_acquire()
61 #define AES_RELEASE() esp_crypto_dma_lock_release()
62 #endif
63
64 /* Max size of each chunk to process when output buffer is in unaligned external ram
65 must be a multiple of block size
66 */
67 #define AES_MAX_CHUNK_WRITE_SIZE 1600
68
69 /* Input over this length will yield and wait for interrupt instead of
70 busy-waiting, 30000 bytes is approx 0.5 ms */
71 #define AES_DMA_INTR_TRIG_LEN 2000
72
73 /* With buffers in PSRAM (worst condition) we still achieve a speed of 4 MB/s
74 thus a 2 second timeout value should be suffient for even very large buffers.
75 */
76 #define AES_WAIT_INTR_TIMEOUT_MS 2000
77
78 #if defined(CONFIG_MBEDTLS_AES_USE_INTERRUPT)
79 static SemaphoreHandle_t op_complete_sem;
80 #if defined(CONFIG_PM_ENABLE)
81 static esp_pm_lock_handle_t s_pm_cpu_lock;
82 static esp_pm_lock_handle_t s_pm_sleep_lock;
83 #endif
84 #endif
85
86 #if SOC_PSRAM_DMA_CAPABLE
87
88 #if (CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B)
89 #define DCACHE_LINE_SIZE 16
90 #elif (CONFIG_ESP32S2_DATA_CACHE_LINE_32B || CONFIG_ESP32S3_DATA_CACHE_LINE_32B)
91 #define DCACHE_LINE_SIZE 32
92 #elif CONFIG_ESP32S3_DATA_CACHE_LINE_64B
93 #define DCACHE_LINE_SIZE 64
94 #endif //(CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B)
95
96 #endif //SOC_PSRAM_DMA_CAPABLE
97
98 static const char *TAG = "esp-aes";
99 static bool s_check_dma_capable(const void *p);
100
101 /* These are static due to:
102 * * Must be in DMA capable memory, so stack is not a safe place to put them
103 * * To avoid having to malloc/free them for every DMA operation
104 */
105 static DRAM_ATTR lldesc_t s_stream_in_desc;
106 static DRAM_ATTR lldesc_t s_stream_out_desc;
107 static DRAM_ATTR uint8_t s_stream_in[AES_BLOCK_BYTES];
108 static DRAM_ATTR uint8_t s_stream_out[AES_BLOCK_BYTES];
109
esp_aes_wait_dma_done(lldesc_t * output)110 static inline void esp_aes_wait_dma_done(lldesc_t *output)
111 {
112 /* Wait for DMA write operation to complete */
113 while (1) {
114 if ( esp_aes_dma_done(output) ) {
115 break;
116 }
117 }
118 }
119
120 /* Append a descriptor to the chain, set head if chain empty */
lldesc_append(lldesc_t ** head,lldesc_t * item)121 static inline void lldesc_append(lldesc_t **head, lldesc_t *item)
122 {
123 lldesc_t *it;
124 if (*head == NULL) {
125 *head = item;
126 return;
127 }
128
129 it = *head;
130
131 while (it->empty != 0) {
132 it = (lldesc_t *)it->empty;
133 }
134 it->eof = 0;
135 it->empty = (uint32_t)item;
136 }
137
esp_aes_acquire_hardware(void)138 void esp_aes_acquire_hardware( void )
139 {
140 /* Released by esp_aes_release_hardware()*/
141 AES_LOCK();
142
143 /* Enable AES and DMA hardware */
144 #if SOC_AES_CRYPTO_DMA
145 periph_module_enable(PERIPH_AES_DMA_MODULE);
146 #elif SOC_AES_GDMA
147 periph_module_enable(PERIPH_AES_MODULE);
148 #endif
149 }
150
151 /* Function to disable AES and Crypto DMA clocks and release locks */
esp_aes_release_hardware(void)152 void esp_aes_release_hardware( void )
153 {
154 /* Disable AES and DMA hardware */
155 #if SOC_AES_CRYPTO_DMA
156 periph_module_disable(PERIPH_AES_DMA_MODULE);
157 #elif SOC_AES_GDMA
158 periph_module_disable(PERIPH_AES_MODULE);
159 #endif
160
161 AES_RELEASE();
162 }
163
164
165 #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
esp_aes_complete_isr(void * arg)166 static IRAM_ATTR void esp_aes_complete_isr(void *arg)
167 {
168 BaseType_t higher_woken;
169 aes_hal_interrupt_clear();
170 xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
171 if (higher_woken) {
172 portYIELD_FROM_ISR();
173 }
174 }
175
esp_aes_intr_alloc(void)176 void esp_aes_intr_alloc(void)
177 {
178 if (op_complete_sem == NULL) {
179
180 esp_err_t ret = esp_intr_alloc(ETS_AES_INTR_SOURCE, 0, esp_aes_complete_isr, NULL, NULL);
181 if (ret != ESP_OK) {
182 ESP_LOGE(TAG, "Failed to allocate AES interrupt %d", ret);
183 // This should be treated as fatal error as this API would mostly
184 // be invoked within mbedTLS interface. There is no way for the system
185 // to proceed if the AES interrupt allocation fails here.
186 abort();
187 }
188
189 static StaticSemaphore_t op_sem_buf;
190 op_complete_sem = xSemaphoreCreateBinaryStatic(&op_sem_buf);
191 // Static semaphore creation is unlikley to fail but still basic sanity
192 assert(op_complete_sem != NULL);
193 }
194 }
195
esp_aes_isr_initialise(void)196 static esp_err_t esp_aes_isr_initialise( void )
197 {
198 aes_hal_interrupt_clear();
199 aes_hal_interrupt_enable(true);
200
201 /* AES is clocked proportionally to CPU clock, take power management lock */
202 #ifdef CONFIG_PM_ENABLE
203 if (s_pm_cpu_lock == NULL) {
204 if (esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "aes_sleep", &s_pm_sleep_lock) != ESP_OK) {
205 ESP_LOGE(TAG, "Failed to create PM sleep lock");
206 return ESP_FAIL;
207 }
208 if (esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "aes_cpu", &s_pm_cpu_lock) != ESP_OK) {
209 ESP_LOGE(TAG, "Failed to create PM CPU lock");
210 return ESP_FAIL;
211 }
212 }
213 esp_pm_lock_acquire(s_pm_cpu_lock);
214 esp_pm_lock_acquire(s_pm_sleep_lock);
215 #endif
216
217 return ESP_OK;
218 }
219 #endif // CONFIG_MBEDTLS_AES_USE_INTERRUPT
220
221 /* Wait for AES hardware block operation to complete */
esp_aes_dma_wait_complete(bool use_intr,lldesc_t * output_desc)222 static int esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
223 {
224 #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
225 if (use_intr) {
226 if (!xSemaphoreTake(op_complete_sem, AES_WAIT_INTR_TIMEOUT_MS / portTICK_PERIOD_MS)) {
227 /* indicates a fundamental problem with driver */
228 ESP_LOGE(TAG, "Timed out waiting for completion of AES Interrupt");
229 return -1;
230 }
231 #ifdef CONFIG_PM_ENABLE
232 esp_pm_lock_release(s_pm_cpu_lock);
233 esp_pm_lock_release(s_pm_sleep_lock);
234 #endif // CONFIG_PM_ENABLE
235 }
236 #endif
237 /* Checking this if interrupt is used also, to avoid
238 issues with AES fault injection
239 */
240 aes_hal_wait_done();
241
242 esp_aes_wait_dma_done(output_desc);
243 return 0;
244 }
245
246
247 static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out);
248
249
250 /* Output buffers in external ram needs to be 16-byte aligned and DMA cant access input in the iCache mem range,
251 reallocate them into internal memory and encrypt in chunks to avoid
252 having to malloc too big of a buffer
253
254 The function esp_aes_process_dma_ext_ram zeroises the output buffer in the case of memory allocation failure.
255 */
256
esp_aes_process_dma_ext_ram(esp_aes_context * ctx,const unsigned char * input,unsigned char * output,size_t len,uint8_t * stream_out,bool realloc_input,bool realloc_output)257 static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out, bool realloc_input, bool realloc_output)
258 {
259 size_t chunk_len;
260 int ret = 0;
261 int offset = 0;
262 unsigned char *input_buf = NULL;
263 unsigned char *output_buf = NULL;
264 const unsigned char *dma_input;
265 chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len);
266
267 if (realloc_input) {
268 input_buf = heap_caps_malloc(chunk_len, MALLOC_CAP_DMA);
269
270 if (input_buf == NULL) {
271 mbedtls_platform_zeroize(output, len);
272 ESP_LOGE(TAG, "Failed to allocate memory");
273 return -1;
274 }
275 }
276
277 if (realloc_output) {
278 output_buf = heap_caps_malloc(chunk_len, MALLOC_CAP_DMA);
279
280 if (output_buf == NULL) {
281 mbedtls_platform_zeroize(output, len);
282 ESP_LOGE(TAG, "Failed to allocate memory");
283 return -1;
284 }
285 } else {
286 output_buf = output;
287 }
288
289 while (len) {
290 chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len);
291
292 /* If input needs realloc then copy it, else use the input with offset*/
293 if (realloc_input) {
294 memcpy(input_buf, input + offset, chunk_len);
295 dma_input = input_buf;
296 } else {
297 dma_input = input + offset;
298 }
299
300 if (esp_aes_process_dma(ctx, dma_input, output_buf, chunk_len, stream_out) != 0) {
301 ret = -1;
302 goto cleanup;
303 }
304
305 if (realloc_output) {
306 memcpy(output + offset, output_buf, chunk_len);
307 } else {
308 output_buf = output + offset + chunk_len;
309 }
310
311 len -= chunk_len;
312 offset += chunk_len;
313 }
314
315 cleanup:
316
317 if (realloc_input) {
318 free(input_buf);
319 }
320 if (realloc_output) {
321 free(output_buf);
322 }
323
324 return ret;
325 }
326
327 /* Encrypt/decrypt the input using DMA
328 * The function esp_aes_process_dma zeroises the output buffer in the case of following conditions:
329 * 1. If key is not written in the hardware
330 * 2. Memory allocation failures
331 * 3. If AES interrupt is enabled and ISR initialisation fails
332 * 4. Failure in any of the AES operations
333 */
esp_aes_process_dma(esp_aes_context * ctx,const unsigned char * input,unsigned char * output,size_t len,uint8_t * stream_out)334 static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out)
335 {
336 lldesc_t *in_desc_head = NULL, *out_desc_head = NULL;
337 lldesc_t *out_desc_tail = NULL; /* pointer to the final output descriptor */
338 lldesc_t *block_desc = NULL, *block_in_desc = NULL, *block_out_desc = NULL;
339 size_t lldesc_num;
340 unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block
341 unsigned block_bytes = len - stream_bytes; // bytes which are in a full block
342 unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0);
343 bool use_intr = false;
344 bool input_needs_realloc = false;
345 bool output_needs_realloc = false;
346 int ret = 0;
347
348 assert(len > 0); // caller shouldn't ever have len set to zero
349 assert(stream_bytes == 0 || stream_out != NULL); // stream_out can be NULL if we're processing full block(s)
350
351 /* If no key is written to hardware yet, either the user hasn't called
352 mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
353 know which mode to use - or a fault skipped the
354 key write to hardware. Treat this as a fatal error and zero the output block.
355 */
356 if (ctx->key_in_hardware != ctx->key_bytes) {
357 mbedtls_platform_zeroize(output, len);
358 return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
359 }
360
361 if (block_bytes > 0) {
362 /* Flush cache if input in external ram */
363 #if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE)
364 if (esp_ptr_external_ram(input)) {
365 Cache_WriteBack_Addr((uint32_t)input, len);
366 }
367 if (esp_ptr_external_ram(output)) {
368 if ((((intptr_t)(output) & (DCACHE_LINE_SIZE - 1)) != 0) || (block_bytes % DCACHE_LINE_SIZE != 0)) {
369 // Non aligned ext-mem buffer
370 output_needs_realloc = true;
371 }
372 }
373 #endif
374 /* DMA cannot access memory in the iCache range, copy input to internal ram */
375 if (!s_check_dma_capable(input)) {
376 input_needs_realloc = true;
377 }
378
379 if (!s_check_dma_capable(output)) {
380 output_needs_realloc = true;
381 }
382
383 /* If either input or output is unaccessible to the DMA then they need to be reallocated */
384 if (input_needs_realloc || output_needs_realloc) {
385 return esp_aes_process_dma_ext_ram(ctx, input, output, len, stream_out, input_needs_realloc, output_needs_realloc);
386 }
387
388 /* Set up dma descriptors for input and output considering the 16 byte alignment requirement for EDMA */
389 lldesc_num = lldesc_get_required_num_constrained(block_bytes, LLDESC_MAX_NUM_PER_DESC_16B_ALIGNED);
390
391 /* Allocate both in and out descriptors to save a malloc/free per function call */
392 block_desc = heap_caps_calloc(lldesc_num * 2, sizeof(lldesc_t), MALLOC_CAP_DMA);
393 if (block_desc == NULL) {
394 mbedtls_platform_zeroize(output, len);
395 ESP_LOGE(TAG, "Failed to allocate memory");
396 return -1;
397 }
398
399 block_in_desc = block_desc;
400 block_out_desc = block_desc + lldesc_num;
401
402 lldesc_setup_link(block_in_desc, input, block_bytes, 0);
403 //Limit max inlink descriptor length to be 16 byte aligned, require for EDMA
404 lldesc_setup_link_constrained(block_out_desc, output, block_bytes, LLDESC_MAX_NUM_PER_DESC_16B_ALIGNED, 0);
405
406 /* Setup in/out start descriptors */
407 lldesc_append(&in_desc_head, block_in_desc);
408 lldesc_append(&out_desc_head, block_out_desc);
409
410 out_desc_tail = &block_out_desc[lldesc_num - 1];
411 }
412
413 /* Any leftover bytes which are appended as an additional DMA list */
414 if (stream_bytes > 0) {
415
416 memset(&s_stream_in_desc, 0, sizeof(lldesc_t));
417 memset(&s_stream_out_desc, 0, sizeof(lldesc_t));
418
419 memset(s_stream_in, 0, AES_BLOCK_BYTES);
420 memset(s_stream_out, 0, AES_BLOCK_BYTES);
421
422 memcpy(s_stream_in, input + block_bytes, stream_bytes);
423
424 lldesc_setup_link(&s_stream_in_desc, s_stream_in, AES_BLOCK_BYTES, 0);
425 lldesc_setup_link(&s_stream_out_desc, s_stream_out, AES_BLOCK_BYTES, 0);
426
427 /* Link with block descriptors */
428 lldesc_append(&in_desc_head, &s_stream_in_desc);
429 lldesc_append(&out_desc_head, &s_stream_out_desc);
430
431 out_desc_tail = &s_stream_out_desc;
432 }
433
434 #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
435 /* Only use interrupt for long AES operations */
436 if (len > AES_DMA_INTR_TRIG_LEN) {
437 use_intr = true;
438 if (esp_aes_isr_initialise() != ESP_OK) {
439 ESP_LOGE(TAG, "ESP-AES ISR initialisation failed");
440 ret = -1;
441 goto cleanup;
442 }
443 } else
444 #endif
445 {
446 aes_hal_interrupt_enable(false);
447 }
448
449 if (esp_aes_dma_start(in_desc_head, out_desc_head) != ESP_OK) {
450 ESP_LOGE(TAG, "esp_aes_dma_start failed, no DMA channel available");
451 ret = -1;
452 goto cleanup;
453 }
454
455 aes_hal_transform_dma_start(blocks);
456
457 if (esp_aes_dma_wait_complete(use_intr, out_desc_tail) < 0) {
458 ESP_LOGE(TAG, "esp_aes_dma_wait_complete failed");
459 ret = -1;
460 goto cleanup;
461 }
462
463 #if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE)
464 if (block_bytes > 0) {
465 if (esp_ptr_external_ram(output)) {
466 Cache_Invalidate_Addr((uint32_t)output, block_bytes);
467 }
468 }
469 #endif
470 aes_hal_transform_dma_finish();
471
472 if (stream_bytes > 0) {
473 memcpy(output + block_bytes, s_stream_out, stream_bytes);
474 memcpy(stream_out, s_stream_out, AES_BLOCK_BYTES);
475 }
476
477 cleanup:
478 if (ret != 0) {
479 mbedtls_platform_zeroize(output, len);
480 }
481 free(block_desc);
482 return ret;
483 }
484
485
486 #if CONFIG_MBEDTLS_HARDWARE_GCM
487
488 /* Encrypt/decrypt with AES-GCM the input using DMA
489 * The function esp_aes_process_dma_gcm zeroises the output buffer in the case of following conditions:
490 * 1. If key is not written in the hardware
491 * 2. Memory allocation failures
492 * 3. If AES interrupt is enabled and ISR initialisation fails
493 * 4. Failure in any of the AES operations
494 */
esp_aes_process_dma_gcm(esp_aes_context * ctx,const unsigned char * input,unsigned char * output,size_t len,lldesc_t * aad_desc,size_t aad_len)495 int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len)
496 {
497 lldesc_t *in_desc_head = NULL, *out_desc_head = NULL, *len_desc = NULL;
498 lldesc_t *out_desc_tail = NULL; /* pointer to the final output descriptor */
499 lldesc_t stream_in_desc, stream_out_desc;
500 lldesc_t *block_desc = NULL, *block_in_desc = NULL, *block_out_desc = NULL;
501 size_t lldesc_num;
502 uint32_t len_buf[4] = {};
503 uint8_t stream_in[16] = {};
504 uint8_t stream_out[16] = {};
505 unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block
506 unsigned block_bytes = len - stream_bytes; // bytes which are in a full block
507
508 unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0);
509
510 bool use_intr = false;
511 int ret = 0;
512
513 /* If no key is written to hardware yet, either the user hasn't called
514 mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
515 know which mode to use - or a fault skipped the
516 key write to hardware. Treat this as a fatal error and zero the output block.
517 */
518 if (ctx->key_in_hardware != ctx->key_bytes) {
519 mbedtls_platform_zeroize(output, len);
520 return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
521 }
522
523 /* Set up dma descriptors for input and output */
524 lldesc_num = lldesc_get_required_num(block_bytes);
525
526 /* Allocate both in and out descriptors to save a malloc/free per function call, add 1 for length descriptor */
527 block_desc = heap_caps_calloc( (lldesc_num * 2) + 1, sizeof(lldesc_t), MALLOC_CAP_DMA);
528 if (block_desc == NULL) {
529 mbedtls_platform_zeroize(output, len);
530 ESP_LOGE(TAG, "Failed to allocate memory");
531 return -1;
532 }
533
534 block_in_desc = block_desc;
535 len_desc = block_desc + lldesc_num;
536 block_out_desc = block_desc + lldesc_num + 1;
537
538 if (aad_desc != NULL) {
539 lldesc_append(&in_desc_head, aad_desc);
540 }
541
542 if (block_bytes > 0) {
543 lldesc_setup_link(block_in_desc, input, block_bytes, 0);
544 lldesc_setup_link(block_out_desc, output, block_bytes, 0);
545
546 lldesc_append(&in_desc_head, block_in_desc);
547 lldesc_append(&out_desc_head, block_out_desc);
548
549 out_desc_tail = &block_out_desc[lldesc_num - 1];
550 }
551
552 /* Any leftover bytes which are appended as an additional DMA list */
553 if (stream_bytes > 0) {
554 memcpy(stream_in, input + block_bytes, stream_bytes);
555
556 lldesc_setup_link(&stream_in_desc, stream_in, AES_BLOCK_BYTES, 0);
557 lldesc_setup_link(&stream_out_desc, stream_out, AES_BLOCK_BYTES, 0);
558
559 lldesc_append(&in_desc_head, &stream_in_desc);
560 lldesc_append(&out_desc_head, &stream_out_desc);
561
562 out_desc_tail = &stream_out_desc;
563 }
564
565
566 len_buf[1] = __builtin_bswap32(aad_len * 8);
567 len_buf[3] = __builtin_bswap32(len * 8);
568
569 len_desc->length = sizeof(len_buf);
570 len_desc->size = sizeof(len_buf);
571 len_desc->owner = 1;
572 len_desc->eof = 1;
573 len_desc->buf = (uint8_t *)len_buf;
574
575 lldesc_append(&in_desc_head, len_desc);
576
577 #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
578 /* Only use interrupt for long AES operations */
579 if (len > AES_DMA_INTR_TRIG_LEN) {
580 use_intr = true;
581 if (esp_aes_isr_initialise() != ESP_OK) {
582 ESP_LOGE(TAG, "ESP-AES ISR initialisation failed");
583 ret = -1;
584 goto cleanup;
585 }
586 } else
587 #endif
588 {
589 aes_hal_interrupt_enable(false);
590 }
591
592 /* Start AES operation */
593 if (esp_aes_dma_start(in_desc_head, out_desc_head) != ESP_OK) {
594 ESP_LOGE(TAG, "esp_aes_dma_start failed, no DMA channel available");
595 ret = -1;
596 goto cleanup;
597 }
598
599 aes_hal_transform_dma_gcm_start(blocks);
600
601 if (esp_aes_dma_wait_complete(use_intr, out_desc_tail) < 0) {
602 ESP_LOGE(TAG, "esp_aes_dma_wait_complete failed");
603 ret = -1;
604 goto cleanup;
605 }
606
607 aes_hal_transform_dma_finish();
608
609 if (stream_bytes > 0) {
610 memcpy(output + block_bytes, stream_out, stream_bytes);
611 }
612
613 cleanup:
614 if (ret != 0) {
615 mbedtls_platform_zeroize(output, len);
616 }
617 free(block_desc);
618 return ret;
619 }
620
621 #endif //CONFIG_MBEDTLS_HARDWARE_GCM
622
esp_aes_validate_input(esp_aes_context * ctx,const unsigned char * input,unsigned char * output)623 static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
624 unsigned char *output )
625 {
626 if (!ctx) {
627 ESP_LOGE(TAG, "No AES context supplied");
628 return -1;
629 }
630 if (!input) {
631 ESP_LOGE(TAG, "No input supplied");
632 return -1;
633 }
634 if (!output) {
635 ESP_LOGE(TAG, "No output supplied");
636 return -1;
637 }
638
639 return 0;
640 }
641
642
643 /*
644 * AES-ECB single block encryption
645 */
esp_internal_aes_encrypt(esp_aes_context * ctx,const unsigned char input[16],unsigned char output[16])646 int esp_internal_aes_encrypt(esp_aes_context *ctx,
647 const unsigned char input[16],
648 unsigned char output[16] )
649 {
650 int r = -1;
651
652 if (esp_aes_validate_input(ctx, input, output)) {
653 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
654 }
655
656 if (!valid_key_length(ctx)) {
657 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
658 }
659
660 esp_aes_acquire_hardware();
661 ctx->key_in_hardware = 0;
662 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
663 aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
664 r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
665 esp_aes_release_hardware();
666
667 return r;
668 }
669
esp_aes_encrypt(esp_aes_context * ctx,const unsigned char input[16],unsigned char output[16])670 void esp_aes_encrypt(esp_aes_context *ctx,
671 const unsigned char input[16],
672 unsigned char output[16] )
673 {
674 esp_internal_aes_encrypt(ctx, input, output);
675 }
676
677 /*
678 * AES-ECB single block decryption
679 */
esp_internal_aes_decrypt(esp_aes_context * ctx,const unsigned char input[16],unsigned char output[16])680 int esp_internal_aes_decrypt(esp_aes_context *ctx,
681 const unsigned char input[16],
682 unsigned char output[16] )
683 {
684 int r = -1;
685
686 if (esp_aes_validate_input(ctx, input, output)) {
687 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
688 }
689
690 if (!valid_key_length(ctx)) {
691 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
692 }
693
694 esp_aes_acquire_hardware();
695 ctx->key_in_hardware = 0;
696 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
697 aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
698 r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
699 esp_aes_release_hardware();
700
701 return r;
702 }
703
esp_aes_decrypt(esp_aes_context * ctx,const unsigned char input[16],unsigned char output[16])704 void esp_aes_decrypt(esp_aes_context *ctx,
705 const unsigned char input[16],
706 unsigned char output[16] )
707 {
708 esp_internal_aes_decrypt(ctx, input, output);
709 }
710
711
712 /*
713 * AES-ECB block encryption/decryption
714 */
esp_aes_crypt_ecb(esp_aes_context * ctx,int mode,const unsigned char input[16],unsigned char output[16])715 int esp_aes_crypt_ecb(esp_aes_context *ctx,
716 int mode,
717 const unsigned char input[16],
718 unsigned char output[16] )
719 {
720 int r = -1;
721
722 if (esp_aes_validate_input(ctx, input, output)) {
723 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
724 }
725
726 if (!valid_key_length(ctx)) {
727 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
728 }
729
730 esp_aes_acquire_hardware();
731 ctx->key_in_hardware = 0;
732 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
733 aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
734 r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
735 esp_aes_release_hardware();
736
737 return r;
738 }
739
740 /*
741 * AES-CBC buffer encryption/decryption
742 */
esp_aes_crypt_cbc(esp_aes_context * ctx,int mode,size_t length,unsigned char iv[16],const unsigned char * input,unsigned char * output)743 int esp_aes_crypt_cbc(esp_aes_context *ctx,
744 int mode,
745 size_t length,
746 unsigned char iv[16],
747 const unsigned char *input,
748 unsigned char *output )
749 {
750 int r = -1;
751 if (esp_aes_validate_input(ctx, input, output)) {
752 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
753 }
754
755 if (!iv) {
756 ESP_LOGE(TAG, "No IV supplied");
757 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
758 }
759
760 /* For CBC input length should be multiple of
761 * AES BLOCK BYTES
762 * */
763 if ( (length % AES_BLOCK_BYTES) || (length == 0) ) {
764 return ERR_ESP_AES_INVALID_INPUT_LENGTH;
765 }
766
767 if (!valid_key_length(ctx)) {
768 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
769 }
770
771 esp_aes_acquire_hardware();
772 ctx->key_in_hardware = 0;
773 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
774 aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC);
775 aes_hal_set_iv(iv);
776
777 r = esp_aes_process_dma(ctx, input, output, length, NULL);
778 if (r != 0) {
779 goto cleanup;
780 }
781
782 aes_hal_read_iv(iv);
783
784 cleanup:
785 esp_aes_release_hardware();
786 return r;
787 }
788
789 /*
790 * AES-CFB8 buffer encryption/decryption
791 */
esp_aes_crypt_cfb8(esp_aes_context * ctx,int mode,size_t length,unsigned char iv[16],const unsigned char * input,unsigned char * output)792 int esp_aes_crypt_cfb8(esp_aes_context *ctx,
793 int mode,
794 size_t length,
795 unsigned char iv[16],
796 const unsigned char *input,
797 unsigned char *output )
798 {
799 int r = -1;
800 unsigned char c;
801 unsigned char ov[17];
802 size_t block_bytes = length - (length % AES_BLOCK_BYTES);
803
804 if (esp_aes_validate_input(ctx, input, output)) {
805 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
806 }
807
808 if (!iv) {
809 ESP_LOGE(TAG, "No IV supplied");
810 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
811 }
812
813
814 if (!valid_key_length(ctx)) {
815 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
816 }
817
818 /* The DMA engine will only output correct IV if it runs
819 full blocks of input in CFB8 mode
820 */
821 esp_aes_acquire_hardware();
822
823 if (block_bytes > 0) {
824
825 ctx->key_in_hardware = 0;
826 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
827 aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8);
828 aes_hal_set_iv(iv);
829 r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
830 if (r != 0) {
831 goto cleanup;
832 }
833
834 aes_hal_read_iv(iv);
835
836 length -= block_bytes;
837 input += block_bytes;
838 output += block_bytes;
839 }
840
841 // Process remaining bytes block-at-a-time in ECB mode
842 if (length > 0) {
843 ctx->key_in_hardware = 0;
844 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, MBEDTLS_AES_ENCRYPT);
845 aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
846
847 while ( length-- ) {
848 memcpy( ov, iv, 16 );
849
850 r = esp_aes_process_dma(ctx, iv, iv, AES_BLOCK_BYTES, NULL);
851 if (r != 0) {
852 goto cleanup;
853 }
854
855 if ( mode == MBEDTLS_AES_DECRYPT ) {
856 ov[16] = *input;
857 }
858
859 c = *output++ = ( iv[0] ^ *input++ );
860
861 if ( mode == MBEDTLS_AES_ENCRYPT ) {
862 ov[16] = c;
863 }
864 memcpy( iv, ov + 1, 16 );
865 }
866
867 }
868 r = 0;
869
870 cleanup:
871 esp_aes_release_hardware();
872 return r;
873 }
874
875 /*
876 * AES-CFB128 buffer encryption/decryption
877 */
esp_aes_crypt_cfb128(esp_aes_context * ctx,int mode,size_t length,size_t * iv_off,unsigned char iv[16],const unsigned char * input,unsigned char * output)878 int esp_aes_crypt_cfb128(esp_aes_context *ctx,
879 int mode,
880 size_t length,
881 size_t *iv_off,
882 unsigned char iv[16],
883 const unsigned char *input,
884 unsigned char *output )
885
886 {
887 uint8_t c;
888 size_t stream_bytes = 0;
889 size_t n;
890
891 if (esp_aes_validate_input(ctx, input, output)) {
892 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
893 }
894
895 if (!iv) {
896 ESP_LOGE(TAG, "No IV supplied");
897 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
898 }
899
900 if (!iv_off) {
901 ESP_LOGE(TAG, "No IV offset supplied");
902 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
903 }
904
905 if (!valid_key_length(ctx)) {
906 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
907 }
908
909 n = *iv_off;
910
911 /* First process the *iv_off bytes
912 * which are pending from the previous call to this API
913 */
914 while (n > 0 && length > 0) {
915 if (mode == MBEDTLS_AES_ENCRYPT) {
916 iv[n] = *output++ = *input++ ^ iv[n];
917 } else {
918 c = *input++;
919 *output++ = c ^ iv[n];
920 iv[n] = c;
921 }
922 n = (n + 1) % AES_BLOCK_BYTES;
923 length--;
924 }
925
926
927 if (length > 0) {
928 stream_bytes = length % AES_BLOCK_BYTES;
929 esp_aes_acquire_hardware();
930 ctx->key_in_hardware = 0;
931 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
932 aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128);
933 aes_hal_set_iv(iv);
934
935 int r = esp_aes_process_dma(ctx, input, output, length, iv);
936 if (r != 0) {
937 esp_aes_release_hardware();
938 return r;
939 }
940
941 if (stream_bytes == 0) {
942 // if we didn't need the partial 'stream block' then the new IV is in the IV register
943 aes_hal_read_iv(iv);
944 } else {
945 // if we did process a final partial block the new IV is already processed via DMA (and has some bytes of output in it),
946 // In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next
947 // block uses ciphertext as its IV input)
948 //
949 // Note: It may be more efficient to not process the partial block via DMA in this case.
950 if (mode == MBEDTLS_AES_DECRYPT) {
951 memcpy(iv, input + length - stream_bytes, stream_bytes);
952 }
953 }
954 esp_aes_release_hardware();
955 }
956
957 *iv_off = n + stream_bytes;
958 return 0;
959 }
960
961 /*
962 * AES-OFB (Output Feedback Mode) buffer encryption/decryption
963 */
964
esp_aes_crypt_ofb(esp_aes_context * ctx,size_t length,size_t * iv_off,unsigned char iv[16],const unsigned char * input,unsigned char * output)965 int esp_aes_crypt_ofb(esp_aes_context *ctx,
966 size_t length,
967 size_t *iv_off,
968 unsigned char iv[16],
969 const unsigned char *input,
970 unsigned char *output )
971 {
972 size_t n;
973 size_t stream_bytes = 0;
974
975 if (esp_aes_validate_input(ctx, input, output)) {
976 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
977 }
978
979 if (!iv) {
980 ESP_LOGE(TAG, "No IV supplied");
981 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
982 }
983
984 if (!iv_off) {
985 ESP_LOGE(TAG, "No IV offset supplied");
986 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
987 }
988
989 n = *iv_off;
990
991 /* If there is an offset then use the output of the previous AES block
992 (the updated IV) to calculate the new output */
993 while (n > 0 && length > 0) {
994 *output++ = (*input++ ^ iv[n]);
995 n = (n + 1) & 0xF;
996 length--;
997 }
998 if (length > 0) {
999 stream_bytes = (length % AES_BLOCK_BYTES);
1000
1001 esp_aes_acquire_hardware();
1002 ctx->key_in_hardware = 0;
1003 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
1004 aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB);
1005 aes_hal_set_iv(iv);
1006
1007 int r = esp_aes_process_dma(ctx, input, output, length, iv);
1008 if (r != 0) {
1009 esp_aes_release_hardware();
1010 return r;
1011 }
1012
1013 aes_hal_read_iv(iv);
1014 esp_aes_release_hardware();
1015 }
1016
1017 *iv_off = n + stream_bytes;
1018
1019 return 0;
1020 }
1021
1022 /*
1023 * AES-CTR buffer encryption/decryption
1024 */
esp_aes_crypt_ctr(esp_aes_context * ctx,size_t length,size_t * nc_off,unsigned char nonce_counter[16],unsigned char stream_block[16],const unsigned char * input,unsigned char * output)1025 int esp_aes_crypt_ctr(esp_aes_context *ctx,
1026 size_t length,
1027 size_t *nc_off,
1028 unsigned char nonce_counter[16],
1029 unsigned char stream_block[16],
1030 const unsigned char *input,
1031 unsigned char *output )
1032 {
1033 size_t n;
1034
1035 if (esp_aes_validate_input(ctx, input, output)) {
1036 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
1037 }
1038
1039 if (!stream_block) {
1040 ESP_LOGE(TAG, "No stream supplied");
1041 return -1;
1042 }
1043
1044 if (!nonce_counter) {
1045 ESP_LOGE(TAG, "No nonce supplied");
1046 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
1047 }
1048
1049 if (!nc_off) {
1050 ESP_LOGE(TAG, "No nonce offset supplied");
1051 return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
1052 }
1053
1054 n = *nc_off;
1055
1056 if (!valid_key_length(ctx)) {
1057 return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
1058 }
1059
1060 /* Process any unprocessed bytes left in stream block from
1061 last operation */
1062 while (n > 0 && length > 0) {
1063 *output++ = (unsigned char)(*input++ ^ stream_block[n]);
1064 n = (n + 1) & 0xF;
1065 length--;
1066 }
1067
1068 if (length > 0) {
1069
1070 esp_aes_acquire_hardware();
1071 ctx->key_in_hardware = 0;
1072 ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
1073
1074 aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR);
1075 aes_hal_set_iv(nonce_counter);
1076
1077 int r = esp_aes_process_dma(ctx, input, output, length, stream_block);
1078
1079 if (r != 0) {
1080 esp_aes_release_hardware();
1081 return r;
1082 }
1083
1084 aes_hal_read_iv(nonce_counter);
1085
1086 esp_aes_release_hardware();
1087
1088 }
1089 *nc_off = n + (length % AES_BLOCK_BYTES);
1090
1091 return 0;
1092 }
1093
s_check_dma_capable(const void * p)1094 static bool s_check_dma_capable(const void *p)
1095 {
1096 bool is_capable = false;
1097 #if CONFIG_SPIRAM
1098 is_capable |= esp_ptr_dma_ext_capable(p);
1099 #endif
1100 is_capable |= esp_ptr_dma_capable(p);
1101
1102 return is_capable;
1103 }
1104