summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \
generate_rocklatin mkboot ipod_fw codepages uclpack mi4 gigabeat database \
- lngdump telechips gigabeats mktccboot mknkboot rbspeexenc
+ lngdump telechips gigabeats creative hmac-sha1 mktccboot mknkboot rbspeexenc
all:
@echo "Run make in your build directory!"
-scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o iaudio_bl_flash.o
+scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o iaudio_bl_flash.o creative.o hmac-sha1.o
descramble: descramble.o iriver.o gigabeat.o
+scramble.o: scramble.c iriver.h mi4.h gigabeat.h telechips.h iaudio_bl_flash.h creative.h
-scramble.o: scramble.c iriver.h mi4.h gigabeat.h telechips.h iaudio_bl_flash.h
descramble.o: descramble.c iriver.h gigabeat.h
+creative.o: creative.c creative.h
+hmac-sha1.o: hmac-sha1.c hmac-sha1.h
iriver.o: iriver.c iriver.h
gigabeat.o: gigabeat.c gigabeat.h
gigabeats.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
target_id=35
modelname="creativezvm"
target="-DCREATIVE_ZVM"
- memory=32 # always
+ memory=64
arm926ejscc
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
bmp2rb_remotemono="$rootdir/tools/bmp2rb -f 0"
bmp2rb_remotenative="$rootdir/tools/bmp2rb -f 0"
+ tool="cp"
output="rockbox.zvm"
appextra="recorder:gui"
- plugins="yes"
+ plugins=""
swcodec="yes"
toolset=$gigabeatbitmaptools
- boottool="$rootdir/tools/scramble -zvm"
+ boottool="$rootdir/tools/scramble -creative=zvm"
bootoutput="rockbox.zvmboot"
# architecture, manufacturer and model for the target-tree build
t_cpu="arm"
@@ -1998,7 +1999,7 @@ sed > Makefile \
-e "s,@VOICETOOLSET@,${voicetoolset},g" \
-e "s,@LANGS@,${buildlangs},g" \
<<EOF
-## Automaticly generated. http://www.rockbox.org/
+## Automatically generated. http://www.rockbox.org/
ifndef V
SILENT=@
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "creative.h"
+#include "hmac-sha1.h"
+#include <stdio.h>
+#include <stdbool.h>
+
+/*
+Create a Zen Vision:M FRESCUE structure file
+*/
+
+
+static int make_ciff_file(char *inbuf, int length, char *outbuf, int device)
+{
+ memcpy(outbuf, "FFIC", 4);
+ int2le(length+90, &outbuf[4]);
+ memcpy(&outbuf[8], "FNIC", 4);
+ int2le(96, &outbuf[0xC]);
+ memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
+ memset(&outbuf[0x10+devices[device].cinf_size], 0, 96 - devices[device].cinf_size);
+ memcpy(&outbuf[0x70], "ATAD", 4);
+ int2le(length+32, &outbuf[0x74]);
+ memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m", 32); /*Unicode encoded*/
+ memcpy(&outbuf[0x98], inbuf, length);
+ memcpy(&outbuf[0x98+length], "LLUN", 4);
+ int2le(20, &outbuf[0x98+length+4]);
+ /* Do checksum */
+ char key[20];
+ hmac_sha((char*)devices[device].null, strlen(devices[device].null), outbuf, 0x98+length, key, 20);
+ memcpy(&outbuf[0x98+length+8], key, 20);
+ return length+0x90+0x1C+8;
+}
+
+static int make_jrm_file(char *inbuf, int length, char *outbuf)
+{
+ int i;
+ unsigned int sum = 0;
+ /* Calculate checksum for later use in header */
+ for(i=0; i<length; i+= 4)
+ sum += le2int(&inbuf[i]) + (le2int(&inbuf[i])>>16);
+
+ /* Clear the header area to zero */
+ memset(outbuf, 0, 0x18);
+
+ /* Header (EDOC) */
+ memcpy(outbuf, "EDOC", 4);
+ /* Total Size */
+ int2le(length+0x20, &outbuf[0x4]);
+ /* 4 bytes of zero */
+
+ /* Address = 0x900000 */
+ int2le(0x900000, &outbuf[0xC]);
+ /* Size */
+ int2le(length, &outbuf[0x10]);
+ /* Checksum */
+ int2le(sum, &outbuf[0x14]);
+ outbuf[0x16] = 0;
+ outbuf[0x17] = 0;
+ /* Data starts here... */
+ memcpy(&outbuf[0x18], inbuf, length);
+
+ /* Second block starts here ... */
+ /* Address = 0x0 */
+ /* Size */
+ int2le(0x4, &outbuf[0x18+length+0x4]);
+ /* Checksum */
+ outbuf[0x18+length+0x8] = 0xA9;
+ outbuf[0x18+length+0x9] = 0xD9;
+ /* Data: MOV PC, 0x900000 */
+ outbuf[0x18+length+0xC] = 0x09;
+ outbuf[0x18+length+0xD] = 0xF6;
+ outbuf[0x18+length+0xE] = 0xA0;
+ outbuf[0x18+length+0xF] = 0xE3;
+
+ return length+0x18+0x10;
+}
+
+int zvm_encode(char *iname, char *oname, int device)
+{
+ size_t len;
+ int length;
+ FILE *file;
+ unsigned char *outbuf;
+ unsigned char *buf;
+ int i;
+
+ file = fopen(iname, "rb");
+ if (!file) {
+ perror(iname);
+ return -1;
+ }
+ fseek(file, 0, SEEK_END);
+ length = ftell(file);
+
+ fseek(file, 0, SEEK_SET);
+
+ buf = (unsigned char*)malloc(length);
+ if ( !buf ) {
+ printf("out of memory!\n");
+ return -1;
+ }
+
+ len = fread(buf, 1, length, file);
+ if(len < length) {
+ perror(iname);
+ return -2;
+ }
+ fclose(file);
+
+ outbuf = (unsigned char*)malloc(length+0x300);
+ if ( !outbuf ) {
+ free(buf);
+ printf("out of memory!\n");
+ return -1;
+ }
+ length = make_jrm_file(buf, len, outbuf);
+ free(buf);
+ buf = (unsigned char*)malloc(length+0x200);
+ memset(buf, 0, length+0x200);
+ length = make_ciff_file(outbuf, length, buf, device);
+ free(outbuf);
+
+ file = fopen(oname, "wb");
+ if (!file) {
+ free(buf);
+ perror(oname);
+ return -3;
+ }
+
+ len = fwrite(buf, 1, length, file);
+ if(len < length) {
+ free(buf);
+ perror(oname);
+ return -4;
+ }
+
+ free(buf);
+
+ fclose(file);
+
+ return 0;
+}
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef CREATIVE_H_
+#define CREATIVE_H_
+
+enum
+{
+ ZENVISIONM = 0,
+ ZENVISIONM60 = 1,
+ ZENVISION = 2,
+ ZENV = 3
+};
+
+static struct device_info
+{
+ const char* cinf; /*Must be Unicode encoded*/
+ const int cinf_size;
+ const char* null;
+} device_info;
+
+static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
+static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
+static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
+static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
+
+static const struct device_info devices[] =
+{
+ {"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},
+ {"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},
+ {"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},
+ {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4}
+};
+
+int zvm_encode(char *iname, char *oname, int device);
+
+#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 @@
+/*
+ * sha1.c
+ *
+ * Description:
+ * This file implements the Secure Hashing Algorithm 1 as
+ * defined in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * The SHA-1, produces a 160-bit message digest for a given
+ * data stream. It should take about 2**n steps to find a
+ * message with the same digest as a given message and
+ * 2**(n/2) to find any two messages with the same digest,
+ * when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-1 is defined in terms of 32-bit "words". This code
+ * uses <stdint.h> (included via "sha1.h" to define 32 and 8
+ * bit unsigned integer types. If your C compiler does not
+ * support 32 bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-1 is designed to work with messages less than 2^64 bits
+ * long. Although SHA-1 allows a message digest to be generated
+ * for messages of any number of bits less than 2^64, this
+ * implementation only works with messages with a length that is
+ * a multiple of the size of an 8-bit character.
+ *
+ */
+
+#include "hmac-sha1.h"
+
+/*
+ * Define the SHA1 circular left shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/* Local Function Prototyptes */
+void SHA1PadMessage(SHA1Context *);
+void SHA1ProcessMessageBlock(SHA1Context *);
+
+/*
+ * SHA1Reset
+ *
+ * Description:
+ * This function will initialize the SHA1Context in preparation
+ * for computing a new SHA1 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Reset(SHA1Context *context)
+{
+ if (!context)
+ {
+ return shaNull;
+ }
+
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = 0x67452301;
+ context->Intermediate_Hash[1] = 0xEFCDAB89;
+ context->Intermediate_Hash[2] = 0x98BADCFE;
+ context->Intermediate_Hash[3] = 0x10325476;
+ context->Intermediate_Hash[4] = 0xC3D2E1F0;
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Result
+ *
+ * Description:
+ * This function will return the 160-bit message digest into the
+ * Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 19th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA-1 hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Result( SHA1Context *context,
+ uint8_t Message_Digest[SHA1HashSize])
+{
+ int i;
+
+ if (!context || !Message_Digest)
+ {
+ return shaNull;
+ }
+
+ if (context->Corrupted)
+ {
+ return context->Corrupted;
+ }
+
+ if (!context->Computed)
+ {
+ SHA1PadMessage(context);
+ for(i=0; i<64; ++i)
+ {
+ /* message may be sensitive, clear it out */
+ context->Message_Block[i] = 0;
+ }
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+ context->Computed = 1;
+ }
+
+ for(i = 0; i < SHA1HashSize; ++i)
+ {
+ Message_Digest[i] = context->Intermediate_Hash[i>>2]
+ >> 8 * ( 3 - ( i & 0x03 ) );
+ }
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Input( SHA1Context *context,
+ const uint8_t *message_array,
+ unsigned length)
+{
+ if (!length)
+ {
+ return shaSuccess;
+ }
+
+ if (!context || !message_array)
+ {
+ return shaNull;
+ }
+
+ if (context->Computed)
+ {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ {
+ return context->Corrupted;
+ }
+ while(length-- && !context->Corrupted)
+ {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ context->Length_Low += 8;
+ if (context->Length_Low == 0)
+ {
+ context->Length_High++;
+ if (context->Length_High == 0)
+ {
+ /* Message is too long */
+ context->Corrupted = 1;
+ }
+ }
+
+ if (context->Message_Block_Index == 64)
+ {
+ SHA1ProcessMessageBlock(context);
+ }
+
+ message_array++;
+ }
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1ProcessMessageBlock
+ *
+ * Description:
+ * This function will process the next 512 bits of the message
+ * stored in the Message_Block array.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the publication.
+ *
+ *
+ */
+void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+ const uint32_t K[] = { /* Constants defined in SHA-1 */
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int t; /* Loop counter */
+ uint32_t temp; /* Temporary word value */
+ uint32_t W[80]; /* Word sequence */
+ uint32_t A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for(t = 0; t < 16; t++)
+ {
+ W[t] = context->Message_Block[t * 4] << 24;
+ W[t] |= context->Message_Block[t * 4 + 1] << 16;
+ W[t] |= context->Message_Block[t * 4 + 2] << 8;
+ W[t] |= context->Message_Block[t * 4 + 3];
+ }
+
+ for(t = 16; t < 80; t++)
+ {
+ W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+
+ for(t = 0; t < 20; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 20; t < 40; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 40; t < 60; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 60; t < 80; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+
+ context->Message_Block_Index = 0;
+}
+
+
+/*
+ * SHA1PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64
+ * bits represent the length of the original message. All bits in
+ * between should be 0. This function will pad the message
+ * according to those rules by filling the Message_Block array
+ * accordingly. It will also call the ProcessMessageBlock function
+ * provided appropriately. When it returns, it can be assumed that
+ * the message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad
+ * ProcessMessageBlock: [in]
+ * The appropriate SHA*ProcessMessageBlock function
+ * Returns:
+ * Nothing.
+ *
+ */
+
+void SHA1PadMessage(SHA1Context *context)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index > 55)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 64)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+
+ SHA1ProcessMessageBlock(context);
+
+ while(context->Message_Block_Index < 56)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+ else
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 56)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = context->Length_High >> 24;
+ context->Message_Block[57] = context->Length_High >> 16;
+ context->Message_Block[58] = context->Length_High >> 8;
+ context->Message_Block[59] = context->Length_High;
+ context->Message_Block[60] = context->Length_Low >> 24;
+ context->Message_Block[61] = context->Length_Low >> 16;
+ context->Message_Block[62] = context->Length_Low >> 8;
+ context->Message_Block[63] = context->Length_Low;
+
+ SHA1ProcessMessageBlock(context);
+}
+#define SHA_DIGESTSIZE 20
+
+#define SHA_BLOCKSIZE 64
+
+static void truncate
+(
+ char* d1, /* data to be truncated */
+ char* d2, /* truncated data */
+ int len /* length in bytes to keep */
+)
+{
+ int i ;
+ for (i = 0 ; i < len ; i++) d2[i] = d1[i];
+}
+
+
+/* Function to compute the digest */
+void
+hmac_sha
+(
+ char* k, /* secret key */
+ int lk, /* length of the key in bytes */
+ char* d, /* data */
+ int ld, /* length of data in bytes */
+ char* out, /* output buffer, at least "t" bytes */
+ int t
+)
+{
+ SHA1Context ictx, octx ;
+ char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ;
+ char key[SHA_DIGESTSIZE] ;
+ char buf[SHA_BLOCKSIZE] ;
+ int i ;
+
+ if (lk > SHA_BLOCKSIZE) {
+
+ SHA1Context tctx ;
+
+ SHA1Reset(&tctx) ;
+ SHA1Input(&tctx, k, lk) ;
+ SHA1Result(&tctx, key) ;
+
+ k = key ;
+ lk = SHA_DIGESTSIZE ;
+ }
+
+ /**** Inner Digest ****/
+
+ SHA1Reset(&ictx) ;
+
+ /* Pad the key for inner digest */
+ for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ;
+ for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ;
+
+ SHA1Input(&ictx, buf, SHA_BLOCKSIZE) ;
+ SHA1Input(&ictx, d, ld) ;
+
+ SHA1Result(&ictx, isha) ;
+
+ /**** Outter Digest ****/
+
+ SHA1Reset(&octx) ;
+
+ /* Pad the key for outter digest */
+
+
+ for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ;
+ for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ;
+
+ SHA1Input(&octx, buf, SHA_BLOCKSIZE) ;
+ SHA1Input(&octx, isha, SHA_DIGESTSIZE) ;
+
+ SHA1Result(&octx, osha) ;
+
+ /* truncate and print the results */
+ t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ;
+ truncate(osha, out, t) ;
+
+}
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 @@
+/*
+ * sha1.h
+ *
+ * Description:
+ * This is the header file for code which implements the Secure
+ * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
+ * April 17, 1995.
+ *
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the names
+ * used in the publication.
+ *
+ * Please read the file sha1.c for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+#include <stdint.h>
+/*
+ * If you do not have the ISO standard stdint.h header file, then you
+ * must typdef the following:
+ * name meaning
+ * uint32_t unsigned 32 bit integer
+ * uint8_t unsigned 8 bit integer (i.e., unsigned char)
+ * int_least16_t integer of >= 16 bits
+ *
+ */
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+enum
+{
+ shaSuccess = 0,
+ shaNull, /* Null pointer parameter */
+ shaInputTooLong, /* input data too long */
+ shaStateError /* called Input after Result */
+};
+#endif
+#define SHA1HashSize 20
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation
+ */
+typedef struct SHA1Context
+{
+ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+ uint32_t Length_Low; /* Message length in bits */
+ uint32_t Length_High; /* Message length in bits */
+
+ /* Index into message block array */
+ int_least16_t Message_Block_Index;
+ uint8_t Message_Block[64]; /* 512-bit message blocks */
+
+ int Computed; /* Is the digest computed? */
+ int Corrupted; /* Is the message digest corrupted? */
+} SHA1Context;
+
+/*
+ * Function Prototypes
+ */
+
+int SHA1Reset( SHA1Context *);
+int SHA1Input( SHA1Context *,
+ const uint8_t *,
+ unsigned int);
+int SHA1Result( SHA1Context *,
+ uint8_t Message_Digest[SHA1HashSize]);
+
+void
+hmac_sha
+(
+ char* k,
+ int lk,
+ char* d,
+ int ld,
+ char* out,
+ int t
+);
+
+#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 @@
#include "gigabeats.h"
#include "mi4.h"
#include "telechips.h"
+#include "creative.h"
#include "iaudio_bl_flash.h"
int iaudio_encode(char *iname, char *oname, char *idstring);
@@ -102,7 +103,7 @@ void usage(void)
"\t-ipod3g ipod firmware partition format (3rd Gen)\n"
"\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
"\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
- "\t-zvm Zen Vision:M FRESCUE structure format\n"
+ "\t-creative=X Creative firmware structure format\n"
"\t-gigabeat Toshiba Gigabeat F/X format\n"
"\t-gigabeats Toshiba Gigabeat S format\n"
"\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
@@ -332,10 +333,21 @@ int main (int argc, char** argv)
oname = argv[3];
return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
}
- else if(!strcmp(argv[1], "-zvm")) {
+ else if(!strncmp(argv[1], "-creative=", 10)) {
iname = argv[2];
oname = argv[3];
- return zvm_encode(iname, oname);
+ if(!strcmp(&argv[1][10], "zvm"))
+ return zvm_encode(iname, oname, ZENVISIONM);
+ else if(!strcmp(&argv[1][10], "zvm60"))
+ return zvm_encode(iname, oname, ZENVISIONM60);
+ else if(!strcmp(&argv[1][10], "zenvision"))
+ return zvm_encode(iname, oname, ZENVISION);
+ else if(!strcmp(&argv[1][10], "zenv"))
+ return zvm_encode(iname, oname, ZENV);
+ else {
+ fprintf(stderr, "unsupported Creative device: %s\n", &argv[1][10]);
+ return 2;
+ }
}
else if(!strncmp(argv[1], "-mi4", 4)) {
int mi4magic;
@@ -752,96 +764,3 @@ int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc)
return 0;
}
-
-/* Create an Zen Vision:M FRESCUE structure file
-*/
-
-int zvm_encode(char *iname, char *oname)
-{
- size_t len;
- int length;
- FILE *file;
- unsigned int sum = 0;
- unsigned char *outbuf;
- int i;
-
- file = fopen(iname, "rb");
- if (!file) {
- perror(iname);
- return -1;
- }
- fseek(file,0,SEEK_END);
- length = ftell(file);
-
- fseek(file,0,SEEK_SET);
-
- outbuf = malloc(length+0x18+0x10);
-
- if ( !outbuf ) {
- printf("out of memory!\n");
- return -1;
- }
-
- len = fread(outbuf+0x18, 1, length, file);
- if(len < length) {
- perror(iname);
- return -2;
- }
- fclose(file);
-
- /* Calculate checksum for later use in header */
- for(i=0; i<length; i+= 4)
- sum += le2int(&outbuf[0x18+i]) + (le2int(&outbuf[0x18+i])>>16);
-
- /* Clear the header area to zero */
- memset(outbuf, 0, 0x18);
-
- /* Header (EDOC) */
- memcpy((char*)outbuf, "EDOC", 4);
- /* Total Size */
- int2le(length+0x20, &outbuf[0x4]);
- /* 4 bytes of zero */
-
- /* Address = 0x900000 */
- int2le(0x900000, &outbuf[0xC]);
- /* Size */
- int2le(length, &outbuf[0x10]);
- /* Checksum */
- int2le(sum, &outbuf[0x14]);
- outbuf[0x16] = 0;
- outbuf[0x17] = 0;
- /* Data starts here... */
-
- /* Second block starts here ... */
- /* Address = 0x0 */
- /* Size */
- int2le(0x4, &outbuf[0x18+length+0x4]);
- /* Checksum */
- outbuf[0x18+length+0x8] = 0xB7;
- outbuf[0x18+length+0x9] = 0xD5;
- /* Data: LDR PC, =0x900000 */
- outbuf[0x18+length+0xC] = 0x18;
- outbuf[0x18+length+0xD] = 0xF0;
- outbuf[0x18+length+0xE] = 0x9F;
- outbuf[0x18+length+0xF] = 0xE5;
-
-
- file = fopen(oname, "wb");
- if (!file) {
- perror(oname);
- return -3;
- }
-
- len = fwrite(outbuf, 1, length+0x28, file);
- if(len < length+0x18) {
- perror(oname);
- return -4;
- }
-
- free(outbuf);
-
- fclose(file);
-
- return 0;
-}
-