135 lines
4.1 KiB
C
135 lines
4.1 KiB
C
#include "hw/arm/ipod_touch_aes.h"
|
|
|
|
static uint64_t s5l8900_aes_read(void *opaque, hwaddr offset, unsigned size)
|
|
{
|
|
struct S5L8900AESState *aesop = (struct S5L8900AESState *)opaque;
|
|
|
|
switch(offset) {
|
|
case AES_STATUS:
|
|
return aesop->status;
|
|
default:
|
|
//fprintf(stderr, "%s: UNMAPPED AES_ADDR @ offset 0x%08x\n", __FUNCTION__, offset);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void s5l8900_aes_write(void *opaque, hwaddr offset, uint64_t value, unsigned size)
|
|
{
|
|
struct S5L8900AESState *aesop = (struct S5L8900AESState *)opaque;
|
|
static uint8_t keylenop = 0;
|
|
|
|
uint8_t *inbuf;
|
|
uint8_t *buf;
|
|
|
|
// fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
|
|
|
|
switch(offset) {
|
|
case AES_GO:
|
|
inbuf = (uint8_t *)malloc(aesop->insize);
|
|
cpu_physical_memory_read((aesop->inaddr - 0x80000000), inbuf, aesop->insize);
|
|
|
|
switch(aesop->keytype) {
|
|
case AESGID:
|
|
fprintf(stderr, "%s: No support for GID key\n", __func__);
|
|
return;
|
|
case AESUID:
|
|
AES_set_decrypt_key(key_uid, sizeof(key_uid) * 8, &aesop->decryptKey);
|
|
break;
|
|
case AESCustom:
|
|
AES_set_decrypt_key((uint8_t *)aesop->custkey, 0x20 * 8, &aesop->decryptKey);
|
|
break;
|
|
}
|
|
|
|
buf = (uint8_t *) malloc(aesop->insize);
|
|
|
|
AES_cbc_encrypt(inbuf, buf, aesop->insize, &aesop->decryptKey, (uint8_t *)aesop->ivec, aesop->operation);
|
|
|
|
cpu_physical_memory_write((aesop->outaddr - 0x80000000), buf, aesop->insize);
|
|
memset(aesop->custkey, 0, 0x20);
|
|
memset(aesop->ivec, 0, 0x10);
|
|
free(inbuf);
|
|
free(buf);
|
|
keylenop = 0;
|
|
aesop->outsize = aesop->insize;
|
|
aesop->status = 0xf;
|
|
break;
|
|
case AES_KEYLEN:
|
|
if(keylenop == 1) {
|
|
aesop->operation = value;
|
|
}
|
|
keylenop++;
|
|
aesop->keylen = value;
|
|
break;
|
|
case AES_INADDR:
|
|
aesop->inaddr = value;
|
|
break;
|
|
case AES_INSIZE:
|
|
aesop->insize = value;
|
|
break;
|
|
case AES_OUTSIZE:
|
|
aesop->outsize = value;
|
|
break;
|
|
case AES_OUTADDR:
|
|
aesop->outaddr = value;
|
|
break;
|
|
case AES_TYPE:
|
|
aesop->keytype = value;
|
|
break;
|
|
case AES_KEY_REG ... ((AES_KEY_REG + AES_KEYSIZE) - 1):
|
|
{
|
|
uint8_t idx = (offset - AES_KEY_REG) / 4;
|
|
aesop->custkey[idx] |= value;
|
|
break;
|
|
}
|
|
case AES_IV_REG ... ((AES_IV_REG + AES_IVSIZE) -1 ):
|
|
{
|
|
uint8_t idx = (offset - AES_IV_REG) / 4;
|
|
aesop->ivec[idx] |= value;
|
|
break;
|
|
}
|
|
default:
|
|
//fprintf(stderr, "%s: UNMAPPED AES_ADDR @ offset 0x%08x - 0x%08x\n", __FUNCTION__, offset, value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static const MemoryRegionOps aes_ops = {
|
|
.read = s5l8900_aes_read,
|
|
.write = s5l8900_aes_write,
|
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
|
};
|
|
|
|
static void s5l8900_aes_init(Object *obj)
|
|
{
|
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
|
DeviceState *dev = DEVICE(sbd);
|
|
S5L8900AESState *s = IPOD_TOUCH_AES(dev);
|
|
|
|
memory_region_init_io(&s->iomem, obj, &aes_ops, s, "aes", 0x100);
|
|
sysbus_init_mmio(sbd, &s->iomem);
|
|
|
|
memset(&s->custkey, 0, 8 * sizeof(uint32_t));
|
|
memset(&s->ivec, 0, 4 * sizeof(uint32_t));
|
|
}
|
|
|
|
static void s5l8900_aes_class_init(ObjectClass *klass, void *data)
|
|
{
|
|
|
|
}
|
|
|
|
static const TypeInfo ipod_touch_aes_info = {
|
|
.name = TYPE_IPOD_TOUCH_AES,
|
|
.parent = TYPE_SYS_BUS_DEVICE,
|
|
.instance_size = sizeof(S5L8900AESState),
|
|
.instance_init = s5l8900_aes_init,
|
|
.class_init = s5l8900_aes_class_init,
|
|
};
|
|
|
|
static void ipod_touch_machine_types(void)
|
|
{
|
|
type_register_static(&ipod_touch_aes_info);
|
|
}
|
|
|
|
type_init(ipod_touch_machine_types) |