10
10
#include "qemu/osdep.h"
11
11
#include "hw/sysbus.h"
12
12
#include "hw/misc/esp32c3_aes.h"
13
- #include "crypto/aes.h"
14
13
#include "qemu/error-report.h"
14
+ #include <gcrypt.h>
15
+ #include <endian.h>
16
+ #include "hw/irq.h"
17
+ #include "crypto/aes.h"
15
18
16
19
#define AES_WARNING 0
17
20
#define AES_DEBUG 0
18
21
19
22
20
23
static void esp32c3_aes_dma_exit (ESP32C3AesState * s )
21
24
{
22
- /* DMA is not supported yet */
23
- (void ) s ;
25
+ s -> state_reg = ESP32C3_AES_IDLE ;
24
26
}
25
27
28
+ static void * esp32c3_aes_get_buffer (uint32_t size )
29
+ {
30
+ /* Instead of reallocating a buffer every time, keep a watermark and a single buffer */
31
+ static void * buffer = NULL ;
32
+ static uint32_t buf_size = 0 ;
26
33
27
- static void esp32c3_aes_start (ESP32C3AesState * s )
34
+ if (buf_size < size ) {
35
+ buffer = g_realloc (buffer , size );
36
+ buf_size = size ;
37
+ }
38
+
39
+ return buffer ;
40
+ }
41
+
42
+
43
+ /**
44
+ * @brief Interpret data in IV memory as a counter and add a block count to its value.
45
+ * Used in CTR block mode.
46
+ */
47
+ static void esp32c3_aes_ctr_add_counter (ESP32C3AesState * s , uint32_t blocks )
28
48
{
29
- AES_KEY aes_key ;
49
+ /* Check the length of this counter in bits. In both cases, it is stored in BIG-ENDIAN */
50
+ if (FIELD_EX32 (s -> inc_sel_reg , AES_INC_SEL_REG , AES_INC_SEL ) == 1 ) {
51
+ /* 128-bit mode, no native 128 integer type, use two 64-bit types */
52
+ uint64_t * low_ptr = (uint64_t * ) (s -> iv_mem + sizeof (uint64_t ));
53
+ uint64_t * high_ptr = (uint64_t * ) s -> iv_mem ;
54
+ const uint64_t original = be64toh (* low_ptr );
55
+ uint64_t value = original + blocks ;
56
+ * low_ptr = htobe64 (value );
57
+ /* If the value overflowed, we have to update the upper part too */
58
+ if (original > value ) {
59
+ value = be64toh (* high_ptr ) + 1 ;
60
+ * high_ptr = htobe64 (value );
61
+ }
62
+ } else {
63
+ /* 32-bit mode */
64
+ uint32_t * counter_ptr = (uint32_t * ) & s -> iv_mem [ESP32C3_AES_IV_REG_CNT - sizeof (uint32_t )];
65
+ const uint32_t value = be32toh (* counter_ptr ) + blocks ;
66
+ * counter_ptr = htobe32 (value );
67
+ }
68
+ }
69
+
30
70
31
- /* DMA mode is not supported yet! */
32
- if (FIELD_EX32 (s -> dma_enable_reg , AES_DMA_ENA_REG , AES_DMA_ENA ) != 0 ) {
33
- error_report ("[AES] DMA-AES is not supported yet\n" );
71
+ static void esp32c3_aes_dma_start (ESP32C3AesState * s )
72
+ {
73
+ gcry_cipher_hd_t ghandle ;
74
+ uint32_t gdma_out_idx ;
75
+ uint32_t gdma_in_idx ;
76
+
77
+ const enum gcry_cipher_modes cipher_map [ESP32C3_AES_CIPHER_COUNT ] = {
78
+ [ESP32C3_AES_ECB_CIPHER ] = GCRY_CIPHER_MODE_ECB ,
79
+ [ESP32C3_AES_CBC_CIPHER ] = GCRY_CIPHER_MODE_CBC ,
80
+ [ESP32C3_AES_OFB_CIPHER ] = GCRY_CIPHER_MODE_OFB ,
81
+ [ESP32C3_AES_CTR_CIPHER ] = GCRY_CIPHER_MODE_CTR ,
82
+ [ESP32C3_AES_CFB8_CIPHER ] = GCRY_CIPHER_MODE_CFB8 ,
83
+ [ESP32C3_AES_CFB128_CIPHER ] = GCRY_CIPHER_MODE_CFB ,
84
+ };
85
+
86
+ /* Get the block Cipher mode */
87
+ const uint32_t cipher_mode = FIELD_EX32 (s -> block_mode_reg , AES_BLK_MODE_REG , AES_BLOCK_MODE );
88
+
89
+ /* Check whether we have to encrypt or decrypt */
90
+ const uint32_t mode = FIELD_EX32 (s -> mode_reg , AES_MODE_REG , AES_MODE );
91
+ const bool encrypt = (mode == ESP32C3_AES_MODE_128_ENC ) || (mode == ESP32C3_AES_MODE_256_ENC );
92
+ const bool decrypt = (mode == ESP32C3_AES_MODE_128_DEC ) || (mode == ESP32C3_AES_MODE_256_DEC );
93
+
94
+ /* Get the length, in bits of the key */
95
+ const int length = (mode == ESP32C3_AES_MODE_128_ENC || mode == ESP32C3_AES_MODE_128_DEC ) ? 128 : 256 ;
96
+ const int algo = length == 128 ? GCRY_CIPHER_AES128 : GCRY_CIPHER_AES256 ;
97
+
98
+ if (cipher_mode >= ESP32C3_AES_CIPHER_COUNT ) {
99
+ error_report ("[AES] Invalid or unsupported Cipher block mode!" );
34
100
return ;
101
+ } else if (!decrypt && !encrypt ) {
102
+ error_report ("[AES] Invalid mode!" );
103
+ return ;
104
+ }
105
+
106
+ gcry_error_t err = gcry_cipher_open (& ghandle , algo , cipher_map [cipher_mode ], 0 );
107
+ if (err ) {
108
+ error_report ("[AES] error 0x%x when opening cipher" , err );
109
+ return ;
110
+ }
111
+
112
+ /* Cast the keys and data to byte array.
113
+ * This can only work as-is if the host computer is has a little-endian CPU. */
114
+ const uint8_t * key = (uint8_t * ) & s -> key ;
115
+ uint8_t * iv_mem = (uint8_t * ) & s -> iv_mem ;
116
+
117
+ /* Set the algorithm key */
118
+ err = gcry_cipher_setkey (ghandle , key , length / 8 );
119
+ if (err ) {
120
+ error_report ("[AES] error 0x%x setting key" , err );
121
+ goto close_exit ;
122
+ }
123
+
124
+ /* `iv_mem` field represents the Initialization Vector for CBC/OFB/CFB operations
125
+ * But it represents the Initial Counter Block for CTR operation.
126
+ * It shall be ignored for ECB block operation. */
127
+ if (cipher_mode == ESP32C3_AES_CTR_CIPHER ) {
128
+ err = gcry_cipher_setctr (ghandle , iv_mem , ESP32C3_AES_IV_REG_CNT );
129
+ } else if (cipher_mode != ESP32C3_AES_ECB_CIPHER ) {
130
+ err = gcry_cipher_setiv (ghandle , iv_mem , ESP32C3_AES_IV_REG_CNT );
131
+ }
132
+
133
+ if (err ) {
134
+ error_report ("[AES] error 0x%x setting IV memory" , err );
135
+ goto close_exit ;
136
+ }
137
+
138
+ /* Get the GDMA input channel index for AES peripheral */
139
+ assert (s -> gdma != NULL );
140
+
141
+ if ( !esp32c3_gdma_get_channel_periph (s -> gdma , GDMA_AES , ESP32C3_GDMA_OUT_IDX , & gdma_out_idx ) ||
142
+ !esp32c3_gdma_get_channel_periph (s -> gdma , GDMA_AES , ESP32C3_GDMA_IN_IDX , & gdma_in_idx ) ) {
143
+ warn_report ("[AES] GDMA requested but no properly configured channel found" );
144
+ goto close_exit ;
145
+ }
146
+
147
+ /* Block number represents the number of 128-bit (16-byte) blocks to encrypt.
148
+ * If block_num_reg is 100, we have to encrypt 100*128/8 = 1600 bytes */
149
+ uint32_t buf_size = s -> block_num_reg * 16 ;
150
+ uint8_t * buffer = esp32c3_aes_get_buffer (buf_size );
151
+
152
+ if ( !esp32c3_gdma_read_channel (s -> gdma , gdma_out_idx , buffer , buf_size ) ) {
153
+ warn_report ("[AES] Error reading from GDMA buffer" );
154
+ goto close_exit ;
35
155
}
36
156
157
+ /* Reading was successful, process the buffer (encrypt/decrypt) and write back to the GDMA OUT buffer */
158
+ if (encrypt ) {
159
+ err = gcry_cipher_encrypt (ghandle , buffer , buf_size , NULL , 0 );
160
+
161
+ if (cipher_mode != ESP32C3_AES_CTR_CIPHER ) {
162
+ /* On the real hardware, IV memory is used in-place for encrypting data, so copy the last encrypted block to IV memory */
163
+ memcpy (iv_mem , buffer + buf_size - 16 , ESP32C3_AES_IV_REG_CNT );
164
+ }
165
+ } else {
166
+ /* Store the last block of plaintext, needed for OFB */
167
+ const uint8_t * buffer_last_block = buffer + buf_size - ESP32C3_AES_IV_REG_CNT ;
168
+ uint8_t plaintext [ESP32C3_AES_IV_REG_CNT ];
169
+ memcpy (plaintext , buffer_last_block , ESP32C3_AES_IV_REG_CNT );
170
+
171
+ /* The IV memory is initalized with the encrypted data, so do the copy now */
172
+ if (cipher_mode != ESP32C3_AES_OFB_CIPHER && cipher_mode != ESP32C3_AES_CTR_CIPHER ) {
173
+ memcpy (iv_mem , buffer + buf_size - 16 , ESP32C3_AES_IV_REG_CNT );
174
+ }
175
+
176
+ err = gcry_cipher_decrypt (ghandle , buffer , buf_size , NULL , 0 );
177
+
178
+ /* For OFB, it is done after the decryption. Moreover, the hardware XOR the original plaintext with the output
179
+ * and stores the result in IV memory. */
180
+ if (cipher_mode == ESP32C3_AES_OFB_CIPHER ) {
181
+ for (int i = 0 ; i < ESP32C3_AES_IV_REG_CNT ; i ++ ) {
182
+ iv_mem [i ] = buffer_last_block [i ] ^ plaintext [i ];
183
+ }
184
+ }
185
+ }
186
+
187
+ if (cipher_mode == ESP32C3_AES_CTR_CIPHER ) {
188
+ esp32c3_aes_ctr_add_counter (s , s -> block_num_reg );
189
+ }
190
+
191
+ if (err ) {
192
+ error_report ("[AES] error processing memory" );
193
+ goto close_exit ;
194
+ }
195
+
196
+ if ( !esp32c3_gdma_write_channel (s -> gdma , gdma_in_idx , buffer , buf_size ) ) {
197
+ warn_report ("[AES] Error writing to GDMA buffer" );
198
+ goto close_exit ;
199
+ }
200
+
201
+ s -> state_reg = ESP32C3_AES_DONE ;
202
+
203
+ if (s -> int_ena_reg ) {
204
+ qemu_irq_raise (s -> irq );
205
+ }
206
+
207
+ close_exit :
208
+ gcry_cipher_close (ghandle );
209
+ }
210
+
211
+
212
+ static void esp32c3_aes_start (ESP32C3AesState * s )
213
+ {
214
+ AES_KEY aes_key ;
215
+
37
216
/* Check whether we have to encrypt or decrypt */
38
217
const uint32_t mode = FIELD_EX32 (s -> mode_reg , AES_MODE_REG , AES_MODE );
39
218
const bool encrypt = (mode == ESP32C3_AES_MODE_128_ENC ) || (mode == ESP32C3_AES_MODE_256_ENC );
@@ -68,6 +247,10 @@ static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size)
68
247
ESP32C3AesState * s = ESP32C3_AES (opaque );
69
248
uint64_t r = 0 ;
70
249
250
+ /* At the moment, make the assumption that we always write a 32-bit word, except for IV memory */
251
+ assert ((addr >= A_AES_IV_MEM_0_REG && addr <= A_AES_IV_MEM_15_REG ) ||
252
+ size == sizeof (uint32_t ));
253
+
71
254
switch (addr ) {
72
255
case A_AES_KEY_0_REG ... A_AES_KEY_7_REG :
73
256
r = s -> key [(addr - A_AES_KEY_0_REG ) / sizeof (uint32_t )];
@@ -82,7 +265,13 @@ static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size)
82
265
break ;
83
266
84
267
case A_AES_IV_MEM_0_REG ... A_AES_IV_MEM_15_REG :
85
- r = s -> iv_mem [(addr - A_AES_IV_MEM_0_REG ) / sizeof (uint32_t )];
268
+ /* Use r as the offset */
269
+ r = addr - A_AES_IV_MEM_0_REG ;
270
+ if (size == sizeof (uint32_t )) {
271
+ r = * ((uint32_t * ) (s -> iv_mem + r ));
272
+ } else if (size == sizeof (uint8_t )) {
273
+ r = s -> iv_mem [r ];
274
+ }
86
275
break ;
87
276
88
277
case A_AES_STATE_REG :
@@ -116,13 +305,13 @@ static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size)
116
305
default :
117
306
#if AES_WARNING
118
307
/* Other registers are not supported yet */
119
- warn_report ("[AES] Unsupported read to %08lx\n " , addr );
308
+ warn_report ("[AES] Unsupported read to %08lx" , addr );
120
309
#endif
121
310
break ;
122
311
}
123
312
124
313
#if AES_DEBUG
125
- info_report ("[AES] Reading from %08lx (%08lx)\n " , addr , r );
314
+ info_report ("[AES] Reading from %08lx (%08lx)" , addr , r );
126
315
#endif
127
316
128
317
@@ -134,6 +323,11 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr,
134
323
uint64_t value , unsigned int size )
135
324
{
136
325
ESP32C3AesState * s = ESP32C3_AES (opaque );
326
+ uint32_t offset = 0 ;
327
+
328
+ /* At the moment, make the assumption that we always write a 32-bit word, except for IV memory */
329
+ assert ((addr >= A_AES_IV_MEM_0_REG && addr <= A_AES_IV_MEM_15_REG ) ||
330
+ size == sizeof (uint32_t ));
137
331
138
332
switch (addr ) {
139
333
case A_AES_KEY_0_REG ... A_AES_KEY_7_REG :
@@ -145,7 +339,12 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr,
145
339
break ;
146
340
147
341
case A_AES_IV_MEM_0_REG ... A_AES_IV_MEM_15_REG :
148
- s -> iv_mem [(addr - A_AES_IV_MEM_0_REG ) / sizeof (uint32_t )] = value ;
342
+ offset = addr - A_AES_IV_MEM_0_REG ;
343
+ if (size == sizeof (uint32_t )) {
344
+ * ((uint32_t * ) (s -> iv_mem + offset )) = value ;
345
+ } else if (size == sizeof (uint8_t )) {
346
+ s -> iv_mem [offset ] = value & 0xff ;
347
+ }
149
348
break ;
150
349
151
350
case A_AES_MODE_REG :
@@ -154,7 +353,12 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr,
154
353
155
354
case A_AES_TRIGGER_REG :
156
355
if (FIELD_EX32 (value , AES_TRIGGER_REG , AES_TRIGGER )) {
157
- esp32c3_aes_start (s );
356
+ /* DMA mode is different than "regular" mode */
357
+ if (FIELD_EX32 (s -> dma_enable_reg , AES_DMA_ENA_REG , AES_DMA_ENA ) != 0 ) {
358
+ esp32c3_aes_dma_start (s );
359
+ } else {
360
+ esp32c3_aes_start (s );
361
+ }
158
362
}
159
363
break ;
160
364
@@ -176,7 +380,7 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr,
176
380
177
381
case A_AES_INT_CLR_REG :
178
382
if (FIELD_EX32 (value , AES_INT_CLR_REG , AES_INT_CLR )) {
179
- s -> int_st = 0 ;
383
+ qemu_irq_lower ( s -> irq ) ;
180
384
}
181
385
break ;
182
386
@@ -191,13 +395,13 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr,
191
395
default :
192
396
#if AES_WARNING
193
397
/* Other registers are not supported yet */
194
- warn_report ("[AES] Unsupported write to %08lx (%08lx)\n " , addr , value );
398
+ warn_report ("[AES] Unsupported write to %08lx (%08lx)" , addr , value );
195
399
#endif
196
400
break ;
197
401
}
198
402
199
403
#if AES_DEBUG
200
- info_report ("[AES] Writing to %08lx (%08lx)\n " , addr , value );
404
+ info_report ("[AES] Writing to %08lx (%08lx)" , addr , value );
201
405
#endif
202
406
203
407
}
@@ -224,6 +428,16 @@ static void esp32c3_aes_reset(DeviceState *dev)
224
428
s -> int_ena_reg = 0 ;
225
429
}
226
430
431
+ static void esp32c3_aes_realize (DeviceState * dev , Error * * errp )
432
+ {
433
+ ESP32C3AesState * s = ESP32C3_AES (dev );
434
+
435
+ /* Make sure GDMA was set of issue an error */
436
+ if (s -> gdma == NULL ) {
437
+ error_report ("[AES] GDMA controller must be set!" );
438
+ }
439
+ }
440
+
227
441
static void esp32c3_aes_init (Object * obj )
228
442
{
229
443
ESP32C3AesState * s = ESP32C3_AES (obj );
@@ -232,12 +446,15 @@ static void esp32c3_aes_init(Object *obj)
232
446
memory_region_init_io (& s -> iomem , obj , & esp32c3_aes_ops , s ,
233
447
TYPE_ESP32C3_AES , ESP32C3_AES_REGS_SIZE );
234
448
sysbus_init_mmio (sbd , & s -> iomem );
449
+
450
+ sysbus_init_irq (sbd , & s -> irq );
235
451
}
236
452
237
453
static void esp32_aes_class_init (ObjectClass * klass , void * data )
238
454
{
239
455
DeviceClass * dc = DEVICE_CLASS (klass );
240
456
457
+ dc -> realize = esp32c3_aes_realize ;
241
458
dc -> reset = esp32c3_aes_reset ;
242
459
}
243
460
0 commit comments