forked from len0rd/rockbox
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
This commit is contained in:
parent
5a3651bf94
commit
e810721e72
7 changed files with 784 additions and 103 deletions
|
|
@ -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
|
||||
|
|
|
|||
9
tools/configure
vendored
9
tools/configure
vendored
|
|
@ -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=@
|
||||
|
|
|
|||
159
tools/creative.c
Normal file
159
tools/creative.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
53
tools/creative.h
Normal file
53
tools/creative.h
Normal file
|
|
@ -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_*/
|
||||
463
tools/hmac-sha1.c
Normal file
463
tools/hmac-sha1.c
Normal file
|
|
@ -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) ;
|
||||
|
||||
}
|
||||
84
tools/hmac-sha1.h
Normal file
84
tools/hmac-sha1.h
Normal file
|
|
@ -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
|
||||
111
tools/scramble.c
111
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue