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 /* 83 * The MAX78000 AES engine stores an internal key, which it uses only 84 * for decryption. This results in the slighly odd looking pairs of 85 * set_encrypt and set_decrypt calls below; s->internal_key is 86 * being stored for later use in both cases. 87 */ 88 AES_KEY key; 89 if ((s->ctrl & TYPE) == 0) { 90 AES_set_encrypt_key(keydata, keylen, &key); 91 AES_set_decrypt_key(keydata, keylen, &s->internal_key); 92 AES_encrypt(s->data, s->result, &key); 93 s->result_index = 16; 94 } else if ((s->ctrl & TYPE) == 1 << 8) { 95 AES_set_decrypt_key(keydata, keylen, &key); 96 AES_set_decrypt_key(keydata, keylen, &s->internal_key); 97 AES_decrypt(s->data, s->result, &key); 98 s->result_index = 16; 99 } else{ 100 AES_decrypt(s->data, s->result, &s->internal_key); 101 s->result_index = 16; 102 } 103 s->intfl |= DONE; 104 } 105 106 static void max78000_aes_write(void *opaque, hwaddr addr, 107 uint64_t val64, unsigned int size) 108 { 109 Max78000AesState *s = opaque; 110 uint32_t val = val64; 111 switch (addr) { 112 case CTRL: 113 if (val & OUTPUT_FLUSH) { 114 s->result_index = 0; 115 val &= ~OUTPUT_FLUSH; 116 } 117 if (val & INPUT_FLUSH) { 118 s->data_index = 0; 119 val &= ~INPUT_FLUSH; 120 } 121 if (val & START) { 122 max78000_aes_do_crypto(s); 123 } 124 125 /* Hardware appears to stay enabled even if 0 written */ 126 s->ctrl = val | (s->ctrl & AES_EN); 127 break; 128 129 case FIFO: 130 assert(s->data_index <= 12); 131 stl_be_p(&s->data[12 - s->data_index], val); 132 s->data_index += 4; 133 if (s->data_index >= 16) { 134 s->data_index = 0; 135 max78000_aes_do_crypto(s); 136 } 137 break; 138 139 case KEY_BASE ... KEY_END - 4: 140 stl_be_p(&s->key[(KEY_END - KEY_BASE - 4) - (addr - KEY_BASE)], val); 141 break; 142 143 default: 144 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" 145 HWADDR_PRIx "\n", __func__, addr); 146 break; 147 148 } 149 max78000_aes_set_status(s); 150 } 151 152 static void max78000_aes_reset_hold(Object *obj, ResetType type) 153 { 154 Max78000AesState *s = MAX78000_AES(obj); 155 s->ctrl = 0; 156 s->status = 0; 157 s->intfl = 0; 158 s->inten = 0; 159 160 s->data_index = 0; 161 s->result_index = 0; 162 163 memset(s->data, 0, sizeof(s->data)); 164 memset(s->key, 0, sizeof(s->key)); 165 memset(s->result, 0, sizeof(s->result)); 166 memset(&s->internal_key, 0, sizeof(s->internal_key)); 167 } 168 169 static const MemoryRegionOps max78000_aes_ops = { 170 .read = max78000_aes_read, 171 .write = max78000_aes_write, 172 .endianness = DEVICE_LITTLE_ENDIAN, 173 .valid.min_access_size = 4, 174 .valid.max_access_size = 4, 175 }; 176 177 static const VMStateDescription vmstate_max78000_aes = { 178 .name = TYPE_MAX78000_AES, 179 .version_id = 1, 180 .minimum_version_id = 1, 181 .fields = (const VMStateField[]) { 182 VMSTATE_UINT32(ctrl, Max78000AesState), 183 VMSTATE_UINT32(status, Max78000AesState), 184 VMSTATE_UINT32(intfl, Max78000AesState), 185 VMSTATE_UINT32(inten, Max78000AesState), 186 VMSTATE_UINT8_ARRAY(data, Max78000AesState, 16), 187 VMSTATE_UINT8_ARRAY(key, Max78000AesState, 32), 188 VMSTATE_UINT8_ARRAY(result, Max78000AesState, 16), 189 VMSTATE_UINT32_ARRAY(internal_key.rd_key, Max78000AesState, 60), 190 VMSTATE_INT32(internal_key.rounds, Max78000AesState), 191 VMSTATE_END_OF_LIST() 192 } 193 }; 194 195 static void max78000_aes_init(Object *obj) 196 { 197 Max78000AesState *s = MAX78000_AES(obj); 198 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 199 200 memory_region_init_io(&s->mmio, obj, &max78000_aes_ops, s, 201 TYPE_MAX78000_AES, 0xc00); 202 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 203 204 } 205 206 static void max78000_aes_class_init(ObjectClass *klass, const void *data) 207 { 208 ResettableClass *rc = RESETTABLE_CLASS(klass); 209 DeviceClass *dc = DEVICE_CLASS(klass); 210 211 rc->phases.hold = max78000_aes_reset_hold; 212 dc->vmsd = &vmstate_max78000_aes; 213 214 } 215 216 static const TypeInfo max78000_aes_info = { 217 .name = TYPE_MAX78000_AES, 218 .parent = TYPE_SYS_BUS_DEVICE, 219 .instance_size = sizeof(Max78000AesState), 220 .instance_init = max78000_aes_init, 221 .class_init = max78000_aes_class_init, 222 }; 223 224 static void max78000_aes_register_types(void) 225 { 226 type_register_static(&max78000_aes_info); 227 } 228 229 type_init(max78000_aes_register_types) 230