summaryrefslogtreecommitdiffstats
path: root/utils/atj2137/atjboottool/fwu.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/atj2137/atjboottool/fwu.c')
-rw-r--r--utils/atj2137/atjboottool/fwu.c628
1 files changed, 344 insertions, 284 deletions
diff --git a/utils/atj2137/atjboottool/fwu.c b/utils/atj2137/atjboottool/fwu.c
index 4d09dd876e..c9f6c440fd 100644
--- a/utils/atj2137/atjboottool/fwu.c
+++ b/utils/atj2137/atjboottool/fwu.c
@@ -59,6 +59,46 @@ struct fwu_crypto_hdr_t
uint8_t key[32];
} __attribute__((packed));
+struct fwu_sector0_tail_t
+{
+ uint8_t unk_2;
+ uint32_t unk_x808;
+ uint32_t unk_8;
+ uint8_t key_B[16];
+ uint8_t guid[16];
+ uint8_t unk_190;
+ uint8_t super_secret_xor[16];
+ uint8_t timestamp[8];
+ uint8_t unk_0;
+ uint8_t guid_filler[20];
+ uint8_t unk_1;
+ uint8_t check[20];
+} __attribute__((packed));
+
+struct fwu_block_A_hdr_t
+{
+ uint16_t block_A_size;
+ uint8_t unk_0_a;
+ uint8_t unk_1_a;
+ uint8_t key_B[16];
+ uint8_t guid_filler[256];
+ uint8_t ec_sz;
+ uint8_t unk_0_b;
+ uint32_t unk_5;
+ uint32_t unk_x505;
+ uint16_t unk_1_b;
+ uint8_t timestamp[8];
+} __attribute__((packed));
+
+struct fwu_block_B_hdr_t
+{
+ uint16_t block_B_size;
+ uint8_t unk_1_a;
+ uint16_t unk_1_b;
+ uint8_t timestamp[8];
+ uint16_t guid_filler_size;
+} __attribute__((packed));
+
struct fwu_tail_t
{
uint8_t length; /* in blocks? it's always 1 */
@@ -95,41 +135,32 @@ typedef struct ec_point_t
uint32_t *y;
}ec_point_t;
-struct block_A_info_t
+struct ec_info_t
{
int nr_bits;
- uint16_t field_2;
- int nr_words;
- int nr_dwords_x12;
+ int point_size;
uint32_t *ec_a; // size
- uint32_t *ptr7; // size
+ uint32_t *ec_b; // size
uint32_t *field_poly; // size
uint32_t size;
- uint32_t field_1C;
- ec_point_t ptr1;
- uint32_t *ptr3; // size
- uint32_t *ptr4; // size
- int nr_words2;
+ ec_point_t pt_G;
+ ec_point_t pt_kG; // calculated ECIES public key
uint32_t field_bits;
- int nr_dwords_x8;
+ int size_x2;
int nr_bytes;
- int nr_bytes2;
int nr_dwords_m1;
- int nr_dwords_x2_m1;
int nr_dwords_x2;
+ int nr_dwords_x2_m1;
int nr_dwords;
- uint32_t field_54;
- uint32_t field_58;
};
-struct block_A_info_t g_decode_A_info;
-uint8_t g_subblock_A[0x128];
+struct ec_info_t g_ec_info;
+struct fwu_block_A_hdr_t g_subblock_A;
uint8_t g_key_B[20];
-uint8_t g_perm_B[258];
-uint8_t g_crypto_info_byte;
-uint8_t *g_decode_buffer;
-uint8_t *g_decode_buffer2;
-void *g_decode_buffer3;
+uint8_t g_rc4_S[258];
+uint8_t g_field_sz_byte;
+ec_point_t g_public_key; // from block A
+uint32_t *g_private_key; // from block B
#include "atj_tables.h"
#include <ctype.h>
@@ -186,7 +217,7 @@ int get_version(uint8_t *buf, unsigned long size)
static int decode_block_A(uint8_t block[1020])
{
- uint8_t *p = &g_check_block_A_table[32 * (block[998] & 0x1f)];
+ uint8_t *p = &g_decode_A_table[32 * (block[998] & 31)];
uint8_t key[32];
for(int i = 0; i < 20; i++)
@@ -197,50 +228,53 @@ static int decode_block_A(uint8_t block[1020])
for(int i = 20; i < 32; i++)
key[i] = key[i - 20];
- for(int i = 0; i < 992; i++)
- block[i] ^= key[i % 32] ^ g_check_block_A_table[i];
+ for(int i = 0; i < 31 * 32; i++)
+ block[i] ^= key[i % 32] ^ g_decode_A_table[i];
+ // FIXME dereferencing block - 1 is undefined behavior in standard C
return check_block(block - 1, block + 1000, 1001);
}
-static void compute_perm(uint8_t *keybuf, size_t size, uint8_t perm[258])
+// https://en.wikipedia.org/wiki/RC4#Key-scheduling_algorithm_(KSA)
+static void rc4_key_schedule(uint8_t *key, size_t keylength, uint8_t S[258])
{
for(int i = 0; i < 256; i++)
- perm[i] = i;
- perm[256] = perm[257] = 0;
- uint8_t idx = 0;
+ S[i] = i;
+ S[256] = S[257] = 0;
+ uint8_t j = 0;
for(int i = 0; i < 256; i++)
{
- uint8_t v = perm[i];
- idx = (v + keybuf[i % size] + idx) % 256;
- perm[i] = perm[idx];
- perm[idx] = v;
+ j = (j + S[i] + key[i % keylength]) % 256;
+ uint8_t tmp = S[i];
+ S[i] = S[j];
+ S[j] = tmp;
}
}
-static void decode_perm(uint8_t *buf, size_t size, uint8_t perm[258])
+// https://en.wikipedia.org/wiki/RC4#Pseudo-random_generation_algorithm_(PRGA)
+static void rc4_stream_cipher(uint8_t *buf, size_t size, uint8_t S[258])
{
- uint8_t idxa = perm[256];
- uint8_t idxb = perm[257];
- for(size_t i = 0; i < size; i++)
+ uint8_t i = S[256];
+ uint8_t j = S[257];
+ for(size_t k = 0; k < size; k++)
{
- idxa = (idxa + 1) % 256;
- uint8_t v = perm[idxa];
- idxb = (idxb + v) % 256;
- perm[idxa] = perm[idxb];
- perm[idxb] = v;
- buf[i] ^= perm[(v + perm[idxa]) % 256];
+ i = (i + 1) % 256;
+ j = (j + S[i]) % 256;
+ uint8_t tmp = S[i];
+ S[i] = S[j];
+ S[j] = tmp;
+ buf[k] ^= S[(S[i] + S[j]) % 256];
}
}
-static void decode_block_with_perm(uint8_t *keybuf, int keysize,
- uint8_t *buf, int bufsize, uint8_t perm[258])
+static void rc4_cipher_block(uint8_t *keybuf, int keysize,
+ uint8_t *buf, int bufsize, uint8_t S[258])
{
- compute_perm(keybuf, keysize, perm);
- decode_perm(buf, bufsize, perm);
+ rc4_key_schedule(keybuf, keysize, S);
+ rc4_stream_cipher(buf, bufsize, S);
}
-static void apply_perm(uint8_t *inbuf, uint8_t *outbuf, size_t size, int swap)
+static void rc4_key_swap(uint8_t *inbuf, uint8_t *outbuf, size_t size, int swap)
{
memcpy(outbuf, inbuf, size);
int a = swap & 0xf;
@@ -250,16 +284,16 @@ static void apply_perm(uint8_t *inbuf, uint8_t *outbuf, size_t size, int swap)
outbuf[b] = v;
}
-static void decode_block_with_swap(uint8_t keybuf[32], int swap,
- uint8_t *buf, int bufsize, uint8_t perm[258])
+static void rc4_key_swap_and_decode(uint8_t keybuf[32], int swap,
+ uint8_t *buf, int bufsize, uint8_t S[258])
{
uint8_t keybuf_interm[32];
- apply_perm(keybuf, keybuf_interm, 32, swap);
- decode_block_with_perm(keybuf_interm, 32, buf, bufsize, perm);
+ rc4_key_swap(keybuf, keybuf_interm, 32, swap);
+ rc4_cipher_block(keybuf_interm, 32, buf, bufsize, S);
}
-static void clear_memory(void *buf, size_t size_dwords)
+static void gf_zero(void *buf, size_t size_dwords)
{
memset(buf, 0, 4 * size_dwords);
}
@@ -269,40 +303,35 @@ static void set_bit(int bit_pos, uint32_t *buf)
buf[bit_pos / 32] |= 1 << (bit_pos % 32);
}
-static int fill_decode_info(uint8_t sz)
+static int fill_ec_info(uint8_t sz)
{
if(sz == 2) sz = 233;
else if(sz == 3) sz = 163;
else return 1;
- g_decode_A_info.nr_bits = sz;
- g_decode_A_info.nr_bytes2 = sz / 8 + (sz % 8 != 0);
- g_decode_A_info.nr_words = 2 * g_decode_A_info.nr_bytes2;
- g_decode_A_info.nr_bytes = sz / 8 + (sz % 8 != 0);
- g_decode_A_info.nr_words2 = 2 * g_decode_A_info.nr_bytes2;
- g_decode_A_info.nr_dwords = sz / 32 + (sz % 32 != 0);
- g_decode_A_info.size = 4 * g_decode_A_info.nr_dwords;
- g_decode_A_info.nr_dwords_x8 = 8 * g_decode_A_info.nr_dwords;
- g_decode_A_info.nr_dwords_m1 = g_decode_A_info.nr_dwords - 1;
- g_decode_A_info.nr_dwords_x2 = 2 * g_decode_A_info.nr_dwords;
- g_decode_A_info.nr_dwords_x2_m1 = g_decode_A_info.nr_dwords_x2 - 1;
- g_decode_A_info.nr_dwords_x12 = 12 * g_decode_A_info.nr_dwords;
- g_decode_A_info.ptr1.x = malloc(4 * g_decode_A_info.nr_dwords);
- g_decode_A_info.ptr1.y = malloc(g_decode_A_info.size);
- g_decode_A_info.ptr3 = malloc(g_decode_A_info.size);
- g_decode_A_info.ptr4 = malloc(g_decode_A_info.size);
- g_decode_A_info.field_poly = malloc(g_decode_A_info.size);
- g_decode_A_info.ec_a = malloc(g_decode_A_info.size);
- g_decode_A_info.ptr7 = malloc(g_decode_A_info.size);
-
- cprintf(BLUE, " Decode Info:\n");
- cprintf_field(" Nr Bits: ", "%d\n", g_decode_A_info.nr_bits);
- cprintf_field(" Nr Bytes: ", "%d\n", g_decode_A_info.nr_bytes);
- cprintf_field(" Nr Bytes 2: ", "%d\n", g_decode_A_info.nr_bytes2);
- cprintf_field(" Nr Words: ", "%d\n", g_decode_A_info.nr_words);
- cprintf_field(" Nr Words 2: ", "%d\n", g_decode_A_info.nr_words2);
- cprintf_field(" Nr DWords: ", "%d\n", g_decode_A_info.nr_dwords);
- cprintf_field(" Size: ", "%d\n", g_decode_A_info.size);
+ g_ec_info.nr_bits = sz;
+ g_ec_info.nr_bytes = sz / 8 + (sz % 8 != 0);
+ g_ec_info.point_size = 2 * g_ec_info.nr_bytes;
+ g_ec_info.nr_dwords = sz / 32 + (sz % 32 != 0);
+ g_ec_info.size = 4 * g_ec_info.nr_dwords;
+ g_ec_info.size_x2 = 8 * g_ec_info.nr_dwords;
+ g_ec_info.nr_dwords_m1 = g_ec_info.nr_dwords - 1;
+ g_ec_info.nr_dwords_x2 = 2 * g_ec_info.nr_dwords;
+ g_ec_info.nr_dwords_x2_m1 = g_ec_info.nr_dwords_x2 - 1;
+ g_ec_info.pt_G.x = malloc(4 * g_ec_info.nr_dwords);
+ g_ec_info.pt_G.y = malloc(g_ec_info.size);
+ g_ec_info.pt_kG.x = malloc(g_ec_info.size);
+ g_ec_info.pt_kG.y = malloc(g_ec_info.size);
+ g_ec_info.field_poly = malloc(g_ec_info.size);
+ g_ec_info.ec_a = malloc(g_ec_info.size);
+ g_ec_info.ec_b = malloc(g_ec_info.size);
+
+ cprintf(BLUE, " Elliptic curve info:\n");
+ cprintf_field(" Field Bits: ", "%d\n", g_ec_info.nr_bits);
+ cprintf_field(" Field Bytes: ", "%d\n", g_ec_info.nr_bytes);
+ cprintf_field(" Point Size: ", "%d\n", g_ec_info.point_size);
+ cprintf_field(" Field DWords: ", "%d\n", g_ec_info.nr_dwords);
+ cprintf_field(" Size: ", "%d\n", g_ec_info.size);
return 0;
}
@@ -313,29 +342,31 @@ static int process_block_A(uint8_t block[1024])
int ret = decode_block_A(block + 4);
cprintf(GREEN, " Check: ");
check_field(ret, 0, "Pass\n", "Fail\n");
- print_hex("BlockA", block, 1024);
+ // print_hex("BlockA", block, 1024);
- memcpy(g_subblock_A, block, sizeof(g_subblock_A));
- ret = fill_decode_info(g_subblock_A[276]);
+ memcpy(&g_subblock_A, block, sizeof(g_subblock_A));
+ // assert(offsetof(struct fwu_block_A_hdr_t, ec_sz) == 276);
+ ret = fill_ec_info(g_subblock_A.ec_sz);
cprintf(GREEN, " Info: ");
check_field(ret, 0, "Pass\n", "Fail\n");
- int tmp = 2 * g_decode_A_info.nr_bytes2 + 38;
+ int tmp = 2 * g_ec_info.nr_bytes + 38;
int offset = 1004 - tmp + 5;
- g_crypto_info_byte = block[offset - 1];
- g_decode_buffer = malloc(g_decode_A_info.size);
- g_decode_buffer2 = malloc(g_decode_A_info.size);
+ g_field_sz_byte = block[offset - 1];
+ g_public_key.x = malloc(g_ec_info.size);
+ g_public_key.y = malloc(g_ec_info.size);
- memset(g_decode_buffer, 0, g_decode_A_info.size);
- memset(g_decode_buffer2, 0, g_decode_A_info.size);
+ memset(g_public_key.x, 0, g_ec_info.size);
+ memset(g_public_key.y, 0, g_ec_info.size);
- memcpy(g_decode_buffer, &block[offset], g_decode_A_info.nr_bytes2);
- int offset2 = g_decode_A_info.nr_bytes2 + offset;
- memcpy(g_decode_buffer2, &block[offset2], g_decode_A_info.nr_bytes2);
+ memcpy(g_public_key.x, &block[offset], g_ec_info.nr_bytes);
+ int offset2 = g_ec_info.nr_bytes + offset;
+ memcpy(g_public_key.y, &block[offset2], g_ec_info.nr_bytes);
- cprintf_field(" Word: ", "%d ", *(uint16_t *)&g_subblock_A[286]);
- check_field(*(uint16_t *)&g_subblock_A[286], 1, "Ok\n", "Mismatch\n");
+ // assert(offsetof(struct fwu_block_A_hdr_t, unk_1_b) == 286);
+ cprintf_field(" Word: ", "%d ", g_subblock_A.unk_1_b);
+ check_field(g_subblock_A.unk_1_b, 1, "Ok\n", "Mismatch\n");
return 0;
}
@@ -353,12 +384,12 @@ static void decode_key_B(uint8_t buf[20], uint8_t buf2[16], uint8_t key[20])
static void decode_block_B(uint8_t *buf, uint8_t key[16], size_t size)
{
decode_key_B(&buf[size], key, g_key_B);
- decode_block_with_perm(g_key_B, 20, buf, size, g_perm_B);
+ rc4_cipher_block(g_key_B, 20, buf, size, g_rc4_S);
}
static int find_last_bit_set(uint32_t *buf, bool a)
{
- int i = a ? g_decode_A_info.nr_dwords_m1 : g_decode_A_info.nr_dwords_x2_m1;
+ int i = a ? g_ec_info.nr_dwords_m1 : g_ec_info.nr_dwords_x2_m1;
while(i >= 0 && buf[i] == 0)
i--;
@@ -370,15 +401,15 @@ static int find_last_bit_set(uint32_t *buf, bool a)
return -1; // unreachable
}
-static void copy_memory(uint32_t *to, uint32_t *from)
+static void gf_copy(uint32_t *to, uint32_t *from)
{
- for(int i = 0; i < g_decode_A_info.nr_dwords; i++)
+ for(int i = 0; i < g_ec_info.nr_dwords; i++)
to[i] = from[i];
}
-static void swap_memory(uint32_t *a, uint32_t *b)
+static void gf_swap(uint32_t *a, uint32_t *b)
{
- for(int i = 0; i < g_decode_A_info.nr_dwords; i++)
+ for(int i = 0; i < g_ec_info.nr_dwords; i++)
{
uint32_t c = a[i];
a[i] = b[i];
@@ -388,11 +419,11 @@ static void swap_memory(uint32_t *a, uint32_t *b)
static void shift_left(uint32_t *buf, int nr_bits)
{
- for(int i = g_decode_A_info.nr_dwords_m1; i >= 0; i--)
+ for(int i = g_ec_info.nr_dwords_m1; i >= 0; i--)
buf[i + (nr_bits / 32)] = buf[i];
memset(buf, 0, 4 * (nr_bits / 32));
- size_t size = g_decode_A_info.nr_dwords + (nr_bits + 31) / 32;
+ size_t size = g_ec_info.nr_dwords + (nr_bits + 31) / 32;
nr_bits = nr_bits % 32;
uint32_t acc = 0;
@@ -407,9 +438,9 @@ static void shift_left(uint32_t *buf, int nr_bits)
}
}
-static void xor_big(uint32_t *res, uint32_t *a, uint32_t *b)
+static void gf_add_x2(uint32_t *res, uint32_t *a, uint32_t *b)
{
- for(int i = 0; i < g_decode_A_info.nr_dwords_x2; i++)
+ for(int i = 0; i < g_ec_info.nr_dwords_x2; i++)
res[i] = a[i] ^ b[i];
}
@@ -433,39 +464,49 @@ static void print_poly(const char *name, uint32_t *poly, int nr_dwords)
cprintf(OFF, "\n");
}
-static void gf_inverse(uint32_t *res, uint32_t *val)
+/* https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Simple_algebraic_field_extensions
+ * invariant: p * s + a * t == r -> a * t == r (mod p)
+ * loop until only lowest bit set (r == 1) -> inverse in t */
+static void gf_inverse(uint32_t *newt, uint32_t *val)
{
- uint32_t *tmp = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *copy = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *copy_arg = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *tmp2 = malloc(g_decode_A_info.nr_dwords_x8);
- clear_memory(tmp, g_decode_A_info.nr_dwords_x2);
- clear_memory(res, g_decode_A_info.nr_dwords);
- *res = 1;
- clear_memory(tmp2, g_decode_A_info.nr_dwords);
- copy_memory(copy_arg, val);
- copy_memory(copy, (uint32_t *)g_decode_A_info.field_poly);
-
- for(int i = find_last_bit_set(copy_arg, 1); i; i = find_last_bit_set(copy_arg, 1))
+ uint32_t *tmp = malloc(g_ec_info.size_x2);
+ uint32_t *r = malloc(g_ec_info.size_x2);
+ uint32_t *newr = malloc(g_ec_info.size_x2);
+ uint32_t *t = malloc(g_ec_info.size_x2);
+ gf_zero(tmp, g_ec_info.nr_dwords_x2);
+ /* newt := 1 */
+ gf_zero(newt, g_ec_info.nr_dwords);
+ *newt = 1;
+ /* t := 0 */
+ gf_zero(t, g_ec_info.nr_dwords);
+ /* newr := a */
+ gf_copy(newr, val);
+ /* r := p */
+ gf_copy(r, g_ec_info.field_poly);
+
+ for(int i = find_last_bit_set(newr, 1); i; i = find_last_bit_set(newr, 1))
{
- int pos = i - find_last_bit_set(copy, 1);
+ /* pos := degree(newr) - degree(r) */
+ int pos = i - find_last_bit_set(r, 1);
if(pos < 0)
{
- swap_memory(copy_arg, copy);
- swap_memory(res, tmp2);
+ gf_swap(newr, r);
+ gf_swap(newt, t);
pos = -pos;
}
- copy_memory(tmp, copy);
+ /* newr := newr - x^pos * r */
+ gf_copy(tmp, r);
shift_left(tmp, pos);
- xor_big(copy_arg, copy_arg, tmp);
- copy_memory(tmp, tmp2);
+ gf_add_x2(newr, newr, tmp);
+ /* newt := newt - x^pos * t */
+ gf_copy(tmp, t);
shift_left(tmp, pos);
- xor_big(res, res, tmp);
+ gf_add_x2(newt, newt, tmp);
}
free(tmp);
- free(copy);
- free(copy_arg);
- free(tmp2);
+ free(r);
+ free(newr);
+ free(t);
}
static void shift_left_one(uint32_t *a)
@@ -488,15 +529,15 @@ static void shift_left_one(uint32_t *a)
#if 1
static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
{
- uint32_t *tmp2 = malloc(g_decode_A_info.nr_dwords_x8);
- clear_memory(tmp2, g_decode_A_info.nr_dwords_x2);
- copy_memory(tmp2, a3);
+ uint32_t *tmp2 = malloc(g_ec_info.size_x2);
+ gf_zero(tmp2, g_ec_info.nr_dwords_x2);
+ gf_copy(tmp2, a3);
- int pos = g_decode_A_info.nr_dwords;
+ int pos = g_ec_info.nr_dwords;
uint32_t mask = 1;
for(int i = 0; i < 32; i++)
{
- for(int j = 0; j < g_decode_A_info.nr_dwords; j++)
+ for(int j = 0; j < g_ec_info.nr_dwords; j++)
{
if(a2[j] & mask)
for(int k = 0; k < pos; k++)
@@ -511,8 +552,8 @@ static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
#else
static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
{
- for(int i = 0; i < 32 * g_decode_A_info.nr_dwords; i++)
- for(int j = 0; j < 32 * g_decode_A_info.nr_dwords; j++)
+ for(int i = 0; i < 32 * g_ec_info.nr_dwords; i++)
+ for(int j = 0; j < 32 * g_ec_info.nr_dwords; j++)
{
int k = i + j;
uint32_t v1 = (a2[i / 32] >> (i % 32)) & 1;
@@ -522,32 +563,35 @@ static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
}
#endif
-static void gf_mod(uint32_t *inout, uint32_t *other)
+// https://en.wikipedia.org/wiki/Polynomial_long_division#Pseudocode
+static void gf_mod(uint32_t *r, uint32_t *field_poly)
{
- uint32_t *tmp = malloc(g_decode_A_info.nr_dwords_x8);
- int v4 = g_decode_A_info.field_bits;
- int pos = find_last_bit_set(inout, 0);
- for(int i = pos - v4; i >= 0; i = find_last_bit_set(inout, 0) - v4)
+ uint32_t *tmp = malloc(g_ec_info.size_x2);
+ int deg_d = g_ec_info.field_bits;
+ int deg_r = find_last_bit_set(r, 0);
+ /* i := degree(lead(r) / lead(d)) */
+ for(int i = deg_r - deg_d; i >= 0; i = find_last_bit_set(r, 0) - deg_d)
{
- clear_memory(tmp, g_decode_A_info.nr_dwords_x2);
- copy_memory(tmp, other);
+ /* r := r - x^i * d */
+ gf_zero(tmp, g_ec_info.nr_dwords_x2);
+ gf_copy(tmp, field_poly);
shift_left(tmp, i);
- xor_big(inout, inout, tmp);
+ gf_add_x2(r, r, tmp);
}
free(tmp);
}
static void gf_add(uint32_t *res, uint32_t *a, uint32_t *b)
{
- for(int i = 0; i < g_decode_A_info.nr_dwords; i++)
+ for(int i = 0; i < g_ec_info.nr_dwords; i++)
res[i] = a[i] ^ b[i];
}
static void print_point(const char *name, ec_point_t *ptr)
{
cprintf(BLUE, "%s\n", name);
- print_poly(" x: ", ptr->x, g_decode_A_info.nr_dwords);
- print_poly(" y: ", ptr->y, g_decode_A_info.nr_dwords);
+ print_poly(" x: ", ptr->x, g_ec_info.nr_dwords);
+ print_poly(" y: ", ptr->y, g_ec_info.nr_dwords);
}
static uint32_t g_gf_one[9] =
@@ -557,42 +601,42 @@ static uint32_t g_gf_one[9] =
static void ec_double(ec_point_t *point, ec_point_t *res)
{
- uint32_t *v2 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v3 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v4 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v5 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v6 = malloc(g_decode_A_info.nr_dwords_x8);
- clear_memory(res->x, g_decode_A_info.nr_dwords);
- clear_memory(res->y, g_decode_A_info.nr_dwords);
- clear_memory(v3, g_decode_A_info.nr_dwords_x2);
- clear_memory(v6, g_decode_A_info.nr_dwords_x2);
- clear_memory(v4, g_decode_A_info.nr_dwords_x2);
+ uint32_t *v2 = malloc(g_ec_info.size_x2);
+ uint32_t *v3 = malloc(g_ec_info.size_x2);
+ uint32_t *v4 = malloc(g_ec_info.size_x2);
+ uint32_t *v5 = malloc(g_ec_info.size_x2);
+ uint32_t *v6 = malloc(g_ec_info.size_x2);
+ gf_zero(res->x, g_ec_info.nr_dwords);
+ gf_zero(res->y, g_ec_info.nr_dwords);
+ gf_zero(v3, g_ec_info.nr_dwords_x2);
+ gf_zero(v6, g_ec_info.nr_dwords_x2);
+ gf_zero(v4, g_ec_info.nr_dwords_x2);
/* v4 := 1/x */
gf_inverse(v4, point->x);
- clear_memory(v5, g_decode_A_info.nr_dwords_x2);
+ gf_zero(v5, g_ec_info.nr_dwords_x2);
/* v5 := y/x */
gf_mult(v5, v4, point->y);
- gf_mod(v5, g_decode_A_info.field_poly);
+ gf_mod(v5, g_ec_info.field_poly);
/* v2 := x + y/x (lambda) */
gf_add(v2, point->x, v5);
/* v4 := ec_a + lambda */
- gf_add(v4, v2, g_decode_A_info.ec_a);
- clear_memory(v3, g_decode_A_info.nr_dwords_x2);
+ gf_add(v4, v2, g_ec_info.ec_a);
+ gf_zero(v3, g_ec_info.nr_dwords_x2);
/* v3 := lambda^2 */
gf_mult(v3, v2, v2);
- gf_mod(v3, g_decode_A_info.field_poly);
+ gf_mod(v3, g_ec_info.field_poly);
/* x' := lambda + lambda^2 + ec_a */
gf_add(res->x, v4, v3);
- clear_memory(v5, g_decode_A_info.nr_dwords_x2);
+ gf_zero(v5, g_ec_info.nr_dwords_x2);
/* v4 := lambda + g_gf_one */
gf_add(v4, v2, g_gf_one);
/* v5 := (lambda + 1) * x' = lambda.x' + x' */
gf_mult(v5, v4, res->x);
- gf_mod(v5, g_decode_A_info.field_poly);
- clear_memory(v6, g_decode_A_info.nr_dwords_x2);
+ gf_mod(v5, g_ec_info.field_poly);
+ gf_zero(v6, g_ec_info.nr_dwords_x2);
/* v6 := x1^2 */
gf_mult(v6, point->x, point->x);
- gf_mod(v6, g_decode_A_info.field_poly);
+ gf_mod(v6, g_ec_info.field_poly);
/* y' = (lambda + g_gf_one) * x + x^2 = x^2 + lambda.x + x */
gf_add(res->y, v5, v6);
free(v2);
@@ -604,31 +648,31 @@ static void ec_double(ec_point_t *point, ec_point_t *res)
static void ec_add(ec_point_t *a1, ec_point_t *a2, ec_point_t *res)
{
- uint32_t *v3 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v4 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v5 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v6 = malloc(g_decode_A_info.nr_dwords_x8);
- uint32_t *v7 = malloc(g_decode_A_info.nr_dwords_x8);
- clear_memory(res->x, g_decode_A_info.nr_dwords);
- clear_memory(res->y, g_decode_A_info.nr_dwords);
- clear_memory(v4, g_decode_A_info.nr_dwords_x2);
- clear_memory(v7, g_decode_A_info.nr_dwords_x2);
+ uint32_t *v3 = malloc(g_ec_info.size_x2);
+ uint32_t *v4 = malloc(g_ec_info.size_x2);
+ uint32_t *v5 = malloc(g_ec_info.size_x2);
+ uint32_t *v6 = malloc(g_ec_info.size_x2);
+ uint32_t *v7 = malloc(g_ec_info.size_x2);
+ gf_zero(res->x, g_ec_info.nr_dwords);
+ gf_zero(res->y, g_ec_info.nr_dwords);
+ gf_zero(v4, g_ec_info.nr_dwords_x2);
+ gf_zero(v7, g_ec_info.nr_dwords_x2);
/* v5 = y1 + y2 */
gf_add(v5, a1->y, a2->y);
/* v6 = x1 + x2 */
gf_add(v6, a1->x, a2->x);
/* v7 = 1/(x1 + x2) */
gf_inverse(v7, v6);
- clear_memory(v3, g_decode_A_info.nr_dwords_x2);
+ gf_zero(v3, g_ec_info.nr_dwords_x2);
/* v3 = (y1 + y2) / (x1 + x2) (lambda) */
gf_mult(v3, v7, v5);
- gf_mod(v3, g_decode_A_info.field_poly);
+ gf_mod(v3, g_ec_info.field_poly);
/* v5 = lambda + ec_a */
- gf_add(v5, v3, g_decode_A_info.ec_a);
- clear_memory(v4, g_decode_A_info.nr_dwords_x2);
+ gf_add(v5, v3, g_ec_info.ec_a);
+ gf_zero(v4, g_ec_info.nr_dwords_x2);
/* v4 = lambda^2 */
gf_mult(v4, v3, v3);
- gf_mod(v4, g_decode_A_info.field_poly);
+ gf_mod(v4, g_ec_info.field_poly);
/* v7 = lambda^2 + lambda + ec_a */
gf_add(v7, v5, v4);
/* x' = ec_a + x1 + x2 + lambda + lambda^2 */
@@ -637,10 +681,10 @@ static void ec_add(ec_point_t *a1, ec_point_t *a2, ec_point_t *res)
gf_add(v5, a1->x, res->x);
/* v6 = x' + y1 */
gf_add(v6, res->x, a1->y);
- clear_memory(v7, g_decode_A_info.nr_dwords_x2);
+ gf_zero(v7, g_ec_info.nr_dwords_x2);
/* v7 = (x1 + x').lambda */
gf_mult(v7, v5, v3);
- gf_mod(v7, g_decode_A_info.field_poly);
+ gf_mod(v7, g_ec_info.field_poly);
/* y' = (x1 + x').lambda + x' + y1 */
gf_add(res->y, v7, v6);
free(v3);
@@ -654,17 +698,17 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
{
ec_point_t res_others;
- res_others.x = malloc(g_decode_A_info.size);
- res_others.y = malloc(g_decode_A_info.size);
- clear_memory(res->x, g_decode_A_info.nr_dwords);
- clear_memory(res->y, g_decode_A_info.nr_dwords);
- clear_memory(res_others.x, g_decode_A_info.nr_dwords);
- clear_memory(res_others.y, g_decode_A_info.nr_dwords);
+ res_others.x = malloc(g_ec_info.size);
+ res_others.y = malloc(g_ec_info.size);
+ gf_zero(res->x, g_ec_info.nr_dwords);
+ gf_zero(res->y, g_ec_info.nr_dwords);
+ gf_zero(res_others.x, g_ec_info.nr_dwords);
+ gf_zero(res_others.y, g_ec_info.nr_dwords);
int pos = find_last_bit_set(n, 1);
/* res_other := point */
- copy_memory(res_others.x, point->x);
- copy_memory(res_others.y, point->y);
+ gf_copy(res_others.x, point->x);
+ gf_copy(res_others.y, point->y);
/* for all bit from SZ-1 downto 0 */
for(int bit = (pos % 32) - 1; bit >= 0; bit--)
@@ -672,15 +716,15 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
/* res := 2 * res_other */
ec_double(&res_others, res);
/* res_other := res = 2 * res_other */
- copy_memory(res_others.x, res->x);
- copy_memory(res_others.y, res->y);
+ gf_copy(res_others.x, res->x);
+ gf_copy(res_others.y, res->y);
/* if bit of n is set */
if(n[pos / 32] & (1 << bit))
{
/* res := res_other + point */
ec_add(&res_others, point, res);
- copy_memory(res_others.x, res->x);
- copy_memory(res_others.y, res->y);
+ gf_copy(res_others.x, res->x);
+ gf_copy(res_others.y, res->y);
}
}
/* same but optimized */
@@ -689,18 +733,18 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
for(int bit = 31; bit >= 0; bit--)
{
ec_double(&res_others, res);
- copy_memory(res_others.x, res->x);
- copy_memory(res_others.y, res->y);
+ gf_copy(res_others.x, res->x);
+ gf_copy(res_others.y, res->y);
if(n[i] & (1 << bit))
{
ec_add(&res_others, point, res);
- copy_memory(res_others.x, res->x);
- copy_memory(res_others.y, res->y);
+ gf_copy(res_others.x, res->x);
+ gf_copy(res_others.y, res->y);
}
}
}
- copy_memory(res->x, res_others.x);
- copy_memory(res->y, res_others.y);
+ gf_copy(res->x, res_others.x);
+ gf_copy(res->y, res_others.y);
free(res_others.x);
free(res_others.y);
return 0;
@@ -709,7 +753,7 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
static void xor_with_point(uint8_t *buf, ec_point_t *point)
{
/*
- int sz = g_decode_A_info.nr_bytes2 - 1;
+ int sz = g_ec_info.nr_bytes - 1;
if(sz <= 32)
{
for(int i = 0; i < sz; i++)
@@ -723,39 +767,40 @@ static void xor_with_point(uint8_t *buf, ec_point_t *point)
*/
uint8_t *ptrA = (uint8_t *)point->x;
uint8_t *ptrB = (uint8_t *)point->y;
- int sz = MIN(g_decode_A_info.nr_bytes2 - 1, 32);
+ int sz = MIN(g_ec_info.nr_bytes - 1, 32);
for(int i = 0; i < sz; i++)
buf[i] ^= ptrA[i];
for(int i = sz; i < 32; i++)
buf[i] ^= ptrB[i - sz];
}
-static int crypto4(uint8_t *a1, ec_point_t *ptrs, uint32_t *a3)
+// https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme#Formal_description_of_ECIES
+static int xor_with_shared_secret(uint8_t *buf, ec_point_t *pt_rG, uint32_t *private_key)
{
- ec_point_t ptrs_others;
+ ec_point_t shared_secret;
- ptrs_others.x = malloc(g_decode_A_info.size);
- ptrs_others.y = malloc(g_decode_A_info.size);
- clear_memory(ptrs_others.x, g_decode_A_info.nr_dwords);
- clear_memory(ptrs_others.y, g_decode_A_info.nr_dwords);
- int ret = ec_mult(a3, ptrs, &ptrs_others);
+ shared_secret.x = malloc(g_ec_info.size);
+ shared_secret.y = malloc(g_ec_info.size);
+ gf_zero(shared_secret.x, g_ec_info.nr_dwords);
+ gf_zero(shared_secret.y, g_ec_info.nr_dwords);
+ int ret = ec_mult(private_key, pt_rG, &shared_secret);
if(ret == 0)
- xor_with_point(a1, &ptrs_others);
- free(ptrs_others.x);
- free(ptrs_others.y);
+ xor_with_point(buf, &shared_secret);
+ free(shared_secret.x);
+ free(shared_secret.y);
return ret;
}
static int set_field_poly(uint32_t *field_poly, int field_sz)
{
- clear_memory(field_poly, g_decode_A_info.nr_dwords);
- g_decode_A_info.field_bits = 0;
+ gf_zero(field_poly, g_ec_info.nr_dwords);
+ g_ec_info.field_bits = 0;
if(field_sz == 4)
{
set_bit(0, field_poly);
set_bit(74, field_poly);
set_bit(233, field_poly);
- g_decode_A_info.field_bits = 233;
+ g_ec_info.field_bits = 233;
return 0;
}
else if (field_sz == 5)
@@ -765,31 +810,31 @@ static int set_field_poly(uint32_t *field_poly, int field_sz)
set_bit(6, field_poly);
set_bit(7, field_poly);
set_bit(163, field_poly);
- g_decode_A_info.field_bits = 163;
+ g_ec_info.field_bits = 163;
return 0;
}
else
return 1;
}
-static int ec_init(ec_point_t *a1, char field_sz)
+static int ec_init(ec_point_t *ec_G, char field_sz)
{
- int ret = set_field_poly(g_decode_A_info.field_poly, field_sz);
+ int ret = set_field_poly(g_ec_info.field_poly, field_sz);
if(ret) return ret;
if(field_sz == 4)
{
- copy_memory(a1->x, g_crypto_table);
- copy_memory(a1->y, g_crypto_table2);
- copy_memory(g_decode_A_info.ec_a, g_atj_ec233_a);
- copy_memory(g_decode_A_info.ptr7, g_crypto_key6);
+ gf_copy(ec_G->x, g_sect233k1_G_x);
+ gf_copy(ec_G->y, g_sect233k1_G_y);
+ gf_copy(g_ec_info.ec_a, g_sect233k1_a); // zero
+ gf_copy(g_ec_info.ec_b, g_sect233k1_b); // never used
return 0;
}
- else if(field_sz == 5 )
+ else if(field_sz == 6 ) // yet to find even a single specimen
{
- copy_memory(a1->x, g_crypto_key3);
- copy_memory(a1->y, g_crypto_key4);
- copy_memory(g_decode_A_info.ec_a, g_atj_ec163_a);
- copy_memory(g_decode_A_info.ptr7, g_crypto_key5);
+ gf_copy(ec_G->x, g_sect163r2_G_x);
+ gf_copy(ec_G->y, g_sect163r2_G_y);
+ gf_copy(g_ec_info.ec_a, g_sect163r2_a);
+ gf_copy(g_ec_info.ec_b, g_sect163r2_b);
return 0;
}
else
@@ -805,19 +850,21 @@ static void create_guid(void *uid, int bit_size)
static int process_block_B(uint8_t block[512])
{
+ struct fwu_block_B_hdr_t *p_hdr = (void *)block;
+
cprintf(BLUE, "Block B\n");
- decode_block_B(block + 3, g_subblock_A + 4, 489);
- cprintf_field(" Word: ", "%d ", *(uint16_t *)(block + 3));
- check_field(*(uint16_t *)(block + 3), 1, "Ok\n", "Mismatch\n");
+ decode_block_B(block + 3, g_subblock_A.key_B, 492 - 3);
+ cprintf_field(" Word: ", "%d ", p_hdr->unk_1_b);
+ check_field(p_hdr->unk_1_b, 1, "Ok\n", "Mismatch\n");
int ret = check_block(block, block + 492, 492);
cprintf(GREEN, " Check: ");
check_field(ret, 0, "Pass\n", "Fail\n");
- g_decode_buffer3 = malloc(g_decode_A_info.size);
- memset(g_decode_buffer3, 0, g_decode_A_info.size);
- int offset = *(uint16_t *)(block + 13) + 16;
- memcpy(g_decode_buffer3, &block[offset], g_decode_A_info.nr_bytes2);
+ g_private_key = malloc(g_ec_info.size);
+ memset(g_private_key, 0, g_ec_info.size);
+ int offset = sizeof *p_hdr + p_hdr->guid_filler_size + 1;
+ memcpy(g_private_key, &block[offset], g_ec_info.nr_bytes);
return 0;
}
@@ -832,22 +879,22 @@ static int get_key_fwu_v3(size_t size, uint8_t *buf, uint8_t *blockA, uint8_t *b
memset(smallblock, 0, sizeof(smallblock));
memset(bigblock, 0, sizeof(bigblock));
- uint8_t ba = buf[0x1ee] & 0xf;
- uint8_t bb = buf[0x1fe] & 0xf;
+ *blockA = buf[0x1ee] & 15;
+ *blockB = buf[0x1fe] & 15;
+ size_t offsetA = 512 * (1 + *blockA);
+ size_t offsetB = 512 * (1 + *blockB);
cprintf(BLUE, "Crypto\n");
- cprintf_field(" Block A: ", "%d\n", ba + 2);
- cprintf_field(" Block B: ", "%d\n", ba + bb + 5);
+ cprintf_field(" Block A: ", "0x%zx\n", 512 + offsetA);
+ cprintf_field(" Block B: ", "0x%zx\n", 512 + offsetA + 1024 + offsetB);
- *blockA = buf[494] & 0xf;
- *blockB = buf[510] & 0xf;
- memcpy(bigblock, &buf[512 * (*blockA + 2)], sizeof(bigblock));
+ memcpy(bigblock, &buf[512 + offsetA], sizeof(bigblock));
int ret = process_block_A(bigblock);
if(ret != 0)
return ret;
- memcpy(smallblock, &buf[512 * (*blockA + *blockB + 5)], sizeof(smallblock));
+ memcpy(smallblock, &buf[512 + offsetA + 1024 + offsetB], sizeof(smallblock));
ret = process_block_B(smallblock);
if(ret != 0)
return ret;
@@ -859,64 +906,77 @@ static int get_key_fwu_v3(size_t size, uint8_t *buf, uint8_t *blockA, uint8_t *b
cprintf_field(" Byte: ", "%d ", crypto_hdr.unk);
check_field(crypto_hdr.unk, 3, "Ok\n", "Mismatch\n");
- ec_point_t ptrs;
- ptrs.x = malloc(g_decode_A_info.size);
- ptrs.y = malloc(g_decode_A_info.size);
- memset(ptrs.x, 0, g_decode_A_info.size);
- memset(ptrs.y, 0, g_decode_A_info.size);
- memcpy(ptrs.x, buf + 91, g_decode_A_info.nr_bytes2);
- memcpy(ptrs.y, buf + 91 + g_decode_A_info.nr_bytes2, g_decode_A_info.nr_bytes2);
-
- ret = ec_init(&g_decode_A_info.ptr1, g_crypto_info_byte);
- cprintf(GREEN, " Crypto bits copy: ");
+ size_t offset = sizeof(struct fwu_hdr_t) + sizeof(struct fwu_crypto_hdr_t);
+ ec_point_t pt_rG;
+ pt_rG.x = malloc(g_ec_info.size);
+ pt_rG.y = malloc(g_ec_info.size);
+ memset(pt_rG.x, 0, g_ec_info.size);
+ memset(pt_rG.y, 0, g_ec_info.size);
+ memcpy(pt_rG.x, buf + offset, g_ec_info.nr_bytes);
+ memcpy(pt_rG.y, buf + offset + g_ec_info.nr_bytes, g_ec_info.nr_bytes);
+
+ ret = ec_init(&g_ec_info.pt_G, g_field_sz_byte);
+ cprintf(GREEN, " Elliptic curve init: ");
check_field(ret, 0, "Pass\n", "Fail\n");
- ret = crypto4(crypto_hdr.key, &ptrs, g_decode_buffer3);
- cprintf(GREEN, " Crypto 4: ");
+ ec_mult(g_private_key, &g_ec_info.pt_G, &g_ec_info.pt_kG);
+ cprintf(GREEN, " Public key check: ");
+ if (memcmp(g_public_key.x, g_ec_info.pt_kG.x, g_ec_info.nr_bytes) ||
+ memcmp(g_public_key.y, g_ec_info.pt_kG.y, g_ec_info.nr_bytes))
+ {
+ cprintf(RED, "Fail\n");
+ return 1;
+ }
+ else
+ cprintf(RED, "Pass\n");
+
+ ret = xor_with_shared_secret(crypto_hdr.key, &pt_rG, g_private_key);
+ cprintf(GREEN, " ECIES decryption: ");
check_field(ret, 0, "Pass\n", "Fail\n");
memcpy(keybuf, crypto_hdr.key, 32);
- int offset = g_decode_A_info.nr_words + 91;
+ offset += g_ec_info.point_size;
- decode_block_with_swap(keybuf, 0, &buf[offset], 512 - offset, g_perm_B);
+ rc4_key_swap_and_decode(keybuf, 0, &buf[offset], 512 - offset, g_rc4_S);
int pos = *(uint16_t *)&buf[offset];
- cprintf_field(" Word: ", "%d ", pos);
- int tmp = g_decode_A_info.nr_words2 + 199;
+ cprintf_field(" Filler size: ", "%d ", pos);
+ int tmp = offset + sizeof(struct fwu_sector0_tail_t);
check_field(pos, 510 - tmp, "Ok\n", "Mismatch\n");
- uint8_t midbuf[108];
- memcpy(midbuf, &buf[pos + offset + 2], sizeof(midbuf));
+ struct fwu_sector0_tail_t tail;
+ memcpy(&tail, &buf[offset + 2 + pos], sizeof(tail));
- cprintf_field(" Byte: ", "%d ", midbuf[0]);
- check_field(midbuf[0], 2, "Ok\n", "Invalid\n");
- cprintf_field(" DWord: ", "%d ", *(uint32_t *)&midbuf[1]);
- check_field(*(uint32_t *)&midbuf[1], 2056, "Ok\n", "Invalid\n");
- cprintf_field(" DWord: ", "%d ", *(uint32_t *)&midbuf[5]);
- check_field(*(uint32_t *)&midbuf[5], 8, "Ok\n", "Invalid\n");
- cprintf_field(" Byte: ", "%d ", midbuf[41]);
- check_field(midbuf[41], 190, "Ok\n", "Invalid\n");
+ cprintf_field(" Byte: ", "%d ", tail.unk_2);
+ check_field(tail.unk_2, 2, "Ok\n", "Invalid\n");
+ cprintf_field(" DWord: ", "0x%x ", tail.unk_x808);
+ check_field(tail.unk_x808, 0x808, "Ok\n", "Invalid\n");
+ cprintf_field(" DWord: ", "%d ", tail.unk_8);
+ check_field(tail.unk_8, 8, "Ok\n", "Invalid\n");
+ cprintf_field(" Byte: ", "%d ", tail.unk_190);
+ check_field(tail.unk_190, 190, "Ok\n", "Invalid\n");
+ /* encode super secret at random position in guid stream, never used */
memset(blo, 0, 512);
- create_guid(smallblock, 3808);
- memcpy(smallblock + 476, midbuf + 42, 16);
+ create_guid(smallblock, 476 * 8);
+ memcpy(smallblock + 476, tail.super_secret_xor, 16);
compute_checksum(smallblock, 492, blo + 492);
int bsz = blo[500];
memcpy(blo, smallblock, bsz);
- memcpy(blo + bsz, midbuf + 42, 16);
+ memcpy(blo + bsz, tail.super_secret_xor, 16);
memcpy(blo + bsz + 16, smallblock + bsz, 476 - bsz);
+ rc4_cipher_block(blo + 492, 16, blo, 492, g_rc4_S);
- decode_block_with_perm(blo + 492, 16, blo, 492, g_perm_B);
- ret = check_block(buf + 42, midbuf + 88, 450);
- cprintf(GREEN, " Decode block: ");
+ ret = check_block(buf + sizeof(struct fwu_hdr_t), tail.check, 492 - sizeof(struct fwu_hdr_t));
+ cprintf(GREEN, " Check: ");
check_field(ret, 0, "Pass\n", "Fail\n");
- ret = memcmp(g_subblock_A + 4, midbuf + 9, 16);
+ ret = memcmp(g_subblock_A.key_B, tail.key_B, 16);
cprintf(GREEN, " Compare: ");
check_field(ret, 0, "Pass\n", "Fail\n");
/*
- ret = memcmp(midbuf + 25, zero, sizeof(zero));
+ ret = memcmp(tail.guid, zero, sizeof(zero));
cprintf(GREEN, " Sanity: ");
check_field(ret, 0, "Pass\n", "Fail\n");
*/
@@ -1000,15 +1060,15 @@ static int decrypt_fwu_v3(uint8_t *buf, size_t *size, uint8_t block[512], enum f
/* the input buffer is reorganized based on two offsets (blockA and blockB),
* skip 2048 bytes of data used for crypto init */
*size = hdr->fw_size; /* use firmware size, not file size */
- *size -= 2048;
+ *size -= 512 + 1024 + 512; /* sector0 + blockA + blockB */
uint8_t *tmpbuf = malloc(*size);
memset(tmpbuf, 0, *size);
- int offsetA = (blockA + 1) << 9;
- int offsetB = (blockB + 1) << 9;
+ int offsetA = 512 * (1 + blockA);
+ int offsetB = 512 * (1 + blockB);
memcpy(tmpbuf, buf + 512, offsetA);
- memcpy(tmpbuf + offsetA, buf + offsetA + 1536, offsetB);
+ memcpy(tmpbuf + offsetA, buf + 512 + offsetA + 1024, offsetB);
memcpy(tmpbuf + offsetA + offsetB,
- buf + offsetA + 1536 + offsetB + 512, *size - offsetA - offsetB);
+ buf + 512 + offsetA + 1024 + offsetB + 512, *size - offsetA - offsetB);
/* stolen from https://github.com/nfd/atj2127decrypt, I have no idea from where
* he got this sequence of code. This code is really weird, I copy verbatim
* his authors comment below.
@@ -1048,8 +1108,8 @@ static int decrypt_fwu_v3(uint8_t *buf, size_t *size, uint8_t block[512], enum f
atj2127_decrypt(buf, tmpbuf, *size, keybuf, rounds_to_perform);
else
{
- compute_perm(keybuf, 32, g_perm_B);
- decode_perm(tmpbuf, *size, g_perm_B);
+ rc4_key_schedule(keybuf, 32, g_rc4_S);
+ rc4_stream_cipher(tmpbuf, *size, g_rc4_S);
memcpy(buf, tmpbuf, *size);
}
@@ -1102,7 +1162,7 @@ int fwu_decrypt(uint8_t *buf, size_t *size, enum fwu_mode_t mode)
cprintf_field(" Block size: ", "%d ", hdr->block_size);
check_field(hdr->block_size, FWU_BLOCK_SIZE, "Ok\n", "Invalid\n");
- cprintf_field(" Version: ", "%x ", hdr->version);
+ cprintf_field(" Version: ", "0x%x ", hdr->version);
int ver = get_version(buf, *size);
if(ver < 0)
{