diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-02-16 20:47:07 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-02-16 20:49:07 +0100 |
commit | b05b762ed45c6c8967fce098c598ec1a6ed7a533 (patch) | |
tree | ca704d48a3ac5acd8097d8485208f2f328766650 | |
parent | 4db4985f21bd8f36533f8e71db916e6d3d5d2249 (diff) | |
download | rockbox-b05b762ed45c6c8967fce098c598ec1a6ed7a533.tar.gz rockbox-b05b762ed45c6c8967fce098c598ec1a6ed7a533.zip |
sbtools: add brute force option for sb1 in sbtoelf
After some reverse engineering, it appears that the keys of the
sb1 format are very weak: the 128 bytes are generated from the
laserfuse words 4,5 and 6 but in a weird manner: 4 and 5 are
simply ORed and 6 is only half used (somehow), making it "only" a
48 bit word to find.
Change-Id: I40702e19d0924ef51c01894efce3cb65bd664456
-rw-r--r-- | utils/imxtools/sbtools/crypto.h | 1 | ||||
-rw-r--r-- | utils/imxtools/sbtools/misc.c | 19 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sb1.c | 103 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sb1.h | 5 | ||||
-rw-r--r-- | utils/imxtools/sbtools/sbtoelf.c | 34 | ||||
-rw-r--r-- | utils/imxtools/sbtools/xorcrypt.c | 59 |
6 files changed, 218 insertions, 3 deletions
diff --git a/utils/imxtools/sbtools/crypto.h b/utils/imxtools/sbtools/crypto.h index 599ebf4bf4..6751c2e861 100644 --- a/utils/imxtools/sbtools/crypto.h +++ b/utils/imxtools/sbtools/crypto.h | |||
@@ -125,5 +125,6 @@ void sha_1_output(struct sha_1_params_t *params, byte *out); | |||
125 | // WARNING those functions modifies the keys !! | 125 | // WARNING those functions modifies the keys !! |
126 | uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size); | 126 | uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size); |
127 | uint32_t xor_decrypt(union xorcrypt_key_t keys[2], void *data, int size); | 127 | uint32_t xor_decrypt(union xorcrypt_key_t keys[2], void *data, int size); |
128 | void xor_generate_key(uint32_t laserfuse[3], union xorcrypt_key_t key[2]); | ||
128 | 129 | ||
129 | #endif /* __CRYPTO_H__ */ | 130 | #endif /* __CRYPTO_H__ */ |
diff --git a/utils/imxtools/sbtools/misc.c b/utils/imxtools/sbtools/misc.c index dae4f92121..b9f5d21f7e 100644 --- a/utils/imxtools/sbtools/misc.c +++ b/utils/imxtools/sbtools/misc.c | |||
@@ -117,8 +117,23 @@ bool parse_key(char **pstr, struct crypto_key_t *key) | |||
117 | while(isspace(*str)) | 117 | while(isspace(*str)) |
118 | str++; | 118 | str++; |
119 | /* CRYPTO_KEY: 32 hex characters | 119 | /* CRYPTO_KEY: 32 hex characters |
120 | * CRYPTO_USBOTP: usbotp(vid:pid) where vid and pid are hex numbers */ | 120 | * CRYPTO_USBOTP: usbotp(vid:pid) where vid and pid are hex numbers |
121 | if(isxdigit(str[0])) | 121 | * CRYPTO_XOR_KEY: 256 hex characters */ |
122 | if(isxdigit(str[0]) && strlen(str) >= 256 && isxdigit(str[32])) | ||
123 | { | ||
124 | for(int j = 0; j < 128; j++) | ||
125 | { | ||
126 | byte a, b; | ||
127 | if(convxdigit(str[2 * j], &a) || convxdigit(str[2 * j + 1], &b)) | ||
128 | return false; | ||
129 | key->u.xor_key[j / 64].key[j % 64] = (a << 4) | b; | ||
130 | } | ||
131 | /* skip key */ | ||
132 | *pstr = str + 256; | ||
133 | key->method = CRYPTO_XOR_KEY; | ||
134 | return true; | ||
135 | } | ||
136 | else if(isxdigit(str[0])) | ||
122 | { | 137 | { |
123 | if(strlen(str) < 32) | 138 | if(strlen(str) < 32) |
124 | return false; | 139 | return false; |
diff --git a/utils/imxtools/sbtools/sb1.c b/utils/imxtools/sbtools/sb1.c index e4eb470e99..deb09a51e1 100644 --- a/utils/imxtools/sbtools/sb1.c +++ b/utils/imxtools/sbtools/sb1.c | |||
@@ -252,6 +252,109 @@ static const char *sb1_datatype_name(int cmd) | |||
252 | } | 252 | } |
253 | } | 253 | } |
254 | 254 | ||
255 | bool sb1_is_key_valid_fast(void *buffer, size_t size, union xorcrypt_key_t _key[2]) | ||
256 | { | ||
257 | struct sb1_header_t *header = (struct sb1_header_t *)buffer; | ||
258 | |||
259 | union xorcrypt_key_t key[2]; | ||
260 | |||
261 | uint8_t sector[SECTOR_SIZE]; | ||
262 | /* copy key and data because it's modified by the crypto code */ | ||
263 | memcpy(key, _key, sizeof(key)); | ||
264 | memcpy(sector, header + 1, SECTOR_SIZE - header->header_size); | ||
265 | /* try to decrypt the first sector */ | ||
266 | uint32_t mark = xor_decrypt(key, sector, SECTOR_SIZE - 4 - header->header_size); | ||
267 | /* copy key again it's modified by the crypto code */ | ||
268 | return mark == *(uint32_t *)§or[SECTOR_SIZE - 4 - header->header_size]; | ||
269 | } | ||
270 | |||
271 | bool sb1_brute_force(const char *filename, void *u, sb1_color_printf cprintf, | ||
272 | enum sb1_error_t *err, struct crypto_key_t *key) | ||
273 | { | ||
274 | #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__) | ||
275 | uint8_t sector[SECTOR_SIZE]; | ||
276 | FILE *f = fopen(filename, "rb"); | ||
277 | if(f == NULL) | ||
278 | { | ||
279 | printf("Cannot open file '%s' for reading: %m\n", filename); | ||
280 | *err = SB1_OPEN_ERROR; | ||
281 | return false; | ||
282 | } | ||
283 | if(fread(sector, sizeof(sector), 1, f) != 1) | ||
284 | { | ||
285 | printf("Cannot read file '%s': %m\n", filename); | ||
286 | *err = SB1_READ_ERROR; | ||
287 | fclose(f); | ||
288 | return false; | ||
289 | } | ||
290 | fclose(f); | ||
291 | |||
292 | printf(BLUE, "Brute forcing key...\n"); | ||
293 | time_t start_time = time(NULL); | ||
294 | uint32_t laserfuse[3] = {0, 0, 0}; | ||
295 | unsigned last_print = 0; | ||
296 | do | ||
297 | { | ||
298 | for(int i = 0; i < 0x10000; i++) | ||
299 | { | ||
300 | laserfuse[2] = (i & 0xff00) << 8 | (i & 0xff); | ||
301 | xor_generate_key(laserfuse, key->u.xor_key); | ||
302 | if(g_debug) | ||
303 | { | ||
304 | printf(GREEN, "Trying key"); | ||
305 | printf(GREEN, "["); | ||
306 | printf(RED, "%08x", laserfuse[0]); | ||
307 | printf(GREEN, ","); | ||
308 | printf(RED, "%08x", laserfuse[1]); | ||
309 | printf(GREEN, ","); | ||
310 | printf(RED, "%08x", laserfuse[2]); | ||
311 | printf(GREEN, "]:"); | ||
312 | for(int j = 0; j < 32; j++) | ||
313 | printf(YELLOW, " %08x", key->u.xor_key[j / 16].k[j % 16]); | ||
314 | } | ||
315 | if(sb1_is_key_valid_fast(sector, SECTOR_SIZE, key->u.xor_key)) | ||
316 | { | ||
317 | if(g_debug) | ||
318 | printf(RED, " Ok\n"); | ||
319 | return true; | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | if(g_debug) | ||
324 | printf(RED, " No\n"); | ||
325 | } | ||
326 | } | ||
327 | laserfuse[0]++; | ||
328 | |||
329 | if(laserfuse[0] / 1000 != last_print) | ||
330 | { | ||
331 | time_t cur_time = time(NULL); | ||
332 | float key_per_sec = laserfuse[0] / (float)(cur_time - start_time); | ||
333 | float tot = 0x1000000LL / key_per_sec; | ||
334 | time_t eta_time = start_time + tot; | ||
335 | |||
336 | printf(YELLOW, "%llu", laserfuse[0] * 0x10000LL); | ||
337 | printf(GREEN, " out of "); | ||
338 | printf(BLUE, "%llu", 0x1000000LL * 0x10000LL); | ||
339 | printf(GREEN, " tested ("); | ||
340 | printf(RED, "%f%%", laserfuse[0] / (float)0x1000000LL * 100.0); | ||
341 | printf(GREEN, "), "); | ||
342 | printf(YELLOW, "%d", cur_time - start_time); | ||
343 | printf(GREEN, " seconds elapsed, "); | ||
344 | printf(BLUE, "%d", eta_time - cur_time); | ||
345 | printf(GREEN, " seconds remaining, ["); | ||
346 | printf(RED, "%f", key_per_sec); | ||
347 | printf(GREEN, " keys/s], ETA "); | ||
348 | printf(YELLOW, "%s", ctime(&eta_time)); | ||
349 | last_print = laserfuse[0] / 1000; | ||
350 | } | ||
351 | }while(laserfuse[0] != 0); | ||
352 | |||
353 | *err = SB1_NO_VALID_KEY; | ||
354 | return false; | ||
355 | #undef printf | ||
356 | } | ||
357 | |||
255 | struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, | 358 | struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, |
256 | sb1_color_printf cprintf, enum sb1_error_t *err) | 359 | sb1_color_printf cprintf, enum sb1_error_t *err) |
257 | { | 360 | { |
diff --git a/utils/imxtools/sbtools/sb1.h b/utils/imxtools/sbtools/sb1.h index 1ee28978e1..2adfc6a26c 100644 --- a/utils/imxtools/sbtools/sb1.h +++ b/utils/imxtools/sbtools/sb1.h | |||
@@ -154,6 +154,11 @@ struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t | |||
154 | struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u, | 154 | struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u, |
155 | sb1_color_printf printf, enum sb1_error_t *err); | 155 | sb1_color_printf printf, enum sb1_error_t *err); |
156 | 156 | ||
157 | /* do as little checks as possible, make sure the image is valid (advance use only) */ | ||
158 | bool sb1_is_key_valid_fast(void *buffer, size_t size, union xorcrypt_key_t key[2]); | ||
159 | bool sb1_brute_force(const char *filename, void *u, sb1_color_printf printf, | ||
160 | enum sb1_error_t *err, struct crypto_key_t *key); | ||
161 | |||
157 | void sb1_get_default_key(struct crypto_key_t *key); | 162 | void sb1_get_default_key(struct crypto_key_t *key); |
158 | 163 | ||
159 | void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf); | 164 | void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf); |
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c index 540d55acc1..e68f5e6e06 100644 --- a/utils/imxtools/sbtools/sbtoelf.c +++ b/utils/imxtools/sbtools/sbtoelf.c | |||
@@ -231,6 +231,7 @@ static void usage(void) | |||
231 | printf(" -2/--v2\tForce to read file as a version 2 file\n"); | 231 | printf(" -2/--v2\tForce to read file as a version 2 file\n"); |
232 | printf(" -s/--no-simpl\tPrevent elf files from being simplified*\n"); | 232 | printf(" -s/--no-simpl\tPrevent elf files from being simplified*\n"); |
233 | printf(" -x\t\tUse default sb1 key\n"); | 233 | printf(" -x\t\tUse default sb1 key\n"); |
234 | printf(" -b\tBrute force key\n"); | ||
234 | printf("Options marked with a * are for debug purpose only\n"); | 235 | printf("Options marked with a * are for debug purpose only\n"); |
235 | exit(1); | 236 | exit(1); |
236 | } | 237 | } |
@@ -308,6 +309,7 @@ int main(int argc, char **argv) | |||
308 | const char *loopback = NULL; | 309 | const char *loopback = NULL; |
309 | bool force_sb1 = false; | 310 | bool force_sb1 = false; |
310 | bool force_sb2 = false; | 311 | bool force_sb2 = false; |
312 | bool brute_force = false; | ||
311 | 313 | ||
312 | while(1) | 314 | while(1) |
313 | { | 315 | { |
@@ -325,7 +327,7 @@ int main(int argc, char **argv) | |||
325 | {0, 0, 0, 0} | 327 | {0, 0, 0, 0} |
326 | }; | 328 | }; |
327 | 329 | ||
328 | int c = getopt_long(argc, argv, "?do:k:zra:nl:f12xs", long_options, NULL); | 330 | int c = getopt_long(argc, argv, "?do:k:zra:nl:f12xsb", long_options, NULL); |
329 | if(c == -1) | 331 | if(c == -1) |
330 | break; | 332 | break; |
331 | switch(c) | 333 | switch(c) |
@@ -391,6 +393,9 @@ int main(int argc, char **argv) | |||
391 | case 's': | 393 | case 's': |
392 | g_elf_simplify = false; | 394 | g_elf_simplify = false; |
393 | break; | 395 | break; |
396 | case 'b': | ||
397 | brute_force = true; | ||
398 | break; | ||
394 | default: | 399 | default: |
395 | abort(); | 400 | abort(); |
396 | } | 401 | } |
@@ -442,6 +447,33 @@ int main(int argc, char **argv) | |||
442 | } | 447 | } |
443 | else if(force_sb1 || ver == SB_VERSION_1) | 448 | else if(force_sb1 || ver == SB_VERSION_1) |
444 | { | 449 | { |
450 | if(brute_force) | ||
451 | { | ||
452 | struct crypto_key_t key; | ||
453 | enum sb1_error_t err; | ||
454 | if(!sb1_brute_force(sb_filename, NULL, sb_printf, &err, &key)) | ||
455 | { | ||
456 | color(OFF); | ||
457 | printf("Brute force failed: %d\n", err); | ||
458 | return 1; | ||
459 | } | ||
460 | color(RED); | ||
461 | printf("Key found:"); | ||
462 | color(YELLOW); | ||
463 | for(int i = 0; i < 32; i++) | ||
464 | printf(" %08x", key.u.xor_key[i / 16].k[i % 16]); | ||
465 | color(OFF); | ||
466 | printf("\n"); | ||
467 | color(RED); | ||
468 | printf("Key: "); | ||
469 | color(YELLOW); | ||
470 | for(int i = 0; i < 128; i++) | ||
471 | printf("%02x", key.u.xor_key[i / 64].key[i % 64]); | ||
472 | color(OFF); | ||
473 | printf("\n"); | ||
474 | add_keys(&key, 1); | ||
475 | } | ||
476 | |||
445 | enum sb1_error_t err; | 477 | enum sb1_error_t err; |
446 | struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err); | 478 | struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err); |
447 | if(file == NULL) | 479 | if(file == NULL) |
diff --git a/utils/imxtools/sbtools/xorcrypt.c b/utils/imxtools/sbtools/xorcrypt.c index 5ecf9208d6..32f2b6b875 100644 --- a/utils/imxtools/sbtools/xorcrypt.c +++ b/utils/imxtools/sbtools/xorcrypt.c | |||
@@ -22,6 +22,42 @@ | |||
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #include "misc.h" | 23 | #include "misc.h" |
24 | 24 | ||
25 | static uint32_t g_ROM_Key_Table[256] = | ||
26 | { | ||
27 | 0x6B8B4567,0x327B23C6,0x643C9869,0x66334873,0x74B0DC51,0x19495CFF,0x2AE8944A, | ||
28 | 0x625558EC,0x238E1F29,0x46E87CCD,0x3D1B58BA,0x507ED7AB,0x2EB141F2,0x41B71EFB,0x79E2A9E3,0x7545E146, | ||
29 | 0x515F007C,0x5BD062C2,0x12200854,0x4DB127F8,0x216231B,0x1F16E9E8,0x1190CDE7, | ||
30 | 0x66EF438D,0x140E0F76,0x3352255A,0x109CF92E,0xDED7263,0x7FDCC233,0x1BEFD79F,0x41A7C4C9,0x6B68079A, | ||
31 | 0x4E6AFB66,0x25E45D32,0x519B500D,0x431BD7B7,0x3F2DBA31,0x7C83E458,0x257130A3, | ||
32 | 0x62BBD95A,0x436C6125,0x628C895D,0x333AB105,0x721DA317,0x2443A858,0x2D1D5AE9,0x6763845E,0x75A2A8D4, | ||
33 | 0x8EDBDAB,0x79838CB2,0x4353D0CD,0xB03E0C6,0x189A769B,0x54E49EB4,0x71F32454, | ||
34 | 0x2CA88611,0x836C40E,0x2901D82,0x3A95F874,0x8138641,0x1E7FF521,0x7C3DBD3D,0x737B8DDC,0x6CEAF087, | ||
35 | 0x22221A70,0x4516DDE9,0x3006C83E,0x614FD4A1,0x419AC241,0x5577F8E1,0x440BADFC, | ||
36 | 0x5072367,0x3804823E,0x77465F01,0x7724C67E,0x5C482A97,0x2463B9EA,0x5E884ADC,0x51EAD36B,0x2D517796, | ||
37 | 0x580BD78F,0x153EA438,0x3855585C,0x70A64E2A,0x6A2342EC,0x2A487CB0,0x1D4ED43B, | ||
38 | 0x725A06FB,0x2CD89A32,0x57E4CCAF,0x7A6D8D3C,0x4B588F54,0x542289EC,0x6DE91B18,0x38437FDB,0x7644A45C, | ||
39 | 0x32FFF902,0x684A481A,0x579478FE,0x749ABB43,0x3DC240FB,0x1BA026FA,0x79A1DEAA, | ||
40 | 0x75C6C33A,0x12E685FB,0x70C6A529,0x520EEDD1,0x374A3FE6,0x4F4EF005,0x23F9C13C,0x649BB77C,0x275AC794, | ||
41 | 0x39386575,0x1CF10FD8,0x180115BE,0x235BA861,0x47398C89,0x354FE9F9,0x15B5AF5C, | ||
42 | 0x741226BB,0xD34B6A8,0x10233C99,0x3F6AB60F,0x61574095,0x7E0C57B1,0x77AE35EB,0x579BE4F1,0x310C50B3, | ||
43 | 0x5FF87E05,0x2F305DEF,0x25A70BF7,0x1DBABF00,0x4AD084E9,0x1F48EAA1,0x1381823A, | ||
44 | 0x5DB70AE5,0x100F8FCA,0x6590700B,0x15014ACB,0x5F5E7FD0,0x98A3148,0x799D0247,0x6B94764,0x42C296BD, | ||
45 | 0x168E121F,0x1EBA5D23,0x661E3F1E,0x5DC79EA8,0x540A471C,0x7BD3EE7B,0x51D9C564, | ||
46 | 0x613EFDC5,0xBF72B14,0x11447B73,0x42963E5A,0xA0382C5,0x8F2B15E,0x1A32234B,0x3B0FD379,0x68EB2F63, | ||
47 | 0x4962813B,0x60B6DF70,0x6A5EE64,0x14330624,0x7FFFCA11,0x1A27709E,0x71EA1109, | ||
48 | 0x100F59DC,0x7FB7E0AA,0x6EB5BD4,0x6F6DD9AC,0x94211F2,0x885E1B,0x76272110,0x4C04A8AF,0x1716703B, | ||
49 | 0x14E17E33,0x3222E7CD,0x74DE0EE3,0x68EBC550,0x2DF6D648,0x46B7D447,0x4A2AC315, | ||
50 | 0x39EE015C,0x57FC4FBB,0xCC1016F,0x43F18422,0x60EF0119,0x26F324BA,0x7F01579B,0x49DA307D,0x7055A5F5, | ||
51 | 0x5FB8370B,0x50801EE1,0x488AC1A,0x5FB8011C,0x6AA78F7F,0x7672BD23,0x6FC75AF8, | ||
52 | 0x6A5F7029,0x7D5E18F8,0x5F3534A4,0x73A1821B,0x7DE67713,0x555C55B5,0x3FA62ACA,0x14FCE74E,0x6A3DD3E8, | ||
53 | 0x71C91298,0x9DAF632,0x53299938,0x1FBFE8E0,0x5092CA79,0x1D545C4D,0x59ADEA3D, | ||
54 | 0x288F1A34,0x2A155DBC,0x1D9F6E5F,0x97E1B4E,0x51088277,0x1CA0C5FA,0x53584BCB,0x415E286C,0x7C58FD05, | ||
55 | 0x23D86AAC,0x45E6D486,0x5C10FE21,0xE7FFA2B,0x3C5991AA,0x4BD8591A,0x78DF6A55, | ||
56 | 0x39B7AAA2,0x2B0D8DBE,0x6C80EC70,0x379E21B5,0x69E373,0x2C27173B,0x4C9B0904,0x6AA7B75C,0x1DF029D3, | ||
57 | 0x5675FF36,0x3DD15094,0x3DB012B3,0x2708C9AF,0x5B25ACE2,0x175DFCF0,0x4F97E3E4, | ||
58 | 0x53B0A9E,0x34FD6B4F,0x5915FF32,0x56438D15,0x519E3149,0x2C6E4AFD,0x17A1B582,0x4DF72E4E,0x5046B5A9 | ||
59 | }; | ||
60 | |||
25 | static uint32_t do_round(union xorcrypt_key_t *key) | 61 | static uint32_t do_round(union xorcrypt_key_t *key) |
26 | { | 62 | { |
27 | uint32_t k7 = key->k[7]; | 63 | uint32_t k7 = key->k[7]; |
@@ -97,6 +133,29 @@ static void test_round(union xorcrypt_key_t keys[2]) | |||
97 | } | 133 | } |
98 | } | 134 | } |
99 | 135 | ||
136 | void xor_generate_key(uint32_t laserfuse[3], union xorcrypt_key_t key[2]) | ||
137 | { | ||
138 | uint16_t bitmask = 0x36c9; | ||
139 | uint8_t magic = (laserfuse[2] >> 24 | laserfuse[2] >> 16) & 0xff; | ||
140 | uint32_t magic2 = laserfuse[0] | laserfuse[1]; | ||
141 | uint8_t magic3 = (laserfuse[2] >> 8 | laserfuse[2] >> 0) & 0xff; | ||
142 | |||
143 | for(int i = 0; i < 16; i++, bitmask >>= 1, magic++) | ||
144 | key[0].k[i] = (bitmask & 1) ? 0 : g_ROM_Key_Table[magic]; | ||
145 | bitmask = 0x36c9; | ||
146 | for(int i = 0; i < 16; i++, bitmask >>= 1, magic++) | ||
147 | key[1].k[i] = (bitmask & 1) ? 0 : g_ROM_Key_Table[magic]; | ||
148 | key[0].k[0] ^= magic2; | ||
149 | key[1].k[0] ^= magic2; | ||
150 | |||
151 | #if 1 | ||
152 | for(int i = 0; i < magic3 + 57; i++) | ||
153 | do_round(&key[0]); | ||
154 | for(int i = 0; i < magic3 + 57; i++) | ||
155 | do_round(&key[1]); | ||
156 | #endif | ||
157 | } | ||
158 | |||
100 | uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *_data, int size) | 159 | uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *_data, int size) |
101 | { | 160 | { |
102 | if(size % 4) | 161 | if(size % 4) |