summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2008-04-09 11:53:28 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2008-04-09 11:53:28 +0000
commite810721e72d0d70d87b02603299d50809b794470 (patch)
tree19cc6a608e064abd6361493bb5cfa7589c531bba
parent5a3651bf940001693153ab52a67c9cd87e7d41c7 (diff)
downloadrockbox-e810721e72d0d70d87b02603299d50809b794470.tar.gz
rockbox-e810721e72d0d70d87b02603299d50809b794470.zip
First commit:
* add Creative (ZVM, 60GB, ZV, ZVW, ZENV) support to scramble * update configure to the correct values git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17042 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--tools/Makefile8
-rwxr-xr-xtools/configure9
-rw-r--r--tools/creative.c159
-rw-r--r--tools/creative.h53
-rw-r--r--tools/hmac-sha1.c463
-rw-r--r--tools/hmac-sha1.h84
-rw-r--r--tools/scramble.c111
7 files changed, 784 insertions, 103 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 94378d8fc5..e43bf98f22 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -13,16 +13,18 @@ LDFLAGS := -g
13 13
14CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ 14CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \
15 generate_rocklatin mkboot ipod_fw codepages uclpack mi4 gigabeat database \ 15 generate_rocklatin mkboot ipod_fw codepages uclpack mi4 gigabeat database \
16 lngdump telechips gigabeats mktccboot mknkboot rbspeexenc 16 lngdump telechips gigabeats creative hmac-sha1 mktccboot mknkboot rbspeexenc
17 17
18all: 18all:
19 @echo "Run make in your build directory!" 19 @echo "Run make in your build directory!"
20 20
21scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o iaudio_bl_flash.o 21scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o iaudio_bl_flash.o creative.o hmac-sha1.o
22descramble: descramble.o iriver.o gigabeat.o 22descramble: descramble.o iriver.o gigabeat.o
23scramble.o: scramble.c iriver.h mi4.h gigabeat.h telechips.h iaudio_bl_flash.h creative.h
23 24
24scramble.o: scramble.c iriver.h mi4.h gigabeat.h telechips.h iaudio_bl_flash.h
25descramble.o: descramble.c iriver.h gigabeat.h 25descramble.o: descramble.c iriver.h gigabeat.h
26creative.o: creative.c creative.h
27hmac-sha1.o: hmac-sha1.c hmac-sha1.h
26iriver.o: iriver.c iriver.h 28iriver.o: iriver.c iriver.h
27gigabeat.o: gigabeat.c gigabeat.h 29gigabeat.o: gigabeat.c gigabeat.h
28gigabeats.o: gigabeats.c gigabeats.h 30gigabeats.o: gigabeats.c gigabeats.h
diff --git a/tools/configure b/tools/configure
index 7f70c332ae..151a4b70ff 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1455,18 +1455,19 @@ fi
1455 target_id=35 1455 target_id=35
1456 modelname="creativezvm" 1456 modelname="creativezvm"
1457 target="-DCREATIVE_ZVM" 1457 target="-DCREATIVE_ZVM"
1458 memory=32 # always 1458 memory=64
1459 arm926ejscc 1459 arm926ejscc
1460 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" 1460 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
1461 bmp2rb_native="$rootdir/tools/bmp2rb -f 4" 1461 bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
1462 bmp2rb_remotemono="$rootdir/tools/bmp2rb -f 0" 1462 bmp2rb_remotemono="$rootdir/tools/bmp2rb -f 0"
1463 bmp2rb_remotenative="$rootdir/tools/bmp2rb -f 0" 1463 bmp2rb_remotenative="$rootdir/tools/bmp2rb -f 0"
1464 tool="cp"
1464 output="rockbox.zvm" 1465 output="rockbox.zvm"
1465 appextra="recorder:gui" 1466 appextra="recorder:gui"
1466 plugins="yes" 1467 plugins=""
1467 swcodec="yes" 1468 swcodec="yes"
1468 toolset=$gigabeatbitmaptools 1469 toolset=$gigabeatbitmaptools
1469 boottool="$rootdir/tools/scramble -zvm" 1470 boottool="$rootdir/tools/scramble -creative=zvm"
1470 bootoutput="rockbox.zvmboot" 1471 bootoutput="rockbox.zvmboot"
1471 # architecture, manufacturer and model for the target-tree build 1472 # architecture, manufacturer and model for the target-tree build
1472 t_cpu="arm" 1473 t_cpu="arm"
@@ -1998,7 +1999,7 @@ sed > Makefile \
1998 -e "s,@VOICETOOLSET@,${voicetoolset},g" \ 1999 -e "s,@VOICETOOLSET@,${voicetoolset},g" \
1999 -e "s,@LANGS@,${buildlangs},g" \ 2000 -e "s,@LANGS@,${buildlangs},g" \
2000<<EOF 2001<<EOF
2001## Automaticly generated. http://www.rockbox.org/ 2002## Automatically generated. http://www.rockbox.org/
2002 2003
2003ifndef V 2004ifndef V
2004SILENT=@ 2005SILENT=@
diff --git a/tools/creative.c b/tools/creative.c
new file mode 100644
index 0000000000..5dc65ab992
--- /dev/null
+++ b/tools/creative.c
@@ -0,0 +1,159 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "creative.h"
21#include "hmac-sha1.h"
22#include <stdio.h>
23#include <stdbool.h>
24
25/*
26Create a Zen Vision:M FRESCUE structure file
27*/
28
29
30static int make_ciff_file(char *inbuf, int length, char *outbuf, int device)
31{
32 memcpy(outbuf, "FFIC", 4);
33 int2le(length+90, &outbuf[4]);
34 memcpy(&outbuf[8], "FNIC", 4);
35 int2le(96, &outbuf[0xC]);
36 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
37 memset(&outbuf[0x10+devices[device].cinf_size], 0, 96 - devices[device].cinf_size);
38 memcpy(&outbuf[0x70], "ATAD", 4);
39 int2le(length+32, &outbuf[0x74]);
40 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m", 32); /*Unicode encoded*/
41 memcpy(&outbuf[0x98], inbuf, length);
42 memcpy(&outbuf[0x98+length], "LLUN", 4);
43 int2le(20, &outbuf[0x98+length+4]);
44 /* Do checksum */
45 char key[20];
46 hmac_sha((char*)devices[device].null, strlen(devices[device].null), outbuf, 0x98+length, key, 20);
47 memcpy(&outbuf[0x98+length+8], key, 20);
48 return length+0x90+0x1C+8;
49}
50
51static int make_jrm_file(char *inbuf, int length, char *outbuf)
52{
53 int i;
54 unsigned int sum = 0;
55 /* Calculate checksum for later use in header */
56 for(i=0; i<length; i+= 4)
57 sum += le2int(&inbuf[i]) + (le2int(&inbuf[i])>>16);
58
59 /* Clear the header area to zero */
60 memset(outbuf, 0, 0x18);
61
62 /* Header (EDOC) */
63 memcpy(outbuf, "EDOC", 4);
64 /* Total Size */
65 int2le(length+0x20, &outbuf[0x4]);
66 /* 4 bytes of zero */
67
68 /* Address = 0x900000 */
69 int2le(0x900000, &outbuf[0xC]);
70 /* Size */
71 int2le(length, &outbuf[0x10]);
72 /* Checksum */
73 int2le(sum, &outbuf[0x14]);
74 outbuf[0x16] = 0;
75 outbuf[0x17] = 0;
76 /* Data starts here... */
77 memcpy(&outbuf[0x18], inbuf, length);
78
79 /* Second block starts here ... */
80 /* Address = 0x0 */
81 /* Size */
82 int2le(0x4, &outbuf[0x18+length+0x4]);
83 /* Checksum */
84 outbuf[0x18+length+0x8] = 0xA9;
85 outbuf[0x18+length+0x9] = 0xD9;
86 /* Data: MOV PC, 0x900000 */
87 outbuf[0x18+length+0xC] = 0x09;
88 outbuf[0x18+length+0xD] = 0xF6;
89 outbuf[0x18+length+0xE] = 0xA0;
90 outbuf[0x18+length+0xF] = 0xE3;
91
92 return length+0x18+0x10;
93}
94
95int zvm_encode(char *iname, char *oname, int device)
96{
97 size_t len;
98 int length;
99 FILE *file;
100 unsigned char *outbuf;
101 unsigned char *buf;
102 int i;
103
104 file = fopen(iname, "rb");
105 if (!file) {
106 perror(iname);
107 return -1;
108 }
109 fseek(file, 0, SEEK_END);
110 length = ftell(file);
111
112 fseek(file, 0, SEEK_SET);
113
114 buf = (unsigned char*)malloc(length);
115 if ( !buf ) {
116 printf("out of memory!\n");
117 return -1;
118 }
119
120 len = fread(buf, 1, length, file);
121 if(len < length) {
122 perror(iname);
123 return -2;
124 }
125 fclose(file);
126
127 outbuf = (unsigned char*)malloc(length+0x300);
128 if ( !outbuf ) {
129 free(buf);
130 printf("out of memory!\n");
131 return -1;
132 }
133 length = make_jrm_file(buf, len, outbuf);
134 free(buf);
135 buf = (unsigned char*)malloc(length+0x200);
136 memset(buf, 0, length+0x200);
137 length = make_ciff_file(outbuf, length, buf, device);
138 free(outbuf);
139
140 file = fopen(oname, "wb");
141 if (!file) {
142 free(buf);
143 perror(oname);
144 return -3;
145 }
146
147 len = fwrite(buf, 1, length, file);
148 if(len < length) {
149 free(buf);
150 perror(oname);
151 return -4;
152 }
153
154 free(buf);
155
156 fclose(file);
157
158 return 0;
159}
diff --git a/tools/creative.h b/tools/creative.h
new file mode 100644
index 0000000000..c28001a0e7
--- /dev/null
+++ b/tools/creative.h
@@ -0,0 +1,53 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef CREATIVE_H_
21#define CREATIVE_H_
22
23enum
24{
25 ZENVISIONM = 0,
26 ZENVISIONM60 = 1,
27 ZENVISION = 2,
28 ZENV = 3
29};
30
31static struct device_info
32{
33 const char* cinf; /*Must be Unicode encoded*/
34 const int cinf_size;
35 const char* null;
36} device_info;
37
38static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
39static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
40static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
41static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
42
43static const struct device_info devices[] =
44{
45 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0:\0M", 42, null_key_v2},
46 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0:\0M\0 \0G\0o\0!", 50, null_key_v2},
47 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0 \0©\0T\0L", 48, null_key_v2},
48 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4}
49};
50
51int zvm_encode(char *iname, char *oname, int device);
52
53#endif /*CREATIVE_H_*/
diff --git a/tools/hmac-sha1.c b/tools/hmac-sha1.c
new file mode 100644
index 0000000000..1b4b3b5abd
--- /dev/null
+++ b/tools/hmac-sha1.c
@@ -0,0 +1,463 @@
1/*
2 * sha1.c
3 *
4 * Description:
5 * This file implements the Secure Hashing Algorithm 1 as
6 * defined in FIPS PUB 180-1 published April 17, 1995.
7 *
8 * The SHA-1, produces a 160-bit message digest for a given
9 * data stream. It should take about 2**n steps to find a
10 * message with the same digest as a given message and
11 * 2**(n/2) to find any two messages with the same digest,
12 * when n is the digest size in bits. Therefore, this
13 * algorithm can serve as a means of providing a
14 * "fingerprint" for a message.
15 *
16 * Portability Issues:
17 * SHA-1 is defined in terms of 32-bit "words". This code
18 * uses <stdint.h> (included via "sha1.h" to define 32 and 8
19 * bit unsigned integer types. If your C compiler does not
20 * support 32 bit unsigned integers, this code is not
21 * appropriate.
22 *
23 * Caveats:
24 * SHA-1 is designed to work with messages less than 2^64 bits
25 * long. Although SHA-1 allows a message digest to be generated
26 * for messages of any number of bits less than 2^64, this
27 * implementation only works with messages with a length that is
28 * a multiple of the size of an 8-bit character.
29 *
30 */
31
32#include "hmac-sha1.h"
33
34/*
35 * Define the SHA1 circular left shift macro
36 */
37#define SHA1CircularShift(bits,word) \
38 (((word) << (bits)) | ((word) >> (32-(bits))))
39
40/* Local Function Prototyptes */
41void SHA1PadMessage(SHA1Context *);
42void SHA1ProcessMessageBlock(SHA1Context *);
43
44/*
45 * SHA1Reset
46 *
47 * Description:
48 * This function will initialize the SHA1Context in preparation
49 * for computing a new SHA1 message digest.
50 *
51 * Parameters:
52 * context: [in/out]
53 * The context to reset.
54 *
55 * Returns:
56 * sha Error Code.
57 *
58 */
59int SHA1Reset(SHA1Context *context)
60{
61 if (!context)
62 {
63 return shaNull;
64 }
65
66 context->Length_Low = 0;
67 context->Length_High = 0;
68 context->Message_Block_Index = 0;
69
70 context->Intermediate_Hash[0] = 0x67452301;
71 context->Intermediate_Hash[1] = 0xEFCDAB89;
72 context->Intermediate_Hash[2] = 0x98BADCFE;
73 context->Intermediate_Hash[3] = 0x10325476;
74 context->Intermediate_Hash[4] = 0xC3D2E1F0;
75
76 context->Computed = 0;
77 context->Corrupted = 0;
78
79 return shaSuccess;
80}
81
82/*
83 * SHA1Result
84 *
85 * Description:
86 * This function will return the 160-bit message digest into the
87 * Message_Digest array provided by the caller.
88 * NOTE: The first octet of hash is stored in the 0th element,
89 * the last octet of hash in the 19th element.
90 *
91 * Parameters:
92 * context: [in/out]
93 * The context to use to calculate the SHA-1 hash.
94 * Message_Digest: [out]
95 * Where the digest is returned.
96 *
97 * Returns:
98 * sha Error Code.
99 *
100 */
101int SHA1Result( SHA1Context *context,
102 uint8_t Message_Digest[SHA1HashSize])
103{
104 int i;
105
106 if (!context || !Message_Digest)
107 {
108 return shaNull;
109 }
110
111 if (context->Corrupted)
112 {
113 return context->Corrupted;
114 }
115
116 if (!context->Computed)
117 {
118 SHA1PadMessage(context);
119 for(i=0; i<64; ++i)
120 {
121 /* message may be sensitive, clear it out */
122 context->Message_Block[i] = 0;
123 }
124 context->Length_Low = 0; /* and clear length */
125 context->Length_High = 0;
126 context->Computed = 1;
127 }
128
129 for(i = 0; i < SHA1HashSize; ++i)
130 {
131 Message_Digest[i] = context->Intermediate_Hash[i>>2]
132 >> 8 * ( 3 - ( i & 0x03 ) );
133 }
134
135 return shaSuccess;
136}
137
138/*
139 * SHA1Input
140 *
141 * Description:
142 * This function accepts an array of octets as the next portion
143 * of the message.
144 *
145 * Parameters:
146 * context: [in/out]
147 * The SHA context to update
148 * message_array: [in]
149 * An array of characters representing the next portion of
150 * the message.
151 * length: [in]
152 * The length of the message in message_array
153 *
154 * Returns:
155 * sha Error Code.
156 *
157 */
158int SHA1Input( SHA1Context *context,
159 const uint8_t *message_array,
160 unsigned length)
161{
162 if (!length)
163 {
164 return shaSuccess;
165 }
166
167 if (!context || !message_array)
168 {
169 return shaNull;
170 }
171
172 if (context->Computed)
173 {
174 context->Corrupted = shaStateError;
175 return shaStateError;
176 }
177
178 if (context->Corrupted)
179 {
180 return context->Corrupted;
181 }
182 while(length-- && !context->Corrupted)
183 {
184 context->Message_Block[context->Message_Block_Index++] =
185 (*message_array & 0xFF);
186
187 context->Length_Low += 8;
188 if (context->Length_Low == 0)
189 {
190 context->Length_High++;
191 if (context->Length_High == 0)
192 {
193 /* Message is too long */
194 context->Corrupted = 1;
195 }
196 }
197
198 if (context->Message_Block_Index == 64)
199 {
200 SHA1ProcessMessageBlock(context);
201 }
202
203 message_array++;
204 }
205
206 return shaSuccess;
207}
208
209/*
210 * SHA1ProcessMessageBlock
211 *
212 * Description:
213 * This function will process the next 512 bits of the message
214 * stored in the Message_Block array.
215 *
216 * Parameters:
217 * None.
218 *
219 * Returns:
220 * Nothing.
221 *
222 * Comments:
223 * Many of the variable names in this code, especially the
224 * single character names, were used because those were the
225 * names used in the publication.
226 *
227 *
228 */
229void SHA1ProcessMessageBlock(SHA1Context *context)
230{
231 const uint32_t K[] = { /* Constants defined in SHA-1 */
232 0x5A827999,
233 0x6ED9EBA1,
234 0x8F1BBCDC,
235 0xCA62C1D6
236 };
237 int t; /* Loop counter */
238 uint32_t temp; /* Temporary word value */
239 uint32_t W[80]; /* Word sequence */
240 uint32_t A, B, C, D, E; /* Word buffers */
241
242 /*
243 * Initialize the first 16 words in the array W
244 */
245 for(t = 0; t < 16; t++)
246 {
247 W[t] = context->Message_Block[t * 4] << 24;
248 W[t] |= context->Message_Block[t * 4 + 1] << 16;
249 W[t] |= context->Message_Block[t * 4 + 2] << 8;
250 W[t] |= context->Message_Block[t * 4 + 3];
251 }
252
253 for(t = 16; t < 80; t++)
254 {
255 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
256 }
257
258 A = context->Intermediate_Hash[0];
259 B = context->Intermediate_Hash[1];
260 C = context->Intermediate_Hash[2];
261 D = context->Intermediate_Hash[3];
262 E = context->Intermediate_Hash[4];
263
264 for(t = 0; t < 20; t++)
265 {
266 temp = SHA1CircularShift(5,A) +
267 ((B & C) | ((~B) & D)) + E + W[t] + K[0];
268 E = D;
269 D = C;
270 C = SHA1CircularShift(30,B);
271 B = A;
272 A = temp;
273 }
274
275 for(t = 20; t < 40; t++)
276 {
277 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
278 E = D;
279 D = C;
280 C = SHA1CircularShift(30,B);
281 B = A;
282 A = temp;
283 }
284
285 for(t = 40; t < 60; t++)
286 {
287 temp = SHA1CircularShift(5,A) +
288 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
289 E = D;
290 D = C;
291 C = SHA1CircularShift(30,B);
292 B = A;
293 A = temp;
294 }
295
296 for(t = 60; t < 80; t++)
297 {
298 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
299 E = D;
300 D = C;
301 C = SHA1CircularShift(30,B);
302 B = A;
303 A = temp;
304 }
305
306 context->Intermediate_Hash[0] += A;
307 context->Intermediate_Hash[1] += B;
308 context->Intermediate_Hash[2] += C;
309 context->Intermediate_Hash[3] += D;
310 context->Intermediate_Hash[4] += E;
311
312 context->Message_Block_Index = 0;
313}
314
315
316/*
317 * SHA1PadMessage
318 *
319 * Description:
320 * According to the standard, the message must be padded to an even
321 * 512 bits. The first padding bit must be a '1'. The last 64
322 * bits represent the length of the original message. All bits in
323 * between should be 0. This function will pad the message
324 * according to those rules by filling the Message_Block array
325 * accordingly. It will also call the ProcessMessageBlock function
326 * provided appropriately. When it returns, it can be assumed that
327 * the message digest has been computed.
328 *
329 * Parameters:
330 * context: [in/out]
331 * The context to pad
332 * ProcessMessageBlock: [in]
333 * The appropriate SHA*ProcessMessageBlock function
334 * Returns:
335 * Nothing.
336 *
337 */
338
339void SHA1PadMessage(SHA1Context *context)
340{
341 /*
342 * Check to see if the current message block is too small to hold
343 * the initial padding bits and length. If so, we will pad the
344 * block, process it, and then continue padding into a second
345 * block.
346 */
347 if (context->Message_Block_Index > 55)
348 {
349 context->Message_Block[context->Message_Block_Index++] = 0x80;
350 while(context->Message_Block_Index < 64)
351 {
352 context->Message_Block[context->Message_Block_Index++] = 0;
353 }
354
355 SHA1ProcessMessageBlock(context);
356
357 while(context->Message_Block_Index < 56)
358 {
359 context->Message_Block[context->Message_Block_Index++] = 0;
360 }
361 }
362 else
363 {
364 context->Message_Block[context->Message_Block_Index++] = 0x80;
365 while(context->Message_Block_Index < 56)
366 {
367 context->Message_Block[context->Message_Block_Index++] = 0;
368 }
369 }
370
371 /*
372 * Store the message length as the last 8 octets
373 */
374 context->Message_Block[56] = context->Length_High >> 24;
375 context->Message_Block[57] = context->Length_High >> 16;
376 context->Message_Block[58] = context->Length_High >> 8;
377 context->Message_Block[59] = context->Length_High;
378 context->Message_Block[60] = context->Length_Low >> 24;
379 context->Message_Block[61] = context->Length_Low >> 16;
380 context->Message_Block[62] = context->Length_Low >> 8;
381 context->Message_Block[63] = context->Length_Low;
382
383 SHA1ProcessMessageBlock(context);
384}
385#define SHA_DIGESTSIZE 20
386
387#define SHA_BLOCKSIZE 64
388
389static void truncate
390(
391 char* d1, /* data to be truncated */
392 char* d2, /* truncated data */
393 int len /* length in bytes to keep */
394)
395{
396 int i ;
397 for (i = 0 ; i < len ; i++) d2[i] = d1[i];
398}
399
400
401/* Function to compute the digest */
402void
403hmac_sha
404(
405 char* k, /* secret key */
406 int lk, /* length of the key in bytes */
407 char* d, /* data */
408 int ld, /* length of data in bytes */
409 char* out, /* output buffer, at least "t" bytes */
410 int t
411)
412{
413 SHA1Context ictx, octx ;
414 char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ;
415 char key[SHA_DIGESTSIZE] ;
416 char buf[SHA_BLOCKSIZE] ;
417 int i ;
418
419 if (lk > SHA_BLOCKSIZE) {
420
421 SHA1Context tctx ;
422
423 SHA1Reset(&tctx) ;
424 SHA1Input(&tctx, k, lk) ;
425 SHA1Result(&tctx, key) ;
426
427 k = key ;
428 lk = SHA_DIGESTSIZE ;
429 }
430
431 /**** Inner Digest ****/
432
433 SHA1Reset(&ictx) ;
434
435 /* Pad the key for inner digest */
436 for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ;
437 for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ;
438
439 SHA1Input(&ictx, buf, SHA_BLOCKSIZE) ;
440 SHA1Input(&ictx, d, ld) ;
441
442 SHA1Result(&ictx, isha) ;
443
444 /**** Outter Digest ****/
445
446 SHA1Reset(&octx) ;
447
448 /* Pad the key for outter digest */
449
450
451 for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ;
452 for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ;
453
454 SHA1Input(&octx, buf, SHA_BLOCKSIZE) ;
455 SHA1Input(&octx, isha, SHA_DIGESTSIZE) ;
456
457 SHA1Result(&octx, osha) ;
458
459 /* truncate and print the results */
460 t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ;
461 truncate(osha, out, t) ;
462
463}
diff --git a/tools/hmac-sha1.h b/tools/hmac-sha1.h
new file mode 100644
index 0000000000..149b5bac46
--- /dev/null
+++ b/tools/hmac-sha1.h
@@ -0,0 +1,84 @@
1/*
2 * sha1.h
3 *
4 * Description:
5 * This is the header file for code which implements the Secure
6 * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
7 * April 17, 1995.
8 *
9 * Many of the variable names in this code, especially the
10 * single character names, were used because those were the names
11 * used in the publication.
12 *
13 * Please read the file sha1.c for more information.
14 *
15 */
16
17#ifndef _SHA1_H_
18#define _SHA1_H_
19
20#include <stdint.h>
21/*
22 * If you do not have the ISO standard stdint.h header file, then you
23 * must typdef the following:
24 * name meaning
25 * uint32_t unsigned 32 bit integer
26 * uint8_t unsigned 8 bit integer (i.e., unsigned char)
27 * int_least16_t integer of >= 16 bits
28 *
29 */
30
31#ifndef _SHA_enum_
32#define _SHA_enum_
33enum
34{
35 shaSuccess = 0,
36 shaNull, /* Null pointer parameter */
37 shaInputTooLong, /* input data too long */
38 shaStateError /* called Input after Result */
39};
40#endif
41#define SHA1HashSize 20
42
43/*
44 * This structure will hold context information for the SHA-1
45 * hashing operation
46 */
47typedef struct SHA1Context
48{
49 uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
50
51 uint32_t Length_Low; /* Message length in bits */
52 uint32_t Length_High; /* Message length in bits */
53
54 /* Index into message block array */
55 int_least16_t Message_Block_Index;
56 uint8_t Message_Block[64]; /* 512-bit message blocks */
57
58 int Computed; /* Is the digest computed? */
59 int Corrupted; /* Is the message digest corrupted? */
60} SHA1Context;
61
62/*
63 * Function Prototypes
64 */
65
66int SHA1Reset( SHA1Context *);
67int SHA1Input( SHA1Context *,
68 const uint8_t *,
69 unsigned int);
70int SHA1Result( SHA1Context *,
71 uint8_t Message_Digest[SHA1HashSize]);
72
73void
74hmac_sha
75(
76 char* k,
77 int lk,
78 char* d,
79 int ld,
80 char* out,
81 int t
82);
83
84#endif
diff --git a/tools/scramble.c b/tools/scramble.c
index b49bde10a2..91f46be816 100644
--- a/tools/scramble.c
+++ b/tools/scramble.c
@@ -26,6 +26,7 @@
26#include "gigabeats.h" 26#include "gigabeats.h"
27#include "mi4.h" 27#include "mi4.h"
28#include "telechips.h" 28#include "telechips.h"
29#include "creative.h"
29#include "iaudio_bl_flash.h" 30#include "iaudio_bl_flash.h"
30 31
31int iaudio_encode(char *iname, char *oname, char *idstring); 32int iaudio_encode(char *iname, char *oname, char *idstring);
@@ -102,7 +103,7 @@ void usage(void)
102 "\t-ipod3g ipod firmware partition format (3rd Gen)\n" 103 "\t-ipod3g ipod firmware partition format (3rd Gen)\n"
103 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n" 104 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
104 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n" 105 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
105 "\t-zvm Zen Vision:M FRESCUE structure format\n" 106 "\t-creative=X Creative firmware structure format\n"
106 "\t-gigabeat Toshiba Gigabeat F/X format\n" 107 "\t-gigabeat Toshiba Gigabeat F/X format\n"
107 "\t-gigabeats Toshiba Gigabeat S format\n" 108 "\t-gigabeats Toshiba Gigabeat S format\n"
108 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n" 109 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
@@ -332,10 +333,21 @@ int main (int argc, char** argv)
332 oname = argv[3]; 333 oname = argv[3];
333 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */ 334 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
334 } 335 }
335 else if(!strcmp(argv[1], "-zvm")) { 336 else if(!strncmp(argv[1], "-creative=", 10)) {
336 iname = argv[2]; 337 iname = argv[2];
337 oname = argv[3]; 338 oname = argv[3];
338 return zvm_encode(iname, oname); 339 if(!strcmp(&argv[1][10], "zvm"))
340 return zvm_encode(iname, oname, ZENVISIONM);
341 else if(!strcmp(&argv[1][10], "zvm60"))
342 return zvm_encode(iname, oname, ZENVISIONM60);
343 else if(!strcmp(&argv[1][10], "zenvision"))
344 return zvm_encode(iname, oname, ZENVISION);
345 else if(!strcmp(&argv[1][10], "zenv"))
346 return zvm_encode(iname, oname, ZENV);
347 else {
348 fprintf(stderr, "unsupported Creative device: %s\n", &argv[1][10]);
349 return 2;
350 }
339 } 351 }
340 else if(!strncmp(argv[1], "-mi4", 4)) { 352 else if(!strncmp(argv[1], "-mi4", 4)) {
341 int mi4magic; 353 int mi4magic;
@@ -752,96 +764,3 @@ int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc)
752 return 0; 764 return 0;
753} 765}
754 766
755
756/* Create an Zen Vision:M FRESCUE structure file
757*/
758
759int zvm_encode(char *iname, char *oname)
760{
761 size_t len;
762 int length;
763 FILE *file;
764 unsigned int sum = 0;
765 unsigned char *outbuf;
766 int i;
767
768 file = fopen(iname, "rb");
769 if (!file) {
770 perror(iname);
771 return -1;
772 }
773 fseek(file,0,SEEK_END);
774 length = ftell(file);
775
776 fseek(file,0,SEEK_SET);
777
778 outbuf = malloc(length+0x18+0x10);
779
780 if ( !outbuf ) {
781 printf("out of memory!\n");
782 return -1;
783 }
784
785 len = fread(outbuf+0x18, 1, length, file);
786 if(len < length) {
787 perror(iname);
788 return -2;
789 }
790 fclose(file);
791
792 /* Calculate checksum for later use in header */
793 for(i=0; i<length; i+= 4)
794 sum += le2int(&outbuf[0x18+i]) + (le2int(&outbuf[0x18+i])>>16);
795
796 /* Clear the header area to zero */
797 memset(outbuf, 0, 0x18);
798
799 /* Header (EDOC) */
800 memcpy((char*)outbuf, "EDOC", 4);
801 /* Total Size */
802 int2le(length+0x20, &outbuf[0x4]);
803 /* 4 bytes of zero */
804
805 /* Address = 0x900000 */
806 int2le(0x900000, &outbuf[0xC]);
807 /* Size */
808 int2le(length, &outbuf[0x10]);
809 /* Checksum */
810 int2le(sum, &outbuf[0x14]);
811 outbuf[0x16] = 0;
812 outbuf[0x17] = 0;
813 /* Data starts here... */
814
815 /* Second block starts here ... */
816 /* Address = 0x0 */
817 /* Size */
818 int2le(0x4, &outbuf[0x18+length+0x4]);
819 /* Checksum */
820 outbuf[0x18+length+0x8] = 0xB7;
821 outbuf[0x18+length+0x9] = 0xD5;
822 /* Data: LDR PC, =0x900000 */
823 outbuf[0x18+length+0xC] = 0x18;
824 outbuf[0x18+length+0xD] = 0xF0;
825 outbuf[0x18+length+0xE] = 0x9F;
826 outbuf[0x18+length+0xF] = 0xE5;
827
828
829 file = fopen(oname, "wb");
830 if (!file) {
831 perror(oname);
832 return -3;
833 }
834
835 len = fwrite(outbuf, 1, length+0x28, file);
836 if(len < length+0x18) {
837 perror(oname);
838 return -4;
839 }
840
841 free(outbuf);
842
843 fclose(file);
844
845 return 0;
846}
847