diff --git a/Makefile.main b/Makefile.main
index a3a5b0b2..54e816a0 100644
--- a/Makefile.main
+++ b/Makefile.main
@@ -28,6 +28,7 @@ SOURCES := source \
source/gc \
source/gecko \
source/gui \
+ source/hw \
source/homebrew \
source/libwbfs \
source/list \
diff --git a/source/hw/aes.c b/source/hw/aes.c
new file mode 100644
index 00000000..3850241f
--- /dev/null
+++ b/source/hw/aes.c
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * Copyright (C) 2013 FIX94
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ ****************************************************************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include "loader/utils.h"
+#include "memory/memory.h"
+#include "aes.h"
+
+#define AES_CMD_FLAG_EXEC (1<<31)
+#define AES_CMD_FLAG_ENA (1<<28)
+#define AES_CMD_FLAG_DEC (1<<27)
+#define AES_CMD_FLAG_IV (1<<12)
+
+u8 aes_mode = 0;
+
+void AES_EnableDecrypt(const u8 *key, const u8 *iv)
+{
+ const u32 *aes_iv = (const u32*)iv;
+ const u32 *aes_key = (const u32*)key;
+ /* Reset Engine */
+ write32(HW_AES_CMD, 0x00000000);
+ while ((read32(HW_AES_CMD) & AES_CMD_FLAG_EXEC) != 0);
+ /* write in IV and Key */
+ u8 i;
+ for(i = 0; i < 4; ++i)
+ {
+ write32(HW_AES_IV, *(aes_iv+i));
+ write32(HW_AES_KEY, *(aes_key+i));
+ }
+ /* set mode back to 0 */
+ aes_mode = 0;
+}
+
+#define AES_LIMIT 0x1000
+static u8 AES_BUF[AES_LIMIT*16] ATTRIBUTE_ALIGN(16); /* 64KB */
+void AES_Decrypt(u8 *inbuf, u8 *outbuf, u16 num_blocks)
+{
+ /* split cause of limit */
+ u32 buf_pos = 0;
+ u16 blocks_done = 0;
+ u32 buf_done = 0;
+ u16 blocks_full = num_blocks;
+ while(blocks_done < blocks_full)
+ {
+ /* Calculate Position */
+ blocks_done = blocks_full;
+ if(blocks_done > AES_LIMIT)
+ blocks_done = AES_LIMIT;
+ buf_done = blocks_done * 16;
+ /* Copy into our aligned buffer */
+ memcpy(AES_BUF, (inbuf + buf_pos), buf_done);
+ /* Flush and Invalidate */
+ DCFlushRange(AES_BUF, buf_done);
+ ICInvalidateRange(AES_BUF, buf_done);
+ /* set location */
+ write32(HW_AES_SRC, (u32)MEM_VIRTUAL_TO_PHYSICAL(AES_BUF));
+ write32(HW_AES_DEST, (u32)MEM_VIRTUAL_TO_PHYSICAL(AES_BUF));
+ /* enable engine, set size, set iv flag and enable decryption */
+ write32(HW_AES_CMD, AES_CMD_FLAG_ENA | AES_CMD_FLAG_DEC | AES_CMD_FLAG_EXEC |
+ ((aes_mode == 0) ? 0 : AES_CMD_FLAG_IV) | (blocks_done - 1));
+ while (read32(HW_AES_CMD) & AES_CMD_FLAG_EXEC);
+ /* set down num blocks */
+ blocks_full -= blocks_done;
+ /* increase aes mode to keep iv */
+ if(aes_mode == 0) aes_mode++;
+ /* flush and write outbuf */
+ DCFlushRange(AES_BUF, buf_done);
+ memcpy((outbuf + buf_pos), AES_BUF, buf_done);
+ /* increase block pos */
+ buf_pos += buf_done;
+ }
+}
diff --git a/source/hw/aes.h b/source/hw/aes.h
new file mode 100644
index 00000000..3ddbe878
--- /dev/null
+++ b/source/hw/aes.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ * Copyright (C) 2013 FIX94
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ ****************************************************************************/
+#ifndef __AES_H__
+#define __AES_H__
+
+void AES_EnableDecrypt(const u8 *key, const u8 *iv);
+void AES_Decrypt(u8 *inbuf, u8 *outbuf, u16 num_blocks);
+
+#endif
diff --git a/source/hw/sha1.c b/source/hw/sha1.c
new file mode 100644
index 00000000..b7df9e25
--- /dev/null
+++ b/source/hw/sha1.c
@@ -0,0 +1,174 @@
+/*
+SHA-1 in C
+By Steve Reid
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#define SHA1HANDSOFF
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "loader/utils.h"
+#include "memory/memory.h"
+#include "sha1.h"
+
+//should be divisibly by four
+#define BLOCKSIZE 32
+
+#define SHA_CMD_FLAG_EXEC (1<<31)
+#define SHA_CMD_FLAG_IRQ (1<<30)
+#define SHA_CMD_FLAG_ERR (1<<29)
+#define SHA_CMD_AREA_BLOCK ((1<<10) - 1)
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+static void SHA1Transforml(unsigned long state[5], unsigned char buffer[64], u32 len)
+{
+ /* Copy context->state[] to working vars */
+ write32(HW_SHA1_H0, state[0]);
+ write32(HW_SHA1_H1, state[1]);
+ write32(HW_SHA1_H2, state[2]);
+ write32(HW_SHA1_H3, state[3]);
+ write32(HW_SHA1_H4, state[4]);
+
+ static u32 num_blocks;
+ num_blocks = len;
+
+ // assign block to local copy which is 64-byte aligned
+ static u8 block[64*BLOCKSIZE] ATTRIBUTE_ALIGN(64);
+ // for further improvments!
+ // u8 *block = memalign(64, 64*num_blocks);
+ memcpy(block, buffer, 64*num_blocks);
+
+ // royal flush :)
+ DCFlushRange(block, 64*num_blocks);
+
+ // tell sha1 controller the block source address
+ write32(HW_SHA1_SRC, MEM_VIRTUAL_TO_PHYSICAL(block));
+
+ // tell sha1 controller number of blocks
+ if (num_blocks != 0)
+ num_blocks--;
+ write32(HW_SHA1_CMD, (read32(HW_SHA1_CMD) & ~(SHA_CMD_AREA_BLOCK)) | num_blocks);
+
+ // fire up hashing and wait till its finished
+ write32(HW_SHA1_CMD, read32(HW_SHA1_CMD) | SHA_CMD_FLAG_EXEC);
+ while (read32(HW_SHA1_CMD) & SHA_CMD_FLAG_EXEC);
+
+ // free the aligned data
+ // free(block);
+
+ /* Add the working vars back into context.state[] */
+ state[0] = read32(HW_SHA1_H0);
+ state[1] = read32(HW_SHA1_H1);
+ state[2] = read32(HW_SHA1_H2);
+ state[3] = read32(HW_SHA1_H3);
+ state[4] = read32(HW_SHA1_H4);
+}
+
+static void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
+{
+ SHA1Transforml(state, buffer, 1);
+}
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* reset sha-1 engine */
+ write32(HW_SHA1_CMD, read32(HW_SHA1_CMD) & ~(SHA_CMD_FLAG_EXEC));
+ while ((read32(HW_SHA1_CMD) & SHA_CMD_FLAG_EXEC) != 0);
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
+{
+ unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3))
+ context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ // try bigger blocks at once
+ for ( ; i + 63 + ((BLOCKSIZE-1)*64) < len; i += (64 + (BLOCKSIZE-1)*64)) {
+ SHA1Transforml(context->state, &data[i], BLOCKSIZE);
+ }
+ for ( ; i + 63 + (((BLOCKSIZE/2)-1)*64) < len; i += (64 + ((BLOCKSIZE/2)-1)*64)) {
+ SHA1Transforml(context->state, &data[i], BLOCKSIZE/2);
+ }
+ for ( ; i + 63 + (((BLOCKSIZE/4)-1)*64) < len; i += (64 + ((BLOCKSIZE/4)-1)*64)) {
+ SHA1Transforml(context->state, &data[i], BLOCKSIZE/4);
+ }
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+ unsigned long i, j;
+ unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf)
+{
+ SHA1_CTX ctx;
+
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, ptr, size);
+ SHA1Final(outbuf, &ctx);
+}
diff --git a/source/loader/sha1.h b/source/hw/sha1.h
similarity index 64%
rename from source/loader/sha1.h
rename to source/hw/sha1.h
index 253d4695..9b27f178 100644
--- a/source/loader/sha1.h
+++ b/source/hw/sha1.h
@@ -1,12 +1,15 @@
-typedef struct {
- unsigned long state[5];
- unsigned long count[2];
- unsigned char buffer[64];
-} SHA1_CTX;
-
-void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
-void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
-
-void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf);
+
+#ifndef __SHA1_H__
+#define __SHA1_H__
+
+typedef struct {
+ unsigned long state[5];
+ unsigned long count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+
+#endif
diff --git a/source/libwbfs/rijndael.c b/source/libwbfs/rijndael.c
deleted file mode 100644
index 1b1edcc4..00000000
--- a/source/libwbfs/rijndael.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/* Rijndael Block Cipher - rijndael.c
-
- Written by Mike Scott 21st April 1999
- mike@compapp.dcu.ie
-
- Permission for free direct or derivative use is granted subject
- to compliance with any conditions that the originators of the
- algorithm place on its exploitation.
-
- */
-
-#include
-#include
-#include "gecko/gecko.hpp"
-#include "loader/utils.h"
-#define u8 unsigned char /* 8 bits */
-#define u32 unsigned long /* 32 bits */
-#define u64 unsigned long long
-
-/* rotates x one bit to the left */
-
-#define ROTL(x) (((x)>>7)|((x)<<1))
-
-/* Rotates 32-bit word left by 1, 2 or 3 byte */
-
-#define ROTL8(x) (((x)<<8)|((x)>>24))
-#define ROTL16(x) (((x)<<16)|((x)>>16))
-#define ROTL24(x) (((x)<<24)|((x)>>8))
-
-/* Fixed Data */
-
-static u8 InCo[4] = { 0xB, 0xD, 0x9, 0xE }; /* Inverse Coefficients */
-
-static u8 fbsub[256];
-static u8 rbsub[256];
-static u8 ptab[256], ltab[256];
-static u32 ftable[256];
-static u32 rtable[256];
-static u32 rco[30];
-
-/* Parameter-dependent data */
-
-int Nk, Nb, Nr;
-u8 fi[24], ri[24];
-u32 fkey[120];
-u32 rkey[120];
-
-static u32 pack(u8 *b)
-{ /* pack bytes into a 32-bit Word */
- return ((u32 ) b[3] << 24) | ((u32 ) b[2] << 16) | ((u32 ) b[1] << 8) | (u32 ) b[0];
-}
-
-static void unpack(u32 a, u8 *b)
-{ /* unpack bytes from a word */
- b[0] = (u8 ) a;
- b[1] = (u8 ) (a >> 8);
- b[2] = (u8 ) (a >> 16);
- b[3] = (u8 ) (a >> 24);
-}
-
-static u8 xtime(u8 a)
-{
- u8 b;
- if (a & 0x80)
- b = 0x1B;
- else b = 0;
- a <<= 1;
- a ^= b;
- return a;
-}
-
-static u8 bmul(u8 x, u8 y)
-{ /* x.y= AntiLog(Log(x) + Log(y)) */
- if (x && y)
- return ptab[(ltab[x] + ltab[y]) % 255];
- else return 0;
-}
-
-static u32 SubByte(u32 a)
-{
- u8 b[4];
- unpack(a, b);
- b[0] = fbsub[b[0]];
- b[1] = fbsub[b[1]];
- b[2] = fbsub[b[2]];
- b[3] = fbsub[b[3]];
- return pack(b);
-}
-
-static u8 product(u32 x, u32 y)
-{ /* dot product of two 4-byte arrays */
- u8 xb[4], yb[4];
- unpack(x, xb);
- unpack(y, yb);
- return bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2], yb[2]) ^ bmul(xb[3], yb[3]);
-}
-
-static u32 InvMixCol(u32 x)
-{ /* matrix Multiplication */
- u32 y, m;
- u8 b[4];
-
- m = pack(InCo);
- b[3] = product(m, x);
- m = ROTL24( m );
- b[2] = product(m, x);
- m = ROTL24( m );
- b[1] = product(m, x);
- m = ROTL24( m );
- b[0] = product(m, x);
- y = pack(b);
- return y;
-}
-
-u8 ByteSub(u8 x)
-{
- u8 y = ptab[255 - ltab[x]]; /* multiplicative inverse */
- x = y;
- x = ROTL( x );
- y ^= x;
- x = ROTL( x );
- y ^= x;
- x = ROTL( x );
- y ^= x;
- x = ROTL( x );
- y ^= x;
- y ^= 0x63;
- return y;
-}
-
-void gentables(void)
-{ /* generate tables */
- int i;
- u8 y, b[4];
-
- /* use 3 as primitive root to generate power and log tables */
-
- ltab[0] = 0;
- ptab[0] = 1;
- ltab[1] = 0;
- ptab[1] = 3;
- ltab[3] = 1;
- for (i = 2; i < 256; i++)
- {
- ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]);
- ltab[ptab[i]] = i;
- }
-
- /* affine transformation:- each bit is xored with itself shifted one bit */
-
- fbsub[0] = 0x63;
- rbsub[0x63] = 0;
- for (i = 1; i < 256; i++)
- {
- y = ByteSub((u8 ) i);
- fbsub[i] = y;
- rbsub[y] = i;
- }
-
- for (i = 0, y = 1; i < 30; i++)
- {
- rco[i] = y;
- y = xtime(y);
- }
-
- /* calculate forward and reverse tables */
- for (i = 0; i < 256; i++)
- {
- y = fbsub[i];
- b[3] = y ^ xtime(y);
- b[2] = y;
- b[1] = y;
- b[0] = xtime(y);
- ftable[i] = pack(b);
-
- y = rbsub[i];
- b[3] = bmul(InCo[0], y);
- b[2] = bmul(InCo[1], y);
- b[1] = bmul(InCo[2], y);
- b[0] = bmul(InCo[3], y);
- rtable[i] = pack(b);
- }
-}
-
-void gkey(int nb, int nk, char *key)
-{ /* blocksize=32*nb bits. Key=32*nk bits */
- /* currently nb,bk = 4, 6 or 8 */
- /* key comes as 4*Nk bytes */
- /* Key Scheduler. Create expanded encryption key */
- int i, j, k, m, N;
- int C1, C2, C3;
- u32 CipherKey[8];
-
- Nb = nb;
- Nk = nk;
-
- /* Nr is number of rounds */
- if (Nb >= Nk)
- Nr = 6 + Nb;
- else Nr = 6 + Nk;
-
- C1 = 1;
- if (Nb < 8)
- {
- C2 = 2;
- C3 = 3;
- }
- else
- {
- C2 = 3;
- C3 = 4;
- }
-
- /* pre-calculate forward and reverse increments */
- for (m = j = 0; j < nb; j++, m += 3)
- {
- fi[m] = (j + C1) % nb;
- fi[m + 1] = (j + C2) % nb;
- fi[m + 2] = (j + C3) % nb;
- ri[m] = (nb + j - C1) % nb;
- ri[m + 1] = (nb + j - C2) % nb;
- ri[m + 2] = (nb + j - C3) % nb;
- }
-
- N = Nb * (Nr + 1);
-
- for (i = j = 0; i < Nk; i++, j += 4)
- {
- CipherKey[i] = pack((u8 *) &key[j]);
- }
- for (i = 0; i < Nk; i++)
- fkey[i] = CipherKey[i];
- for (j = Nk, k = 0; j < N; j += Nk, k++)
- {
- fkey[j] = fkey[j - Nk] ^ SubByte(ROTL24( fkey[j-1] )) ^ rco[k];
- if (Nk <= 6)
- {
- for (i = 1; i < Nk && (i + j) < N; i++)
- fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
- }
- else
- {
- for (i = 1; i < 4 && (i + j) < N; i++)
- fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
- if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ SubByte(fkey[j + 3]);
- for (i = 5; i < Nk && (i + j) < N; i++)
- fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1];
- }
-
- }
-
- /* now for the expanded decrypt key in reverse order */
-
- for (j = 0; j < Nb; j++)
- rkey[j + N - Nb] = fkey[j];
- for (i = Nb; i < N - Nb; i += Nb)
- {
- k = N - Nb - i;
- for (j = 0; j < Nb; j++)
- rkey[k + j] = InvMixCol(fkey[i + j]);
- }
- for (j = N - Nb; j < N; j++)
- rkey[j - N + Nb] = fkey[j];
-}
-
-/* There is an obvious time/space trade-off possible here. *
- * Instead of just one ftable[], I could have 4, the other *
- * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
-
-void encrypt(char *buff)
-{
- int i, j, k, m;
- u32 a[8], b[8], *x, *y, *t;
-
- for (i = j = 0; i < Nb; i++, j += 4)
- {
- a[i] = pack((u8 *) &buff[j]);
- a[i] ^= fkey[i];
- }
- k = Nb;
- x = a;
- y = b;
-
- /* State alternates between a and b */
- for (i = 1; i < Nr; i++)
- { /* Nr is number of rounds. May be odd. */
-
- /* if Nb is fixed - unroll this next
- loop and hard-code in the values of fi[] */
-
- for (m = j = 0; j < Nb; j++, m += 3)
- { /* deal with each 32-bit element of the State */
- /* This is the time-critical bit */
- y[j] = fkey[k++] ^ ftable[(u8 ) x[j]] ^ ROTL8( ftable[( u8 )( x[fi[m]] >> 8 )] )
- ^ ROTL16( ftable[( u8 )( x[fi[m+1]] >> 16 )] ) ^ ROTL24( ftable[x[fi[m+2]] >> 24] );
- }
- t = x;
- x = y;
- y = t; /* swap pointers */
- }
-
- /* Last Round - unroll if possible */
- for (m = j = 0; j < Nb; j++, m += 3)
- {
- y[j] = fkey[k++] ^ (u32 ) fbsub[(u8 ) x[j]] ^ ROTL8( ( u32 )fbsub[( u8 )( x[fi[m]] >> 8 )] )
- ^ ROTL16( ( u32 )fbsub[( u8 )( x[fi[m+1]] >> 16 )] ) ^ ROTL24( ( u32 )fbsub[x[fi[m+2]] >> 24] );
- }
- for (i = j = 0; i < Nb; i++, j += 4)
- {
- unpack(y[i], (u8 *) &buff[j]);
- x[i] = y[i] = 0; /* clean up stack */
- }
- return;
-}
-
-void decrypt(char *buff)
-{
- int i, j, k, m;
- u32 a[8], b[8], *x, *y, *t;
-
- for (i = j = 0; i < Nb; i++, j += 4)
- {
- a[i] = pack((u8 *) &buff[j]);
- a[i] ^= rkey[i];
- }
- k = Nb;
- x = a;
- y = b;
-
- /* State alternates between a and b */
- for (i = 1; i < Nr; i++)
- { /* Nr is number of rounds. May be odd. */
-
- /* if Nb is fixed - unroll this next
- loop and hard-code in the values of ri[] */
-
- for (m = j = 0; j < Nb; j++, m += 3)
- { /* This is the time-critical bit */
- y[j] = rkey[k++] ^ rtable[(u8 ) x[j]] ^ ROTL8( rtable[( u8 )( x[ri[m]] >> 8 )] )
- ^ ROTL16( rtable[( u8 )( x[ri[m+1]] >> 16 )] ) ^ ROTL24( rtable[x[ri[m+2]] >> 24] );
- }
- t = x;
- x = y;
- y = t; /* swap pointers */
- }
-
- /* Last Round - unroll if possible */
- for (m = j = 0; j < Nb; j++, m += 3)
- {
- y[j] = rkey[k++] ^ (u32 ) rbsub[(u8 ) x[j]] ^ ROTL8( ( u32 )rbsub[( u8 )( x[ri[m]] >> 8 )] )
- ^ ROTL16( ( u32 )rbsub[( u8 )( x[ri[m+1]] >> 16 )] ) ^ ROTL24( ( u32 )rbsub[x[ri[m+2]] >> 24] );
- }
- for (i = j = 0; i < Nb; i++, j += 4)
- {
- unpack(y[i], (u8 *) &buff[j]);
- x[i] = y[i] = 0; /* clean up stack */
- }
- return;
-}
-
-void aes_set_key(u8 *key)
-{
- gentables();
- gkey(4, 4, (char*) key);
-}
-
-// CBC mode decryption
-void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len)
-{
- u8 block[16];
- u32 blockno = 0, i;
-
- //printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
-
- for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
- {
- u32 fraction;
- if (blockno == (len / sizeof(block))) // last block
- {
- fraction = len % sizeof(block);
- if (fraction == 0) break;
- memset(block, 0, sizeof(block));
- }
- else fraction = 16;
-
- // debug_printf("block %d: fraction = %d\n", blockno, fraction);
- memcpy(block, inbuf + blockno * sizeof(block), fraction);
- decrypt((char*) block);
- u8 *ctext_ptr;
- if (blockno == 0)
- ctext_ptr = iv;
- else ctext_ptr = inbuf + (blockno - 1) * sizeof(block);
-
- for (i = 0; i < fraction; i++)
- outbuf[blockno * sizeof(block) + i] = ctext_ptr[i] ^ block[i];
- // debug_printf("Block %d output: ", blockno);
- // hexdump(outbuf + blockno*sizeof(block), 16);
- }
-}
-
-// CBC mode encryption
-void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len)
-{
- u8 block[16];
- u32 blockno = 0, i;
-
- // debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len);
-
- for (blockno = 0; blockno <= (len / sizeof(block)); blockno++)
- {
- u32 fraction;
- if (blockno == (len / sizeof(block))) // last block
- {
- fraction = len % sizeof(block);
- if (fraction == 0) break;
- memset(block, 0, sizeof(block));
- }
- else fraction = 16;
-
- // debug_printf("block %d: fraction = %d\n", blockno, fraction);
- memcpy(block, inbuf + blockno * sizeof(block), fraction);
-
- for (i = 0; i < fraction; i++)
- block[i] = inbuf[blockno * sizeof(block) + i] ^ iv[i];
-
- encrypt((char*) block);
- memcpy(iv, block, sizeof(block));
- memcpy(outbuf + blockno * sizeof(block), block, sizeof(block));
- // debug_printf("Block %d output: ", blockno);
- // hexdump(outbuf + blockno*sizeof(block), 16);
- }
-}
-
-
-// CBC mode decryption
-#define WAD_BUF 0x10000
-
-void aes_decrypt_partial(u8 *inbuf, u8 *outbuf, u8 block[16], u8 *ctext_ptr, u32 tmp_blockno)
-{
- memcpy(block, inbuf + tmp_blockno * 16, 16);
- decrypt((char*)block);
- u32 i;
- for(i = 0; i < 16; i++)
- outbuf[tmp_blockno * 16 + i] = ctext_ptr[i] ^ block[i];
-}
diff --git a/source/libwbfs/wiidisc.c b/source/libwbfs/wiidisc.c
index 74d577ed..7626d00d 100644
--- a/source/libwbfs/wiidisc.c
+++ b/source/libwbfs/wiidisc.c
@@ -4,9 +4,7 @@
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include "wiidisc.h"
-
-void aes_set_key(u8 *key);
-void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len);
+#include "hw/aes.h"
int wd_last_error = 0;
@@ -15,19 +13,19 @@ int wd_get_last_error(void)
return wd_last_error;
}
+static const u8 common_key[16] = {
+ 0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4,
+ 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7
+};
+
+//korean common key
+static const u8 korean_key[16] = {
+ 0x63, 0xb8, 0x2b, 0xb4, 0xf4, 0x61, 0x4e, 0x2e,
+ 0x13, 0xf2, 0xfe, 0xfb, 0xba, 0x4c, 0x9b, 0x7e
+};
+
void decrypt_title_key(u8 *tik, u8 *title_key)
{
- u8 common_key[16] = {
- 0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4,
- 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7
- };
-
- //korean common key
- u8 korean_key[16]={
- 0x63, 0xb8, 0x2b, 0xb4, 0xf4, 0x61, 0x4e, 0x2e,
- 0x13, 0xf2, 0xfe, 0xfb, 0xba, 0x4c, 0x9b, 0x7e
- };
-
u8 iv[16];
wbfs_memset(iv, 0, sizeof iv);
@@ -38,13 +36,13 @@ void decrypt_title_key(u8 *tik, u8 *title_key)
u8 korean_flag = tik[0x01f1];
if(korean_flag == 1)
- aes_set_key(korean_key);
+ AES_EnableDecrypt(korean_key, iv);
else
- aes_set_key(common_key);
+ AES_EnableDecrypt(common_key, iv);
- //_aes_cbc_dec(common_key, iv, tik + 0x01bf, 16, title_key);
- aes_decrypt(iv, tik + 0x01bf, title_key, 16);
+ AES_Decrypt(tik + 0x01bf, title_key, 1);
}
+
static u32 _be32(const u8 *p)
{
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
@@ -90,8 +88,8 @@ static void partition_read_block(wiidisc_t *d, u32 blockno, u8 *block)
// decrypt data
memcpy(iv, raw + 0x3d0, 16);
- aes_set_key(d->disc_key);
- aes_decrypt(iv, raw + 0x400, block, 0x7c00);
+ AES_EnableDecrypt(d->disc_key, iv);
+ AES_Decrypt(raw + 0x400, block, 0x7c0);
}
static void partition_read(wiidisc_t *d, u32 offset, u8 *data, u32 len, int fake)
diff --git a/source/loader/sha1.c b/source/loader/sha1.c
deleted file mode 100644
index 410715a1..00000000
--- a/source/loader/sha1.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-SHA-1 in C
-By Steve Reid
-100% Public Domain
-
-Test Vectors (from FIPS PUB 180-1)
-"abc"
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/* #define LITTLE_ENDIAN * This should be #define'd if true. */
-#define SHA1HANDSOFF
-
-#include
-#include
-#include "sha1.h"
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#ifdef LITTLE_ENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
- |(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
- ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
-{
-unsigned long a, b, c, d, e;
-typedef union {
- unsigned char c[64];
- unsigned long l[16];
-} CHAR64LONG16;
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static unsigned char workspace[64];
- block = (CHAR64LONG16*)workspace;
- memcpy(block, buffer, 64);
-#else
- block = (CHAR64LONG16*)buffer;
-#endif
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- /* Wipe variables */
- a = b = c = d = e = 0;
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
-{
-unsigned int i, j;
-
- j = (context->count[0] >> 3) & 63;
- if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
- context->count[1] += (len >> 29);
- if ((j + len) > 63) {
- memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64) {
- SHA1Transform(context->state, &data[i]);
- }
- j = 0;
- }
- else i = 0;
- memcpy(&context->buffer[j], &data[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
-{
-unsigned long i, j;
-unsigned char finalcount[8];
-
- for (i = 0; i < 8; i++) {
- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- }
- SHA1Update(context, (unsigned char *)"\200", 1);
- while ((context->count[0] & 504) != 448) {
- SHA1Update(context, (unsigned char *)"\0", 1);
- }
- SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
- for (i = 0; i < 20; i++) {
- digest[i] = (unsigned char)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- }
- /* Wipe variables */
- i = j = 0;
- memset(context->buffer, 0, 64);
- memset(context->state, 0, 20);
- memset(context->count, 0, 8);
- memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
- SHA1Transform(context->state, context->buffer);
-#endif
-}
-
-void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
- SHA1_CTX ctx;
-
- SHA1Init(&ctx);
- SHA1Update(&ctx, ptr, size);
- SHA1Final(outbuf, &ctx);
-}
-
diff --git a/source/loader/sys.c b/source/loader/sys.c
index c617b197..245a0588 100644
--- a/source/loader/sys.c
+++ b/source/loader/sys.c
@@ -7,7 +7,6 @@
#include
#include
-#include "sha1.h"
#include "fs.h"
#include "mload.h"
#include "sys.h"
diff --git a/source/loader/utils.h b/source/loader/utils.h
index e8e3bc48..2a2b6e86 100644
--- a/source/loader/utils.h
+++ b/source/loader/utils.h
@@ -20,10 +20,6 @@
#define TITLE_UPPER(x) ((u32)((x) >> 32))
#define TITLE_LOWER(x) ((u32)(x) & 0xFFFFFFFF)
-#define Write8(addr, val) *(u8 *)addr = val; DCFlushRange((void *)addr, sizeof(u8));
-#define Write16(addr, val) *(u16 *)addr = val; DCFlushRange((void *)addr, sizeof(u16));
-#define Write32(addr, val) *(u32 *)addr = val; DCFlushRange((void *)addr, sizeof(u32));
-
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
diff --git a/source/memory/memory.h b/source/memory/memory.h
index a8465d73..e87895d7 100644
--- a/source/memory/memory.h
+++ b/source/memory/memory.h
@@ -37,4 +37,18 @@
#define HW_AHBPROT ((vu32*)0xCD800064)
#define MEM_PROT ((vu32)0xCD8B420A)
+#define HW_AES_CMD ((vu32)0x0D020000)
+#define HW_AES_SRC ((vu32)0x0D020004)
+#define HW_AES_DEST ((vu32)0x0D020008)
+#define HW_AES_KEY ((vu32)0x0D02000C)
+#define HW_AES_IV ((vu32)0x0D020010)
+
+#define HW_SHA1_CMD ((vu32)0x0D030000)
+#define HW_SHA1_SRC ((vu32)0x0D030004)
+#define HW_SHA1_H0 ((vu32)0x0D030008)
+#define HW_SHA1_H1 ((vu32)0x0D03000C)
+#define HW_SHA1_H2 ((vu32)0x0D030010)
+#define HW_SHA1_H3 ((vu32)0x0D030014)
+#define HW_SHA1_H4 ((vu32)0x0D030018)
+
#endif
diff --git a/source/menu/menu_wad.cpp b/source/menu/menu_wad.cpp
index d6d4766c..d6aa20c4 100644
--- a/source/menu/menu_wad.cpp
+++ b/source/menu/menu_wad.cpp
@@ -19,10 +19,8 @@
#include "channel/nand.hpp"
extern "C" {
-#include "loader/sha1.h"
-extern void aes_set_key(u8 *key);
-extern void aes_decrypt_partial(u8 *inbuf, u8 *outbuf, u8 block[16],
- u8 *ctext_ptr, u32 tmp_blockno);
+#include "hw/sha1.h"
+#include "hw/aes.h"
};
#define WAD_BUF 0x10000
@@ -94,7 +92,6 @@ int installWad(const char *path)
gprintf("Decrypting key\n");
u8 tik_key[16];
decrypt_title_key(tik_buf, tik_key);
- aes_set_key(tik_key);
gprintf("Reading tmd\n");
signed_blob *tmd_buf = (signed_blob*)MEM2_alloc(hdr.tmd_len);
@@ -145,6 +142,7 @@ int installWad(const char *path)
new_uid_file[chans].TitleID = tid;
new_uid_file[chans].uid = 0x1000+chans;
fsop_WriteFile(fmt("%s/sys/uid.sys", EmuNAND), new_uid_file, new_uid_size);
+ MEM2_free(new_uid_buf);
}
/* clear old tik */
fsop_deleteFile(fmt("%s/ticket/%08x/%08x.tik", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
@@ -162,15 +160,15 @@ int installWad(const char *path)
fsop_MakeFolder(fmt("%s/title/%08x/%08x/data", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF));
}
int hash_errors = 0;
-
+ u8 *AES_WAD_Buf = (u8*)MEM2_alloc(WAD_BUF);
/* decrypt and write app files */
for(u16 cnt = 0; cnt < tmd_ptr->num_contents; cnt++)
{
- u8 iv[16];
+ u8 aes_iv[16];
+ memset(aes_iv, 0, 16);
const tmd_content *content = &tmd_ptr->contents[cnt];
u16 content_index = content->index;
- memset(iv, 0, 16);
- memcpy(iv, &content_index, 2);
+ memcpy(aes_iv, &content_index, 2);
/* longass filename */
FILE *app_file = NULL;
s32 fd = -1;
@@ -195,16 +193,10 @@ int installWad(const char *path)
gprintf("Writing Real NAND File %s\n", ISFS_Path);
}
u64 read = 0;
- u8 *encBuf = (u8*)MEM2_alloc(WAD_BUF);
- u8 *decBuf = (u8*)MEM2_alloc(WAD_BUF);
-
- u8 block[16];
- u8 prev_block[16];
- u8 *ctext_ptr = iv;
SHA1_CTX ctx;
SHA1Init(&ctx);
-
+ AES_EnableDecrypt(tik_key, aes_iv);
u32 size_enc_full = ALIGN(16, content->size);
while(read < size_enc_full)
{
@@ -212,27 +204,18 @@ int installWad(const char *path)
if (size_enc > WAD_BUF)
size_enc = WAD_BUF;
- memset(encBuf, 0, WAD_BUF);
- fread(encBuf, size_enc, 1, wad_file);
+ u16 num_blocks = (size_enc / 16);
+ fread(AES_WAD_Buf, size_enc, 1, wad_file);
+ AES_Decrypt(AES_WAD_Buf, AES_WAD_Buf, num_blocks);
- u32 partnr = 0;
- u32 lastnr = (size_enc / sizeof(block));
-
- for(partnr = 0; partnr < lastnr; partnr++)
- {
- aes_decrypt_partial(encBuf, decBuf, block, ctext_ptr, partnr);
- memcpy(prev_block, encBuf + (partnr * 16), 16);
- ctext_ptr = prev_block;
- }
- /* we need to work with the real size here */
u64 size_dec = (content->size - read);
if(size_dec > WAD_BUF)
size_dec = WAD_BUF;
- SHA1Update(&ctx, decBuf, size_dec);
+ SHA1Update(&ctx, AES_WAD_Buf, size_dec);
if(mios == false)
- fwrite(decBuf, size_dec, 1, app_file);
+ fwrite(AES_WAD_Buf, size_dec, 1, app_file);
else if(fd >= 0)
- ISFS_Write(fd, decBuf, size_dec);
+ ISFS_Write(fd, AES_WAD_Buf, size_dec);
/* dont forget to increase the read size */
read += size_enc;
mainMenu.update_pThread(size_enc);
@@ -254,6 +237,8 @@ int installWad(const char *path)
hash_errors++;
}
}
+ MEM2_free(AES_WAD_Buf);
+
if(mios == false)
{
fsop_WriteFile(fmt("%s/ticket/%08x/%08x.tik", EmuNAND, (u32)(tid>>32), (u32)tid&0xFFFFFFFF), tik_buf, hdr.tik_len);
diff --git a/wiiflow.pnproj b/wiiflow.pnproj
index d90e6245..f81b4b26 100644
--- a/wiiflow.pnproj
+++ b/wiiflow.pnproj
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/wiiflow.pnps b/wiiflow.pnps
index eba498cf..8456ab6d 100644
--- a/wiiflow.pnps
+++ b/wiiflow.pnps
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file