1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include "qemu/osdep.h"
29#include "qemu/log.h"
30#include "qemu/error-report.h"
31#include "qapi/error.h"
32#include "hw/misc/xlnx-aes.h"
33#include "migration/vmstate.h"
34#include "hw/qdev-properties.h"
35
36#include "hw/fdt_generic_util.h"
37
38#ifndef XLNX_AES_ERR_DEBUG
39#define XLNX_AES_ERR_DEBUG 0
40#endif
41
42#define XLNX_AES(obj) \
43 OBJECT_CHECK(XlnxAES, (obj), TYPE_XLNX_AES)
44
45#define DPRINT(fmt, args...) do { \
46 if (XLNX_AES_ERR_DEBUG) { \
47 qemu_log("%s:" fmt, __func__, ##args);\
48 } \
49 } while (0)
50
51
52#define DPRINT_NP(fmt, args...) do { \
53 if (XLNX_AES_ERR_DEBUG) { \
54 qemu_log(fmt, ##args); \
55 } \
56 } while (0)
57
58#define XLNX_AES_PACKED_LEN sizeof(((XlnxAES *)0)->pack_buf.u8)
59
60
61static const char *aes_state2str(enum XlnxAESState state)
62{
63 static const char *state2str[] = {
64 [IDLE] = "IDLE",
65 [IV] = "IV",
66 [AAD] = "AAD",
67 [PAYLOAD] = "PAYLOAD",
68 [TAG0] = "TAG0",
69 [TAG1] = "TAG1",
70 [TAG2] = "TAG2",
71 [TAG3] = "TAG3",
72 };
73 return state2str[state];
74}
75
76static int xlnx_check_state(XlnxAES *s,
77 enum XlnxAESState expected,
78 const char *descr)
79{
80 int err = 0;
81 if (s->state != expected) {
82 qemu_log_mask(LOG_GUEST_ERROR,
83 "%s: %s, while state is %s (expected %s)\n",
84 s->prefix, descr,
85 aes_state2str(s->state), aes_state2str(expected));
86 err = 1;
87 }
88 return err;
89}
90
91static void xlnx_aes_set_state(XlnxAES *s, enum XlnxAESState state)
92{
93 assert(state <= TAG3);
94 s->state = state;
95
96 if (s->state != IDLE) {
97 s->inp_ready = 1;
98 } else {
99 s->inp_ready = 0;
100 }
101
102 if (state == AAD) {
103 s->aad_ready = true;
104 }
105}
106
107void xlnx_aes_write_key(XlnxAES *s, unsigned int pos, uint32_t val)
108{
109 if (xlnx_check_state(s, IDLE, "Loading key")) {
110 return;
111 }
112
113 assert(pos < 8);
114
115 s->key[pos] = bswap32(val);
116}
117
118void xlnx_aes_load_key(XlnxAES *s, int len)
119{
120 int i;
121
122 if (xlnx_check_state(s, IDLE, "Loading key")) {
123 return;
124 }
125
126 DPRINT("AES KEY loaded (big endian):\n");
127 for (i = 0; i < len / 32; i++) {
128 DPRINT_NP("0x%08x ", s->key[i]);
129 }
130 DPRINT_NP("\n");
131
132 s->keylen = len;
133 s->key_zeroed = 0;
134}
135
136void xlnx_aes_key_zero(XlnxAES *s)
137{
138 if (xlnx_check_state(s, IDLE, "Clearing key")) {
139 return;
140 }
141 memset(s->key, 0, sizeof s->key);
142 s->key_zeroed = 1;
143}
144
145static void xlnx_aes_load_iv(XlnxAES *s)
146{
147 if (s->state == IV) {
148 unsigned int keylen = s->keylen;
149 int r, i;
150
151 if (keylen == 0) {
152 qemu_log_mask(LOG_GUEST_ERROR, "CSU-AES: Data but no key!\n");
153
154 memset(s->key, 0, sizeof s->key);
155 keylen = 256;
156 }
157 r = gcm_init(&s->gcm_ctx, (void *) s->key, keylen);
158 if (r != 0) {
159 qemu_log_mask(LOG_GUEST_ERROR, "CSU-AES: GCM init failed\n");
160 return;
161 }
162 gcm_push_iv(&s->gcm_ctx, (void *) s->iv, 12, 16);
163 DPRINT("IV (big endian):\n");
164 for (i = 0; i < 4; i++) {
165 DPRINT_NP("0x%08x ", s->iv[i]);
166 }
167 DPRINT_NP("\n");
168 }
169}
170
171static bool xlnx_aes_pack_empty(XlnxAES *s)
172{
173 return s->pack_next == 0;
174}
175
176static bool xlnx_aes_pack_full(XlnxAES *s)
177{
178 return s->pack_next >= XLNX_AES_PACKED_LEN;
179}
180
181static bool xlnx_aes_pack_pad0(XlnxAES *s)
182{
183
184 int pad = XLNX_AES_PACKED_LEN - s->pack_next;
185
186 if (pad > 0 && pad < XLNX_AES_PACKED_LEN) {
187 memset(&s->pack_buf.u8[s->pack_next], 0, pad);
188 s->pack_next = XLNX_AES_PACKED_LEN;
189
190 return true;
191 } else {
192 return xlnx_aes_pack_full(s);
193 }
194}
195
196static unsigned int xlnx_aes_pack_push(XlnxAES *s, const void *data,
197 unsigned len, bool last_word)
198{
199 unsigned next, plen;
200
201 assert(s->state != PAYLOAD);
202
203 if (!len) {
204 return 0;
205 }
206
207 next = s->pack_next;
208 assert(next < XLNX_AES_PACKED_LEN);
209
210 plen = MIN(len, XLNX_AES_PACKED_LEN - next);
211
212 memcpy(&s->pack_buf.u8[next], data, plen);
213 s->pack_next = next + plen;
214
215
216
217
218
219
220
221 if (plen == len && last_word) {
222 xlnx_aes_pack_pad0(s);
223 }
224
225 return plen;
226}
227
228static unsigned xlnx_aes_load_aad(XlnxAES *s, const void *data, unsigned len)
229{
230 assert(s->aad_ready);
231
232
233 if ((const void *)&s->pack_buf == data) {
234 len = s->pack_next;
235 s->pack_next = 0;
236 }
237
238
239 if (!len) {
240 s->aad_ready = false;
241 return 0;
242 }
243
244 if (len & 15) {
245 s->aad_ready = false;
246 }
247
248 gcm_push_aad(&s->gcm_ctx, data, len);
249 return len;
250}
251
252static unsigned xlnx_aes_push_aad(XlnxAES *s, const uint8_t *data,
253 const unsigned len, bool is_aad, void *outbuf)
254{
255 unsigned pos = 0, blen;
256
257 assert(!xlnx_check_state(s, AAD, "Loading AAD"));
258
259 if (!is_aad) {
260
261
262
263
264 xlnx_aes_load_aad(s, &s->pack_buf, 0);
265
266
267 xlnx_aes_set_state(s, PAYLOAD);
268 return 0;
269 }
270
271
272 memcpy(outbuf, data, len);
273
274 if (!xlnx_aes_pack_empty(s)) {
275
276 pos = xlnx_aes_pack_push(s, data, len, false);
277
278
279 if (!xlnx_aes_pack_full(s)) {
280 assert(pos == len);
281 return len;
282 }
283
284 xlnx_aes_load_aad(s, &s->pack_buf, 0);
285 assert(xlnx_aes_pack_empty(s));
286 }
287
288
289 blen = QEMU_ALIGN_DOWN(len, XLNX_AES_PACKED_LEN);
290 if (blen) {
291 pos += xlnx_aes_load_aad(s, &data[pos], blen);
292 }
293
294
295 pos += xlnx_aes_pack_push(s, &data[pos], (len - pos), false);
296
297
298 assert(pos == len);
299 return len;
300}
301
302static unsigned xlnx_aes_push_iv(XlnxAES *s, const void *data,
303 unsigned len, bool last_word)
304{
305 int pos;
306
307 assert(!xlnx_check_state(s, IV, "Loading IV"));
308
309
310 pos = xlnx_aes_pack_push(s, data, len, last_word);
311
312 if (xlnx_aes_pack_full(s)) {
313 memcpy(s->iv, &s->pack_buf, sizeof(s->iv));
314 s->pack_next = 0;
315
316 xlnx_aes_load_iv(s);
317 xlnx_aes_set_state(s, AAD);
318 }
319
320 return pos;
321}
322
323void xlnx_aes_start_message(XlnxAES *s, bool encrypt)
324{
325 if (xlnx_check_state(s, IDLE, "Start message")) {
326
327 xlnx_aes_set_state(s, IDLE);
328 qemu_set_irq(s->s_busy, false);
329 }
330
331 xlnx_aes_set_state(s, IV);
332 s->pack_next = 0;
333 s->encrypt = encrypt;
334 s->tag_ok = 0;
335
336 qemu_set_irq(s->s_done, false);
337 qemu_set_irq(s->s_busy, false);
338}
339
340static void xlnx_aes_done(XlnxAES *s)
341{
342 xlnx_aes_set_state(s, IDLE);
343 qemu_set_irq(s->s_done, true);
344 qemu_set_irq(s->s_busy, false);
345}
346
347
348int xlnx_aes_push_data(XlnxAES *s,
349 const uint8_t *data8, unsigned len,
350 bool is_aad, bool last_word, int lw_len,
351 uint8_t *outbuf, int *outlen)
352{
353 unsigned pos = 0, opos = 0, plen;
354 uint32_t v32;
355
356 assert(!last_word || lw_len == 0 || lw_len == 4);
357 qemu_set_irq(s->s_busy, true);
358
359 while (pos < len) {
360 plen = len - pos;
361 switch (s->state) {
362 case IDLE:
363 qemu_log_mask(LOG_GUEST_ERROR, "AES: Data while idle\n");
364 return len;
365 case IV:
366 pos += xlnx_aes_push_iv(s, &data8[pos], plen, last_word);
367 break;
368 case AAD:
369 plen = xlnx_aes_push_aad(s, &data8[pos], plen, is_aad,
370 outbuf + opos);
371 pos += plen;
372 opos += plen;
373 break;
374 case PAYLOAD:
375 gcm_push_data(&s->gcm_ctx, s->encrypt ? AES_ENCRYPT : AES_DECRYPT,
376 outbuf + opos, &data8[pos], plen);
377 pos += plen;
378 opos += plen;
379 break;
380 case TAG0...TAG3:
381
382 assert(s->encrypt == 0);
383 assert(len >= 4);
384
385 memcpy(&v32, data8 + pos, 4);
386 s->tag[s->state - TAG0] = v32;
387 pos += 4;
388 if (s->state == TAG3) {
389 uint8_t tag[16];
390
391 gcm_emit_tag(&s->gcm_ctx, tag, 16);
392 s->tag_ok = memcmp(s->tag, tag, 16) == 0;
393 if (XLNX_AES_ERR_DEBUG) {
394 qemu_hexdump(stderr, "expected-tag",
395 (void *) s->tag, 16);
396 qemu_hexdump(stderr, "tag", (void *) tag, 16);
397 }
398 xlnx_aes_done(s);
399 goto done;
400 }
401 xlnx_aes_set_state(s, s->state + 1);
402 break;
403 default:
404 assert(0);
405 break;
406 }
407 }
408
409
410 if (last_word && s->state == PAYLOAD) {
411 if (s->encrypt) {
412
413 gcm_emit_tag(&s->gcm_ctx, outbuf + opos, 16);
414 opos += 16;
415 xlnx_aes_done(s);
416 } else {
417
418 xlnx_aes_set_state(s, TAG0);
419 qemu_set_irq(s->s_busy, false);
420 }
421 }
422
423done:
424 if (outlen) {
425 *outlen = opos;
426 }
427 return pos;
428}
429
430static void xlnx_aes_reset(DeviceState *dev)
431{
432 XlnxAES *s = XLNX_AES(dev);
433
434 s->state = IDLE;
435 s->encrypt = false;
436 s->tag_ok = false;
437 s->key_zeroed = false;
438 s->inp_ready = false;
439 memset(s->iv, 0, 16);
440 memset(s->tag, 0, 16);
441 memset(s->key, 0, 32);
442 s->keylen = 256;
443
444 qemu_set_irq(s->s_done, false);
445 qemu_set_irq(s->s_busy, false);
446}
447
448static void reset_handler(void *opaque, int n, int level)
449{
450 XlnxAES *s = XLNX_AES(opaque);
451
452 if (level) {
453 xlnx_aes_reset(DEVICE(s));
454 }
455}
456
457static void xlnx_aes_realize(DeviceState *dev, Error **errp)
458{
459 XlnxAES *s = XLNX_AES(dev);
460
461 qdev_init_gpio_out(dev, &s->s_busy, 1);
462 qdev_init_gpio_out(dev, &s->s_done, 1);
463 qdev_init_gpio_in_named(dev, reset_handler, "reset", 1);
464}
465
466static void xlnx_aes_class_init(ObjectClass *klass, void *data)
467{
468 DeviceClass *dc = DEVICE_CLASS(klass);
469
470 dc->reset = xlnx_aes_reset;
471 dc->realize = xlnx_aes_realize;
472}
473
474static const TypeInfo xlnx_aes_info = {
475 .name = TYPE_XLNX_AES,
476 .parent = TYPE_DEVICE,
477 .instance_size = sizeof(XlnxAES),
478 .class_init = xlnx_aes_class_init,
479};
480
481static void xlnx_aes_types(void)
482{
483 type_register_static(&xlnx_aes_info);
484}
485
486type_init(xlnx_aes_types)
487