158 lines
4.5 KiB
C
158 lines
4.5 KiB
C
#include "hw/arm/ipod_touch_pke.h"
|
|
#include <openssl/bn.h>
|
|
#include <openssl/bio.h>
|
|
|
|
static uint8_t *datahex(char* string) {
|
|
|
|
if(string == NULL)
|
|
return NULL;
|
|
|
|
size_t slength = strlen(string);
|
|
if((slength % 2) != 0) // must be even
|
|
return NULL;
|
|
|
|
size_t dlength = slength / 2;
|
|
|
|
uint8_t* data = malloc(dlength);
|
|
memset(data, 0, dlength);
|
|
|
|
size_t index = 0;
|
|
while (index < slength) {
|
|
char c = string[index];
|
|
int value = 0;
|
|
if(c >= '0' && c <= '9')
|
|
value = (c - '0');
|
|
else if (c >= 'A' && c <= 'F')
|
|
value = (10 + (c - 'A'));
|
|
else if (c >= 'a' && c <= 'f')
|
|
value = (10 + (c - 'a'));
|
|
else {
|
|
free(data);
|
|
return NULL;
|
|
}
|
|
|
|
data[(index/2)] += value << (((index + 1) % 2) * 4);
|
|
|
|
index++;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
static uint64_t ipod_touch_pke_read(void *opaque, hwaddr offset, unsigned size)
|
|
{
|
|
IPodTouchPKEState *s = (IPodTouchPKEState *)opaque;
|
|
|
|
//printf("%s: offset 0x%08x\n", __FUNCTION__, offset);
|
|
|
|
switch(offset) {
|
|
case REG_PKE_SEG_SIZE:
|
|
return s->seg_size_reg;
|
|
case REG_PKE_SEG_START ... (REG_PKE_SEG_START + 1024):
|
|
{
|
|
uint32_t *res = (uint32_t *)s->segments;
|
|
return res[(offset - REG_PKE_SEG_START) / 4];
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ipod_touch_pke_write(void *opaque, hwaddr offset, uint64_t value, unsigned size)
|
|
{
|
|
IPodTouchPKEState *s = (IPodTouchPKEState *)opaque;
|
|
|
|
//printf("%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
|
|
|
|
switch(offset) {
|
|
case 0x0:
|
|
s->num_started = 0;
|
|
break;
|
|
case 0x10:
|
|
break;
|
|
case REG_PKE_SEG_START ... (REG_PKE_SEG_START + 1024):
|
|
{
|
|
uint32_t *segments_cast = (uint32_t *)s->segments;
|
|
segments_cast[(offset - REG_PKE_SEG_START) / 4] = value;
|
|
break;
|
|
}
|
|
case REG_PKE_START:
|
|
{
|
|
s->num_started++;
|
|
|
|
if(s->num_started == 5) { // TODO this is arbitrary!
|
|
|
|
|
|
BIGNUM *mod_bn = BN_lebin2bn(s->segments, s->segment_size, NULL);
|
|
BIGNUM *base_bn = BN_lebin2bn(s->segments + s->segment_size, s->segment_size, NULL);
|
|
BIGNUM *exp_bn = BN_new();
|
|
BN_dec2bn(&exp_bn,"65537");
|
|
// BN_print(BIO_new_fp(stdout, BIO_NOCLOSE), exp_bn);
|
|
// printf("\n\n");
|
|
|
|
BIGNUM *res = BN_new();
|
|
BN_CTX *ctx = BN_CTX_new();
|
|
BN_mod_exp(res, base_bn, exp_bn, mod_bn, ctx);
|
|
// BN_print(BIO_new_fp(stdout, BIO_NOCLOSE), res);
|
|
// printf("\n\n");
|
|
|
|
char *res_hex = datahex(BN_bn2hex(res));
|
|
|
|
// copy this into SEG1 - note that the hex conversion removes the first 0x00 bytes so we add it back and shift everything to the right one place.
|
|
for(int i = 0; i < (s->segment_size - 1); i++) { s->segments[s->segment_size + s->segment_size - 2 - i] = res_hex[i]; }
|
|
s->segments[s->segment_size + s->segment_size - 1] = 0x0;
|
|
}
|
|
break;
|
|
}
|
|
case REG_PKE_SEG_SIZE:
|
|
s->seg_size_reg = value;
|
|
uint32_t size_bit = (s->seg_size_reg >> 6);
|
|
if(size_bit == 0) { s->segment_size = 256; }
|
|
else if(size_bit == 1) { s->segment_size = 128; }
|
|
else { }
|
|
break;
|
|
case REG_PKE_SWRESET:
|
|
s->num_started = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static const MemoryRegionOps pke_ops = {
|
|
.read = ipod_touch_pke_read,
|
|
.write = ipod_touch_pke_write,
|
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
|
};
|
|
|
|
static void ipod_touch_pke_init(Object *obj)
|
|
{
|
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
|
DeviceState *dev = DEVICE(sbd);
|
|
IPodTouchPKEState *s = IPOD_TOUCH_PKE(dev);
|
|
|
|
memory_region_init_io(&s->iomem, obj, &pke_ops, s, "pke", 0x1000);
|
|
sysbus_init_mmio(sbd, &s->iomem);
|
|
}
|
|
|
|
static void ipod_touch_pke_class_init(ObjectClass *klass, void *data)
|
|
{
|
|
|
|
}
|
|
|
|
static const TypeInfo ipod_touch_pke_info = {
|
|
.name = TYPE_IPOD_TOUCH_PKE,
|
|
.parent = TYPE_SYS_BUS_DEVICE,
|
|
.instance_size = sizeof(IPodTouchPKEState),
|
|
.instance_init = ipod_touch_pke_init,
|
|
.class_init = ipod_touch_pke_class_init,
|
|
};
|
|
|
|
static void ipod_touch_machine_types(void)
|
|
{
|
|
type_register_static(&ipod_touch_pke_info);
|
|
}
|
|
|
|
type_init(ipod_touch_machine_types) |