160 lines
4.5 KiB
C
160 lines
4.5 KiB
C
/**
|
|
https://github.com/planetbeing/xpwn/blob/master/crypto/aes.c
|
|
**/
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <IOKit/IOKitLib.h>
|
|
#include <pthread.h>
|
|
#include "IOAESAccelerator.h"
|
|
#include "IOKit.h"
|
|
|
|
io_connect_t conn = 0;
|
|
IOByteCount IOAESStructSize = sizeof(IOAESStruct);
|
|
pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
|
|
|
//see com.apple.driver.AppleCDMA
|
|
typedef struct
|
|
{
|
|
uint32_t key_id;
|
|
uint32_t hw_key_id;
|
|
uint8_t nonce_to_encrypt_with_hw_key[16];
|
|
uint8_t* value;
|
|
} device_key_descriptor;
|
|
|
|
#define NUM_DEVICE_KEYS 4
|
|
device_key_descriptor ios_device_keys[NUM_DEVICE_KEYS]= {
|
|
{0x835, kIOAESAcceleratorUIDMask, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, NULL},
|
|
{0x899, kIOAESAcceleratorUIDMask, {0xD1, 0xE8, 0xFC, 0xB5, 0x39, 0x37, 0xBF, 0x8D, 0xEF, 0xC7, 0x4C, 0xD1, 0xD0, 0xF1, 0xD4, 0xB0}, NULL},
|
|
{0x89B, kIOAESAcceleratorUIDMask, {0x18, 0x3E, 0x99, 0x67, 0x6B, 0xB0, 0x3C, 0x54, 0x6F, 0xA4, 0x68, 0xF5, 0x1C, 0x0C, 0xBD, 0x49}, NULL},
|
|
{0x89A, kIOAESAcceleratorUIDMask, {0xDB, 0x1F, 0x5B, 0x33, 0x60, 0x6C, 0x5F, 0x1C, 0x19, 0x34, 0xAA, 0x66, 0x58, 0x9C, 0x06, 0x61}, NULL},
|
|
};
|
|
|
|
void aes_init()
|
|
{
|
|
conn = IOKit_getConnect("IOAESAccelerator");
|
|
}
|
|
|
|
io_connect_t IOAESAccelerator_getIOconnect()
|
|
{
|
|
pthread_once(&once_control, aes_init);
|
|
return conn;
|
|
}
|
|
|
|
|
|
int doAES(void* inbuf, void *outbuf, uint32_t size, uint32_t keyMask, void* key, void* iv, int mode, int bits) {
|
|
IOReturn ret;
|
|
IOAESStruct in;
|
|
|
|
pthread_once(&once_control, aes_init);
|
|
|
|
in.mode = mode;
|
|
in.bits = bits;
|
|
in.inbuf = inbuf;
|
|
in.outbuf = outbuf;
|
|
in.size = size;
|
|
in.mask = keyMask;
|
|
|
|
memset(in.keybuf, 0, sizeof(in.keybuf));
|
|
|
|
if(key)
|
|
memcpy(in.keybuf, key, in.bits / 8);
|
|
|
|
if(iv)
|
|
memcpy(in.iv, iv, 16);
|
|
else
|
|
memset(in.iv, 0, 16);
|
|
|
|
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
|
|
if(ret == kIOReturnBadArgument) {
|
|
IOAESStructSize = IOAESStruct_sizeold;
|
|
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
|
|
}
|
|
|
|
if(iv)
|
|
memcpy(iv, in.iv, 16);
|
|
|
|
return ret;
|
|
}
|
|
|
|
IOReturn doAES_wrapper(void* thisxxx, int mode, void* iv, void* outbuf, void *inbuf, uint32_t size, uint32_t keyMask)
|
|
{
|
|
int x = doAES(inbuf, outbuf, size, keyMask, NULL, iv, mode, 128);
|
|
return !x;
|
|
}
|
|
|
|
int patch_IOAESAccelerator();
|
|
|
|
int AES_UID_Encrypt(void* input2, void* output, size_t len)
|
|
{
|
|
IOAESStruct in;
|
|
IOReturn ret;
|
|
static int triedToPatchKernelAlready = 0;
|
|
unsigned char* input = valloc(16);
|
|
|
|
memcpy(input, input2, 16);
|
|
|
|
pthread_once(&once_control, aes_init);
|
|
|
|
in.mode = kIOAESAcceleratorEncrypt;
|
|
in.mask = kIOAESAcceleratorUIDMask;
|
|
in.bits = 128;
|
|
in.inbuf = input;
|
|
in.outbuf = output;
|
|
in.size = len;
|
|
|
|
memset(in.keybuf, 0, sizeof(in.keybuf));
|
|
memset(in.iv, 0, 16);
|
|
|
|
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
|
|
if(ret == kIOReturnBadArgument) {
|
|
IOAESStructSize = IOAESStruct_sizeold;
|
|
ret = IOConnectCallStructMethod(conn, kIOAESAcceleratorTask, &in, IOAESStructSize, &in, &IOAESStructSize);
|
|
}
|
|
|
|
if(ret == kIOReturnNotPrivileged && !triedToPatchKernelAlready) {
|
|
triedToPatchKernelAlready = 1;
|
|
fprintf(stderr, "Trying to patch IOAESAccelerator kernel extension to allow UID key usage\n");
|
|
patch_IOAESAccelerator();
|
|
ret = AES_UID_Encrypt(input2, output, len);
|
|
}
|
|
if(ret != kIOReturnSuccess) {
|
|
fprintf(stderr, "IOAESAccelerator returned: %x\n", ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
uint8_t* IOAES_get_device_key(uint32_t id)
|
|
{
|
|
static uint8_t nullkey[16] = {0};
|
|
int i;
|
|
for(i=0; i < NUM_DEVICE_KEYS; i++)
|
|
{
|
|
if (ios_device_keys[i].key_id != id)
|
|
continue;
|
|
if (ios_device_keys[i].value != NULL)
|
|
return ios_device_keys[i].value;
|
|
|
|
ios_device_keys[i].value = (uint8_t*) valloc(16); //on ARMv6 devices stuff needs to be aligned
|
|
memcpy(ios_device_keys[i].value, ios_device_keys[i].nonce_to_encrypt_with_hw_key, 16);
|
|
AES_UID_Encrypt(ios_device_keys[i].value, ios_device_keys[i].value, 16);
|
|
return ios_device_keys[i].value;
|
|
}
|
|
return nullkey;
|
|
|
|
}
|
|
uint8_t* IOAES_key835()
|
|
{
|
|
return IOAES_get_device_key(0x835);
|
|
}
|
|
|
|
uint8_t* IOAES_key89B()
|
|
{
|
|
return IOAES_get_device_key(0x89B);
|
|
}
|
|
|
|
uint8_t* IOAES_key89A()
|
|
{
|
|
return IOAES_get_device_key(0x89A);
|
|
} |