xref: /openbmc/qemu/hw/vmapple/aes.c (revision f5e6e13124440797308d2c044f44d9e655fcb74d)
1*c960b389SAlexander Graf /*
2*c960b389SAlexander Graf  * QEMU Apple AES device emulation
3*c960b389SAlexander Graf  *
4*c960b389SAlexander Graf  * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5*c960b389SAlexander Graf  *
6*c960b389SAlexander Graf  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7*c960b389SAlexander Graf  * See the COPYING file in the top-level directory.
8*c960b389SAlexander Graf  *
9*c960b389SAlexander Graf  * SPDX-License-Identifier: GPL-2.0-or-later
10*c960b389SAlexander Graf  */
11*c960b389SAlexander Graf 
12*c960b389SAlexander Graf #include "qemu/osdep.h"
13*c960b389SAlexander Graf #include "trace.h"
14*c960b389SAlexander Graf #include "crypto/hash.h"
15*c960b389SAlexander Graf #include "crypto/aes.h"
16*c960b389SAlexander Graf #include "crypto/cipher.h"
17*c960b389SAlexander Graf #include "hw/irq.h"
18*c960b389SAlexander Graf #include "hw/sysbus.h"
19*c960b389SAlexander Graf #include "hw/vmapple/vmapple.h"
20*c960b389SAlexander Graf #include "migration/vmstate.h"
21*c960b389SAlexander Graf #include "qemu/cutils.h"
22*c960b389SAlexander Graf #include "qemu/log.h"
23*c960b389SAlexander Graf #include "qemu/module.h"
24*c960b389SAlexander Graf #include "system/dma.h"
25*c960b389SAlexander Graf 
26*c960b389SAlexander Graf OBJECT_DECLARE_SIMPLE_TYPE(AESState, APPLE_AES)
27*c960b389SAlexander Graf 
28*c960b389SAlexander Graf #define MAX_FIFO_SIZE     9
29*c960b389SAlexander Graf 
30*c960b389SAlexander Graf #define CMD_KEY           0x1
31*c960b389SAlexander Graf #define CMD_KEY_CONTEXT_SHIFT    27
32*c960b389SAlexander Graf #define CMD_KEY_CONTEXT_MASK     (0x1 << CMD_KEY_CONTEXT_SHIFT)
33*c960b389SAlexander Graf #define CMD_KEY_SELECT_MAX_IDX   0x7
34*c960b389SAlexander Graf #define CMD_KEY_SELECT_SHIFT     24
35*c960b389SAlexander Graf #define CMD_KEY_SELECT_MASK      (CMD_KEY_SELECT_MAX_IDX << CMD_KEY_SELECT_SHIFT)
36*c960b389SAlexander Graf #define CMD_KEY_KEY_LEN_NUM      4u
37*c960b389SAlexander Graf #define CMD_KEY_KEY_LEN_SHIFT    22
38*c960b389SAlexander Graf #define CMD_KEY_KEY_LEN_MASK     ((CMD_KEY_KEY_LEN_NUM - 1u) << CMD_KEY_KEY_LEN_SHIFT)
39*c960b389SAlexander Graf #define CMD_KEY_ENCRYPT_SHIFT    20
40*c960b389SAlexander Graf #define CMD_KEY_ENCRYPT_MASK     (0x1 << CMD_KEY_ENCRYPT_SHIFT)
41*c960b389SAlexander Graf #define CMD_KEY_BLOCK_MODE_SHIFT 16
42*c960b389SAlexander Graf #define CMD_KEY_BLOCK_MODE_MASK  (0x3 << CMD_KEY_BLOCK_MODE_SHIFT)
43*c960b389SAlexander Graf #define CMD_IV            0x2
44*c960b389SAlexander Graf #define CMD_IV_CONTEXT_SHIFT     26
45*c960b389SAlexander Graf #define CMD_IV_CONTEXT_MASK      (0x3 << CMD_KEY_CONTEXT_SHIFT)
46*c960b389SAlexander Graf #define CMD_DSB           0x3
47*c960b389SAlexander Graf #define CMD_SKG           0x4
48*c960b389SAlexander Graf #define CMD_DATA          0x5
49*c960b389SAlexander Graf #define CMD_DATA_KEY_CTX_SHIFT   27
50*c960b389SAlexander Graf #define CMD_DATA_KEY_CTX_MASK    (0x1 << CMD_DATA_KEY_CTX_SHIFT)
51*c960b389SAlexander Graf #define CMD_DATA_IV_CTX_SHIFT    25
52*c960b389SAlexander Graf #define CMD_DATA_IV_CTX_MASK     (0x3 << CMD_DATA_IV_CTX_SHIFT)
53*c960b389SAlexander Graf #define CMD_DATA_LEN_MASK        0xffffff
54*c960b389SAlexander Graf #define CMD_STORE_IV      0x6
55*c960b389SAlexander Graf #define CMD_STORE_IV_ADDR_MASK   0xffffff
56*c960b389SAlexander Graf #define CMD_WRITE_REG     0x7
57*c960b389SAlexander Graf #define CMD_FLAG          0x8
58*c960b389SAlexander Graf #define CMD_FLAG_STOP_MASK       BIT(26)
59*c960b389SAlexander Graf #define CMD_FLAG_RAISE_IRQ_MASK  BIT(27)
60*c960b389SAlexander Graf #define CMD_FLAG_INFO_MASK       0xff
61*c960b389SAlexander Graf #define CMD_MAX           0x10
62*c960b389SAlexander Graf 
63*c960b389SAlexander Graf #define CMD_SHIFT         28
64*c960b389SAlexander Graf 
65*c960b389SAlexander Graf #define REG_STATUS            0xc
66*c960b389SAlexander Graf #define REG_STATUS_DMA_READ_RUNNING     BIT(0)
67*c960b389SAlexander Graf #define REG_STATUS_DMA_READ_PENDING     BIT(1)
68*c960b389SAlexander Graf #define REG_STATUS_DMA_WRITE_RUNNING    BIT(2)
69*c960b389SAlexander Graf #define REG_STATUS_DMA_WRITE_PENDING    BIT(3)
70*c960b389SAlexander Graf #define REG_STATUS_BUSY                 BIT(4)
71*c960b389SAlexander Graf #define REG_STATUS_EXECUTING            BIT(5)
72*c960b389SAlexander Graf #define REG_STATUS_READY                BIT(6)
73*c960b389SAlexander Graf #define REG_STATUS_TEXT_DPA_SEEDED      BIT(7)
74*c960b389SAlexander Graf #define REG_STATUS_UNWRAP_DPA_SEEDED    BIT(8)
75*c960b389SAlexander Graf 
76*c960b389SAlexander Graf #define REG_IRQ_STATUS        0x18
77*c960b389SAlexander Graf #define REG_IRQ_STATUS_INVALID_CMD      BIT(2)
78*c960b389SAlexander Graf #define REG_IRQ_STATUS_FLAG             BIT(5)
79*c960b389SAlexander Graf #define REG_IRQ_ENABLE        0x1c
80*c960b389SAlexander Graf #define REG_WATERMARK         0x20
81*c960b389SAlexander Graf #define REG_Q_STATUS          0x24
82*c960b389SAlexander Graf #define REG_FLAG_INFO         0x30
83*c960b389SAlexander Graf #define REG_FIFO              0x200
84*c960b389SAlexander Graf 
85*c960b389SAlexander Graf static const uint32_t key_lens[CMD_KEY_KEY_LEN_NUM] = {
86*c960b389SAlexander Graf     [0] = 16,
87*c960b389SAlexander Graf     [1] = 24,
88*c960b389SAlexander Graf     [2] = 32,
89*c960b389SAlexander Graf     [3] = 64,
90*c960b389SAlexander Graf };
91*c960b389SAlexander Graf 
92*c960b389SAlexander Graf typedef struct Key {
93*c960b389SAlexander Graf     uint32_t key_len;
94*c960b389SAlexander Graf     uint8_t key[32];
95*c960b389SAlexander Graf } Key;
96*c960b389SAlexander Graf 
97*c960b389SAlexander Graf typedef struct IV {
98*c960b389SAlexander Graf     uint32_t iv[4];
99*c960b389SAlexander Graf } IV;
100*c960b389SAlexander Graf 
101*c960b389SAlexander Graf static Key builtin_keys[CMD_KEY_SELECT_MAX_IDX + 1] = {
102*c960b389SAlexander Graf     [1] = {
103*c960b389SAlexander Graf         .key_len = 32,
104*c960b389SAlexander Graf         .key = { 0x1 },
105*c960b389SAlexander Graf     },
106*c960b389SAlexander Graf     [2] = {
107*c960b389SAlexander Graf         .key_len = 32,
108*c960b389SAlexander Graf         .key = { 0x2 },
109*c960b389SAlexander Graf     },
110*c960b389SAlexander Graf     [3] = {
111*c960b389SAlexander Graf         .key_len = 32,
112*c960b389SAlexander Graf         .key = { 0x3 },
113*c960b389SAlexander Graf     }
114*c960b389SAlexander Graf };
115*c960b389SAlexander Graf 
116*c960b389SAlexander Graf struct AESState {
117*c960b389SAlexander Graf     SysBusDevice parent_obj;
118*c960b389SAlexander Graf 
119*c960b389SAlexander Graf     qemu_irq irq;
120*c960b389SAlexander Graf     MemoryRegion iomem1;
121*c960b389SAlexander Graf     MemoryRegion iomem2;
122*c960b389SAlexander Graf     AddressSpace *as;
123*c960b389SAlexander Graf 
124*c960b389SAlexander Graf     uint32_t status;
125*c960b389SAlexander Graf     uint32_t q_status;
126*c960b389SAlexander Graf     uint32_t irq_status;
127*c960b389SAlexander Graf     uint32_t irq_enable;
128*c960b389SAlexander Graf     uint32_t watermark;
129*c960b389SAlexander Graf     uint32_t flag_info;
130*c960b389SAlexander Graf     uint32_t fifo[MAX_FIFO_SIZE];
131*c960b389SAlexander Graf     uint32_t fifo_idx;
132*c960b389SAlexander Graf     Key key[2];
133*c960b389SAlexander Graf     IV iv[4];
134*c960b389SAlexander Graf     bool is_encrypt;
135*c960b389SAlexander Graf     QCryptoCipherMode block_mode;
136*c960b389SAlexander Graf };
137*c960b389SAlexander Graf 
aes_update_irq(AESState * s)138*c960b389SAlexander Graf static void aes_update_irq(AESState *s)
139*c960b389SAlexander Graf {
140*c960b389SAlexander Graf     qemu_set_irq(s->irq, !!(s->irq_status & s->irq_enable));
141*c960b389SAlexander Graf }
142*c960b389SAlexander Graf 
aes1_read(void * opaque,hwaddr offset,unsigned size)143*c960b389SAlexander Graf static uint64_t aes1_read(void *opaque, hwaddr offset, unsigned size)
144*c960b389SAlexander Graf {
145*c960b389SAlexander Graf     AESState *s = opaque;
146*c960b389SAlexander Graf     uint64_t res = 0;
147*c960b389SAlexander Graf 
148*c960b389SAlexander Graf     switch (offset) {
149*c960b389SAlexander Graf     case REG_STATUS:
150*c960b389SAlexander Graf         res = s->status;
151*c960b389SAlexander Graf         break;
152*c960b389SAlexander Graf     case REG_IRQ_STATUS:
153*c960b389SAlexander Graf         res = s->irq_status;
154*c960b389SAlexander Graf         break;
155*c960b389SAlexander Graf     case REG_IRQ_ENABLE:
156*c960b389SAlexander Graf         res = s->irq_enable;
157*c960b389SAlexander Graf         break;
158*c960b389SAlexander Graf     case REG_WATERMARK:
159*c960b389SAlexander Graf         res = s->watermark;
160*c960b389SAlexander Graf         break;
161*c960b389SAlexander Graf     case REG_Q_STATUS:
162*c960b389SAlexander Graf         res = s->q_status;
163*c960b389SAlexander Graf         break;
164*c960b389SAlexander Graf     case REG_FLAG_INFO:
165*c960b389SAlexander Graf         res = s->flag_info;
166*c960b389SAlexander Graf         break;
167*c960b389SAlexander Graf 
168*c960b389SAlexander Graf     default:
169*c960b389SAlexander Graf         qemu_log_mask(LOG_UNIMP, "%s: Unknown AES MMIO offset %" PRIx64 "\n",
170*c960b389SAlexander Graf                       __func__, offset);
171*c960b389SAlexander Graf         break;
172*c960b389SAlexander Graf     }
173*c960b389SAlexander Graf 
174*c960b389SAlexander Graf     trace_aes_read(offset, res);
175*c960b389SAlexander Graf 
176*c960b389SAlexander Graf     return res;
177*c960b389SAlexander Graf }
178*c960b389SAlexander Graf 
fifo_append(AESState * s,uint64_t val)179*c960b389SAlexander Graf static void fifo_append(AESState *s, uint64_t val)
180*c960b389SAlexander Graf {
181*c960b389SAlexander Graf     if (s->fifo_idx == MAX_FIFO_SIZE) {
182*c960b389SAlexander Graf         /* Exceeded the FIFO. Bail out */
183*c960b389SAlexander Graf         return;
184*c960b389SAlexander Graf     }
185*c960b389SAlexander Graf 
186*c960b389SAlexander Graf     s->fifo[s->fifo_idx++] = val;
187*c960b389SAlexander Graf }
188*c960b389SAlexander Graf 
has_payload(AESState * s,uint32_t elems)189*c960b389SAlexander Graf static bool has_payload(AESState *s, uint32_t elems)
190*c960b389SAlexander Graf {
191*c960b389SAlexander Graf     return s->fifo_idx >= elems + 1;
192*c960b389SAlexander Graf }
193*c960b389SAlexander Graf 
cmd_key(AESState * s)194*c960b389SAlexander Graf static bool cmd_key(AESState *s)
195*c960b389SAlexander Graf {
196*c960b389SAlexander Graf     uint32_t cmd = s->fifo[0];
197*c960b389SAlexander Graf     uint32_t key_select = (cmd & CMD_KEY_SELECT_MASK) >> CMD_KEY_SELECT_SHIFT;
198*c960b389SAlexander Graf     uint32_t ctxt = (cmd & CMD_KEY_CONTEXT_MASK) >> CMD_KEY_CONTEXT_SHIFT;
199*c960b389SAlexander Graf     uint32_t key_len;
200*c960b389SAlexander Graf 
201*c960b389SAlexander Graf     switch ((cmd & CMD_KEY_BLOCK_MODE_MASK) >> CMD_KEY_BLOCK_MODE_SHIFT) {
202*c960b389SAlexander Graf     case 0:
203*c960b389SAlexander Graf         s->block_mode = QCRYPTO_CIPHER_MODE_ECB;
204*c960b389SAlexander Graf         break;
205*c960b389SAlexander Graf     case 1:
206*c960b389SAlexander Graf         s->block_mode = QCRYPTO_CIPHER_MODE_CBC;
207*c960b389SAlexander Graf         break;
208*c960b389SAlexander Graf     default:
209*c960b389SAlexander Graf         return false;
210*c960b389SAlexander Graf     }
211*c960b389SAlexander Graf 
212*c960b389SAlexander Graf     s->is_encrypt = cmd & CMD_KEY_ENCRYPT_MASK;
213*c960b389SAlexander Graf     key_len = key_lens[(cmd & CMD_KEY_KEY_LEN_MASK) >> CMD_KEY_KEY_LEN_SHIFT];
214*c960b389SAlexander Graf 
215*c960b389SAlexander Graf     if (key_select) {
216*c960b389SAlexander Graf         trace_aes_cmd_key_select_builtin(ctxt, key_select,
217*c960b389SAlexander Graf                                          s->is_encrypt ? "en" : "de",
218*c960b389SAlexander Graf                                          QCryptoCipherMode_str(s->block_mode));
219*c960b389SAlexander Graf         s->key[ctxt] = builtin_keys[key_select];
220*c960b389SAlexander Graf     } else {
221*c960b389SAlexander Graf         trace_aes_cmd_key_select_new(ctxt, key_len,
222*c960b389SAlexander Graf                                      s->is_encrypt ? "en" : "de",
223*c960b389SAlexander Graf                                      QCryptoCipherMode_str(s->block_mode));
224*c960b389SAlexander Graf         if (key_len > sizeof(s->key[ctxt].key)) {
225*c960b389SAlexander Graf             return false;
226*c960b389SAlexander Graf         }
227*c960b389SAlexander Graf         if (!has_payload(s, key_len / sizeof(uint32_t))) {
228*c960b389SAlexander Graf             /* wait for payload */
229*c960b389SAlexander Graf             qemu_log_mask(LOG_GUEST_ERROR, "%s: No payload\n", __func__);
230*c960b389SAlexander Graf             return false;
231*c960b389SAlexander Graf         }
232*c960b389SAlexander Graf         memcpy(&s->key[ctxt].key, &s->fifo[1], key_len);
233*c960b389SAlexander Graf         s->key[ctxt].key_len = key_len;
234*c960b389SAlexander Graf     }
235*c960b389SAlexander Graf 
236*c960b389SAlexander Graf     return true;
237*c960b389SAlexander Graf }
238*c960b389SAlexander Graf 
cmd_iv(AESState * s)239*c960b389SAlexander Graf static bool cmd_iv(AESState *s)
240*c960b389SAlexander Graf {
241*c960b389SAlexander Graf     uint32_t cmd = s->fifo[0];
242*c960b389SAlexander Graf     uint32_t ctxt = (cmd & CMD_IV_CONTEXT_MASK) >> CMD_IV_CONTEXT_SHIFT;
243*c960b389SAlexander Graf 
244*c960b389SAlexander Graf     if (!has_payload(s, 4)) {
245*c960b389SAlexander Graf         /* wait for payload */
246*c960b389SAlexander Graf         return false;
247*c960b389SAlexander Graf     }
248*c960b389SAlexander Graf     memcpy(&s->iv[ctxt].iv, &s->fifo[1], sizeof(s->iv[ctxt].iv));
249*c960b389SAlexander Graf     trace_aes_cmd_iv(ctxt, s->fifo[1], s->fifo[2], s->fifo[3], s->fifo[4]);
250*c960b389SAlexander Graf 
251*c960b389SAlexander Graf     return true;
252*c960b389SAlexander Graf }
253*c960b389SAlexander Graf 
dump_data(const char * desc,const void * p,size_t len)254*c960b389SAlexander Graf static void dump_data(const char *desc, const void *p, size_t len)
255*c960b389SAlexander Graf {
256*c960b389SAlexander Graf     static const size_t MAX_LEN = 0x1000;
257*c960b389SAlexander Graf     char hex[MAX_LEN * 2 + 1] = "";
258*c960b389SAlexander Graf 
259*c960b389SAlexander Graf     if (len > MAX_LEN) {
260*c960b389SAlexander Graf         return;
261*c960b389SAlexander Graf     }
262*c960b389SAlexander Graf 
263*c960b389SAlexander Graf     qemu_hexdump_to_buffer(hex, sizeof(hex), p, len);
264*c960b389SAlexander Graf     trace_aes_dump_data(desc, hex);
265*c960b389SAlexander Graf }
266*c960b389SAlexander Graf 
cmd_data(AESState * s)267*c960b389SAlexander Graf static bool cmd_data(AESState *s)
268*c960b389SAlexander Graf {
269*c960b389SAlexander Graf     uint32_t cmd = s->fifo[0];
270*c960b389SAlexander Graf     uint32_t ctxt_iv = 0;
271*c960b389SAlexander Graf     uint32_t ctxt_key = (cmd & CMD_DATA_KEY_CTX_MASK) >> CMD_DATA_KEY_CTX_SHIFT;
272*c960b389SAlexander Graf     uint32_t len = cmd & CMD_DATA_LEN_MASK;
273*c960b389SAlexander Graf     uint64_t src_addr = s->fifo[2];
274*c960b389SAlexander Graf     uint64_t dst_addr = s->fifo[3];
275*c960b389SAlexander Graf     QCryptoCipherAlgo alg;
276*c960b389SAlexander Graf     g_autoptr(QCryptoCipher) cipher = NULL;
277*c960b389SAlexander Graf     g_autoptr(GByteArray) src = NULL;
278*c960b389SAlexander Graf     g_autoptr(GByteArray) dst = NULL;
279*c960b389SAlexander Graf     MemTxResult r;
280*c960b389SAlexander Graf 
281*c960b389SAlexander Graf     src_addr |= ((uint64_t)s->fifo[1] << 16) & 0xffff00000000ULL;
282*c960b389SAlexander Graf     dst_addr |= ((uint64_t)s->fifo[1] << 32) & 0xffff00000000ULL;
283*c960b389SAlexander Graf 
284*c960b389SAlexander Graf     trace_aes_cmd_data(ctxt_key, ctxt_iv, src_addr, dst_addr, len);
285*c960b389SAlexander Graf 
286*c960b389SAlexander Graf     if (!has_payload(s, 3)) {
287*c960b389SAlexander Graf         /* wait for payload */
288*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: No payload\n", __func__);
289*c960b389SAlexander Graf         return false;
290*c960b389SAlexander Graf     }
291*c960b389SAlexander Graf 
292*c960b389SAlexander Graf     if (ctxt_key >= ARRAY_SIZE(s->key) ||
293*c960b389SAlexander Graf         ctxt_iv >= ARRAY_SIZE(s->iv)) {
294*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid key or iv\n", __func__);
295*c960b389SAlexander Graf         return false;
296*c960b389SAlexander Graf     }
297*c960b389SAlexander Graf 
298*c960b389SAlexander Graf     src = g_byte_array_sized_new(len);
299*c960b389SAlexander Graf     g_byte_array_set_size(src, len);
300*c960b389SAlexander Graf     dst = g_byte_array_sized_new(len);
301*c960b389SAlexander Graf     g_byte_array_set_size(dst, len);
302*c960b389SAlexander Graf 
303*c960b389SAlexander Graf     r = dma_memory_read(s->as, src_addr, src->data, len, MEMTXATTRS_UNSPECIFIED);
304*c960b389SAlexander Graf     if (r != MEMTX_OK) {
305*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA read of %"PRIu32" bytes "
306*c960b389SAlexander Graf                       "from 0x%"PRIx64" failed. (r=%d)\n",
307*c960b389SAlexander Graf                       __func__, len, src_addr, r);
308*c960b389SAlexander Graf         return false;
309*c960b389SAlexander Graf     }
310*c960b389SAlexander Graf 
311*c960b389SAlexander Graf     dump_data("cmd_data(): src_data=", src->data, len);
312*c960b389SAlexander Graf 
313*c960b389SAlexander Graf     switch (s->key[ctxt_key].key_len) {
314*c960b389SAlexander Graf     case 128 / 8:
315*c960b389SAlexander Graf         alg = QCRYPTO_CIPHER_ALGO_AES_128;
316*c960b389SAlexander Graf         break;
317*c960b389SAlexander Graf     case 192 / 8:
318*c960b389SAlexander Graf         alg = QCRYPTO_CIPHER_ALGO_AES_192;
319*c960b389SAlexander Graf         break;
320*c960b389SAlexander Graf     case 256 / 8:
321*c960b389SAlexander Graf         alg = QCRYPTO_CIPHER_ALGO_AES_256;
322*c960b389SAlexander Graf         break;
323*c960b389SAlexander Graf     default:
324*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid key length\n", __func__);
325*c960b389SAlexander Graf         return false;
326*c960b389SAlexander Graf     }
327*c960b389SAlexander Graf     cipher = qcrypto_cipher_new(alg, s->block_mode,
328*c960b389SAlexander Graf                                 s->key[ctxt_key].key,
329*c960b389SAlexander Graf                                 s->key[ctxt_key].key_len, NULL);
330*c960b389SAlexander Graf     if (!cipher) {
331*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to create cipher object\n",
332*c960b389SAlexander Graf                       __func__);
333*c960b389SAlexander Graf         return false;
334*c960b389SAlexander Graf     }
335*c960b389SAlexander Graf     if (s->block_mode != QCRYPTO_CIPHER_MODE_ECB) {
336*c960b389SAlexander Graf         if (qcrypto_cipher_setiv(cipher, (void *)s->iv[ctxt_iv].iv,
337*c960b389SAlexander Graf                                  sizeof(s->iv[ctxt_iv].iv), NULL) != 0) {
338*c960b389SAlexander Graf             qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to set IV\n", __func__);
339*c960b389SAlexander Graf             return false;
340*c960b389SAlexander Graf         }
341*c960b389SAlexander Graf     }
342*c960b389SAlexander Graf     if (s->is_encrypt) {
343*c960b389SAlexander Graf         if (qcrypto_cipher_encrypt(cipher, src->data, dst->data, len, NULL) != 0) {
344*c960b389SAlexander Graf             qemu_log_mask(LOG_GUEST_ERROR, "%s: Encryption failed\n", __func__);
345*c960b389SAlexander Graf             return false;
346*c960b389SAlexander Graf         }
347*c960b389SAlexander Graf     } else {
348*c960b389SAlexander Graf         if (qcrypto_cipher_decrypt(cipher, src->data, dst->data, len, NULL) != 0) {
349*c960b389SAlexander Graf             qemu_log_mask(LOG_GUEST_ERROR, "%s: Decryption failed\n", __func__);
350*c960b389SAlexander Graf             return false;
351*c960b389SAlexander Graf         }
352*c960b389SAlexander Graf     }
353*c960b389SAlexander Graf 
354*c960b389SAlexander Graf     dump_data("cmd_data(): dst_data=", dst->data, len);
355*c960b389SAlexander Graf     r = dma_memory_write(s->as, dst_addr, dst->data, len, MEMTXATTRS_UNSPECIFIED);
356*c960b389SAlexander Graf     if (r != MEMTX_OK) {
357*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA write of %"PRIu32" bytes "
358*c960b389SAlexander Graf                       "to 0x%"PRIx64" failed. (r=%d)\n",
359*c960b389SAlexander Graf                       __func__, len, src_addr, r);
360*c960b389SAlexander Graf         return false;
361*c960b389SAlexander Graf     }
362*c960b389SAlexander Graf 
363*c960b389SAlexander Graf     return true;
364*c960b389SAlexander Graf }
365*c960b389SAlexander Graf 
cmd_store_iv(AESState * s)366*c960b389SAlexander Graf static bool cmd_store_iv(AESState *s)
367*c960b389SAlexander Graf {
368*c960b389SAlexander Graf     uint32_t cmd = s->fifo[0];
369*c960b389SAlexander Graf     uint32_t ctxt = (cmd & CMD_IV_CONTEXT_MASK) >> CMD_IV_CONTEXT_SHIFT;
370*c960b389SAlexander Graf     uint64_t addr = s->fifo[1];
371*c960b389SAlexander Graf     MemTxResult dma_result;
372*c960b389SAlexander Graf 
373*c960b389SAlexander Graf     if (!has_payload(s, 1)) {
374*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR, "%s: No payload\n", __func__);
375*c960b389SAlexander Graf         return false;
376*c960b389SAlexander Graf     }
377*c960b389SAlexander Graf 
378*c960b389SAlexander Graf     if (ctxt >= ARRAY_SIZE(s->iv)) {
379*c960b389SAlexander Graf         qemu_log_mask(LOG_GUEST_ERROR,
380*c960b389SAlexander Graf                       "%s: Invalid context. ctxt = %u, allowed: 0..%zu\n",
381*c960b389SAlexander Graf                       __func__, ctxt, ARRAY_SIZE(s->iv) - 1);
382*c960b389SAlexander Graf         return false;
383*c960b389SAlexander Graf     }
384*c960b389SAlexander Graf 
385*c960b389SAlexander Graf     addr |= ((uint64_t)cmd << 32) & 0xff00000000ULL;
386*c960b389SAlexander Graf     dma_result = dma_memory_write(&address_space_memory, addr,
387*c960b389SAlexander Graf                                   &s->iv[ctxt].iv, sizeof(s->iv[ctxt].iv),
388*c960b389SAlexander Graf                                   MEMTXATTRS_UNSPECIFIED);
389*c960b389SAlexander Graf 
390*c960b389SAlexander Graf     trace_aes_cmd_store_iv(ctxt, addr, s->iv[ctxt].iv[0], s->iv[ctxt].iv[1],
391*c960b389SAlexander Graf                            s->iv[ctxt].iv[2], s->iv[ctxt].iv[3]);
392*c960b389SAlexander Graf 
393*c960b389SAlexander Graf     return dma_result == MEMTX_OK;
394*c960b389SAlexander Graf }
395*c960b389SAlexander Graf 
cmd_flag(AESState * s)396*c960b389SAlexander Graf static bool cmd_flag(AESState *s)
397*c960b389SAlexander Graf {
398*c960b389SAlexander Graf     uint32_t cmd = s->fifo[0];
399*c960b389SAlexander Graf     uint32_t raise_irq = cmd & CMD_FLAG_RAISE_IRQ_MASK;
400*c960b389SAlexander Graf 
401*c960b389SAlexander Graf     /* We always process data when it's coming in, so fire an IRQ immediately */
402*c960b389SAlexander Graf     if (raise_irq) {
403*c960b389SAlexander Graf         s->irq_status |= REG_IRQ_STATUS_FLAG;
404*c960b389SAlexander Graf     }
405*c960b389SAlexander Graf 
406*c960b389SAlexander Graf     s->flag_info = cmd & CMD_FLAG_INFO_MASK;
407*c960b389SAlexander Graf 
408*c960b389SAlexander Graf     trace_aes_cmd_flag(!!raise_irq, s->flag_info);
409*c960b389SAlexander Graf 
410*c960b389SAlexander Graf     return true;
411*c960b389SAlexander Graf }
412*c960b389SAlexander Graf 
fifo_process(AESState * s)413*c960b389SAlexander Graf static void fifo_process(AESState *s)
414*c960b389SAlexander Graf {
415*c960b389SAlexander Graf     uint32_t cmd = s->fifo[0] >> CMD_SHIFT;
416*c960b389SAlexander Graf     bool success = false;
417*c960b389SAlexander Graf 
418*c960b389SAlexander Graf     if (!s->fifo_idx) {
419*c960b389SAlexander Graf         return;
420*c960b389SAlexander Graf     }
421*c960b389SAlexander Graf 
422*c960b389SAlexander Graf     switch (cmd) {
423*c960b389SAlexander Graf     case CMD_KEY:
424*c960b389SAlexander Graf         success = cmd_key(s);
425*c960b389SAlexander Graf         break;
426*c960b389SAlexander Graf     case CMD_IV:
427*c960b389SAlexander Graf         success = cmd_iv(s);
428*c960b389SAlexander Graf         break;
429*c960b389SAlexander Graf     case CMD_DATA:
430*c960b389SAlexander Graf         success = cmd_data(s);
431*c960b389SAlexander Graf         break;
432*c960b389SAlexander Graf     case CMD_STORE_IV:
433*c960b389SAlexander Graf         success = cmd_store_iv(s);
434*c960b389SAlexander Graf         break;
435*c960b389SAlexander Graf     case CMD_FLAG:
436*c960b389SAlexander Graf         success = cmd_flag(s);
437*c960b389SAlexander Graf         break;
438*c960b389SAlexander Graf     default:
439*c960b389SAlexander Graf         s->irq_status |= REG_IRQ_STATUS_INVALID_CMD;
440*c960b389SAlexander Graf         break;
441*c960b389SAlexander Graf     }
442*c960b389SAlexander Graf 
443*c960b389SAlexander Graf     if (success) {
444*c960b389SAlexander Graf         s->fifo_idx = 0;
445*c960b389SAlexander Graf     }
446*c960b389SAlexander Graf 
447*c960b389SAlexander Graf     trace_aes_fifo_process(cmd, success);
448*c960b389SAlexander Graf }
449*c960b389SAlexander Graf 
aes1_write(void * opaque,hwaddr offset,uint64_t val,unsigned size)450*c960b389SAlexander Graf static void aes1_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
451*c960b389SAlexander Graf {
452*c960b389SAlexander Graf     AESState *s = opaque;
453*c960b389SAlexander Graf 
454*c960b389SAlexander Graf     trace_aes_write(offset, val);
455*c960b389SAlexander Graf 
456*c960b389SAlexander Graf     switch (offset) {
457*c960b389SAlexander Graf     case REG_IRQ_STATUS:
458*c960b389SAlexander Graf         s->irq_status &= ~val;
459*c960b389SAlexander Graf         break;
460*c960b389SAlexander Graf     case REG_IRQ_ENABLE:
461*c960b389SAlexander Graf         s->irq_enable = val;
462*c960b389SAlexander Graf         break;
463*c960b389SAlexander Graf     case REG_FIFO:
464*c960b389SAlexander Graf         fifo_append(s, val);
465*c960b389SAlexander Graf         fifo_process(s);
466*c960b389SAlexander Graf         break;
467*c960b389SAlexander Graf     default:
468*c960b389SAlexander Graf         qemu_log_mask(LOG_UNIMP,
469*c960b389SAlexander Graf                       "%s: Unknown AES MMIO offset %"PRIx64", data %"PRIx64"\n",
470*c960b389SAlexander Graf                       __func__, offset, val);
471*c960b389SAlexander Graf         return;
472*c960b389SAlexander Graf     }
473*c960b389SAlexander Graf 
474*c960b389SAlexander Graf     aes_update_irq(s);
475*c960b389SAlexander Graf }
476*c960b389SAlexander Graf 
477*c960b389SAlexander Graf static const MemoryRegionOps aes1_ops = {
478*c960b389SAlexander Graf     .read = aes1_read,
479*c960b389SAlexander Graf     .write = aes1_write,
480*c960b389SAlexander Graf     .endianness = DEVICE_NATIVE_ENDIAN,
481*c960b389SAlexander Graf     .valid = {
482*c960b389SAlexander Graf         .min_access_size = 4,
483*c960b389SAlexander Graf         .max_access_size = 8,
484*c960b389SAlexander Graf     },
485*c960b389SAlexander Graf     .impl = {
486*c960b389SAlexander Graf         .min_access_size = 4,
487*c960b389SAlexander Graf         .max_access_size = 4,
488*c960b389SAlexander Graf     },
489*c960b389SAlexander Graf };
490*c960b389SAlexander Graf 
aes2_read(void * opaque,hwaddr offset,unsigned size)491*c960b389SAlexander Graf static uint64_t aes2_read(void *opaque, hwaddr offset, unsigned size)
492*c960b389SAlexander Graf {
493*c960b389SAlexander Graf     uint64_t res = 0;
494*c960b389SAlexander Graf 
495*c960b389SAlexander Graf     switch (offset) {
496*c960b389SAlexander Graf     case 0:
497*c960b389SAlexander Graf         res = 0;
498*c960b389SAlexander Graf         break;
499*c960b389SAlexander Graf     default:
500*c960b389SAlexander Graf         qemu_log_mask(LOG_UNIMP,
501*c960b389SAlexander Graf                       "%s: Unknown AES MMIO 2 offset %"PRIx64"\n",
502*c960b389SAlexander Graf                       __func__, offset);
503*c960b389SAlexander Graf         break;
504*c960b389SAlexander Graf     }
505*c960b389SAlexander Graf 
506*c960b389SAlexander Graf     trace_aes_2_read(offset, res);
507*c960b389SAlexander Graf 
508*c960b389SAlexander Graf     return res;
509*c960b389SAlexander Graf }
510*c960b389SAlexander Graf 
aes2_write(void * opaque,hwaddr offset,uint64_t val,unsigned size)511*c960b389SAlexander Graf static void aes2_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
512*c960b389SAlexander Graf {
513*c960b389SAlexander Graf     trace_aes_2_write(offset, val);
514*c960b389SAlexander Graf 
515*c960b389SAlexander Graf     switch (offset) {
516*c960b389SAlexander Graf     default:
517*c960b389SAlexander Graf         qemu_log_mask(LOG_UNIMP,
518*c960b389SAlexander Graf                       "%s: Unknown AES MMIO 2 offset %"PRIx64", data %"PRIx64"\n",
519*c960b389SAlexander Graf                       __func__, offset, val);
520*c960b389SAlexander Graf         return;
521*c960b389SAlexander Graf     }
522*c960b389SAlexander Graf }
523*c960b389SAlexander Graf 
524*c960b389SAlexander Graf static const MemoryRegionOps aes2_ops = {
525*c960b389SAlexander Graf     .read = aes2_read,
526*c960b389SAlexander Graf     .write = aes2_write,
527*c960b389SAlexander Graf     .endianness = DEVICE_NATIVE_ENDIAN,
528*c960b389SAlexander Graf     .valid = {
529*c960b389SAlexander Graf         .min_access_size = 4,
530*c960b389SAlexander Graf         .max_access_size = 8,
531*c960b389SAlexander Graf     },
532*c960b389SAlexander Graf     .impl = {
533*c960b389SAlexander Graf         .min_access_size = 4,
534*c960b389SAlexander Graf         .max_access_size = 4,
535*c960b389SAlexander Graf     },
536*c960b389SAlexander Graf };
537*c960b389SAlexander Graf 
aes_reset(Object * obj,ResetType type)538*c960b389SAlexander Graf static void aes_reset(Object *obj, ResetType type)
539*c960b389SAlexander Graf {
540*c960b389SAlexander Graf     AESState *s = APPLE_AES(obj);
541*c960b389SAlexander Graf 
542*c960b389SAlexander Graf     s->status = 0x3f80;
543*c960b389SAlexander Graf     s->q_status = 2;
544*c960b389SAlexander Graf     s->irq_status = 0;
545*c960b389SAlexander Graf     s->irq_enable = 0;
546*c960b389SAlexander Graf     s->watermark = 0;
547*c960b389SAlexander Graf }
548*c960b389SAlexander Graf 
aes_init(Object * obj)549*c960b389SAlexander Graf static void aes_init(Object *obj)
550*c960b389SAlexander Graf {
551*c960b389SAlexander Graf     AESState *s = APPLE_AES(obj);
552*c960b389SAlexander Graf 
553*c960b389SAlexander Graf     memory_region_init_io(&s->iomem1, obj, &aes1_ops, s, TYPE_APPLE_AES, 0x4000);
554*c960b389SAlexander Graf     memory_region_init_io(&s->iomem2, obj, &aes2_ops, s, TYPE_APPLE_AES, 0x4000);
555*c960b389SAlexander Graf     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem1);
556*c960b389SAlexander Graf     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem2);
557*c960b389SAlexander Graf     sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
558*c960b389SAlexander Graf     s->as = &address_space_memory;
559*c960b389SAlexander Graf }
560*c960b389SAlexander Graf 
aes_class_init(ObjectClass * klass,void * data)561*c960b389SAlexander Graf static void aes_class_init(ObjectClass *klass, void *data)
562*c960b389SAlexander Graf {
563*c960b389SAlexander Graf     ResettableClass *rc = RESETTABLE_CLASS(klass);
564*c960b389SAlexander Graf 
565*c960b389SAlexander Graf     rc->phases.hold = aes_reset;
566*c960b389SAlexander Graf }
567*c960b389SAlexander Graf 
568*c960b389SAlexander Graf static const TypeInfo aes_info = {
569*c960b389SAlexander Graf     .name          = TYPE_APPLE_AES,
570*c960b389SAlexander Graf     .parent        = TYPE_SYS_BUS_DEVICE,
571*c960b389SAlexander Graf     .instance_size = sizeof(AESState),
572*c960b389SAlexander Graf     .class_init    = aes_class_init,
573*c960b389SAlexander Graf     .instance_init = aes_init,
574*c960b389SAlexander Graf };
575*c960b389SAlexander Graf 
aes_register_types(void)576*c960b389SAlexander Graf static void aes_register_types(void)
577*c960b389SAlexander Graf {
578*c960b389SAlexander Graf     type_register_static(&aes_info);
579*c960b389SAlexander Graf }
580*c960b389SAlexander Graf 
581*c960b389SAlexander Graf type_init(aes_register_types)
582