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