This commit is contained in:
Nekotekina 2014-03-31 00:43:44 +04:00
commit 2d955dc297
25 changed files with 2923 additions and 854 deletions

View File

@ -1,7 +1,7 @@
/*
* FIPS-197 compliant AES implementation
*
* Copyright (C) 2006-2010, Brainspark B.V.
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@ -35,18 +35,18 @@
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i) \
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] ) \
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i) \
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
@ -55,6 +55,7 @@
}
#endif
#if defined(POLARSSL_AES_ROM_TABLES)
/*
* Forward S-box
*/
@ -165,19 +166,19 @@ static const unsigned char FSb[256] =
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
#define V(a,b,c,d) 0x##a##b##c##d
static const unsigned long FT0[256] = { FT };
static const uint32_t FT0[256] = { FT };
#undef V
#define V(a,b,c,d) 0x##b##c##d##a
static const unsigned long FT1[256] = { FT };
static const uint32_t FT1[256] = { FT };
#undef V
#define V(a,b,c,d) 0x##c##d##a##b
static const unsigned long FT2[256] = { FT };
static const uint32_t FT2[256] = { FT };
#undef V
#define V(a,b,c,d) 0x##d##a##b##c
static const unsigned long FT3[256] = { FT };
static const uint32_t FT3[256] = { FT };
#undef V
#undef FT
@ -292,19 +293,19 @@ static const unsigned char RSb[256] =
V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
#define V(a,b,c,d) 0x##a##b##c##d
static const unsigned long RT0[256] = { RT };
static const uint32_t RT0[256] = { RT };
#undef V
#define V(a,b,c,d) 0x##b##c##d##a
static const unsigned long RT1[256] = { RT };
static const uint32_t RT1[256] = { RT };
#undef V
#define V(a,b,c,d) 0x##c##d##a##b
static const unsigned long RT2[256] = { RT };
static const uint32_t RT2[256] = { RT };
#undef V
#define V(a,b,c,d) 0x##d##a##b##c
static const unsigned long RT3[256] = { RT };
static const uint32_t RT3[256] = { RT };
#undef V
#undef RT
@ -312,20 +313,141 @@ static const unsigned long RT3[256] = { RT };
/*
* Round constants
*/
static const unsigned long RCON[10] =
static const uint32_t RCON[10] =
{
0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x0000001B, 0x00000036
};
#else
/*
* Forward S-box & tables
*/
static unsigned char FSb[256];
static uint32_t FT0[256];
static uint32_t FT1[256];
static uint32_t FT2[256];
static uint32_t FT3[256];
/*
* Reverse S-box & tables
*/
static unsigned char RSb[256];
static uint32_t RT0[256];
static uint32_t RT1[256];
static uint32_t RT2[256];
static uint32_t RT3[256];
/*
* Round constants
*/
static uint32_t RCON[10];
/*
* Tables generation code
*/
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
static int aes_init_done = 0;
static void aes_gen_tables( void )
{
int i, x, y, z;
int pow[256];
int log[256];
/*
* compute pow and log tables over GF(2^8)
*/
for( i = 0, x = 1; i < 256; i++ )
{
pow[i] = x;
log[x] = i;
x = ( x ^ XTIME( x ) ) & 0xFF;
}
/*
* calculate the round constants
*/
for( i = 0, x = 1; i < 10; i++ )
{
RCON[i] = (uint32_t) x;
x = XTIME( x ) & 0xFF;
}
/*
* generate the forward and reverse S-boxes
*/
FSb[0x00] = 0x63;
RSb[0x63] = 0x00;
for( i = 1; i < 256; i++ )
{
x = pow[255 - log[i]];
y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
x ^= y ^ 0x63;
FSb[i] = (unsigned char) x;
RSb[x] = (unsigned char) i;
}
/*
* generate the forward and reverse tables
*/
for( i = 0; i < 256; i++ )
{
x = FSb[i];
y = XTIME( x ) & 0xFF;
z = ( y ^ x ) & 0xFF;
FT0[i] = ( (uint32_t) y ) ^
( (uint32_t) x << 8 ) ^
( (uint32_t) x << 16 ) ^
( (uint32_t) z << 24 );
FT1[i] = ROTL8( FT0[i] );
FT2[i] = ROTL8( FT1[i] );
FT3[i] = ROTL8( FT2[i] );
x = RSb[i];
RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
( (uint32_t) MUL( 0x09, x ) << 8 ) ^
( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
( (uint32_t) MUL( 0x0B, x ) << 24 );
RT1[i] = ROTL8( RT0[i] );
RT2[i] = ROTL8( RT1[i] );
RT3[i] = ROTL8( RT2[i] );
}
}
#endif
/*
* AES key schedule (encryption)
*/
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
{
unsigned int i;
unsigned long *RK;
uint32_t *RK;
#if !defined(POLARSSL_AES_ROM_TABLES)
if( aes_init_done == 0 )
{
aes_gen_tables();
aes_init_done = 1;
}
#endif
switch( keysize )
{
@ -339,7 +461,7 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
for( i = 0; i < (keysize >> 5); i++ )
{
GET_ULONG_LE( RK[i], key, i << 2 );
GET_UINT32_LE( RK[i], key, i << 2 );
}
switch( ctx->nr )
@ -349,10 +471,10 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
for( i = 0; i < 10; i++, RK += 4 )
{
RK[4] = RK[0] ^ RCON[i] ^
( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
RK[5] = RK[1] ^ RK[4];
RK[6] = RK[2] ^ RK[5];
@ -365,10 +487,10 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
for( i = 0; i < 8; i++, RK += 6 )
{
RK[6] = RK[0] ^ RCON[i] ^
( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
RK[7] = RK[1] ^ RK[6];
RK[8] = RK[2] ^ RK[7];
@ -383,20 +505,20 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
for( i = 0; i < 7; i++, RK += 8 )
{
RK[8] = RK[0] ^ RCON[i] ^
( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
RK[9] = RK[1] ^ RK[8];
RK[10] = RK[2] ^ RK[9];
RK[11] = RK[3] ^ RK[10];
RK[12] = RK[4] ^
( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
RK[13] = RK[5] ^ RK[12];
RK[14] = RK[6] ^ RK[13];
@ -419,8 +541,8 @@ int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int key
{
int i, j;
aes_context cty;
unsigned long *RK;
unsigned long *SK;
uint32_t *RK;
uint32_t *SK;
int ret;
switch( keysize )
@ -520,14 +642,14 @@ int aes_crypt_ecb( aes_context *ctx,
unsigned char output[16] )
{
int i;
unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
RK = ctx->rk;
GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++;
GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++;
GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++;
GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++;
GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++;
GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++;
GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
if( mode == AES_DECRYPT )
{
@ -540,28 +662,28 @@ int aes_crypt_ecb( aes_context *ctx,
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
X0 = *RK++ ^ \
( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
X1 = *RK++ ^ \
( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
X2 = *RK++ ^ \
( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
X3 = *RK++ ^ \
( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
}
else /* AES_ENCRYPT */
{
@ -574,34 +696,34 @@ int aes_crypt_ecb( aes_context *ctx,
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
X0 = *RK++ ^ \
( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
X1 = *RK++ ^ \
( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
X2 = *RK++ ^ \
( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
X3 = *RK++ ^ \
( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
}
PUT_ULONG_LE( X0, output, 0 );
PUT_ULONG_LE( X1, output, 4 );
PUT_ULONG_LE( X2, output, 8 );
PUT_ULONG_LE( X3, output, 12 );
PUT_UINT32_LE( X0, output, 0 );
PUT_UINT32_LE( X1, output, 4 );
PUT_UINT32_LE( X2, output, 8 );
PUT_UINT32_LE( X3, output, 12 );
return( 0 );
}
@ -658,6 +780,52 @@ int aes_crypt_cbc( aes_context *ctx,
return( 0 );
}
/*
* AES-CFB128 buffer encryption/decryption
*/
int aes_crypt_cfb128( aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int c;
size_t n = *iv_off;
if( mode == AES_DECRYPT )
{
while( length-- )
{
if( n == 0 )
aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
c = *input++;
*output++ = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
n = (n + 1) & 0x0F;
}
}
else
{
while( length-- )
{
if( n == 0 )
aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
n = (n + 1) & 0x0F;
}
}
*iv_off = n;
return( 0 );
}
/*
* AES-CTR buffer encryption/decryption
*/
@ -669,7 +837,7 @@ int aes_crypt_ctr( aes_context *ctx,
const unsigned char *input,
unsigned char *output )
{
int c, i, cb;
int c, i;
size_t n = *nc_off;
while( length-- )
@ -677,12 +845,9 @@ int aes_crypt_ctr( aes_context *ctx,
if( n == 0 ) {
aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
i = 15;
do {
nonce_counter[i]++;
cb = nonce_counter[i] == 0;
} while( i-- && cb );
for( i = 16; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break;
}
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
@ -694,3 +859,117 @@ int aes_crypt_ctr( aes_context *ctx,
return( 0 );
}
/* AES-CMAC */
unsigned char const_Rb[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
};
unsigned char const_Zero[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void leftshift_onebit(unsigned char *input, unsigned char *output)
{
int i;
unsigned char overflow = 0;
for (i = 15; i >= 0; i--)
{
output[i] = input[i] << 1;
output[i] |= overflow;
overflow = (input[i] & 0x80) ? 1 : 0;
}
}
void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
{
int i;
for (i = 0; i < 16; i++)
out[i] = a[i] ^ b[i];
}
void generate_subkey(aes_context *ctx, unsigned char *K1, unsigned char *K2)
{
unsigned char L[16];
unsigned char Z[16];
unsigned char tmp[16];
int i;
for (i = 0; i < 16; i++) Z[i] = 0;
aes_crypt_ecb(ctx, AES_ENCRYPT, Z, L);
if ((L[0] & 0x80) == 0)
{
leftshift_onebit(L,K1);
} else {
leftshift_onebit(L,tmp);
xor_128(tmp,const_Rb,K1);
}
if ((K1[0] & 0x80) == 0)
{
leftshift_onebit(K1,K2);
} else {
leftshift_onebit(K1,tmp);
xor_128(tmp,const_Rb,K2);
}
}
void padding (unsigned char *lastb, unsigned char *pad, int length)
{
int i;
for (i = 0; i < 16; i++)
{
if (i < length)
pad[i] = lastb[i];
else if (i == length)
pad[i] = 0x80;
else
pad[i] = 0x00;
}
}
void aes_cmac(aes_context *ctx, int length, unsigned char *input, unsigned char *output)
{
unsigned char X[16], Y[16], M_last[16], padded[16];
unsigned char K1[16], K2[16];
int n, i, flag;
generate_subkey(ctx, K1, K2);
n = (length + 15) / 16;
if (n == 0)
{
n = 1;
flag = 0;
} else {
if ((length % 16) == 0)
flag = 1;
else
flag = 0;
}
if (flag)
{
xor_128(&input[16 * (n - 1)], K1, M_last);
} else {
padding(&input[16 * (n - 1)], padded, length % 16);
xor_128(padded, K2, M_last);
}
for (i = 0; i < 16; i++) X[i] = 0;
for (i = 0; i < n - 1; i++)
{
xor_128(X, &input[16*i], Y);
aes_crypt_ecb(ctx, AES_ENCRYPT, Y, X);
}
xor_128(X,M_last,Y);
aes_crypt_ecb(ctx, AES_ENCRYPT, Y, X);
for (i = 0; i < 16; i++)
output[i] = X[i];
}

View File

@ -3,7 +3,7 @@
*
* \brief AES block cipher
*
* Copyright (C) 2006-2010, Brainspark B.V.
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@ -24,25 +24,32 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_AES_H
#define POLARSSL_AES_H
#include <string.h>
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
// Regular implementation
//
/**
* \brief AES context structure
*/
typedef struct
{
int nr; /*!< number of rounds */
unsigned long *rk; /*!< AES round keys */
unsigned long buf[68]; /*!< unaligned data */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
}
aes_context;
@ -108,7 +115,33 @@ int aes_crypt_cbc( aes_context *ctx,
const unsigned char *input,
unsigned char *output );
/*
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* both
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int aes_crypt_cfb128( aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
@ -137,8 +170,8 @@ int aes_crypt_ctr( aes_context *ctx,
const unsigned char *input,
unsigned char *output );
void aes_cmac(aes_context *ctx, int length, unsigned char *input, unsigned char *output);
#ifdef __cplusplus
}
#endif
#endif /* aes.h */
#endif

View File

@ -682,7 +682,7 @@ SELF_KEY KeyVault::GetSelfLV1Key(u64 version)
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
for(int i = 0; i < sk_LV1_arr.GetCount(); i++)
for(unsigned int i = 0; i < sk_LV1_arr.GetCount(); i++)
{
if (sk_LV1_arr[i].version == version)
{
@ -698,7 +698,7 @@ SELF_KEY KeyVault::GetSelfLV2Key(u64 version)
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
for(int i = 0; i < sk_LV2_arr.GetCount(); i++)
for(unsigned int i = 0; i < sk_LV2_arr.GetCount(); i++)
{
if (sk_LV2_arr[i].version == version)
{
@ -714,7 +714,7 @@ SELF_KEY KeyVault::GetSelfISOKey(u16 revision, u64 version)
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
for(int i = 0; i < sk_ISO_arr.GetCount(); i++)
for(unsigned int i = 0; i < sk_ISO_arr.GetCount(); i++)
{
if ((sk_ISO_arr[i].version == version) &&
(sk_ISO_arr[i].revision == revision))
@ -731,7 +731,7 @@ SELF_KEY KeyVault::GetSelfAPPKey(u16 revision)
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
for(int i = 0; i < sk_APP_arr.GetCount(); i++)
for(unsigned int i = 0; i < sk_APP_arr.GetCount(); i++)
{
if (sk_APP_arr[i].revision == revision)
{
@ -747,7 +747,7 @@ SELF_KEY KeyVault::GetSelfUNK7Key(u64 version)
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
for(int i = 0; i < sk_UNK7_arr.GetCount(); i++)
for(unsigned int i = 0; i < sk_UNK7_arr.GetCount(); i++)
{
if (sk_UNK7_arr[i].version == version)
{
@ -763,7 +763,7 @@ SELF_KEY KeyVault::GetSelfNPDRMKey(u16 revision)
{
SELF_KEY key(0, 0, 0, "", "", "", "", 0);
for(int i = 0; i < sk_NPDRM_arr.GetCount(); i++)
for(unsigned int i = 0; i < sk_NPDRM_arr.GetCount(); i++)
{
if (sk_NPDRM_arr[i].revision == revision)
{
@ -831,8 +831,8 @@ u8 *KeyVault::GetKlicenseeKey()
{
return klicensee_key;
}
void KeyVault::RapToRif(unsigned char* rap, unsigned char* rif)
void rap_to_rif(unsigned char* rap, unsigned char* rif)
{
int i;
int round;

View File

@ -1,5 +1,4 @@
#pragma once
#include "aes.h"
#include "utils.h"
enum SELF_KEY_TYPE {
@ -36,41 +35,85 @@ struct SELF_KEY {
}
};
static const u8 PKG_AES_KEY[0x10] = {
static u8 PKG_AES_KEY[0x10] = {
0x2e, 0x7b, 0x71, 0xd7, 0xc9, 0xc9, 0xa1, 0x4e, 0xa3, 0x22, 0x1f, 0x18, 0x88, 0x28, 0xb8, 0xf8
};
static const u8 NP_IDPS[0x10] = {
static u8 NP_IDPS[0x10] = {
0x5E, 0x06, 0xE0, 0x4F, 0xD9, 0x4A, 0x71, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
static const u8 NP_KLIC_FREE[0x10] = {
static u8 NP_KLIC_FREE[0x10] = {
0x72, 0xF9, 0x90, 0x78, 0x8F, 0x9C, 0xFF, 0x74, 0x57, 0x25, 0xF0, 0x8E, 0x4C, 0x12, 0x83, 0x87
};
static const u8 NP_KLIC_KEY[0x10] = {
static u8 NP_OMAC_KEY_2[0x10] = {
0x6B, 0xA5, 0x29, 0x76, 0xEF, 0xDA, 0x16, 0xEF, 0x3C, 0x33, 0x9F, 0xB2, 0x97, 0x1E, 0x25, 0x6B
};
static u8 NP_OMAC_KEY_3[0x10] = {
0x9B, 0x51, 0x5F, 0xEA, 0xCF, 0x75, 0x06, 0x49, 0x81, 0xAA, 0x60, 0x4D, 0x91, 0xA5, 0x4E, 0x97
};
static u8 NP_KLIC_KEY[0x10] = {
0xF2, 0xFB, 0xCA, 0x7A, 0x75, 0xB0, 0x4E, 0xDC, 0x13, 0x90, 0x63, 0x8C, 0xCD, 0xFD, 0xD1, 0xEE
};
static const u8 NP_RIF_KEY[0x10] = {
static u8 NP_RIF_KEY[0x10] = {
0xDA, 0x7D, 0x4B, 0x5E, 0x49, 0x9A, 0x4F, 0x53, 0xB1, 0xC1, 0xA1, 0x4A, 0x74, 0x84, 0x44, 0x3B
};
static const u8 RAP_KEY[0x10] = {
static u8 NP_PSP_KEY_1[0x10] = {
0x2A, 0x6A, 0xFB, 0xCF, 0x43, 0xD1, 0x57, 0x9F, 0x7D, 0x73, 0x87, 0x41, 0xA1, 0x3B, 0xD4, 0x2E
};
static u8 NP_PSP_KEY_2[0x10] = {
0x0D, 0xB8, 0x57, 0x32, 0x36, 0x6C, 0xD7, 0x34, 0xFC, 0x87, 0x9E, 0x74, 0x33, 0x43, 0xBB, 0x4F
};
static u8 NP_PSX_KEY[0x10] = {
0x52, 0xC0, 0xB5, 0xCA, 0x76, 0xD6, 0x13, 0x4B, 0xB4, 0x5F, 0xC6, 0x6C, 0xA6, 0x37, 0xF2, 0xC1
};
static u8 RAP_KEY[0x10] = {
0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF
};
static const u8 RAP_PBOX[0x10] = {
static u8 RAP_PBOX[0x10] = {
0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09
};
static const u8 RAP_E1[0x10] = {
static u8 RAP_E1[0x10] = {
0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5
};
static const u8 RAP_E2[0x10] = {
static u8 RAP_E2[0x10] = {
0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74
};
static u8 SDAT_KEY[0x10] = {
0x0D, 0x65, 0x5E, 0xF8, 0xE6, 0x74, 0xA9, 0x8A, 0xB8, 0x50, 0x5C, 0xFA, 0x7D, 0x01, 0x29, 0x33
};
static u8 EDAT_KEY_0[0x10] = {
0xBE, 0x95, 0x9C, 0xA8, 0x30, 0x8D, 0xEF, 0xA2, 0xE5, 0xE1, 0x80, 0xC6, 0x37, 0x12, 0xA9, 0xAE
};
static u8 EDAT_HASH_0[0x10] = {
0xEF, 0xFE, 0x5B, 0xD1, 0x65, 0x2E, 0xEB, 0xC1, 0x19, 0x18, 0xCF, 0x7C, 0x04, 0xD4, 0xF0, 0x11
};
static u8 EDAT_KEY_1[0x10] = {
0x4C, 0xA9, 0xC1, 0x4B, 0x01, 0xC9, 0x53, 0x09, 0x96, 0x9B, 0xEC, 0x68, 0xAA, 0x0B, 0xC0, 0x81
};
static u8 EDAT_HASH_1[0x10] = {
0x3D, 0x92, 0x69, 0x9B, 0x70, 0x5B, 0x07, 0x38, 0x54, 0xD8, 0xFC, 0xC6, 0xC7, 0x67, 0x27, 0x47
};
static u8 EDAT_IV[0x10] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
class KeyVault
{
@ -89,7 +132,6 @@ public:
SELF_KEY FindSelfKey(u32 type, u16 revision, u64 version);
void SetKlicenseeKey(u8 *key);
u8 *GetKlicenseeKey();
void RapToRif(unsigned char* rap, unsigned char* rif);
private:
void LoadSelfLV0Keys();
@ -108,4 +150,7 @@ private:
SELF_KEY GetSelfAPPKey(u16 revision);
SELF_KEY GetSelfUNK7Key(u64 version);
SELF_KEY GetSelfNPDRMKey(u16 revision);
};
};
// RAP to RIF function.
void rap_to_rif(unsigned char* rap, unsigned char* rif);

View File

@ -1,400 +1,396 @@
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "stdafx.h"
#include "sha1.h"
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_ULONG_BE
#define GET_ULONG_BE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
| ( (unsigned long) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_ULONG_BE
#define PUT_ULONG_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-1 context setup
*/
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
static void sha1_process( sha1_context *ctx, const unsigned char data[64] )
{
unsigned long temp, W[16], A, B, C, D, E;
GET_ULONG_BE( W[ 0], data, 0 );
GET_ULONG_BE( W[ 1], data, 4 );
GET_ULONG_BE( W[ 2], data, 8 );
GET_ULONG_BE( W[ 3], data, 12 );
GET_ULONG_BE( W[ 4], data, 16 );
GET_ULONG_BE( W[ 5], data, 20 );
GET_ULONG_BE( W[ 6], data, 24 );
GET_ULONG_BE( W[ 7], data, 28 );
GET_ULONG_BE( W[ 8], data, 32 );
GET_ULONG_BE( W[ 9], data, 36 );
GET_ULONG_BE( W[10], data, 40 );
GET_ULONG_BE( W[11], data, 44 );
GET_ULONG_BE( W[12], data, 48 );
GET_ULONG_BE( W[13], data, 52 );
GET_ULONG_BE( W[14], data, 56 );
GET_ULONG_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
unsigned long left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (unsigned long) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (unsigned long) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned long last, padn;
unsigned long high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_ULONG_BE( high, msglen, 0 );
PUT_ULONG_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, (unsigned char *) sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_ULONG_BE( ctx->state[0], output, 0 );
PUT_ULONG_BE( ctx->state[1], output, 4 );
PUT_ULONG_BE( ctx->state[2], output, 8 );
PUT_ULONG_BE( ctx->state[3], output, 12 );
PUT_ULONG_BE( ctx->state[4], output, 16 );
}
/*
* output = SHA-1( input buffer )
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
/*
* SHA-1 HMAC context setup
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
{
size_t i;
unsigned char sum[20];
if( keylen > 64 )
{
sha1( key, keylen, sum );
keylen = 20;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-1 HMAC process buffer
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
sha1_update( ctx, input, ilen );
}
/*
* SHA-1 HMAC final digest
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned char tmpbuf[20];
sha1_finish( ctx, tmpbuf );
sha1_starts( ctx );
sha1_update( ctx, ctx->opad, 64 );
sha1_update( ctx, tmpbuf, 20 );
sha1_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* SHA1 HMAC context reset
*/
void sha1_hmac_reset( sha1_context *ctx )
{
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
}
/*
* output = HMAC-SHA-1( hmac key, input buffer )
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] )
{
sha1_context ctx;
sha1_hmac_starts( &ctx, key, keylen );
sha1_hmac_update( &ctx, input, ilen );
sha1_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
/*
* FIPS-180-1 compliant SHA-1 implementation
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include "stdafx.h"
#include "sha1.h"
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/*
* SHA-1 context setup
*/
void sha1_starts( sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void sha1_process( sha1_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen <= 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
sha1_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
sha1_update( ctx, sha1_padding, padn );
sha1_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
}
/*
* output = SHA-1( input buffer )
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
{
sha1_context ctx;
sha1_starts( &ctx );
sha1_update( &ctx, input, ilen );
sha1_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}
/*
* SHA-1 HMAC context setup
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
{
size_t i;
unsigned char sum[20];
if( keylen > 64 )
{
sha1( key, keylen, sum );
keylen = 20;
key = sum;
}
memset( ctx->ipad, 0x36, 64 );
memset( ctx->opad, 0x5C, 64 );
for( i = 0; i < keylen; i++ )
{
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
/*
* SHA-1 HMAC process buffer
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
{
sha1_update( ctx, input, ilen );
}
/*
* SHA-1 HMAC final digest
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
{
unsigned char tmpbuf[20];
sha1_finish( ctx, tmpbuf );
sha1_starts( ctx );
sha1_update( ctx, ctx->opad, 64 );
sha1_update( ctx, tmpbuf, 20 );
sha1_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
/*
* SHA1 HMAC context reset
*/
void sha1_hmac_reset( sha1_context *ctx )
{
sha1_starts( ctx );
sha1_update( ctx, ctx->ipad, 64 );
}
/*
* output = HMAC-SHA-1( hmac key, input buffer )
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] )
{
sha1_context ctx;
sha1_hmac_starts( &ctx, key, keylen );
sha1_hmac_update( &ctx, input, ilen );
sha1_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( sha1_context ) );
}

View File

@ -1,133 +1,161 @@
/**
* \file sha1.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_SHA1_H
#define POLARSSL_SHA1_H
#include <string.h>
/**
* \brief SHA-1 context structure
*/
typedef struct
{
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
sha1_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void sha1_starts( sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
/**
* \brief SHA-1 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-1 HMAC checksum result
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void sha1_hmac_reset( sha1_context *ctx );
/**
* \brief Output = HMAC-SHA-1( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-1 result
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] );
#ifdef __cplusplus
}
#endif
#endif /* sha1.h */
/**
* \file sha1.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif
#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
// Regular implementation
//
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
sha1_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void sha1_starts( sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void sha1_finish( sha1_context *ctx, unsigned char output[20] );
/* Internal use */
void sha1_process( sha1_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Output = SHA-1( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-1 checksum result
*/
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
/**
* \brief Output = SHA-1( file contents )
*
* \param path input file name
* \param output SHA-1 checksum result
*
* \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
*/
int sha1_file( const char *path, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
/**
* \brief SHA-1 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 HMAC final digest
*
* \param ctx HMAC context
* \param output SHA-1 HMAC checksum result
*/
void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
/**
* \brief SHA-1 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void sha1_hmac_reset( sha1_context *ctx );
/**
* \brief Output = HMAC-SHA-1( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-SHA-1 result
*/
void sha1_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[20] );
#ifdef __cplusplus
}
#endif

673
rpcs3/Crypto/unedat.cpp Normal file
View File

@ -0,0 +1,673 @@
#include "stdafx.h"
#include "unedat.h"
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
{
int mode = (int) (crypto_mode & 0xF0000000);
switch (mode) {
case 0x10000000:
// Encrypted ERK.
// Decrypt the key with EDAT_KEY + EDAT_IV and copy the original IV.
aescbc128_decrypt(version ? EDAT_KEY_1 : EDAT_KEY_0, EDAT_IV, key, key_final, 0x10);
memcpy(iv_final, iv, 0x10);
break;
case 0x20000000:
// Default ERK.
// Use EDAT_KEY and EDAT_IV.
memcpy(key_final, version ? EDAT_KEY_1 : EDAT_KEY_0, 0x10);
memcpy(iv_final, EDAT_IV, 0x10);
break;
case 0x00000000:
// Unencrypted ERK.
// Use the original key and iv.
memcpy(key_final, key, 0x10);
memcpy(iv_final, iv, 0x10);
break;
};
}
void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsigned char *hash)
{
int mode = (int) (hash_mode & 0xF0000000);
switch (mode) {
case 0x10000000:
// Encrypted HASH.
// Decrypt the hash with EDAT_KEY + EDAT_IV.
aescbc128_decrypt(version ? EDAT_KEY_1 : EDAT_KEY_0, EDAT_IV, hash, hash_final, 0x10);
break;
case 0x20000000:
// Default HASH.
// Use EDAT_HASH.
memcpy(hash_final, version ? EDAT_HASH_1 : EDAT_HASH_0, 0x10);
break;
case 0x00000000:
// Unencrypted ERK.
// Use the original hash.
memcpy(hash_final, hash, 0x10);
break;
};
}
bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int lenght, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
{
// Setup buffers for key, iv and hash.
unsigned char key_final[0x10] = {};
unsigned char iv_final[0x10] = {};
unsigned char hash_final_10[0x10] = {};
unsigned char hash_final_14[0x14] = {};
// Generate crypto key and hash.
generate_key(crypto_mode, version, key_final, iv_final, key, iv);
if ((hash_mode & 0xFF) == 0x01)
generate_hash(hash_mode, version, hash_final_14, hash);
else
generate_hash(hash_mode, version, hash_final_10, hash);
if ((crypto_mode & 0xFF) == 0x01) // No algorithm.
{
memcpy(out, in, lenght);
}
else if ((crypto_mode & 0xFF) == 0x02) // AES128-CBC
{
aescbc128_decrypt(key_final, iv_final, in, out, lenght);
}
else
{
ConLog.Error("EDAT: Unknown crypto algorithm!\n");
return false;
}
if ((hash_mode & 0xFF) == 0x01) // 0x14 SHA1-HMAC
{
return hmac_hash_compare(hash_final_14, 0x14, in, lenght, test_hash);
}
else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC
{
return cmac_hash_compare(hash_final_10, 0x10, in, lenght, test_hash);
}
else if ((hash_mode & 0xFF) == 0x04) //0x10 SHA1-HMAC
{
return hmac_hash_compare(hash_final_10, 0x10, in, lenght, test_hash);
}
else
{
ConLog.Error("EDAT: Unknown hashing algorithm!\n");
return false;
}
}
unsigned char* dec_section(unsigned char* metadata)
{
unsigned char *dec = new unsigned char[0x10];
dec[0x00] = (metadata[0xC] ^ metadata[0x8] ^ metadata[0x10]);
dec[0x01] = (metadata[0xD] ^ metadata[0x9] ^ metadata[0x11]);
dec[0x02] = (metadata[0xE] ^ metadata[0xA] ^ metadata[0x12]);
dec[0x03] = (metadata[0xF] ^ metadata[0xB] ^ metadata[0x13]);
dec[0x04] = (metadata[0x4] ^ metadata[0x8] ^ metadata[0x14]);
dec[0x05] = (metadata[0x5] ^ metadata[0x9] ^ metadata[0x15]);
dec[0x06] = (metadata[0x6] ^ metadata[0xA] ^ metadata[0x16]);
dec[0x07] = (metadata[0x7] ^ metadata[0xB] ^ metadata[0x17]);
dec[0x08] = (metadata[0xC] ^ metadata[0x0] ^ metadata[0x18]);
dec[0x09] = (metadata[0xD] ^ metadata[0x1] ^ metadata[0x19]);
dec[0x0A] = (metadata[0xE] ^ metadata[0x2] ^ metadata[0x1A]);
dec[0x0B] = (metadata[0xF] ^ metadata[0x3] ^ metadata[0x1B]);
dec[0x0C] = (metadata[0x4] ^ metadata[0x0] ^ metadata[0x1C]);
dec[0x0D] = (metadata[0x5] ^ metadata[0x1] ^ metadata[0x1D]);
dec[0x0E] = (metadata[0x6] ^ metadata[0x2] ^ metadata[0x1E]);
dec[0x0F] = (metadata[0x7] ^ metadata[0x3] ^ metadata[0x1F]);
return dec;
}
unsigned char* get_block_key(int block, NPD_HEADER *npd)
{
unsigned char empty_key[0x10] = {};
unsigned char *src_key = (npd->version <= 1) ? empty_key : npd->dev_hash;
unsigned char *dest_key = new unsigned char[0x10];
memcpy(dest_key, src_key, 0xC);
dest_key[0xC] = (block >> 24 & 0xFF);
dest_key[0xD] = (block >> 16 & 0xFF);
dest_key[0xE] = (block >> 8 & 0xFF);
dest_key[0xF] = (block & 0xFF);
return dest_key;
}
// EDAT/SDAT functions.
int decrypt_data(wxFile *in, wxFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
{
// Get metadata info and setup buffers.
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
int metadata_offset = 0x100;
unsigned char *enc_data;
unsigned char *dec_data;
unsigned char *b_key;
unsigned char *iv;
unsigned char empty_iv[0x10] = {};
// Decrypt the metadata.
int i;
for (i = 0; i < block_num; i++)
{
in->Seek(metadata_offset + i * metadata_section_size);
unsigned char hash_result[0x10];
long offset;
int lenght;
int compression_end = 0;
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0)
{
unsigned char metadata[0x20];
in->Read(metadata, 0x20);
// If the data is compressed, decrypt the metadata.
unsigned char *result = dec_section(metadata);
offset = ((swap32(*(int*)&result[0]) << 4) | (swap32(*(int*)&result[4])));
lenght = swap32(*(int*)&result[8]);
compression_end = swap32(*(int*)&result[12]);
delete[] result;
memcpy(hash_result, metadata, 0x10);
}
else if ((edat->flags & EDAT_FLAG_0x20) != 0)
{
// If FLAG 0x20, the metadata precedes each data block.
in->Seek(metadata_offset + i * metadata_section_size + lenght);
unsigned char metadata[0x20];
in->Read(metadata, 0x20);
// If FLAG 0x20 is set, apply custom xor.
int j;
for (j = 0; j < 0x10; j++) {
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j+0x10]);
}
offset = metadata_offset + i * edat->block_size + (i + 1) * metadata_section_size;
lenght = edat->block_size;
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
lenght = (int) (edat->file_size % edat->block_size);
}
else
{
in->Read(hash_result, 0x10);
offset = metadata_offset + i * edat->block_size + block_num * metadata_section_size;
lenght = edat->block_size;
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
lenght = (int) (edat->file_size % edat->block_size);
}
// Locate the real data.
int pad_lenght = lenght;
lenght = (int) ((pad_lenght + 0xF) & 0xFFFFFFF0);
in->Seek(offset);
// Setup buffers for decryption and read the data.
enc_data = new unsigned char[lenght];
dec_data = new unsigned char[lenght];
unsigned char key_result[0x10];
unsigned char hash[0x10];
in->Read(enc_data, lenght);
// Generate a key for the current block.
b_key = get_block_key(i, npd);
// Encrypt the block key with the crypto key.
aesecb128_encrypt(crypt_key, b_key, key_result);
if ((edat->flags & EDAT_FLAG_0x10) != 0)
aesecb128_encrypt(crypt_key, key_result, hash); // If FLAG 0x10 is set, encrypt again to get the final hash.
else
memcpy(hash, key_result, 0x10);
// Setup the crypto and hashing mode based on the extra flags.
int crypto_mode = ((edat->flags & EDAT_FLAG_0x02) == 0) ? 0x2 : 0x1;
int hash_mode;
if ((edat->flags & EDAT_FLAG_0x10) == 0)
hash_mode = 0x02;
else if ((edat->flags & EDAT_FLAG_0x20) == 0)
hash_mode = 0x04;
else
hash_mode = 0x01;
if ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) != 0)
{
crypto_mode |= 0x10000000;
hash_mode |= 0x10000000;
}
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
{
// Reset the flags.
crypto_mode |= 0x01000000;
hash_mode |= 0x01000000;
// Simply copy the data without the header or the footer.
memcpy(dec_data, enc_data, lenght);
}
else
{
// IV is null if NPD version is 1 or 0.
iv = (npd->version <= 1) ? empty_iv : npd->digest;
// Call main crypto routine on this data block.
crypto(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, lenght, key_result, iv, hash, hash_result);
}
// Apply additional compression if needed and write the decrypted data.
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0) && compression_end)
{
int decomp_size = (int)edat->file_size;
unsigned char *decomp_data = new unsigned char[decomp_size];
memset(decomp_data, 0, decomp_size);
if (verbose)
ConLog.Write("EDAT: Decompressing...\n");
int res = lz_decompress(decomp_data, dec_data, decomp_size);
out->Write(decomp_data, res);
if (verbose)
{
ConLog.Write("EDAT: Compressed block size: %d\n", pad_lenght);
ConLog.Write("EDAT: Decompressed block size: %d\n", res);
}
edat->file_size -= res;
if (edat->file_size == 0)
{
if (res < 0)
{
ConLog.Error("EDAT: Decompression failed!\n");
return 1;
}
else
ConLog.Success("EDAT: Data successfully decompressed!\n");
}
delete[] decomp_data;
}
else
{
out->Write(dec_data, pad_lenght);
}
delete[] enc_data;
delete[] dec_data;
}
return 0;
}
int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, wxFile *f, bool verbose)
{
f->Seek(0);
unsigned char *header = new unsigned char[0xA0];
unsigned char *tmp = new unsigned char[0xA0];
unsigned char *hash_result = new unsigned char[0x10];
// Check NPD version and EDAT flags.
if ((npd->version == 0) || (npd->version == 1))
{
if (edat->flags & 0x7EFFFFFE)
{
ConLog.Error("EDAT: Bad header flags!\n");
return 1;
}
}
else if (npd->version == 2)
{
if (edat->flags & 0x7EFFFFE0)
{
ConLog.Error("EDAT: Bad header flags!\n");
return 1;
}
}
else if ((npd->version == 3) || (npd->version == 4))
{
if (edat->flags & 0x7EFFFFC0)
{
ConLog.Error("EDAT: Bad header flags!\n");
return 1;
}
}
else
{
ConLog.Error("EDAT: Unknown version!\n");
return 1;
}
// Read in the file header.
f->Read(header, 0xA0);
f->Read(hash_result, 0x10);
// Setup the hashing mode and the crypto mode used in the file.
int crypto_mode = 0x1;
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
{
ConLog.Warning("EDAT: DEBUG data detected!\n");
hash_mode |= 0x01000000;
}
// Setup header key and iv buffers.
unsigned char header_key[0x10] = {};
unsigned char header_iv[0x10] = {};
// Test the header hash (located at offset 0xA0).
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), header, tmp, 0xA0, header_key, header_iv, key, hash_result))
{
if (verbose)
ConLog.Warning("EDAT: Header hash is invalid!\n");
}
// Parse the metadata info.
int metadata_section_size = 0x10;
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
{
ConLog.Warning("EDAT: COMPRESSED data detected!\n");
metadata_section_size = 0x20;
}
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
int bytes_read = 0;
int metadata_offset = 0x100;
long bytes_to_read = metadata_section_size * block_num;
while (bytes_to_read > 0)
{
// Locate the metadata blocks.
int block_size = (0x3C00 > bytes_to_read) ? (int) bytes_to_read : 0x3C00; // 0x3C00 is the maximum block size.
f->Seek(metadata_offset + bytes_read);
unsigned char *data = new unsigned char[block_size];
// Read in the metadata.
tmp = new unsigned char[block_size];
f->Read(data, block_size);
// Check the generated hash against the metadata hash located at offset 0x90 in the header.
memset(hash_result, 0, 0x10);
f->Seek(0x90);
f->Read(hash_result, 0x10);
// Generate the hash for this block.
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), data, tmp, block_size, header_key, header_iv, key, hash_result))
{
if (verbose)
ConLog.Warning("EDAT: Metadata hash from block 0x%08x is invalid!\n", metadata_offset + bytes_read);
}
// Adjust sizes.
bytes_read += block_size;
bytes_to_read -= block_size;
delete[] data;
}
// Cleanup.
delete[] header;
delete[] tmp;
delete[] hash_result;
return 0;
}
void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
{
int title_hash_result = 0;
int dev_hash_result = 0;
int file_name_length = strlen(file_name);
unsigned char *buf = new unsigned char[0x30 + file_name_length];
unsigned char key[0x10];
// Build the buffer (content_id + file_name).
memcpy(buf, npd->content_id, 0x30);
memcpy(buf + 0x30, file_name, file_name_length);
// Hash with NP_OMAC_KEY_3 and compare with title_hash.
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash);
if (verbose)
{
if (title_hash_result)
ConLog.Success("EDAT: NPD title hash is valid!\n");
else
ConLog.Warning("EDAT: NPD title hash is invalid!\n");
}
// Check for an empty dev_hash (can't validate if devklic is NULL);
bool isDevklicEmpty = true;
for (int i = 0; i < 0x10; i++)
{
if (klicensee[i] != 0)
{
isDevklicEmpty = false;
break;
}
}
if (isDevklicEmpty)
{
if (verbose)
ConLog.Warning("EDAT: NPD dev hash is empty!\n");
}
else
{
// Generate klicensee xor key.
xor(key, klicensee, NP_OMAC_KEY_2, 0x10);
// Hash with generated key and compare with dev_hash.
dev_hash_result = cmac_hash_compare(key, 0x10, (unsigned char *)npd, 0x60, npd->dev_hash);
if (verbose)
{
if (dev_hash_result)
ConLog.Success("EDAT: NPD dev hash is valid!\n");
else
ConLog.Warning("EDAT: NPD dev hash is invalid!\n");
}
}
delete[] buf;
}
bool extract_data(wxFile *input, wxFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
{
// Setup NPD and EDAT/SDAT structs.
NPD_HEADER *NPD = new NPD_HEADER();
EDAT_SDAT_HEADER *EDAT = new EDAT_SDAT_HEADER();
// Read in the NPD and EDAT/SDAT headers.
char npd_header[0x80];
char edat_header[0x10];
input->Read(npd_header, 0x80);
input->Read(edat_header, 0x10);
memcpy(NPD->magic, npd_header, 4);
NPD->version = swap32(*(int*)&npd_header[4]);
NPD->license = swap32(*(int*)&npd_header[8]);
NPD->type = swap32(*(int*)&npd_header[12]);
memcpy(NPD->content_id, (unsigned char*)&npd_header[16], 0x30);
memcpy(NPD->digest, (unsigned char*)&npd_header[64], 0x10);
memcpy(NPD->title_hash, (unsigned char*)&npd_header[80], 0x10);
memcpy(NPD->dev_hash, (unsigned char*)&npd_header[96], 0x10);
NPD->unk1 = swap64(*(u64*)&npd_header[112]);
NPD->unk2 = swap64(*(u64*)&npd_header[120]);
unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00}; //NPD0
if(memcmp(NPD->magic, npd_magic, 4))
{
ConLog.Error("EDAT: File has invalid NPD header.");
return 1;
}
EDAT->flags = swap32(*(int*)&edat_header[0]);
EDAT->block_size = swap32(*(int*)&edat_header[4]);
EDAT->file_size = swap64(*(u64*)&edat_header[8]);
if (verbose)
{
ConLog.Write("NPD HEADER\n");
ConLog.Write("NPD version: %d\n", NPD->version);
ConLog.Write("NPD license: %d\n", NPD->license);
ConLog.Write("NPD type: %d\n", NPD->type);
ConLog.Write("\n");
ConLog.Write("EDAT HEADER\n");
ConLog.Write("EDAT flags: 0x%08X\n", EDAT->flags);
ConLog.Write("EDAT block size: 0x%08X\n", EDAT->block_size);
ConLog.Write("EDAT file size: 0x%08X\n", EDAT->file_size);
ConLog.Write("\n");
}
// Set decryption key.
unsigned char key[0x10];
memset(key, 0, 0x10);
if((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
{
ConLog.Warning("EDAT: SDAT detected!\n");
xor(key, NPD->dev_hash, SDAT_KEY, 0x10);
}
else
{
// Perform header validation (optional step).
validate_data(input_file_name, devklic, NPD, verbose);
if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
memcpy(key, devklic, 0x10);
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
{
memcpy(key, rifkey, 0x10);
// Make sure we don't have an empty RIF key.
int i, test = 0;
for(i = 0; i < 0x10; i++)
{
if (key[i] != 0)
{
test = 1;
break;
}
}
if (!test)
{
ConLog.Error("EDAT: A valid RAP file is needed!");
return 1;
}
}
}
ConLog.Write("EDAT: Parsing data...\n");
if (check_data(key, EDAT, NPD, input, verbose))
ConLog.Error("EDAT: Data parsing failed!\n");
else
ConLog.Success("EDAT: Data successfully parsed!\n");
printf("\n");
ConLog.Write("EDAT: Decrypting data...\n");
if (decrypt_data(input, output, EDAT, NPD, key, verbose))
ConLog.Error("EDAT: Data decryption failed!");
else
ConLog.Success("EDAT: Data successfully decrypted!");
delete NPD;
delete EDAT;
return 0;
}
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose)
{
// Prepare the files.
wxFile input(input_file_name.c_str());
wxFile output(output_file_name.c_str(), wxFile::write);
wxFile rap(rap_file_name.c_str());
// Set keys (RIF and DEVKLIC).
unsigned char rifkey[0x10];
unsigned char devklic[0x10];
memset(rifkey, 0, 0x10);
memset(devklic, 0, 0x10);
// Select the EDAT key mode.
switch (mode)
{
case 0:
break;
case 1:
memcpy(devklic, NP_KLIC_FREE, 0x10);
break;
case 2:
memcpy(devklic, NP_OMAC_KEY_2, 0x10);
break;
case 3:
memcpy(devklic, NP_OMAC_KEY_3, 0x10);
break;
case 4:
memcpy(devklic, NP_KLIC_KEY, 0x10);
break;
case 5:
memcpy(devklic, NP_PSX_KEY, 0x10);
break;
case 6:
memcpy(devklic, NP_PSP_KEY_1, 0x10);
break;
case 7:
memcpy(devklic, NP_PSP_KEY_2, 0x10);
break;
case 8:
{
if (custom_klic != NULL)
memcpy(devklic, custom_klic, 0x10);
else
{
ConLog.Error("EDAT: Invalid custom klic!\n");
return -1;
}
break;
}
default:
ConLog.Error("EDAT: Invalid mode!\n");
return -1;
}
// Check the input/output files.
if (!input.IsOpened() || !output.IsOpened())
{
ConLog.Error("EDAT: Failed to open files!\n");
return -1;
}
// Read the RAP file, if provided.
if (rap.IsOpened())
{
unsigned char rapkey[0x10];
memset(rapkey, 0, 0x10);
rap.Read(rapkey, 0x10);
rap_to_rif(rapkey, rifkey);
rap.Close();
}
// Delete the bad output file if any errors arise.
if (extract_data(&input, &output, input_file_name.c_str(), devklic, rifkey, verbose))
{
input.Close();
output.Close();
wxRemoveFile(output_file_name);
return 0;
}
// Cleanup.
input.Close();
output.Close();
return 0;
}

34
rpcs3/Crypto/unedat.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "utils.h"
#include "key_vault.h"
#define SDAT_FLAG 0x01000000
#define EDAT_COMPRESSED_FLAG 0x00000001
#define EDAT_FLAG_0x02 0x00000002
#define EDAT_ENCRYPTED_KEY_FLAG 0x00000008
#define EDAT_FLAG_0x10 0x00000010
#define EDAT_FLAG_0x20 0x00000020
#define EDAT_DEBUG_DATA_FLAG 0x80000000
typedef struct
{
unsigned char magic[4];
int version;
int license;
int type;
unsigned char content_id[0x30];
unsigned char digest[0x10];
unsigned char title_hash[0x10];
unsigned char dev_hash[0x10];
unsigned long long unk1;
unsigned long long unk2;
} NPD_HEADER;
typedef struct
{
int flags;
int block_size;
unsigned long long file_size;
} EDAT_SDAT_HEADER;
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);

View File

@ -1,6 +1,5 @@
#pragma once
#include "aes.h"
#include "sha1.h"
#include "utils.h"
#include "key_vault.h"
// Constants

View File

@ -92,9 +92,7 @@ bool SELFDecrypter::LoadHeaders(bool isElf32)
{
ControlInfo* cinfo = new ControlInfo();
cinfo->Load(self_f);
i += cinfo->size;
ctrlinfo_arr.Move(cinfo);
}
@ -155,12 +153,12 @@ void SELFDecrypter::ShowHeaders(bool isElf32)
ConLog.Write("----------------------------------------------------");
ConLog.Write("ELF program headers");
ConLog.Write("----------------------------------------------------");
for(int i = 0; i < ((isElf32) ? phdr32_arr.GetCount() : phdr64_arr.GetCount()); i++)
for(unsigned int i = 0; i < ((isElf32) ? phdr32_arr.GetCount() : phdr64_arr.GetCount()); i++)
isElf32 ? phdr32_arr[i].Show() : phdr64_arr[i].Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("Section info");
ConLog.Write("----------------------------------------------------");
for(int i = 0; i < secinfo_arr.GetCount(); i++)
for(unsigned int i = 0; i < secinfo_arr.GetCount(); i++)
secinfo_arr[i].Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("SCE version info");
@ -169,12 +167,12 @@ void SELFDecrypter::ShowHeaders(bool isElf32)
ConLog.Write("----------------------------------------------------");
ConLog.Write("Control info");
ConLog.Write("----------------------------------------------------");
for(int i = 0; i < ctrlinfo_arr.GetCount(); i++)
for(unsigned int i = 0; i < ctrlinfo_arr.GetCount(); i++)
ctrlinfo_arr[i].Show();
ConLog.Write("----------------------------------------------------");
ConLog.Write("ELF section headers");
ConLog.Write("----------------------------------------------------");
for(int i = 0; i < ((isElf32) ? shdr32_arr.GetCount() : shdr64_arr.GetCount()); i++)
for(unsigned int i = 0; i < ((isElf32) ? shdr32_arr.GetCount() : shdr64_arr.GetCount()); i++)
isElf32 ? shdr32_arr[i].Show() : shdr64_arr[i].Show();
ConLog.Write("----------------------------------------------------");
}
@ -187,7 +185,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
u8 npdrm_iv[0x10];
// Parse the control info structures to find the NPDRM control info.
for(int i = 0; i < ctrlinfo_arr.GetCount(); i++)
for(unsigned int i = 0; i < ctrlinfo_arr.GetCount(); i++)
{
if (ctrlinfo_arr[i].type == 3)
{
@ -310,7 +308,7 @@ bool SELFDecrypter::LoadMetadata()
// Load the metadata section headers.
meta_shdr.Clear();
for (int i = 0; i < meta_hdr.section_count; i++)
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
MetadataSectionHeader* m_shdr = new MetadataSectionHeader();
m_shdr->Load(metadata_headers + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i);
@ -330,7 +328,7 @@ bool SELFDecrypter::DecryptData()
aes_context aes;
// Calculate the total data size.
for (int i = 0; i < meta_hdr.section_count; i++)
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
if (meta_shdr[i].encrypted == 3)
{
@ -346,7 +344,7 @@ bool SELFDecrypter::DecryptData()
u32 data_buf_offset = 0;
// Parse the metadata section headers to find the offsets of encrypted data.
for (int i = 0; i < meta_hdr.section_count; i++)
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
size_t ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
@ -370,7 +368,7 @@ bool SELFDecrypter::DecryptData()
self_f.Seek(meta_shdr[i].data_offset);
self_f.Read(buf, meta_shdr[i].data_size);
// Zero out our ctr nonce
// Zero out our ctr nonce.
memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
// Perform AES-CTR encryption on the data blocks.
@ -414,7 +412,7 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
for(u32 i = 0; i < elf32_hdr.e_phnum; ++i)
WritePhdr(e, phdr32_arr[i]);
for (int i = 0; i < meta_hdr.section_count; i++)
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
// PHDR type.
if (meta_shdr[i].type == 2)
@ -447,7 +445,7 @@ bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32)
WritePhdr(e, phdr64_arr[i]);
// Write data.
for (int i = 0; i < meta_hdr.section_count; i++)
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
// PHDR type.
if (meta_shdr[i].type == 2)
@ -533,8 +531,8 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
rap_file.Read(rap_key, 0x10);
rap_file.Close();
// Call the key vault to convert the RAP key.
key_v.RapToRif(rap_key, npdrm_key);
// Convert the RAP key.
rap_to_rif(rap_key, npdrm_key);
return true;
}

View File

@ -1,6 +1,5 @@
#pragma once
#include "aes.h"
#include "sha1.h"
#include "utils.h"
#include "key_vault.h"
#include "Loader/ELF.h"
#include "Loader/SELF.h"

View File

@ -19,6 +19,15 @@ u64 swap64(u64 i)
((i & 0x000000ff00000000) >> 8) | ((i & 0x0000ff0000000000) >> 24) |
((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56);
}
void xor(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
{
int i;
for(i = 0; i < size; i++)
{
dest[i] = src1[i] ^ src2[i];
}
}
// Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str)
@ -68,4 +77,671 @@ void hex_to_bytes(unsigned char *data, const char *hex_str)
// Copy back to our array.
memcpy(data, out, data_length);
}
}
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
{
aes_context ctx;
aes_setkey_dec(&ctx, key, 128);
aes_crypt_cbc(&ctx, AES_DECRYPT, len, iv, in, out);
// Reset the IV.
memset(iv, 0, 0x10);
}
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out)
{
aes_context ctx;
aes_setkey_enc(&ctx, key, 128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out);
}
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
{
unsigned char *out = new unsigned char[key_len];
sha1_hmac(key, key_len, in, in_len, out);
for (int i = 0; i < 0x10; i++)
{
if (out[i] != hash[i])
{
delete[] out;
return false;
}
}
delete[] out;
return true;
}
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
{
unsigned char *out = new unsigned char[key_len];
aes_context ctx;
aes_setkey_enc(&ctx, key, 128);
aes_cmac(&ctx, in_len, in, out);
for (int i = 0; i < key_len; i++)
{
if (out[i] != hash[i])
{
delete[] out;
return false;
}
}
delete[] out;
return true;
}
// Reverse-engineered custom LempelZivMarkov based compression (unknown variant of LZRC).
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size)
{
char *tmp = new char[3272];
char *p;
char *p2;
char *sub;
char *sub2;
char *sub3;
int offset;
int index;
int index2;
int unk;
int flag;
int flag2;
unsigned int c;
int cc;
int sp;
unsigned int sc;
int scc;
char st;
char t;
unsigned int n_size;
unsigned int r_size;
signed int f_size;
signed int b_size;
signed int diff;
signed int diff_pad;
bool adjust;
int pos;
int end;
int n_end;
signed int end_size;
int chunk_size;
char pad;
unsigned int remainder;
int result;
adjust = true;
offset = 0;
index = 0;
remainder = -1;
end = (int)((char *)out + size);
pos = (int)in;
pad = *in;
chunk_size = (*(in + 1) << 24) | (*(in + 2) << 16) | (*(in + 3) << 8) | *(in + 4);
if (*in >= 0) // Check if we have a valid starting byte.
{
memset(tmp, 128, 0xCA8u);
end_size = 0;
while (1)
{
while (1)
{
p = &tmp[offset];
c = (unsigned char)tmp[offset + 2920];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
cc = c - (c >> 3);
r_size = c * (remainder >> 8);
f_size = (unsigned int)chunk_size < r_size;
if ((unsigned int)chunk_size < r_size)
break;
remainder -= r_size;
chunk_size -= r_size;
p[2920] = cc;
offset = (offset - 1) & ((u64)~(offset - 1) >> 32);
if (out == (void *)end)
return -1;
sub = &tmp[255 * ((((((unsigned char)out & 7) << 8) | index & 0xFFFFF8FFu) >> pad) & 7)];
index = 1;
do
{
sp = (int)&sub[index];
sc = (unsigned char)sub[index - 1];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
index *= 2;
n_size = sc * (remainder >> 8);
scc = sc - (sc >> 3);
st = scc;
if ((unsigned int)chunk_size < n_size)
{
remainder = n_size;
++index;
st = scc + 31;
}
else
{
remainder -= n_size;
chunk_size -= n_size;
}
*(unsigned char *)(sp - 1) = st;
}
while (index <= 255);
out += 1;
++end_size;
*(out - 1) = index;
}
remainder = c * (remainder >> 8);
p[2920] = cc + 31;
index = -1;
while (1)
{
c = (unsigned char)p[2928];
if (!(r_size >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder = r_size << 8;
chunk_size = (chunk_size << 8) + add;
}
p += 8;
r_size = c * (remainder >> 8);
cc = c - (c >> 3);
if ((unsigned int)chunk_size >= r_size)
break;
remainder = r_size;
p[2920] = cc + 31;
++index;
if (index == 6)
{
adjust = false;
break;
}
}
if (adjust)
{
remainder -= r_size;
chunk_size -= r_size;
p[2920] = cc;
}
adjust = true;
p2 = &tmp[index];
if (index >= 0)
{
sub3 = &tmp[offset & 7 | 8 * (((unsigned int)out << index) & 3) | 32 * index];
flag = index - 3;
c = (unsigned char)sub3[2984];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
index2 = 2;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
index2 = 3;
t = cc + 31;
}
if (flag < 0)
{
sub3[2984] = t;
}
else
{
if (flag <= 0)
{
sub3[2984] = t;
}
else
{
c = (unsigned char)t;
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub3[2984] = t;
if (flag != 1)
{
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
do
{
remainder >>= 1;
index2 = ((unsigned int)chunk_size < remainder) + 2 * index2;
if ((unsigned int)chunk_size >= remainder)
chunk_size -= remainder;
--flag;
}
while (flag != 1);
}
}
c = (unsigned char)sub3[3008];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub3[3008] = t;
}
if (index > 0)
{
c = (unsigned char)sub3[2992];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub3[2992] = t;
if (index != 1)
{
c = (unsigned char)sub3[3000];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub3[3000] = t;
}
}
f_size = index2;
if (index2 == 255)
break;
}
index = 8;
b_size = 352;
if (f_size <= 2)
{
p2 += 248;
b_size = 64;
}
do
{
unk = (int)&p2[index];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
c = *(unsigned char *)(unk + 2033);
index *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size < n_size)
{
remainder = n_size;
t = cc + 31;
index += 8;
}
else
{
remainder -= n_size;
chunk_size -= n_size;
}
*(unsigned char *)(unk + 2033) = t;
diff = index - b_size;
}
while ((index - b_size) < 0);
if (index != b_size)
{
diff_pad = diff >> 3;
flag = diff_pad - 1;
flag2 = diff_pad - 4;
sub2 = &tmp[32 * (diff_pad - 1)];
c = (unsigned char)sub2[2344];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
index2 = 2;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
index2 = 3;
t = cc + 31;
}
if (flag2 < 0)
{
sub2[2344] = t;
}
else
{
if (flag2 <= 0)
{
sub2[2344] = t;
}
else
{
c = (unsigned char)t;
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub2[2344] = t;
if (flag2 != 1)
{
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
do
{
remainder >>= 1;
index2 = ((unsigned int)chunk_size < remainder) + 2 * index2;
if ((unsigned int)chunk_size >= remainder)
chunk_size -= remainder;
--flag2;
}
while (flag2 != 1);
}
}
c = (unsigned char)sub2[2368];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub2[2368] = t;
}
if (flag > 0)
{
c = (unsigned char)sub2[2352];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos++ + 5);
remainder <<= 8;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub2[2352] = t;
if (flag != 1)
{
c = (unsigned char)sub2[2360];
if (!(remainder >> 24))
{
int add = *(unsigned char *)(pos + 5);
remainder <<= 8;
++pos;
chunk_size = (chunk_size << 8) + add;
}
index2 *= 2;
n_size = c * (remainder >> 8);
cc = c - (c >> 3);
t = cc;
if ((unsigned int)chunk_size >= n_size)
{
remainder -= n_size;
chunk_size -= n_size;
}
else
{
remainder = n_size;
++index2;
t = cc + 31;
}
sub2[2360] = t;
}
}
diff = index2 - 1;
}
if (end_size <= diff)
return -1;
index = *(out - diff - 1);
n_end = (int)(out + f_size);
offset = (((unsigned char)f_size + (unsigned char)out) & 1) + 6;
if ((unsigned int)(out + f_size) >= (unsigned int)end)
return -1;
do
{
out += 1;
++end_size;
*(out - 1) = index;
index = *(out - diff - 1);
}
while (out != (void *)n_end);
out += 1;
++end_size;
*((unsigned char *)out - 1) = index;
}
result = end_size;
}
else // Starting byte is invalid.
{
result = -1;
if (chunk_size <= (int)size)
{
memcpy(out, (const void *)(in + 5), chunk_size);
result = chunk_size;
}
}
delete[] tmp;
return result;
}

View File

@ -1,7 +1,22 @@
#pragma once
#include "aes.h"
#include "sha1.h"
// Auxiliary functions (endian swap and xor).
u16 swap16(u16 i);
u32 swap32(u32 i);
u64 swap64(u64 i);
void xor(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
// Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str);
void hex_to_bytes(unsigned char *data, const char *hex_str);
void hex_to_bytes(unsigned char *data, const char *hex_str);
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out);
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
// Reverse-engineered custom LempelZivMarkov based compression (unknown variant of LZRC).
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size);

View File

@ -0,0 +1,12 @@
#include "stdafx.h"
#include "SPURSManager.h"
SPURSManager::SPURSManager(SPURSManagerAttribute *attr)
{
this->attr = attr;
}
void SPURSManager::Finalize()
{
delete this->attr;
}

View File

@ -0,0 +1,92 @@
#pragma once
// SPURS defines.
enum SPURSKernelInterfaces
{
CELL_SPURS_MAX_SPU = 8,
CELL_SPURS_MAX_WORKLOAD = 16,
CELL_SPURS_MAX_WORKLOAD2 = 32,
CELL_SPURS_MAX_PRIORITY = 16,
CELL_SPURS_NAME_MAX_LENGTH = 15,
CELL_SPURS_SIZE = 4096,
CELL_SPURS_SIZE2 = 8192,
CELL_SPURS_ALIGN = 128,
CELL_SPURS_ATTRIBUTE_SIZE = 512,
CELL_SPURS_ATTRIBUTE_ALIGN = 8,
CELL_SPURS_INTERRUPT_VECTOR = 0x0,
CELL_SPURS_LOCK_LINE = 0x80,
CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
};
enum RangeofEventQueuePortNumbers
{
CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15,
CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16,
CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63,
};
enum SPURSTraceTypes
{
CELL_SPURS_TRACE_TAG_LOAD = 0x2a,
CELL_SPURS_TRACE_TAG_MAP = 0x2b,
CELL_SPURS_TRACE_TAG_START = 0x2c,
CELL_SPURS_TRACE_TAG_STOP = 0x2d,
CELL_SPURS_TRACE_TAG_USER = 0x2e,
CELL_SPURS_TRACE_TAG_GUID = 0x2f,
};
// SPURS task defines.
enum TaskConstants
{
CELL_SPURS_MAX_TASK = 128,
CELL_SPURS_TASK_TOP = 0x3000,
CELL_SPURS_TASK_BOTTOM = 0x40000,
CELL_SPURS_MAX_TASK_NAME_LENGTH = 32,
};
// Internal class to shape a SPURS attribute.
class SPURSManagerAttribute
{
public:
SPURSManagerAttribute(int nSpus, int spuPriority, int ppuPriority, bool exitIfNoWork)
{
this->nSpus = nSpus;
this->spuThreadGroupPriority = spuPriority;
this->ppuThreadPriority = ppuPriority;
this->exitIfNoWork = exitIfNoWork;
memset(this->namePrefix, 0, CELL_SPURS_NAME_MAX_LENGTH + 1);
this->threadGroupType = 0;
}
int _setNamePrefix(const char *name, u32 size)
{
strncpy(this->namePrefix, name, size);
this->namePrefix[0] = 0;
return 0;
}
int _setSpuThreadGroupType(int type)
{
this->threadGroupType = type;
return 0;
}
protected:
be_t<int> nSpus;
be_t<int> spuThreadGroupPriority;
be_t<int> ppuThreadPriority;
bool exitIfNoWork;
char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1];
be_t<int> threadGroupType;
};
// Main SPURS manager class.
class SPURSManager
{
public:
SPURSManager(SPURSManagerAttribute *attr);
void Finalize();
protected:
SPURSManagerAttribute *attr;
};

View File

@ -423,11 +423,11 @@ public:
class vfsHDD : public vfsFileBase
{
vfsHDD_Hdr m_hdd_info;
vfsLocalFile m_hdd_file;
const wxString& m_hdd_path;
vfsHDD_Entry m_cur_dir;
u64 m_cur_dir_block;
vfsHDDFile m_file;
vfsLocalFile m_hdd_file;
const wxString& m_hdd_path;
public:
vfsHDD(vfsDevice* device, const wxString& hdd_path)

View File

@ -6,12 +6,69 @@
void cellSpurs_init();
Module cellSpurs(0x000a, cellSpurs_init);
int cellSpursInitialize(mem_ptr_t<CellSpurs> spurs, int nSpus, int spuPriority,
int ppuPriority, bool exitIfNoWork)
{
cellSpurs.Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
spurs.GetAddr(), nSpus, spuPriority, ppuPriority, exitIfNoWork);
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
SPURSManagerAttribute *attr = new SPURSManagerAttribute(nSpus, spuPriority, ppuPriority, exitIfNoWork);
spurs->spurs = new SPURSManager(attr);
return CELL_OK;
}
int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
{
cellSpurs.Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
spurs->spurs->Finalize();
return CELL_OK;
}
int cellSpursInitializeWithAttribute(mem_ptr_t<CellSpurs> spurs, const mem_ptr_t<CellSpursAttribute> attr)
{
cellSpurs.Warning("cellSpursInitializeWithAttribute(spurs_addr=0x%x, spurs_addr=0x%x)",
spurs.GetAddr(), attr.GetAddr());
if(!attr.IsGood() || !spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
spurs->spurs = new SPURSManager(attr->attr);
return CELL_OK;
}
int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr_t<CellSpursAttribute> attr)
{
cellSpurs.Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)",
spurs.GetAddr(), attr.GetAddr());
if(!attr.IsGood() || !spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
spurs->spurs = new SPURSManager(attr->attr);
return CELL_OK;
}
int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus, int spuPriority,
int ppuPriority, bool exitIfNoWork)
{
cellSpurs.Error("_cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
cellSpurs.Warning("_cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
attr.GetAddr(), nSpus, spuPriority, ppuPriority, exitIfNoWork);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!attr.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
attr->attr = new SPURSManagerAttribute(nSpus, spuPriority, ppuPriority, exitIfNoWork);
return CELL_OK;
}
@ -20,17 +77,25 @@ int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribut
{
cellSpurs.Error("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)",
attr.GetAddr(), container);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!attr.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const mem8_t prefix, u32 size)
{
cellSpurs.Error("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)",
cellSpurs.Warning("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)",
attr.GetAddr(), prefix.GetAddr(), size);
if(!attr.IsGood() || !prefix.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(size > 15) return CELL_SPURS_CORE_ERROR_INVAL;
if(!attr.IsGood() || !prefix.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(size > 15)
return CELL_SPURS_CORE_ERROR_INVAL;
attr->attr->_setNamePrefix(Memory.ReadString(prefix.GetAddr(), size), size);
return CELL_OK;
}
@ -38,53 +103,48 @@ int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const me
int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> attr)
{
cellSpurs.Error("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr());
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!attr.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr, int type)
{
cellSpurs.Error("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
cellSpurs.Warning("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type);
if(!attr.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
attr->attr->_setSpuThreadGroupType(type);
return CELL_OK;
}
int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, const u8 priority[8],
uint maxSpu, const bool isPreemptible[8])
u32 maxSpu, const bool isPreemptible[8])
{
cellSpurs.Error("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority[%u], maxSpu=%u, isPreemptible[%u])",
attr.GetAddr(), priority, maxSpu, isPreemptible);
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!attr.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
for (int i=0; i<8; i++)
if(priority[i] != 1 || maxSpu == 0) return CELL_SPURS_CORE_ERROR_INVAL;
if(priority[i] != 1 || maxSpu == 0)
return CELL_SPURS_CORE_ERROR_INVAL;
return CELL_OK;
}
int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr_t<CellSpursAttribute> attr)
{
cellSpurs.Error("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)",
spurs.GetAddr(), attr.GetAddr());
if(!attr.IsGood() || !spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
{
cellSpurs.Error("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group)
{
cellSpurs.Error("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)",
spurs.GetAddr(), group.GetAddr());
if(!spurs.IsGood() || group.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood() || group.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -93,7 +153,9 @@ int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads)
{
cellSpurs.Error("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)",
spurs.GetAddr(), nThreads.GetAddr());
if(!spurs.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood() || nThreads.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -102,34 +164,42 @@ int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t
{
cellSpurs.Error("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)",
spurs.GetAddr(), thread.GetAddr(), nThreads.GetAddr());
if(!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint maxContention)
int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, u32 workloadId, u32 maxContention)
{
cellSpurs.Error("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)",
spurs.GetAddr(), workloadId, maxContention);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU])
int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, u32 workloadId, const u8 priorities[CELL_SPURS_MAX_SPU])
{
cellSpurs.Error("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])",
spurs.GetAddr(), workloadId, priorities);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId, uint priority)
int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, u32 workloadId, u32 spuId, u32 priority)
{
cellSpurs.Error("cellSpursSetPriority(spurs_addr=0x%x, workloadId=%u, spuId=%u, priority=%u)",
spurs.GetAddr(), workloadId, spuId, priority);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -138,7 +208,9 @@ int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isP
{
cellSpurs.Error("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])",
spurs.GetAddr(), isPreemptible);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -147,7 +219,9 @@ int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t p
{
cellSpurs.Error("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%u)",
spurs.GetAddr(), queue, port.GetAddr(), isDynamic);
if(!spurs.IsGood() || !port.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood() || !port.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -155,7 +229,52 @@ int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t p
int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
{
cellSpurs.Error("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int _cellSpursEventFlagInitialize(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
mem_ptr_t<CellSpursEventFlag> eventFlag, u32 flagClearMode, u32 flagDirection)
{
cellSpurs.Error("_cellSpursEventFlagInitialize(spurs_addr=0x%x, taskset_addr=0x%x, eventFlag_addr=0x%x, flagClearMode=%u, flagDirection=%u)",
spurs.GetAddr(), taskset.GetAddr(), eventFlag.GetAddr(), flagClearMode, flagDirection);
if(!spurs.IsGood() || !taskset.IsGood() || !eventFlag.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursEventFlagAttachLv2EventQueue(mem_ptr_t<CellSpursEventFlag> event_flag)
{
cellSpurs.Error("cellSpursEventFlagAttachLv2EventQueue(event_flag_addr=0x%x)", event_flag.GetAddr());
if(!event_flag.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursEventFlagDetachLv2EventQueue(mem_ptr_t<CellSpursEventFlag> event_flag)
{
cellSpurs.Error("cellSpursEventFlagDetachLv2EventQueue(event_flag_addr=0x%x)", event_flag.GetAddr());
if(!event_flag.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursEventFlagWait(mem_ptr_t<CellSpursEventFlag> event_flag, mem16_t flag_bits, u32 wait_mode)
{
cellSpurs.Error("cellSpursEventFlagWait(event_flag_addr=0x%x, flag_bits_addr=0x%x, wait_mode=%u)",
event_flag.GetAddr(), flag_bits.GetAddr(), wait_mode);
if(!event_flag.IsGood() || !flag_bits.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -163,7 +282,9 @@ int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag)
{
cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag);
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -173,7 +294,9 @@ int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
{
cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)",
spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr());
if(!spurs.IsGood() || eaHandler.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood() || eaHandler.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -181,7 +304,9 @@ int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
{
cellSpurs.Error("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr());
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
@ -189,47 +314,120 @@ int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info)
{
cellSpurs.Error("cellSpursGetInfo(spurs_addr=0x%x, info_addr=0x%x)", spurs.GetAddr(), info.GetAddr());
if(!spurs.IsGood() || !info.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
if(!spurs.IsGood() || !info.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int _cellSpursSendSignal(mem_ptr_t<CellSpursTaskset> taskset, u32 taskID)
{
cellSpurs.Error("_cellSpursSendSignal(taskset_addr=0x%x, taskID=%u)", taskset.GetAddr(), taskID);
if(!taskset.IsGood())
return CELL_SPURS_CORE_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursCreateTaskset(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
u64 args, mem8_t priority, u32 maxContention)
{
cellSpurs.Error("cellSpursCreateTaskset(spurs_addr=0x%x, taskset_addr=0x%x, args=0x%x, priority_addr=0x%x, maxContention=%u)",
spurs.GetAddr(), taskset.GetAddr(), args, priority.GetAddr(), maxContention);
if(!spurs.IsGood() || !taskset.IsGood())
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursJoinTaskset(mem_ptr_t<CellSpursTaskset> taskset)
{
cellSpurs.Error("cellSpursJoinTaskset(taskset_addr=0x%x)", taskset.GetAddr());
if(!taskset.IsGood())
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK;
}
// Task functions
int cellSpursGetTasksetId(mem_ptr_t<CellSpursTaskset> taskset, mem32_t workloadId)
{
cellSpurs.Error("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr());
if(!taskset.IsGood() || !workloadId.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER;
if(!taskset.IsGood() || !workloadId.IsGood())
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursShutdownTaskset(mem_ptr_t<CellSpursTaskset> taskset)
{
cellSpurs.Error("cellSpursShutdownTaskset(taskset_addr=0x%x)", taskset.GetAddr());
if(!taskset.IsGood())
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK;
}
int cellSpursCreateTask(mem_ptr_t<CellSpursTaskset> taskset, mem32_t taskID, mem_ptr_t<void> elf_addr,
mem_ptr_t<void> context_addr, u32 context_size, mem_ptr_t<CellSpursTaskLsPattern> lsPattern,
mem_ptr_t<CellSpursTaskArgument> argument)
{
cellSpurs.Error("cellSpursCreateTask(taskset_addr=0x%x, taskID_addr=0x%x, elf_addr_addr=0x%x, context_addr_addr=0x%x, context_size=%u, lsPattern_addr=0x%x, argument_addr=0x%x)",
taskset.GetAddr(), taskID.GetAddr(), elf_addr.GetAddr(), context_addr.GetAddr(), context_size, lsPattern.GetAddr(), argument.GetAddr());
if(!taskset.IsGood())
return CELL_SPURS_TASK_ERROR_NULL_POINTER;
return CELL_OK;
}
void cellSpurs_init()
{
//libspurs core functions
cellSpurs.AddFunc(0xacfc8dbc, cellSpursInitialize);
cellSpurs.AddFunc(0xaa6269a8, cellSpursInitializeWithAttribute);
cellSpurs.AddFunc(0x30aa96c4, cellSpursInitializeWithAttribute2);
cellSpurs.AddFunc(0xca4c4600, cellSpursFinalize);
cellSpurs.AddFunc(0x95180230, _cellSpursAttributeInitialize);
cellSpurs.AddFunc(0x82275c1c, cellSpursAttributeSetMemoryContainerForSpuThread);
cellSpurs.AddFunc(0x07529113, cellSpursAttributeSetNamePrefix);
cellSpurs.AddFunc(0x1051d134, cellSpursAttributeEnableSpuPrintfIfAvailable);
cellSpurs.AddFunc(0xa839a4d9, cellSpursAttributeSetSpuThreadGroupType);
cellSpurs.AddFunc(0x9dcbcb5d, cellSpursAttributeEnableSystemWorkload);
cellSpurs.AddFunc(0x30aa96c4, cellSpursInitializeWithAttribute2);
cellSpurs.AddFunc(0xca4c4600, cellSpursFinalize);
cellSpurs.AddFunc(0x39c173fb, cellSpursGetSpuThreadGroupId);
cellSpurs.AddFunc(0xc56defb5, cellSpursGetNumSpuThread);
cellSpurs.AddFunc(0x6c960f6d, cellSpursGetSpuThreadId);
cellSpurs.AddFunc(0x84d2f6d5,cellSpursSetMaxContention);
cellSpurs.AddFunc(0x80a29e27,cellSpursSetPriorities);
//cellSpurs.AddFunc(,cellSpursSetPriority);
cellSpurs.AddFunc(0x84d2f6d5, cellSpursSetMaxContention);
cellSpurs.AddFunc(0x80a29e27, cellSpursSetPriorities);
cellSpurs.AddFunc(0x4de203e2, cellSpursSetPreemptionVictimHints);
cellSpurs.AddFunc(0xb9bc6207, cellSpursAttachLv2EventQueue);
cellSpurs.AddFunc(0x4e66d483, cellSpursDetachLv2EventQueue);
//cellSpurs.AddFunc(0x5ef96465, _cellSpursEventFlagInitialize);
cellSpurs.AddFunc(0x87630976, cellSpursEventFlagAttachLv2EventQueue);
cellSpurs.AddFunc(0x22aab31d, cellSpursEventFlagDetachLv2EventQueue);
cellSpurs.AddFunc(0x373523d4, cellSpursEventFlagWait);
cellSpurs.AddFunc(0x32b94add, cellSpursEnableExceptionEventHandler);
cellSpurs.AddFunc(0x7517724a, cellSpursSetGlobalExceptionEventHandler);
cellSpurs.AddFunc(0x861237f8, cellSpursUnsetGlobalExceptionEventHandler);
cellSpurs.AddFunc(0x1f402f8f, cellSpursGetInfo);
cellSpurs.AddFunc(0xe0a6dbe4, _cellSpursSendSignal);
//libspurs task functions
cellSpurs.AddFunc(0x52cc6c82, cellSpursCreateTaskset);
cellSpurs.AddFunc(0x9f72add3, cellSpursJoinTaskset);
cellSpurs.AddFunc(0xe7dd87e1, cellSpursGetTasksetId);
cellSpurs.AddFunc(0xa789e631, cellSpursShutdownTaskset);
cellSpurs.AddFunc(0xbeb600ac, cellSpursCreateTask);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "Emu/Cell/SPURSManager.h"
// return codes
// Core return codes.
enum
{
CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701,
@ -14,39 +15,38 @@ enum
CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711,
};
//defines
enum SPURSKernelInterfaces
// Task return codes.
enum
{
CELL_SPURS_MAX_SPU = 8,
CELL_SPURS_MAX_WORKLOAD = 16,
CELL_SPURS_MAX_WORKLOAD2 = 32,
CELL_SPURS_MAX_PRIORITY = 16,
CELL_SPURS_NAME_MAX_LENGTH = 15,
CELL_SPURS_SIZE = 4096,
CELL_SPURS_SIZE2 = 8192,
CELL_SPURS_ALIGN = 128,
CELL_SPURS_ATTRIBUTE_SIZE = 512,
CELL_SPURS_ATTRIBUTE_ALIGN = 8,
CELL_SPURS_INTERRUPT_VECTOR = 0x0,
CELL_SPURS_LOCK_LINE = 0x80,
CELL_SPURS_KERNEL_DMA_TAG_ID = 31,
CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901,
CELL_SPURS_TASK_ERROR_INVAL = 0x80410902,
CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904,
CELL_SPURS_TASK_ERROR_SRCH = 0x80410905,
CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907,
CELL_SPURS_TASK_ERROR_PERM = 0x80410909,
CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A,
CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D,
CELL_SPURS_TASK_ERROR_STAT = 0x8041090F,
CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910,
CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911,
CELL_SPURS_TASK_ERROR_FATAL = 0x80410914,
CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920,
};
enum RangeofEventQueuePortNumbers
{
CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15,
CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16,
CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63,
// Core CellSpurs structures.
struct CellSpurs
{
SPURSManager *spurs;
};
enum SPURSTraceTypes
{
CELL_SPURS_TRACE_TAG_LOAD = 0x2a,
CELL_SPURS_TRACE_TAG_MAP = 0x2b,
CELL_SPURS_TRACE_TAG_START = 0x2c,
CELL_SPURS_TRACE_TAG_STOP = 0x2d,
CELL_SPURS_TRACE_TAG_USER = 0x2e,
CELL_SPURS_TRACE_TAG_GUID = 0x2f,
struct CellSpurs2
{
SPURSManager *spurs;
};
struct CellSpursAttribute
{
SPURSManagerAttribute *attr;
};
struct CellSpursInfo
@ -87,7 +87,6 @@ struct CellSpursTraceInfo
//u8 padding[];
};
//__declspec(align(8))
struct CellTraceHeader
{
u8 tag;
@ -136,67 +135,18 @@ struct CellSpursTracePacket
} data;
};
//__declspec(align(128))
struct CellSpurs
{
u8 skip[CELL_SPURS_SIZE];
};
//__declspec(align(128))
struct CellSpurs2
{
u8 skip[CELL_SPURS_SIZE2 - CELL_SPURS_SIZE];
};
//__declspec(align(8))
struct CellSpursAttribute
{
u8 skip[CELL_SPURS_ATTRIBUTE_SIZE];
};
//typedef unsigned CellSpursWorkloadId;
typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, const mem_ptr_t<CellSpursExceptionInfo> info,
uint id, mem_ptr_t<void> arg);
// task datatypes and constans
enum TaskConstants
{
CELL_SPURS_MAX_TASK = 128,
CELL_SPURS_TASK_TOP = 0x3000,
CELL_SPURS_TASK_BOTTOM = 0x40000,
CELL_SPURS_MAX_TASK_NAME_LENGTH = 32,
};
enum
{
CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901,
CELL_SPURS_TASK_ERROR_INVAL = 0x80410902,
CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904,
CELL_SPURS_TASK_ERROR_SRCH = 0x80410905,
CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907,
CELL_SPURS_TASK_ERROR_PERM = 0x80410909,
CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A,
CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D,
CELL_SPURS_TASK_ERROR_STAT = 0x8041090F,
CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910,
CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911,
CELL_SPURS_TASK_ERROR_FATAL = 0x80410914,
CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920,
};
//__declspec(align(128))
// cellSpurs taskset structures.
struct CellSpursTaskset
{
u8 skip[6400];
};
typedef void(*CellSpursTasksetExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
uint idTask, const mem_ptr_t<CellSpursExceptionInfo> info, mem_ptr_t<void> arg);
// Exception handlers.
typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, const mem_ptr_t<CellSpursExceptionInfo> info,
uint id, mem_ptr_t<void> arg);
typedef void (*CellSpursTasksetExceptionEventHandler)(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursTaskset> taskset,
uint idTask, const mem_ptr_t<CellSpursExceptionInfo> info, mem_ptr_t<void> arg);
struct CellSpursTasksetInfo
{
@ -211,18 +161,6 @@ struct CellSpursTasksetInfo
//be_t<u8> reserved[];
};
/*
#define CELL_SPURS_TASKSET_CLASS0_SIZE (128 * 50)
#define _CELL_SPURS_TASKSET_CLASS1_EXTENDED_SIZE (128 + 128 * 16 + 128 * 15)
#define CELL_SPURS_TASKSET_CLASS1_SIZE (CELL_SPURS_TASKSET_CLASS0_SIZE + _CELL_SPURS_TASKSET_CLASS1_EXTENDED_SIZE)
#define CELL_SPURS_TASKSET2_SIZE (CELL_SPURS_TASKSET_CLASS1_SIZE)
#define CELL_SPURS_TASKSET2_ALIGN 128
#define CELL_SPURS_TASKSET_ALIGN 128
#define CELL_SPURS_TASKSET_SIZE CELL_SPURS_TASKSET_CLASS0_SIZE
*/
//__declspec(align(128))
struct CellSpursTaskset2
{
be_t<u8> skip[10496];
@ -240,6 +178,7 @@ struct CellSpursTasksetAttribute2
//be_t<u32> __reserved__[];
};
// cellSpurs task structures.
struct CellSpursTaskNameBuffer
{
char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH];
@ -273,7 +212,6 @@ struct CellSpursTaskAttribute2
//be_t<u32> __reserved__[];
};
//__declspec(align(128))
struct CellSpursTaskExitCode
{
unsigned char skip[128];
@ -301,3 +239,7 @@ struct CellSpursTaskBinInfo
CellSpursTaskLsPattern lsPattern;
};
// cellSpurs event flag.
struct CellSpursEventFlag {
u8 skip[128];
};

View File

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/SysCalls/SysCalls.h"
#include "Emu/SysCalls/SC_FUNC.h"
#include "Crypto/unedat.h"
#include "sceNp.h"
void sceNp_init();
@ -23,8 +23,8 @@ int sceNpDrmIsAvailable(u32 k_licensee_addr, u32 drm_path_addr)
{
sceNp.Warning("sceNpDrmIsAvailable(k_licensee_addr=0x%x, drm_path_addr=0x%x)", k_licensee_addr, drm_path_addr);
wxString k_licensee_str;
wxString drm_path = Memory.ReadString(drm_path_addr);
wxString k_licensee_str;
u8 k_licensee[0x10];
for(int i = 0; i < 0x10; i++)
{
@ -35,6 +35,41 @@ int sceNpDrmIsAvailable(u32 k_licensee_addr, u32 drm_path_addr)
sceNp.Warning("sceNpDrmIsAvailable: Found DRM license file at %s", drm_path.wx_str());
sceNp.Warning("sceNpDrmIsAvailable: Using k_licensee 0x%s", k_licensee_str.wx_str());
// Set the necessary file paths.
wxString drm_file_name = drm_path.AfterLast('/');
wxString titleID = drm_path.AfterFirst('/').AfterFirst('/').AfterFirst('/').BeforeFirst('/');
wxString enc_drm_path = wxGetCwd() + drm_path;
wxString dec_drm_path = wxGetCwd() + "/dev_hdd1/" + titleID + "/" + drm_file_name;
wxString rap_dir_path = wxGetCwd() + "/dev_usb000/";
wxString rap_file_path = rap_dir_path;
// Search dev_usb000 for a compatible RAP file.
vfsDir *raps_dir = new vfsDir(rap_dir_path);
if (!raps_dir->IsOpened())
sceNp.Warning("sceNpDrmIsAvailable: Can't find RAP file for DRM!");
else
{
Array<DirEntryInfo> entries = raps_dir->GetEntries();
for (unsigned int i = 0; i < entries.GetCount(); i++)
{
if (entries[i].name.Contains(titleID))
{
rap_file_path += entries[i].name;
break;
}
}
}
// Create a new directory under dev_hdd1/titleID to hold the decrypted data.
wxString tmp_dir = wxGetCwd() + "/dev_hdd1/" + titleID;
if (!wxDir::Exists(tmp_dir))
wxMkdir(wxGetCwd() + "/dev_hdd1/" + titleID);
// Decrypt this EDAT using the supplied k_licensee and matching RAP file.
DecryptEDAT(enc_drm_path.ToStdString(), dec_drm_path.ToStdString(), 8, rap_file_path.ToStdString(), k_licensee, false);
return CELL_OK;
}

View File

@ -33,12 +33,12 @@ struct FsRingBufferConfig
, m_alloc_mem_size(0)
, m_current_addr(0)
{
memset(&m_ring_buffer, 0, sizeof(FsRingBufferConfig));
memset(&m_ring_buffer, 0, sizeof(FsRingBuffer));
}
~FsRingBufferConfig()
{
memset(&m_ring_buffer, 0, sizeof(FsRingBufferConfig));
memset(&m_ring_buffer, 0, sizeof(FsRingBuffer));
}
} m_fs_config;

View File

@ -391,7 +391,7 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event))
if(Memory.IsGoodAddr(sh_addr))
{
for(u64 addr=sh_addr; addr<sh_addr+sh_size; addr, vsize++)
for(u64 addr=sh_addr; addr<sh_addr+sh_size; addr++, vsize++)
{
disasm->dump_pc = addr;
decoder->Decode(Memory.Read32(disasm->dump_pc));

View File

@ -87,7 +87,7 @@ void VHDDExplorer::UpdateList()
{
m_list->Freeze();
m_list->DeleteAllItems();
m_entries.Clear();
m_entries.clear();
m_names.Clear();
u64 block;
@ -101,7 +101,7 @@ void VHDDExplorer::UpdateList()
m_list->SetItem(item, 1, entry.type == vfsHDD_Entry_Dir ? "Dir" : "File");
m_list->SetItem(item, 2, wxString::Format("%lld", entry.size));
m_list->SetItem(item, 3, wxDateTime().Set(time_t(entry.ctime)).Format());
m_entries.AddCpy(entry);
m_entries.push_back(entry);
m_names.Add(name);
}
@ -397,7 +397,7 @@ VHDDManagerDialog::VHDDManagerDialog(wxWindow* parent)
Connect(id_remove, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(VHDDManagerDialog::OnRemove));
Connect(id_create_hdd, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(VHDDManagerDialog::OnCreateHDD));
Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(VHDDManagerDialog::OnClose));
LoadPathes();
LoadPaths();
UpdateList();
}
@ -406,9 +406,9 @@ void VHDDManagerDialog::UpdateList()
m_list->Freeze();
m_list->DeleteAllItems();
for(size_t i=0; i<m_pathes.GetCount(); ++i)
for(size_t i=0; i<m_paths.size(); ++i)
{
m_list->InsertItem(i, m_pathes[i]);
m_list->InsertItem(i, m_paths[i]);
}
m_list->SetColumnWidth(0, wxLIST_AUTOSIZE_USEHEADER);
@ -420,7 +420,7 @@ void VHDDManagerDialog::UpdateList()
void VHDDManagerDialog::Open(int sel)
{
VHDDExplorer dial(this, m_pathes[sel]);
VHDDExplorer dial(this, m_paths[sel]);
dial.ShowModal();
}
@ -439,14 +439,14 @@ void VHDDManagerDialog::AddHDD(wxCommandEvent& event)
return;
}
wxArrayString pathes;
ctrl.GetPaths(pathes);
for(size_t i=0; i<pathes.GetCount(); ++i)
wxArrayString paths;
ctrl.GetPaths(paths);
for(size_t i=0; i<paths.GetCount(); ++i)
{
bool skip = false;
for(size_t j=0; j<m_pathes.GetCount(); ++j)
for(size_t j=0; j<m_paths.size(); ++j)
{
if(m_pathes[j].CmpNoCase(pathes[i]) == 0)
if(m_paths[j].CmpNoCase(paths[i]) == 0)
{
skip = true;
break;
@ -455,7 +455,7 @@ void VHDDManagerDialog::AddHDD(wxCommandEvent& event)
if(!skip)
{
m_pathes.Move(new wxString(pathes[i].c_str()));
m_paths.emplace_back(paths[i]);
}
}
UpdateList();
@ -483,7 +483,7 @@ void VHDDManagerDialog::OnRemove(wxCommandEvent& event)
{
for(int sel = m_list->GetNextSelected(-1), offs = 0; sel != wxNOT_FOUND; sel = m_list->GetNextSelected(sel), --offs)
{
m_pathes.RemoveAt(sel + offs);
m_paths.erase(m_paths.begin() + (sel + offs));
}
UpdateList();
@ -506,44 +506,42 @@ void VHDDManagerDialog::OnCreateHDD(wxCommandEvent& event)
u64 size, bsize;
dial.GetResult(size, bsize);
vfsHDDManager::CreateHDD(ctrl.GetPath(), size, bsize);
m_pathes.AddCpy(ctrl.GetPath());
m_paths.push_back(ctrl.GetPath());
UpdateList();
}
}
void VHDDManagerDialog::OnClose(wxCloseEvent& event)
{
SavePathes();
SavePaths();
event.Skip();
}
void VHDDManagerDialog::LoadPathes()
void VHDDManagerDialog::LoadPaths()
{
IniEntry<int> path_count;
path_count.Init("path_count", "HDDManager");
int count = 0;
count = path_count.LoadValue(count);
m_pathes.SetCount(count);
for(size_t i=0; i<m_pathes.GetCount(); ++i)
for(size_t i=0; i<count; ++i)
{
IniEntry<wxString> path_entry;
path_entry.Init(wxString::Format("path[%d]", i), "HDDManager");
new (m_pathes + i) wxString(path_entry.LoadValue(wxEmptyString));
m_paths.emplace_back(path_entry.LoadValue(wxEmptyString));
}
}
void VHDDManagerDialog::SavePathes()
void VHDDManagerDialog::SavePaths()
{
IniEntry<int> path_count;
path_count.Init("path_count", "HDDManager");
path_count.SaveValue(m_pathes.GetCount());
path_count.SaveValue(m_paths.size());
for(size_t i=0; i<m_pathes.GetCount(); ++i)
for(size_t i=0; i<m_paths.size(); ++i)
{
IniEntry<wxString> path_entry;
path_entry.Init(wxString::Format("path[%d]", i), "HDDManager");
path_entry.SaveValue(m_pathes[i]);
path_entry.SaveValue(m_paths[i]);
}
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <vector>
#include <wx/dnd.h>
#include "Emu/HDD/HDD.h"
@ -20,7 +21,7 @@ public:
class VHDDExplorer : public wxDialog
{
Array<vfsHDD_Entry> m_entries;
std::vector<vfsHDD_Entry> m_entries;
wxArrayString m_names;
wxListView* m_list;
vfsHDD* m_hdd;
@ -65,7 +66,7 @@ public:
class VHDDManagerDialog : public wxDialog
{
Array<wxString> m_pathes;
std::vector<wxString> m_paths;
wxListView* m_list;
public:
@ -82,6 +83,6 @@ public:
void OnCreateHDD(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
void LoadPathes();
void SavePathes();
void LoadPaths();
void SavePaths();
};

View File

@ -212,6 +212,7 @@
<ClCompile Include="Crypto\aes.cpp" />
<ClCompile Include="Crypto\key_vault.cpp" />
<ClCompile Include="Crypto\sha1.cpp" />
<ClCompile Include="Crypto\unedat.cpp" />
<ClCompile Include="Crypto\unpkg.cpp" />
<ClCompile Include="Crypto\unself.cpp" />
<ClCompile Include="Crypto\utils.cpp" />
@ -225,6 +226,7 @@
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" />
<ClCompile Include="Emu\Cell\PPUThread.cpp" />
<ClCompile Include="Emu\Cell\RawSPUThread.cpp" />
<ClCompile Include="Emu\Cell\SPURSManager.cpp" />
<ClCompile Include="Emu\Cell\SPUThread.cpp" />
<ClCompile Include="Emu\CPU\CPUThread.cpp" />
<ClCompile Include="Emu\CPU\CPUThreadManager.cpp" />
@ -365,6 +367,7 @@
<ClInclude Include="Crypto\aes.h" />
<ClInclude Include="Crypto\key_vault.h" />
<ClInclude Include="Crypto\sha1.h" />
<ClInclude Include="Crypto\unedat.h" />
<ClInclude Include="Crypto\unpkg.h" />
<ClInclude Include="Crypto\unself.h" />
<ClInclude Include="Crypto\utils.h" />
@ -387,6 +390,7 @@
<ClInclude Include="Emu\Cell\SPUDisAsm.h" />
<ClInclude Include="Emu\Cell\SPUInterpreter.h" />
<ClInclude Include="Emu\Cell\SPUOpcodes.h" />
<ClInclude Include="Emu\Cell\SPURSManager.h" />
<ClInclude Include="Emu\Cell\SPUThread.h" />
<ClInclude Include="Emu\DbgConsole.h" />
<ClInclude Include="Emu\GameInfo.h" />

View File

@ -478,6 +478,12 @@
<ClCompile Include="Emu\SysCalls\Modules\cellSysutil_SaveData.cpp">
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Crypto\unedat.cpp">
<Filter>Crypto</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\SPURSManager.cpp">
<Filter>Emu\Cell</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />
@ -681,5 +687,11 @@
<ClInclude Include="Crypto\utils.h">
<Filter>Crypto</Filter>
</ClInclude>
<ClInclude Include="Crypto\unedat.h">
<Filter>Crypto</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPURSManager.h">
<Filter>Include</Filter>
</ClInclude>
</ItemGroup>
</Project>