]> Chaos Git - corbenik/corbenik.git/commitdiff
Crypto stuff...partially working, CBC seems busted still
authorchaoskagami <chaos.kagami@gmail.com>
Mon, 25 Jul 2016 19:13:54 +0000 (15:13 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Mon, 25 Jul 2016 19:13:54 +0000 (15:13 -0400)
include/firm/decryptor.h
source/firm/decryptor.c
source/firm/firm.c

index fe7d7034ad520369db5fda9a4b7b8878a103324b..c7f95f67887b592d056036f17cc60822a3e1e708 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef __DECRYPTOR_H
 #define __DECRYPTOR_H
 
-void aes(void *dst, void *src, uint32_t blockCount, void *iv, uint32_t mode);
 void sha256sum(void* sum, void* data, uint32_t size);
 
+void cbc_decrypt(void *inbuf, void *outbuf, size_t size, uint32_t mode, uint8_t *iv);
+
 typedef enum {
     NCCHTYPE_EXHEADER = 1,
     NCCHTYPE_EXEFS = 2,
index 099ecb514553aa30a44565e441a96e5bd468fbe9..b93555d4d3fed7bed8040e2ed690223f0cbfd503 100644 (file)
@@ -36,75 +36,29 @@ ncch_getctr(const ncch_h *ncch, uint8_t *ctr, uint8_t type)
 }
 
 void
-aes_batch(void *dst, const void *src, uint32_t blockCount)
+cbc_decrypt(void *inbuf, void *outbuf, size_t size, uint32_t mode, uint8_t *iv)
 {
-    *REG_AESBLKCNT = blockCount << 16;
-    *REG_AESCNT |= AES_CNT_START;
+    size_t blocks = size;
+    uint8_t *in = inbuf;
+    uint8_t *out = outbuf;
+    while (blocks) {
+               set_ctr(iv);
 
-    const uint32_t *src32 = (const uint32_t *)src;
-    uint32_t *dst32 = (uint32_t *)dst;
+        size_t current_blocks = blocks > 0xFFFF ? 0xFFFF : blocks;
 
-    uint32_t wbc = blockCount;
-    uint32_t rbc = blockCount;
+        aes_decrypt(in, out, current_blocks, mode);
 
-    while (rbc) {
-        if (wbc && ((*REG_AESCNT & 0x1F) <= 0xC)) // There's space for at least 4 ints
-        {
-                       for(int i=0; i < 4; i++)
-                   *REG_AESWRFIFO = *src32++;
-            wbc--;
-        }
+        memcpy(iv, out + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
 
-        if (rbc && ((*REG_AESCNT & (0x1F << 0x5)) >= (0x4 << 0x5))) // At least 4 ints available for read
-        {
-                       for(int i=0; i < 4; i++)
-                   *dst32++ = *REG_AESRDFIFO;
-            rbc--;
-        }
+        blocks -= current_blocks;
+        in  += AES_BLOCK_SIZE * current_blocks;
+        out += AES_BLOCK_SIZE * current_blocks;
     }
 }
 
-inline void
-aes_setmode(uint32_t mode)
-{
-    *REG_AESCNT = mode | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN | AES_CNT_FLUSH_READ | AES_CNT_FLUSH_WRITE;
-}
-
 void
-aes(void *dst, void *src, uint32_t blockCount, void *iv, uint32_t mode)
+sha256sum(void* sum, void* data, uint32_t size)
 {
-    aes_setmode(mode);
-
-    uint32_t blocks;
-    while (blockCount != 0) {
-        if ((mode & (7u << 27)) != AES_ECB_ENCRYPT_MODE && (mode & (7u << 27)) != AES_ECB_DECRYPT_MODE)
-            set_ctr(iv);
-
-        blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount;
-
-        // Save the last block for the next decryption CBC batch's iv
-        if ((mode & (7u << 27)) == AES_CBC_DECRYPT_MODE)
-            memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-        // Process the current batch
-        aes_batch(dst, src, blocks);
-
-        // Save the last block for the next encryption CBC batch's iv
-        if ((mode & (7u << 27)) == AES_CBC_ENCRYPT_MODE)
-            memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-
-        // Advance counter for CTR mode
-        else if ((mode & (7u << 27)) == AES_CTR_MODE)
-            add_ctr(iv, blocks);
-
-        src += blocks * AES_BLOCK_SIZE;
-        dst += blocks * AES_BLOCK_SIZE;
-        blockCount -= blocks;
-    }
-}
-
-void
-sha256sum(void* sum, void* data, uint32_t size) {
        sha_init(SHA256_MODE);
     sha_update(data, size);
     sha_get(sum);
index 0a54d640113b1141af8797f747c8b162fbe9ff04..a534738fa3026f7b6f366625cbb6d2d35ec7dd3e 100644 (file)
@@ -60,13 +60,13 @@ void dump_firm(firm_h** buffer, uint8_t index) {
 
     use_aeskey(0x06);
     set_ctr(ctr);
-    aes(firm, firm, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE);
-
-    fprintf(stderr, "  AES decrypted FIRM%u.\n", index);
+       ctr_decrypt(firm, firm, firm_size / AES_BLOCK_SIZE, AES_CTR_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER, ctr);
 
     if (memcmp((char*) & firm->magic, "FIRM", 4))
         abort("  Decryption failed on FIRM.\n");
 
+    fprintf(stderr, "  AES decrypted FIRM%u.\n", index);
+
     fprintf(stderr, "  Magic is intact on FIRM%u.\n", index);
 
     uint8_t detver = 0;
@@ -197,18 +197,20 @@ decrypt_cetk_key(void *key, const void *cetk)
                return 1;
 
        if (got_cetk == 0) {
+               fprintf(stderr, "  Retrieving 0x3D KeyY...\n");
                extract_slot0x3DkeyY();
                got_cetk = 1;
        }
 
        use_aeskey(0x3D);
 
-       memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
+       memcpy(iv,  ticket->titleID,  sizeof(ticket->titleID));
        memcpy(key, ticket->titleKey, sizeof(ticket->titleKey));
 
-       aes(key, key, 1, iv, AES_CBC_DECRYPT_MODE);
+       set_ctr(iv);
+       cbc_decrypt(key, key, 1, AES_CBC_DECRYPT_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER, iv);
 
-       fprintf(stderr, " Extracted titlekey from cetk.\n");
+       fprintf(stderr, "  Extracted titlekey from cetk.\n");
 
        return 0;
 }
@@ -221,9 +223,11 @@ decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
     uint8_t exefs_iv[16] = { 0 };
 
     fprintf(stderr, "  Decrypting FIRM container\n");
+
     setup_aeskey(0x16, key);
     use_aeskey(0x16);
-    aes(ncch, ncch, *size / AES_BLOCK_SIZE, firm_iv, AES_CBC_DECRYPT_MODE);
+       set_ctr(firm_iv);
+    cbc_decrypt(ncch, ncch, *size / AES_BLOCK_SIZE, AES_CBC_DECRYPT_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER, firm_iv);
 
     if (ncch->magic != NCCH_MAGIC)
         return 1;
@@ -238,7 +242,7 @@ decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
     fprintf(stderr, "  Decrypting ExeFs for FIRM\n");
     setup_aeskeyY(0x2C, exefs_key);
     use_aeskey(0x2C);
-    aes(exefs, exefs, exefs_size / AES_BLOCK_SIZE, exefs_iv, AES_CTR_MODE);
+    ctr_decrypt(exefs, exefs, exefs_size / AES_BLOCK_SIZE, AES_CTR_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER, exefs_iv);
 
     // Get the decrypted FIRM
     // We assume the firm.bin is always the first file
@@ -266,7 +270,7 @@ decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version)
         slot = 0x16;
 
         use_aeskey(0x11);
-        aes(decrypted_keyx, header->slot0x16keyX, 1, NULL, AES_ECB_DECRYPT_MODE);
+        aes_decrypt(decrypted_keyx, header->slot0x16keyX, 1, AES_ECB_DECRYPT_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER);
         setup_aeskeyX(slot, decrypted_keyx);
     }
 
@@ -277,7 +281,7 @@ decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version)
     int size = atoi(header->size);
 
     use_aeskey(slot);
-    aes(arm9bin, arm9bin, size / AES_BLOCK_SIZE, header->ctr, AES_CTR_MODE);
+    ctr_decrypt(arm9bin, arm9bin, size / AES_BLOCK_SIZE, AES_CTR_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER, header->ctr);
 
     if (firm_title == NATIVE_FIRM_TITLEID)
         return *(uint32_t *)arm9bin != ARM9BIN_MAGIC;
@@ -439,7 +443,7 @@ boot_firm()
         use_aeskey(0x11);
         uint8_t keyx[AES_BLOCK_SIZE];
         for (int slot = 0x19; slot < 0x20; slot++) {
-            aes(keyx, keydata, 1, NULL, AES_ECB_DECRYPT_MODE);
+            aes_decrypt(keyx, keydata, 1, AES_ECB_DECRYPT_MODE|AES_CNT_INPUT_ENDIAN|AES_CNT_OUTPUT_ENDIAN|AES_CNT_INPUT_ORDER|AES_CNT_OUTPUT_ORDER);
             setup_aeskeyX(slot, keyx);
             *(uint8_t *)(keydata + 0xF) += 1;
         }