Combine the Vorbis, WMA and AAC IMDCT functions and put them into the codeclib. ...
[kugel-rb.git] / tools / mkzenboot.c
blob494838833ae0af977b37f5c436a30a49db3fd09f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * Based on zenutils by Rasmus Ry <rasmus.ry{at}gmail.com>
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdbool.h>
27 #include <inttypes.h>
28 #include <zlib.h>
29 #include "hmac-sha1.h"
31 static int filesize(FILE* fd)
33 int tmp, tmp2 = ftell(fd);
34 fseek(fd, 0, SEEK_END);
35 tmp = ftell(fd);
36 fseek(fd, tmp2, SEEK_SET);
37 return tmp;
40 static unsigned int le2int(unsigned char* buf)
42 return ((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]);
45 static void int2le(unsigned int val, unsigned char* addr)
47 addr[0] = val & 0xFF;
48 addr[1] = (val >> 8) & 0xff;
49 addr[2] = (val >> 16) & 0xff;
50 addr[3] = (val >> 24) & 0xff;
53 static const char* find_firmware_key(const unsigned char* buffer, size_t len)
55 char szkey1[] = "34d1";
56 size_t cchkey1 = strlen(szkey1);
57 char szkey2[] = "TbnCboEbn";
58 size_t cchkey2 = strlen(szkey2);
59 uint32_t i;
60 for (i = 0; i < (uint32_t)len; i++)
62 if (len >= cchkey1)
64 if (!strncmp((char*)&buffer[i], szkey1, cchkey1))
65 return (const char*)&buffer[i];
67 if (len >= cchkey2)
69 if (!strncmp((char*)&buffer[i], szkey2, cchkey2))
70 return (const char*)&buffer[i];
73 return NULL;
76 static uint32_t find_firmware_offset(unsigned char* buffer, size_t len)
78 uint32_t i;
79 for (i = 0; i < (uint32_t)len; i += 0x10)
81 if (buffer[i + sizeof(uint32_t)] != 0
82 && buffer[i + sizeof(uint32_t) + 1] != 0
83 && buffer[i + sizeof(uint32_t) + 2] != 0
84 && buffer[i + sizeof(uint32_t) + 3] != 0)
86 return i;
88 if(i > 0xFF) /* Arbitrary guess */
89 return 0;
91 return 0;
94 static bool crypt_firmware(const char* key, unsigned char* buffer, size_t len)
96 char key_cpy[255];
97 unsigned int i;
98 unsigned int tmp = 0;
99 int key_length = strlen(key);
101 strcpy(key_cpy, key);
102 for(i=0; i < strlen(key); i++)
103 key_cpy[i] = key[i] - 1;
105 for(i=0; i < len; i++)
107 buffer[i] ^= key_cpy[tmp] | 0x80;
108 tmp = (tmp + 1) % key_length;
111 return true;
114 static bool inflate_to_buffer(const unsigned char *buffer, size_t len, unsigned char* out_buffer, size_t out_len, char** err_msg)
116 /* Initialize Zlib */
117 z_stream d_stream;
118 int ret;
120 d_stream.zalloc = Z_NULL;
121 d_stream.zfree = Z_NULL;
122 d_stream.opaque = Z_NULL;
124 d_stream.next_in = (unsigned char*)buffer;
125 d_stream.avail_in = len;
127 ret = inflateInit(&d_stream);
128 if (ret != Z_OK)
130 *err_msg = d_stream.msg;
131 return false;
134 d_stream.next_out = out_buffer;
135 d_stream.avail_out = out_len;
137 ret = inflate(&d_stream, Z_SYNC_FLUSH);
138 if(ret < 0)
140 *err_msg = d_stream.msg;
141 return false;
143 else
144 inflateEnd(&d_stream);
146 return true;
149 #define CODE_MASK 0xC0
150 #define ARGS_MASK 0x3F
152 #define REPEAT_CODE 0x00
153 #define BLOCK_CODE 0x40
154 #define LONG_RUN_CODE 0x80
155 #define SHORT_RUN_CODE 0xC0
157 #define BLOCK_ARGS 0x1F
158 #define BLOCK_MODE 0x20
161 static void decode_run(unsigned char* dst, uint16_t len, unsigned char val,
162 int* dstidx)
164 memset(dst + *dstidx, val, len);
165 *dstidx += len;
168 static void decode_pattern(unsigned char* src, unsigned char* dst,
169 uint16_t len, int* srcidx, int* dstidx,
170 bool bdecode, int npasses)
172 int i, j;
173 for (i = 0; i < npasses; i++)
175 if (bdecode)
177 for (j = 0; j < len; j++)
179 uint16_t c, d;
180 c = src[*srcidx + j];
181 d = (c >> 5) & 7;
182 c = (c << 3) & 0xF8;
183 src[*srcidx + j] = (unsigned char)(c | d);
185 bdecode = false;
187 memcpy(dst + *dstidx, src + *srcidx, len);
188 *dstidx += len;
190 *srcidx += len;
193 static int cenc_decode(unsigned char* src, int srclen, unsigned char* dst, int dstlen)
195 int i = 0, j = 0;
198 uint16_t c, d, e;
199 c = src[i++];
200 switch (c & CODE_MASK)
202 case REPEAT_CODE: /* 2 unsigned chars */
203 d = src[i++];
204 d = d + 2;
206 e = (c & ARGS_MASK) + 2;
208 decode_pattern(src, dst, e, &i, &j, false, d);
209 break;
211 case BLOCK_CODE: /* 1/2/3 unsigned chars */
212 d = c & BLOCK_ARGS;
213 if (!(c & BLOCK_MODE))
215 e = src[i++];
216 e = (d << 8) + (e + 0x21);
218 d = (uint16_t)(i ^ j);
220 else
222 e = d + 1;
224 d = (uint16_t)(i ^ j);
226 if (d & 1)
228 i++;
231 decode_pattern(src, dst, e, &i, &j, true, 1);
232 break;
234 case LONG_RUN_CODE: /* 3 unsigned chars */
235 d = src[i++];
236 e = ((c & ARGS_MASK) << 8) + (d + 0x42);
238 d = src[i++];
239 d = ((d & 7) << 5) | ((d >> 3) & 0x1F);
241 decode_run(dst, e, (unsigned char)(d), &j);
242 break;
244 case SHORT_RUN_CODE: /* 2 unsigned chars */
245 d = src[i++];
246 d = ((d & 3) << 6) | ((d >> 2) & 0x3F);
248 e = (c & ARGS_MASK) + 2;
250 decode_run(dst, e, (unsigned char)(d), &j);
251 break;
253 } while (i < srclen && j < dstlen);
255 return j;
259 * Copyright (c) 1999, 2000, 2002 Virtual Unlimited B.V.
261 * This library is free software; you can redistribute it and/or
262 * modify it under the terms of the GNU Lesser General Public
263 * License as published by the Free Software Foundation; either
264 * version 2.1 of the License, or (at your option) any later version.
266 * This library is distributed in the hope that it will be useful,
267 * but WITHOUT ANY WARRANTY; without even the implied warranty of
268 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
269 * Lesser General Public License for more details.
271 * You should have received a copy of the GNU Lesser General Public
272 * License along with this library; if not, write to the Free Software
273 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
277 #define BLOWFISHROUNDS 16
278 #define BLOWFISHPSIZE (BLOWFISHROUNDS+2)
279 #define WORDS_BIGENDIAN 0
281 struct blowfishParam
283 uint32_t p[BLOWFISHPSIZE];
284 uint32_t s[1024];
285 uint32_t fdback[2];
288 typedef enum
290 NOCRYPT,
291 ENCRYPT,
292 DECRYPT
293 } cipherOperation;
295 static inline uint32_t swapu32(uint32_t n)
297 return ( ((n & 0xffU) << 24) |
298 ((n & 0xff00U) << 8) |
299 ((n & 0xff0000U) >> 8) |
300 ((n & 0xff000000U) >> 24) );
303 static uint32_t _bf_p[BLOWFISHPSIZE] = {
304 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
305 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
306 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
307 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
308 0x9216d5d9, 0x8979fb1b
311 static uint32_t _bf_s[1024] = {
312 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
313 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
314 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
315 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
316 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
317 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
318 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
319 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
320 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
321 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
322 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
323 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
324 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
325 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
326 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
327 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
328 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
329 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
330 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
331 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
332 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
333 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
334 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
335 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
336 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
337 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
338 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
339 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
340 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
341 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
342 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
343 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
344 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
345 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
346 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
347 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
348 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
349 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
350 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
351 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
352 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
353 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
354 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
355 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
356 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
357 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
358 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
359 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
360 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
361 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
362 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
363 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
364 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
365 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
366 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
367 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
368 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
369 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
370 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
371 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
372 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
373 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
374 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
375 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
376 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
377 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
378 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
379 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
380 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
381 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
382 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
383 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
384 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
385 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
386 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
387 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
388 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
389 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
390 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
391 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
392 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
393 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
394 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
395 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
396 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
397 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
398 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
399 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
400 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
401 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
402 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
403 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
404 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
405 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
406 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
407 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
408 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
409 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
410 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
411 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
412 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
413 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
414 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
415 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
416 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
417 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
418 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
419 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
420 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
421 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
422 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
423 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
424 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
425 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
426 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
427 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
428 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
429 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
430 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
431 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
432 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
433 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
434 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
435 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
436 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
437 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
438 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
439 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
440 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
441 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
442 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
443 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
444 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
445 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
446 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
447 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
448 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
449 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
450 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
451 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
452 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
453 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
454 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
455 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
456 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
457 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
458 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
459 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
460 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
461 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
462 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
463 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
464 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
465 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
466 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
467 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
468 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
469 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
470 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
471 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
472 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
473 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
474 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
475 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
476 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
477 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
478 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
479 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
480 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
481 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
482 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
483 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
484 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
485 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
486 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
487 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
488 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
489 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
490 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
491 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
492 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
493 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
494 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
495 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
496 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
497 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
498 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
499 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
500 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
501 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
502 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
503 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
504 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
505 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
506 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
507 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
508 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
509 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
510 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
511 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
512 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
513 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
514 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
515 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
516 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
517 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
518 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
519 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
520 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
521 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
522 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
523 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
524 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
525 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
526 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
527 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
528 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
529 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
530 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
531 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
532 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
533 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
534 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
535 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
536 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
537 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
538 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
539 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
540 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
541 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
542 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
543 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
544 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
545 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
546 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
547 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
548 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
549 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
550 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
551 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
552 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
553 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
554 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
555 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
556 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
557 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
558 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
559 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
560 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
561 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
562 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
563 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
564 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
565 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
566 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
567 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
570 #define EROUND(l,r) l ^= *(p++); r ^= ((s[((l>>24)&0xff)+0x000]+s[((l>>16)&0xff)+0x100])^s[((l>>8)&0xff)+0x200])+s[((l>>0)&0xff)+0x300]
571 #define DROUND(l,r) l ^= *(p--); r ^= ((s[((l>>24)&0xff)+0x000]+s[((l>>16)&0xff)+0x100])^s[((l>>8)&0xff)+0x200])+s[((l>>0)&0xff)+0x300]
573 static int blowfishEncrypt(struct blowfishParam* bp, uint32_t* dst, const uint32_t* src)
575 #if WORDS_BIGENDIAN
576 register uint32_t xl = src[0], xr = src[1];
577 #else
578 register uint32_t xl = swapu32(src[0]), xr = swapu32(src[1]);
579 #endif
580 register uint32_t* p = bp->p;
581 register uint32_t* s = bp->s;
583 EROUND(xl, xr); EROUND(xr, xl);
584 EROUND(xl, xr); EROUND(xr, xl);
585 EROUND(xl, xr); EROUND(xr, xl);
586 EROUND(xl, xr); EROUND(xr, xl);
587 EROUND(xl, xr); EROUND(xr, xl);
588 EROUND(xl, xr); EROUND(xr, xl);
589 EROUND(xl, xr); EROUND(xr, xl);
590 EROUND(xl, xr); EROUND(xr, xl);
592 #if WORDS_BIGENDIAN
593 dst[1] = xl ^ *(p++);
594 dst[0] = xr ^ *(p++);
595 #else
596 dst[1] = swapu32(xl ^ *(p++));
597 dst[0] = swapu32(xr ^ *(p++));
598 #endif
600 return 0;
603 static int blowfishDecrypt(struct blowfishParam* bp, uint32_t* dst, const uint32_t* src)
605 #if WORDS_BIGENDIAN
606 register uint32_t xl = src[0], xr = src[1];
607 #else
608 register uint32_t xl = swapu32(src[0]), xr = swapu32(src[1]);
609 #endif
610 register uint32_t* p = bp->p+BLOWFISHPSIZE-1;
611 register uint32_t* s = bp->s;
613 DROUND(xl, xr); DROUND(xr, xl);
614 DROUND(xl, xr); DROUND(xr, xl);
615 DROUND(xl, xr); DROUND(xr, xl);
616 DROUND(xl, xr); DROUND(xr, xl);
617 DROUND(xl, xr); DROUND(xr, xl);
618 DROUND(xl, xr); DROUND(xr, xl);
619 DROUND(xl, xr); DROUND(xr, xl);
620 DROUND(xl, xr); DROUND(xr, xl);
622 #if WORDS_BIGENDIAN
623 dst[1] = xl ^ *(p--);
624 dst[0] = xr ^ *(p--);
625 #else
626 dst[1] = swapu32(xl ^ *(p--));
627 dst[0] = swapu32(xr ^ *(p--));
628 #endif
630 return 0;
633 static int blowfishSetup(struct blowfishParam* bp, const unsigned char* key, size_t keybits, cipherOperation op)
635 if ((op != ENCRYPT) && (op != DECRYPT))
636 return -1;
638 if (((keybits & 7) == 0) && (keybits >= 32) && (keybits <= 448))
640 register uint32_t* p = bp->p;
641 register uint32_t* s = bp->s;
642 register unsigned int i, j, k;
644 uint32_t tmp, work[2];
646 memcpy(s, _bf_s, 1024 * sizeof(uint32_t));
648 for (i = 0, k = 0; i < BLOWFISHPSIZE; i++)
650 tmp = 0;
651 for (j = 0; j < 4; j++)
653 tmp <<= 8;
654 tmp |= key[k++];
655 if (k >= (keybits >> 3))
656 k = 0;
658 p[i] = _bf_p[i] ^ tmp;
661 work[0] = work[1] = 0;
663 for (i = 0; i < BLOWFISHPSIZE; i += 2, p += 2)
665 blowfishEncrypt(bp, work, work);
666 #if WORDS_BIGENDIAN
667 p[0] = work[0];
668 p[1] = work[1];
669 #else
670 p[0] = swapu32(work[0]);
671 p[1] = swapu32(work[1]);
672 #endif
675 for (i = 0; i < 1024; i += 2, s += 2)
677 blowfishEncrypt(bp, work, work);
678 #if WORDS_BIGENDIAN
679 s[0] = work[0];
680 s[1] = work[1];
681 #else
682 s[0] = swapu32(work[0]);
683 s[1] = swapu32(work[1]);
684 #endif
687 /* clear fdback/iv */
688 bp->fdback[0] = 0;
689 bp->fdback[1] = 0;
691 return 0;
693 return -1;
696 static int blowfishSetIV(struct blowfishParam* bp, const unsigned char* iv)
698 if (iv)
699 memcpy(bp->fdback, iv, 8);
700 else
701 memset(bp->fdback, 0, 8);
703 return 0;
706 #define BLOWFISH_BLOCKSIZE 8
707 static int blowfishDecryptCBC(struct blowfishParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
709 register const unsigned int blockwords = BLOWFISH_BLOCKSIZE >> 2;
710 register uint32_t* fdback = bp->fdback;
711 register uint32_t* buf = (uint32_t*) malloc(blockwords * sizeof(uint32_t));
713 if (buf)
715 while (nblocks > 0)
717 register uint32_t tmp;
718 register unsigned int i;
720 blowfishDecrypt(bp, buf, src);
722 for (i = 0; i < blockwords; i++)
724 tmp = src[i];
725 dst[i] = buf[i] ^ fdback[i];
726 fdback[i] = tmp;
729 dst += blockwords;
730 src += blockwords;
732 nblocks--;
734 free(buf);
735 return 0;
738 return -1;
741 static bool bf_cbc_decrypt(const unsigned char* key, size_t keylen,
742 unsigned char* data, size_t datalen,
743 const unsigned char* iv)
745 struct blowfishParam param;
746 unsigned char *cipher;
747 unsigned int nblocks;
749 if (datalen % BLOWFISH_BLOCKSIZE)
750 return false;
752 if (blowfishSetup(&param, key, keylen * 8, ENCRYPT))
753 return false;
754 if (blowfishSetIV(&param, iv))
755 return false;
757 cipher = malloc(datalen);
758 memcpy(cipher, data, datalen);
760 nblocks = datalen / BLOWFISH_BLOCKSIZE;
761 if (blowfishDecryptCBC(&param, (uint32_t*)data, (uint32_t*)cipher,
762 nblocks))
764 free(cipher);
765 return false;
768 free(cipher);
769 return true;
772 static inline uint32_t swap(uint32_t val)
774 return ((val & 0xFF) << 24)
775 | ((val & 0xFF00) << 8)
776 | ((val & 0xFF0000) >> 8)
777 | ((val & 0xFF000000) >> 24);
780 static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
781 static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
782 static const char null_key_v3[] = "CTL:N0MAD|PDE0.DPFP.";
783 static const char null_key_v4[] = "CTL:Z3N07|PDE0.DPMP.";
785 static const char fresc_key_v1[] = "Copyright (C) CTL. -"
786 " zN0MAD iz v~p0wderful!";
787 static const char fresc_key_v2[] = ""; /* Unknown atm */
789 static const char tl_zvm_key[] = "1sN0TM3D az u~may th1nk*"
790 "Creative Zen Vision:M";
791 static const char tl_zvm60_key[] = "1sN0TM3D az u~may th1nk*"
792 "Creative Zen Vision:M (D"
793 "VP-HD0004)";
794 static const char tl_zen_key[] = "1sN0TM3D az u~may th1nk*"
795 "Creative ZEN";
796 static const char tl_zenxf_key[] = "1sN0TM3D az u~may th1nk*"
797 "Creative ZEN X-Fi";
798 static const char tl_zv_key[] = "1sN0TM3D az u~may th1nk*"
799 "Creative Zen Vision";
800 static const char tl_zvw_key[] = "1sN0TM3D az u~may th1nk*"
801 "Creative ZEN Vision W";
802 static const char tl_zm_key[] = "1sN0TM3D az u~may th1nk*"
803 "Creative Zen Micro";
804 static const char tl_zmp_key[] = "1sN0TM3D az u~may th1nk*"
805 "Creative Zen MicroPhoto";
806 static const char tl_zs_key[] = "1sN0TM3D az u~may th1nk*"
807 "Creative Zen Sleek";
808 static const char tl_zsp_key[] = "1sN0TM3D az u~may th1nk*"
809 "Creative Zen Sleek Photo";
810 static const char tl_zt_key[] = "1sN0TM3D az u~may th1nk*"
811 "Creative Zen Touch";
812 static const char tl_zx_key[] = "1sN0TM3D az u~may th1nk*"
813 "NOMAD Jukebox Zen Xtra";
814 static const char tl_zenv_key[] = "1sN0TM3D az u~may th1nk*"
815 "Creative ZEN V";
816 static const char tl_zenvp_key[] = "1sN0TM3D az u~may th1nk*"
817 "Creative ZEN V Plus";
818 static const char tl_zenvv_key[] = "1sN0TM3D az u~may th1nk*"
819 "Creative ZEN V (Video)";
820 struct player_info_t
822 const char* name;
823 const char* null_key; /* HMAC-SHA1 key */
824 const char* fresc_key; /* BlowFish key */
825 const char* tl_key; /* BlowFish key */
826 bool big_endian;
829 static struct player_info_t players[] = {
830 {"Zen Vision:M", null_key_v2, fresc_key_v1, tl_zvm_key, false},
831 {"Zen Vision:M 60GB", null_key_v2, fresc_key_v1, tl_zvm60_key, false},
832 {"ZEN", null_key_v4, fresc_key_v2, tl_zen_key, false},
833 {"ZEN X-Fi", null_key_v4, fresc_key_v2, tl_zenxf_key, false},
834 {"Zen Vision", null_key_v2, fresc_key_v1, tl_zv_key, false},
835 {"Zen Vision W", null_key_v2, fresc_key_v1, tl_zvw_key, false},
836 {"Zen Micro", null_key_v1, fresc_key_v1, tl_zm_key, true},
837 {"Zen MicroPhoto", null_key_v1, fresc_key_v1, tl_zmp_key, true},
838 {"Zen Sleek", null_key_v1, fresc_key_v1, tl_zs_key, true},
839 {"Zen SleekPhoto", null_key_v1, fresc_key_v1, tl_zsp_key, true},
840 {"Zen Touch", null_key_v1, fresc_key_v1, tl_zt_key, true},
841 {"Zen Xtra", null_key_v1, fresc_key_v1, tl_zx_key, true},
842 {"Zen V", null_key_v3, fresc_key_v1, tl_zenv_key, false},
843 {"Zen V Plus", null_key_v3, fresc_key_v1, tl_zenvp_key, false},
844 {"Zen V Video", null_key_v3, fresc_key_v1, tl_zenvv_key, false},
845 {NULL, NULL, NULL, NULL, false}
848 int mkboot(const char* infile, const char* bootfile, const char* outfile, struct player_info_t *player)
850 FILE *infd, *bootfd, *outfd;
851 unsigned char *buffer, *out_buffer, enc_data[40], hash_key[20];
852 char *err_msg;
853 const char *fw_key;
854 uint32_t i, fw_offset, fw_size, data_ptr, data_size, ciff_size, cenc_size, iv[2];
856 infd = fopen(infile, "rb");
857 if(infd == NULL)
859 fprintf(stderr, "[ERR] Could not open %s\n", infile);
860 return -1;
863 buffer = malloc(filesize(infd));
864 if(buffer == NULL)
866 fprintf(stderr, "[ERR] Could not allocate %d unsigned chars\n", filesize(infd));
867 fclose(infd);
868 return -2;
871 if(fread(buffer, filesize(infd), 1, infd) != 1)
873 fprintf(stderr, "[ERR] Short read\n");
874 fclose(infd);
875 free(buffer);
876 return -3;
879 fclose(infd);
881 /* Rudimentary Win32 PE reading */
882 if(memcmp(&buffer[0], "MZ", 2) != 0 &&
883 memcmp(&buffer[0x118], "PE", 2) != 0)
885 fprintf(stderr, "[ERR] Input file isn't an executable\n");
886 free(buffer);
887 return -4;
890 data_ptr = 0, data_size = 0;
891 for(i=0x210; i < 0x1000; i+=0x28)
893 if(strcmp((char*)&buffer[i], ".data") == 0)
895 data_ptr = le2int(&buffer[i+0x14]);
896 data_size = le2int(&buffer[i+0x10]);
897 break;
901 if(data_ptr == 0 || data_size == 0)
903 fprintf(stderr, "[ERR] Couldn't find .data section\n");
904 free(buffer);
905 return -5;
908 fprintf(stderr, "[INFO] .data section is at 0x%x with size 0x%x\n", data_ptr, data_size);
910 fw_offset = find_firmware_offset(&buffer[data_ptr], data_size);
911 if(fw_offset == 0)
913 fprintf(stderr, "[ERR] Couldn't find firmware offset\n");
914 free(buffer);
915 return -6;
917 fw_size = le2int(&buffer[data_ptr+fw_offset]);
918 fprintf(stderr, "[INFO] Firmware offset is at 0x%x with size 0x%x\n", data_ptr+fw_offset, fw_size);
920 fw_key = find_firmware_key(&buffer[0], filesize(infd));
921 if(fw_key == NULL)
923 fprintf(stderr, "[ERR] Couldn't find firmware key\n");
924 free(buffer);
925 return -7;
927 fprintf(stderr, "[INFO] Firmware key is %s\n", fw_key);
929 fprintf(stderr, "[INFO] Descrambling firmware... ");
930 if(!crypt_firmware(fw_key, &buffer[data_ptr+fw_offset+4], fw_size))
932 fprintf(stderr, "Fail!\n");
933 free(buffer);
934 return -8;
936 else
937 fprintf(stderr, "Done!\n");
939 out_buffer = malloc(fw_size*2);
940 if(out_buffer == NULL)
942 fprintf(stderr, "[ERR] Couldn't allocate %d unsigned chars", fw_size*2);
943 free(buffer);
944 return -9;
947 memset(out_buffer, 0, fw_size*2);
949 err_msg = NULL;
950 fprintf(stderr, "[INFO] Decompressing firmware... ");
951 if(!inflate_to_buffer(&buffer[data_ptr+fw_offset+4], fw_size, out_buffer, fw_size*2, &err_msg))
953 fprintf(stderr, "Fail!\n[ERR] ZLib error: %s\n", err_msg);
954 free(buffer);
955 free(out_buffer);
956 return -10;
958 else
960 fprintf(stderr, "Done!\n");
961 free(buffer);
964 if(memcmp(out_buffer, "FFIC", 4) != 0)
966 fprintf(stderr, "[ERR] CIFF header doesn't match\n");
967 free(out_buffer);
968 return -11;
971 ciff_size = le2int(&out_buffer[4])+8+28; /* CIFF block + NULL block*/
973 bootfd = fopen(bootfile, "rb");
974 if(bootfd == NULL)
976 fprintf(stderr, "[ERR] Could not open %s\n", bootfile);
977 free(out_buffer);
978 return -12;
981 out_buffer = realloc(out_buffer, ciff_size+filesize(bootfd));
982 if(out_buffer == NULL)
984 fprintf(stderr, "[ERR] Cannot allocate %d unsigned chars\n", ciff_size+40+filesize(bootfd));
985 fclose(bootfd);
986 return -13;
989 fprintf(stderr, "[INFO] Locating encoded block... ");
991 i = 8;
992 while(memcmp(&out_buffer[i], " LT©", 4) != 0 && i < ciff_size)
994 if(memcmp(&out_buffer[i], "FNIC", 4) == 0)
995 i += 4+4+96;
996 else if(memcmp(&out_buffer[i], "ATAD", 4) == 0)
998 i += 4;
999 i += le2int(&out_buffer[i]);
1000 i += 4;
1002 else
1004 fprintf(stderr, "Fail!\n[ERR] Unknown block\n");
1005 fclose(bootfd);
1006 free(out_buffer);
1007 return -14;
1011 if(i > ciff_size || memcmp(&out_buffer[i], " LT©", 4) != 0)
1013 fprintf(stderr, "Fail!\n[ERR] Couldn't find encoded block\n");
1014 fclose(bootfd);
1015 free(out_buffer);
1016 return -15;
1019 fprintf(stderr, "Done!\n");
1021 outfd = fopen(outfile, "wb+");
1022 if(outfd == NULL)
1024 fprintf(stderr, "[ERR] Could not open %s\n", outfile);
1025 fclose(bootfd);
1026 free(out_buffer);
1027 return -16;
1030 if(fwrite(&out_buffer[0], i, 1, outfd) != 1)
1032 fprintf(stderr, "[ERR] Short write\n");
1033 fclose(bootfd);
1034 fclose(outfd);
1035 free(out_buffer);
1036 return -17;
1039 fprintf(stderr, "[INFO] Decrypting encoded block... ");
1041 iv[0] = 0;
1042 iv[1] = swap(le2int(&out_buffer[i+4]));
1043 if(bf_cbc_decrypt((unsigned char*)player->tl_key, strlen(player->tl_key)+1, &out_buffer[i+8],
1044 le2int(&out_buffer[i+4]), (const unsigned char*)&iv)
1045 == false)
1047 fprintf(stderr, "Fail!\n[ERR] Couldn't decrypt encoded block\n");
1048 fclose(bootfd);
1049 fclose(outfd);
1050 free(out_buffer);
1051 return -18;
1054 fprintf(stderr, "Done!\n");
1056 cenc_size = le2int(&out_buffer[i+8]);
1058 if(cenc_size > le2int(&out_buffer[i+4])*3)
1060 fprintf(stderr, "[ERR] Decrypted length of encoded block is unexpectedly large: 0x%08x\n", cenc_size);
1061 fclose(bootfd);
1062 fclose(outfd);
1063 free(out_buffer);
1064 return -19;
1067 buffer = malloc(cenc_size);
1068 if(buffer == NULL)
1070 fprintf(stderr, "[ERR] Couldn't allocate %d unsigned chars\n", cenc_size);
1071 fclose(bootfd);
1072 fclose(outfd);
1073 free(out_buffer);
1074 return -20;
1077 memset(buffer, 0, cenc_size);
1079 fprintf(stderr, "[INFO] Decompressing encoded block... ");
1081 if(!cenc_decode(&out_buffer[i+12], le2int(&out_buffer[i+4])-4, &buffer[0], cenc_size))
1083 fprintf(stderr, "Fail!\n[ERR] Couldn't decompress the encoded block\n");
1084 fclose(bootfd);
1085 fclose(outfd);
1086 free(out_buffer);
1087 free(buffer);
1088 return -21;
1091 fprintf(stderr, "Done!\n");
1093 fprintf(stderr, "[INFO] Renaming encoded block to Hcreativeos.jrm... ");
1095 memcpy(&enc_data, "ATAD", 4);
1096 int2le(cenc_size+32, &enc_data[4]);
1097 memset(&enc_data[8], 0, 32);
1098 memcpy(&enc_data[8], "H\0c\0r\0e\0a\0t\0i\0v\0e\0o\0s\0.\0j\0r\0m", 30);
1099 if(fwrite(enc_data, 40, 1, outfd) != 1)
1101 fprintf(stderr, "Fail!\n[ERR] Short write\n");
1102 fclose(bootfd);
1103 fclose(outfd);
1104 free(out_buffer);
1105 free(buffer);
1106 return -22;
1109 if(fwrite(&buffer[0], cenc_size, 1, outfd) != 1)
1111 fprintf(stderr, "Fail!\n[ERR] Short write\n");
1112 fclose(bootfd);
1113 fclose(outfd);
1114 free(out_buffer);
1115 free(buffer);
1116 return -23;
1119 free(buffer);
1120 fprintf(stderr, "Done!\n[INFO] Adding Hjukebox2.jrm... ");
1122 memcpy(&enc_data, "ATAD", 4);
1123 int2le(filesize(bootfd)+32, &enc_data[4]);
1124 memset(&enc_data[8], 0, 32);
1125 memcpy(&enc_data[8], "H\0j\0u\0k\0e\0b\0o\0x\0""2\0.\0j\0r\0m", 26);
1126 if(fwrite(enc_data, 40, 1, outfd) != 1)
1128 fprintf(stderr, "Fail!\n[ERR] Short write\n");
1129 fclose(bootfd);
1130 fclose(outfd);
1131 free(out_buffer);
1132 return -24;
1135 if(fread(&out_buffer[ciff_size], filesize(bootfd), 1, bootfd) != 1)
1137 fprintf(stderr, "Fail!\n[ERR] Short read\n");
1138 fclose(bootfd);
1139 fclose(outfd);
1140 free(out_buffer);
1141 return -25;
1144 if(memcmp(&out_buffer[ciff_size], "EDOC", 4) != 0)
1146 fprintf(stderr, "Fail!\n[ERR] Faulty bootloader\n");
1147 free(out_buffer);
1148 fclose(bootfd);
1149 fclose(outfd);
1150 return -26;
1153 if(fwrite(&out_buffer[ciff_size], filesize(bootfd), 1, outfd) != 1)
1155 fprintf(stderr, "Fail!\n[ERR] Short write\n");
1156 fclose(bootfd);
1157 fclose(outfd);
1158 free(out_buffer);
1159 return -27;
1162 fclose(bootfd);
1163 fprintf(stderr, "Done!\n");
1165 if(fwrite(&out_buffer[i+8+le2int(&out_buffer[i+4])], ciff_size-i-8-le2int(&out_buffer[i+4]), 1, outfd) != 1)
1167 fprintf(stderr, "[ERR] Short write\n");
1168 fclose(bootfd);
1169 fclose(outfd);
1170 free(out_buffer);
1171 return -28;
1174 fseek(outfd, 4, SEEK_SET);
1175 int2le(filesize(outfd)-8-28, enc_data);
1176 if(fwrite(enc_data, 4, 1, outfd) != 1)
1178 fprintf(stderr, "[ERR] Short write\n");
1179 fclose(outfd);
1180 free(out_buffer);
1181 return -29;
1184 free(out_buffer);
1185 fflush(outfd);
1187 fprintf(stderr, "[INFO] Updating checksum... ");
1189 buffer = malloc(filesize(outfd)-28);
1190 if(buffer == NULL)
1192 fprintf(stderr, "Fail!\n[ERR] Couldn't allocate %d unsigned chars\n", filesize(outfd)-28);
1193 fclose(outfd);
1194 return -30;
1197 fseek(outfd, 0, SEEK_SET);
1198 if(fread(buffer, filesize(outfd)-28, 1, outfd) != 1)
1200 fprintf(stderr, "Fail!\n[ERR] Short read\n");
1201 fclose(outfd);
1202 free(buffer);
1203 return -31;
1206 hmac_sha1((unsigned char*)player->null_key, strlen(player->null_key), &buffer[0], filesize(outfd)-28, &hash_key);
1208 fseek(outfd, filesize(outfd)-20, SEEK_SET);
1209 if(fwrite(hash_key, 20, 1, outfd) != 1)
1211 fprintf(stderr, "Fail!\n[ERR] Short write\n");
1212 fclose(outfd);
1213 free(buffer);
1214 return -32;
1217 fclose(outfd);
1219 fprintf(stderr, "Done!\n");
1220 return 0;
1223 #ifdef STANDALONE
1224 static void usage(void)
1226 int i;
1228 printf("Usage: mkzenboot <firmware file> <boot file> <output file> <player>\n");
1229 printf("Players:\n");
1230 for (i = 0; players[i].name != NULL; i++)
1231 printf(" * \"%s\"\n", players[i].name);
1233 exit(1);
1236 int main(int argc, char *argv[])
1238 char *infile, *bootfile, *outfile;
1239 int i;
1240 struct player_info_t *player = NULL;
1242 if(argc < 5)
1243 usage();
1245 infile = argv[1];
1246 bootfile = argv[2];
1247 outfile = argv[3];
1249 for (i = 0; players[i].name != NULL; i++)
1251 if(!strcasecmp(players[i].name, argv[4]))
1252 player = &players[i];
1255 if(player == NULL)
1257 fprintf(stderr, "[ERR] %s isn't listed as a player!\n", argv[4]);
1258 exit(1);
1261 return mkboot(infile, bootfile, outfile, player);
1263 #endif