summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Burnashev <nikita.burnashev@gmail.com>2023-04-16 12:46:55 +0300
committerSolomon Peachy <pizza@shaftnet.org>2023-05-17 13:19:31 -0400
commite232f69214cfe0ad83e8a6051c58ef54754e59bb (patch)
treedfe36ac87d182c2e3f8f4a99ea74ad3492a1f1dd
parent72c0e49b41b0da4a43a4852771eed3767fc675ad (diff)
downloadrockbox-e232f69214cfe0ad83e8a6051c58ef54754e59bb.tar.gz
rockbox-e232f69214cfe0ad83e8a6051c58ef54754e59bb.zip
atjboottool: gzipped fw files, option for big-endian fw, clarify ECIES in fwu
Added fw modifications required to unpack real world player dumps. Documented more fwu header fields, magic numbers and finite field arithmetics (extended Euclidean for inverse, long division for reducing modulo field_poly). v3 encryption used is standard RC4 with the key additionally ciphered by the Elliptic Curve Integrated Encryption Scheme. Either sect233k1 (NIST K-233) or sect163r2 (NIST B-163) curves can be used, with the former overwhelmingly prevailing, being hardwired in SDK's maker.exe. Using a private/public key scheme is superfluous because both are stored in the firmware, with the added level of complexity likely serving the purpose of obfuscation. The private key is generated at random with each invokation. None of KDF or MAC from ECIES are used, RC4 key is directly xored with the shared secret. The random number r used to calculate rG isn't stored, but that's unimportant since only krG == rkG is actually used in the encryption. Change-Id: Ieacf8cc744bc90c7c5582dd724b2c10a41bfc191
-rw-r--r--utils/atj2137/atjboottool/Makefile2
-rw-r--r--utils/atj2137/atjboottool/atj_tables.c18
-rw-r--r--utils/atj2137/atjboottool/atj_tables.h20
-rw-r--r--utils/atj2137/atjboottool/atjboottool.c37
-rw-r--r--utils/atj2137/atjboottool/fw.c115
-rw-r--r--utils/atj2137/atjboottool/fw.h2
-rw-r--r--utils/atj2137/atjboottool/fwu.c628
7 files changed, 502 insertions, 320 deletions
diff --git a/utils/atj2137/atjboottool/Makefile b/utils/atj2137/atjboottool/Makefile
index 8d96bcdde0..5414b4810e 100644
--- a/utils/atj2137/atjboottool/Makefile
+++ b/utils/atj2137/atjboottool/Makefile
@@ -2,7 +2,7 @@ DEFINES=
2CC=gcc 2CC=gcc
3LD=gcc 3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall $(DEFINES) 4CFLAGS=-g -std=c99 -W -Wall $(DEFINES)
5LDFLAGS= 5LDFLAGS=-lz
6BINS=atjboottool 6BINS=atjboottool
7 7
8all: $(BINS) 8all: $(BINS)
diff --git a/utils/atj2137/atjboottool/atj_tables.c b/utils/atj2137/atjboottool/atj_tables.c
index 579e17d52b..e2bd976bfe 100644
--- a/utils/atj2137/atjboottool/atj_tables.c
+++ b/utils/atj2137/atjboottool/atj_tables.c
@@ -20,7 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include <stdint.h> 21#include <stdint.h>
22 22
23uint8_t g_check_block_A_table[1024] = 23uint8_t g_decode_A_table[1024] =
24{ 24{
25 0x16, 0x2b, 0x01, 0xe4, 0x0e, 0x3d, 0xc1, 0xdf, 0x0f, 0x35, 0x8f, 0xf5, 0xe2, 25 0x16, 0x2b, 0x01, 0xe4, 0x0e, 0x3d, 0xc1, 0xdf, 0x0f, 0x35, 0x8f, 0xf5, 0xe2,
26 0x48, 0xa0, 0x2e, 0x1c, 0x6a, 0x57, 0xea, 0x6d, 0x9a, 0xe2, 0x03, 0xec, 0xe8, 26 0x48, 0xa0, 0x2e, 0x1c, 0x6a, 0x57, 0xea, 0x6d, 0x9a, 0xe2, 0x03, 0xec, 0xe8,
@@ -109,45 +109,45 @@ uint8_t g_decode_B_table[20] =
109 0xf8, 0xb4, 0x36, 0x41, 0xc5, 0x51, 0xaf 109 0xf8, 0xb4, 0x36, 0x41, 0xc5, 0x51, 0xaf
110}; 110};
111 111
112uint32_t g_crypto_table[8] = 112uint32_t g_sect233k1_G_x[8] =
113{ 113{
114 0xefad6126, 0x0a4c9d6e, 0x19c26bf5, 0x149563a4, 0x29f22ff4, 0x7e731af1, 114 0xefad6126, 0x0a4c9d6e, 0x19c26bf5, 0x149563a4, 0x29f22ff4, 0x7e731af1,
115 0x32ba853a, 0x00000172 115 0x32ba853a, 0x00000172
116}; 116};
117 117
118uint32_t g_crypto_table2[8] = 118uint32_t g_sect233k1_G_y[8] =
119{ 119{
120 0x56fae6a3, 0x56e0c110, 0xf18aeb9b, 0x27a8cd9b, 0x555a67c4, 0x19b7f70f, 120 0x56fae6a3, 0x56e0c110, 0xf18aeb9b, 0x27a8cd9b, 0x555a67c4, 0x19b7f70f,
121 0x537dece8, 0x000001db 121 0x537dece8, 0x000001db
122}; 122};
123 123
124uint32_t g_crypto_key6[8] = 124uint32_t g_sect233k1_b[8] =
125{ 125{
126 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 126 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
127 0x00000000, 0x00000000 127 0x00000000, 0x00000000
128}; 128};
129 129
130uint32_t g_crypto_key3[6] = 130uint32_t g_sect163r2_G_x[6] =
131{ 131{
132 0xe8343e36, 0xd4994637, 0xa0991168, 0x86a2d57e, 0xf0eba162, 0x00000003 132 0xe8343e36, 0xd4994637, 0xa0991168, 0x86a2d57e, 0xf0eba162, 0x00000003
133}; 133};
134 134
135uint32_t g_crypto_key4[6] = 135uint32_t g_sect163r2_G_y[6] =
136{ 136{
137 0x797324f1, 0xb11c5c0c, 0xa2cdd545, 0x71a0094f, 0xd51fbc6c, 0x00000000 137 0x797324f1, 0xb11c5c0c, 0xa2cdd545, 0x71a0094f, 0xd51fbc6c, 0x00000000
138}; 138};
139 139
140uint32_t g_atj_ec163_a[6] = 140uint32_t g_sect163r2_a[6] =
141{ 141{
142 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 142 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
143}; 143};
144 144
145uint32_t g_crypto_key5[6] = 145uint32_t g_sect163r2_b[6] =
146{ 146{
147 0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x00000002 147 0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x00000002
148}; 148};
149 149
150uint32_t g_atj_ec233_a[8] = 150uint32_t g_sect233k1_a[8] =
151{ 151{
152 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 152 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
153}; 153};
diff --git a/utils/atj2137/atjboottool/atj_tables.h b/utils/atj2137/atjboottool/atj_tables.h
index d5eb4ae5d4..5ed75d6ac4 100644
--- a/utils/atj2137/atjboottool/atj_tables.h
+++ b/utils/atj2137/atjboottool/atj_tables.h
@@ -21,15 +21,15 @@
21#ifndef __ATJ_TABLES__ 21#ifndef __ATJ_TABLES__
22#define __ATJ_TABLES__ 22#define __ATJ_TABLES__
23 23
24uint8_t g_check_block_A_table[1024]; 24extern uint8_t g_decode_A_table[1024];
25uint8_t g_decode_B_table[20]; 25extern uint8_t g_decode_B_table[20];
26uint32_t g_crypto_table[8]; 26extern uint32_t g_sect233k1_G_x[8];
27uint32_t g_crypto_table2[8]; 27extern uint32_t g_sect233k1_G_y[8];
28uint32_t g_crypto_key6[8]; 28extern uint32_t g_sect233k1_b[8];
29uint32_t g_crypto_key3[6]; 29extern uint32_t g_sect163r2_G_x[6];
30uint32_t g_crypto_key4[6]; 30extern uint32_t g_sect163r2_G_y[6];
31uint32_t g_crypto_key5[6]; 31extern uint32_t g_sect163r2_a[6];
32uint32_t g_atj_ec233_a[8]; 32extern uint32_t g_sect163r2_b[6];
33uint32_t g_atj_ec163_a[6]; 33extern uint32_t g_sect233k1_a[8];
34 34
35#endif // __ATJ_TABLES__ 35#endif // __ATJ_TABLES__
diff --git a/utils/atj2137/atjboottool/atjboottool.c b/utils/atj2137/atjboottool/atjboottool.c
index d0ad1b468b..b68ada980e 100644
--- a/utils/atj2137/atjboottool/atjboottool.c
+++ b/utils/atj2137/atjboottool/atjboottool.c
@@ -27,6 +27,7 @@
27#include <stdarg.h> 27#include <stdarg.h>
28#include <ctype.h> 28#include <ctype.h>
29#include <sys/stat.h> 29#include <sys/stat.h>
30#include <zlib.h>
30#include "misc.h" 31#include "misc.h"
31#include "fwu.h" 32#include "fwu.h"
32#include "afi.h" 33#include "afi.h"
@@ -100,7 +101,26 @@ static int unpack_afi_fw_cb(const char *filename, uint8_t *buf, size_t size)
100 FILE *f = fopen(name, "wb"); 101 FILE *f = fopen(name, "wb");
101 if(f) 102 if(f)
102 { 103 {
103 fwrite(buf, size, 1, f); 104 if (0 != memcmp(buf, "\x1f\x8b\x8\0\0\0\0\0\0\xb", 10))
105 fwrite(buf, size, 1, f);
106 else
107 {
108 uint8_t buf_out[8192];
109 z_stream zs;
110 int err = Z_OK;
111 cprintf(GREEN, "inflating... ");
112 memset(&zs, 0, sizeof(zs));
113 zs.next_in = buf + 10;
114 zs.avail_in = size - 10;
115 inflateInit2(&zs, -MAX_WBITS); /* raw */
116 while (err == Z_OK)
117 {
118 zs.next_out = buf_out;
119 zs.avail_out = sizeof(buf_out);
120 err = inflate(&zs, Z_NO_FLUSH);
121 fwrite(buf_out, 1, sizeof(buf_out) - zs.avail_out, f);
122 }
123 }
104 fclose(f); 124 fclose(f);
105 cprintf(RED, "Ok\n"); 125 cprintf(RED, "Ok\n");
106 return 0; 126 return 0;
@@ -119,10 +139,10 @@ static int do_afi(uint8_t *buf, size_t size)
119 return afi_unpack(buf, size, &unpack_afi_fw_cb); 139 return afi_unpack(buf, size, &unpack_afi_fw_cb);
120} 140}
121 141
122static int do_fw(uint8_t *buf, size_t size) 142static int do_fw(uint8_t *buf, size_t size, bool big_endian)
123{ 143{
124 build_out_prefix(".unpack", "", true); 144 build_out_prefix(".unpack", "", true);
125 return fw_unpack(buf, size, &unpack_afi_fw_cb); 145 return fw_unpack(buf, size, &unpack_afi_fw_cb, big_endian);
126} 146}
127static void usage(void) 147static void usage(void)
128{ 148{
@@ -135,6 +155,7 @@ static void usage(void)
135 printf(" --fwu Unpack a FWU firmware file\n"); 155 printf(" --fwu Unpack a FWU firmware file\n");
136 printf(" --afi Unpack a AFI archive file\n"); 156 printf(" --afi Unpack a AFI archive file\n");
137 printf(" --fw Unpack a FW archive file\n"); 157 printf(" --fw Unpack a FW archive file\n");
158 printf(" --fw251 Big-endian FW archive used on Flip80251\n");
138 printf(" --atj2127 Force ATJ2127 decryption mode\n"); 159 printf(" --atj2127 Force ATJ2127 decryption mode\n");
139 printf("The default is to try to guess the format.\n"); 160 printf("The default is to try to guess the format.\n");
140 printf("If several formats are specified, all are tried.\n"); 161 printf("If several formats are specified, all are tried.\n");
@@ -147,6 +168,7 @@ int main(int argc, char **argv)
147 bool try_fwu = false; 168 bool try_fwu = false;
148 bool try_afi = false; 169 bool try_afi = false;
149 bool try_fw = false; 170 bool try_fw = false;
171 bool big_endian = false;
150 enum fwu_mode_t fwu_mode = FWU_AUTO; 172 enum fwu_mode_t fwu_mode = FWU_AUTO;
151 173
152 while(1) 174 while(1)
@@ -159,11 +181,12 @@ int main(int argc, char **argv)
159 {"fwu", no_argument, 0, 'u'}, 181 {"fwu", no_argument, 0, 'u'},
160 {"afi", no_argument, 0, 'a'}, 182 {"afi", no_argument, 0, 'a'},
161 {"fw", no_argument, 0, 'w'}, 183 {"fw", no_argument, 0, 'w'},
184 {"fw251", no_argument, 0, 'b'},
162 {"atj2127", no_argument, 0, '2'}, 185 {"atj2127", no_argument, 0, '2'},
163 {0, 0, 0, 0} 186 {0, 0, 0, 0}
164 }; 187 };
165 188
166 int c = getopt_long(argc, argv, "hdco:a2", long_options, NULL); 189 int c = getopt_long(argc, argv, "hdco:a2b", long_options, NULL);
167 if(c == -1) 190 if(c == -1)
168 break; 191 break;
169 switch(c) 192 switch(c)
@@ -192,6 +215,10 @@ int main(int argc, char **argv)
192 case 'w': 215 case 'w':
193 try_fw = true; 216 try_fw = true;
194 break; 217 break;
218 case 'b':
219 try_fw = true;
220 big_endian = true;
221 break;
195 case '2': 222 case '2':
196 fwu_mode = FWU_ATJ2127; 223 fwu_mode = FWU_ATJ2127;
197 break; 224 break;
@@ -238,7 +265,7 @@ int main(int argc, char **argv)
238 else if(try_afi || afi_check(buf, size)) 265 else if(try_afi || afi_check(buf, size))
239 ret = do_afi(buf, size); 266 ret = do_afi(buf, size);
240 else if(try_fw || fw_check(buf, size)) 267 else if(try_fw || fw_check(buf, size))
241 ret = do_fw(buf, size); 268 ret = do_fw(buf, size, big_endian);
242 else 269 else
243 { 270 {
244 cprintf(GREY, "No valid format found\n"); 271 cprintf(GREY, "No valid format found\n");
diff --git a/utils/atj2137/atjboottool/fw.c b/utils/atj2137/atjboottool/fw.c
index 07ce4e2f31..114123813b 100644
--- a/utils/atj2137/atjboottool/fw.c
+++ b/utils/atj2137/atjboottool/fw.c
@@ -38,7 +38,7 @@ struct fw_entry_t
38 uint16_t version; 38 uint16_t version;
39 uint32_t block_offset; // offset shift by 9 39 uint32_t block_offset; // offset shift by 9
40 uint32_t size; 40 uint32_t size;
41 uint32_t unk; 41 uint32_t bytes;
42 uint32_t checksum; 42 uint32_t checksum;
43} __attribute__((packed)); 43} __attribute__((packed));
44 44
@@ -78,7 +78,8 @@ struct fw_hdr_f0_t
78 uint8_t sig[FW_SIG_SIZE]; 78 uint8_t sig[FW_SIG_SIZE];
79 uint8_t res[12]; 79 uint8_t res[12];
80 uint32_t checksum; 80 uint32_t checksum;
81 uint8_t res2[492]; 81 uint8_t res2[490];
82 uint16_t header_checksum;
82 83
83 struct fw_entry_t entry[FW_ENTRIES]; 84 struct fw_entry_t entry[FW_ENTRIES];
84} __attribute__((packed)); 85} __attribute__((packed));
@@ -97,14 +98,56 @@ static void build_filename_fw(char buf[16], struct fw_entry_t *ent)
97{ 98{
98 int pos = 0; 99 int pos = 0;
99 for(int i = 0; i < 8 && ent->name[i] != ' '; i++) 100 for(int i = 0; i < 8 && ent->name[i] != ' '; i++)
100 buf[pos++] = ent->name[i]; 101 buf[pos++] = tolower(ent->name[i]);
101 buf[pos++] = '.'; 102 buf[pos++] = '.';
102 for(int i = 0; i < 3 && ent->ext[i] != ' '; i++) 103 for(int i = 0; i < 3 && ent->ext[i] != ' '; i++)
103 buf[pos++] = ent->ext[i]; 104 buf[pos++] = tolower(ent->ext[i]);
104 buf[pos] = 0; 105 buf[pos] = 0;
105} 106}
106 107
107int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb) 108static inline uint32_t u32_endian_swap(uint32_t u32)
109{
110 return ((u32 & 0xff000000u) >> 24) |
111 ((u32 & 0x00ff0000u) >> 8) |
112 ((u32 & 0x0000ff00u) << 8) |
113 ((u32 & 0x000000ffu) << 24);
114}
115
116static uint32_t big_endian_checksum(void *ptr, size_t size)
117{
118 uint32_t crc = 0;
119 uint32_t *cp = ptr;
120 for(; size >= 4; size -= 4)
121 crc += u32_endian_swap(*cp++);
122 /* FIXME all observed sizes divisible by 4, unclear how to add remainder */
123 return crc;
124}
125
126static inline uint16_t u16_endian_swap(uint16_t u16)
127{
128 return ((u16 & 0xff00u) >> 8) |
129 ((u16 & 0x00ffu) << 8);
130}
131
132static uint16_t lfi_header_checksum(void *ptr, size_t size, bool big_endian)
133{
134 uint16_t crc = 0;
135 uint16_t *cp = ptr;
136 if (big_endian)
137 {
138 for(; size >= 2; size -= 2)
139 crc += u16_endian_swap(*cp++);
140 return u16_endian_swap(crc); /* to make comparable with the stored one */
141 }
142 else
143 {
144 for(; size >= 2; size -= 2)
145 crc += *cp++;
146 return crc;
147 }
148}
149
150int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb, bool big_endian)
108{ 151{
109 struct fw_hdr_t *hdr = (void *)buf; 152 struct fw_hdr_t *hdr = (void *)buf;
110 153
@@ -165,8 +208,32 @@ int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb)
165 } 208 }
166 else 209 else
167 { 210 {
168 /* struct fw_hdr_f0_t *hdr_f0 = (void *)hdr; */ 211 struct fw_hdr_f0_t *hdr_f0 = (void *)hdr;
169 cprintf(GREEN, " Header not dumped because format is unclear.\n"); 212 uint32_t chk;
213 if (big_endian)
214 chk = u32_endian_swap(big_endian_checksum(buf + 0x200, 0x1e00));
215 else
216 chk = afi_checksum(buf + 0x200, 0x1e00);
217 cprintf_field(" Directory checksum: ", "0x%x ", hdr_f0->checksum);
218 if(chk != hdr_f0->checksum)
219 {
220 cprintf(RED, "Mismatch, 0x%x expected\n", chk);
221 return 1;
222 }
223 else
224 cprintf(RED, "Ok\n");
225
226 uint16_t header_chk = lfi_header_checksum(buf, 510, big_endian);
227 cprintf_field(" Header checksum: ", "0x%x ", hdr_f0->header_checksum);
228 if(header_chk != hdr_f0->header_checksum)
229 {
230 cprintf(RED, "Mismatch, 0x%x expected\n", header_chk);
231 return 1;
232 }
233 else
234 cprintf(RED, "Ok\n");
235
236 cprintf(GREEN, " Rest of header not dumped because format is unclear.\n");
170 } 237 }
171 238
172 cprintf(BLUE, "Entries\n"); 239 cprintf(BLUE, "Entries\n");
@@ -175,15 +242,29 @@ int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb)
175 if(hdr->entry[i].name[0] == 0) 242 if(hdr->entry[i].name[0] == 0)
176 continue; 243 continue;
177 struct fw_entry_t *entry = &hdr->entry[i]; 244 struct fw_entry_t *entry = &hdr->entry[i];
245 if (big_endian)
246 {
247 /* must be in-place for correct load checksum later */
248 entry->block_offset = u32_endian_swap(entry->block_offset);
249 entry->size = u32_endian_swap(entry->size);
250 entry->checksum = u32_endian_swap(entry->checksum);
251 }
178 char filename[16]; 252 char filename[16];
179 build_filename_fw(filename, entry); 253 build_filename_fw(filename, entry);
180 cprintf(RED, " %s\n", filename); 254 cprintf(RED, " %s\n", filename);
181 cprintf_field(" Attr: ", "%02x\n", entry->attr); 255 cprintf_field(" Attr: ", "%02x\n", entry->attr);
182 cprintf_field(" Offset: ", "0x%x\n", entry->block_offset << 9); 256 cprintf_field(" Offset: ", "0x%x\n", entry->block_offset << 9);
183 cprintf_field(" Size: ", "0x%x\n", entry->size); 257 cprintf_field(" Size: ", "0x%x\n", entry->size);
184 cprintf_field(" Unknown: ", "%x\n", entry->unk); 258 cprintf_field(" Bytes: ", "0x%x\n", entry->bytes);
185 cprintf_field(" Checksum: ", "0x%x ", entry->checksum); 259 cprintf_field(" Checksum: ", "0x%x ", entry->checksum);
186 uint32_t chk = afi_checksum(buf + (entry->block_offset << 9), entry->size); 260 if (entry->bytes == 0)
261 entry->bytes = entry->size;
262 memset(buf + (entry->block_offset << 9) + entry->bytes, 0, entry->size - entry->bytes);
263 uint32_t chk;
264 if (big_endian)
265 chk = big_endian_checksum(buf + (entry->block_offset << 9), entry->size);
266 else
267 chk = afi_checksum(buf + (entry->block_offset << 9), entry->size);
187 if(chk != entry->checksum) 268 if(chk != entry->checksum)
188 { 269 {
189 cprintf(RED, "Mismatch\n"); 270 cprintf(RED, "Mismatch\n");
@@ -191,11 +272,25 @@ int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb)
191 } 272 }
192 else 273 else
193 cprintf(RED, "Ok\n"); 274 cprintf(RED, "Ok\n");
194 int ret = unpack_cb(filename, buf + (entry->block_offset << 9), entry->size); 275 int ret = unpack_cb(filename, buf + (entry->block_offset << 9), entry->bytes);
195 if(ret != 0) 276 if(ret != 0)
196 return ret; 277 return ret;
197 } 278 }
198 279
280 if (big_endian)
281 {
282 uint32_t load_checksum = *(uint32_t *)(buf + size - 4);
283 uint32_t load_chk = big_endian_checksum(buf, size - 512);
284 cprintf_field(" Load checksum: ", "0x%x ", load_checksum);
285 if(load_chk != load_checksum)
286 {
287 cprintf(RED, "Mismatch, 0x%x expected\n", load_chk);
288 return 1;
289 }
290 else
291 cprintf(RED, "Ok\n");
292 }
293
199 return 0; 294 return 0;
200} 295}
201 296
diff --git a/utils/atj2137/atjboottool/fw.h b/utils/atj2137/atjboottool/fw.h
index 95f8087116..9047de4b6d 100644
--- a/utils/atj2137/atjboottool/fw.h
+++ b/utils/atj2137/atjboottool/fw.h
@@ -27,7 +27,7 @@
27 * its name and content. If the callback returns a nonzero value, the function will stop and return 27 * its name and content. If the callback returns a nonzero value, the function will stop and return
28 * that value. Returns 0 on success */ 28 * that value. Returns 0 on success */
29typedef int (*fw_extract_callback_t)(const char *name, uint8_t *buf, size_t size); 29typedef int (*fw_extract_callback_t)(const char *name, uint8_t *buf, size_t size);
30int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t cb); 30int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t cb, bool big_endian);
31/* Check if a file looks like an AFI file */ 31/* Check if a file looks like an AFI file */
32bool fw_check(uint8_t *buf, size_t size); 32bool fw_check(uint8_t *buf, size_t size);
33 33
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
59 uint8_t key[32]; 59 uint8_t key[32];
60} __attribute__((packed)); 60} __attribute__((packed));
61 61
62struct fwu_sector0_tail_t
63{
64 uint8_t unk_2;
65 uint32_t unk_x808;
66 uint32_t unk_8;
67 uint8_t key_B[16];
68 uint8_t guid[16];
69 uint8_t unk_190;
70 uint8_t super_secret_xor[16];
71 uint8_t timestamp[8];
72 uint8_t unk_0;
73 uint8_t guid_filler[20];
74 uint8_t unk_1;
75 uint8_t check[20];
76} __attribute__((packed));
77
78struct fwu_block_A_hdr_t
79{
80 uint16_t block_A_size;
81 uint8_t unk_0_a;
82 uint8_t unk_1_a;
83 uint8_t key_B[16];
84 uint8_t guid_filler[256];
85 uint8_t ec_sz;
86 uint8_t unk_0_b;
87 uint32_t unk_5;
88 uint32_t unk_x505;
89 uint16_t unk_1_b;
90 uint8_t timestamp[8];
91} __attribute__((packed));
92
93struct fwu_block_B_hdr_t
94{
95 uint16_t block_B_size;
96 uint8_t unk_1_a;
97 uint16_t unk_1_b;
98 uint8_t timestamp[8];
99 uint16_t guid_filler_size;
100} __attribute__((packed));
101
62struct fwu_tail_t 102struct fwu_tail_t
63{ 103{
64 uint8_t length; /* in blocks? it's always 1 */ 104 uint8_t length; /* in blocks? it's always 1 */
@@ -95,41 +135,32 @@ typedef struct ec_point_t
95 uint32_t *y; 135 uint32_t *y;
96}ec_point_t; 136}ec_point_t;
97 137
98struct block_A_info_t 138struct ec_info_t
99{ 139{
100 int nr_bits; 140 int nr_bits;
101 uint16_t field_2; 141 int point_size;
102 int nr_words;
103 int nr_dwords_x12;
104 uint32_t *ec_a; // size 142 uint32_t *ec_a; // size
105 uint32_t *ptr7; // size 143 uint32_t *ec_b; // size
106 uint32_t *field_poly; // size 144 uint32_t *field_poly; // size
107 uint32_t size; 145 uint32_t size;
108 uint32_t field_1C; 146 ec_point_t pt_G;
109 ec_point_t ptr1; 147 ec_point_t pt_kG; // calculated ECIES public key
110 uint32_t *ptr3; // size
111 uint32_t *ptr4; // size
112 int nr_words2;
113 uint32_t field_bits; 148 uint32_t field_bits;
114 int nr_dwords_x8; 149 int size_x2;
115 int nr_bytes; 150 int nr_bytes;
116 int nr_bytes2;
117 int nr_dwords_m1; 151 int nr_dwords_m1;
118 int nr_dwords_x2_m1;
119 int nr_dwords_x2; 152 int nr_dwords_x2;
153 int nr_dwords_x2_m1;
120 int nr_dwords; 154 int nr_dwords;
121 uint32_t field_54;
122 uint32_t field_58;
123}; 155};
124 156
125struct block_A_info_t g_decode_A_info; 157struct ec_info_t g_ec_info;
126uint8_t g_subblock_A[0x128]; 158struct fwu_block_A_hdr_t g_subblock_A;
127uint8_t g_key_B[20]; 159uint8_t g_key_B[20];
128uint8_t g_perm_B[258]; 160uint8_t g_rc4_S[258];
129uint8_t g_crypto_info_byte; 161uint8_t g_field_sz_byte;
130uint8_t *g_decode_buffer; 162ec_point_t g_public_key; // from block A
131uint8_t *g_decode_buffer2; 163uint32_t *g_private_key; // from block B
132void *g_decode_buffer3;
133 164
134#include "atj_tables.h" 165#include "atj_tables.h"
135#include <ctype.h> 166#include <ctype.h>
@@ -186,7 +217,7 @@ int get_version(uint8_t *buf, unsigned long size)
186 217
187static int decode_block_A(uint8_t block[1020]) 218static int decode_block_A(uint8_t block[1020])
188{ 219{
189 uint8_t *p = &g_check_block_A_table[32 * (block[998] & 0x1f)]; 220 uint8_t *p = &g_decode_A_table[32 * (block[998] & 31)];
190 uint8_t key[32]; 221 uint8_t key[32];
191 222
192 for(int i = 0; i < 20; i++) 223 for(int i = 0; i < 20; i++)
@@ -197,50 +228,53 @@ static int decode_block_A(uint8_t block[1020])
197 for(int i = 20; i < 32; i++) 228 for(int i = 20; i < 32; i++)
198 key[i] = key[i - 20]; 229 key[i] = key[i - 20];
199 230
200 for(int i = 0; i < 992; i++) 231 for(int i = 0; i < 31 * 32; i++)
201 block[i] ^= key[i % 32] ^ g_check_block_A_table[i]; 232 block[i] ^= key[i % 32] ^ g_decode_A_table[i];
202 233
234 // FIXME dereferencing block - 1 is undefined behavior in standard C
203 return check_block(block - 1, block + 1000, 1001); 235 return check_block(block - 1, block + 1000, 1001);
204} 236}
205 237
206static void compute_perm(uint8_t *keybuf, size_t size, uint8_t perm[258]) 238// https://en.wikipedia.org/wiki/RC4#Key-scheduling_algorithm_(KSA)
239static void rc4_key_schedule(uint8_t *key, size_t keylength, uint8_t S[258])
207{ 240{
208 for(int i = 0; i < 256; i++) 241 for(int i = 0; i < 256; i++)
209 perm[i] = i; 242 S[i] = i;
210 perm[256] = perm[257] = 0; 243 S[256] = S[257] = 0;
211 uint8_t idx = 0; 244 uint8_t j = 0;
212 for(int i = 0; i < 256; i++) 245 for(int i = 0; i < 256; i++)
213 { 246 {
214 uint8_t v = perm[i]; 247 j = (j + S[i] + key[i % keylength]) % 256;
215 idx = (v + keybuf[i % size] + idx) % 256; 248 uint8_t tmp = S[i];
216 perm[i] = perm[idx]; 249 S[i] = S[j];
217 perm[idx] = v; 250 S[j] = tmp;
218 } 251 }
219} 252}
220 253
221static void decode_perm(uint8_t *buf, size_t size, uint8_t perm[258]) 254// https://en.wikipedia.org/wiki/RC4#Pseudo-random_generation_algorithm_(PRGA)
255static void rc4_stream_cipher(uint8_t *buf, size_t size, uint8_t S[258])
222{ 256{
223 uint8_t idxa = perm[256]; 257 uint8_t i = S[256];
224 uint8_t idxb = perm[257]; 258 uint8_t j = S[257];
225 for(size_t i = 0; i < size; i++) 259 for(size_t k = 0; k < size; k++)
226 { 260 {
227 idxa = (idxa + 1) % 256; 261 i = (i + 1) % 256;
228 uint8_t v = perm[idxa]; 262 j = (j + S[i]) % 256;
229 idxb = (idxb + v) % 256; 263 uint8_t tmp = S[i];
230 perm[idxa] = perm[idxb]; 264 S[i] = S[j];
231 perm[idxb] = v; 265 S[j] = tmp;
232 buf[i] ^= perm[(v + perm[idxa]) % 256]; 266 buf[k] ^= S[(S[i] + S[j]) % 256];
233 } 267 }
234} 268}
235 269
236static void decode_block_with_perm(uint8_t *keybuf, int keysize, 270static void rc4_cipher_block(uint8_t *keybuf, int keysize,
237 uint8_t *buf, int bufsize, uint8_t perm[258]) 271 uint8_t *buf, int bufsize, uint8_t S[258])
238{ 272{
239 compute_perm(keybuf, keysize, perm); 273 rc4_key_schedule(keybuf, keysize, S);
240 decode_perm(buf, bufsize, perm); 274 rc4_stream_cipher(buf, bufsize, S);
241} 275}
242 276
243static void apply_perm(uint8_t *inbuf, uint8_t *outbuf, size_t size, int swap) 277static void rc4_key_swap(uint8_t *inbuf, uint8_t *outbuf, size_t size, int swap)
244{ 278{
245 memcpy(outbuf, inbuf, size); 279 memcpy(outbuf, inbuf, size);
246 int a = swap & 0xf; 280 int a = swap & 0xf;
@@ -250,16 +284,16 @@ static void apply_perm(uint8_t *inbuf, uint8_t *outbuf, size_t size, int swap)
250 outbuf[b] = v; 284 outbuf[b] = v;
251} 285}
252 286
253static void decode_block_with_swap(uint8_t keybuf[32], int swap, 287static void rc4_key_swap_and_decode(uint8_t keybuf[32], int swap,
254 uint8_t *buf, int bufsize, uint8_t perm[258]) 288 uint8_t *buf, int bufsize, uint8_t S[258])
255{ 289{
256 uint8_t keybuf_interm[32]; 290 uint8_t keybuf_interm[32];
257 291
258 apply_perm(keybuf, keybuf_interm, 32, swap); 292 rc4_key_swap(keybuf, keybuf_interm, 32, swap);
259 decode_block_with_perm(keybuf_interm, 32, buf, bufsize, perm); 293 rc4_cipher_block(keybuf_interm, 32, buf, bufsize, S);
260} 294}
261 295
262static void clear_memory(void *buf, size_t size_dwords) 296static void gf_zero(void *buf, size_t size_dwords)
263{ 297{
264 memset(buf, 0, 4 * size_dwords); 298 memset(buf, 0, 4 * size_dwords);
265} 299}
@@ -269,40 +303,35 @@ static void set_bit(int bit_pos, uint32_t *buf)
269 buf[bit_pos / 32] |= 1 << (bit_pos % 32); 303 buf[bit_pos / 32] |= 1 << (bit_pos % 32);
270} 304}
271 305
272static int fill_decode_info(uint8_t sz) 306static int fill_ec_info(uint8_t sz)
273{ 307{
274 if(sz == 2) sz = 233; 308 if(sz == 2) sz = 233;
275 else if(sz == 3) sz = 163; 309 else if(sz == 3) sz = 163;
276 else return 1; 310 else return 1;
277 311
278 g_decode_A_info.nr_bits = sz; 312 g_ec_info.nr_bits = sz;
279 g_decode_A_info.nr_bytes2 = sz / 8 + (sz % 8 != 0); 313 g_ec_info.nr_bytes = sz / 8 + (sz % 8 != 0);
280 g_decode_A_info.nr_words = 2 * g_decode_A_info.nr_bytes2; 314 g_ec_info.point_size = 2 * g_ec_info.nr_bytes;
281 g_decode_A_info.nr_bytes = sz / 8 + (sz % 8 != 0); 315 g_ec_info.nr_dwords = sz / 32 + (sz % 32 != 0);
282 g_decode_A_info.nr_words2 = 2 * g_decode_A_info.nr_bytes2; 316 g_ec_info.size = 4 * g_ec_info.nr_dwords;
283 g_decode_A_info.nr_dwords = sz / 32 + (sz % 32 != 0); 317 g_ec_info.size_x2 = 8 * g_ec_info.nr_dwords;
284 g_decode_A_info.size = 4 * g_decode_A_info.nr_dwords; 318 g_ec_info.nr_dwords_m1 = g_ec_info.nr_dwords - 1;
285 g_decode_A_info.nr_dwords_x8 = 8 * g_decode_A_info.nr_dwords; 319 g_ec_info.nr_dwords_x2 = 2 * g_ec_info.nr_dwords;
286 g_decode_A_info.nr_dwords_m1 = g_decode_A_info.nr_dwords - 1; 320 g_ec_info.nr_dwords_x2_m1 = g_ec_info.nr_dwords_x2 - 1;
287 g_decode_A_info.nr_dwords_x2 = 2 * g_decode_A_info.nr_dwords; 321 g_ec_info.pt_G.x = malloc(4 * g_ec_info.nr_dwords);
288 g_decode_A_info.nr_dwords_x2_m1 = g_decode_A_info.nr_dwords_x2 - 1; 322 g_ec_info.pt_G.y = malloc(g_ec_info.size);
289 g_decode_A_info.nr_dwords_x12 = 12 * g_decode_A_info.nr_dwords; 323 g_ec_info.pt_kG.x = malloc(g_ec_info.size);
290 g_decode_A_info.ptr1.x = malloc(4 * g_decode_A_info.nr_dwords); 324 g_ec_info.pt_kG.y = malloc(g_ec_info.size);
291 g_decode_A_info.ptr1.y = malloc(g_decode_A_info.size); 325 g_ec_info.field_poly = malloc(g_ec_info.size);
292 g_decode_A_info.ptr3 = malloc(g_decode_A_info.size); 326 g_ec_info.ec_a = malloc(g_ec_info.size);
293 g_decode_A_info.ptr4 = malloc(g_decode_A_info.size); 327 g_ec_info.ec_b = malloc(g_ec_info.size);
294 g_decode_A_info.field_poly = malloc(g_decode_A_info.size); 328
295 g_decode_A_info.ec_a = malloc(g_decode_A_info.size); 329 cprintf(BLUE, " Elliptic curve info:\n");
296 g_decode_A_info.ptr7 = malloc(g_decode_A_info.size); 330 cprintf_field(" Field Bits: ", "%d\n", g_ec_info.nr_bits);
297 331 cprintf_field(" Field Bytes: ", "%d\n", g_ec_info.nr_bytes);
298 cprintf(BLUE, " Decode Info:\n"); 332 cprintf_field(" Point Size: ", "%d\n", g_ec_info.point_size);
299 cprintf_field(" Nr Bits: ", "%d\n", g_decode_A_info.nr_bits); 333 cprintf_field(" Field DWords: ", "%d\n", g_ec_info.nr_dwords);
300 cprintf_field(" Nr Bytes: ", "%d\n", g_decode_A_info.nr_bytes); 334 cprintf_field(" Size: ", "%d\n", g_ec_info.size);
301 cprintf_field(" Nr Bytes 2: ", "%d\n", g_decode_A_info.nr_bytes2);
302 cprintf_field(" Nr Words: ", "%d\n", g_decode_A_info.nr_words);
303 cprintf_field(" Nr Words 2: ", "%d\n", g_decode_A_info.nr_words2);
304 cprintf_field(" Nr DWords: ", "%d\n", g_decode_A_info.nr_dwords);
305 cprintf_field(" Size: ", "%d\n", g_decode_A_info.size);
306 335
307 return 0; 336 return 0;
308} 337}
@@ -313,29 +342,31 @@ static int process_block_A(uint8_t block[1024])
313 int ret = decode_block_A(block + 4); 342 int ret = decode_block_A(block + 4);
314 cprintf(GREEN, " Check: "); 343 cprintf(GREEN, " Check: ");
315 check_field(ret, 0, "Pass\n", "Fail\n"); 344 check_field(ret, 0, "Pass\n", "Fail\n");
316 print_hex("BlockA", block, 1024); 345 // print_hex("BlockA", block, 1024);
317 346
318 memcpy(g_subblock_A, block, sizeof(g_subblock_A)); 347 memcpy(&g_subblock_A, block, sizeof(g_subblock_A));
319 ret = fill_decode_info(g_subblock_A[276]); 348 // assert(offsetof(struct fwu_block_A_hdr_t, ec_sz) == 276);
349 ret = fill_ec_info(g_subblock_A.ec_sz);
320 cprintf(GREEN, " Info: "); 350 cprintf(GREEN, " Info: ");
321 check_field(ret, 0, "Pass\n", "Fail\n"); 351 check_field(ret, 0, "Pass\n", "Fail\n");
322 352
323 int tmp = 2 * g_decode_A_info.nr_bytes2 + 38; 353 int tmp = 2 * g_ec_info.nr_bytes + 38;
324 int offset = 1004 - tmp + 5; 354 int offset = 1004 - tmp + 5;
325 g_crypto_info_byte = block[offset - 1]; 355 g_field_sz_byte = block[offset - 1];
326 g_decode_buffer = malloc(g_decode_A_info.size); 356 g_public_key.x = malloc(g_ec_info.size);
327 g_decode_buffer2 = malloc(g_decode_A_info.size); 357 g_public_key.y = malloc(g_ec_info.size);
328 358
329 memset(g_decode_buffer, 0, g_decode_A_info.size); 359 memset(g_public_key.x, 0, g_ec_info.size);
330 memset(g_decode_buffer2, 0, g_decode_A_info.size); 360 memset(g_public_key.y, 0, g_ec_info.size);
331 361
332 memcpy(g_decode_buffer, &block[offset], g_decode_A_info.nr_bytes2); 362 memcpy(g_public_key.x, &block[offset], g_ec_info.nr_bytes);
333 int offset2 = g_decode_A_info.nr_bytes2 + offset; 363 int offset2 = g_ec_info.nr_bytes + offset;
334 memcpy(g_decode_buffer2, &block[offset2], g_decode_A_info.nr_bytes2); 364 memcpy(g_public_key.y, &block[offset2], g_ec_info.nr_bytes);
335 365
336 366
337 cprintf_field(" Word: ", "%d ", *(uint16_t *)&g_subblock_A[286]); 367 // assert(offsetof(struct fwu_block_A_hdr_t, unk_1_b) == 286);
338 check_field(*(uint16_t *)&g_subblock_A[286], 1, "Ok\n", "Mismatch\n"); 368 cprintf_field(" Word: ", "%d ", g_subblock_A.unk_1_b);
369 check_field(g_subblock_A.unk_1_b, 1, "Ok\n", "Mismatch\n");
339 370
340 return 0; 371 return 0;
341} 372}
@@ -353,12 +384,12 @@ static void decode_key_B(uint8_t buf[20], uint8_t buf2[16], uint8_t key[20])
353static void decode_block_B(uint8_t *buf, uint8_t key[16], size_t size) 384static void decode_block_B(uint8_t *buf, uint8_t key[16], size_t size)
354{ 385{
355 decode_key_B(&buf[size], key, g_key_B); 386 decode_key_B(&buf[size], key, g_key_B);
356 decode_block_with_perm(g_key_B, 20, buf, size, g_perm_B); 387 rc4_cipher_block(g_key_B, 20, buf, size, g_rc4_S);
357} 388}
358 389
359static int find_last_bit_set(uint32_t *buf, bool a) 390static int find_last_bit_set(uint32_t *buf, bool a)
360{ 391{
361 int i = a ? g_decode_A_info.nr_dwords_m1 : g_decode_A_info.nr_dwords_x2_m1; 392 int i = a ? g_ec_info.nr_dwords_m1 : g_ec_info.nr_dwords_x2_m1;
362 393
363 while(i >= 0 && buf[i] == 0) 394 while(i >= 0 && buf[i] == 0)
364 i--; 395 i--;
@@ -370,15 +401,15 @@ static int find_last_bit_set(uint32_t *buf, bool a)
370 return -1; // unreachable 401 return -1; // unreachable
371} 402}
372 403
373static void copy_memory(uint32_t *to, uint32_t *from) 404static void gf_copy(uint32_t *to, uint32_t *from)
374{ 405{
375 for(int i = 0; i < g_decode_A_info.nr_dwords; i++) 406 for(int i = 0; i < g_ec_info.nr_dwords; i++)
376 to[i] = from[i]; 407 to[i] = from[i];
377} 408}
378 409
379static void swap_memory(uint32_t *a, uint32_t *b) 410static void gf_swap(uint32_t *a, uint32_t *b)
380{ 411{
381 for(int i = 0; i < g_decode_A_info.nr_dwords; i++) 412 for(int i = 0; i < g_ec_info.nr_dwords; i++)
382 { 413 {
383 uint32_t c = a[i]; 414 uint32_t c = a[i];
384 a[i] = b[i]; 415 a[i] = b[i];
@@ -388,11 +419,11 @@ static void swap_memory(uint32_t *a, uint32_t *b)
388 419
389static void shift_left(uint32_t *buf, int nr_bits) 420static void shift_left(uint32_t *buf, int nr_bits)
390{ 421{
391 for(int i = g_decode_A_info.nr_dwords_m1; i >= 0; i--) 422 for(int i = g_ec_info.nr_dwords_m1; i >= 0; i--)
392 buf[i + (nr_bits / 32)] = buf[i]; 423 buf[i + (nr_bits / 32)] = buf[i];
393 memset(buf, 0, 4 * (nr_bits / 32)); 424 memset(buf, 0, 4 * (nr_bits / 32));
394 425
395 size_t size = g_decode_A_info.nr_dwords + (nr_bits + 31) / 32; 426 size_t size = g_ec_info.nr_dwords + (nr_bits + 31) / 32;
396 nr_bits = nr_bits % 32; 427 nr_bits = nr_bits % 32;
397 428
398 uint32_t acc = 0; 429 uint32_t acc = 0;
@@ -407,9 +438,9 @@ static void shift_left(uint32_t *buf, int nr_bits)
407 } 438 }
408} 439}
409 440
410static void xor_big(uint32_t *res, uint32_t *a, uint32_t *b) 441static void gf_add_x2(uint32_t *res, uint32_t *a, uint32_t *b)
411{ 442{
412 for(int i = 0; i < g_decode_A_info.nr_dwords_x2; i++) 443 for(int i = 0; i < g_ec_info.nr_dwords_x2; i++)
413 res[i] = a[i] ^ b[i]; 444 res[i] = a[i] ^ b[i];
414} 445}
415 446
@@ -433,39 +464,49 @@ static void print_poly(const char *name, uint32_t *poly, int nr_dwords)
433 cprintf(OFF, "\n"); 464 cprintf(OFF, "\n");
434} 465}
435 466
436static void gf_inverse(uint32_t *res, uint32_t *val) 467/* https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Simple_algebraic_field_extensions
468 * invariant: p * s + a * t == r -> a * t == r (mod p)
469 * loop until only lowest bit set (r == 1) -> inverse in t */
470static void gf_inverse(uint32_t *newt, uint32_t *val)
437{ 471{
438 uint32_t *tmp = malloc(g_decode_A_info.nr_dwords_x8); 472 uint32_t *tmp = malloc(g_ec_info.size_x2);
439 uint32_t *copy = malloc(g_decode_A_info.nr_dwords_x8); 473 uint32_t *r = malloc(g_ec_info.size_x2);
440 uint32_t *copy_arg = malloc(g_decode_A_info.nr_dwords_x8); 474 uint32_t *newr = malloc(g_ec_info.size_x2);
441 uint32_t *tmp2 = malloc(g_decode_A_info.nr_dwords_x8); 475 uint32_t *t = malloc(g_ec_info.size_x2);
442 clear_memory(tmp, g_decode_A_info.nr_dwords_x2); 476 gf_zero(tmp, g_ec_info.nr_dwords_x2);
443 clear_memory(res, g_decode_A_info.nr_dwords); 477 /* newt := 1 */
444 *res = 1; 478 gf_zero(newt, g_ec_info.nr_dwords);
445 clear_memory(tmp2, g_decode_A_info.nr_dwords); 479 *newt = 1;
446 copy_memory(copy_arg, val); 480 /* t := 0 */
447 copy_memory(copy, (uint32_t *)g_decode_A_info.field_poly); 481 gf_zero(t, g_ec_info.nr_dwords);
448 482 /* newr := a */
449 for(int i = find_last_bit_set(copy_arg, 1); i; i = find_last_bit_set(copy_arg, 1)) 483 gf_copy(newr, val);
484 /* r := p */
485 gf_copy(r, g_ec_info.field_poly);
486
487 for(int i = find_last_bit_set(newr, 1); i; i = find_last_bit_set(newr, 1))
450 { 488 {
451 int pos = i - find_last_bit_set(copy, 1); 489 /* pos := degree(newr) - degree(r) */
490 int pos = i - find_last_bit_set(r, 1);
452 if(pos < 0) 491 if(pos < 0)
453 { 492 {
454 swap_memory(copy_arg, copy); 493 gf_swap(newr, r);
455 swap_memory(res, tmp2); 494 gf_swap(newt, t);
456 pos = -pos; 495 pos = -pos;
457 } 496 }
458 copy_memory(tmp, copy); 497 /* newr := newr - x^pos * r */
498 gf_copy(tmp, r);
459 shift_left(tmp, pos); 499 shift_left(tmp, pos);
460 xor_big(copy_arg, copy_arg, tmp); 500 gf_add_x2(newr, newr, tmp);
461 copy_memory(tmp, tmp2); 501 /* newt := newt - x^pos * t */
502 gf_copy(tmp, t);
462 shift_left(tmp, pos); 503 shift_left(tmp, pos);
463 xor_big(res, res, tmp); 504 gf_add_x2(newt, newt, tmp);
464 } 505 }
465 free(tmp); 506 free(tmp);
466 free(copy); 507 free(r);
467 free(copy_arg); 508 free(newr);
468 free(tmp2); 509 free(t);
469} 510}
470 511
471static void shift_left_one(uint32_t *a) 512static void shift_left_one(uint32_t *a)
@@ -488,15 +529,15 @@ static void shift_left_one(uint32_t *a)
488#if 1 529#if 1
489static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3) 530static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
490{ 531{
491 uint32_t *tmp2 = malloc(g_decode_A_info.nr_dwords_x8); 532 uint32_t *tmp2 = malloc(g_ec_info.size_x2);
492 clear_memory(tmp2, g_decode_A_info.nr_dwords_x2); 533 gf_zero(tmp2, g_ec_info.nr_dwords_x2);
493 copy_memory(tmp2, a3); 534 gf_copy(tmp2, a3);
494 535
495 int pos = g_decode_A_info.nr_dwords; 536 int pos = g_ec_info.nr_dwords;
496 uint32_t mask = 1; 537 uint32_t mask = 1;
497 for(int i = 0; i < 32; i++) 538 for(int i = 0; i < 32; i++)
498 { 539 {
499 for(int j = 0; j < g_decode_A_info.nr_dwords; j++) 540 for(int j = 0; j < g_ec_info.nr_dwords; j++)
500 { 541 {
501 if(a2[j] & mask) 542 if(a2[j] & mask)
502 for(int k = 0; k < pos; k++) 543 for(int k = 0; k < pos; k++)
@@ -511,8 +552,8 @@ static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
511#else 552#else
512static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3) 553static void gf_mult(uint32_t *res, uint32_t *a2, uint32_t *a3)
513{ 554{
514 for(int i = 0; i < 32 * g_decode_A_info.nr_dwords; i++) 555 for(int i = 0; i < 32 * g_ec_info.nr_dwords; i++)
515 for(int j = 0; j < 32 * g_decode_A_info.nr_dwords; j++) 556 for(int j = 0; j < 32 * g_ec_info.nr_dwords; j++)
516 { 557 {
517 int k = i + j; 558 int k = i + j;
518 uint32_t v1 = (a2[i / 32] >> (i % 32)) & 1; 559 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)
522} 563}
523#endif 564#endif
524 565
525static void gf_mod(uint32_t *inout, uint32_t *other) 566// https://en.wikipedia.org/wiki/Polynomial_long_division#Pseudocode
567static void gf_mod(uint32_t *r, uint32_t *field_poly)
526{ 568{
527 uint32_t *tmp = malloc(g_decode_A_info.nr_dwords_x8); 569 uint32_t *tmp = malloc(g_ec_info.size_x2);
528 int v4 = g_decode_A_info.field_bits; 570 int deg_d = g_ec_info.field_bits;
529 int pos = find_last_bit_set(inout, 0); 571 int deg_r = find_last_bit_set(r, 0);
530 for(int i = pos - v4; i >= 0; i = find_last_bit_set(inout, 0) - v4) 572 /* i := degree(lead(r) / lead(d)) */
573 for(int i = deg_r - deg_d; i >= 0; i = find_last_bit_set(r, 0) - deg_d)
531 { 574 {
532 clear_memory(tmp, g_decode_A_info.nr_dwords_x2); 575 /* r := r - x^i * d */
533 copy_memory(tmp, other); 576 gf_zero(tmp, g_ec_info.nr_dwords_x2);
577 gf_copy(tmp, field_poly);
534 shift_left(tmp, i); 578 shift_left(tmp, i);
535 xor_big(inout, inout, tmp); 579 gf_add_x2(r, r, tmp);
536 } 580 }
537 free(tmp); 581 free(tmp);
538} 582}
539 583
540static void gf_add(uint32_t *res, uint32_t *a, uint32_t *b) 584static void gf_add(uint32_t *res, uint32_t *a, uint32_t *b)
541{ 585{
542 for(int i = 0; i < g_decode_A_info.nr_dwords; i++) 586 for(int i = 0; i < g_ec_info.nr_dwords; i++)
543 res[i] = a[i] ^ b[i]; 587 res[i] = a[i] ^ b[i];
544} 588}
545 589
546static void print_point(const char *name, ec_point_t *ptr) 590static void print_point(const char *name, ec_point_t *ptr)
547{ 591{
548 cprintf(BLUE, "%s\n", name); 592 cprintf(BLUE, "%s\n", name);
549 print_poly(" x: ", ptr->x, g_decode_A_info.nr_dwords); 593 print_poly(" x: ", ptr->x, g_ec_info.nr_dwords);
550 print_poly(" y: ", ptr->y, g_decode_A_info.nr_dwords); 594 print_poly(" y: ", ptr->y, g_ec_info.nr_dwords);
551} 595}
552 596
553static uint32_t g_gf_one[9] = 597static uint32_t g_gf_one[9] =
@@ -557,42 +601,42 @@ static uint32_t g_gf_one[9] =
557 601
558static void ec_double(ec_point_t *point, ec_point_t *res) 602static void ec_double(ec_point_t *point, ec_point_t *res)
559{ 603{
560 uint32_t *v2 = malloc(g_decode_A_info.nr_dwords_x8); 604 uint32_t *v2 = malloc(g_ec_info.size_x2);
561 uint32_t *v3 = malloc(g_decode_A_info.nr_dwords_x8); 605 uint32_t *v3 = malloc(g_ec_info.size_x2);
562 uint32_t *v4 = malloc(g_decode_A_info.nr_dwords_x8); 606 uint32_t *v4 = malloc(g_ec_info.size_x2);
563 uint32_t *v5 = malloc(g_decode_A_info.nr_dwords_x8); 607 uint32_t *v5 = malloc(g_ec_info.size_x2);
564 uint32_t *v6 = malloc(g_decode_A_info.nr_dwords_x8); 608 uint32_t *v6 = malloc(g_ec_info.size_x2);
565 clear_memory(res->x, g_decode_A_info.nr_dwords); 609 gf_zero(res->x, g_ec_info.nr_dwords);
566 clear_memory(res->y, g_decode_A_info.nr_dwords); 610 gf_zero(res->y, g_ec_info.nr_dwords);
567 clear_memory(v3, g_decode_A_info.nr_dwords_x2); 611 gf_zero(v3, g_ec_info.nr_dwords_x2);
568 clear_memory(v6, g_decode_A_info.nr_dwords_x2); 612 gf_zero(v6, g_ec_info.nr_dwords_x2);
569 clear_memory(v4, g_decode_A_info.nr_dwords_x2); 613 gf_zero(v4, g_ec_info.nr_dwords_x2);
570 /* v4 := 1/x */ 614 /* v4 := 1/x */
571 gf_inverse(v4, point->x); 615 gf_inverse(v4, point->x);
572 clear_memory(v5, g_decode_A_info.nr_dwords_x2); 616 gf_zero(v5, g_ec_info.nr_dwords_x2);
573 /* v5 := y/x */ 617 /* v5 := y/x */
574 gf_mult(v5, v4, point->y); 618 gf_mult(v5, v4, point->y);
575 gf_mod(v5, g_decode_A_info.field_poly); 619 gf_mod(v5, g_ec_info.field_poly);
576 /* v2 := x + y/x (lambda) */ 620 /* v2 := x + y/x (lambda) */
577 gf_add(v2, point->x, v5); 621 gf_add(v2, point->x, v5);
578 /* v4 := ec_a + lambda */ 622 /* v4 := ec_a + lambda */
579 gf_add(v4, v2, g_decode_A_info.ec_a); 623 gf_add(v4, v2, g_ec_info.ec_a);
580 clear_memory(v3, g_decode_A_info.nr_dwords_x2); 624 gf_zero(v3, g_ec_info.nr_dwords_x2);
581 /* v3 := lambda^2 */ 625 /* v3 := lambda^2 */
582 gf_mult(v3, v2, v2); 626 gf_mult(v3, v2, v2);
583 gf_mod(v3, g_decode_A_info.field_poly); 627 gf_mod(v3, g_ec_info.field_poly);
584 /* x' := lambda + lambda^2 + ec_a */ 628 /* x' := lambda + lambda^2 + ec_a */
585 gf_add(res->x, v4, v3); 629 gf_add(res->x, v4, v3);
586 clear_memory(v5, g_decode_A_info.nr_dwords_x2); 630 gf_zero(v5, g_ec_info.nr_dwords_x2);
587 /* v4 := lambda + g_gf_one */ 631 /* v4 := lambda + g_gf_one */
588 gf_add(v4, v2, g_gf_one); 632 gf_add(v4, v2, g_gf_one);
589 /* v5 := (lambda + 1) * x' = lambda.x' + x' */ 633 /* v5 := (lambda + 1) * x' = lambda.x' + x' */
590 gf_mult(v5, v4, res->x); 634 gf_mult(v5, v4, res->x);
591 gf_mod(v5, g_decode_A_info.field_poly); 635 gf_mod(v5, g_ec_info.field_poly);
592 clear_memory(v6, g_decode_A_info.nr_dwords_x2); 636 gf_zero(v6, g_ec_info.nr_dwords_x2);
593 /* v6 := x1^2 */ 637 /* v6 := x1^2 */
594 gf_mult(v6, point->x, point->x); 638 gf_mult(v6, point->x, point->x);
595 gf_mod(v6, g_decode_A_info.field_poly); 639 gf_mod(v6, g_ec_info.field_poly);
596 /* y' = (lambda + g_gf_one) * x + x^2 = x^2 + lambda.x + x */ 640 /* y' = (lambda + g_gf_one) * x + x^2 = x^2 + lambda.x + x */
597 gf_add(res->y, v5, v6); 641 gf_add(res->y, v5, v6);
598 free(v2); 642 free(v2);
@@ -604,31 +648,31 @@ static void ec_double(ec_point_t *point, ec_point_t *res)
604 648
605static void ec_add(ec_point_t *a1, ec_point_t *a2, ec_point_t *res) 649static void ec_add(ec_point_t *a1, ec_point_t *a2, ec_point_t *res)
606{ 650{
607 uint32_t *v3 = malloc(g_decode_A_info.nr_dwords_x8); 651 uint32_t *v3 = malloc(g_ec_info.size_x2);
608 uint32_t *v4 = malloc(g_decode_A_info.nr_dwords_x8); 652 uint32_t *v4 = malloc(g_ec_info.size_x2);
609 uint32_t *v5 = malloc(g_decode_A_info.nr_dwords_x8); 653 uint32_t *v5 = malloc(g_ec_info.size_x2);
610 uint32_t *v6 = malloc(g_decode_A_info.nr_dwords_x8); 654 uint32_t *v6 = malloc(g_ec_info.size_x2);
611 uint32_t *v7 = malloc(g_decode_A_info.nr_dwords_x8); 655 uint32_t *v7 = malloc(g_ec_info.size_x2);
612 clear_memory(res->x, g_decode_A_info.nr_dwords); 656 gf_zero(res->x, g_ec_info.nr_dwords);
613 clear_memory(res->y, g_decode_A_info.nr_dwords); 657 gf_zero(res->y, g_ec_info.nr_dwords);
614 clear_memory(v4, g_decode_A_info.nr_dwords_x2); 658 gf_zero(v4, g_ec_info.nr_dwords_x2);
615 clear_memory(v7, g_decode_A_info.nr_dwords_x2); 659 gf_zero(v7, g_ec_info.nr_dwords_x2);
616 /* v5 = y1 + y2 */ 660 /* v5 = y1 + y2 */
617 gf_add(v5, a1->y, a2->y); 661 gf_add(v5, a1->y, a2->y);
618 /* v6 = x1 + x2 */ 662 /* v6 = x1 + x2 */
619 gf_add(v6, a1->x, a2->x); 663 gf_add(v6, a1->x, a2->x);
620 /* v7 = 1/(x1 + x2) */ 664 /* v7 = 1/(x1 + x2) */
621 gf_inverse(v7, v6); 665 gf_inverse(v7, v6);
622 clear_memory(v3, g_decode_A_info.nr_dwords_x2); 666 gf_zero(v3, g_ec_info.nr_dwords_x2);
623 /* v3 = (y1 + y2) / (x1 + x2) (lambda) */ 667 /* v3 = (y1 + y2) / (x1 + x2) (lambda) */
624 gf_mult(v3, v7, v5); 668 gf_mult(v3, v7, v5);
625 gf_mod(v3, g_decode_A_info.field_poly); 669 gf_mod(v3, g_ec_info.field_poly);
626 /* v5 = lambda + ec_a */ 670 /* v5 = lambda + ec_a */
627 gf_add(v5, v3, g_decode_A_info.ec_a); 671 gf_add(v5, v3, g_ec_info.ec_a);
628 clear_memory(v4, g_decode_A_info.nr_dwords_x2); 672 gf_zero(v4, g_ec_info.nr_dwords_x2);
629 /* v4 = lambda^2 */ 673 /* v4 = lambda^2 */
630 gf_mult(v4, v3, v3); 674 gf_mult(v4, v3, v3);
631 gf_mod(v4, g_decode_A_info.field_poly); 675 gf_mod(v4, g_ec_info.field_poly);
632 /* v7 = lambda^2 + lambda + ec_a */ 676 /* v7 = lambda^2 + lambda + ec_a */
633 gf_add(v7, v5, v4); 677 gf_add(v7, v5, v4);
634 /* x' = ec_a + x1 + x2 + lambda + lambda^2 */ 678 /* 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)
637 gf_add(v5, a1->x, res->x); 681 gf_add(v5, a1->x, res->x);
638 /* v6 = x' + y1 */ 682 /* v6 = x' + y1 */
639 gf_add(v6, res->x, a1->y); 683 gf_add(v6, res->x, a1->y);
640 clear_memory(v7, g_decode_A_info.nr_dwords_x2); 684 gf_zero(v7, g_ec_info.nr_dwords_x2);
641 /* v7 = (x1 + x').lambda */ 685 /* v7 = (x1 + x').lambda */
642 gf_mult(v7, v5, v3); 686 gf_mult(v7, v5, v3);
643 gf_mod(v7, g_decode_A_info.field_poly); 687 gf_mod(v7, g_ec_info.field_poly);
644 /* y' = (x1 + x').lambda + x' + y1 */ 688 /* y' = (x1 + x').lambda + x' + y1 */
645 gf_add(res->y, v7, v6); 689 gf_add(res->y, v7, v6);
646 free(v3); 690 free(v3);
@@ -654,17 +698,17 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
654{ 698{
655 ec_point_t res_others; 699 ec_point_t res_others;
656 700
657 res_others.x = malloc(g_decode_A_info.size); 701 res_others.x = malloc(g_ec_info.size);
658 res_others.y = malloc(g_decode_A_info.size); 702 res_others.y = malloc(g_ec_info.size);
659 clear_memory(res->x, g_decode_A_info.nr_dwords); 703 gf_zero(res->x, g_ec_info.nr_dwords);
660 clear_memory(res->y, g_decode_A_info.nr_dwords); 704 gf_zero(res->y, g_ec_info.nr_dwords);
661 clear_memory(res_others.x, g_decode_A_info.nr_dwords); 705 gf_zero(res_others.x, g_ec_info.nr_dwords);
662 clear_memory(res_others.y, g_decode_A_info.nr_dwords); 706 gf_zero(res_others.y, g_ec_info.nr_dwords);
663 int pos = find_last_bit_set(n, 1); 707 int pos = find_last_bit_set(n, 1);
664 708
665 /* res_other := point */ 709 /* res_other := point */
666 copy_memory(res_others.x, point->x); 710 gf_copy(res_others.x, point->x);
667 copy_memory(res_others.y, point->y); 711 gf_copy(res_others.y, point->y);
668 712
669 /* for all bit from SZ-1 downto 0 */ 713 /* for all bit from SZ-1 downto 0 */
670 for(int bit = (pos % 32) - 1; bit >= 0; bit--) 714 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)
672 /* res := 2 * res_other */ 716 /* res := 2 * res_other */
673 ec_double(&res_others, res); 717 ec_double(&res_others, res);
674 /* res_other := res = 2 * res_other */ 718 /* res_other := res = 2 * res_other */
675 copy_memory(res_others.x, res->x); 719 gf_copy(res_others.x, res->x);
676 copy_memory(res_others.y, res->y); 720 gf_copy(res_others.y, res->y);
677 /* if bit of n is set */ 721 /* if bit of n is set */
678 if(n[pos / 32] & (1 << bit)) 722 if(n[pos / 32] & (1 << bit))
679 { 723 {
680 /* res := res_other + point */ 724 /* res := res_other + point */
681 ec_add(&res_others, point, res); 725 ec_add(&res_others, point, res);
682 copy_memory(res_others.x, res->x); 726 gf_copy(res_others.x, res->x);
683 copy_memory(res_others.y, res->y); 727 gf_copy(res_others.y, res->y);
684 } 728 }
685 } 729 }
686 /* same but optimized */ 730 /* same but optimized */
@@ -689,18 +733,18 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
689 for(int bit = 31; bit >= 0; bit--) 733 for(int bit = 31; bit >= 0; bit--)
690 { 734 {
691 ec_double(&res_others, res); 735 ec_double(&res_others, res);
692 copy_memory(res_others.x, res->x); 736 gf_copy(res_others.x, res->x);
693 copy_memory(res_others.y, res->y); 737 gf_copy(res_others.y, res->y);
694 if(n[i] & (1 << bit)) 738 if(n[i] & (1 << bit))
695 { 739 {
696 ec_add(&res_others, point, res); 740 ec_add(&res_others, point, res);
697 copy_memory(res_others.x, res->x); 741 gf_copy(res_others.x, res->x);
698 copy_memory(res_others.y, res->y); 742 gf_copy(res_others.y, res->y);
699 } 743 }
700 } 744 }
701 } 745 }
702 copy_memory(res->x, res_others.x); 746 gf_copy(res->x, res_others.x);
703 copy_memory(res->y, res_others.y); 747 gf_copy(res->y, res_others.y);
704 free(res_others.x); 748 free(res_others.x);
705 free(res_others.y); 749 free(res_others.y);
706 return 0; 750 return 0;
@@ -709,7 +753,7 @@ static int ec_mult(uint32_t *n, ec_point_t *point, ec_point_t *res)
709static void xor_with_point(uint8_t *buf, ec_point_t *point) 753static void xor_with_point(uint8_t *buf, ec_point_t *point)
710{ 754{
711 /* 755 /*
712 int sz = g_decode_A_info.nr_bytes2 - 1; 756 int sz = g_ec_info.nr_bytes - 1;
713 if(sz <= 32) 757 if(sz <= 32)
714 { 758 {
715 for(int i = 0; i < sz; i++) 759 for(int i = 0; i < sz; i++)
@@ -723,39 +767,40 @@ static void xor_with_point(uint8_t *buf, ec_point_t *point)
723 */ 767 */
724 uint8_t *ptrA = (uint8_t *)point->x; 768 uint8_t *ptrA = (uint8_t *)point->x;
725 uint8_t *ptrB = (uint8_t *)point->y; 769 uint8_t *ptrB = (uint8_t *)point->y;
726 int sz = MIN(g_decode_A_info.nr_bytes2 - 1, 32); 770 int sz = MIN(g_ec_info.nr_bytes - 1, 32);
727 for(int i = 0; i < sz; i++) 771 for(int i = 0; i < sz; i++)
728 buf[i] ^= ptrA[i]; 772 buf[i] ^= ptrA[i];
729 for(int i = sz; i < 32; i++) 773 for(int i = sz; i < 32; i++)
730 buf[i] ^= ptrB[i - sz]; 774 buf[i] ^= ptrB[i - sz];
731} 775}
732 776
733static int crypto4(uint8_t *a1, ec_point_t *ptrs, uint32_t *a3) 777// https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme#Formal_description_of_ECIES
778static int xor_with_shared_secret(uint8_t *buf, ec_point_t *pt_rG, uint32_t *private_key)
734{ 779{
735 ec_point_t ptrs_others; 780 ec_point_t shared_secret;
736 781
737 ptrs_others.x = malloc(g_decode_A_info.size); 782 shared_secret.x = malloc(g_ec_info.size);
738 ptrs_others.y = malloc(g_decode_A_info.size); 783 shared_secret.y = malloc(g_ec_info.size);
739 clear_memory(ptrs_others.x, g_decode_A_info.nr_dwords); 784 gf_zero(shared_secret.x, g_ec_info.nr_dwords);
740 clear_memory(ptrs_others.y, g_decode_A_info.nr_dwords); 785 gf_zero(shared_secret.y, g_ec_info.nr_dwords);
741 int ret = ec_mult(a3, ptrs, &ptrs_others); 786 int ret = ec_mult(private_key, pt_rG, &shared_secret);
742 if(ret == 0) 787 if(ret == 0)
743 xor_with_point(a1, &ptrs_others); 788 xor_with_point(buf, &shared_secret);
744 free(ptrs_others.x); 789 free(shared_secret.x);
745 free(ptrs_others.y); 790 free(shared_secret.y);
746 return ret; 791 return ret;
747} 792}
748 793
749static int set_field_poly(uint32_t *field_poly, int field_sz) 794static int set_field_poly(uint32_t *field_poly, int field_sz)
750{ 795{
751 clear_memory(field_poly, g_decode_A_info.nr_dwords); 796 gf_zero(field_poly, g_ec_info.nr_dwords);
752 g_decode_A_info.field_bits = 0; 797 g_ec_info.field_bits = 0;
753 if(field_sz == 4) 798 if(field_sz == 4)
754 { 799 {
755 set_bit(0, field_poly); 800 set_bit(0, field_poly);
756 set_bit(74, field_poly); 801 set_bit(74, field_poly);
757 set_bit(233, field_poly); 802 set_bit(233, field_poly);
758 g_decode_A_info.field_bits = 233; 803 g_ec_info.field_bits = 233;
759 return 0; 804 return 0;
760 } 805 }
761 else if (field_sz == 5) 806 else if (field_sz == 5)
@@ -765,31 +810,31 @@ static int set_field_poly(uint32_t *field_poly, int field_sz)
765 set_bit(6, field_poly); 810 set_bit(6, field_poly);
766 set_bit(7, field_poly); 811 set_bit(7, field_poly);
767 set_bit(163, field_poly); 812 set_bit(163, field_poly);
768 g_decode_A_info.field_bits = 163; 813 g_ec_info.field_bits = 163;
769 return 0; 814 return 0;
770 } 815 }
771 else 816 else
772 return 1; 817 return 1;
773} 818}
774 819
775static int ec_init(ec_point_t *a1, char field_sz) 820static int ec_init(ec_point_t *ec_G, char field_sz)
776{ 821{
777 int ret = set_field_poly(g_decode_A_info.field_poly, field_sz); 822 int ret = set_field_poly(g_ec_info.field_poly, field_sz);
778 if(ret) return ret; 823 if(ret) return ret;
779 if(field_sz == 4) 824 if(field_sz == 4)
780 { 825 {
781 copy_memory(a1->x, g_crypto_table); 826 gf_copy(ec_G->x, g_sect233k1_G_x);
782 copy_memory(a1->y, g_crypto_table2); 827 gf_copy(ec_G->y, g_sect233k1_G_y);
783 copy_memory(g_decode_A_info.ec_a, g_atj_ec233_a); 828 gf_copy(g_ec_info.ec_a, g_sect233k1_a); // zero
784 copy_memory(g_decode_A_info.ptr7, g_crypto_key6); 829 gf_copy(g_ec_info.ec_b, g_sect233k1_b); // never used
785 return 0; 830 return 0;
786 } 831 }
787 else if(field_sz == 5 ) 832 else if(field_sz == 6 ) // yet to find even a single specimen
788 { 833 {
789 copy_memory(a1->x, g_crypto_key3); 834 gf_copy(ec_G->x, g_sect163r2_G_x);
790 copy_memory(a1->y, g_crypto_key4); 835 gf_copy(ec_G->y, g_sect163r2_G_y);
791 copy_memory(g_decode_A_info.ec_a, g_atj_ec163_a); 836 gf_copy(g_ec_info.ec_a, g_sect163r2_a);
792 copy_memory(g_decode_A_info.ptr7, g_crypto_key5); 837 gf_copy(g_ec_info.ec_b, g_sect163r2_b);
793 return 0; 838 return 0;
794 } 839 }
795 else 840 else
@@ -805,19 +850,21 @@ static void create_guid(void *uid, int bit_size)
805 850
806static int process_block_B(uint8_t block[512]) 851static int process_block_B(uint8_t block[512])
807{ 852{
853 struct fwu_block_B_hdr_t *p_hdr = (void *)block;
854
808 cprintf(BLUE, "Block B\n"); 855 cprintf(BLUE, "Block B\n");
809 decode_block_B(block + 3, g_subblock_A + 4, 489); 856 decode_block_B(block + 3, g_subblock_A.key_B, 492 - 3);
810 cprintf_field(" Word: ", "%d ", *(uint16_t *)(block + 3)); 857 cprintf_field(" Word: ", "%d ", p_hdr->unk_1_b);
811 check_field(*(uint16_t *)(block + 3), 1, "Ok\n", "Mismatch\n"); 858 check_field(p_hdr->unk_1_b, 1, "Ok\n", "Mismatch\n");
812 859
813 int ret = check_block(block, block + 492, 492); 860 int ret = check_block(block, block + 492, 492);
814 cprintf(GREEN, " Check: "); 861 cprintf(GREEN, " Check: ");
815 check_field(ret, 0, "Pass\n", "Fail\n"); 862 check_field(ret, 0, "Pass\n", "Fail\n");
816 863
817 g_decode_buffer3 = malloc(g_decode_A_info.size); 864 g_private_key = malloc(g_ec_info.size);
818 memset(g_decode_buffer3, 0, g_decode_A_info.size); 865 memset(g_private_key, 0, g_ec_info.size);
819 int offset = *(uint16_t *)(block + 13) + 16; 866 int offset = sizeof *p_hdr + p_hdr->guid_filler_size + 1;
820 memcpy(g_decode_buffer3, &block[offset], g_decode_A_info.nr_bytes2); 867 memcpy(g_private_key, &block[offset], g_ec_info.nr_bytes);
821 868
822 return 0; 869 return 0;
823} 870}
@@ -832,22 +879,22 @@ static int get_key_fwu_v3(size_t size, uint8_t *buf, uint8_t *blockA, uint8_t *b
832 memset(smallblock, 0, sizeof(smallblock)); 879 memset(smallblock, 0, sizeof(smallblock));
833 memset(bigblock, 0, sizeof(bigblock)); 880 memset(bigblock, 0, sizeof(bigblock));
834 881
835 uint8_t ba = buf[0x1ee] & 0xf; 882 *blockA = buf[0x1ee] & 15;
836 uint8_t bb = buf[0x1fe] & 0xf; 883 *blockB = buf[0x1fe] & 15;
884 size_t offsetA = 512 * (1 + *blockA);
885 size_t offsetB = 512 * (1 + *blockB);
837 886
838 cprintf(BLUE, "Crypto\n"); 887 cprintf(BLUE, "Crypto\n");
839 cprintf_field(" Block A: ", "%d\n", ba + 2); 888 cprintf_field(" Block A: ", "0x%zx\n", 512 + offsetA);
840 cprintf_field(" Block B: ", "%d\n", ba + bb + 5); 889 cprintf_field(" Block B: ", "0x%zx\n", 512 + offsetA + 1024 + offsetB);
841 890
842 *blockA = buf[494] & 0xf; 891 memcpy(bigblock, &buf[512 + offsetA], sizeof(bigblock));
843 *blockB = buf[510] & 0xf;
844 memcpy(bigblock, &buf[512 * (*blockA + 2)], sizeof(bigblock));
845 892
846 int ret = process_block_A(bigblock); 893 int ret = process_block_A(bigblock);
847 if(ret != 0) 894 if(ret != 0)
848 return ret; 895 return ret;
849 896
850 memcpy(smallblock, &buf[512 * (*blockA + *blockB + 5)], sizeof(smallblock)); 897 memcpy(smallblock, &buf[512 + offsetA + 1024 + offsetB], sizeof(smallblock));
851 ret = process_block_B(smallblock); 898 ret = process_block_B(smallblock);
852 if(ret != 0) 899 if(ret != 0)
853 return ret; 900 return ret;
@@ -859,64 +906,77 @@ static int get_key_fwu_v3(size_t size, uint8_t *buf, uint8_t *blockA, uint8_t *b
859 cprintf_field(" Byte: ", "%d ", crypto_hdr.unk); 906 cprintf_field(" Byte: ", "%d ", crypto_hdr.unk);
860 check_field(crypto_hdr.unk, 3, "Ok\n", "Mismatch\n"); 907 check_field(crypto_hdr.unk, 3, "Ok\n", "Mismatch\n");
861 908
862 ec_point_t ptrs; 909 size_t offset = sizeof(struct fwu_hdr_t) + sizeof(struct fwu_crypto_hdr_t);
863 ptrs.x = malloc(g_decode_A_info.size); 910 ec_point_t pt_rG;
864 ptrs.y = malloc(g_decode_A_info.size); 911 pt_rG.x = malloc(g_ec_info.size);
865 memset(ptrs.x, 0, g_decode_A_info.size); 912 pt_rG.y = malloc(g_ec_info.size);
866 memset(ptrs.y, 0, g_decode_A_info.size); 913 memset(pt_rG.x, 0, g_ec_info.size);
867 memcpy(ptrs.x, buf + 91, g_decode_A_info.nr_bytes2); 914 memset(pt_rG.y, 0, g_ec_info.size);
868 memcpy(ptrs.y, buf + 91 + g_decode_A_info.nr_bytes2, g_decode_A_info.nr_bytes2); 915 memcpy(pt_rG.x, buf + offset, g_ec_info.nr_bytes);
869 916 memcpy(pt_rG.y, buf + offset + g_ec_info.nr_bytes, g_ec_info.nr_bytes);
870 ret = ec_init(&g_decode_A_info.ptr1, g_crypto_info_byte); 917
871 cprintf(GREEN, " Crypto bits copy: "); 918 ret = ec_init(&g_ec_info.pt_G, g_field_sz_byte);
919 cprintf(GREEN, " Elliptic curve init: ");
872 check_field(ret, 0, "Pass\n", "Fail\n"); 920 check_field(ret, 0, "Pass\n", "Fail\n");
873 921
874 ret = crypto4(crypto_hdr.key, &ptrs, g_decode_buffer3); 922 ec_mult(g_private_key, &g_ec_info.pt_G, &g_ec_info.pt_kG);
875 cprintf(GREEN, " Crypto 4: "); 923 cprintf(GREEN, " Public key check: ");
924 if (memcmp(g_public_key.x, g_ec_info.pt_kG.x, g_ec_info.nr_bytes) ||
925 memcmp(g_public_key.y, g_ec_info.pt_kG.y, g_ec_info.nr_bytes))
926 {
927 cprintf(RED, "Fail\n");
928 return 1;
929 }
930 else
931 cprintf(RED, "Pass\n");
932
933 ret = xor_with_shared_secret(crypto_hdr.key, &pt_rG, g_private_key);
934 cprintf(GREEN, " ECIES decryption: ");
876 check_field(ret, 0, "Pass\n", "Fail\n"); 935 check_field(ret, 0, "Pass\n", "Fail\n");
877 936
878 memcpy(keybuf, crypto_hdr.key, 32); 937 memcpy(keybuf, crypto_hdr.key, 32);
879 int offset = g_decode_A_info.nr_words + 91; 938 offset += g_ec_info.point_size;
880 939
881 decode_block_with_swap(keybuf, 0, &buf[offset], 512 - offset, g_perm_B); 940 rc4_key_swap_and_decode(keybuf, 0, &buf[offset], 512 - offset, g_rc4_S);
882 941
883 int pos = *(uint16_t *)&buf[offset]; 942 int pos = *(uint16_t *)&buf[offset];
884 cprintf_field(" Word: ", "%d ", pos); 943 cprintf_field(" Filler size: ", "%d ", pos);
885 int tmp = g_decode_A_info.nr_words2 + 199; 944 int tmp = offset + sizeof(struct fwu_sector0_tail_t);
886 check_field(pos, 510 - tmp, "Ok\n", "Mismatch\n"); 945 check_field(pos, 510 - tmp, "Ok\n", "Mismatch\n");
887 946
888 uint8_t midbuf[108]; 947 struct fwu_sector0_tail_t tail;
889 memcpy(midbuf, &buf[pos + offset + 2], sizeof(midbuf)); 948 memcpy(&tail, &buf[offset + 2 + pos], sizeof(tail));
890 949
891 cprintf_field(" Byte: ", "%d ", midbuf[0]); 950 cprintf_field(" Byte: ", "%d ", tail.unk_2);
892 check_field(midbuf[0], 2, "Ok\n", "Invalid\n"); 951 check_field(tail.unk_2, 2, "Ok\n", "Invalid\n");
893 cprintf_field(" DWord: ", "%d ", *(uint32_t *)&midbuf[1]); 952 cprintf_field(" DWord: ", "0x%x ", tail.unk_x808);
894 check_field(*(uint32_t *)&midbuf[1], 2056, "Ok\n", "Invalid\n"); 953 check_field(tail.unk_x808, 0x808, "Ok\n", "Invalid\n");
895 cprintf_field(" DWord: ", "%d ", *(uint32_t *)&midbuf[5]); 954 cprintf_field(" DWord: ", "%d ", tail.unk_8);
896 check_field(*(uint32_t *)&midbuf[5], 8, "Ok\n", "Invalid\n"); 955 check_field(tail.unk_8, 8, "Ok\n", "Invalid\n");
897 cprintf_field(" Byte: ", "%d ", midbuf[41]); 956 cprintf_field(" Byte: ", "%d ", tail.unk_190);
898 check_field(midbuf[41], 190, "Ok\n", "Invalid\n"); 957 check_field(tail.unk_190, 190, "Ok\n", "Invalid\n");
899 958
959 /* encode super secret at random position in guid stream, never used */
900 memset(blo, 0, 512); 960 memset(blo, 0, 512);
901 create_guid(smallblock, 3808); 961 create_guid(smallblock, 476 * 8);
902 memcpy(smallblock + 476, midbuf + 42, 16); 962 memcpy(smallblock + 476, tail.super_secret_xor, 16);
903 compute_checksum(smallblock, 492, blo + 492); 963 compute_checksum(smallblock, 492, blo + 492);
904 int bsz = blo[500]; 964 int bsz = blo[500];
905 memcpy(blo, smallblock, bsz); 965 memcpy(blo, smallblock, bsz);
906 memcpy(blo + bsz, midbuf + 42, 16); 966 memcpy(blo + bsz, tail.super_secret_xor, 16);
907 memcpy(blo + bsz + 16, smallblock + bsz, 476 - bsz); 967 memcpy(blo + bsz + 16, smallblock + bsz, 476 - bsz);
968 rc4_cipher_block(blo + 492, 16, blo, 492, g_rc4_S);
908 969
909 decode_block_with_perm(blo + 492, 16, blo, 492, g_perm_B); 970 ret = check_block(buf + sizeof(struct fwu_hdr_t), tail.check, 492 - sizeof(struct fwu_hdr_t));
910 ret = check_block(buf + 42, midbuf + 88, 450); 971 cprintf(GREEN, " Check: ");
911 cprintf(GREEN, " Decode block: ");
912 check_field(ret, 0, "Pass\n", "Fail\n"); 972 check_field(ret, 0, "Pass\n", "Fail\n");
913 973
914 ret = memcmp(g_subblock_A + 4, midbuf + 9, 16); 974 ret = memcmp(g_subblock_A.key_B, tail.key_B, 16);
915 cprintf(GREEN, " Compare: "); 975 cprintf(GREEN, " Compare: ");
916 check_field(ret, 0, "Pass\n", "Fail\n"); 976 check_field(ret, 0, "Pass\n", "Fail\n");
917 977
918 /* 978 /*
919 ret = memcmp(midbuf + 25, zero, sizeof(zero)); 979 ret = memcmp(tail.guid, zero, sizeof(zero));
920 cprintf(GREEN, " Sanity: "); 980 cprintf(GREEN, " Sanity: ");
921 check_field(ret, 0, "Pass\n", "Fail\n"); 981 check_field(ret, 0, "Pass\n", "Fail\n");
922 */ 982 */
@@ -1000,15 +1060,15 @@ static int decrypt_fwu_v3(uint8_t *buf, size_t *size, uint8_t block[512], enum f
1000 /* the input buffer is reorganized based on two offsets (blockA and blockB), 1060 /* the input buffer is reorganized based on two offsets (blockA and blockB),
1001 * skip 2048 bytes of data used for crypto init */ 1061 * skip 2048 bytes of data used for crypto init */
1002 *size = hdr->fw_size; /* use firmware size, not file size */ 1062 *size = hdr->fw_size; /* use firmware size, not file size */
1003 *size -= 2048; 1063 *size -= 512 + 1024 + 512; /* sector0 + blockA + blockB */
1004 uint8_t *tmpbuf = malloc(*size); 1064 uint8_t *tmpbuf = malloc(*size);
1005 memset(tmpbuf, 0, *size); 1065 memset(tmpbuf, 0, *size);
1006 int offsetA = (blockA + 1) << 9; 1066 int offsetA = 512 * (1 + blockA);
1007 int offsetB = (blockB + 1) << 9; 1067 int offsetB = 512 * (1 + blockB);
1008 memcpy(tmpbuf, buf + 512, offsetA); 1068 memcpy(tmpbuf, buf + 512, offsetA);
1009 memcpy(tmpbuf + offsetA, buf + offsetA + 1536, offsetB); 1069 memcpy(tmpbuf + offsetA, buf + 512 + offsetA + 1024, offsetB);
1010 memcpy(tmpbuf + offsetA + offsetB, 1070 memcpy(tmpbuf + offsetA + offsetB,
1011 buf + offsetA + 1536 + offsetB + 512, *size - offsetA - offsetB); 1071 buf + 512 + offsetA + 1024 + offsetB + 512, *size - offsetA - offsetB);
1012 /* stolen from https://github.com/nfd/atj2127decrypt, I have no idea from where 1072 /* stolen from https://github.com/nfd/atj2127decrypt, I have no idea from where
1013 * he got this sequence of code. This code is really weird, I copy verbatim 1073 * he got this sequence of code. This code is really weird, I copy verbatim
1014 * his authors comment below. 1074 * 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
1048 atj2127_decrypt(buf, tmpbuf, *size, keybuf, rounds_to_perform); 1108 atj2127_decrypt(buf, tmpbuf, *size, keybuf, rounds_to_perform);
1049 else 1109 else
1050 { 1110 {
1051 compute_perm(keybuf, 32, g_perm_B); 1111 rc4_key_schedule(keybuf, 32, g_rc4_S);
1052 decode_perm(tmpbuf, *size, g_perm_B); 1112 rc4_stream_cipher(tmpbuf, *size, g_rc4_S);
1053 memcpy(buf, tmpbuf, *size); 1113 memcpy(buf, tmpbuf, *size);
1054 } 1114 }
1055 1115
@@ -1102,7 +1162,7 @@ int fwu_decrypt(uint8_t *buf, size_t *size, enum fwu_mode_t mode)
1102 cprintf_field(" Block size: ", "%d ", hdr->block_size); 1162 cprintf_field(" Block size: ", "%d ", hdr->block_size);
1103 check_field(hdr->block_size, FWU_BLOCK_SIZE, "Ok\n", "Invalid\n"); 1163 check_field(hdr->block_size, FWU_BLOCK_SIZE, "Ok\n", "Invalid\n");
1104 1164
1105 cprintf_field(" Version: ", "%x ", hdr->version); 1165 cprintf_field(" Version: ", "0x%x ", hdr->version);
1106 int ver = get_version(buf, *size); 1166 int ver = get_version(buf, *size);
1107 if(ver < 0) 1167 if(ver < 0)
1108 { 1168 {