1 /* 2 * MAX78000 AES 3 * 4 * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/log.h" 11 #include "trace.h" 12 #include "hw/irq.h" 13 #include "migration/vmstate.h" 14 #include "hw/misc/max78000_aes.h" 15 #include "crypto/aes.h" 16 17 static void max78000_aes_set_status(Max78000AesState *s) 18 { 19 s->status = 0; 20 if (s->result_index >= 16) { 21 s->status |= OUTPUT_FULL; 22 } 23 if (s->result_index == 0) { 24 s->status |= OUTPUT_EMPTY; 25 } 26 if (s->data_index >= 16) { 27 s->status |= INPUT_FULL; 28 } 29 if (s->data_index == 0) { 30 s->status |= INPUT_EMPTY; 31 } 32 } 33 34 static uint64_t max78000_aes_read(void *opaque, hwaddr addr, 35 unsigned int size) 36 { 37 Max78000AesState *s = opaque; 38 switch (addr) { 39 case CTRL: 40 return s->ctrl; 41 42 case STATUS: 43 return s->status; 44 45 case INTFL: 46 return s->intfl; 47 48 case INTEN: 49 return s->inten; 50 51 case FIFO: 52 if (s->result_index >= 4) { 53 s->intfl &= ~DONE; 54 s->result_index -= 4; 55 max78000_aes_set_status(s); 56 return ldl_be_p(&s->result[s->result_index]); 57 } else{ 58 return 0; 59 } 60 61 default: 62 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" 63 HWADDR_PRIx "\n", __func__, addr); 64 break; 65 66 } 67 return 0; 68 } 69 70 static void max78000_aes_do_crypto(Max78000AesState *s) 71 { 72 int keylen = 256; 73 uint8_t *keydata = s->key; 74 if ((s->ctrl & KEY_SIZE) == 0) { 75 keylen = 128; 76 keydata += 16; 77 } else if ((s->ctrl & KEY_SIZE) == 1 << 6) { 78 keylen = 192; 79 keydata += 8; 80 } 81 82 AES_KEY key; 83 if ((s->ctrl & TYPE) == 0) { 84 AES_set_encrypt_key(keydata, keylen, &key); 85 AES_set_decrypt_key(keydata, keylen, &s->internal_key); 86 AES_encrypt(s->data, s->result, &key); 87 s->result_index = 16; 88 } else if ((s->ctrl & TYPE) == 1 << 8) { 89 AES_set_decrypt_key(keydata, keylen, &key); 90 AES_set_decrypt_key(keydata, keylen, &s->internal_key); 91 AES_decrypt(s->data, s->result, &key); 92 s->result_index = 16; 93 } else{ 94 AES_decrypt(s->data, s->result, &s->internal_key); 95 s->result_index = 16; 96 } 97 s->intfl |= DONE; 98 } 99 100 static void max78000_aes_write(void *opaque, hwaddr addr, 101 uint64_t val64, unsigned int size) 102 { 103 Max78000AesState *s = opaque; 104 uint32_t val = val64; 105 switch (addr) { 106 case CTRL: 107 if (val & OUTPUT_FLUSH) { 108 s->result_index = 0; 109 val &= ~OUTPUT_FLUSH; 110 } 111 if (val & INPUT_FLUSH) { 112 s->data_index = 0; 113 val &= ~INPUT_FLUSH; 114 } 115 if (val & START) { 116 max78000_aes_do_crypto(s); 117 } 118 119 /* Hardware appears to stay enabled even if 0 written */ 120 s->ctrl = val | (s->ctrl & AES_EN); 121 break; 122 123 case FIFO: 124 assert(s->data_index <= 12); 125 stl_be_p(&s->data[12 - s->data_index], val); 126 s->data_index += 4; 127 if (s->data_index >= 16) { 128 s->data_index = 0; 129 max78000_aes_do_crypto(s); 130 } 131 break; 132 133 case KEY_BASE ... KEY_END - 4: 134 stl_be_p(&s->key[(KEY_END - KEY_BASE - 4) - (addr - KEY_BASE)], val); 135 break; 136 137 default: 138 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" 139 HWADDR_PRIx "\n", __func__, addr); 140 break; 141 142 } 143 max78000_aes_set_status(s); 144 } 145 146 static void max78000_aes_reset_hold(Object *obj, ResetType type) 147 { 148 Max78000AesState *s = MAX78000_AES(obj); 149 s->ctrl = 0; 150 s->status = 0; 151 s->intfl = 0; 152 s->inten = 0; 153 154 s->data_index = 0; 155 s->result_index = 0; 156 157 memset(s->data, 0, sizeof(s->data)); 158 memset(s->key, 0, sizeof(s->key)); 159 memset(s->result, 0, sizeof(s->result)); 160 memset(&s->internal_key, 0, sizeof(s->internal_key)); 161 } 162 163 static const MemoryRegionOps max78000_aes_ops = { 164 .read = max78000_aes_read, 165 .write = max78000_aes_write, 166 .endianness = DEVICE_LITTLE_ENDIAN, 167 .valid.min_access_size = 4, 168 .valid.max_access_size = 4, 169 }; 170 171 static const VMStateDescription vmstate_max78000_aes = { 172 .name = TYPE_MAX78000_AES, 173 .version_id = 1, 174 .minimum_version_id = 1, 175 .fields = (const VMStateField[]) { 176 VMSTATE_UINT32(ctrl, Max78000AesState), 177 VMSTATE_UINT32(status, Max78000AesState), 178 VMSTATE_UINT32(intfl, Max78000AesState), 179 VMSTATE_UINT32(inten, Max78000AesState), 180 VMSTATE_UINT8_ARRAY(data, Max78000AesState, 16), 181 VMSTATE_UINT8_ARRAY(key, Max78000AesState, 32), 182 VMSTATE_UINT8_ARRAY(result, Max78000AesState, 16), 183 VMSTATE_UINT32_ARRAY(internal_key.rd_key, Max78000AesState, 60), 184 VMSTATE_INT32(internal_key.rounds, Max78000AesState), 185 VMSTATE_END_OF_LIST() 186 } 187 }; 188 189 static void max78000_aes_init(Object *obj) 190 { 191 Max78000AesState *s = MAX78000_AES(obj); 192 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 193 194 memory_region_init_io(&s->mmio, obj, &max78000_aes_ops, s, 195 TYPE_MAX78000_AES, 0xc00); 196 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 197 198 } 199 200 static void max78000_aes_class_init(ObjectClass *klass, const void *data) 201 { 202 ResettableClass *rc = RESETTABLE_CLASS(klass); 203 DeviceClass *dc = DEVICE_CLASS(klass); 204 205 rc->phases.hold = max78000_aes_reset_hold; 206 dc->vmsd = &vmstate_max78000_aes; 207 208 } 209 210 static const TypeInfo max78000_aes_info = { 211 .name = TYPE_MAX78000_AES, 212 .parent = TYPE_SYS_BUS_DEVICE, 213 .instance_size = sizeof(Max78000AesState), 214 .instance_init = max78000_aes_init, 215 .class_init = max78000_aes_class_init, 216 }; 217 218 static void max78000_aes_register_types(void) 219 { 220 type_register_static(&max78000_aes_info); 221 } 222 223 type_init(max78000_aes_register_types) 224