diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3364ec1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "decryptor"] + path = decryptor + url = https://github.com/zoe-vb/8900decryptor diff --git a/README.md b/README.md index 4e1961f..c3ef94d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ -Compile with: - -`gcc generate_nor.c aes.c -o generate_nor -I/usr/local/Cellar/openssl@1.1/1.1.1l/include -L/usr/local/Cellar/openssl@1.1/1.1.1l/lib -lssl -lcrypto` +# Preparing a NOR file for iPod Touch 2G +### This process is different to the iPod Touch 1G because we now have LLB support!
+Copy all the files from Firmware/all_flash/all_flash.n72ap.production into the data folder
+Rename the files to look as below
+`recoverymode.img3, applelogo.img3, batterylow0.img3, batterylow1.img3, dtree.img3 (originally DeviceTree.n72ap), glyphcharging.img3, glyphplugin.img3, needservice.img3, iboot.img3 and llb.img3`
+Delete the other files that aren't mentioned
+Now due to the fact that A: Apple made the NOR contain encrypted img3 files and B: We have LLB now anyway which decrypts the images, we no longer have to worry about decrypting
+Now compile `generate_nor` as described in the `main` branch. And run `./generate_nor`
+This leaves you with a NOR image. diff --git a/data/DeviceTree.n45ap b/data/DeviceTree.n45ap deleted file mode 100755 index 47e8e81..0000000 Binary files a/data/DeviceTree.n45ap and /dev/null differ diff --git a/data/applelogo b/data/applelogo deleted file mode 100755 index 0269957..0000000 Binary files a/data/applelogo and /dev/null differ diff --git a/data/batterycharging b/data/batterycharging deleted file mode 100755 index 1d06560..0000000 Binary files a/data/batterycharging and /dev/null differ diff --git a/data/batterylow0 b/data/batterylow0 deleted file mode 100755 index b2e0385..0000000 Binary files a/data/batterylow0 and /dev/null differ diff --git a/data/batterylow1 b/data/batterylow1 deleted file mode 100755 index e88e63f..0000000 Binary files a/data/batterylow1 and /dev/null differ diff --git a/data/needservice b/data/needservice deleted file mode 100755 index f6087f6..0000000 Binary files a/data/needservice and /dev/null differ diff --git a/data/recoverymode b/data/recoverymode deleted file mode 100755 index ff6b2d9..0000000 Binary files a/data/recoverymode and /dev/null differ diff --git a/generate_nor.c b/generate_nor.c index 7a1b840..c551203 100755 --- a/generate_nor.c +++ b/generate_nor.c @@ -3,14 +3,16 @@ #include #include #include +#include +#include #include #include "aes.h" #define NOR_SIZE 1024 * 1024 -#define NOR_BLOCK_SIZE 0x40 +#define NOR_BLOCK_SIZE 64 // 64 bytes #define NOR_SYSCFG_HEADER_OFFSET 0x4000 -#define NOR_IMG_HEADER_OFFSET 0x8400 -#define NOR_IMG_SECTION_OFFSET 1040 // in blocks +#define NOR_IMG_HEADER_OFFSET 0x200 +#define NOR_IMG_SECTION_OFFSET 0x0 // in blocks #define NUM_SYSCFG_ENTRIES 4 @@ -29,6 +31,8 @@ static const uint8_t Img2HashPadding[] = { 0xAD, 0x2E, 0xE3, 0x8D, 0x2D, 0x9B, static uint32_t crc32_table[256]; static int crc32_table_computed = 0; +#define key_uid ((uint8_t[]){0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}) + typedef struct nor_header { uint32_t fourcc; uint32_t block_size; @@ -60,6 +64,12 @@ typedef struct Img2Header { uint8_t hash[0x20]; } Img2Header; +typedef struct Img3Header { + uint32_t magic; + uint32_t size; + uint32_t dataSize; +} Img3Header; + typedef struct SyscfgHeader { uint32_t shMagic; uint32_t shSize; @@ -74,10 +84,13 @@ typedef struct SyscfgEntry { char seData[16]; } SyscfgEntry; -SyscfgEntry syscfg_entries[NUM_SYSCFG_ENTRIES] = { {'Mod#', "MA623" }, +SyscfgEntry syscfg_entries[NUM_SYSCFG_ENTRIES] = { {'Mod#', "MB528" }, {'Regn', "B/LL" }, - {'SrNm', "ABCDEFG" }, - {'Batt', "690476146348"}}; + {'SrNm', "1A8478BH203" }, + {'Batt', "690476146348"}, + //{'WMac', "00:23:32:6E:AA:10"}, + //{'BMac', "00:23:32:6B:38:E2"} + }; typedef struct chrp_nvram_header { uint8_t sig; @@ -218,8 +231,8 @@ static void calculate_img2_hash(Img2Header *header, uint8_t* hash) { aes_img2verify_encrypt(hash, 32, NULL); } -void add_img2(void *nor, char *filename, int *cur_block_ind) { - printf("Adding IMG2 %s\n", filename); +void add_img3(void *nor, char *filename, int *cur_block_ind) { + printf("Adding IMG3 %s\n", filename); FILE *f = fopen(filename, "rb"); fseek(f, 0, SEEK_END); long fsize = ftell(f); @@ -228,41 +241,58 @@ void add_img2(void *nor, char *filename, int *cur_block_ind) { char *imgdata = malloc(fsize); fread(imgdata, 1, fsize, f); fclose(f); - + // modify header - printf("Raw IMG2 length (in bytes): %ld\n", fsize); - int img_length_in_blocks = (fsize / NOR_BLOCK_SIZE) + 5; - Img2Header *img_header = (Img2Header *)imgdata; - img_header->length_in_blocks = img_length_in_blocks; - img_header->flags2 |= (1 << 24); // this bit needs to be set to indicate a trusted write - img_header->flags2 |= (1 << 1); // this bit needs to be set to indicate that the content is encrypted - printf("--- IMG2 info ---\n"); - printf("Data length: %d (padded: %d)\n", img_header->dataLen, img_header->dataLenPadded); - printf("Flags: 0x%0x8\n", img_header->flags2); + int img_length_in_blocks = ceil((float)fsize / (float)NOR_BLOCK_SIZE); + printf("Raw IMG3 length (in bytes): %ld, in blocks: %ld\n", fsize, img_length_in_blocks); + Img3Header *img_header = (Img3Header *)imgdata; + printf("--- IMG3 info ---\n"); + printf("Data length: %d (padded: %d)\n", img_header->size, img_header->dataSize); printf("\n"); - - uint32_t *databuf = malloc(img_header->dataLenPadded); - memcpy((void *)databuf, imgdata + sizeof(Img2Header), img_header->dataLenPadded); - - // calculate data hash - calculate_img2_data_hash(databuf, img_header->dataLenPadded, img_header->data_hash); - - // calculate CRC32 code of header - img_header->header_checksum = crc32((uint8_t *)img_header, 0x64); - if(img_header->flags2 & (1 << 30)) - { - printf("Extension found with size %d and options 0x%0x8\n", img_header->next_size, img_header->extension_options); - uint8_t *buf = malloc(img_header->next_size); - memcpy(buf, (uint8_t*)img_header + 0x6c, img_header->next_size); - img_header->extension_checksum = crc32(buf, img_header->next_size); + img_header->size = img_length_in_blocks * NOR_BLOCK_SIZE; // the images should be aligned to a block + + // If we're adding the iBoot image, we have to encrypt the signed hash + if(strcmp(filename, "data/iboot.img3") == 0) { + printf("Encrypting hash...\n"); + unsigned char derivedSeed[16] = {0xdb, 0x1f, 0x5b, 0x33, 0x60, 0x6c, 0x5f, 0x1c, 0x19, 0x34, 0xaa, 0x66, 0x58, 0x9c, 0x06, 0x61}; + unsigned char derivedKey[16]; + + /* derive the key */ + AES_KEY encryptKey, decryptKey; + AES_set_decrypt_key(key_uid, sizeof(key_uid) * 8, &encryptKey); + uint8_t ivec[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + AES_cbc_encrypt(derivedSeed, derivedKey, 16, &encryptKey, &ivec, AES_DECRYPT); + + printf("Derived key: 0x"); + for(int i = 0; i < 16; i++) { printf("%02x", derivedKey[i]); } + printf("\n"); + + printf("Plaintext hash: 0x"); + for(int i = 0; i < 128; i++) { printf("%02x", ((uint8_t *)imgdata)[168108 + i]); } + printf("\n"); + + // encrypt the signature using the derived key + AES_set_encrypt_key(derivedKey, sizeof(key_uid) * 8, &encryptKey); + uint8_t ivec2[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + uint8_t res[128]; + AES_cbc_encrypt(&imgdata[168108], &imgdata[168108], 0x80, &encryptKey, &ivec2, AES_ENCRYPT); + + printf("Encrypted hash: 0x"); + for(int i = 0; i < 128; i++) { printf("%02x", ((uint8_t *)imgdata)[168108 + i]); } + printf("\n"); + + // // decrypt again + // AES_set_decrypt_key(derivedKey, sizeof(key_uid) * 8, &decryptKey); + // uint8_t res2[128]; + // uint8_t ivec3[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + // AES_cbc_encrypt(&imgdata[168108], &imgdata[168108], 0x80, &decryptKey, &ivec3, AES_DECRYPT); + + // printf("Decrypted hash: 0x"); + // for(int i = 0; i < 128; i++) { printf("%02x", ((uint8_t *)imgdata)[168108 + i]); } + // printf("\n"); } - // calculate header hash - uint8_t header_hash[0x20]; - calculate_img2_hash(img_header, header_hash); - - memcpy(&img_header->hash, &header_hash, 0x20); - + // copy image uint32_t img_section_offset = NOR_IMG_SECTION_OFFSET * NOR_BLOCK_SIZE; uint32_t addr_offset = img_section_offset + *cur_block_ind * NOR_BLOCK_SIZE; printf("Copying image to address 0x%08x\n", addr_offset); @@ -271,25 +301,33 @@ void add_img2(void *nor, char *filename, int *cur_block_ind) { printf("\n"); } -void setup_img2_partition(void *nor) { +void setup_nor_partition(void *nor) { // prepare the header nor_header *header = malloc(sizeof(nor_header)); header->fourcc = 0x494d4732; // 2GMI header->block_size = NOR_BLOCK_SIZE; header->img_section_offset = NOR_IMG_SECTION_OFFSET; - header->img_section_len = 512 * 1024; // TODO hard-coded - header->checksum = crc32((uint8_t *)header, 0x30); - memcpy(nor + NOR_IMG_HEADER_OFFSET, header, sizeof(nor_header)); + header->img_section_blk_location = NOR_IMG_HEADER_OFFSET; - // add IMG2 images - int cur_block_ind = 0; // the current block index, counted from the img2 partition start - add_img2(nor, "data/DeviceTree.n45ap", &cur_block_ind); - add_img2(nor, "data/batterycharging", &cur_block_ind); - add_img2(nor, "data/applelogo", &cur_block_ind); - add_img2(nor, "data/needservice", &cur_block_ind); - add_img2(nor, "data/batterylow0", &cur_block_ind); - add_img2(nor, "data/batterylow1", &cur_block_ind); - add_img2(nor, "data/recoverymode", &cur_block_ind); + // add IMG3 images + int cur_block_ind = NOR_IMG_HEADER_OFFSET; // the current block index, counted from the img2 partition start + add_img3(nor, "data/llb.img3", &cur_block_ind); + add_img3(nor, "data/iboot.img3", &cur_block_ind); + add_img3(nor, "data/dtree.img3", &cur_block_ind); + add_img3(nor, "data/applelogo.img3", &cur_block_ind); + add_img3(nor, "data/needservice.img3", &cur_block_ind); + add_img3(nor, "data/batterylow0.img3", &cur_block_ind); + add_img3(nor, "data/batterylow1.img3", &cur_block_ind); + //add_img3(nor, 'data/batterycharging0.img3", &cur_block_ind); + //add_img3(nor, 'data/batterycharging1.img3", &cur_block_ind); + //add_img3(nor, 'data/batteryfull.img3", &cur_block_ind); + add_img3(nor, "data/recoverymode.img3", &cur_block_ind); + add_img3(nor, "data/glyphcharging.img3", &cur_block_ind); + add_img3(nor, "data/glyphplugin.img3", &cur_block_ind); + + header->img_section_len = cur_block_ind; // TODO hard-coded + header->checksum = crc32((uint8_t *)header, 0x30); + memcpy(nor, header, sizeof(nor_header)); } int main(int argc, char *argv[]) { @@ -300,21 +338,21 @@ int main(int argc, char *argv[]) { void *nor = malloc(NOR_SIZE); memset(nor, 0x0, NOR_SIZE); - setup_img2_partition(nor); - - // prepare syscfg - SyscfgHeader *syscfg_header = malloc(sizeof(SyscfgHeader)); - syscfg_header->shMagic = 'SCfg'; - syscfg_header->maxSize = 0x2000; - syscfg_header->version = 0x00010001; - syscfg_header->shSize = 200; - syscfg_header->keyCount = NUM_SYSCFG_ENTRIES; - memcpy(nor + NOR_SYSCFG_HEADER_OFFSET, syscfg_header, sizeof(SyscfgHeader)); - - // write syscfg entries - for(int index = 0; index < NUM_SYSCFG_ENTRIES; index++) { - memcpy(nor + NOR_SYSCFG_HEADER_OFFSET + sizeof(SyscfgHeader) + sizeof(SyscfgEntry) * index, &syscfg_entries[index], sizeof(SyscfgEntry)); - } + setup_nor_partition(nor); + + // // prepare syscfg + // SyscfgHeader *syscfg_header = malloc(sizeof(SyscfgHeader)); + // syscfg_header->shMagic = 'SCfg'; + // syscfg_header->maxSize = 0x2000; + // syscfg_header->version = 0x00010001; + // syscfg_header->shSize = 200; + // syscfg_header->keyCount = NUM_SYSCFG_ENTRIES; + // memcpy(nor + NOR_SYSCFG_HEADER_OFFSET, syscfg_header, sizeof(SyscfgHeader)); + + // // write syscfg entries + // for(int index = 0; index < NUM_SYSCFG_ENTRIES; index++) { + // memcpy(nor + NOR_SYSCFG_HEADER_OFFSET + sizeof(SyscfgHeader) + sizeof(SyscfgEntry) * index, &syscfg_entries[index], sizeof(SyscfgEntry)); + // } // prepare NVRAM printf("Preparing NVRAM...\n"); @@ -330,7 +368,7 @@ int main(int argc, char *argv[]) { // create "common" partition with env variables chrp_nvram_header *partition_header = (chrp_nvram_header *)(nvram_data + sizeof(apple_nvram_header)); - char *env = "boot-args=debug=0x8 kextlog=0xfff cpus=1 rd=disk0s1 serial=1 io=0xffff8fff"; + char *env = "debug-uarts=3"; memcpy(partition_header->data, env, strlen(env) + 1); partition_header->sig = 0x70; partition_header->len = 0x80;