diff --git a/rpcs3/Crypto/aes.cpp b/rpcs3/Crypto/aes.cpp index 7927e70b4a..8b411732e0 100644 --- a/rpcs3/Crypto/aes.cpp +++ b/rpcs3/Crypto/aes.cpp @@ -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 @@ -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]; +} \ No newline at end of file diff --git a/rpcs3/Crypto/aes.h b/rpcs3/Crypto/aes.h index efac0130bf..7a9c20a567 100644 --- a/rpcs3/Crypto/aes.h +++ b/rpcs3/Crypto/aes.h @@ -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 @@ -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 +#ifdef _MSC_VER +#include +typedef UINT32 uint32_t; +#else +#include +#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 \ No newline at end of file diff --git a/rpcs3/Crypto/key_vault.cpp b/rpcs3/Crypto/key_vault.cpp index 5c145a8e73..4926a428db 100644 --- a/rpcs3/Crypto/key_vault.cpp +++ b/rpcs3/Crypto/key_vault.cpp @@ -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; diff --git a/rpcs3/Crypto/key_vault.h b/rpcs3/Crypto/key_vault.h index bd01797c70..3fbd2b5ff1 100644 --- a/rpcs3/Crypto/key_vault.h +++ b/rpcs3/Crypto/key_vault.h @@ -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); -}; \ No newline at end of file +}; + +// RAP to RIF function. +void rap_to_rif(unsigned char* rap, unsigned char* rif); \ No newline at end of file diff --git a/rpcs3/Crypto/sha1.cpp b/rpcs3/Crypto/sha1.cpp index 78faccf7ac..8e6177c0e7 100644 --- a/rpcs3/Crypto/sha1.cpp +++ b/rpcs3/Crypto/sha1.cpp @@ -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 - * - * 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 + * + * 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 ) ); +} \ No newline at end of file diff --git a/rpcs3/Crypto/sha1.h b/rpcs3/Crypto/sha1.h index 9ec45b200c..9272d94746 100644 --- a/rpcs3/Crypto/sha1.h +++ b/rpcs3/Crypto/sha1.h @@ -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 - * - * 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 - -/** - * \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 + * + * 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 + +#ifdef _MSC_VER +#include +typedef UINT32 uint32_t; +#else +#include +#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 \ No newline at end of file diff --git a/rpcs3/Crypto/unedat.cpp b/rpcs3/Crypto/unedat.cpp new file mode 100644 index 0000000000..03dddf89ce --- /dev/null +++ b/rpcs3/Crypto/unedat.cpp @@ -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; +} \ No newline at end of file diff --git a/rpcs3/Crypto/unedat.h b/rpcs3/Crypto/unedat.h new file mode 100644 index 0000000000..01ce706f3f --- /dev/null +++ b/rpcs3/Crypto/unedat.h @@ -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); \ No newline at end of file diff --git a/rpcs3/Crypto/unpkg.h b/rpcs3/Crypto/unpkg.h index b59fceb30e..cb89f8dbee 100644 --- a/rpcs3/Crypto/unpkg.h +++ b/rpcs3/Crypto/unpkg.h @@ -1,6 +1,5 @@ #pragma once -#include "aes.h" -#include "sha1.h" +#include "utils.h" #include "key_vault.h" // Constants diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 3a10863859..dd04f2d754 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -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; } diff --git a/rpcs3/Crypto/unself.h b/rpcs3/Crypto/unself.h index 3c0dd395e3..df721a588a 100644 --- a/rpcs3/Crypto/unself.h +++ b/rpcs3/Crypto/unself.h @@ -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" diff --git a/rpcs3/Crypto/utils.cpp b/rpcs3/Crypto/utils.cpp index bc42cb9994..5df31b17e7 100644 --- a/rpcs3/Crypto/utils.cpp +++ b/rpcs3/Crypto/utils.cpp @@ -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 Lempel–Ziv–Markov 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; } \ No newline at end of file diff --git a/rpcs3/Crypto/utils.h b/rpcs3/Crypto/utils.h index 4e3f59e65f..51bc56eba3 100644 --- a/rpcs3/Crypto/utils.h +++ b/rpcs3/Crypto/utils.h @@ -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); \ No newline at end of file +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 Lempel–Ziv–Markov based compression (unknown variant of LZRC). +int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size); \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPURSManager.cpp b/rpcs3/Emu/Cell/SPURSManager.cpp new file mode 100644 index 0000000000..83548482dd --- /dev/null +++ b/rpcs3/Emu/Cell/SPURSManager.cpp @@ -0,0 +1,12 @@ +#include "stdafx.h" +#include "SPURSManager.h" + +SPURSManager::SPURSManager(SPURSManagerAttribute *attr) +{ + this->attr = attr; +} + +void SPURSManager::Finalize() +{ + delete this->attr; +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPURSManager.h b/rpcs3/Emu/Cell/SPURSManager.h new file mode 100644 index 0000000000..4f22f5b8f2 --- /dev/null +++ b/rpcs3/Emu/Cell/SPURSManager.h @@ -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 nSpus; + be_t spuThreadGroupPriority; + be_t ppuThreadPriority; + bool exitIfNoWork; + char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1]; + be_t threadGroupType; +}; + +// Main SPURS manager class. +class SPURSManager +{ +public: + SPURSManager(SPURSManagerAttribute *attr); + void Finalize(); + +protected: + SPURSManagerAttribute *attr; +}; \ No newline at end of file diff --git a/rpcs3/Emu/HDD/HDD.h b/rpcs3/Emu/HDD/HDD.h index ba7c86e0ed..2a6afe07dc 100644 --- a/rpcs3/Emu/HDD/HDD.h +++ b/rpcs3/Emu/HDD/HDD.h @@ -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) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 15cd57b4a3..71bade3785 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -6,12 +6,69 @@ void cellSpurs_init(); Module cellSpurs(0x000a, cellSpurs_init); +int cellSpursInitialize(mem_ptr_t 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 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 spurs, const mem_ptr_t 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 spurs, const mem_ptr_t 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 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 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 attr, const me int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t 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 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 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 spurs, const mem_ptr_t 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 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 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 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 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 spurs, uint workloadId, uint maxContention) +int cellSpursSetMaxContention(mem_ptr_t 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 spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU]) +int cellSpursSetPriorities(mem_ptr_t 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 spurs, uint workloadId, uint spuId, uint priority) +int cellSpursSetPriority(mem_ptr_t 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 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 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 spurs, u32 queue, mem8_t p int cellSpursDetachLv2EventQueue(mem_ptr_t 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 spurs, mem_ptr_t taskset, + mem_ptr_t 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 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 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 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 spurs, u8 port) int cellSpursEnableExceptionEventHandler(mem_ptr_t 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 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 spurs, int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t 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 spurs) int cellSpursGetInfo(mem_ptr_t spurs, mem_ptr_t 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 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 spurs, mem_ptr_t 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 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 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 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 taskset, mem32_t taskID, mem_ptr_t elf_addr, + mem_ptr_t context_addr, u32 context_size, mem_ptr_t lsPattern, + mem_ptr_t 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); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index bc9f70b848..a72e3f2816 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -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 spurs, const mem_ptr_t info, - uint id, mem_ptr_t 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 spurs, mem_ptr_t taskset, - uint idTask, const mem_ptr_t info, mem_ptr_t arg); +// Exception handlers. +typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t spurs, const mem_ptr_t info, + uint id, mem_ptr_t arg); +typedef void (*CellSpursTasksetExceptionEventHandler)(mem_ptr_t spurs, mem_ptr_t taskset, + uint idTask, const mem_ptr_t info, mem_ptr_t arg); struct CellSpursTasksetInfo { @@ -211,18 +161,6 @@ struct CellSpursTasksetInfo //be_t 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 skip[10496]; @@ -240,6 +178,7 @@ struct CellSpursTasksetAttribute2 //be_t __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 __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]; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp index 2846199ff8..5a9319dc1a 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp @@ -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 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; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index c006439d1e..5dcdf1a12f 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -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; diff --git a/rpcs3/Gui/DisAsmFrame.cpp b/rpcs3/Gui/DisAsmFrame.cpp index 3d0c152dd8..d9520348fa 100644 --- a/rpcs3/Gui/DisAsmFrame.cpp +++ b/rpcs3/Gui/DisAsmFrame.cpp @@ -391,7 +391,7 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event)) if(Memory.IsGoodAddr(sh_addr)) { - for(u64 addr=sh_addr; addrdump_pc = addr; decoder->Decode(Memory.Read32(disasm->dump_pc)); diff --git a/rpcs3/Gui/VHDDManager.cpp b/rpcs3/Gui/VHDDManager.cpp index bc16439916..f64bef72b3 100644 --- a/rpcs3/Gui/VHDDManager.cpp +++ b/rpcs3/Gui/VHDDManager.cpp @@ -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; iInsertItem(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; iGetNextSelected(-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 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 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 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 path_entry; path_entry.Init(wxString::Format("path[%d]", i), "HDDManager"); - path_entry.SaveValue(m_pathes[i]); + path_entry.SaveValue(m_paths[i]); } } diff --git a/rpcs3/Gui/VHDDManager.h b/rpcs3/Gui/VHDDManager.h index 744760f27e..8632f225bb 100644 --- a/rpcs3/Gui/VHDDManager.h +++ b/rpcs3/Gui/VHDDManager.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include "Emu/HDD/HDD.h" @@ -20,7 +21,7 @@ public: class VHDDExplorer : public wxDialog { - Array m_entries; + std::vector m_entries; wxArrayString m_names; wxListView* m_list; vfsHDD* m_hdd; @@ -65,7 +66,7 @@ public: class VHDDManagerDialog : public wxDialog { - Array m_pathes; + std::vector 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(); }; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 2ae058702f..80574729e6 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -212,6 +212,7 @@ + @@ -225,6 +226,7 @@ + @@ -365,6 +367,7 @@ + @@ -387,6 +390,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 9450c462e2..b82ef165e5 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -478,6 +478,12 @@ Emu\SysCalls\Modules + + Crypto + + + Emu\Cell + @@ -681,5 +687,11 @@ Crypto + + Crypto + + + Include + \ No newline at end of file