mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-20 22:05:12 +00:00
split rpcs3 and hle libraries
merge rpcs3 utilities
This commit is contained in:
parent
b33e2662b6
commit
62ad27d1e2
1233 changed files with 7004 additions and 3819 deletions
1010
rpcs3/Crypto/aes.cpp
Normal file
1010
rpcs3/Crypto/aes.cpp
Normal file
File diff suppressed because it is too large
Load diff
179
rpcs3/Crypto/aes.h
Normal file
179
rpcs3/Crypto/aes.h
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
#pragma once
|
||||
#define POLARSSL_AES_ROM_TABLES
|
||||
/**
|
||||
* \file aes.h
|
||||
*
|
||||
* \brief AES block cipher
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <basetsd.h>
|
||||
typedef UINT32 uint32_t;
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#define 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 */
|
||||
uint32_t* rk; /*!< AES round keys */
|
||||
uint32_t buf[68]; /*!< unaligned data */
|
||||
} aes_context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize);
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_dec(aes_context* ctx, const unsigned char* key, unsigned int keysize);
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ecb(aes_context* ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16]);
|
||||
|
||||
/**
|
||||
* \brief AES-CBC buffer encryption/decryption
|
||||
* Length should be a multiple of the block
|
||||
* size (16 bytes)
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \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, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
|
||||
*/
|
||||
int aes_crypt_cbc(aes_context* ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
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!
|
||||
*
|
||||
* Note: Due to the nature of CTR 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.
|
||||
*
|
||||
* \param length The length of the data
|
||||
* \param nc_off The offset in the current stream_block (for resuming
|
||||
* within current cipher stream). The offset pointer to
|
||||
* should be 0 at the start of a stream.
|
||||
* \param nonce_counter The 128-bit nonce and counter.
|
||||
* \param stream_block The saved stream-block for resuming. Is overwritten
|
||||
* by the function.
|
||||
* \param input The input data stream
|
||||
* \param output The output data stream
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ctr(aes_context* ctx,
|
||||
size_t length,
|
||||
size_t* nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char* input,
|
||||
unsigned char* output);
|
||||
|
||||
void aes_cmac(aes_context* ctx, size_t length, unsigned char* input, unsigned char* output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
686
rpcs3/Crypto/aesni.cpp
Normal file
686
rpcs3/Crypto/aesni.cpp
Normal file
|
|
@ -0,0 +1,686 @@
|
|||
#if defined(__SSE2__) || defined(_M_X64)
|
||||
|
||||
/*
|
||||
* AES-NI support functions
|
||||
*
|
||||
* Copyright (C) 2013, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
|
||||
* [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
|
||||
*/
|
||||
|
||||
#include "aesni.h"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_X64)
|
||||
#define POLARSSL_HAVE_MSVC_X64_INTRINSICS
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AES-NI support detection routine
|
||||
*/
|
||||
int aesni_supports(unsigned int what)
|
||||
{
|
||||
static int done = 0;
|
||||
static unsigned int c = 0;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
int regs[4]; // eax, ebx, ecx, edx
|
||||
__cpuid(regs, 1);
|
||||
c = regs[2];
|
||||
#else
|
||||
asm("movl $1, %%eax \n"
|
||||
"cpuid \n"
|
||||
: "=c"(c)
|
||||
:
|
||||
: "eax", "ebx", "edx");
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
done = 1;
|
||||
}
|
||||
|
||||
return ((c & what) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-NI AES-ECB block en(de)cryption
|
||||
*/
|
||||
int aesni_crypt_ecb(aes_context* ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16])
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
__m128i *rk, a;
|
||||
int i;
|
||||
|
||||
rk = (__m128i*)ctx->rk;
|
||||
a = _mm_xor_si128(_mm_loadu_si128((__m128i*)input), _mm_loadu_si128(rk++));
|
||||
|
||||
if (mode == AES_ENCRYPT)
|
||||
{
|
||||
for (i = ctx->nr - 1; i; --i)
|
||||
a = _mm_aesenc_si128(a, _mm_loadu_si128(rk++));
|
||||
a = _mm_aesenclast_si128(a, _mm_loadu_si128(rk));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = ctx->nr - 1; i; --i)
|
||||
a = _mm_aesdec_si128(a, _mm_loadu_si128(rk++));
|
||||
a = _mm_aesdeclast_si128(a, _mm_loadu_si128(rk));
|
||||
}
|
||||
|
||||
_mm_storeu_si128((__m128i*)output, a);
|
||||
#else
|
||||
asm("movdqu (%3), %%xmm0 \n" // load input
|
||||
"movdqu (%1), %%xmm1 \n" // load round key 0
|
||||
"pxor %%xmm1, %%xmm0 \n" // round 0
|
||||
"addq $16, %1 \n" // point to next round key
|
||||
"subl $1, %0 \n" // normal rounds = nr - 1
|
||||
"test %2, %2 \n" // mode?
|
||||
"jz 2f \n" // 0 = decrypt
|
||||
|
||||
"1: \n" // encryption loop
|
||||
"movdqu (%1), %%xmm1 \n" // load round key
|
||||
"aesenc %%xmm1, %%xmm0 \n" // do round
|
||||
"addq $16, %1 \n" // point to next round key
|
||||
"subl $1, %0 \n" // loop
|
||||
"jnz 1b \n"
|
||||
"movdqu (%1), %%xmm1 \n" // load round key
|
||||
"aesenclast %%xmm1, %%xmm0 \n" // last round
|
||||
"jmp 3f \n"
|
||||
|
||||
"2: \n" // decryption loop
|
||||
"movdqu (%1), %%xmm1 \n"
|
||||
"aesdec %%xmm1, %%xmm0 \n"
|
||||
"addq $16, %1 \n"
|
||||
"subl $1, %0 \n"
|
||||
"jnz 2b \n"
|
||||
"movdqu (%1), %%xmm1 \n" // load round key
|
||||
"aesdeclast %%xmm1, %%xmm0 \n" // last round
|
||||
|
||||
"3: \n"
|
||||
"movdqu %%xmm0, (%4) \n" // export output
|
||||
:
|
||||
: "r"(ctx->nr), "r"(ctx->rk), "r"(mode), "r"(input), "r"(output)
|
||||
: "memory", "cc", "xmm0", "xmm1");
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
static inline void clmul256(__m128i a, __m128i b, __m128i* r0, __m128i* r1)
|
||||
{
|
||||
__m128i c, d, e, f, ef;
|
||||
c = _mm_clmulepi64_si128(a, b, 0x00);
|
||||
d = _mm_clmulepi64_si128(a, b, 0x11);
|
||||
e = _mm_clmulepi64_si128(a, b, 0x10);
|
||||
f = _mm_clmulepi64_si128(a, b, 0x01);
|
||||
|
||||
// r0 = f0^e0^c1:c0 = c1:c0 ^ f0^e0:0
|
||||
// r1 = d1:f1^e1^d0 = d1:d0 ^ 0:f1^e1
|
||||
|
||||
ef = _mm_xor_si128(e, f);
|
||||
*r0 = _mm_xor_si128(c, _mm_slli_si128(ef, 8));
|
||||
*r1 = _mm_xor_si128(d, _mm_srli_si128(ef, 8));
|
||||
}
|
||||
|
||||
static inline void sll256(__m128i a0, __m128i a1, __m128i* s0, __m128i* s1)
|
||||
{
|
||||
__m128i l0, l1, r0, r1;
|
||||
|
||||
l0 = _mm_slli_epi64(a0, 1);
|
||||
l1 = _mm_slli_epi64(a1, 1);
|
||||
|
||||
r0 = _mm_srli_epi64(a0, 63);
|
||||
r1 = _mm_srli_epi64(a1, 63);
|
||||
|
||||
*s0 = _mm_or_si128(l0, _mm_slli_si128(r0, 8));
|
||||
*s1 = _mm_or_si128(_mm_or_si128(l1, _mm_srli_si128(r0, 8)), _mm_slli_si128(r1, 8));
|
||||
}
|
||||
|
||||
static inline __m128i reducemod128(__m128i x10, __m128i x32)
|
||||
{
|
||||
__m128i a, b, c, dx0, e, f, g, h;
|
||||
|
||||
// (1) left shift x0 by 63, 62 and 57
|
||||
a = _mm_slli_epi64(x10, 63);
|
||||
b = _mm_slli_epi64(x10, 62);
|
||||
c = _mm_slli_epi64(x10, 57);
|
||||
|
||||
// (2) compute D xor'ing a, b, c and x1
|
||||
// d:x0 = x1:x0 ^ [a^b^c:0]
|
||||
dx0 = _mm_xor_si128(x10, _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(a, b), c), 8));
|
||||
|
||||
// (3) right shift [d:x0] by 1, 2, 7
|
||||
e = _mm_or_si128(_mm_srli_epi64(dx0, 1), _mm_srli_si128(_mm_slli_epi64(dx0, 63), 8));
|
||||
f = _mm_or_si128(_mm_srli_epi64(dx0, 2), _mm_srli_si128(_mm_slli_epi64(dx0, 62), 8));
|
||||
g = _mm_or_si128(_mm_srli_epi64(dx0, 7), _mm_srli_si128(_mm_slli_epi64(dx0, 57), 8));
|
||||
|
||||
// (4) compute h = d^e1^f1^g1 : x0^e0^f0^g0
|
||||
h = _mm_xor_si128(dx0, _mm_xor_si128(e, _mm_xor_si128(f, g)));
|
||||
|
||||
// result is x3^h1:x2^h0
|
||||
return _mm_xor_si128(x32, h);
|
||||
}
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
|
||||
/*
|
||||
* GCM multiplication: c = a times b in GF(2^128)
|
||||
* Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
|
||||
*/
|
||||
void aesni_gcm_mult(unsigned char c[16],
|
||||
const unsigned char a[16],
|
||||
const unsigned char b[16])
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
__m128i xa, xb, m0, m1, x10, x32, r;
|
||||
|
||||
xa.m128i_u64[1] = _byteswap_uint64(*((unsigned __int64*)a + 0));
|
||||
xa.m128i_u64[0] = _byteswap_uint64(*((unsigned __int64*)a + 1));
|
||||
xb.m128i_u64[1] = _byteswap_uint64(*((unsigned __int64*)b + 0));
|
||||
xb.m128i_u64[0] = _byteswap_uint64(*((unsigned __int64*)b + 1));
|
||||
|
||||
clmul256(xa, xb, &m0, &m1);
|
||||
sll256(m0, m1, &x10, &x32);
|
||||
r = reducemod128(x10, x32);
|
||||
|
||||
*((unsigned __int64*)c + 0) = _byteswap_uint64(r.m128i_u64[1]);
|
||||
*((unsigned __int64*)c + 1) = _byteswap_uint64(r.m128i_u64[0]);
|
||||
#else
|
||||
unsigned char aa[16], bb[16], cc[16];
|
||||
size_t i;
|
||||
|
||||
/* The inputs are in big-endian order, so byte-reverse them */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
aa[i] = a[15 - i];
|
||||
bb[i] = b[15 - i];
|
||||
}
|
||||
|
||||
asm("movdqu (%0), %%xmm0 \n" // a1:a0
|
||||
"movdqu (%1), %%xmm1 \n" // b1:b0
|
||||
|
||||
/*
|
||||
* Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
|
||||
* using [CLMUL-WP] algorithm 1 (p. 13).
|
||||
*/
|
||||
"movdqa %%xmm1, %%xmm2 \n" // copy of b1:b0
|
||||
"movdqa %%xmm1, %%xmm3 \n" // same
|
||||
"movdqa %%xmm1, %%xmm4 \n" // same
|
||||
"pclmulqdq $0x00, %%xmm0, %%xmm1 \n" // a0*b0 = c1:c0
|
||||
"pclmulqdq $0x11, %%xmm0, %%xmm2 \n" // a1*b1 = d1:d0
|
||||
"pclmulqdq $0x10, %%xmm0, %%xmm3 \n" // a0*b1 = e1:e0
|
||||
"pclmulqdq $0x01, %%xmm0, %%xmm4 \n" // a1*b0 = f1:f0
|
||||
"pxor %%xmm3, %%xmm4 \n" // e1+f1:e0+f0
|
||||
"movdqa %%xmm4, %%xmm3 \n" // same
|
||||
"psrldq $8, %%xmm4 \n" // 0:e1+f1
|
||||
"pslldq $8, %%xmm3 \n" // e0+f0:0
|
||||
"pxor %%xmm4, %%xmm2 \n" // d1:d0+e1+f1
|
||||
"pxor %%xmm3, %%xmm1 \n" // c1+e0+f1:c0
|
||||
|
||||
/*
|
||||
* Now shift the result one bit to the left,
|
||||
* taking advantage of [CLMUL-WP] eq 27 (p. 20)
|
||||
*/
|
||||
"movdqa %%xmm1, %%xmm3 \n" // r1:r0
|
||||
"movdqa %%xmm2, %%xmm4 \n" // r3:r2
|
||||
"psllq $1, %%xmm1 \n" // r1<<1:r0<<1
|
||||
"psllq $1, %%xmm2 \n" // r3<<1:r2<<1
|
||||
"psrlq $63, %%xmm3 \n" // r1>>63:r0>>63
|
||||
"psrlq $63, %%xmm4 \n" // r3>>63:r2>>63
|
||||
"movdqa %%xmm3, %%xmm5 \n" // r1>>63:r0>>63
|
||||
"pslldq $8, %%xmm3 \n" // r0>>63:0
|
||||
"pslldq $8, %%xmm4 \n" // r2>>63:0
|
||||
"psrldq $8, %%xmm5 \n" // 0:r1>>63
|
||||
"por %%xmm3, %%xmm1 \n" // r1<<1|r0>>63:r0<<1
|
||||
"por %%xmm4, %%xmm2 \n" // r3<<1|r2>>62:r2<<1
|
||||
"por %%xmm5, %%xmm2 \n" // r3<<1|r2>>62:r2<<1|r1>>63
|
||||
|
||||
/*
|
||||
* Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
|
||||
* using [CLMUL-WP] algorithm 5 (p. 20).
|
||||
* Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
|
||||
*/
|
||||
/* Step 2 (1) */
|
||||
"movdqa %%xmm1, %%xmm3 \n" // x1:x0
|
||||
"movdqa %%xmm1, %%xmm4 \n" // same
|
||||
"movdqa %%xmm1, %%xmm5 \n" // same
|
||||
"psllq $63, %%xmm3 \n" // x1<<63:x0<<63 = stuff:a
|
||||
"psllq $62, %%xmm4 \n" // x1<<62:x0<<62 = stuff:b
|
||||
"psllq $57, %%xmm5 \n" // x1<<57:x0<<57 = stuff:c
|
||||
|
||||
/* Step 2 (2) */
|
||||
"pxor %%xmm4, %%xmm3 \n" // stuff:a+b
|
||||
"pxor %%xmm5, %%xmm3 \n" // stuff:a+b+c
|
||||
"pslldq $8, %%xmm3 \n" // a+b+c:0
|
||||
"pxor %%xmm3, %%xmm1 \n" // x1+a+b+c:x0 = d:x0
|
||||
|
||||
/* Steps 3 and 4 */
|
||||
"movdqa %%xmm1,%%xmm0 \n" // d:x0
|
||||
"movdqa %%xmm1,%%xmm4 \n" // same
|
||||
"movdqa %%xmm1,%%xmm5 \n" // same
|
||||
"psrlq $1, %%xmm0 \n" // e1:x0>>1 = e1:e0'
|
||||
"psrlq $2, %%xmm4 \n" // f1:x0>>2 = f1:f0'
|
||||
"psrlq $7, %%xmm5 \n" // g1:x0>>7 = g1:g0'
|
||||
"pxor %%xmm4, %%xmm0 \n" // e1+f1:e0'+f0'
|
||||
"pxor %%xmm5, %%xmm0 \n" // e1+f1+g1:e0'+f0'+g0'
|
||||
// e0'+f0'+g0' is almost e0+f0+g0, except for some missing
|
||||
// bits carried from d. Now get those bits back in.
|
||||
"movdqa %%xmm1,%%xmm3 \n" // d:x0
|
||||
"movdqa %%xmm1,%%xmm4 \n" // same
|
||||
"movdqa %%xmm1,%%xmm5 \n" // same
|
||||
"psllq $63, %%xmm3 \n" // d<<63:stuff
|
||||
"psllq $62, %%xmm4 \n" // d<<62:stuff
|
||||
"psllq $57, %%xmm5 \n" // d<<57:stuff
|
||||
"pxor %%xmm4, %%xmm3 \n" // d<<63+d<<62:stuff
|
||||
"pxor %%xmm5, %%xmm3 \n" // missing bits of d:stuff
|
||||
"psrldq $8, %%xmm3 \n" // 0:missing bits of d
|
||||
"pxor %%xmm3, %%xmm0 \n" // e1+f1+g1:e0+f0+g0
|
||||
"pxor %%xmm1, %%xmm0 \n" // h1:h0
|
||||
"pxor %%xmm2, %%xmm0 \n" // x3+h1:x2+h0
|
||||
|
||||
"movdqu %%xmm0, (%2) \n" // done
|
||||
:
|
||||
: "r"(aa), "r"(bb), "r"(cc)
|
||||
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
|
||||
|
||||
/* Now byte-reverse the outputs */
|
||||
for (i = 0; i < 16; i++)
|
||||
c[i] = cc[15 - i];
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute decryption round keys from encryption round keys
|
||||
*/
|
||||
void aesni_inverse_key(unsigned char* invkey,
|
||||
const unsigned char* fwdkey, int nr)
|
||||
{
|
||||
unsigned char* ik = invkey;
|
||||
const unsigned char* fk = fwdkey + 16 * nr;
|
||||
|
||||
memcpy(ik, fk, 16);
|
||||
|
||||
for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16)
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
_mm_storeu_si128((__m128i*)ik, _mm_aesimc_si128(_mm_loadu_si128((__m128i*)fk)));
|
||||
#else
|
||||
asm("movdqu (%0), %%xmm0 \n"
|
||||
"aesimc %%xmm0, %%xmm0 \n"
|
||||
"movdqu %%xmm0, (%1) \n"
|
||||
:
|
||||
: "r"(fk), "r"(ik)
|
||||
: "memory", "xmm0");
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
|
||||
memcpy(ik, fk, 16);
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
inline static __m128i aes_key_128_assist(__m128i key, __m128i kg)
|
||||
{
|
||||
key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
|
||||
key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
|
||||
key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
|
||||
kg = _mm_shuffle_epi32(kg, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
return _mm_xor_si128(key, kg);
|
||||
}
|
||||
|
||||
// [AES-WP] Part of Fig. 25 page 32
|
||||
inline static void aes_key_192_assist(__m128i* temp1, __m128i* temp3, __m128i kg)
|
||||
{
|
||||
__m128i temp4;
|
||||
kg = _mm_shuffle_epi32(kg, 0x55);
|
||||
temp4 = _mm_slli_si128(*temp1, 0x4);
|
||||
*temp1 = _mm_xor_si128(*temp1, temp4);
|
||||
temp4 = _mm_slli_si128(temp4, 0x4);
|
||||
*temp1 = _mm_xor_si128(*temp1, temp4);
|
||||
temp4 = _mm_slli_si128(temp4, 0x4);
|
||||
*temp1 = _mm_xor_si128(*temp1, temp4);
|
||||
*temp1 = _mm_xor_si128(*temp1, kg);
|
||||
kg = _mm_shuffle_epi32(*temp1, 0xff);
|
||||
temp4 = _mm_slli_si128(*temp3, 0x4);
|
||||
*temp3 = _mm_xor_si128(*temp3, temp4);
|
||||
*temp3 = _mm_xor_si128(*temp3, kg);
|
||||
}
|
||||
|
||||
// [AES-WP] Part of Fig. 26 page 34
|
||||
inline static void aes_key_256_assist_1(__m128i* temp1, __m128i kg)
|
||||
{
|
||||
__m128i temp4;
|
||||
kg = _mm_shuffle_epi32(kg, 0xff);
|
||||
temp4 = _mm_slli_si128(*temp1, 0x4);
|
||||
*temp1 = _mm_xor_si128(*temp1, temp4);
|
||||
temp4 = _mm_slli_si128(temp4, 0x4);
|
||||
*temp1 = _mm_xor_si128(*temp1, temp4);
|
||||
temp4 = _mm_slli_si128(temp4, 0x4);
|
||||
*temp1 = _mm_xor_si128(*temp1, temp4);
|
||||
*temp1 = _mm_xor_si128(*temp1, kg);
|
||||
}
|
||||
|
||||
inline static void aes_key_256_assist_2(__m128i* temp1, __m128i* temp3)
|
||||
{
|
||||
__m128i temp2, temp4;
|
||||
temp4 = _mm_aeskeygenassist_si128(*temp1, 0x0);
|
||||
temp2 = _mm_shuffle_epi32(temp4, 0xaa);
|
||||
temp4 = _mm_slli_si128(*temp3, 0x4);
|
||||
*temp3 = _mm_xor_si128(*temp3, temp4);
|
||||
temp4 = _mm_slli_si128(temp4, 0x4);
|
||||
*temp3 = _mm_xor_si128(*temp3, temp4);
|
||||
temp4 = _mm_slli_si128(temp4, 0x4);
|
||||
*temp3 = _mm_xor_si128(*temp3, temp4);
|
||||
*temp3 = _mm_xor_si128(*temp3, temp2);
|
||||
}
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
|
||||
/*
|
||||
* Key expansion, 128-bit case
|
||||
*/
|
||||
static void aesni_setkey_enc_128(unsigned char* rk,
|
||||
const unsigned char* key)
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
__m128i *xrk, k;
|
||||
|
||||
xrk = (__m128i*)rk;
|
||||
|
||||
#define EXPAND_ROUND(k, rcon) \
|
||||
_mm_storeu_si128(xrk++, k); \
|
||||
k = aes_key_128_assist(k, _mm_aeskeygenassist_si128(k, rcon))
|
||||
|
||||
k = _mm_loadu_si128((__m128i*)key);
|
||||
EXPAND_ROUND(k, 0x01);
|
||||
EXPAND_ROUND(k, 0x02);
|
||||
EXPAND_ROUND(k, 0x04);
|
||||
EXPAND_ROUND(k, 0x08);
|
||||
EXPAND_ROUND(k, 0x10);
|
||||
EXPAND_ROUND(k, 0x20);
|
||||
EXPAND_ROUND(k, 0x40);
|
||||
EXPAND_ROUND(k, 0x80);
|
||||
EXPAND_ROUND(k, 0x1b);
|
||||
EXPAND_ROUND(k, 0x36);
|
||||
_mm_storeu_si128(xrk, k);
|
||||
|
||||
#undef EXPAND_ROUND
|
||||
|
||||
#else
|
||||
asm("movdqu (%1), %%xmm0 \n" // copy the original key
|
||||
"movdqu %%xmm0, (%0) \n" // as round key 0
|
||||
"jmp 2f \n" // skip auxiliary routine
|
||||
|
||||
/*
|
||||
* Finish generating the next round key.
|
||||
*
|
||||
* On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
|
||||
* with X = rot( sub( r3 ) ) ^ RCON.
|
||||
*
|
||||
* On exit, xmm0 is r7:r6:r5:r4
|
||||
* with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
|
||||
* and those are written to the round key buffer.
|
||||
*/
|
||||
"1: \n"
|
||||
"pshufd $0xff, %%xmm1, %%xmm1 \n" // X:X:X:X
|
||||
"pxor %%xmm0, %%xmm1 \n" // X+r3:X+r2:X+r1:r4
|
||||
"pslldq $4, %%xmm0 \n" // r2:r1:r0:0
|
||||
"pxor %%xmm0, %%xmm1 \n" // X+r3+r2:X+r2+r1:r5:r4
|
||||
"pslldq $4, %%xmm0 \n" // etc
|
||||
"pxor %%xmm0, %%xmm1 \n"
|
||||
"pslldq $4, %%xmm0 \n"
|
||||
"pxor %%xmm1, %%xmm0 \n" // update xmm0 for next time!
|
||||
"add $16, %0 \n" // point to next round key
|
||||
"movdqu %%xmm0, (%0) \n" // write it
|
||||
"ret \n"
|
||||
|
||||
/* Main "loop" */
|
||||
"2: \n"
|
||||
"aeskeygenassist $0x01, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x02, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x04, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x08, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x10, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x20, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x40, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x80, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x1B, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
"aeskeygenassist $0x36, %%xmm0, %%xmm1 \ncall 1b \n"
|
||||
:
|
||||
: "r"(rk), "r"(key)
|
||||
: "memory", "cc", "0");
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion, 192-bit case
|
||||
*/
|
||||
static void aesni_setkey_enc_192(unsigned char* rk,
|
||||
const unsigned char* key)
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
__m128i temp1, temp3;
|
||||
__m128i* key_schedule = (__m128i*)rk;
|
||||
temp1 = _mm_loadu_si128((__m128i*)key);
|
||||
temp3 = _mm_loadu_si128((__m128i*)(key + 16));
|
||||
key_schedule[0] = temp1;
|
||||
key_schedule[1] = temp3;
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x1));
|
||||
key_schedule[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_schedule[1]), _mm_castsi128_pd(temp1), 0));
|
||||
key_schedule[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1));
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x2));
|
||||
key_schedule[3] = temp1;
|
||||
key_schedule[4] = temp3;
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x4));
|
||||
key_schedule[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_schedule[4]), _mm_castsi128_pd(temp1), 0));
|
||||
key_schedule[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1));
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x8));
|
||||
key_schedule[6] = temp1;
|
||||
key_schedule[7] = temp3;
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x10));
|
||||
key_schedule[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_schedule[7]), _mm_castsi128_pd(temp1), 0));
|
||||
key_schedule[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1));
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x20));
|
||||
key_schedule[9] = temp1;
|
||||
key_schedule[10] = temp3;
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x40));
|
||||
key_schedule[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_schedule[10]), _mm_castsi128_pd(temp1), 0));
|
||||
key_schedule[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(temp1), _mm_castsi128_pd(temp3), 1));
|
||||
aes_key_192_assist(&temp1, &temp3, _mm_aeskeygenassist_si128(temp3, 0x80));
|
||||
key_schedule[12] = temp1;
|
||||
#else
|
||||
asm("movdqu (%1), %%xmm0 \n" // copy original round key
|
||||
"movdqu %%xmm0, (%0) \n"
|
||||
"add $16, %0 \n"
|
||||
"movq 16(%1), %%xmm1 \n"
|
||||
"movq %%xmm1, (%0) \n"
|
||||
"add $8, %0 \n"
|
||||
"jmp 2f \n" // skip auxiliary routine
|
||||
|
||||
/*
|
||||
* Finish generating the next 6 quarter-keys.
|
||||
*
|
||||
* On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
|
||||
* and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
|
||||
*
|
||||
* On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
|
||||
* and those are written to the round key buffer.
|
||||
*/
|
||||
"1: \n"
|
||||
"pshufd $0x55, %%xmm2, %%xmm2 \n" // X:X:X:X
|
||||
"pxor %%xmm0, %%xmm2 \n" // X+r3:X+r2:X+r1:r4
|
||||
"pslldq $4, %%xmm0 \n" // etc
|
||||
"pxor %%xmm0, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm0 \n"
|
||||
"pxor %%xmm0, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm0 \n"
|
||||
"pxor %%xmm2, %%xmm0 \n" // update xmm0 = r9:r8:r7:r6
|
||||
"movdqu %%xmm0, (%0) \n"
|
||||
"add $16, %0 \n"
|
||||
"pshufd $0xff, %%xmm0, %%xmm2 \n" // r9:r9:r9:r9
|
||||
"pxor %%xmm1, %%xmm2 \n" // stuff:stuff:r9+r5:r10
|
||||
"pslldq $4, %%xmm1 \n" // r2:r1:r0:0
|
||||
"pxor %%xmm2, %%xmm1 \n" // update xmm1 = stuff:stuff:r11:r10
|
||||
"movq %%xmm1, (%0) \n"
|
||||
"add $8, %0 \n"
|
||||
"ret \n"
|
||||
|
||||
"2: \n"
|
||||
"aeskeygenassist $0x01, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x02, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x04, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x08, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x10, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x20, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x40, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x80, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
|
||||
:
|
||||
: "r"(rk), "r"(key)
|
||||
: "memory", "cc", "0");
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion, 256-bit case
|
||||
*/
|
||||
static void aesni_setkey_enc_256(unsigned char* rk,
|
||||
const unsigned char* key)
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
|
||||
__m128i temp1, temp3;
|
||||
__m128i* key_schedule = (__m128i*)rk;
|
||||
temp1 = _mm_loadu_si128((__m128i*)key);
|
||||
temp3 = _mm_loadu_si128((__m128i*)(key + 16));
|
||||
key_schedule[0] = temp1;
|
||||
key_schedule[1] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x01));
|
||||
key_schedule[2] = temp1;
|
||||
aes_key_256_assist_2(&temp1, &temp3);
|
||||
key_schedule[3] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x02));
|
||||
key_schedule[4] = temp1;
|
||||
aes_key_256_assist_2(&temp1, &temp3);
|
||||
key_schedule[5] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x04));
|
||||
key_schedule[6] = temp1;
|
||||
aes_key_256_assist_2(&temp1, &temp3);
|
||||
key_schedule[7] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x08));
|
||||
key_schedule[8] = temp1;
|
||||
aes_key_256_assist_2(&temp1, &temp3);
|
||||
key_schedule[9] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x10));
|
||||
key_schedule[10] = temp1;
|
||||
aes_key_256_assist_2(&temp1, &temp3);
|
||||
key_schedule[11] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x20));
|
||||
key_schedule[12] = temp1;
|
||||
aes_key_256_assist_2(&temp1, &temp3);
|
||||
key_schedule[13] = temp3;
|
||||
aes_key_256_assist_1(&temp1, _mm_aeskeygenassist_si128(temp3, 0x40));
|
||||
key_schedule[14] = temp1;
|
||||
#else
|
||||
asm("movdqu (%1), %%xmm0 \n"
|
||||
"movdqu %%xmm0, (%0) \n"
|
||||
"add $16, %0 \n"
|
||||
"movdqu 16(%1), %%xmm1 \n"
|
||||
"movdqu %%xmm1, (%0) \n"
|
||||
"jmp 2f \n" // skip auxiliary routine
|
||||
|
||||
/*
|
||||
* Finish generating the next two round keys.
|
||||
*
|
||||
* On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
|
||||
* xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
|
||||
*
|
||||
* On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
|
||||
* and those have been written to the output buffer.
|
||||
*/
|
||||
"1: \n"
|
||||
"pshufd $0xff, %%xmm2, %%xmm2 \n"
|
||||
"pxor %%xmm0, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm0 \n"
|
||||
"pxor %%xmm0, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm0 \n"
|
||||
"pxor %%xmm0, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm0 \n"
|
||||
"pxor %%xmm2, %%xmm0 \n"
|
||||
"add $16, %0 \n"
|
||||
"movdqu %%xmm0, (%0) \n"
|
||||
|
||||
/* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
|
||||
* and proceed to generate next round key from there */
|
||||
"aeskeygenassist $0, %%xmm0, %%xmm2\n"
|
||||
"pshufd $0xaa, %%xmm2, %%xmm2 \n"
|
||||
"pxor %%xmm1, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm1 \n"
|
||||
"pxor %%xmm1, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm1 \n"
|
||||
"pxor %%xmm1, %%xmm2 \n"
|
||||
"pslldq $4, %%xmm1 \n"
|
||||
"pxor %%xmm2, %%xmm1 \n"
|
||||
"add $16, %0 \n"
|
||||
"movdqu %%xmm1, (%0) \n"
|
||||
"ret \n"
|
||||
|
||||
/*
|
||||
* Main "loop" - Generating one more key than necessary,
|
||||
* see definition of aes_context.buf
|
||||
*/
|
||||
"2: \n"
|
||||
"aeskeygenassist $0x01, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x02, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x04, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x08, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x10, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x20, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
"aeskeygenassist $0x40, %%xmm1, %%xmm2 \ncall 1b \n"
|
||||
:
|
||||
: "r"(rk), "r"(key)
|
||||
: "memory", "cc", "0");
|
||||
#endif /* POLARSSL_HAVE_MSVC_X64_INTRINSICS */
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion, wrapper
|
||||
*/
|
||||
int aesni_setkey_enc(unsigned char* rk,
|
||||
const unsigned char* key,
|
||||
size_t bits)
|
||||
{
|
||||
switch (bits)
|
||||
{
|
||||
case 128: aesni_setkey_enc_128(rk, key); break;
|
||||
case 192: aesni_setkey_enc_192(rk, key); break;
|
||||
case 256: aesni_setkey_enc_256(rk, key); break;
|
||||
default: return (POLARSSL_ERR_AES_INVALID_KEY_LENGTH);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
104
rpcs3/Crypto/aesni.h
Normal file
104
rpcs3/Crypto/aesni.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#pragma once
|
||||
#define POLARSSL_HAVE_ASM
|
||||
/**
|
||||
* \file aesni.h
|
||||
*
|
||||
* \brief AES-NI for hardware AES acceleration on some Intel processors
|
||||
*
|
||||
* Copyright (C) 2013, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
#define POLARSSL_AESNI_AES 0x02000000u
|
||||
#define POLARSSL_AESNI_CLMUL 0x00000002u
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES-NI features detection routine
|
||||
*
|
||||
* \param what The feature to detect
|
||||
* (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL)
|
||||
*
|
||||
* \return 1 if CPU has support for the feature, 0 otherwise
|
||||
*/
|
||||
int aesni_supports(unsigned int what);
|
||||
|
||||
/**
|
||||
* \brief AES-NI AES-ECB block en(de)cryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 on success (cannot fail)
|
||||
*/
|
||||
int aesni_crypt_ecb(aes_context* ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16]);
|
||||
|
||||
/**
|
||||
* \brief GCM multiplication: c = a * b in GF(2^128)
|
||||
*
|
||||
* \param c Result
|
||||
* \param a First operand
|
||||
* \param b Second operand
|
||||
*
|
||||
* \note Both operands and result are bit strings interpreted as
|
||||
* elements of GF(2^128) as per the GCM spec.
|
||||
*/
|
||||
void aesni_gcm_mult(unsigned char c[16],
|
||||
const unsigned char a[16],
|
||||
const unsigned char b[16]);
|
||||
|
||||
/**
|
||||
* \brief Compute decryption round keys from encryption round keys
|
||||
*
|
||||
* \param invkey Round keys for the equivalent inverse cipher
|
||||
* \param fwdkey Original round keys (for encryption)
|
||||
* \param nr Number of rounds (that is, number of round keys minus one)
|
||||
*/
|
||||
void aesni_inverse_key(unsigned char* invkey,
|
||||
const unsigned char* fwdkey, int nr);
|
||||
|
||||
/**
|
||||
* \brief Perform key expansion (for encryption)
|
||||
*
|
||||
* \param rk Destination buffer where the round keys are written
|
||||
* \param key Encryption key
|
||||
* \param bits Key size in bits (must be 128, 192 or 256)
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aesni_setkey_enc(unsigned char* rk,
|
||||
const unsigned char* key,
|
||||
size_t bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
185
rpcs3/Crypto/decrypt_binaries.cpp
Normal file
185
rpcs3/Crypto/decrypt_binaries.cpp
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
#include "stdafx.h"
|
||||
#include "decrypt_binaries.h"
|
||||
#include "unedat.h"
|
||||
#include "unself.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/System.h"
|
||||
#include "util/StrUtil.h"
|
||||
|
||||
#include <charconv>
|
||||
#include <iostream>
|
||||
|
||||
LOG_CHANNEL(dec_log, "DECRYPT");
|
||||
|
||||
usz decrypt_binaries_t::decrypt(std::string_view klic_input)
|
||||
{
|
||||
if (m_index >= m_modules.size())
|
||||
{
|
||||
std::cout << "No paths specified" << std::endl; // For CLI
|
||||
m_index = umax;
|
||||
return umax;
|
||||
}
|
||||
|
||||
if (m_klics.empty())
|
||||
{
|
||||
dec_log.notice("Decrypting binaries...");
|
||||
std::cout << "Decrypting binaries..." << std::endl; // For CLI
|
||||
|
||||
// Always start with no KLIC
|
||||
m_klics.emplace_back(u128{});
|
||||
|
||||
if (const auto keys = g_fxo->try_get<loaded_npdrm_keys>())
|
||||
{
|
||||
// Second klic: get it from a running game
|
||||
if (const u128 klic = keys->last_key())
|
||||
{
|
||||
m_klics.emplace_back(klic);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to use the key that has been for the current running ELF
|
||||
m_klics.insert(m_klics.end(), Emu.klic.begin(), Emu.klic.end());
|
||||
}
|
||||
|
||||
if (std::string_view text = klic_input.substr(klic_input.find_first_of('x') + 1); text.size() == 32)
|
||||
{
|
||||
// Allowed to fail (would simply repeat the operation if fails again)
|
||||
u64 lo = 0;
|
||||
u64 hi = 0;
|
||||
bool success = false;
|
||||
|
||||
if (auto res = std::from_chars(text.data() + 0, text.data() + 16, lo, 16); res.ec == std::errc() && res.ptr == text.data() + 16)
|
||||
{
|
||||
if (res = std::from_chars(text.data() + 16, text.data() + 32, hi, 16); res.ec == std::errc() && res.ptr == text.data() + 32)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
lo = std::bit_cast<be_t<u64>>(lo);
|
||||
hi = std::bit_cast<be_t<u64>>(hi);
|
||||
|
||||
if (u128 input_key = ((u128{hi} << 64) | lo))
|
||||
{
|
||||
m_klics.emplace_back(input_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (m_index < m_modules.size())
|
||||
{
|
||||
const std::string& _module = m_modules[m_index];
|
||||
const std::string old_path = _module;
|
||||
|
||||
fs::file elf_file;
|
||||
fs::file internal_file;
|
||||
|
||||
bool invalid = false;
|
||||
usz key_it = 0;
|
||||
u32 file_magic{};
|
||||
|
||||
while (true)
|
||||
{
|
||||
for (; key_it < m_klics.size(); key_it++)
|
||||
{
|
||||
internal_file.close();
|
||||
|
||||
if (!elf_file.open(old_path) || !elf_file.read(file_magic))
|
||||
{
|
||||
file_magic = 0;
|
||||
}
|
||||
|
||||
switch (file_magic)
|
||||
{
|
||||
case "SCE\0"_u32:
|
||||
{
|
||||
// First KLIC is no KLIC
|
||||
elf_file = decrypt_self(elf_file, key_it != 0 ? reinterpret_cast<u8*>(&m_klics[key_it]) : nullptr);
|
||||
|
||||
if (!elf_file)
|
||||
{
|
||||
// Try another key
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "NPD\0"_u32:
|
||||
{
|
||||
// EDAT / SDAT
|
||||
internal_file = std::move(elf_file);
|
||||
elf_file = DecryptEDAT(internal_file, old_path, key_it != 0 ? 8 : 1, reinterpret_cast<u8*>(&m_klics[key_it]));
|
||||
|
||||
if (!elf_file)
|
||||
{
|
||||
// Try another key
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid)
|
||||
{
|
||||
elf_file.close();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (elf_file)
|
||||
{
|
||||
const std::string exec_ext = fmt::to_lower(_module).ends_with(".sprx") ? ".prx" : ".elf";
|
||||
const std::string new_path = file_magic == "NPD\0"_u32 ? old_path + ".unedat" :
|
||||
old_path.substr(0, old_path.find_last_of('.')) + exec_ext;
|
||||
|
||||
if (fs::file new_file{new_path, fs::rewrite})
|
||||
{
|
||||
// 16MB buffer
|
||||
std::vector<u8> buffer(std::min<usz>(elf_file.size(), 1u << 24));
|
||||
|
||||
elf_file.seek(0);
|
||||
|
||||
while (usz read_size = elf_file.read(buffer.data(), buffer.size()))
|
||||
{
|
||||
new_file.write(buffer.data(), read_size);
|
||||
}
|
||||
|
||||
dec_log.success("Decrypted %s -> %s", old_path, new_path);
|
||||
std::cout << "Decrypted " << old_path << " -> " << new_path << std::endl; // For CLI
|
||||
m_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dec_log.error("Failed to create %s", new_path);
|
||||
std::cout << "Failed to create " << new_path << std::endl; // For CLI
|
||||
m_index = umax;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!invalid)
|
||||
{
|
||||
// Allow the user to manually type KLIC if decryption failed
|
||||
return m_index;
|
||||
}
|
||||
|
||||
dec_log.error("Failed to decrypt \"%s\".", old_path);
|
||||
std::cout << "Failed to decrypt \"" << old_path << "\"." << std::endl; // For CLI
|
||||
return m_index;
|
||||
}
|
||||
}
|
||||
|
||||
dec_log.notice("Finished decrypting all binaries.");
|
||||
std::cout << "Finished decrypting all binaries." << std::endl; // For CLI
|
||||
return m_index;
|
||||
}
|
||||
26
rpcs3/Crypto/decrypt_binaries.h
Normal file
26
rpcs3/Crypto/decrypt_binaries.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
class decrypt_binaries_t
|
||||
{
|
||||
std::vector<u128> m_klics;
|
||||
std::vector<std::string> m_modules;
|
||||
usz m_index = 0;
|
||||
|
||||
public:
|
||||
decrypt_binaries_t(std::vector<std::string> modules) noexcept
|
||||
: m_modules(std::move(modules))
|
||||
{
|
||||
}
|
||||
|
||||
usz decrypt(std::string_view klic_input = {});
|
||||
|
||||
bool done() const
|
||||
{
|
||||
return m_index >= m_modules.size();
|
||||
}
|
||||
|
||||
const std::string& operator[](usz index) const
|
||||
{
|
||||
return ::at32(m_modules, index);
|
||||
}
|
||||
};
|
||||
537
rpcs3/Crypto/ec.cpp
Normal file
537
rpcs3/Crypto/ec.cpp
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include <cstring>
|
||||
|
||||
static inline int bn_compare(const u8* a, const u8* b, u32 n)
|
||||
{
|
||||
for (u32 i = 0; i < n; i++)
|
||||
{
|
||||
if (a[i] < b[i])
|
||||
return -1;
|
||||
if (a[i] > b[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 bn_add_1(u8* d, const u8* a, const u8* b, u32 n)
|
||||
{
|
||||
u8 c = 0;
|
||||
for (u32 i = n - 1; i != umax; i--)
|
||||
{
|
||||
const u32 dig = a[i] + b[i] + c;
|
||||
c = dig >> 8;
|
||||
d[i] = dig;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static u8 bn_sub_1(u8* d, const u8* a, const u8* b, u32 n)
|
||||
{
|
||||
u8 c = 1;
|
||||
for (u32 i = n - 1; i != umax; i--)
|
||||
{
|
||||
const u32 dig = a[i] + 255 - b[i] + c;
|
||||
c = dig >> 8;
|
||||
d[i] = dig;
|
||||
}
|
||||
|
||||
return 1 - c;
|
||||
}
|
||||
|
||||
static void bn_reduce(u8* d, const u8* N, u32 n)
|
||||
{
|
||||
if (bn_compare(d, N, n) >= 0)
|
||||
bn_sub_1(d, d, N, n);
|
||||
}
|
||||
|
||||
static void bn_add(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
|
||||
{
|
||||
if (bn_add_1(d, a, b, n))
|
||||
bn_sub_1(d, d, N, n);
|
||||
|
||||
bn_reduce(d, N, n);
|
||||
}
|
||||
|
||||
static void bn_sub(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
|
||||
{
|
||||
if (bn_sub_1(d, a, b, n))
|
||||
bn_add_1(d, d, N, n);
|
||||
}
|
||||
|
||||
static constexpr u8 inv256[0x80] = {
|
||||
0x01,
|
||||
0xab,
|
||||
0xcd,
|
||||
0xb7,
|
||||
0x39,
|
||||
0xa3,
|
||||
0xc5,
|
||||
0xef,
|
||||
0xf1,
|
||||
0x1b,
|
||||
0x3d,
|
||||
0xa7,
|
||||
0x29,
|
||||
0x13,
|
||||
0x35,
|
||||
0xdf,
|
||||
0xe1,
|
||||
0x8b,
|
||||
0xad,
|
||||
0x97,
|
||||
0x19,
|
||||
0x83,
|
||||
0xa5,
|
||||
0xcf,
|
||||
0xd1,
|
||||
0xfb,
|
||||
0x1d,
|
||||
0x87,
|
||||
0x09,
|
||||
0xf3,
|
||||
0x15,
|
||||
0xbf,
|
||||
0xc1,
|
||||
0x6b,
|
||||
0x8d,
|
||||
0x77,
|
||||
0xf9,
|
||||
0x63,
|
||||
0x85,
|
||||
0xaf,
|
||||
0xb1,
|
||||
0xdb,
|
||||
0xfd,
|
||||
0x67,
|
||||
0xe9,
|
||||
0xd3,
|
||||
0xf5,
|
||||
0x9f,
|
||||
0xa1,
|
||||
0x4b,
|
||||
0x6d,
|
||||
0x57,
|
||||
0xd9,
|
||||
0x43,
|
||||
0x65,
|
||||
0x8f,
|
||||
0x91,
|
||||
0xbb,
|
||||
0xdd,
|
||||
0x47,
|
||||
0xc9,
|
||||
0xb3,
|
||||
0xd5,
|
||||
0x7f,
|
||||
0x81,
|
||||
0x2b,
|
||||
0x4d,
|
||||
0x37,
|
||||
0xb9,
|
||||
0x23,
|
||||
0x45,
|
||||
0x6f,
|
||||
0x71,
|
||||
0x9b,
|
||||
0xbd,
|
||||
0x27,
|
||||
0xa9,
|
||||
0x93,
|
||||
0xb5,
|
||||
0x5f,
|
||||
0x61,
|
||||
0x0b,
|
||||
0x2d,
|
||||
0x17,
|
||||
0x99,
|
||||
0x03,
|
||||
0x25,
|
||||
0x4f,
|
||||
0x51,
|
||||
0x7b,
|
||||
0x9d,
|
||||
0x07,
|
||||
0x89,
|
||||
0x73,
|
||||
0x95,
|
||||
0x3f,
|
||||
0x41,
|
||||
0xeb,
|
||||
0x0d,
|
||||
0xf7,
|
||||
0x79,
|
||||
0xe3,
|
||||
0x05,
|
||||
0x2f,
|
||||
0x31,
|
||||
0x5b,
|
||||
0x7d,
|
||||
0xe7,
|
||||
0x69,
|
||||
0x53,
|
||||
0x75,
|
||||
0x1f,
|
||||
0x21,
|
||||
0xcb,
|
||||
0xed,
|
||||
0xd7,
|
||||
0x59,
|
||||
0xc3,
|
||||
0xe5,
|
||||
0x0f,
|
||||
0x11,
|
||||
0x3b,
|
||||
0x5d,
|
||||
0xc7,
|
||||
0x49,
|
||||
0x33,
|
||||
0x55,
|
||||
0xff,
|
||||
};
|
||||
|
||||
static void bn_mon_muladd_dig(u8* d, const u8* a, u8 b, const u8* N, u32 n)
|
||||
{
|
||||
const u8 z = -(d[n - 1] + a[n - 1] * b) * inv256[N[n - 1] / 2];
|
||||
|
||||
u32 dig = d[n - 1] + a[n - 1] * b + N[n - 1] * z;
|
||||
dig >>= 8;
|
||||
|
||||
for (u32 i = n - 2; i < n; i--)
|
||||
{
|
||||
dig += d[i] + a[i] * b + N[i] * z;
|
||||
d[i + 1] = dig;
|
||||
dig >>= 8;
|
||||
}
|
||||
|
||||
d[0] = dig;
|
||||
dig >>= 8;
|
||||
|
||||
if (dig)
|
||||
bn_sub_1(d, d, N, n);
|
||||
|
||||
bn_reduce(d, N, n);
|
||||
}
|
||||
|
||||
static void bn_mon_mul(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
|
||||
{
|
||||
u8 t[512];
|
||||
memset(t, 0, n);
|
||||
|
||||
for (u32 i = n - 1; i != umax; i--)
|
||||
bn_mon_muladd_dig(t, a, b[i], N, n);
|
||||
|
||||
memcpy(d, t, n);
|
||||
}
|
||||
|
||||
static void bn_to_mon(u8* d, const u8* N, u32 n)
|
||||
{
|
||||
for (u32 i = 0; i < 8 * n; i++)
|
||||
bn_add(d, d, d, N, n);
|
||||
}
|
||||
|
||||
static void bn_from_mon(u8* d, const u8* N, u32 n)
|
||||
{
|
||||
u8 t[512];
|
||||
|
||||
memset(t, 0, n);
|
||||
t[n - 1] = 1;
|
||||
bn_mon_mul(d, d, t, N, n);
|
||||
}
|
||||
|
||||
static void bn_mon_exp(u8* d, const u8* a, const u8* N, u32 n, const u8* e, u32 en)
|
||||
{
|
||||
u8 t[512];
|
||||
|
||||
memset(d, 0, n);
|
||||
d[n - 1] = 1;
|
||||
bn_to_mon(d, N, n);
|
||||
|
||||
for (u32 i = 0; i < en; i++)
|
||||
{
|
||||
for (u8 mask = 0x80; mask != 0; mask >>= 1)
|
||||
{
|
||||
bn_mon_mul(t, d, d, N, n);
|
||||
if ((e[i] & mask) != 0)
|
||||
bn_mon_mul(d, t, a, N, n);
|
||||
else
|
||||
memcpy(d, t, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bn_mon_inv(u8* d, const u8* a, const u8* N, u32 n)
|
||||
{
|
||||
u8 t[512], s[512];
|
||||
|
||||
memset(s, 0, n);
|
||||
s[n - 1] = 2;
|
||||
bn_sub_1(t, N, s, n);
|
||||
bn_mon_exp(d, a, N, n, t, n);
|
||||
}
|
||||
|
||||
struct point
|
||||
{
|
||||
u8 x[20];
|
||||
u8 y[20];
|
||||
};
|
||||
|
||||
static thread_local u8 ec_p[20]{};
|
||||
static thread_local u8 ec_a[20]{}; // mon
|
||||
static thread_local u8 ec_b[20]{}; // mon
|
||||
static thread_local u8 ec_N[21]{};
|
||||
static thread_local point ec_G{}; // mon
|
||||
static thread_local point ec_Q{}; // mon
|
||||
static thread_local u8 ec_k[21]{};
|
||||
static thread_local bool ec_curve_initialized{};
|
||||
static thread_local bool ec_pub_initialized{};
|
||||
|
||||
static inline bool elt_is_zero(const u8* d)
|
||||
{
|
||||
for (u32 i = 0; i < 20; i++)
|
||||
if (d[i] != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void elt_add(u8* d, const u8* a, const u8* b)
|
||||
{
|
||||
bn_add(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_sub(u8* d, const u8* a, const u8* b)
|
||||
{
|
||||
bn_sub(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_mul(u8* d, const u8* a, const u8* b)
|
||||
{
|
||||
bn_mon_mul(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_square(u8* d, const u8* a)
|
||||
{
|
||||
elt_mul(d, a, a);
|
||||
}
|
||||
|
||||
static void elt_inv(u8* d, const u8* a)
|
||||
{
|
||||
u8 s[20];
|
||||
memcpy(s, a, 20);
|
||||
bn_mon_inv(d, s, ec_p, 20);
|
||||
}
|
||||
|
||||
static void point_to_mon(point* p)
|
||||
{
|
||||
bn_to_mon(p->x, ec_p, 20);
|
||||
bn_to_mon(p->y, ec_p, 20);
|
||||
}
|
||||
|
||||
static void point_from_mon(point* p)
|
||||
{
|
||||
bn_from_mon(p->x, ec_p, 20);
|
||||
bn_from_mon(p->y, ec_p, 20);
|
||||
}
|
||||
|
||||
static inline void point_zero(point* p)
|
||||
{
|
||||
memset(p->x, 0, 20);
|
||||
memset(p->y, 0, 20);
|
||||
}
|
||||
|
||||
static inline bool point_is_zero(const point* p)
|
||||
{
|
||||
return elt_is_zero(p->x) && elt_is_zero(p->y);
|
||||
}
|
||||
|
||||
static void point_double(point* r, const point* p)
|
||||
{
|
||||
u8 s[20], t[20];
|
||||
|
||||
point pp = *p;
|
||||
|
||||
const u8* px = pp.x;
|
||||
const u8* py = pp.y;
|
||||
u8* rx = r->x;
|
||||
u8* ry = r->y;
|
||||
|
||||
if (elt_is_zero(py))
|
||||
{
|
||||
point_zero(r);
|
||||
return;
|
||||
}
|
||||
|
||||
elt_square(t, px); // t = px*px
|
||||
elt_add(s, t, t); // s = 2*px*px
|
||||
elt_add(s, s, t); // s = 3*px*px
|
||||
elt_add(s, s, ec_a); // s = 3*px*px + a
|
||||
elt_add(t, py, py); // t = 2*py
|
||||
elt_inv(t, t); // t = 1/(2*py)
|
||||
elt_mul(s, s, t); // s = (3*px*px+a)/(2*py)
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(t, px, px); // t = 2*px
|
||||
elt_sub(rx, rx, t); // rx = s*s - 2*px
|
||||
|
||||
elt_sub(t, px, rx); // t = -(rx-px)
|
||||
elt_mul(ry, s, t); // ry = -s*(rx-px)
|
||||
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
|
||||
}
|
||||
|
||||
static void point_add(point* r, const point* p, const point* q)
|
||||
{
|
||||
u8 s[20], t[20], u[20];
|
||||
|
||||
point pp = *p;
|
||||
point qq = *q;
|
||||
|
||||
const u8* px = pp.x;
|
||||
const u8* py = pp.y;
|
||||
const u8* qx = qq.x;
|
||||
const u8* qy = qq.y;
|
||||
u8* rx = r->x;
|
||||
u8* ry = r->y;
|
||||
|
||||
if (point_is_zero(&pp))
|
||||
{
|
||||
memcpy(rx, qx, 20);
|
||||
memcpy(ry, qy, 20);
|
||||
return;
|
||||
}
|
||||
|
||||
if (point_is_zero(&qq))
|
||||
{
|
||||
memcpy(rx, px, 20);
|
||||
memcpy(ry, py, 20);
|
||||
return;
|
||||
}
|
||||
|
||||
elt_sub(u, qx, px);
|
||||
|
||||
if (elt_is_zero(u))
|
||||
{
|
||||
elt_sub(u, qy, py);
|
||||
if (elt_is_zero(u))
|
||||
point_double(r, &pp);
|
||||
else
|
||||
point_zero(r);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
elt_inv(t, u); // t = 1/(qx-px)
|
||||
elt_sub(u, qy, py); // u = qy-py
|
||||
elt_mul(s, t, u); // s = (qy-py)/(qx-px)
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(t, px, qx); // t = px+qx
|
||||
elt_sub(rx, rx, t); // rx = s*s - (px+qx)
|
||||
|
||||
elt_sub(t, px, rx); // t = -(rx-px)
|
||||
elt_mul(ry, s, t); // ry = -s*(rx-px)
|
||||
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
|
||||
}
|
||||
|
||||
static void point_mul(point* d, const u8* a, const point* b) // a is bignum
|
||||
{
|
||||
point_zero(d);
|
||||
|
||||
for (u32 i = 0; i < 21; i++)
|
||||
{
|
||||
for (u8 mask = 0x80; mask != 0; mask >>= 1)
|
||||
{
|
||||
point_double(d, d);
|
||||
if ((a[i] & mask) != 0)
|
||||
point_add(d, d, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_ecdsa(const struct point* Q, u8* R, u8* S, const u8* hash)
|
||||
{
|
||||
u8 Sinv[21];
|
||||
u8 e[21];
|
||||
u8 w1[21], w2[21];
|
||||
struct point r1, r2;
|
||||
u8 rr[21];
|
||||
|
||||
e[0] = 0;
|
||||
memcpy(e + 1, hash, 20);
|
||||
bn_reduce(e, ec_N, 21);
|
||||
|
||||
bn_to_mon(R, ec_N, 21);
|
||||
bn_to_mon(S, ec_N, 21);
|
||||
bn_to_mon(e, ec_N, 21);
|
||||
|
||||
bn_mon_inv(Sinv, S, ec_N, 21);
|
||||
|
||||
bn_mon_mul(w1, e, Sinv, ec_N, 21);
|
||||
bn_mon_mul(w2, R, Sinv, ec_N, 21);
|
||||
|
||||
bn_from_mon(w1, ec_N, 21);
|
||||
bn_from_mon(w2, ec_N, 21);
|
||||
|
||||
point_mul(&r1, w1, &ec_G);
|
||||
point_mul(&r2, w2, Q);
|
||||
|
||||
point_add(&r1, &r1, &r2);
|
||||
|
||||
point_from_mon(&r1);
|
||||
|
||||
rr[0] = 0;
|
||||
memcpy(rr + 1, r1.x, 20);
|
||||
bn_reduce(rr, ec_N, 21);
|
||||
|
||||
bn_from_mon(R, ec_N, 21);
|
||||
bn_from_mon(S, ec_N, 21);
|
||||
|
||||
return (bn_compare(rr, R, 21) == 0);
|
||||
}
|
||||
|
||||
void ecdsa_set_curve(const u8* p, const u8* a, const u8* b, const u8* N, const u8* Gx, const u8* Gy)
|
||||
{
|
||||
if (ec_curve_initialized)
|
||||
return;
|
||||
|
||||
memcpy(ec_p, p, 20);
|
||||
memcpy(ec_a, a, 20);
|
||||
memcpy(ec_b, b, 20);
|
||||
memcpy(ec_N, N, 21);
|
||||
memcpy(ec_G.x, Gx, 20);
|
||||
memcpy(ec_G.y, Gy, 20);
|
||||
|
||||
bn_to_mon(ec_a, ec_p, 20);
|
||||
bn_to_mon(ec_b, ec_p, 20);
|
||||
|
||||
point_to_mon(&ec_G);
|
||||
|
||||
ec_curve_initialized = true;
|
||||
}
|
||||
|
||||
void ecdsa_set_pub(const u8* Q)
|
||||
{
|
||||
if (ec_pub_initialized)
|
||||
return;
|
||||
|
||||
memcpy(ec_Q.x, Q, 20);
|
||||
memcpy(ec_Q.y, Q + 20, 20);
|
||||
point_to_mon(&ec_Q);
|
||||
|
||||
ec_pub_initialized = true;
|
||||
}
|
||||
|
||||
void ecdsa_set_priv(const u8* k)
|
||||
{
|
||||
memcpy(ec_k, k, sizeof ec_k);
|
||||
}
|
||||
|
||||
bool ecdsa_verify(const u8* hash, u8* R, u8* S)
|
||||
{
|
||||
return check_ecdsa(&ec_Q, R, S, hash);
|
||||
}
|
||||
12
rpcs3/Crypto/ec.h
Normal file
12
rpcs3/Crypto/ec.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 2.0 or later versions.
|
||||
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
|
||||
#include "util/types.hpp"
|
||||
|
||||
void ecdsa_set_curve(const u8* p, const u8* a, const u8* b, const u8* N, const u8* Gx, const u8* Gy);
|
||||
void ecdsa_set_pub(const u8* Q);
|
||||
void ecdsa_set_priv(const u8* k);
|
||||
bool ecdsa_verify(const u8* hash, u8* R, u8* S);
|
||||
817
rpcs3/Crypto/key_vault.cpp
Normal file
817
rpcs3/Crypto/key_vault.cpp
Normal file
|
|
@ -0,0 +1,817 @@
|
|||
#include "utils.h"
|
||||
#include "aes.h"
|
||||
#include "key_vault.h"
|
||||
#include "util/logs.hpp"
|
||||
|
||||
LOG_CHANNEL(key_vault_log, "KEY_VAULT");
|
||||
|
||||
SELF_KEY::SELF_KEY(u64 ver_start, u64 ver_end, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct)
|
||||
{
|
||||
version_start = ver_start;
|
||||
version_end = ver_end;
|
||||
revision = rev;
|
||||
self_type = type;
|
||||
hex_to_bytes(erk, e.c_str(), 0);
|
||||
hex_to_bytes(riv, r.c_str(), 0);
|
||||
hex_to_bytes(pub, pb.c_str(), 0);
|
||||
hex_to_bytes(priv, pr.c_str(), 0);
|
||||
curve_type = ct;
|
||||
}
|
||||
|
||||
KeyVault::KeyVault()
|
||||
{
|
||||
std::memcpy(klicensee_key, NP_KLIC_FREE, sizeof(klicensee_key));
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfLV0Keys()
|
||||
{
|
||||
sk_LV0_arr.clear();
|
||||
sk_LV0_arr.emplace_back(0x0000000000000000, 0x0000000000000000, 0x0000, KEY_LV0,
|
||||
"CA7A24EC38BDB45B98CCD7D363EA2AF0C326E65081E0630CB9AB2D215865878A",
|
||||
"F9205F46F6021697E670F13DFA726212",
|
||||
"A8FD6DB24532D094EFA08CB41C9A72287D905C6B27B42BE4AB925AAF4AFFF34D41EEB54DD128700D",
|
||||
"001AD976FCDE86F5B8FF3E63EF3A7F94E861975BA3",
|
||||
0x33);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfLDRKeys()
|
||||
{
|
||||
sk_LDR_arr.clear();
|
||||
sk_LDR_arr.emplace_back(0x0000000000000000, 0x0000000000000000, 0x0000, KEY_LDR,
|
||||
"C0CEFE84C227F75BD07A7EB846509F93B238E770DACB9FF4A388F812482BE21B",
|
||||
"47EE7454E4774CC9B8960C7B59F4C14D",
|
||||
"C2D4AAF319355019AF99D44E2B58CA29252C89123D11D6218F40B138CAB29B7101F3AEB72A975019",
|
||||
"00C5B2BFA1A413DD16F26D31C0F2ED4720DCFB0670",
|
||||
0x20);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfLV1Keys()
|
||||
{
|
||||
sk_LV1_arr.clear();
|
||||
sk_LV1_arr.emplace_back(0x0003000000000000, 0x0003003100000000, 0x0000, KEY_LV1,
|
||||
"B9F3F9E6107CFF2680A91E118C2403CF4A6F18F3C7EFD7D13D1AC4DB760BD222",
|
||||
"B43661B9A79BAD9D8E2B046469CDA1E7",
|
||||
"4C870BE86DDD996A92A3F7F404F33604244A1D02AB5B78BC9DAF030B78BE8867CF586171B7D45D20",
|
||||
"002CC736C7AD06D264E9AB663EB1F35F5DC159248C",
|
||||
0x33);
|
||||
sk_LV1_arr.emplace_back(0x0003004000000000, 0x0003004200000000, 0x0000, KEY_LV1,
|
||||
"B880593856C8C6D2037585626A12977F50DCFCF3F132D2C89AA6E670EAFC1646",
|
||||
"A79B05D4E37B8117A95E6E7C14FB640E",
|
||||
"7454C7CCBFC2F66C142D78A730A3A6F973CC0FB75A46FCBB390790138910A0CAC78E5E21F4DA3375",
|
||||
"00033A699FDD2DA6CDD6CCC03B2C6145F998706F74",
|
||||
0x34);
|
||||
sk_LV1_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0000, KEY_LV1,
|
||||
"1E8EEEA9E80A729F3FA52CF523B25941EA44B4155D94E5DADC5C5A77847620C7",
|
||||
"E034D31A80316960024D1B3D3164FDC3",
|
||||
"7E3A196f4A5879F3A7B091A2263F7C24E1716129B580566D308D9C2254B36AEE53DEF30EC85F8398",
|
||||
"005815D17125D04C33790321DE29EB6241365100B5",
|
||||
0x35);
|
||||
sk_LV1_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x0000, KEY_LV1,
|
||||
"53ABDF84BE08B0351B734F2B97D2BE1621BC6C889E4362E5C70F39D6C3ED9F23",
|
||||
"44E652661AC7584DBE08ECB810FB5FC0",
|
||||
"733198A7759BC07326755BC9773A8A17C8A7043C7BDAB83D88E230512E2EA3852D7DA4263A7E97F9",
|
||||
"004312C65347ACBE95CC306442FEFD0AF4C2935EB3",
|
||||
0x05);
|
||||
sk_LV1_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x0000, KEY_LV1,
|
||||
"48793EBDDA1AF65D737DA2FDA2DD104447A698F8A82CAAEE992831711BA94E83",
|
||||
"15DCF3C67147A45D09DE7521EECA07A1",
|
||||
"85A8868C320127F10B6598964C69221C086702021D31803520E21FDE4DBE827766BE41825CB7328C",
|
||||
"",
|
||||
0x07);
|
||||
sk_LV1_arr.emplace_back(0x0003006000000000, 0x0003006100000000, 0x0000, KEY_LV1,
|
||||
"5FF17D836E2C4AD69476E2614F64BDD05B9115389A9A6D055B5B544B1C34E3D5",
|
||||
"DF0F50EC3C4743C5B17839D7B49F24A4",
|
||||
"1CDABE30833823F461CA534104115FFF60010B710631E435A7D915E82AE88EDE667264656CB7062E",
|
||||
"",
|
||||
0x05);
|
||||
sk_LV1_arr.emplace_back(0x0003006500000000, 0x0003006600000000, 0x0000, KEY_LV1,
|
||||
"BD0621FA19383C3C72ECBC3B008F1CD55FFD7C3BB7510BF11AD0CF0FC2B70951",
|
||||
"569AF3745E1E02E3E288273CDE244CD8",
|
||||
"21E26F11C2D69478609DD1BD278CDFC940D90386455BA52FCD1FA7E27AC2AFA826C79A10193B625C",
|
||||
"",
|
||||
0x07);
|
||||
sk_LV1_arr.emplace_back(0x0003007000000000, 0x0003007400000000, 0x0000, KEY_LV1,
|
||||
"41A6E0039041E9D8AAF4EF2F2A2971248EDBD96A3985611ED7B4CE73EE4804FE",
|
||||
"C8C98D5A5CE23AF5607A352AECACB0DC",
|
||||
"4389664390265F96C1A882374C0F856364E33DB09BE124A4666F9A12F0DD9C811EDD55BA21ED0667",
|
||||
"",
|
||||
0x12);
|
||||
sk_LV1_arr.emplace_back(0x0004000000000000, 0x0004001100000000, 0x0000, KEY_LV1,
|
||||
"557EDF6C063F3272B0D44EEC12F418DA774815B5415597CC5F75C21E048BAD74",
|
||||
"7144D7574937818517826227EF4AC0B4",
|
||||
"085D38DBF9B757329EB862107929909D32FA1DAE60641BF4AC25319D7650597EE977F8E810FEEA96",
|
||||
"",
|
||||
0x13);
|
||||
sk_LV1_arr.emplace_back(0x0004002000000000, 0xFFFFFFFFFFFFFFFF, 0x0000, KEY_LV1,
|
||||
"10CEA04973FCCC12EC19924510822D8D4C41F657FD3D7E73F415A8D687421BCD",
|
||||
"ED8699562C6AC65204FA166257E7FCF4",
|
||||
"9AF86FC869C159FBB62F7D9674EE257ABF12E5A96D5875B4AA73C13C2BC13E2A4079F98B9B935EE2",
|
||||
"",
|
||||
0x14);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfLV2Keys()
|
||||
{
|
||||
sk_LV2_arr.clear();
|
||||
sk_LV2_arr.emplace_back(0x0000000300000000, 0x0003003100000000, 0x0000, KEY_LV2,
|
||||
"94303F69513572AB5AE17C8C2A1839D2C24C28F65389D3BBB11894CE23E0798F",
|
||||
"9769BFD187B90990AE5FEA4E110B9CF5",
|
||||
"AFAF5E96AF396CBB69071082C46A8F34A030E8EDB799E0A7BE00AA264DFF3AEBF7923920D559404D",
|
||||
"0070ABF9361B02291829D479F56AB248203CD3EB46",
|
||||
0x20);
|
||||
sk_LV2_arr.emplace_back(0x0003004000000000, 0x0003004200000000, 0x0000, KEY_LV2,
|
||||
"575B0A6C4B4F2760A03FE4189EBAF4D947279FD982B14070349098B08FF92C10",
|
||||
"411CB18F460CE50CAF2C426D8F0D93C8",
|
||||
"3FEE313954CB3039C321A7E33B97FFDEC8988A8B55759161B04DBF4731284E4A8191E3F17D32B0EA",
|
||||
"0073076441A08CD179E5FACE349B86DA58B5B7BA78",
|
||||
0x21);
|
||||
sk_LV2_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0000, KEY_LV2,
|
||||
"6DBD48D787C58803A8D724DA5ACF04FF8FCE91D7545D2322F2B7ABF57014AF68",
|
||||
"603A36213708520ED5D745DEC1325BA5",
|
||||
"5888CB83AC3CCA9610BC173C53141C0CA58B93719E744660CA8823D5EAEE8F9BF736997054E4B7E3",
|
||||
"0009EBC3DE442FA5FBF6C4F3D4F9EAB07778A142BD",
|
||||
0x22);
|
||||
sk_LV2_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x0000, KEY_LV2,
|
||||
"84015E90FA23139628A3C75CC09714E6427B527A82D18ABC3E91CD8D7DDAFF17",
|
||||
"5B240444D645F2038118F97FD5A145D5",
|
||||
"B266318245266B2D33641CD8A864066D077FAC60B7E27399099A70A683454B70F9888E7CC0C2BF72",
|
||||
"009D4CBA2BFB1A8330D3E20E59D281D476D231C73A",
|
||||
0x32);
|
||||
sk_LV2_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x0000, KEY_LV2,
|
||||
"EAE15444048EFDE7A831BFA9F5D96F047C9FCFF50723E292CF50F5417D81E359",
|
||||
"9CA9282DC7FA9F315EF3156D970B7CD4",
|
||||
"0D58938CB47598A6A672874F1768068F8B80D8D17014D2ABEBAC85E5B0993D9FB6F307DDC3DDA699",
|
||||
"",
|
||||
0x33);
|
||||
sk_LV2_arr.emplace_back(0x0003006000000000, 0x0003006100000000, 0x0000, KEY_LV2,
|
||||
"88AD367EDEC2FEED3E2F99B1C685075C41BDEC90C84F526CAF588F89BBD1CBCC",
|
||||
"8D18E8E525230E63DE10291C9DD615BF",
|
||||
"86EED1D65E58890ABDA9ACA486A2BDDB9C0A529C2053FAE301F0F698EAF443DA0F60595A597A7027",
|
||||
"",
|
||||
0x32);
|
||||
sk_LV2_arr.emplace_back(0x0003006500000000, 0x0003006600000000, 0x0000, KEY_LV2,
|
||||
"688D5FCAC6F4EA35AC6AC79B10506007286131EE038116DB8AA2C0B0340D9FB0",
|
||||
"75E0239D18B0B669EAE650972F99726B",
|
||||
"008E1C820AC567D1BFB8FE3CC6AD2E1845A1D1B19ED2E18B18CA34A8D28A83EC60C63859CDB3DACA",
|
||||
"",
|
||||
0x33);
|
||||
sk_LV2_arr.emplace_back(0x0003007000000000, 0x0003007400000000, 0x0000, KEY_LV2,
|
||||
"E81C5B04C29FB079A4A2687A39D4EA97BFB49D80EF546CEB292979A5F77A6254",
|
||||
"15058FA7F2CAD7C528B5F605F6444EB0",
|
||||
"438D0E5C1E7AFB18234DB6867472FF5F52B750F30C379C7DD1EE0FD23E417B3EA819CC01BAC480ED",
|
||||
"",
|
||||
0x11);
|
||||
sk_LV2_arr.emplace_back(0x0004001000000000, 0x0004001100000000, 0x0000, KEY_LV2,
|
||||
"A1E4B86ED02BF7F1372A2C73FE02BC738907EB37CE3BA605FE783C999FAFDB97",
|
||||
"BBE7799B9A37CB272E386618FDFD4AEC",
|
||||
"5B31A8E2A663EBD673196E2E1022E0D64988C4E1BBFE5E474415883A3BA0D9C562A2BE9C30E9B4A8",
|
||||
"",
|
||||
0x07);
|
||||
sk_LV2_arr.emplace_back(0x0004002000000000, 0xFFFFFFFFFFFFFFFF, 0x0000, KEY_LV2,
|
||||
"0CAF212B6FA53C0DA7E2C575ADF61DBE68F34A33433B1B891ABF5C4251406A03",
|
||||
"9B79374722AD888EB6A35A2DF25A8B3E",
|
||||
"1034A6F98AF6625CC3E3604B59B971CA617DF337538D2179EBB22F3BDC9D0C6DA56BA7DDFD205A50",
|
||||
"",
|
||||
0x14);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfISOKeys()
|
||||
{
|
||||
sk_ISO_arr.clear();
|
||||
sk_ISO_arr.emplace_back(0x0000006000000000, 0x0003003000000000, 0x0001, KEY_ISO,
|
||||
"8860D0CFF4D0DC688D3223321B96B59A777E6914961488E07048DAECB020ECA4",
|
||||
"C82D015D46CF152F1DD0C16F18B5B1E5",
|
||||
"733918D7C888130509346E6B4A8B6CAA357AB557E814E8122BF102C14A314BF9475B9D70EAF9EC29",
|
||||
"009BE892E122A5C943C1BB7403A67318AA9E1B286F",
|
||||
0x36);
|
||||
sk_ISO_arr.emplace_back(0x0003004000000000, 0x0003004200000000, 0x0001, KEY_ISO,
|
||||
"101E27F3FA2FB53ACA924F783AD553162D56B975D05B81351A1111799F20254D",
|
||||
"8D2E9C6297B8AD252998458296AC773C",
|
||||
"138446EE0BDDA5638F97328C8956E6489CBBFE57C5961D40DD5C43BB4138F1C400A8B27204A5D625",
|
||||
"00849DBC57D3B92F01864E6E82EB4EF0EF6311E122",
|
||||
0x32);
|
||||
sk_ISO_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0001, KEY_ISO,
|
||||
"3F2604FA27AEADFBE1AC69EB00BB16EF196C2193CBD62900FFD8C25041680843",
|
||||
"A414AC1DB7987E43777651B330B899E1",
|
||||
"1F4633AFDE18614D6CEF38A2FD6C4CCAC7B6EB8109D72CD066ECEBA0193EA3F43C37AE83179A4E5F",
|
||||
"0085B4B05DEBA7E6AD831653C974D95149803BB272",
|
||||
0x33);
|
||||
sk_ISO_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x0001, KEY_ISO,
|
||||
"BDB74AA6E3BA2DC10B1BD7F17198399A158DBE1FA0BEA68C90FCACBE4D04BE37",
|
||||
"0207A479B1574F8E7F697528F05D5435",
|
||||
"917E1F1DC48A54EB5F10B38E7569BB5383628A7C906F0DCA62FDA33805C15FAB270016940A09DB58",
|
||||
"00294411363290975BA551336D3965D88AF029A17B",
|
||||
0x03);
|
||||
sk_ISO_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x0001, KEY_ISO,
|
||||
"311C015F169F2A1E0757F7064B14C7C9F3A3FFEE015BD4E3A22401A2667857CE",
|
||||
"7BB8B3F5AC8E0890E3148AE5688C7350",
|
||||
"3F040EFA2335FED5670BA4D5C3AB2D9D0B4BA69D154A0062EA995A7D21DBAF0DC5A0DAD333D1C1DD",
|
||||
"",
|
||||
0x08);
|
||||
sk_ISO_arr.emplace_back(0x0003006000000000, 0x0003006100000000, 0x0001, KEY_ISO,
|
||||
"8474ADCA3B3244931EECEB9357841442442A1C4A4BCF4E498E6738950F4E4093",
|
||||
"FFF9CACCC4129125CAFB240F419E5F39",
|
||||
"098E1A53E59A95316B00D5A29C05FFEBAE41D1A8A386F9DA96F98858FD25E07BB7A3BC96A5D5B556",
|
||||
"",
|
||||
0x03);
|
||||
sk_ISO_arr.emplace_back(0x0003006500000000, 0x0003006600000000, 0x0001, KEY_ISO,
|
||||
"E6A21C599B75696C169EC02582BDA74A776134A6E05108EA701EC0CA2AC03592",
|
||||
"D292A7BD57C0BB2EABBCA1252FA9EDEF",
|
||||
"2ED078A13DC4617EB550AD06E228C83C142A2D588EB5E729402D18038A14842FD65B277DCAD225A5",
|
||||
"",
|
||||
0x08);
|
||||
sk_ISO_arr.emplace_back(0x0003007000000000, 0x0003007400000000, 0x0001, KEY_ISO,
|
||||
"072D3A5C3BDB0D674DE209381432B20414BC9BDA0F583ECB94BD9A134176DD51",
|
||||
"8516A81F02CF938740498A406C880871",
|
||||
"5A778DEB5C4F12E8D48E06A2BBBBE3C90FA8C6C47DF9BDB5697FD4A8EB7941CE3F59A557E81C787D",
|
||||
"",
|
||||
0x21);
|
||||
sk_ISO_arr.emplace_back(0x0003007000000000, 0x0003007400000000, 0x0100, KEY_ISO,
|
||||
"786FAB8A0B89474A2CB80B3EA104CCCB9E13F66B45EC499BB31865D07C661EA8",
|
||||
"94662F13D99A9F5D211C979FFDF65FE3",
|
||||
"912C94C252B7799CEB45DFBB73EF7CAD9BCC0793A3331BBB79E3C47C0F5C782F698065A8D4DB0D8B",
|
||||
"",
|
||||
0x0E);
|
||||
sk_ISO_arr.emplace_back(0x0004001000000000, 0x0004001100000000, 0x0001, KEY_ISO,
|
||||
"4262657A3185D9480F82C8BD2F81766FCC2C8FD7DD5EBE8657B00B939E0C75BD",
|
||||
"4F1E3EF07D893A4714B1B3D5A4E50479",
|
||||
"4DBFCFA68B52F1D66E09AFA6C18EC65479EDBD027B6B8C6A5D85FE5C84D43EA40CEF1672078A0702",
|
||||
"",
|
||||
0x11);
|
||||
sk_ISO_arr.emplace_back(0x0004001000000000, 0x0004001100000000, 0x0100, KEY_ISO,
|
||||
"16AA7D7C35399E2B1BFAF68CD19D7512A7855029C08BECC4CC3F035DF7F9C70B",
|
||||
"0E50DB6D937D262CB0499136852FCB80",
|
||||
"AEE2795BF295662A50DFAFE70D1B0B6F0A2EBB211E1323A275FC6E2D13BE4F2F10CA34784F4CF1EC",
|
||||
"",
|
||||
0x0F);
|
||||
sk_ISO_arr.emplace_back(0x0004002000000000, 0xFFFFFFFFFFFFFFFF, 0x0001, KEY_ISO,
|
||||
"63565DBE98C3B1A52AADC907C47130FE57A10734E84F22592670F86ED2B0A086",
|
||||
"953F6A99891B4739358F5363A00C08B9",
|
||||
"26BE7B02E7D65C6C21BF4063CDB8C0092FE1679D62FA1A8CCC284A1D21885473A959992537A06612",
|
||||
"",
|
||||
0x15);
|
||||
sk_ISO_arr.emplace_back(0x0004002000000000, 0xFFFFFFFFFFFFFFFF, 0x0100, KEY_ISO,
|
||||
"B96EA32CB96EA32DB96EA32CB96EA32CB96EA32CB96EA32DB96EA32CB96EA32C",
|
||||
"B96EA32CB96EA32DB96EA32DB96EA32C",
|
||||
"2D7066E68C6AC3373B1346FD76FE7D18A207C811500E65D85DB57BC4A27AD78F59FD53F38F50E151",
|
||||
"0044AA25B4276D79B494A29CB8DE104642424F8EEF",
|
||||
0x02);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfAPPKeys()
|
||||
{
|
||||
sk_APP_arr.clear();
|
||||
sk_APP_arr.emplace_back(0x0000009200000000, 0x0000009200000000, 0x0000, KEY_APP,
|
||||
"95F50019E7A68E341FA72EFDF4D60ED376E25CF46BB48DFDD1F080259DC93F04",
|
||||
"4A0955D946DB70D691A640BB7FAECC4C",
|
||||
"6F8DF8EBD0A1D1DB08B30DD3A951E3F1F27E34030B42C729C55555232D61B834B8BDFFB07E54B343",
|
||||
"006C3E4CCB2C69A5AD7C6F60448E50C7F9184EEAF4",
|
||||
0x21);
|
||||
sk_APP_arr.emplace_back(0x0003003000000000, 0x0003003000000000, 0x0001, KEY_APP,
|
||||
"79481839C406A632BDB4AC093D73D99AE1587F24CE7E69192C1CD0010274A8AB",
|
||||
"6F0F25E1C8C4B7AE70DF968B04521DDA",
|
||||
"94D1B7378BAFF5DFED269240A7A364ED68446741622E50BC6079B6E606A2F8E0A4C56E5CFF836526",
|
||||
"003DE80167D2F0E9D30F2145144A558D1174F5410C",
|
||||
0x11);
|
||||
sk_APP_arr.emplace_back(0x0003003000000000, 0x0003003000000000, 0x0002, KEY_APP,
|
||||
"4F89BE98DDD43CAD343F5BA6B1A133B0A971566F770484AAC20B5DD1DC9FA06A",
|
||||
"90C127A9B43BA9D8E89FE6529E25206F",
|
||||
"8CA6905F46148D7D8D84D2AFCEAE61B41E6750FC22EA435DFA61FCE6F4F860EE4F54D9196CA5290E",
|
||||
"",
|
||||
0x13);
|
||||
sk_APP_arr.emplace_back(0x0003003000000000, 0x0003003000000000, 0x0003, KEY_APP,
|
||||
"C1E6A351FCED6A0636BFCB6801A0942DB7C28BDFC5E0A053A3F52F52FCE9754E",
|
||||
"E0908163F457576440466ACAA443AE7C",
|
||||
"50022D5D37C97905F898E78E7AA14A0B5CAAD5CE8190AE5629A10D6F0CF4173597B37A95A7545C92",
|
||||
"",
|
||||
0x0B);
|
||||
sk_APP_arr.emplace_back(0x0003004200000000, 0x0003004200000000, 0x0004, KEY_APP,
|
||||
"838F5860CF97CDAD75B399CA44F4C214CDF951AC795298D71DF3C3B7E93AAEDA",
|
||||
"7FDBB2E924D182BB0D69844ADC4ECA5B",
|
||||
"1F140E8EF887DAB52F079A06E6915A6460B75CD256834A43FA7AF90C23067AF412EDAFE2C1778D69",
|
||||
"0074E922FDEE5DC4CDF22FC8D7986477F813400860",
|
||||
0x14);
|
||||
sk_APP_arr.emplace_back(0x0003004200000000, 0x0003004200000000, 0x0005, KEY_APP,
|
||||
"C109AB56593DE5BE8BA190578E7D8109346E86A11088B42C727E2B793FD64BDC",
|
||||
"15D3F191295C94B09B71EBDE088A187A",
|
||||
"B6BB0A84C649A90D97EBA55B555366F52381BB38A84C8BB71DA5A5A0949043C6DB249029A43156F7",
|
||||
"",
|
||||
0x15);
|
||||
sk_APP_arr.emplace_back(0x0003004200000000, 0x0003004200000000, 0x0006, KEY_APP,
|
||||
"6DFD7AFB470D2B2C955AB22264B1FF3C67F180983B26C01615DE9F2ECCBE7F41",
|
||||
"24BD1C19D2A8286B8ACE39E4A37801C2",
|
||||
"71F46AC33FF89DF589A100A7FB64CEAC244C9A0CBBC1FDCE80FB4BF8A0D2E66293309CB8EE8CFA95",
|
||||
"",
|
||||
0x2C);
|
||||
sk_APP_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0007, KEY_APP,
|
||||
"945B99C0E69CAF0558C588B95FF41B232660ECB017741F3218C12F9DFDEEDE55",
|
||||
"1D5EFBE7C5D34AD60F9FBC46A5977FCE",
|
||||
"AB284CA549B2DE9AA5C903B75652F78D192F8F4A8F3CD99209415C0A84C5C9FD6BF3095C1C18FFCD",
|
||||
"002CF896D35DB871D0E6A252E799876A70D043C23E",
|
||||
0x15);
|
||||
sk_APP_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0008, KEY_APP,
|
||||
"2C9E8969EC44DFB6A8771DC7F7FDFBCCAF329EC3EC070900CABB23742A9A6E13",
|
||||
"5A4CEFD5A9C3C093D0B9352376D19405",
|
||||
"6E82F6B54A0E9DEBE4A8B3043EE3B24CD9BBB62B4416B0482582E419A2552E29AB4BEA0A4D7FA2D5",
|
||||
"",
|
||||
0x16);
|
||||
sk_APP_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0009, KEY_APP,
|
||||
"F69E4A2934F114D89F386CE766388366CDD210F1D8913E3B973257F1201D632B",
|
||||
"F4D535069301EE888CC2A852DB654461",
|
||||
"1D7B974D10E61C2ED087A0981535904677EC07E96260F89565FF7EBDA4EE035C2AA9BCBDD5893F99",
|
||||
"",
|
||||
0x2D);
|
||||
sk_APP_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x000A, KEY_APP,
|
||||
"29805302E7C92F204009161CA93F776A072141A8C46A108E571C46D473A176A3",
|
||||
"5D1FAB844107676ABCDFC25EAEBCB633",
|
||||
"09301B6436C85B53CB1585300A3F1AF9FB14DB7C30088C4642AD66D5C148B8995BB1A698A8C71827",
|
||||
"0010818ED8A666051C6198662C3D6DDE2CA4901DDC",
|
||||
0x25);
|
||||
sk_APP_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x000B, KEY_APP,
|
||||
"A4C97402CC8A71BC7748661FE9CE7DF44DCE95D0D58938A59F47B9E9DBA7BFC3",
|
||||
"E4792F2B9DB30CB8D1596077A13FB3B5",
|
||||
"2733C889D289550FE00EAA5A47A34CEF0C1AF187610EB07BA35D2C09BB73C80B244EB4147700D1BF",
|
||||
"",
|
||||
0x26);
|
||||
sk_APP_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x000C, KEY_APP,
|
||||
"9814EFFF67B7074D1B263BF85BDC8576CE9DEC914123971B169472A1BC2387FA",
|
||||
"D43B1FA8BE15714B3078C23908BB2BCA",
|
||||
"7D1986C6BEE6CE1E0C5893BD2DF203881F40D5056761CC3F1F2E9D9A378617A2DE40BA5F09844CEB",
|
||||
"",
|
||||
0x3D);
|
||||
sk_APP_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x000D, KEY_APP,
|
||||
"03B4C421E0C0DE708C0F0B71C24E3EE04306AE7383D8C5621394CCB99FF7A194",
|
||||
"5ADB9EAFE897B54CB1060D6885BE22CF",
|
||||
"71502ADB5783583AB88B2D5F23F419AF01C8B1E72FCA1E694AD49FE3266F1F9C61EFC6F29B351142",
|
||||
"",
|
||||
0x12);
|
||||
sk_APP_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x000E, KEY_APP,
|
||||
"39A870173C226EB8A3EEE9CA6FB675E82039B2D0CCB22653BFCE4DB013BAEA03",
|
||||
"90266C98CBAA06C1BF145FF760EA1B45",
|
||||
"84DE5692809848E5ACBE25BE548F6981E3DB14735A5DDE1A0FD1F475866532B862B1AB6A004B7255",
|
||||
"",
|
||||
0x27);
|
||||
sk_APP_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x000F, KEY_APP,
|
||||
"FD52DFA7C6EEF5679628D12E267AA863B9365E6DB95470949CFD235B3FCA0F3B",
|
||||
"64F50296CF8CF49CD7C643572887DA0B",
|
||||
"0696D6CCBD7CF585EF5E00D547503C185D7421581BAD196E081723CD0A97FA40B2C0CD2492B0B5A1",
|
||||
"",
|
||||
0x3A);
|
||||
sk_APP_arr.emplace_back(0x0003006100000000, 0x0003006100000000, 0x0010, KEY_APP,
|
||||
"A5E51AD8F32FFBDE808972ACEE46397F2D3FE6BC823C8218EF875EE3A9B0584F",
|
||||
"7A203D5112F799979DF0E1B8B5B52AA4",
|
||||
"50597B7F680DD89F6594D9BDC0CBEE03666AB53647D0487F7F452FE2DD02694631EA755548C9E934",
|
||||
"",
|
||||
0x25);
|
||||
sk_APP_arr.emplace_back(0x0003006100000000, 0x0003006100000000, 0x0011, KEY_APP,
|
||||
"0F8EAB8884A51D092D7250597388E3B8B75444AC138B9D36E5C7C5B8C3DF18FD",
|
||||
"97AF39C383E7EF1C98FA447C597EA8FE",
|
||||
"2FDA7A56AAEA65921C0284FF1942C6DE137370093D106034B59191951A5201B422D462F8726F852D",
|
||||
"",
|
||||
0x26);
|
||||
sk_APP_arr.emplace_back(0x0003006600000000, 0x0003006600000000, 0x0013, KEY_APP,
|
||||
"DBF62D76FC81C8AC92372A9D631DDC9219F152C59C4B20BFF8F96B64AB065E94",
|
||||
"CB5DD4BE8CF115FFB25801BC6086E729",
|
||||
"B26FE6D3E3A1E766FAE79A8E6A7F48998E7FC1E4B0AD8745FF54C018C2A6CC7A0DD7525FAFEA4917",
|
||||
"",
|
||||
0x12);
|
||||
sk_APP_arr.emplace_back(0x0003006600000000, 0x0003006600000000, 0x0014, KEY_APP,
|
||||
"491B0D72BB21ED115950379F4564CE784A4BFAABB00E8CB71294B192B7B9F88E",
|
||||
"F98843588FED8B0E62D7DDCB6F0CECF4",
|
||||
"04275E8838EF95BD013B223C3DF674540932F21B534C7ED2944B9104D938FEB03B824DDB866AB26E",
|
||||
"",
|
||||
0x27);
|
||||
sk_APP_arr.emplace_back(0x0003007400000000, 0x0003007400000000, 0x0016, KEY_APP,
|
||||
"A106692224F1E91E1C4EBAD4A25FBFF66B4B13E88D878E8CD072F23CD1C5BF7C",
|
||||
"62773C70BD749269C0AFD1F12E73909E",
|
||||
"566635D3E1DCEC47243AAD1628AE6B2CEB33463FC155E4635846CE33899C5E353DDFA47FEF5694AF",
|
||||
"",
|
||||
0x30);
|
||||
sk_APP_arr.emplace_back(0x0003007400000000, 0x0003007400000000, 0x0017, KEY_APP,
|
||||
"4E104DCE09BA878C75DA98D0B1636F0E5F058328D81419E2A3D22AB0256FDF46",
|
||||
"954A86C4629E116532304A740862EF85",
|
||||
"3B7B04C71CAE2B1199D57453C038BB1B541A05AD1B94167B0AB47A9B24CAECB9000CB21407009666",
|
||||
"",
|
||||
0x08);
|
||||
sk_APP_arr.emplace_back(0x0003007400000000, 0x0003007400000000, 0x0018, KEY_APP,
|
||||
"1F876AB252DDBCB70E74DC4A20CD8ED51E330E62490E652F862877E8D8D0F997",
|
||||
"BF8D6B1887FA88E6D85C2EDB2FBEC147",
|
||||
"64A04126D77BF6B4D686F6E8F87DD150A5B014BA922D2B694FFF4453E11239A6E0B58F1703C51494",
|
||||
"",
|
||||
0x11);
|
||||
sk_APP_arr.emplace_back(0x0004001100000000, 0x0004001100000000, 0x0019, KEY_APP,
|
||||
"3236B9937174DF1DC12EC2DD8A318A0EA4D3ECDEA5DFB4AC1B8278447000C297",
|
||||
"6153DEE781B8ADDC6A439498B816DC46",
|
||||
"148DCA961E2738BAF84B2D1B6E2DA2ABD6A95F2C9571E54C6922F9ED9674F062B7F1BE5BD6FA5268",
|
||||
"",
|
||||
0x31);
|
||||
sk_APP_arr.emplace_back(0x0004001100000000, 0x0004001100000000, 0x001A, KEY_APP,
|
||||
"5EFD1E9961462794E3B9EF2A4D0C1F46F642AAE053B5025504130590E66F19C9",
|
||||
"1AC8FA3B3C90F8FDE639515F91B58327",
|
||||
"BE4B1B513536960618BFEF12A713F6673881B02F9DC616191E823FC8337CCF99ADAA6172019C0C23",
|
||||
"",
|
||||
0x17);
|
||||
sk_APP_arr.emplace_back(0x0004001100000000, 0x0004001100000000, 0x001B, KEY_APP,
|
||||
"66637570D1DEC098467DB207BAEA786861964D0964D4DBAF89E76F46955D181B",
|
||||
"9F7B5713A5ED59F6B35CD8F8A165D4B8",
|
||||
"4AB6FB1F6F0C3D9219923C1AC683137AB05DF667833CC6A5E8F590E4E28FE2EB180C7D5861117CFB",
|
||||
"",
|
||||
0x12);
|
||||
sk_APP_arr.emplace_back(0x0004004600000000, 0x0004004600000000, 0x001C, KEY_APP,
|
||||
"CFF025375BA0079226BE01F4A31F346D79F62CFB643CA910E16CF60BD9092752",
|
||||
"FD40664E2EBBA01BF359B0DCDF543DA4",
|
||||
"36C1ACE6DD5CCC0006FDF3424750FAC515FC5CFA2C93EC53C6EC2BC421708D154E91F2E7EA54A893",
|
||||
"",
|
||||
0x09);
|
||||
sk_APP_arr.emplace_back(0x0004004600000000, 0x0004004600000000, 0x001D, KEY_APP,
|
||||
"D202174EB65A62048F3674B59EF6FE72E1872962F3E1CD658DE8D7AF71DA1F3E",
|
||||
"ACB9945914EBB7B9A31ECE320AE09F2D",
|
||||
"430322887503CF52928FAAA410FD623C7321281C8825D95F5B47EF078EFCFC44454C3AB4F00BB879",
|
||||
"",
|
||||
0x1A);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfNPDRMKeys()
|
||||
{
|
||||
sk_NPDRM_arr.clear();
|
||||
sk_NPDRM_arr.emplace_back(0x0001000000000000, 0x0001000000000000, 0x0001, KEY_NPDRM,
|
||||
"F9EDD0301F770FABBA8863D9897F0FEA6551B09431F61312654E28F43533EA6B",
|
||||
"A551CCB4A42C37A734A2B4F9657D5540",
|
||||
"B05F9DA5F9121EE4031467E74C505C29A8E29D1022379EDFF0500B9AE480B5DAB4578A4C61C5D6BF",
|
||||
"00040AB47509BED04BD96521AD1B365B86BF620A98",
|
||||
0x11);
|
||||
sk_NPDRM_arr.emplace_back(0x0001000000000000, 0x0001000000000000, 0x0002, KEY_NPDRM,
|
||||
"8E737230C80E66AD0162EDDD32F1F774EE5E4E187449F19079437A508FCF9C86",
|
||||
"7AAECC60AD12AED90C348D8C11D2BED5",
|
||||
"05BF09CB6FD78050C78DE69CC316FF27C9F1ED66A45BFCE0A1E5A6749B19BD546BBB4602CF373440",
|
||||
"",
|
||||
0x0A);
|
||||
sk_NPDRM_arr.emplace_back(0x0003003000000000, 0x0003003000000000, 0x0003, KEY_NPDRM,
|
||||
"1B715B0C3E8DC4C1A5772EBA9C5D34F7CCFE5B82025D453F3167566497239664",
|
||||
"E31E206FBB8AEA27FAB0D9A2FFB6B62F",
|
||||
"3F51E59FC74D6618D34431FA67987FA11ABBFACC7111811473CD9988FE91C43FC74605E7B8CB732D",
|
||||
"",
|
||||
0x08);
|
||||
sk_NPDRM_arr.emplace_back(0x0003004200000000, 0x0003004200000000, 0x0004, KEY_NPDRM,
|
||||
"BB4DBF66B744A33934172D9F8379A7A5EA74CB0F559BB95D0E7AECE91702B706",
|
||||
"ADF7B207A15AC601110E61DDFC210AF6",
|
||||
"9C327471BAFF1F877AE4FE29F4501AF5AD6A2C459F8622697F583EFCA2CA30ABB5CD45D1131CAB30",
|
||||
"00B61A91DF4AB6A9F142C326BA9592B5265DA88856",
|
||||
0x16);
|
||||
sk_NPDRM_arr.emplace_back(0x0003004200000000, 0x0003004200000000, 0x0006, KEY_NPDRM,
|
||||
"8B4C52849765D2B5FA3D5628AFB17644D52B9FFEE235B4C0DB72A62867EAA020",
|
||||
"05719DF1B1D0306C03910ADDCE4AF887",
|
||||
"2A5D6C6908CA98FC4740D834C6400E6D6AD74CF0A712CF1E7DAE806E98605CC308F6A03658F2970E",
|
||||
"",
|
||||
0x29);
|
||||
sk_NPDRM_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0007, KEY_NPDRM,
|
||||
"3946DFAA141718C7BE339A0D6C26301C76B568AEBC5CD52652F2E2E0297437C3",
|
||||
"E4897BE553AE025CDCBF2B15D1C9234E",
|
||||
"A13AFE8B63F897DA2D3DC3987B39389DC10BAD99DFB703838C4A0BC4E8BB44659C726CFD0CE60D0E",
|
||||
"009EF86907782A318D4CC3617EBACE2480E73A46F6",
|
||||
0x17);
|
||||
sk_NPDRM_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0009, KEY_NPDRM,
|
||||
"0786F4B0CA5937F515BDCE188F569B2EF3109A4DA0780A7AA07BD89C3350810A",
|
||||
"04AD3C2F122A3B35E804850CAD142C6D",
|
||||
"A1FE61035DBBEA5A94D120D03C000D3B2F084B9F4AFA99A2D4A588DF92B8F36327CE9E47889A45D0",
|
||||
"",
|
||||
0x2A);
|
||||
sk_NPDRM_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x000A, KEY_NPDRM,
|
||||
"03C21AD78FBB6A3D425E9AAB1298F9FD70E29FD4E6E3A3C151205DA50C413DE4",
|
||||
"0A99D4D4F8301A88052D714AD2FB565E",
|
||||
"3995C390C9F7FBBAB124A1C14E70F9741A5E6BDF17A605D88239652C8EA7D5FC9F24B30546C1E44B",
|
||||
"009AC6B22A056BA9E0B6D1520F28A57A3135483F9F",
|
||||
0x27);
|
||||
sk_NPDRM_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x000C, KEY_NPDRM,
|
||||
"357EBBEA265FAEC271182D571C6CD2F62CFA04D325588F213DB6B2E0ED166D92",
|
||||
"D26E6DD2B74CD78E866E742E5571B84F",
|
||||
"00DCF5391618604AB42C8CFF3DC304DF45341EBA4551293E9E2B68FFE2DF527FFA3BE8329E015E57",
|
||||
"",
|
||||
0x3A);
|
||||
sk_NPDRM_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x000D, KEY_NPDRM,
|
||||
"337A51416105B56E40D7CAF1B954CDAF4E7645F28379904F35F27E81CA7B6957",
|
||||
"8405C88E042280DBD794EC7E22B74002",
|
||||
"9BFF1CC7118D2393DE50D5CF44909860683411A532767BFDAC78622DB9E5456753FE422CBAFA1DA1",
|
||||
"",
|
||||
0x18);
|
||||
sk_NPDRM_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x000F, KEY_NPDRM,
|
||||
"135C098CBE6A3E037EBE9F2BB9B30218DDE8D68217346F9AD33203352FBB3291",
|
||||
"4070C898C2EAAD1634A288AA547A35A8",
|
||||
"BBD7CCCB556C2EF0F908DC7810FAFC37F2E56B3DAA5F7FAF53A4944AA9B841F76AB091E16B231433",
|
||||
"",
|
||||
0x3B);
|
||||
sk_NPDRM_arr.emplace_back(0x0003006100000000, 0x0003006100000000, 0x0010, KEY_NPDRM,
|
||||
"4B3CD10F6A6AA7D99F9B3A660C35ADE08EF01C2C336B9E46D1BB5678B4261A61",
|
||||
"C0F2AB86E6E0457552DB50D7219371C5",
|
||||
"64A5C60BC2AD18B8A237E4AA690647E12BF7A081523FAD4F29BE89ACAC72F7AB43C74EC9AFFDA213",
|
||||
"",
|
||||
0x27);
|
||||
sk_NPDRM_arr.emplace_back(0x0003006600000000, 0x0003006600000000, 0x0013, KEY_NPDRM,
|
||||
"265C93CF48562EC5D18773BEB7689B8AD10C5EB6D21421455DEBC4FB128CBF46",
|
||||
"8DEA5FF959682A9B98B688CEA1EF4A1D",
|
||||
"9D8DB5A880608DC69717991AFC3AD5C0215A5EE413328C2ABC8F35589E04432373DB2E2339EEF7C8",
|
||||
"",
|
||||
0x18);
|
||||
sk_NPDRM_arr.emplace_back(0x0003007400000000, 0x0003007400000000, 0x0016, KEY_NPDRM,
|
||||
"7910340483E419E55F0D33E4EA5410EEEC3AF47814667ECA2AA9D75602B14D4B",
|
||||
"4AD981431B98DFD39B6388EDAD742A8E",
|
||||
"62DFE488E410B1B6B2F559E4CB932BCB78845AB623CC59FDF65168400FD76FA82ED1DC60E091D1D1",
|
||||
"",
|
||||
0x25);
|
||||
sk_NPDRM_arr.emplace_back(0x0004001100000000, 0x0004001100000000, 0x0019, KEY_NPDRM,
|
||||
"FBDA75963FE690CFF35B7AA7B408CF631744EDEF5F7931A04D58FD6A921FFDB3",
|
||||
"F72C1D80FFDA2E3BF085F4133E6D2805",
|
||||
"637EAD34E7B85C723C627E68ABDD0419914EBED4008311731DD87FDDA2DAF71F856A70E14DA17B42",
|
||||
"",
|
||||
0x24);
|
||||
sk_NPDRM_arr.emplace_back(0x0004004600000000, 0x0004004600000000, 0x001C, KEY_NPDRM,
|
||||
"8103EA9DB790578219C4CEDF0592B43064A7D98B601B6C7BC45108C4047AA80F",
|
||||
"246F4B8328BE6A2D394EDE20479247C5",
|
||||
"503172C9551308A87621ECEE90362D14889BFED2CF32B0B3E32A4F9FE527A41464B735E1ADBC6762",
|
||||
"",
|
||||
0x30);
|
||||
}
|
||||
|
||||
void KeyVault::LoadSelfUNK7Keys()
|
||||
{
|
||||
sk_UNK7_arr.clear();
|
||||
sk_UNK7_arr.emplace_back(0x0000008400000000, 0x0003003100000000, 0x0000, KEY_UNK7,
|
||||
"D91166973979EA8694476B011AC62C7E9F37DA26DE1E5C2EE3D66E42B8517085",
|
||||
"DC01280A6E46BC674B81A7E8801EBE6E",
|
||||
"A0FC44108236141BF3517A662B027AFC1AC513A05690496C754DEB7D43BDC41B80FD75C212624EE4",
|
||||
"",
|
||||
0x11);
|
||||
sk_UNK7_arr.emplace_back(0x0003004000000000, 0x0003004200000000, 0x0000, KEY_UNK7,
|
||||
"B73111B0B00117E48DE5E2EE5E534C0F0EFFA4890BBB8CAD01EE0F848F91583E",
|
||||
"86F56F9E5DE513894874B8BA253334B1",
|
||||
"B0BA1A1AB9723BB4E87CED9637BE056066BC56E16572D43D0210A06411DBF8FEB8885CD912384AE5",
|
||||
"",
|
||||
0x12);
|
||||
sk_UNK7_arr.emplace_back(0x0003005000000000, 0x0003005000000000, 0x0000, KEY_UNK7,
|
||||
"8E944267C02E69A4FE474B7F5FCD7974A4F936FF4355AEC4F80EFA123858D8F6",
|
||||
"908A75754E521EAC2F5A4889C6D7B72D",
|
||||
"91201DA7D79E8EE2563142ECBD646DA026C963AC09E760E5390FFE24DAE6864310ABE147F8204D0B",
|
||||
"",
|
||||
0x13);
|
||||
sk_UNK7_arr.emplace_back(0x0003005500000000, 0x0003005500000000, 0x0000, KEY_UNK7,
|
||||
"BB31DF9A6F62C0DF853075FAA65134D9CE2240306C1731D1F7DA9B5329BD699F",
|
||||
"263057225873F83940A65C8C926AC3E4",
|
||||
"BC3A82A4F44C43A197070CD236FDC94FCC542D69A3E803E0AFF78D1F3DA19A79D2F61FAB5B94B437",
|
||||
"",
|
||||
0x23);
|
||||
sk_UNK7_arr.emplace_back(0x0003005600000000, 0x0003005600000000, 0x0000, KEY_UNK7,
|
||||
"71AA75C70A255580E4AE9BDAA0B08828C53EAA713CD0713797F143B284C1589B",
|
||||
"9DED878CB6BA07121C0F50E7B172A8BF",
|
||||
"387FCDAEAFF1B59CFAF79CE6215A065ACEAFFAF4048A4F217E1FF5CE67C66EC3F089DB235E52F9D3",
|
||||
"",
|
||||
0x29);
|
||||
sk_UNK7_arr.emplace_back(0x0003006000000000, 0x0003006100000000, 0x0000, KEY_UNK7,
|
||||
"F5D1DBC182F5083CD4EA37C431C7DAC73882C07F232D2699B1DD9FDDF1BF4195",
|
||||
"D3A7C3C91CBA014FCBCA6D5570DE13FF",
|
||||
"97CA8A9781F45E557E98F176EF794FCDA6B151EB3DFD1ABA12151E00AE59957C3B15628FC8875D28",
|
||||
"",
|
||||
0x23);
|
||||
sk_UNK7_arr.emplace_back(0x0003006500000000, 0x0003006600000000, 0x0000, KEY_UNK7,
|
||||
"BF10F09590C0152F7EF749FF4B990122A4E8E5491DA49A2D931E72EEB990F860",
|
||||
"22C19C5522F7A782AFC547C2640F5BDE",
|
||||
"3233BA2B284189FB1687DF653002257A0925D8EB0C64EBBE8CC7DE87F548D107DE1FD3D1D285DB4F",
|
||||
"",
|
||||
0x29);
|
||||
sk_UNK7_arr.emplace_back(0x0003007000000000, 0x0003007400000000, 0x0000, KEY_UNK7,
|
||||
"F11DBD2C97B32AD37E55F8E743BC821D3E67630A6784D9A058DDD26313482F0F",
|
||||
"FC5FA12CA3D2D336C4B8B425D679DA55",
|
||||
"19E27EE90E33EDAB16B22E688B5F704E5C6EC1062070EBF43554CD03DFDAE16D684BB8B5574DBECA",
|
||||
"",
|
||||
0x15);
|
||||
sk_UNK7_arr.emplace_back(0x0004000000000000, 0x0004001100000000, 0x0000, KEY_UNK7,
|
||||
"751EE949CD3ADF50A469197494A1EC358409CCBE6E85217EBDE7A87D3FF1ABD8",
|
||||
"23AE4ADA4D3F798DC5ED98000337FF77",
|
||||
"1BABA87CD1AD705C462D4E7427B6DAF59A50383A348A15088F0EDFCF1ADF2B5C2B2D507B2A357D36",
|
||||
"",
|
||||
0x1A);
|
||||
sk_UNK7_arr.emplace_back(0x0004002000000000, 0xFFFFFFFFFFFFFFFF, 0x0000, KEY_UNK7,
|
||||
"46BD0891224E0CE13E2162921D4BB76193AEEE4416A729FCDD111C5536BF87C9",
|
||||
"BF036387CDB613C0AC88A6D9D2CC5316",
|
||||
"A14F6D5F9AD7EBB3B7A39A7C32F13E5DC3B0BA16BDC33D39FDDF88F4AEEA6CFEEB0C0796C917A952",
|
||||
"",
|
||||
0x0F);
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfLV0Key() const
|
||||
{
|
||||
return sk_LV0_arr[0];
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfLDRKey() const
|
||||
{
|
||||
return sk_LDR_arr[0];
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfLV1Key(u64 version) const
|
||||
{
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
for (uint i = 0; i < sk_LV1_arr.size(); i++)
|
||||
{
|
||||
if (version >= sk_LV1_arr[i].version_start && version <= sk_LV1_arr[i].version_end)
|
||||
{
|
||||
key = sk_LV1_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfLV2Key(u64 version) const
|
||||
{
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
for (uint i = 0; i < sk_LV2_arr.size(); i++)
|
||||
{
|
||||
if (version >= sk_LV2_arr[i].version_start && version <= sk_LV2_arr[i].version_end)
|
||||
{
|
||||
key = sk_LV2_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfISOKey(u16 revision, u64 version) const
|
||||
{
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
for (uint i = 0; i < sk_ISO_arr.size(); i++)
|
||||
{
|
||||
if ((version >= sk_ISO_arr[i].version_start && version <= sk_ISO_arr[i].version_end) && (sk_ISO_arr[i].revision == revision))
|
||||
{
|
||||
key = sk_ISO_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfAPPKey(u16 revision) const
|
||||
{
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
for (uint i = 0; i < sk_APP_arr.size(); i++)
|
||||
{
|
||||
if (sk_APP_arr[i].revision == revision)
|
||||
{
|
||||
key = sk_APP_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfUNK7Key(u64 version) const
|
||||
{
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
for (uint i = 0; i < sk_UNK7_arr.size(); i++)
|
||||
{
|
||||
if (version >= sk_UNK7_arr[i].version_start && version <= sk_UNK7_arr[i].version_end)
|
||||
{
|
||||
key = sk_UNK7_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::GetSelfNPDRMKey(u16 revision) const
|
||||
{
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
for (uint i = 0; i < sk_NPDRM_arr.size(); i++)
|
||||
{
|
||||
if (sk_NPDRM_arr[i].revision == revision)
|
||||
{
|
||||
key = sk_NPDRM_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
SELF_KEY KeyVault::FindSelfKey(u32 type, u16 revision, u64 version)
|
||||
{
|
||||
// Empty key.
|
||||
SELF_KEY key(0, 0, 0, 0, "", "", "", "", 0);
|
||||
|
||||
key_vault_log.trace("FindSelfKey: Type:0x%x, Revision:0x%x, Version:0x%x", type, revision, version);
|
||||
|
||||
// Check SELF type.
|
||||
switch (type)
|
||||
{
|
||||
case KEY_LV0:
|
||||
LoadSelfLV0Keys();
|
||||
key = GetSelfLV0Key();
|
||||
break;
|
||||
case KEY_LV1:
|
||||
LoadSelfLV1Keys();
|
||||
key = GetSelfLV1Key(version);
|
||||
break;
|
||||
case KEY_LV2:
|
||||
LoadSelfLV2Keys();
|
||||
key = GetSelfLV2Key(version);
|
||||
break;
|
||||
case KEY_APP:
|
||||
LoadSelfAPPKeys();
|
||||
key = GetSelfAPPKey(revision);
|
||||
break;
|
||||
case KEY_ISO:
|
||||
LoadSelfISOKeys();
|
||||
key = GetSelfISOKey(revision, version);
|
||||
break;
|
||||
case KEY_LDR:
|
||||
LoadSelfLDRKeys();
|
||||
key = GetSelfLDRKey();
|
||||
break;
|
||||
case KEY_UNK7:
|
||||
LoadSelfUNK7Keys();
|
||||
key = GetSelfUNK7Key(version);
|
||||
break;
|
||||
case KEY_NPDRM:
|
||||
LoadSelfNPDRMKeys();
|
||||
key = GetSelfNPDRMKey(revision);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void KeyVault::SetKlicenseeKey(const u8* key)
|
||||
{
|
||||
std::memcpy(klicensee_key, key, 0x10);
|
||||
}
|
||||
|
||||
const u8* KeyVault::GetKlicenseeKey() const
|
||||
{
|
||||
return klicensee_key;
|
||||
}
|
||||
|
||||
void rap_to_rif(const unsigned char* rap, unsigned char* rif)
|
||||
{
|
||||
int i;
|
||||
int round;
|
||||
aes_context aes;
|
||||
|
||||
unsigned char key[0x10];
|
||||
unsigned char iv[0x10];
|
||||
memset(key, 0, 0x10);
|
||||
memset(iv, 0, 0x10);
|
||||
|
||||
// Initial decrypt.
|
||||
aes_setkey_dec(&aes, RAP_KEY, 128);
|
||||
aes_crypt_cbc(&aes, AES_DECRYPT, 0x10, iv, rap, key);
|
||||
|
||||
// rap2rifkey round.
|
||||
for (round = 0; round < 5; ++round)
|
||||
{
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
const int p = RAP_PBOX[i];
|
||||
key[p] ^= RAP_E1[p];
|
||||
}
|
||||
for (i = 15; i >= 1; --i)
|
||||
{
|
||||
const int p = RAP_PBOX[i];
|
||||
const int pp = RAP_PBOX[i - 1];
|
||||
key[p] ^= key[pp];
|
||||
}
|
||||
int o = 0;
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
const int p = RAP_PBOX[i];
|
||||
const unsigned char kc = key[p] - o;
|
||||
const unsigned char ec2 = RAP_E2[p];
|
||||
if (o != 1 || kc != 0xFF)
|
||||
{
|
||||
o = kc < ec2 ? 1 : 0;
|
||||
key[p] = kc - ec2;
|
||||
}
|
||||
else if (kc == 0xFF)
|
||||
{
|
||||
key[p] = kc - ec2;
|
||||
}
|
||||
else
|
||||
{
|
||||
key[p] = kc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(rif, key, 0x10);
|
||||
}
|
||||
315
rpcs3/Crypto/key_vault.h
Normal file
315
rpcs3/Crypto/key_vault.h
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
enum SELF_KEY_TYPE
|
||||
{
|
||||
KEY_LV0 = 1,
|
||||
KEY_LV1,
|
||||
KEY_LV2,
|
||||
KEY_APP,
|
||||
KEY_ISO,
|
||||
KEY_LDR,
|
||||
KEY_UNK7,
|
||||
KEY_NPDRM
|
||||
};
|
||||
|
||||
struct SELF_KEY
|
||||
{
|
||||
u64 version_start{};
|
||||
u64 version_end{};
|
||||
u16 revision{};
|
||||
u32 self_type{};
|
||||
u8 erk[0x20]{};
|
||||
u8 riv[0x10]{};
|
||||
u8 pub[0x28]{};
|
||||
u8 priv[0x15]{};
|
||||
u32 curve_type{};
|
||||
|
||||
SELF_KEY(u64 ver_start, u64 ver_end, u16 rev, u32 type, const std::string& e, const std::string& r, const std::string& pb, const std::string& pr, u32 ct);
|
||||
};
|
||||
|
||||
constexpr u32 PASSPHRASE_KEY_LEN = 16;
|
||||
constexpr u32 PASSPHRASE_OUT_LEN = 4096;
|
||||
|
||||
constexpr u8 SC_ISO_SERIES_KEY_1[PASSPHRASE_KEY_LEN] = {
|
||||
0xD4, 0x13, 0xB8, 0x96, 0x63, 0xE1, 0xFE, 0x9F, 0x75, 0x14, 0x3D, 0x3B, 0xB4, 0x56, 0x52, 0x74 // D413B89663E1FE9F75143D3BB4565274
|
||||
};
|
||||
|
||||
constexpr u8 SC_ISO_SERIES_KEY_2[PASSPHRASE_KEY_LEN] = {
|
||||
0xFA, 0x72, 0xCE, 0xEF, 0x59, 0xB4, 0xD2, 0x98, 0x9F, 0x11, 0x19, 0x13, 0x28, 0x7F, 0x51, 0xC7 // FA72CEEF59B4D2989F111913287F51C7
|
||||
};
|
||||
|
||||
constexpr u8 SC_KEY_FOR_MASTER_1[PASSPHRASE_KEY_LEN] = {
|
||||
0xDA, 0xA4, 0xB9, 0xF2, 0xBC, 0x70, 0xB2, 0x80, 0xA7, 0xB3, 0x40, 0xFA, 0x0D, 0x04, 0xBA, 0x14 // DAA4B9F2BC70B280A7B340FA0D04BA14
|
||||
};
|
||||
|
||||
constexpr u8 SC_KEY_FOR_MASTER_2[PASSPHRASE_KEY_LEN] = {
|
||||
0x29, 0xC1, 0x94, 0xFF, 0xEC, 0x1F, 0xD1, 0x4D, 0x4A, 0xAE, 0x00, 0x6C, 0x32, 0xB3, 0x59, 0x90 // 29C194FFEC1FD14D4AAE006C32B35990
|
||||
};
|
||||
|
||||
constexpr u8 SC_ISO_SERIES_INTERNAL_KEY_1[PASSPHRASE_KEY_LEN] = {
|
||||
0x73, 0x63, 0x6B, 0x65, 0x79, 0x5F, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x6B, 0x65, 0x79, 0x00 // 73636B65795F7365726965736B657900
|
||||
};
|
||||
|
||||
constexpr u8 SC_ISO_SERIES_INTERNAL_KEY_2[PASSPHRASE_KEY_LEN] = {
|
||||
0x73, 0x63, 0x6B, 0x65, 0x79, 0x5F, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x6B, 0x65, 0x79, 0x32 // 73636B65795F7365726965736B657932
|
||||
};
|
||||
|
||||
constexpr u8 SC_ISO_SERIES_INTERNAL_KEY_3[PASSPHRASE_KEY_LEN] = {
|
||||
0x73, 0x63, 0x6B, 0x65, 0x79, 0x5F, 0x66, 0x6F, 0x72, 0x5F, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72 // 73636B65795F666F725F6D6173746572
|
||||
};
|
||||
|
||||
constexpr u8 PKG_AES_KEY_IDU[0x10] = {
|
||||
0x5d, 0xb9, 0x11, 0xe6, 0xb7, 0xe5, 0x0a, 0x7d, 0x32, 0x15, 0x38, 0xfd, 0x7c, 0x66, 0xf1, 0x7b};
|
||||
|
||||
constexpr u8 PKG_AES_KEY[0x10] = {
|
||||
0x2e, 0x7b, 0x71, 0xd7, 0xc9, 0xc9, 0xa1, 0x4e, 0xa3, 0x22, 0x1f, 0x18, 0x88, 0x28, 0xb8, 0xf8};
|
||||
|
||||
constexpr u8 PKG_AES_KEY2[0x10] = {
|
||||
0x07, 0xf2, 0xc6, 0x82, 0x90, 0xb5, 0x0d, 0x2c, 0x33, 0x81, 0x8d, 0x70, 0x9b, 0x60, 0xe6, 0x2b};
|
||||
|
||||
constexpr u8 PKG_AES_KEY_VITA_1[0x10] = {
|
||||
0xE3, 0x1A, 0x70, 0xC9, 0xCE, 0x1D, 0xD7, 0x2B, 0xF3, 0xC0, 0x62, 0x29, 0x63, 0xF2, 0xEC, 0xCB};
|
||||
|
||||
constexpr u8 PKG_AES_KEY_VITA_2[0x10] = {
|
||||
0x42, 0x3A, 0xCA, 0x3A, 0x2B, 0xD5, 0x64, 0x9F, 0x96, 0x86, 0xAB, 0xAD, 0x6F, 0xD8, 0x80, 0x1F};
|
||||
|
||||
constexpr u8 PKG_AES_KEY_VITA_3[0x10] = {
|
||||
0xAF, 0x07, 0xFD, 0x59, 0x65, 0x25, 0x27, 0xBA, 0xF1, 0x33, 0x89, 0x66, 0x8B, 0x17, 0xD9, 0xEA};
|
||||
|
||||
constexpr u8 NP_IDPS[0x10] = {
|
||||
0x5E, 0x06, 0xE0, 0x4F, 0xD9, 0x4A, 0x71, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
|
||||
constexpr u8 NP_KLIC_FREE[0x10] = {
|
||||
0x72, 0xF9, 0x90, 0x78, 0x8F, 0x9C, 0xFF, 0x74, 0x57, 0x25, 0xF0, 0x8E, 0x4C, 0x12, 0x83, 0x87};
|
||||
|
||||
constexpr u8 NP_OMAC_KEY_2[0x10] = {
|
||||
0x6B, 0xA5, 0x29, 0x76, 0xEF, 0xDA, 0x16, 0xEF, 0x3C, 0x33, 0x9F, 0xB2, 0x97, 0x1E, 0x25, 0x6B};
|
||||
|
||||
constexpr u8 NP_OMAC_KEY_3[0x10] = {
|
||||
0x9B, 0x51, 0x5F, 0xEA, 0xCF, 0x75, 0x06, 0x49, 0x81, 0xAA, 0x60, 0x4D, 0x91, 0xA5, 0x4E, 0x97};
|
||||
|
||||
constexpr u8 NP_KLIC_KEY[0x10] = {
|
||||
0xF2, 0xFB, 0xCA, 0x7A, 0x75, 0xB0, 0x4E, 0xDC, 0x13, 0x90, 0x63, 0x8C, 0xCD, 0xFD, 0xD1, 0xEE};
|
||||
|
||||
constexpr u8 NP_RIF_KEY[0x10] = {
|
||||
0xDA, 0x7D, 0x4B, 0x5E, 0x49, 0x9A, 0x4F, 0x53, 0xB1, 0xC1, 0xA1, 0x4A, 0x74, 0x84, 0x44, 0x3B};
|
||||
|
||||
// PSP Minis
|
||||
constexpr u8 NP_PSP_KEY_1[0x10] = {
|
||||
0x2A, 0x6A, 0xFB, 0xCF, 0x43, 0xD1, 0x57, 0x9F, 0x7D, 0x73, 0x87, 0x41, 0xA1, 0x3B, 0xD4, 0x2E};
|
||||
|
||||
// PSP Remasters
|
||||
constexpr u8 NP_PSP_KEY_2[0x10] = {
|
||||
0x0D, 0xB8, 0x57, 0x32, 0x36, 0x6C, 0xD7, 0x34, 0xFC, 0x87, 0x9E, 0x74, 0x33, 0x43, 0xBB, 0x4F};
|
||||
|
||||
constexpr u8 NP_PSX_KEY[0x10] = {
|
||||
0x52, 0xC0, 0xB5, 0xCA, 0x76, 0xD6, 0x13, 0x4B, 0xB4, 0x5F, 0xC6, 0x6C, 0xA6, 0x37, 0xF2, 0xC1};
|
||||
|
||||
constexpr u8 RAP_KEY[0x10] = {
|
||||
0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF};
|
||||
|
||||
constexpr u8 RAP_PBOX[0x10] = {
|
||||
0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09};
|
||||
|
||||
constexpr u8 RAP_E1[0x10] = {
|
||||
0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5};
|
||||
|
||||
constexpr u8 RAP_E2[0x10] = {
|
||||
0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74};
|
||||
|
||||
constexpr u8 SDAT_KEY[0x10] = {
|
||||
0x0D, 0x65, 0x5E, 0xF8, 0xE6, 0x74, 0xA9, 0x8A, 0xB8, 0x50, 0x5C, 0xFA, 0x7D, 0x01, 0x29, 0x33};
|
||||
|
||||
constexpr u8 EDAT_KEY_0[0x10] = {
|
||||
0xBE, 0x95, 0x9C, 0xA8, 0x30, 0x8D, 0xEF, 0xA2, 0xE5, 0xE1, 0x80, 0xC6, 0x37, 0x12, 0xA9, 0xAE};
|
||||
|
||||
constexpr u8 EDAT_HASH_0[0x10] = {
|
||||
0xEF, 0xFE, 0x5B, 0xD1, 0x65, 0x2E, 0xEB, 0xC1, 0x19, 0x18, 0xCF, 0x7C, 0x04, 0xD4, 0xF0, 0x11};
|
||||
|
||||
constexpr u8 EDAT_KEY_1[0x10] = {
|
||||
0x4C, 0xA9, 0xC1, 0x4B, 0x01, 0xC9, 0x53, 0x09, 0x96, 0x9B, 0xEC, 0x68, 0xAA, 0x0B, 0xC0, 0x81};
|
||||
|
||||
constexpr u8 EDAT_HASH_1[0x10] = {
|
||||
0x3D, 0x92, 0x69, 0x9B, 0x70, 0x5B, 0x07, 0x38, 0x54, 0xD8, 0xFC, 0xC6, 0xC7, 0x67, 0x27, 0x47};
|
||||
|
||||
constexpr u8 EDAT_IV[0x10] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
constexpr u8 VSH_CURVE_P[0x14] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
constexpr u8 VSH_CURVE_A[0x14] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC};
|
||||
|
||||
constexpr u8 VSH_CURVE_B[0x14] = {
|
||||
0xA6, 0x8B, 0xED, 0xC3, 0x34, 0x18, 0x02, 0x9C, 0x1D, 0x3C, 0xE3, 0x3B, 0x9A, 0x32, 0x1F, 0xCC, 0xBB, 0x9E, 0x0F, 0x0B};
|
||||
|
||||
constexpr u8 VSH_CURVE_N[0x15] = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xB5, 0xAE, 0x3C, 0x52, 0x3E, 0x63, 0x94, 0x4F, 0x21, 0x27};
|
||||
|
||||
constexpr u8 VSH_CURVE_GX[0x14] = {
|
||||
0x12, 0x8E, 0xC4, 0x25, 0x64, 0x87, 0xFD, 0x8F, 0xDF, 0x64, 0xE2, 0x43, 0x7B, 0xC0, 0xA1, 0xF6, 0xD5, 0xAF, 0xDE, 0x2C};
|
||||
|
||||
constexpr u8 VSH_CURVE_GY[0x14] = {
|
||||
0x59, 0x58, 0x55, 0x7E, 0xB1, 0xDB, 0x00, 0x12, 0x60, 0x42, 0x55, 0x24, 0xDB, 0xC3, 0x79, 0xD5, 0xAC, 0x5F, 0x4A, 0xDF};
|
||||
|
||||
constexpr u8 VSH_PUB[0x28] = {
|
||||
0x62, 0x27, 0xB0, 0x0A, 0x02, 0x85, 0x6F, 0xB0, 0x41, 0x08, 0x87, 0x67, 0x19, 0xE0, 0xA0, 0x18, 0x32, 0x91, 0xEE, 0xB9,
|
||||
0x6E, 0x73, 0x6A, 0xBF, 0x81, 0xF7, 0x0E, 0xE9, 0x16, 0x1B, 0x0D, 0xDE, 0xB0, 0x26, 0x76, 0x1A, 0xFF, 0x7B, 0xC8, 0x5B};
|
||||
|
||||
constexpr u8 SCEPKG_RIV[0x10] = {
|
||||
0x4A, 0xCE, 0xF0, 0x12, 0x24, 0xFB, 0xEE, 0xDF, 0x82, 0x45, 0xF8, 0xFF, 0x10, 0x21, 0x1E, 0x6E};
|
||||
|
||||
constexpr u8 SCEPKG_ERK[0x20] = {
|
||||
0xA9, 0x78, 0x18, 0xBD, 0x19, 0x3A, 0x67, 0xA1, 0x6F, 0xE8, 0x3A, 0x85, 0x5E, 0x1B, 0xE9, 0xFB, 0x56, 0x40, 0x93, 0x8D,
|
||||
0x4D, 0xBC, 0xB2, 0xCB, 0x52, 0xC5, 0xA2, 0xF8, 0xB0, 0x2B, 0x10, 0x31};
|
||||
|
||||
constexpr u8 PUP_KEY[0x40] = {
|
||||
0xF4, 0x91, 0xAD, 0x94, 0xC6, 0x81, 0x10, 0x96, 0x91, 0x5F, 0xD5, 0xD2, 0x44, 0x81, 0xAE, 0xDC, 0xED, 0xED, 0xBE, 0x6B,
|
||||
0xE5, 0x13, 0x72, 0x4D, 0xD8, 0xF7, 0xB6, 0x91, 0xE8, 0x8A, 0x38, 0xF4, 0xB5, 0x16, 0x2B, 0xFB, 0xEC, 0xBE, 0x3A, 0x62,
|
||||
0x18, 0x5D, 0xD7, 0xC9, 0x4D, 0xA2, 0x22, 0x5A, 0xDA, 0x3F, 0xBF, 0xCE, 0x55, 0x5B, 0x9E, 0xA9, 0x64, 0x98, 0x29, 0xEB,
|
||||
0x30, 0xCE, 0x83, 0x66};
|
||||
|
||||
// name; location; notes
|
||||
constexpr s64 PAID_01 = 0x0003CD28CB47D3C1L; // spu_token_processor.self; CoreOS; Only for 2E - 083.007
|
||||
constexpr s64 PAID_02 = 0x1010000001000001L; // vsh / games / utilities; /dev_flash/, cell_root/target/images; only for 2E - 080.006
|
||||
constexpr s64 PAID_03 = 0x1010000001000003L; // retail games and their updates
|
||||
constexpr s64 PAID_04 = 0x1010000002000003L;
|
||||
constexpr s64 PAID_05 = 0x1020000401000001L; // ps2emu; /dev_flash/ps2emu; CEX DEX DECR ?
|
||||
constexpr s64 PAID_06 = 0x1050000003000001L; // lv2_kernel.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_07 = 0x1070000001000002L; // onicore_child.self; /dev_flash/vsh/module; same for CEX DEX DECR
|
||||
constexpr s64 PAID_08 = 0x1070000002000002L; // mcore.self; /dev_flash/vsh/module; same for CEX DEX DECR
|
||||
constexpr s64 PAID_09 = 0x1070000003000002L; // mgvideo.self; /dev_flash/vsh/module; same for CEX DEX DECR
|
||||
constexpr s64 PAID_10 = 0x1070000004000002L; // swagner / swreset; /dev_flash/vsh/module; DTCP-IP DRM modules
|
||||
constexpr s64 PAID_11 = 0x107000000E000001L; // vtrm_server.fself; lv1
|
||||
constexpr s64 PAID_12 = 0x107000000F000001L; // update_manager_server.fself; lv1
|
||||
constexpr s64 PAID_13 = 0x1070000010000001L; // sc_manager_server.fself; lv1
|
||||
constexpr s64 PAID_14 = 0x1070000011000001L; // secure_rtc_server.fself; lv1
|
||||
constexpr s64 PAID_15 = 0x1070000012000001L; // spm_server.fself; lv1
|
||||
constexpr s64 PAID_16 = 0x1070000013000001L; // sb_manager_server.fself; lv1
|
||||
constexpr s64 PAID_17 = 0x1070000014000001L; // framework.fself; lv1
|
||||
constexpr s64 PAID_18 = 0x1070000015000001L; // lv2_loader.fself; lv1
|
||||
constexpr s64 PAID_19 = 0x1070000016000001L; // profile_loader.fself; lv1
|
||||
constexpr s64 PAID_20 = 0x1070000017000001L; // ss_init.fself; lv1
|
||||
constexpr s64 PAID_21 = 0x1070000018000001L; // individual_info_mgr_server.fself; lv1
|
||||
constexpr s64 PAID_22 = 0x1070000019000001L; // app_info_manager_server.fself; lv1
|
||||
constexpr s64 PAID_23 = 0x107000001A000001L; // ss_sc_init_pu.fself; JIG lv1 proc
|
||||
constexpr s64 PAID_24 = 0x107000001C000001L; // updater_frontend.fself; lv1
|
||||
constexpr s64 PAID_25 = 0x107000001D000001L; // sysmgr_ss.fself; lv1
|
||||
constexpr s64 PAID_26 = 0x107000001F000001L; // sb_iso_spu_module.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_27 = 0x1070000020000001L; // sc_iso.self / sc_iso_factory.self; CoreOS / [2.43 JIG PUP]; same for CEX DEX DECR
|
||||
constexpr s64 PAID_28 = 0x1070000021000001L; // spp_verifier.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_29 = 0x1070000022000001L; // spu_pkg_rvk_verifier.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_30 = 0x1070000023000001L; // spu_token_processor.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_31 = 0x1070000024000001L; // sv_iso_spu_module.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_32 = 0x1070000025000001L; // aim_spu_module.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_33 = 0x1070000026000001L; // ss_sc_init.self; [2.43 JIG PUP]
|
||||
constexpr s64 PAID_34 = 0x1070000027000001L; // dispatcher.fself; lv1;
|
||||
constexpr s64 PAID_35 = 0x1070000028000001L; // factory_data_mngr_server.fself; JIG lv1 proc
|
||||
constexpr s64 PAID_36 = 0x1070000029000001L; // fdm_spu_module.self; [2.43 JIG PUP]
|
||||
constexpr s64 PAID_37 = 0x107000002A000001L;
|
||||
constexpr s64 PAID_38 = 0x1070000031000001L;
|
||||
constexpr s64 PAID_39 = 0x1070000032000001L; // ss_server1.fself; lv1
|
||||
constexpr s64 PAID_40 = 0x1070000033000001L; // ss_server2.fself; lv1
|
||||
constexpr s64 PAID_41 = 0x1070000034000001L; // ss_server3.fself; lv1
|
||||
constexpr s64 PAID_42 = 0x1070000037000001L; // mc_iso_spu_module.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_43 = 0x1070000039000001L; // bdp_bdmv.self; /dev_flash/bdplayer
|
||||
constexpr s64 PAID_44 = 0x107000003A000001L; // bdj.self; /dev_flash/bdplayer
|
||||
constexpr s64 PAID_45 = 0x1070000040000001L; // sys/external modules; /dev_flash/sys/external; same for CEX DEX DECR (incl. liblv2dbg_for_cex.sprx + liblv2dbg_for_dex.sprx)
|
||||
constexpr s64 PAID_46 = 0x1070000041000001L; // ps1emu; /dev_flash/ps1emu; CEX DEX DECR ?
|
||||
constexpr s64 PAID_47 = 0x1070000043000001L; // me_iso_spu_module.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_48 = 0x1070000044000001L; // (related to usb dongle)
|
||||
constexpr s64 PAID_49 = 0x1070000045000001L; // USB Dongle Authenticator; ss_server1.fself; same for CEX DEX DECR
|
||||
constexpr s64 PAID_50 = 0x1070000046000001L; // spu_mode_auth.self; [2.43 JIG PUP]
|
||||
constexpr s64 PAID_51 = 0x1070000047000001L; // otheros.self; otheros.self
|
||||
constexpr s64 PAID_52 = 0x1070000048000001L; // ftpd; cell_root/target/images; DECR
|
||||
constexpr s64 PAID_53 = 0x107000004C000001L; // spu_utoken_processor.self; CoreOS (since FW 2.40)
|
||||
constexpr s64 PAID_54 = 0x107000004E000001L; // (syscall 878)
|
||||
constexpr s64 PAID_55 = 0x107000004F000001L;
|
||||
constexpr s64 PAID_56 = 0x1070000050000001L;
|
||||
constexpr s64 PAID_57 = 0x1070000051000001L;
|
||||
constexpr s64 PAID_58 = 0x1070000052000001L; // sys/internal CEX + vsh/module modules CEX; /dev_flash/sys/internal + /dev_flash/vsh/module; Differs between CEX (this authid) and DECR
|
||||
constexpr s64 PAID_59 = 0x1070000054000001L; // (syscall 21)
|
||||
constexpr s64 PAID_60 = 0x1070000055000001L; // manu_info_spu_module.self; CoreOS (since FW 3.50)
|
||||
constexpr s64 PAID_61 = 0x1070000058000001L; // me_iso_for_ps2emu.self; CoreOS (since FW 3.70)
|
||||
constexpr s64 PAID_62 = 0x1070000059000001L; // sv_iso_for_ps2emu.self; CoreOS (since FW 3.70)
|
||||
constexpr s64 PAID_63 = 0x1070000300000001L; // Lv2diag.self; BD-remarry toolkit
|
||||
constexpr s64 PAID_64 = 0x10700003FC000001L; // emer_init.self; CoreOS (since FW 2.00)
|
||||
constexpr s64 PAID_65 = 0x10700003FD000001L; // ps3swu; PUP root; same for CEX DEX DECR
|
||||
constexpr s64 PAID_66 = 0x10700003FD000001L; // PS3ToolUpdater; cell_root/target/images; Only DECR
|
||||
constexpr s64 PAID_67 = 0x10700003FD000001L; // manufacturing_updater_for_reset.self; BD-remarry toolkit
|
||||
constexpr s64 PAID_68 = 0x10700003FE000001L; // sys_agent.self DECR; /dev_flash/sys/internal; DECR
|
||||
constexpr s64 PAID_69 = 0x10700003FF000001L; // db_backup, mkfs, mkfs_085, mount_hdd, registry_backup, set_monitor, most sys/internal modules DECR + most vsh/module modules DECR; /dev_flash/sys/internal + /dev_flash/vsh/module + cell_root/target/images; Differs between DECR (this authid) and CEX
|
||||
constexpr s64 PAID_70 = 0x1070000400000001L; // vsh / games / utilities; /dev_flash/, cell_root/target/images; only for 081.003 - 083.007
|
||||
constexpr s64 PAID_71 = 0x1070000409000001L; // psp_emulator.self; /dev_flash/pspemu/psp_emulator.self; CEX DEX DECR ?
|
||||
constexpr s64 PAID_72 = 0x107000040A000001L; // psp_translator.self; /dev_flash/pspemu/psp_translator.self; CEX DEX DECR ?
|
||||
constexpr s64 PAID_73 = 0x107000040B000001L; // emulator_api.sprx and other .sprx; /dev_flash/pspemu/release/; CEX DEX DECR ?
|
||||
constexpr s64 PAID_74 = 0x107000040C000001L; // emulator_drm.sprx; /dev_flash/pspemu/release/emulator_drm.sprx; CEX DEX DECR ?
|
||||
constexpr s64 PAID_75 = 0x107000040C000001L; // libchnnlsv.sprx; /dev_flash/sys/internal/; CEX DEX DECR ?
|
||||
constexpr s64 PAID_76 = 0x107000040D000001L; // ?psp related?; ?/dev_flash/pspemu/release/?; CEX DEX DECR ?
|
||||
constexpr s64 PAID_77 = 0x1070000500000001L; // cellftp; cell_root/target/images/; DECR
|
||||
constexpr s64 PAID_78 = 0x1070000501000001L; // hdd_copy.self; CoreOS (since FW 3.10)
|
||||
constexpr s64 PAID_79 = 0x10700005FC000001L; // sys_audio; /dev_flash/sys/internal; CEX
|
||||
constexpr s64 PAID_80 = 0x10700005FD000001L; // sys_init_osd; /dev_flash/sys/internal; CEX
|
||||
constexpr s64 PAID_81 = 0x10700005FF000001L; // vsh.self; /dev_flash/vsh/; CEX
|
||||
constexpr s64 PAID_82 = 0x1070001002000001L; // PvrRecSvr.sprx; BCJB95006\USRDIR\v320; CEX
|
||||
constexpr s64 PAID_83 = 0x1070200056000001L; // cachemgr.self; WebMAF apps/USRDIR
|
||||
constexpr s64 PAID_84 = 0x1070200057000001L; // EBOOT.BIN.self + .sprx files; WebMAF apps/USRDIR/prx/ps3; Demen_prx.ppu.sprx + WebMAF sprx files
|
||||
constexpr s64 PAID_85 = 0x1FF0000001000001L; // lv0; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_86 = 0x1FF0000002000001L; // lv1.self; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_87 = 0x1FF0000008000001L; // lv1ldr; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_88 = 0x1FF0000009000001L; // lv2ldr; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_89 = 0x1FF000000A000001L; // isoldr; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_90 = 0x1FF000000B000001L; // rvkldr; CoreOS; same for CEX DEX DECR
|
||||
constexpr s64 PAID_91 = 0x1FF000000C000001L; // appldr; CoreOS; same for CEX DEX DECR
|
||||
|
||||
constexpr s64 LAID_1 = 0x1070000001000001L; // (= HV processes / SCE_CELLOS_PME); flash and vflash
|
||||
constexpr s64 LAID_2 = 0x1070000002000001L; // (= GameOS / PS3_LPAR); flash and vflash
|
||||
constexpr s64 LAID_3 = 0x1020000003000001L; // (= PS2_LPAR / PS2_GX_LPAR / PS2_SW_LPAR / PS2_NE_LPAR); (used in ps3vflashc region inside vflash in NOR consoles, and ps3db region)... dev_flash and dev_hdd0 regions
|
||||
constexpr s64 LAID_4 = 0x1080000004000001L; // (= LINUX_LPAR); (used in ps3vflashf region inside vflash in NOR consoles)... otheros bootloader region
|
||||
|
||||
class KeyVault
|
||||
{
|
||||
std::vector<SELF_KEY> sk_LV0_arr{};
|
||||
std::vector<SELF_KEY> sk_LV1_arr{};
|
||||
std::vector<SELF_KEY> sk_LV2_arr{};
|
||||
std::vector<SELF_KEY> sk_APP_arr{};
|
||||
std::vector<SELF_KEY> sk_ISO_arr{};
|
||||
std::vector<SELF_KEY> sk_LDR_arr{};
|
||||
std::vector<SELF_KEY> sk_UNK7_arr{};
|
||||
std::vector<SELF_KEY> sk_NPDRM_arr{};
|
||||
u8 klicensee_key[16]{};
|
||||
|
||||
public:
|
||||
KeyVault();
|
||||
SELF_KEY FindSelfKey(u32 type, u16 revision, u64 version);
|
||||
void SetKlicenseeKey(const u8* key);
|
||||
const u8* GetKlicenseeKey() const;
|
||||
|
||||
private:
|
||||
void LoadSelfLV0Keys();
|
||||
void LoadSelfLDRKeys();
|
||||
void LoadSelfLV1Keys();
|
||||
void LoadSelfLV2Keys();
|
||||
void LoadSelfISOKeys();
|
||||
void LoadSelfAPPKeys();
|
||||
void LoadSelfUNK7Keys();
|
||||
void LoadSelfNPDRMKeys();
|
||||
SELF_KEY GetSelfLV0Key() const;
|
||||
SELF_KEY GetSelfLDRKey() const;
|
||||
SELF_KEY GetSelfLV1Key(u64 version) const;
|
||||
SELF_KEY GetSelfLV2Key(u64 version) const;
|
||||
SELF_KEY GetSelfISOKey(u16 revision, u64 version) const;
|
||||
SELF_KEY GetSelfAPPKey(u16 revision) const;
|
||||
SELF_KEY GetSelfUNK7Key(u64 version) const;
|
||||
SELF_KEY GetSelfNPDRMKey(u16 revision) const;
|
||||
};
|
||||
|
||||
// RAP to RIF function.
|
||||
void rap_to_rif(const unsigned char* rap, unsigned char* rif);
|
||||
287
rpcs3/Crypto/lz.cpp
Normal file
287
rpcs3/Crypto/lz.cpp
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 2.0 or later versions.
|
||||
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include "lz.h"
|
||||
|
||||
void decode_range(unsigned int* range, unsigned int* code, unsigned char** src)
|
||||
{
|
||||
if (!((*range) >> 24))
|
||||
{
|
||||
(*range) <<= 8;
|
||||
*code = ((*code) << 8) + (*src)++[5];
|
||||
}
|
||||
}
|
||||
|
||||
int decode_bit(unsigned int* range, unsigned int* code, int* index, unsigned char** src, unsigned char* c)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
|
||||
unsigned int val = ((*range) >> 8) * (*c);
|
||||
|
||||
*c -= ((*c) >> 3);
|
||||
if (index)
|
||||
(*index) <<= 1;
|
||||
|
||||
if (*code < val)
|
||||
{
|
||||
*range = val;
|
||||
*c += 31;
|
||||
if (index)
|
||||
(*index)++;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*code -= val;
|
||||
*range -= val;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int decode_number(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src)
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
if (index >= 3)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x18);
|
||||
if (index >= 4)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x18);
|
||||
if (index >= 5)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
for (; index >= 5; index--)
|
||||
{
|
||||
i <<= 1;
|
||||
(*range) >>= 1;
|
||||
if (*code < *range)
|
||||
i++;
|
||||
else
|
||||
(*code) -= *range;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr);
|
||||
|
||||
if (index >= 1)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x8);
|
||||
if (index >= 2)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int decode_word(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src)
|
||||
{
|
||||
int i = 1;
|
||||
index /= 8;
|
||||
|
||||
if (index >= 3)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 4);
|
||||
if (index >= 4)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 4);
|
||||
if (index >= 5)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
for (; index >= 5; index--)
|
||||
{
|
||||
i <<= 1;
|
||||
(*range) >>= 1;
|
||||
if (*code < *range)
|
||||
i++;
|
||||
else
|
||||
(*code) -= *range;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr);
|
||||
|
||||
if (index >= 1)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 1);
|
||||
if (index >= 2)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 2);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int decompress(unsigned char* out, unsigned char* in, unsigned int size)
|
||||
{
|
||||
int result;
|
||||
|
||||
int offset = 0;
|
||||
int bit_flag = 0;
|
||||
int data_length = 0;
|
||||
int data_offset = 0;
|
||||
|
||||
unsigned char *tmp_sect1, *tmp_sect2, *tmp_sect3;
|
||||
const unsigned char *buf_start, *buf_end;
|
||||
unsigned char prev = 0;
|
||||
|
||||
unsigned char* start = out;
|
||||
const unsigned char* end = (out + size);
|
||||
unsigned char head = in[0];
|
||||
|
||||
unsigned int range = 0xFFFFFFFF;
|
||||
unsigned int code = (in[1] << 24) | (in[2] << 16) | (in[3] << 8) | in[4];
|
||||
|
||||
if (head > 0x80) // Check if we have a valid starting byte.
|
||||
{
|
||||
// The dictionary header is invalid, the data is not compressed.
|
||||
result = -1;
|
||||
if (code <= size)
|
||||
{
|
||||
memcpy(out, in + 5, code);
|
||||
result = static_cast<int>(start - out);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set up a temporary buffer (sliding window).
|
||||
std::vector<unsigned char> tmp_vec(0xCC8);
|
||||
unsigned char* tmp = tmp_vec.data();
|
||||
memset(tmp, 0x80, 0xCA8);
|
||||
while (true)
|
||||
{
|
||||
// Start reading at 0xB68.
|
||||
tmp_sect1 = tmp + offset + 0xB68;
|
||||
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
|
||||
{
|
||||
// Adjust offset and check for stream end.
|
||||
if (offset > 0)
|
||||
offset--;
|
||||
if (start == end)
|
||||
return static_cast<int>(start - out);
|
||||
|
||||
// Locate first section.
|
||||
int sect = ((((((static_cast<int>(start - out)) & 7) << 8) + prev) >> head) & 7) * 0xFF - 1;
|
||||
tmp_sect1 = tmp + sect;
|
||||
int index = 1;
|
||||
|
||||
// Read, decode and write back.
|
||||
do
|
||||
{
|
||||
decode_bit(&range, &code, &index, &in, tmp_sect1 + index);
|
||||
} while ((index >> 8) == 0);
|
||||
|
||||
// Save index.
|
||||
*start++ = index;
|
||||
}
|
||||
else // Compressed char stream.
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
// Identify the data length bit field.
|
||||
do
|
||||
{
|
||||
tmp_sect1 += 8;
|
||||
bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1);
|
||||
index += bit_flag;
|
||||
} while ((bit_flag != 0) && (index < 6));
|
||||
|
||||
// Default block size is 0x160.
|
||||
int b_size = 0x160;
|
||||
tmp_sect2 = tmp + index + 0x7F1;
|
||||
|
||||
// If the data length was found, parse it as a number.
|
||||
if ((index >= 0) || (bit_flag != 0))
|
||||
{
|
||||
// Locate next section.
|
||||
int sect = (index << 5) | ((((static_cast<int>(start - out)) << index) & 3) << 3) | (offset & 7);
|
||||
tmp_sect1 = tmp + 0xBA8 + sect;
|
||||
|
||||
// Decode the data length (8 bit fields).
|
||||
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
|
||||
if (data_length == 0xFF)
|
||||
return static_cast<int>(start - out); // End of stream.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume one byte of advance.
|
||||
data_length = 1;
|
||||
}
|
||||
|
||||
// If we got valid parameters, seek to find data offset.
|
||||
if ((data_length <= 2))
|
||||
{
|
||||
tmp_sect2 += 0xF8;
|
||||
b_size = 0x40; // Block size is now 0x40.
|
||||
}
|
||||
|
||||
int diff = 0;
|
||||
int shift = 1;
|
||||
|
||||
// Identify the data offset bit field.
|
||||
do
|
||||
{
|
||||
diff = (shift << 4) - b_size;
|
||||
bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3));
|
||||
} while (diff < 0);
|
||||
|
||||
// If the data offset was found, parse it as a number.
|
||||
if ((diff > 0) || (bit_flag != 0))
|
||||
{
|
||||
// Adjust diff if needed.
|
||||
if (bit_flag == 0)
|
||||
diff -= 8;
|
||||
|
||||
// Locate section.
|
||||
tmp_sect3 = tmp + 0x928 + diff;
|
||||
|
||||
// Decode the data offset (1 bit fields).
|
||||
data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume one byte of advance.
|
||||
data_offset = 1;
|
||||
}
|
||||
|
||||
// Set buffer start/end.
|
||||
buf_start = start - data_offset;
|
||||
buf_end = start + data_length + 1;
|
||||
|
||||
// Underflow.
|
||||
if (buf_start < out)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Overflow.
|
||||
if (buf_end > end)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Update offset.
|
||||
offset = (((static_cast<int>(buf_end - out)) + 1) & 1) + 6;
|
||||
|
||||
// Copy data.
|
||||
do
|
||||
{
|
||||
*start++ = *buf_start++;
|
||||
} while (start < buf_end);
|
||||
}
|
||||
prev = *(start - 1);
|
||||
}
|
||||
result = static_cast<int>(start - out);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
13
rpcs3/Crypto/lz.h
Normal file
13
rpcs3/Crypto/lz.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 2.0 or later versions.
|
||||
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression.
|
||||
|
||||
void decode_range(unsigned int* range, unsigned int* code, unsigned char** src);
|
||||
int decode_bit(unsigned int* range, unsigned int* code, int* index, unsigned char** src, unsigned char* c);
|
||||
int decode_number(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src);
|
||||
int decode_word(unsigned char* ptr, int index, int* bit_flag, unsigned int* range, unsigned int* code, unsigned char** src);
|
||||
int decompress(unsigned char* out, unsigned char* in, unsigned int size);
|
||||
472
rpcs3/Crypto/md5.cpp
Normal file
472
rpcs3/Crypto/md5.cpp
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* RFC 1321 compliant MD5 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* The MD5 algorithm was designed by Ron Rivest in 1991.
|
||||
*
|
||||
* http://www.ietf.org/rfc/rfc1321.txt
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(MBEDTLS_MD5_ALT)
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (little endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_LE
|
||||
#define GET_UINT32_LE(n, b, i) \
|
||||
{ \
|
||||
(n) = (static_cast<uint32_t>((b)[(i)])) | (static_cast<uint32_t>((b)[(i) + 1]) << 8) | (static_cast<uint32_t>((b)[(i) + 2]) << 16) | (static_cast<uint32_t>((b)[(i) + 3]) << 24); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_LE
|
||||
#define PUT_UINT32_LE(n, b, i) \
|
||||
{ \
|
||||
(b)[(i)] = static_cast<unsigned char>(((n)) & 0xFF); \
|
||||
(b)[(i) + 1] = static_cast<unsigned char>(((n) >> 8) & 0xFF); \
|
||||
(b)[(i) + 2] = static_cast<unsigned char>(((n) >> 16) & 0xFF); \
|
||||
(b)[(i) + 3] = static_cast<unsigned char>(((n) >> 24) & 0xFF); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void mbedtls_md5_init(mbedtls_md5_context* ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(mbedtls_md5_context));
|
||||
}
|
||||
|
||||
void mbedtls_md5_free(mbedtls_md5_context* ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
mbedtls_zeroize(ctx, sizeof(mbedtls_md5_context));
|
||||
}
|
||||
|
||||
void mbedtls_md5_clone(mbedtls_md5_context* dst,
|
||||
const mbedtls_md5_context* src)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 context setup
|
||||
*/
|
||||
int mbedtls_md5_starts_ret(mbedtls_md5_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;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_md5_starts(mbedtls_md5_context* ctx)
|
||||
{
|
||||
mbedtls_md5_starts_ret(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_MD5_PROCESS_ALT)
|
||||
int mbedtls_internal_md5_process(mbedtls_md5_context* ctx,
|
||||
const unsigned char data[64])
|
||||
{
|
||||
uint32_t X[16], A, B, C, D;
|
||||
|
||||
GET_UINT32_LE(X[0], data, 0);
|
||||
GET_UINT32_LE(X[1], data, 4);
|
||||
GET_UINT32_LE(X[2], data, 8);
|
||||
GET_UINT32_LE(X[3], data, 12);
|
||||
GET_UINT32_LE(X[4], data, 16);
|
||||
GET_UINT32_LE(X[5], data, 20);
|
||||
GET_UINT32_LE(X[6], data, 24);
|
||||
GET_UINT32_LE(X[7], data, 28);
|
||||
GET_UINT32_LE(X[8], data, 32);
|
||||
GET_UINT32_LE(X[9], data, 36);
|
||||
GET_UINT32_LE(X[10], data, 40);
|
||||
GET_UINT32_LE(X[11], data, 44);
|
||||
GET_UINT32_LE(X[12], data, 48);
|
||||
GET_UINT32_LE(X[13], data, 52);
|
||||
GET_UINT32_LE(X[14], data, 56);
|
||||
GET_UINT32_LE(X[15], data, 60);
|
||||
|
||||
#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define P(a, b, c, d, k, s, t) \
|
||||
{ \
|
||||
a += F(b, c, d) + X[k] + t; \
|
||||
a = S(a, s) + b; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
|
||||
#define F(x, y, z) (z ^ (x & (y ^ z)))
|
||||
|
||||
P(A, B, C, D, 0, 7, 0xD76AA478);
|
||||
P(D, A, B, C, 1, 12, 0xE8C7B756);
|
||||
P(C, D, A, B, 2, 17, 0x242070DB);
|
||||
P(B, C, D, A, 3, 22, 0xC1BDCEEE);
|
||||
P(A, B, C, D, 4, 7, 0xF57C0FAF);
|
||||
P(D, A, B, C, 5, 12, 0x4787C62A);
|
||||
P(C, D, A, B, 6, 17, 0xA8304613);
|
||||
P(B, C, D, A, 7, 22, 0xFD469501);
|
||||
P(A, B, C, D, 8, 7, 0x698098D8);
|
||||
P(D, A, B, C, 9, 12, 0x8B44F7AF);
|
||||
P(C, D, A, B, 10, 17, 0xFFFF5BB1);
|
||||
P(B, C, D, A, 11, 22, 0x895CD7BE);
|
||||
P(A, B, C, D, 12, 7, 0x6B901122);
|
||||
P(D, A, B, C, 13, 12, 0xFD987193);
|
||||
P(C, D, A, B, 14, 17, 0xA679438E);
|
||||
P(B, C, D, A, 15, 22, 0x49B40821);
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (y ^ (z & (x ^ y)))
|
||||
|
||||
P(A, B, C, D, 1, 5, 0xF61E2562);
|
||||
P(D, A, B, C, 6, 9, 0xC040B340);
|
||||
P(C, D, A, B, 11, 14, 0x265E5A51);
|
||||
P(B, C, D, A, 0, 20, 0xE9B6C7AA);
|
||||
P(A, B, C, D, 5, 5, 0xD62F105D);
|
||||
P(D, A, B, C, 10, 9, 0x02441453);
|
||||
P(C, D, A, B, 15, 14, 0xD8A1E681);
|
||||
P(B, C, D, A, 4, 20, 0xE7D3FBC8);
|
||||
P(A, B, C, D, 9, 5, 0x21E1CDE6);
|
||||
P(D, A, B, C, 14, 9, 0xC33707D6);
|
||||
P(C, D, A, B, 3, 14, 0xF4D50D87);
|
||||
P(B, C, D, A, 8, 20, 0x455A14ED);
|
||||
P(A, B, C, D, 13, 5, 0xA9E3E905);
|
||||
P(D, A, B, C, 2, 9, 0xFCEFA3F8);
|
||||
P(C, D, A, B, 7, 14, 0x676F02D9);
|
||||
P(B, C, D, A, 12, 20, 0x8D2A4C8A);
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (x ^ y ^ z)
|
||||
|
||||
P(A, B, C, D, 5, 4, 0xFFFA3942);
|
||||
P(D, A, B, C, 8, 11, 0x8771F681);
|
||||
P(C, D, A, B, 11, 16, 0x6D9D6122);
|
||||
P(B, C, D, A, 14, 23, 0xFDE5380C);
|
||||
P(A, B, C, D, 1, 4, 0xA4BEEA44);
|
||||
P(D, A, B, C, 4, 11, 0x4BDECFA9);
|
||||
P(C, D, A, B, 7, 16, 0xF6BB4B60);
|
||||
P(B, C, D, A, 10, 23, 0xBEBFBC70);
|
||||
P(A, B, C, D, 13, 4, 0x289B7EC6);
|
||||
P(D, A, B, C, 0, 11, 0xEAA127FA);
|
||||
P(C, D, A, B, 3, 16, 0xD4EF3085);
|
||||
P(B, C, D, A, 6, 23, 0x04881D05);
|
||||
P(A, B, C, D, 9, 4, 0xD9D4D039);
|
||||
P(D, A, B, C, 12, 11, 0xE6DB99E5);
|
||||
P(C, D, A, B, 15, 16, 0x1FA27CF8);
|
||||
P(B, C, D, A, 2, 23, 0xC4AC5665);
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
P(A, B, C, D, 0, 6, 0xF4292244);
|
||||
P(D, A, B, C, 7, 10, 0x432AFF97);
|
||||
P(C, D, A, B, 14, 15, 0xAB9423A7);
|
||||
P(B, C, D, A, 5, 21, 0xFC93A039);
|
||||
P(A, B, C, D, 12, 6, 0x655B59C3);
|
||||
P(D, A, B, C, 3, 10, 0x8F0CCC92);
|
||||
P(C, D, A, B, 10, 15, 0xFFEFF47D);
|
||||
P(B, C, D, A, 1, 21, 0x85845DD1);
|
||||
P(A, B, C, D, 8, 6, 0x6FA87E4F);
|
||||
P(D, A, B, C, 15, 10, 0xFE2CE6E0);
|
||||
P(C, D, A, B, 6, 15, 0xA3014314);
|
||||
P(B, C, D, A, 13, 21, 0x4E0811A1);
|
||||
P(A, B, C, D, 4, 6, 0xF7537E82);
|
||||
P(D, A, B, C, 11, 10, 0xBD3AF235);
|
||||
P(C, D, A, B, 2, 15, 0x2AD7D2BB);
|
||||
P(B, C, D, A, 9, 21, 0xEB86D391);
|
||||
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_md5_process(mbedtls_md5_context* ctx,
|
||||
const unsigned char data[64])
|
||||
{
|
||||
mbedtls_internal_md5_process(ctx, data);
|
||||
}
|
||||
#endif
|
||||
#endif /* !MBEDTLS_MD5_PROCESS_ALT */
|
||||
|
||||
/*
|
||||
* MD5 process buffer
|
||||
*/
|
||||
int mbedtls_md5_update_ret(mbedtls_md5_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen)
|
||||
{
|
||||
int ret;
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if (ilen == 0)
|
||||
return (0);
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += static_cast<uint32_t>(ilen);
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < static_cast<uint32_t>(ilen))
|
||||
ctx->total[1]++;
|
||||
|
||||
if (left && ilen >= fill)
|
||||
{
|
||||
memcpy(ctx->buffer + left, input, fill);
|
||||
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
|
||||
return (ret);
|
||||
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (ilen >= 64)
|
||||
{
|
||||
if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0)
|
||||
return (ret);
|
||||
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if (ilen > 0)
|
||||
{
|
||||
memcpy(ctx->buffer + left, input, ilen);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_md5_update(mbedtls_md5_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen)
|
||||
{
|
||||
mbedtls_md5_update_ret(ctx, input, ilen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MD5 final digest
|
||||
*/
|
||||
int mbedtls_md5_finish_ret(mbedtls_md5_context* ctx,
|
||||
unsigned char output[16])
|
||||
{
|
||||
int ret;
|
||||
uint32_t used;
|
||||
uint32_t high, low;
|
||||
|
||||
/*
|
||||
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
|
||||
*/
|
||||
used = ctx->total[0] & 0x3F;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
if (used <= 56)
|
||||
{
|
||||
/* Enough room for padding + length in current block */
|
||||
memset(ctx->buffer + used, 0, 56 - used);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll need an extra block */
|
||||
memset(ctx->buffer + used, 0, 64 - used);
|
||||
|
||||
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
|
||||
return (ret);
|
||||
|
||||
memset(ctx->buffer, 0, 56);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add message length
|
||||
*/
|
||||
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
|
||||
low = (ctx->total[0] << 3);
|
||||
|
||||
PUT_UINT32_LE(low, ctx->buffer, 56);
|
||||
PUT_UINT32_LE(high, ctx->buffer, 60);
|
||||
|
||||
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Output final state
|
||||
*/
|
||||
PUT_UINT32_LE(ctx->state[0], output, 0);
|
||||
PUT_UINT32_LE(ctx->state[1], output, 4);
|
||||
PUT_UINT32_LE(ctx->state[2], output, 8);
|
||||
PUT_UINT32_LE(ctx->state[3], output, 12);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_md5_finish(mbedtls_md5_context* ctx,
|
||||
unsigned char output[16])
|
||||
{
|
||||
mbedtls_md5_finish_ret(ctx, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !MBEDTLS_MD5_ALT */
|
||||
|
||||
/*
|
||||
* output = MD5( input buffer )
|
||||
*/
|
||||
int mbedtls_md5_ret(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[16])
|
||||
{
|
||||
int ret;
|
||||
mbedtls_md5_context ctx;
|
||||
|
||||
mbedtls_md5_init(&ctx);
|
||||
|
||||
if ((ret = mbedtls_md5_starts_ret(&ctx)) != 0)
|
||||
goto exit;
|
||||
|
||||
if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0)
|
||||
goto exit;
|
||||
|
||||
if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
mbedtls_md5_free(&ctx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_md5(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[16])
|
||||
{
|
||||
mbedtls_md5_ret(input, ilen, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
/*
|
||||
* RFC 1321 test vectors
|
||||
*/
|
||||
static const unsigned char md5_test_buf[7][81] =
|
||||
{
|
||||
{""},
|
||||
{"a"},
|
||||
{"abc"},
|
||||
{"message digest"},
|
||||
{"abcdefghijklmnopqrstuvwxyz"},
|
||||
{"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
|
||||
{"12345678901234567890123456789012345678901234567890123456789012"
|
||||
"345678901234567890"}};
|
||||
|
||||
static const size_t md5_test_buflen[7] =
|
||||
{
|
||||
0, 1, 3, 14, 26, 62, 80};
|
||||
|
||||
static const unsigned char md5_test_sum[7][16] =
|
||||
{
|
||||
{0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
|
||||
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E},
|
||||
{0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
|
||||
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61},
|
||||
{0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
|
||||
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72},
|
||||
{0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
|
||||
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0},
|
||||
{0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
|
||||
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B},
|
||||
{0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
|
||||
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F},
|
||||
{0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
|
||||
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A}};
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
int mbedtls_md5_self_test(int verbose)
|
||||
{
|
||||
int i, ret = 0;
|
||||
unsigned char md5sum[16];
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if (verbose != 0)
|
||||
mbedtls_printf(" MD5 test #%d: ", i + 1);
|
||||
|
||||
ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
if (memcmp(md5sum, md5_test_sum[i], 16) != 0)
|
||||
{
|
||||
ret = 1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
mbedtls_printf("passed\n");
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
mbedtls_printf("\n");
|
||||
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
if (verbose != 0)
|
||||
mbedtls_printf("failed\n");
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
307
rpcs3/Crypto/md5.h
Normal file
307
rpcs3/Crypto/md5.h
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* \file md5.h
|
||||
*
|
||||
* \brief MD5 message digest algorithm (hash function)
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use constitutes a
|
||||
* security risk. We recommend considering stronger message
|
||||
* digests instead.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#ifndef MBEDTLS_MD5_H
|
||||
#define MBEDTLS_MD5_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */
|
||||
#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_MD5_ALT)
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
/**
|
||||
* \brief MD5 context structure
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
typedef struct mbedtls_md5_context
|
||||
{
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[4]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
} mbedtls_md5_context;
|
||||
|
||||
#else /* MBEDTLS_MD5_ALT */
|
||||
#include "md5_alt.h"
|
||||
#endif /* MBEDTLS_MD5_ALT */
|
||||
|
||||
/**
|
||||
* \brief Initialize MD5 context
|
||||
*
|
||||
* \param ctx MD5 context to be initialized
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
void mbedtls_md5_init(mbedtls_md5_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief Clear MD5 context
|
||||
*
|
||||
* \param ctx MD5 context to be cleared
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
void mbedtls_md5_free(mbedtls_md5_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) an MD5 context
|
||||
*
|
||||
* \param dst The destination context
|
||||
* \param src The context to be cloned
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
void mbedtls_md5_clone(mbedtls_md5_context* dst,
|
||||
const mbedtls_md5_context* src);
|
||||
|
||||
/**
|
||||
* \brief MD5 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*
|
||||
* \return 0 if successful
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
int mbedtls_md5_starts_ret(mbedtls_md5_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief MD5 process buffer
|
||||
*
|
||||
* \param ctx MD5 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
int mbedtls_md5_update_ret(mbedtls_md5_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief MD5 final digest
|
||||
*
|
||||
* \param ctx MD5 context
|
||||
* \param output MD5 checksum result
|
||||
*
|
||||
* \return 0 if successful
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
int mbedtls_md5_finish_ret(mbedtls_md5_context* ctx,
|
||||
unsigned char output[16]);
|
||||
|
||||
/**
|
||||
* \brief MD5 process data block (internal use only)
|
||||
*
|
||||
* \param ctx MD5 context
|
||||
* \param data buffer holding one block of data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
int mbedtls_internal_md5_process(mbedtls_md5_context* ctx,
|
||||
const unsigned char data[64]);
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
#if defined(MBEDTLS_DEPRECATED_WARNING)
|
||||
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define MBEDTLS_DEPRECATED
|
||||
#endif
|
||||
/**
|
||||
* \brief MD5 context setup
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief MD5 process buffer
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0
|
||||
*
|
||||
* \param ctx MD5 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief MD5 final digest
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0
|
||||
*
|
||||
* \param ctx MD5 context
|
||||
* \param output MD5 checksum result
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context* ctx,
|
||||
unsigned char output[16]);
|
||||
|
||||
/**
|
||||
* \brief MD5 process data block (internal use only)
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0
|
||||
*
|
||||
* \param ctx MD5 context
|
||||
* \param data buffer holding one block of data
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context* ctx,
|
||||
const unsigned char data[64]);
|
||||
|
||||
#undef MBEDTLS_DEPRECATED
|
||||
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
/**
|
||||
* \brief Output = MD5( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output MD5 checksum result
|
||||
*
|
||||
* \return 0 if successful
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
int mbedtls_md5_ret(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[16]);
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
#if defined(MBEDTLS_DEPRECATED_WARNING)
|
||||
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define MBEDTLS_DEPRECATED
|
||||
#endif
|
||||
/**
|
||||
* \brief Output = MD5( input buffer )
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_md5_ret() in 2.7.0
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output MD5 checksum result
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_md5(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[16]);
|
||||
|
||||
#undef MBEDTLS_DEPRECATED
|
||||
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*
|
||||
* \warning MD5 is considered a weak message digest and its use
|
||||
* constitutes a security risk. We recommend considering
|
||||
* stronger message digests instead.
|
||||
*
|
||||
*/
|
||||
int mbedtls_md5_self_test(int verbose);
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* mbedtls_md5.h */
|
||||
392
rpcs3/Crypto/sha1.cpp
Normal file
392
rpcs3/Crypto/sha1.cpp
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* FIPS-180-1 compliant SHA-1 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* The SHA-1 standard was published by NIST in 1993.
|
||||
*
|
||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
*/
|
||||
|
||||
#include "sha1.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_BE
|
||||
#define GET_UINT32_BE(n, b, i) \
|
||||
{ \
|
||||
(n) = (static_cast<uint32_t>((b)[(i)]) << 24) | (static_cast<uint32_t>((b)[(i) + 1]) << 16) | (static_cast<uint32_t>((b)[(i) + 2]) << 8) | (static_cast<uint32_t>((b)[(i) + 3])); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n, b, i) \
|
||||
{ \
|
||||
(b)[(i)] = static_cast<unsigned char>((n) >> 24); \
|
||||
(b)[(i) + 1] = static_cast<unsigned char>((n) >> 16); \
|
||||
(b)[(i) + 2] = static_cast<unsigned char>((n) >> 8); \
|
||||
(b)[(i) + 3] = static_cast<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;
|
||||
|
||||
// TODO:: Syphurith: Orz. It is said that size_t is an unsigned type..
|
||||
if (ilen <= 0)
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += static_cast<uint32_t>(ilen);
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < static_cast<uint32_t>(ilen))
|
||||
ctx->total[1]++;
|
||||
|
||||
if (left && ilen >= fill)
|
||||
{
|
||||
memcpy(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(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);
|
||||
|
||||
mbedtls_zeroize(&ctx, 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] ^= key[i];
|
||||
ctx->opad[i] ^= key[i];
|
||||
}
|
||||
|
||||
sha1_starts(ctx);
|
||||
sha1_update(ctx, ctx->ipad, 64);
|
||||
|
||||
mbedtls_zeroize(sum, 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));
|
||||
}
|
||||
164
rpcs3/Crypto/sha1.h
Normal file
164
rpcs3/Crypto/sha1.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* \file sha1.h
|
||||
*
|
||||
* \brief SHA-1 cryptographic hash function
|
||||
*
|
||||
* Copyright (C) 2006-2013, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <basetsd.h>
|
||||
typedef UINT32 uint32_t;
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
|
||||
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[5]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
|
||||
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||
} sha1_context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void sha1_starts(sha1_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 process buffer
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void sha1_update(sha1_context* ctx, const unsigned char* input, size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void sha1_finish(sha1_context* ctx, unsigned char output[20]);
|
||||
|
||||
/* Internal use */
|
||||
void sha1_process(sha1_context* ctx, const unsigned char data[64]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void sha1(const unsigned char* input, size_t ilen, unsigned char output[20]);
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( file contents )
|
||||
*
|
||||
* \param path input file name
|
||||
* \param output SHA-1 checksum result
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
|
||||
*/
|
||||
int sha1_file(const char* path, unsigned char output[20]);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 HMAC context setup
|
||||
*
|
||||
* \param ctx HMAC context to be initialized
|
||||
* \param key HMAC secret key
|
||||
* \param keylen length of the HMAC key
|
||||
*/
|
||||
void sha1_hmac_starts(sha1_context* ctx, const unsigned char* key, size_t keylen);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 HMAC process buffer
|
||||
*
|
||||
* \param ctx HMAC context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void sha1_hmac_update(sha1_context* ctx, const unsigned char* input, size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 HMAC final digest
|
||||
*
|
||||
* \param ctx HMAC context
|
||||
* \param output SHA-1 HMAC checksum result
|
||||
*/
|
||||
void sha1_hmac_finish(sha1_context* ctx, unsigned char output[20]);
|
||||
|
||||
/**
|
||||
* \brief SHA-1 HMAC context reset
|
||||
*
|
||||
* \param ctx HMAC context to be reset
|
||||
*/
|
||||
void sha1_hmac_reset(sha1_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief Output = HMAC-SHA-1( hmac key, input buffer )
|
||||
*
|
||||
* \param key HMAC secret key
|
||||
* \param keylen length of the HMAC key
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output HMAC-SHA-1 result
|
||||
*/
|
||||
void sha1_hmac(const unsigned char* key, size_t keylen,
|
||||
const unsigned char* input, size_t ilen,
|
||||
unsigned char output[20]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
495
rpcs3/Crypto/sha256.cpp
Normal file
495
rpcs3/Crypto/sha256.cpp
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
* FIPS-180-2 compliant SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
|
||||
*
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
*/
|
||||
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define mbedtls_printf printf
|
||||
#define mbedtls_calloc calloc
|
||||
#define mbedtls_free free
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#define SHA256_VALIDATE_RET(cond)
|
||||
#define SHA256_VALIDATE(cond)
|
||||
|
||||
#if !defined(MBEDTLS_SHA256_ALT)
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_BE
|
||||
#define GET_UINT32_BE(n, b, i) \
|
||||
do \
|
||||
{ \
|
||||
(n) = (static_cast<uint32_t>((b)[(i)]) << 24) | (static_cast<uint32_t>((b)[(i) + 1]) << 16) | (static_cast<uint32_t>((b)[(i) + 2]) << 8) | (static_cast<uint32_t>((b)[(i) + 3])); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n, b, i) \
|
||||
do \
|
||||
{ \
|
||||
(b)[(i)] = static_cast<unsigned char>((n) >> 24); \
|
||||
(b)[(i) + 1] = static_cast<unsigned char>((n) >> 16); \
|
||||
(b)[(i) + 2] = static_cast<unsigned char>((n) >> 8); \
|
||||
(b)[(i) + 3] = static_cast<unsigned char>((n)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
void mbedtls_sha256_init(mbedtls_sha256_context* ctx)
|
||||
{
|
||||
SHA256_VALIDATE(ctx != NULL);
|
||||
|
||||
memset(ctx, 0, sizeof(mbedtls_sha256_context));
|
||||
}
|
||||
|
||||
void mbedtls_sha256_free(mbedtls_sha256_context* ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context));
|
||||
}
|
||||
|
||||
void mbedtls_sha256_clone(mbedtls_sha256_context* dst,
|
||||
const mbedtls_sha256_context* src)
|
||||
{
|
||||
SHA256_VALIDATE(dst != NULL);
|
||||
SHA256_VALIDATE(src != NULL);
|
||||
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 context setup
|
||||
*/
|
||||
int mbedtls_sha256_starts_ret(mbedtls_sha256_context* ctx, int is224)
|
||||
{
|
||||
SHA256_VALIDATE_RET(ctx != NULL);
|
||||
SHA256_VALIDATE_RET(is224 == 0 || is224 == 1);
|
||||
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
if (is224 == 0)
|
||||
{
|
||||
/* SHA-256 */
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SHA-224 */
|
||||
ctx->state[0] = 0xC1059ED8;
|
||||
ctx->state[1] = 0x367CD507;
|
||||
ctx->state[2] = 0x3070DD17;
|
||||
ctx->state[3] = 0xF70E5939;
|
||||
ctx->state[4] = 0xFFC00B31;
|
||||
ctx->state[5] = 0x68581511;
|
||||
ctx->state[6] = 0x64F98FA7;
|
||||
ctx->state[7] = 0xBEFA4FA4;
|
||||
}
|
||||
|
||||
ctx->is224 = is224;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_sha256_starts(mbedtls_sha256_context* ctx,
|
||||
int is224)
|
||||
{
|
||||
mbedtls_sha256_starts_ret(ctx, is224);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
|
||||
static const uint32_t K[] =
|
||||
{
|
||||
0x428A2F98,
|
||||
0x71374491,
|
||||
0xB5C0FBCF,
|
||||
0xE9B5DBA5,
|
||||
0x3956C25B,
|
||||
0x59F111F1,
|
||||
0x923F82A4,
|
||||
0xAB1C5ED5,
|
||||
0xD807AA98,
|
||||
0x12835B01,
|
||||
0x243185BE,
|
||||
0x550C7DC3,
|
||||
0x72BE5D74,
|
||||
0x80DEB1FE,
|
||||
0x9BDC06A7,
|
||||
0xC19BF174,
|
||||
0xE49B69C1,
|
||||
0xEFBE4786,
|
||||
0x0FC19DC6,
|
||||
0x240CA1CC,
|
||||
0x2DE92C6F,
|
||||
0x4A7484AA,
|
||||
0x5CB0A9DC,
|
||||
0x76F988DA,
|
||||
0x983E5152,
|
||||
0xA831C66D,
|
||||
0xB00327C8,
|
||||
0xBF597FC7,
|
||||
0xC6E00BF3,
|
||||
0xD5A79147,
|
||||
0x06CA6351,
|
||||
0x14292967,
|
||||
0x27B70A85,
|
||||
0x2E1B2138,
|
||||
0x4D2C6DFC,
|
||||
0x53380D13,
|
||||
0x650A7354,
|
||||
0x766A0ABB,
|
||||
0x81C2C92E,
|
||||
0x92722C85,
|
||||
0xA2BFE8A1,
|
||||
0xA81A664B,
|
||||
0xC24B8B70,
|
||||
0xC76C51A3,
|
||||
0xD192E819,
|
||||
0xD6990624,
|
||||
0xF40E3585,
|
||||
0x106AA070,
|
||||
0x19A4C116,
|
||||
0x1E376C08,
|
||||
0x2748774C,
|
||||
0x34B0BCB5,
|
||||
0x391C0CB3,
|
||||
0x4ED8AA4A,
|
||||
0x5B9CCA4F,
|
||||
0x682E6FF3,
|
||||
0x748F82EE,
|
||||
0x78A5636F,
|
||||
0x84C87814,
|
||||
0x8CC70208,
|
||||
0x90BEFFFA,
|
||||
0xA4506CEB,
|
||||
0xBEF9A3F7,
|
||||
0xC67178F2,
|
||||
};
|
||||
|
||||
#define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
|
||||
#define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
|
||||
|
||||
#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
|
||||
#define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
|
||||
#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
|
||||
#define R(t) \
|
||||
( \
|
||||
W[t] = S1(W[(t) - 2]) + W[(t) - 7] + \
|
||||
S0(W[(t) - 15]) + W[(t) - 16])
|
||||
|
||||
#define P(a, b, c, d, e, f, g, h, x, K) \
|
||||
do \
|
||||
{ \
|
||||
temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \
|
||||
temp2 = S2(a) + F0((a), (b), (c)); \
|
||||
(d) += temp1; \
|
||||
(h) = temp1 + temp2; \
|
||||
} while (0)
|
||||
|
||||
int mbedtls_internal_sha256_process(mbedtls_sha256_context* ctx,
|
||||
const unsigned char data[64])
|
||||
{
|
||||
uint32_t temp1, temp2, W[64];
|
||||
uint32_t A[8];
|
||||
unsigned int i;
|
||||
|
||||
SHA256_VALIDATE_RET(ctx != NULL);
|
||||
SHA256_VALIDATE_RET((const unsigned char*)data != NULL);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
A[i] = ctx->state[i];
|
||||
|
||||
#if defined(MBEDTLS_SHA256_SMALLER)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
if (i < 16)
|
||||
GET_UINT32_BE(W[i], data, 4 * i);
|
||||
else
|
||||
R(i);
|
||||
|
||||
P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]);
|
||||
|
||||
temp1 = A[7];
|
||||
A[7] = A[6];
|
||||
A[6] = A[5];
|
||||
A[5] = A[4];
|
||||
A[4] = A[3];
|
||||
A[3] = A[2];
|
||||
A[2] = A[1];
|
||||
A[1] = A[0];
|
||||
A[0] = temp1;
|
||||
}
|
||||
#else /* MBEDTLS_SHA256_SMALLER */
|
||||
for (i = 0; i < 16; i++)
|
||||
GET_UINT32_BE(W[i], data, 4 * i);
|
||||
|
||||
for (i = 0; i < 16; i += 8)
|
||||
{
|
||||
P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0]);
|
||||
P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1]);
|
||||
P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2]);
|
||||
P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3]);
|
||||
P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4]);
|
||||
P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5]);
|
||||
P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6]);
|
||||
P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7]);
|
||||
}
|
||||
|
||||
for (i = 16; i < 64; i += 8)
|
||||
{
|
||||
P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0]);
|
||||
P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1]);
|
||||
P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2]);
|
||||
P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3]);
|
||||
P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4]);
|
||||
P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5]);
|
||||
P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6]);
|
||||
P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7]);
|
||||
}
|
||||
#endif /* MBEDTLS_SHA256_SMALLER */
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
ctx->state[i] += A[i];
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_sha256_process(mbedtls_sha256_context* ctx,
|
||||
const unsigned char data[64])
|
||||
{
|
||||
mbedtls_internal_sha256_process(ctx, data);
|
||||
}
|
||||
#endif
|
||||
#endif /* !MBEDTLS_SHA256_PROCESS_ALT */
|
||||
|
||||
/*
|
||||
* SHA-256 process buffer
|
||||
*/
|
||||
int mbedtls_sha256_update_ret(mbedtls_sha256_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen)
|
||||
{
|
||||
int ret;
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
SHA256_VALIDATE_RET(ctx != NULL);
|
||||
SHA256_VALIDATE_RET(ilen == 0 || input != NULL);
|
||||
|
||||
if (ilen == 0)
|
||||
return (0);
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += static_cast<uint32_t>(ilen);
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < static_cast<uint32_t>(ilen))
|
||||
ctx->total[1]++;
|
||||
|
||||
if (left && ilen >= fill)
|
||||
{
|
||||
memcpy(ctx->buffer + left, input, fill);
|
||||
|
||||
if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0)
|
||||
return (ret);
|
||||
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (ilen >= 64)
|
||||
{
|
||||
if ((ret = mbedtls_internal_sha256_process(ctx, input)) != 0)
|
||||
return (ret);
|
||||
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if (ilen > 0)
|
||||
memcpy(ctx->buffer + left, input, ilen);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_sha256_update(mbedtls_sha256_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen)
|
||||
{
|
||||
mbedtls_sha256_update_ret(ctx, input, ilen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SHA-256 final digest
|
||||
*/
|
||||
int mbedtls_sha256_finish_ret(mbedtls_sha256_context* ctx,
|
||||
unsigned char output[32])
|
||||
{
|
||||
int ret;
|
||||
uint32_t used;
|
||||
uint32_t high, low;
|
||||
|
||||
SHA256_VALIDATE_RET(ctx != NULL);
|
||||
SHA256_VALIDATE_RET((unsigned char*)output != NULL);
|
||||
|
||||
/*
|
||||
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
|
||||
*/
|
||||
used = ctx->total[0] & 0x3F;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
if (used <= 56)
|
||||
{
|
||||
/* Enough room for padding + length in current block */
|
||||
memset(ctx->buffer + used, 0, 56 - used);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll need an extra block */
|
||||
memset(ctx->buffer + used, 0, 64 - used);
|
||||
|
||||
if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0)
|
||||
return (ret);
|
||||
|
||||
memset(ctx->buffer, 0, 56);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add message length
|
||||
*/
|
||||
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
|
||||
low = (ctx->total[0] << 3);
|
||||
|
||||
PUT_UINT32_BE(high, ctx->buffer, 56);
|
||||
PUT_UINT32_BE(low, ctx->buffer, 60);
|
||||
|
||||
if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Output final state
|
||||
*/
|
||||
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);
|
||||
PUT_UINT32_BE(ctx->state[5], output, 20);
|
||||
PUT_UINT32_BE(ctx->state[6], output, 24);
|
||||
|
||||
if (ctx->is224 == 0)
|
||||
PUT_UINT32_BE(ctx->state[7], output, 28);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_sha256_finish(mbedtls_sha256_context* ctx,
|
||||
unsigned char output[32])
|
||||
{
|
||||
mbedtls_sha256_finish_ret(ctx, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !MBEDTLS_SHA256_ALT */
|
||||
|
||||
/*
|
||||
* output = SHA-256( input buffer )
|
||||
*/
|
||||
int mbedtls_sha256_ret(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[32],
|
||||
int is224)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_sha256_context ctx;
|
||||
|
||||
SHA256_VALIDATE_RET(is224 == 0 || is224 == 1);
|
||||
SHA256_VALIDATE_RET(ilen == 0 || input != NULL);
|
||||
SHA256_VALIDATE_RET((unsigned char*)output != NULL);
|
||||
|
||||
mbedtls_sha256_init(&ctx);
|
||||
|
||||
if ((ret = mbedtls_sha256_starts_ret(&ctx, is224)) != 0)
|
||||
goto exit;
|
||||
|
||||
if ((ret = mbedtls_sha256_update_ret(&ctx, input, ilen)) != 0)
|
||||
goto exit;
|
||||
|
||||
if ((ret = mbedtls_sha256_finish_ret(&ctx, output)) != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
mbedtls_sha256_free(&ctx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
void mbedtls_sha256(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[32],
|
||||
int is224)
|
||||
{
|
||||
mbedtls_sha256_ret(input, ilen, output, is224);
|
||||
}
|
||||
#endif
|
||||
281
rpcs3/Crypto/sha256.h
Normal file
281
rpcs3/Crypto/sha256.h
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
/**
|
||||
* \file sha256.h
|
||||
*
|
||||
* \brief This file contains SHA-224 and SHA-256 definitions and functions.
|
||||
*
|
||||
* The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic
|
||||
* hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is part of Mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#ifndef MBEDTLS_SHA256_H
|
||||
#define MBEDTLS_SHA256_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */
|
||||
#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */
|
||||
#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_SHA256_ALT)
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
/**
|
||||
* \brief The SHA-256 context structure.
|
||||
*
|
||||
* The structure is used both for SHA-256 and for SHA-224
|
||||
* checksum calculations. The choice between these two is
|
||||
* made in the call to mbedtls_sha256_starts_ret().
|
||||
*/
|
||||
typedef struct mbedtls_sha256_context
|
||||
{
|
||||
uint32_t total[2]; /*!< The number of Bytes processed. */
|
||||
uint32_t state[8]; /*!< The intermediate digest state. */
|
||||
unsigned char buffer[64]; /*!< The data block being processed. */
|
||||
int is224; /*!< Determines which function to use:
|
||||
0: Use SHA-256, or 1: Use SHA-224. */
|
||||
} mbedtls_sha256_context;
|
||||
|
||||
#else /* MBEDTLS_SHA256_ALT */
|
||||
#include "sha256_alt.h"
|
||||
#endif /* MBEDTLS_SHA256_ALT */
|
||||
|
||||
/**
|
||||
* \brief This function initializes a SHA-256 context.
|
||||
*
|
||||
* \param ctx The SHA-256 context to initialize. This must not be \c NULL.
|
||||
*/
|
||||
void mbedtls_sha256_init(mbedtls_sha256_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief This function clears a SHA-256 context.
|
||||
*
|
||||
* \param ctx The SHA-256 context to clear. This may be \c NULL, in which
|
||||
* case this function returns immediately. If it is not \c NULL,
|
||||
* it must point to an initialized SHA-256 context.
|
||||
*/
|
||||
void mbedtls_sha256_free(mbedtls_sha256_context* ctx);
|
||||
|
||||
/**
|
||||
* \brief This function clones the state of a SHA-256 context.
|
||||
*
|
||||
* \param dst The destination context. This must be initialized.
|
||||
* \param src The context to clone. This must be initialized.
|
||||
*/
|
||||
void mbedtls_sha256_clone(mbedtls_sha256_context* dst,
|
||||
const mbedtls_sha256_context* src);
|
||||
|
||||
/**
|
||||
* \brief This function starts a SHA-224 or SHA-256 checksum
|
||||
* calculation.
|
||||
*
|
||||
* \param ctx The context to use. This must be initialized.
|
||||
* \param is224 This determines which function to use. This must be
|
||||
* either \c 0 for SHA-256, or \c 1 for SHA-224.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return A negative error code on failure.
|
||||
*/
|
||||
int mbedtls_sha256_starts_ret(mbedtls_sha256_context* ctx, int is224);
|
||||
|
||||
/**
|
||||
* \brief This function feeds an input buffer into an ongoing
|
||||
* SHA-256 checksum calculation.
|
||||
*
|
||||
* \param ctx The SHA-256 context. This must be initialized
|
||||
* and have a hash operation started.
|
||||
* \param input The buffer holding the data. This must be a readable
|
||||
* buffer of length \p ilen Bytes.
|
||||
* \param ilen The length of the input data in Bytes.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return A negative error code on failure.
|
||||
*/
|
||||
int mbedtls_sha256_update_ret(mbedtls_sha256_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief This function finishes the SHA-256 operation, and writes
|
||||
* the result to the output buffer.
|
||||
*
|
||||
* \param ctx The SHA-256 context. This must be initialized
|
||||
* and have a hash operation started.
|
||||
* \param output The SHA-224 or SHA-256 checksum result.
|
||||
* This must be a writable buffer of length \c 32 Bytes.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return A negative error code on failure.
|
||||
*/
|
||||
int mbedtls_sha256_finish_ret(mbedtls_sha256_context* ctx,
|
||||
unsigned char output[32]);
|
||||
|
||||
/**
|
||||
* \brief This function processes a single data block within
|
||||
* the ongoing SHA-256 computation. This function is for
|
||||
* internal use only.
|
||||
*
|
||||
* \param ctx The SHA-256 context. This must be initialized.
|
||||
* \param data The buffer holding one block of data. This must
|
||||
* be a readable buffer of length \c 64 Bytes.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return A negative error code on failure.
|
||||
*/
|
||||
int mbedtls_internal_sha256_process(mbedtls_sha256_context* ctx,
|
||||
const unsigned char data[64]);
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
#if defined(MBEDTLS_DEPRECATED_WARNING)
|
||||
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define MBEDTLS_DEPRECATED
|
||||
#endif
|
||||
/**
|
||||
* \brief This function starts a SHA-224 or SHA-256 checksum
|
||||
* calculation.
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0.
|
||||
*
|
||||
* \param ctx The context to use. This must be initialized.
|
||||
* \param is224 Determines which function to use. This must be
|
||||
* either \c 0 for SHA-256, or \c 1 for SHA-224.
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_sha256_starts(mbedtls_sha256_context* ctx,
|
||||
int is224);
|
||||
|
||||
/**
|
||||
* \brief This function feeds an input buffer into an ongoing
|
||||
* SHA-256 checksum calculation.
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0.
|
||||
*
|
||||
* \param ctx The SHA-256 context to use. This must be
|
||||
* initialized and have a hash operation started.
|
||||
* \param input The buffer holding the data. This must be a readable
|
||||
* buffer of length \p ilen Bytes.
|
||||
* \param ilen The length of the input data in Bytes.
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_sha256_update(mbedtls_sha256_context* ctx,
|
||||
const unsigned char* input,
|
||||
size_t ilen);
|
||||
|
||||
/**
|
||||
* \brief This function finishes the SHA-256 operation, and writes
|
||||
* the result to the output buffer.
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0.
|
||||
*
|
||||
* \param ctx The SHA-256 context. This must be initialized and
|
||||
* have a hash operation started.
|
||||
* \param output The SHA-224 or SHA-256 checksum result. This must be
|
||||
* a writable buffer of length \c 32 Bytes.
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_sha256_finish(mbedtls_sha256_context* ctx,
|
||||
unsigned char output[32]);
|
||||
|
||||
/**
|
||||
* \brief This function processes a single data block within
|
||||
* the ongoing SHA-256 computation. This function is for
|
||||
* internal use only.
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0.
|
||||
*
|
||||
* \param ctx The SHA-256 context. This must be initialized.
|
||||
* \param data The buffer holding one block of data. This must be
|
||||
* a readable buffer of size \c 64 Bytes.
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_sha256_process(mbedtls_sha256_context* ctx,
|
||||
const unsigned char data[64]);
|
||||
|
||||
#undef MBEDTLS_DEPRECATED
|
||||
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
/**
|
||||
* \brief This function calculates the SHA-224 or SHA-256
|
||||
* checksum of a buffer.
|
||||
*
|
||||
* The function allocates the context, performs the
|
||||
* calculation, and frees the context.
|
||||
*
|
||||
* The SHA-256 result is calculated as
|
||||
* output = SHA-256(input buffer).
|
||||
*
|
||||
* \param input The buffer holding the data. This must be a readable
|
||||
* buffer of length \p ilen Bytes.
|
||||
* \param ilen The length of the input data in Bytes.
|
||||
* \param output The SHA-224 or SHA-256 checksum result. This must
|
||||
* be a writable buffer of length \c 32 Bytes.
|
||||
* \param is224 Determines which function to use. This must be
|
||||
* either \c 0 for SHA-256, or \c 1 for SHA-224.
|
||||
*/
|
||||
int mbedtls_sha256_ret(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[32],
|
||||
int is224);
|
||||
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
#if defined(MBEDTLS_DEPRECATED_WARNING)
|
||||
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define MBEDTLS_DEPRECATED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief This function calculates the SHA-224 or SHA-256 checksum
|
||||
* of a buffer.
|
||||
*
|
||||
* The function allocates the context, performs the
|
||||
* calculation, and frees the context.
|
||||
*
|
||||
* The SHA-256 result is calculated as
|
||||
* output = SHA-256(input buffer).
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0.
|
||||
*
|
||||
* \param input The buffer holding the data. This must be a readable
|
||||
* buffer of length \p ilen Bytes.
|
||||
* \param ilen The length of the input data in Bytes.
|
||||
* \param output The SHA-224 or SHA-256 checksum result. This must be
|
||||
* a writable buffer of length \c 32 Bytes.
|
||||
* \param is224 Determines which function to use. This must be either
|
||||
* \c 0 for SHA-256, or \c 1 for SHA-224.
|
||||
*/
|
||||
MBEDTLS_DEPRECATED void mbedtls_sha256(const unsigned char* input,
|
||||
size_t ilen,
|
||||
unsigned char output[32],
|
||||
int is224);
|
||||
|
||||
#undef MBEDTLS_DEPRECATED
|
||||
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* mbedtls_sha256.h */
|
||||
926
rpcs3/Crypto/unedat.cpp
Normal file
926
rpcs3/Crypto/unedat.cpp
Normal file
|
|
@ -0,0 +1,926 @@
|
|||
#include "stdafx.h"
|
||||
#include "key_vault.h"
|
||||
#include "unedat.h"
|
||||
#include "sha1.h"
|
||||
#include "lz.h"
|
||||
#include "ec.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "Emu/system_utils.hpp"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
#include <algorithm>
|
||||
#include <span>
|
||||
|
||||
LOG_CHANNEL(edat_log, "EDAT");
|
||||
|
||||
void generate_key(int crypto_mode, int version, unsigned char* key_final, unsigned char* iv_final, unsigned char* key, unsigned char* iv)
|
||||
{
|
||||
int mode = crypto_mode & 0xF0000000;
|
||||
uchar temp_iv[16]{};
|
||||
switch (mode)
|
||||
{
|
||||
case 0x10000000:
|
||||
// Encrypted ERK.
|
||||
// Decrypt the key with EDAT_KEY + EDAT_IV and copy the original IV.
|
||||
memcpy(temp_iv, EDAT_IV, 0x10);
|
||||
aescbc128_decrypt(const_cast<u8*>(version ? EDAT_KEY_1 : EDAT_KEY_0), temp_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 = hash_mode & 0xF0000000;
|
||||
uchar temp_iv[16]{};
|
||||
switch (mode)
|
||||
{
|
||||
case 0x10000000:
|
||||
// Encrypted HASH.
|
||||
// Decrypt the hash with EDAT_KEY + EDAT_IV.
|
||||
memcpy(temp_iv, EDAT_IV, 0x10);
|
||||
aescbc128_decrypt(const_cast<u8*>(version ? EDAT_KEY_1 : EDAT_KEY_0), temp_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 decrypt(int hash_mode, int crypto_mode, int version, unsigned char* in, unsigned char* out, usz length, 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, length);
|
||||
}
|
||||
else if ((crypto_mode & 0xFF) == 0x02) // AES128-CBC
|
||||
{
|
||||
aescbc128_decrypt(key_final, iv_final, in, out, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
edat_log.error("Unknown crypto algorithm!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((hash_mode & 0xFF) == 0x01) // 0x14 SHA1-HMAC
|
||||
{
|
||||
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash, 0x14);
|
||||
}
|
||||
else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC
|
||||
{
|
||||
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
|
||||
}
|
||||
else if ((hash_mode & 0xFF) == 0x04) // 0x10 SHA1-HMAC
|
||||
{
|
||||
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
|
||||
}
|
||||
else
|
||||
{
|
||||
edat_log.error("Unknown hashing algorithm!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// EDAT/SDAT functions.
|
||||
std::tuple<u64, s32, s32> dec_section(unsigned char* metadata)
|
||||
{
|
||||
std::array<u8, 0x10> dec;
|
||||
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]);
|
||||
|
||||
u64 offset = read_from_ptr<be_t<u64>>(dec, 0);
|
||||
s32 length = read_from_ptr<be_t<s32>>(dec, 8);
|
||||
s32 compression_end = read_from_ptr<be_t<s32>>(dec, 12);
|
||||
|
||||
return std::make_tuple(offset, length, compression_end);
|
||||
}
|
||||
|
||||
u128 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;
|
||||
u128 dest_key{};
|
||||
std::memcpy(&dest_key, src_key, 0xC);
|
||||
|
||||
s32 swappedBlock = std::bit_cast<be_t<s32>>(block);
|
||||
std::memcpy(reinterpret_cast<uchar*>(&dest_key) + 0xC, &swappedBlock, sizeof(swappedBlock));
|
||||
return dest_key;
|
||||
}
|
||||
|
||||
// for out data, allocate a buffer the size of 'edat->block_size'
|
||||
// Also, set 'in file' to the beginning of the encrypted data, which may be offset if inside another file, but normally just reset to beginning of file
|
||||
// returns number of bytes written, -1 for error
|
||||
s64 decrypt_block(const fs::file* in, u8* out, EDAT_HEADER* edat, NPD_HEADER* npd, u8* crypt_key, u32 block_num, u32 total_blocks, u64 size_left, bool is_out_buffer_aligned = false)
|
||||
{
|
||||
// Get metadata info and setup buffers.
|
||||
const int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
|
||||
const int metadata_offset = 0x100;
|
||||
|
||||
u8 hash[0x10] = {0};
|
||||
u8 key_result[0x10] = {0};
|
||||
u8 hash_result[0x14] = {0};
|
||||
|
||||
u64 offset = 0;
|
||||
u64 metadata_sec_offset = 0;
|
||||
u64 length = 0;
|
||||
s32 compression_end = 0;
|
||||
unsigned char empty_iv[0x10] = {};
|
||||
|
||||
// Decrypt the metadata.
|
||||
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0)
|
||||
{
|
||||
metadata_sec_offset = metadata_offset + u64{block_num} * metadata_section_size;
|
||||
|
||||
u8 metadata[0x20]{};
|
||||
|
||||
in->read_at(metadata_sec_offset, metadata, 0x20);
|
||||
|
||||
// If the data is compressed, decrypt the metadata.
|
||||
// NOTE: For NPD version 1 the metadata is not encrypted.
|
||||
if (npd->version <= 1)
|
||||
{
|
||||
offset = read_from_ptr<be_t<u64>>(metadata, 0x10);
|
||||
length = read_from_ptr<be_t<s32>>(metadata, 0x18);
|
||||
compression_end = read_from_ptr<be_t<s32>>(metadata, 0x1C);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::tie(offset, length, compression_end) = dec_section(metadata);
|
||||
}
|
||||
|
||||
std::memcpy(hash_result, metadata, 0x10);
|
||||
}
|
||||
else if ((edat->flags & EDAT_FLAG_0x20) != 0)
|
||||
{
|
||||
// If FLAG 0x20, the metadata precedes each data block.
|
||||
metadata_sec_offset = metadata_offset + u64{block_num} * (metadata_section_size + edat->block_size);
|
||||
|
||||
u8 metadata[0x20]{};
|
||||
in->read_at(metadata_sec_offset, metadata, 0x20);
|
||||
|
||||
std::memcpy(hash_result, metadata, 0x14);
|
||||
|
||||
// If FLAG 0x20 is set, apply custom xor.
|
||||
for (int j = 0; j < 0x10; j++)
|
||||
hash_result[j] = metadata[j] ^ metadata[j + 0x10];
|
||||
|
||||
offset = metadata_sec_offset + 0x20;
|
||||
length = edat->block_size;
|
||||
|
||||
if ((block_num == (total_blocks - 1)) && (edat->file_size % edat->block_size))
|
||||
length = static_cast<s32>(edat->file_size % edat->block_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
metadata_sec_offset = metadata_offset + u64{block_num} * metadata_section_size;
|
||||
|
||||
in->read_at(metadata_sec_offset, hash_result, 0x10);
|
||||
|
||||
offset = metadata_offset + u64{block_num} * edat->block_size + total_blocks * metadata_section_size;
|
||||
length = edat->block_size;
|
||||
|
||||
if ((block_num == (total_blocks - 1)) && (edat->file_size % edat->block_size))
|
||||
length = static_cast<s32>(edat->file_size % edat->block_size);
|
||||
}
|
||||
|
||||
// Locate the real data.
|
||||
const usz pad_length = length;
|
||||
length = utils::align<usz>(pad_length, 0x10);
|
||||
|
||||
// Setup buffers for decryption and read the data.
|
||||
std::vector<u8> enc_data_buf(is_out_buffer_aligned || length == pad_length ? 0 : length);
|
||||
std::vector<u8> dec_data_buf(length);
|
||||
|
||||
// Try to use out buffer for file reads if no padding is needed instead of a new buffer
|
||||
u8* enc_data = enc_data_buf.empty() ? out : enc_data_buf.data();
|
||||
|
||||
// Variable to avoid copies when possible
|
||||
u8* dec_data = dec_data_buf.data();
|
||||
|
||||
std::memset(hash, 0, 0x10);
|
||||
std::memset(key_result, 0, 0x10);
|
||||
|
||||
in->read_at(offset, enc_data, length);
|
||||
|
||||
// Generate a key for the current block.
|
||||
auto b_key = get_block_key(block_num, npd);
|
||||
|
||||
// Encrypt the block key with the crypto key.
|
||||
aesecb128_encrypt(crypt_key, reinterpret_cast<uchar*>(&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
|
||||
{
|
||||
std::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;
|
||||
}
|
||||
|
||||
const bool should_decompress = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0) && compression_end;
|
||||
|
||||
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.
|
||||
if (should_decompress)
|
||||
{
|
||||
std::memcpy(dec_data, enc_data, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optimize when decompression is not needed by avoiding 2 copies
|
||||
dec_data = enc_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// IV is null if NPD version is 1 or 0.
|
||||
u8* iv = (npd->version <= 1) ? empty_iv : npd->digest;
|
||||
|
||||
// Call main crypto routine on this data block.
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result))
|
||||
{
|
||||
edat_log.error("Block at offset 0x%llx has invalid hash!", offset);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply additional de-compression if needed and write the decrypted data.
|
||||
if (should_decompress)
|
||||
{
|
||||
const int res = decompress(out, dec_data, edat->block_size);
|
||||
|
||||
size_left -= res;
|
||||
|
||||
if (size_left == 0)
|
||||
{
|
||||
if (res < 0)
|
||||
{
|
||||
edat_log.error("Decompression failed!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (dec_data != out)
|
||||
{
|
||||
std::memcpy(out, dec_data, pad_length);
|
||||
}
|
||||
|
||||
return pad_length;
|
||||
}
|
||||
|
||||
// set file offset to beginning before calling
|
||||
bool check_data(u8* key, EDAT_HEADER* edat, NPD_HEADER* npd, const fs::file* f, bool verbose)
|
||||
{
|
||||
u8 header[0xA0] = {0};
|
||||
u8 empty_header[0xA0] = {0};
|
||||
u8 header_hash[0x10] = {0};
|
||||
u8 metadata_hash[0x10] = {0};
|
||||
|
||||
const u64 file_offset = f->pos();
|
||||
|
||||
// Check NPD version and flags.
|
||||
if ((npd->version == 0) || (npd->version == 1))
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFFE)
|
||||
{
|
||||
edat_log.error("Bad header flags!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (npd->version == 2)
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFE0)
|
||||
{
|
||||
edat_log.error("Bad header flags!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ((npd->version == 3) || (npd->version == 4))
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFC0)
|
||||
{
|
||||
edat_log.error("Bad header flags!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edat_log.error("Unknown version!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read in the file header.
|
||||
f->read(header, 0xA0);
|
||||
|
||||
// Read in the header and metadata section hashes.
|
||||
f->seek(file_offset + 0x90);
|
||||
f->read(metadata_hash, 0x10);
|
||||
f->read(header_hash, 0x10);
|
||||
|
||||
// Setup the hashing mode and the crypto mode used in the file.
|
||||
const int crypto_mode = 0x1;
|
||||
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
|
||||
{
|
||||
hash_mode |= 0x01000000;
|
||||
|
||||
if (verbose)
|
||||
edat_log.warning("DEBUG data detected!");
|
||||
}
|
||||
|
||||
// Setup header key and iv buffers.
|
||||
unsigned char header_key[0x10] = {0};
|
||||
unsigned char header_iv[0x10] = {0};
|
||||
|
||||
// Test the header hash (located at offset 0xA0).
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), header, empty_header, 0xA0, header_key, header_iv, key, header_hash))
|
||||
{
|
||||
if (verbose)
|
||||
edat_log.warning("Header hash is invalid!");
|
||||
|
||||
// If the header hash test fails and the data is not DEBUG, then RAP/RIF/KLIC key is invalid.
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
|
||||
{
|
||||
edat_log.error("RAP/RIF/KLIC key is invalid!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the metadata info.
|
||||
const int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
|
||||
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
|
||||
{
|
||||
if (verbose)
|
||||
edat_log.warning("COMPRESSED data detected!");
|
||||
}
|
||||
|
||||
if (!edat->block_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const usz block_num = utils::aligned_div<u64>(edat->file_size, edat->block_size);
|
||||
constexpr usz metadata_offset = 0x100;
|
||||
const usz metadata_size = utils::mul_saturate<u64>(metadata_section_size, block_num);
|
||||
u64 metadata_section_offset = metadata_offset;
|
||||
|
||||
if (utils::add_saturate<u64>(utils::add_saturate<u64>(file_offset, metadata_section_offset), metadata_size) > f->size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 bytes_read = 0;
|
||||
const auto metadata = std::make_unique<u8[]>(metadata_size);
|
||||
const auto empty_metadata = std::make_unique<u8[]>(metadata_size);
|
||||
|
||||
while (bytes_read < metadata_size)
|
||||
{
|
||||
// Locate the metadata blocks.
|
||||
const usz offset = file_offset + metadata_section_offset;
|
||||
|
||||
// Read in the metadata.
|
||||
f->read_at(offset, metadata.get() + bytes_read, metadata_section_size);
|
||||
|
||||
// Adjust sizes.
|
||||
bytes_read += metadata_section_size;
|
||||
|
||||
if (((edat->flags & EDAT_FLAG_0x20) != 0)) // Metadata block before each data block.
|
||||
metadata_section_offset += (metadata_section_size + edat->block_size);
|
||||
else
|
||||
metadata_section_offset += metadata_section_size;
|
||||
}
|
||||
|
||||
// Test the metadata section hash (located at offset 0x90).
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), metadata.get(), empty_metadata.get(), metadata_size, header_key, header_iv, key, metadata_hash))
|
||||
{
|
||||
if (verbose)
|
||||
edat_log.warning("Metadata section hash is invalid!");
|
||||
}
|
||||
|
||||
// Checking ECDSA signatures.
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) == 0)
|
||||
{
|
||||
// Setup buffers.
|
||||
unsigned char metadata_signature[0x28] = {0};
|
||||
unsigned char header_signature[0x28] = {0};
|
||||
unsigned char signature_hash[20] = {0};
|
||||
unsigned char signature_r[0x15] = {0};
|
||||
unsigned char signature_s[0x15] = {0};
|
||||
unsigned char zero_buf[0x15] = {0};
|
||||
|
||||
// Setup ECDSA curve and public key.
|
||||
ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY);
|
||||
ecdsa_set_pub(VSH_PUB);
|
||||
|
||||
// Read in the metadata and header signatures.
|
||||
f->seek(0xB0);
|
||||
f->read(metadata_signature, 0x28);
|
||||
f->read(header_signature, 0x28);
|
||||
|
||||
// Checking metadata signature.
|
||||
// Setup signature r and s.
|
||||
signature_r[0] = 0;
|
||||
signature_s[0] = 0;
|
||||
std::memcpy(signature_r + 1, metadata_signature, 0x14);
|
||||
std::memcpy(signature_s + 1, metadata_signature + 0x14, 0x14);
|
||||
if ((!std::memcmp(signature_r, zero_buf, 0x15)) || (!std::memcmp(signature_s, zero_buf, 0x15)))
|
||||
{
|
||||
edat_log.warning("Metadata signature is invalid!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Setup signature hash.
|
||||
if ((edat->flags & EDAT_FLAG_0x20) != 0) // Sony failed again, they used buffer from 0x100 with half size of real metadata.
|
||||
{
|
||||
const usz metadata_buf_size = block_num * 0x10;
|
||||
|
||||
std::vector<u8> metadata_buf(metadata_buf_size);
|
||||
|
||||
f->read_at(file_offset + metadata_offset, metadata_buf.data(), metadata_buf_size);
|
||||
|
||||
sha1(metadata_buf.data(), metadata_buf_size, signature_hash);
|
||||
}
|
||||
else
|
||||
sha1(metadata.get(), metadata_size, signature_hash);
|
||||
|
||||
if (!ecdsa_verify(signature_hash, signature_r, signature_s))
|
||||
{
|
||||
edat_log.warning("Metadata signature is invalid!");
|
||||
if (((edat->block_size + 0ull) * block_num) > 0x100000000)
|
||||
edat_log.warning("*Due to large file size, metadata signature status may be incorrect!");
|
||||
}
|
||||
}
|
||||
|
||||
// Checking header signature.
|
||||
// Setup header signature r and s.
|
||||
signature_r[0] = 0;
|
||||
signature_s[0] = 0;
|
||||
std::memcpy(signature_r + 1, header_signature, 0x14);
|
||||
std::memcpy(signature_s + 1, header_signature + 0x14, 0x14);
|
||||
|
||||
if ((!std::memcmp(signature_r, zero_buf, 0x15)) || (!std::memcmp(signature_s, zero_buf, 0x15)))
|
||||
{
|
||||
edat_log.warning("Header signature is invalid!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Setup header signature hash.
|
||||
std::memset(signature_hash, 0, 20);
|
||||
|
||||
u8 header_buf[0xD8]{};
|
||||
|
||||
f->read_at(file_offset, header_buf, 0xD8);
|
||||
sha1(header_buf, 0xD8, signature_hash);
|
||||
|
||||
if (!ecdsa_verify(signature_hash, signature_r, signature_s))
|
||||
edat_log.warning("Header signature is invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_dev_klic(const u8* klicensee, NPD_HEADER* npd)
|
||||
{
|
||||
if ((npd->license & 0x3) != 0x3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char dev[0x60]{};
|
||||
|
||||
// Build the dev buffer (first 0x60 bytes of NPD header in big-endian).
|
||||
std::memcpy(dev, npd, 0x60);
|
||||
|
||||
// Fix endianness.
|
||||
s32 version = std::bit_cast<be_t<s32>>(npd->version);
|
||||
s32 license = std::bit_cast<be_t<s32>>(npd->license);
|
||||
s32 type = std::bit_cast<be_t<s32>>(npd->type);
|
||||
std::memcpy(dev + 0x4, &version, 4);
|
||||
std::memcpy(dev + 0x8, &license, 4);
|
||||
std::memcpy(dev + 0xC, &type, 4);
|
||||
|
||||
// Check for an empty dev_hash (can't validate if devklic is NULL);
|
||||
u128 klic;
|
||||
std::memcpy(&klic, klicensee, sizeof(klic));
|
||||
|
||||
// Generate klicensee xor key.
|
||||
u128 key = klic ^ std::bit_cast<u128>(NP_OMAC_KEY_2);
|
||||
|
||||
// Hash with generated key and compare with dev_hash.
|
||||
return cmac_hash_compare(reinterpret_cast<uchar*>(&key), 0x10, dev, 0x60, npd->dev_hash, 0x10);
|
||||
}
|
||||
|
||||
bool validate_npd_hashes(std::string_view file_name, const u8* klicensee, NPD_HEADER* npd, EDAT_HEADER* edat, bool verbose)
|
||||
{
|
||||
// Ignore header validation in DEBUG data.
|
||||
if (edat->flags & EDAT_DEBUG_DATA_FLAG)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!validate_dev_klic(klicensee, npd))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file_name.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const usz buf_len = 0x30 + file_name.size();
|
||||
|
||||
std::unique_ptr<u8[]> buf(new u8[buf_len]);
|
||||
std::unique_ptr<u8[]> buf_lower(new u8[buf_len]);
|
||||
std::unique_ptr<u8[]> buf_upper(new u8[buf_len]);
|
||||
|
||||
// Build the title buffer (content_id + file_name).
|
||||
std::memcpy(buf.get(), npd->content_id, 0x30);
|
||||
std::memcpy(buf.get() + 0x30, file_name.data(), file_name.size());
|
||||
|
||||
std::memcpy(buf_lower.get(), buf.get(), buf_len);
|
||||
std::memcpy(buf_upper.get(), buf.get(), buf_len);
|
||||
|
||||
const auto buf_span = std::span(buf.get(), buf.get() + buf_len);
|
||||
const auto it = std::find(buf_span.rbegin(), buf_span.rend() - 0x30, '.');
|
||||
for (usz i = std::distance(it, buf_span.rend()) - 1; i < buf_len; ++i)
|
||||
{
|
||||
const u8 c = buf[i];
|
||||
buf_upper[i] = std::toupper(c);
|
||||
buf_lower[i] = std::tolower(c);
|
||||
}
|
||||
|
||||
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
|
||||
// Try to ignore case sensivity with file extension
|
||||
const bool title_hash_result =
|
||||
cmac_hash_compare(const_cast<u8*>(NP_OMAC_KEY_3), 0x10, buf.get(), buf_len, npd->title_hash, 0x10) ||
|
||||
cmac_hash_compare(const_cast<u8*>(NP_OMAC_KEY_3), 0x10, buf_lower.get(), buf_len, npd->title_hash, 0x10) ||
|
||||
cmac_hash_compare(const_cast<u8*>(NP_OMAC_KEY_3), 0x10, buf_upper.get(), buf_len, npd->title_hash, 0x10);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (title_hash_result)
|
||||
edat_log.notice("NPD title hash is valid!");
|
||||
else
|
||||
edat_log.warning("NPD title hash is invalid!");
|
||||
}
|
||||
|
||||
return title_hash_result;
|
||||
}
|
||||
|
||||
void read_npd_edat_header(const fs::file* input, NPD_HEADER& NPD, EDAT_HEADER& EDAT)
|
||||
{
|
||||
char npd_header[0x80]{};
|
||||
char edat_header[0x10]{};
|
||||
|
||||
usz pos = input->pos();
|
||||
pos += input->read_at(pos, npd_header, sizeof(npd_header));
|
||||
input->read_at(pos, edat_header, sizeof(edat_header));
|
||||
|
||||
std::memcpy(&NPD.magic, npd_header, 4);
|
||||
NPD.version = read_from_ptr<be_t<s32>>(npd_header, 4);
|
||||
NPD.license = read_from_ptr<be_t<s32>>(npd_header, 8);
|
||||
NPD.type = read_from_ptr<be_t<s32>>(npd_header, 12);
|
||||
std::memcpy(NPD.content_id, &npd_header[16], 0x30);
|
||||
std::memcpy(NPD.digest, &npd_header[64], 0x10);
|
||||
std::memcpy(NPD.title_hash, &npd_header[80], 0x10);
|
||||
std::memcpy(NPD.dev_hash, &npd_header[96], 0x10);
|
||||
NPD.activate_time = read_from_ptr<be_t<s64>>(npd_header, 112);
|
||||
NPD.expire_time = read_from_ptr<be_t<s64>>(npd_header, 120);
|
||||
|
||||
EDAT.flags = read_from_ptr<be_t<s32>>(edat_header, 0);
|
||||
EDAT.block_size = read_from_ptr<be_t<s32>>(edat_header, 4);
|
||||
EDAT.file_size = read_from_ptr<be_t<u64>>(edat_header, 8);
|
||||
}
|
||||
|
||||
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file)
|
||||
{
|
||||
u128 rapkey{};
|
||||
u128 rifkey{};
|
||||
|
||||
rap_file.read<u128>(rapkey);
|
||||
|
||||
rap_to_rif(reinterpret_cast<const uchar*>(&rapkey), reinterpret_cast<uchar*>(&rifkey));
|
||||
|
||||
return rifkey;
|
||||
}
|
||||
|
||||
bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, NPD_HEADER* npd_out)
|
||||
{
|
||||
// Setup NPD and EDAT/SDAT structs.
|
||||
NPD_HEADER NPD;
|
||||
EDAT_HEADER EDAT;
|
||||
|
||||
// Read in the NPD and EDAT/SDAT headers.
|
||||
read_npd_edat_header(&input, NPD, EDAT);
|
||||
|
||||
if (NPD.magic != "NPD\0"_u32)
|
||||
{
|
||||
edat_log.error("%s has invalid NPD header or already decrypted.", input_file_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((EDAT.flags & SDAT_FLAG) == SDAT_FLAG)
|
||||
{
|
||||
edat_log.error("SDATA file given to edat function");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform header validation (EDAT only).
|
||||
char real_file_name[CRYPTO_MAX_PATH]{};
|
||||
extract_file_name(input_file_name.c_str(), real_file_name);
|
||||
if (!validate_npd_hashes(real_file_name, custom_klic, &NPD, &EDAT, false))
|
||||
{
|
||||
edat_log.error("NPD hash validation failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (npd_out)
|
||||
{
|
||||
*npd_out = NPD;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decrypts full file
|
||||
fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8* custom_klic)
|
||||
{
|
||||
if (!input)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// Prepare the files.
|
||||
input.seek(0);
|
||||
|
||||
// Set DEVKLIC
|
||||
u128 devklic{};
|
||||
|
||||
// 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
|
||||
{
|
||||
edat_log.error("Invalid custom klic!");
|
||||
return fs::file{};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
edat_log.error("Invalid mode!");
|
||||
return fs::file{};
|
||||
}
|
||||
|
||||
// Delete the bad output file if any errors arise.
|
||||
auto data = std::make_unique<EDATADecrypter>(input, devklic, input_file_name, false);
|
||||
|
||||
if (!data->ReadHeader())
|
||||
{
|
||||
return fs::file{};
|
||||
}
|
||||
|
||||
fs::file output;
|
||||
output.reset(std::move(data));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool EDATADecrypter::ReadHeader()
|
||||
{
|
||||
edata_file.seek(0);
|
||||
|
||||
// Read in the NPD and EDAT/SDAT headers.
|
||||
read_npd_edat_header(&edata_file, npdHeader, edatHeader);
|
||||
|
||||
if (npdHeader.magic != "NPD\0"_u32)
|
||||
{
|
||||
edat_log.error("Not an NPDRM file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for SDAT flag.
|
||||
if ((edatHeader.flags & SDAT_FLAG) == SDAT_FLAG)
|
||||
{
|
||||
// Generate SDAT key.
|
||||
dec_key = std::bit_cast<u128>(npdHeader.dev_hash) ^ std::bit_cast<u128>(SDAT_KEY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// extract key from RIF
|
||||
char real_file_name[CRYPTO_MAX_PATH]{};
|
||||
extract_file_name(m_file_name.c_str(), real_file_name);
|
||||
|
||||
if (!validate_npd_hashes(real_file_name, reinterpret_cast<const u8*>(&dec_key), &npdHeader, &edatHeader, false))
|
||||
{
|
||||
edat_log.error("NPD hash validation failed!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Select EDAT key.
|
||||
if (m_is_key_final)
|
||||
{
|
||||
// Already provided
|
||||
}
|
||||
// Type 3: Use supplied dec_key.
|
||||
else if ((npdHeader.license & 0x3) == 0x3)
|
||||
{
|
||||
//
|
||||
}
|
||||
// Type 2: Use key from RAP file (RIF key). (also used for type 1 at the moment)
|
||||
else
|
||||
{
|
||||
const std::string rap_path = rpcs3::utils::get_rap_file_path(npdHeader.content_id);
|
||||
|
||||
if (fs::file rap{rap_path}; rap && rap.size() >= sizeof(dec_key))
|
||||
{
|
||||
dec_key = GetEdatRifKeyFromRapFile(rap);
|
||||
}
|
||||
|
||||
// Make sure we don't have an empty RIF key.
|
||||
if (!dec_key)
|
||||
{
|
||||
edat_log.error("A valid RAP file is needed for this EDAT file! (license=%d)", npdHeader.license);
|
||||
return true;
|
||||
}
|
||||
|
||||
edat_log.trace("RIFKEY: %s", std::bit_cast<be_t<u128>>(dec_key));
|
||||
}
|
||||
}
|
||||
|
||||
edata_file.seek(0);
|
||||
|
||||
// k the ecdsa_verify function in this check_data function takes a ridiculous amount of time
|
||||
// like it slows down load time by a factor of x20, at least, so its ignored for now
|
||||
// if (!check_data(reinterpret_cast<u8*>(&dec_key), &edatHeader, &npdHeader, &edata_file, false))
|
||||
//{
|
||||
// edat_log.error("NPDRM check_data() failed!");
|
||||
// return false;
|
||||
//}
|
||||
|
||||
file_size = edatHeader.file_size;
|
||||
total_blocks = ::narrow<u32>(utils::aligned_div(edatHeader.file_size, edatHeader.block_size));
|
||||
|
||||
// Try decrypting the first block instead
|
||||
u8 data_sample[1];
|
||||
|
||||
if (file_size && !ReadData(0, data_sample, 1))
|
||||
{
|
||||
edat_log.error("NPDRM ReadData() failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 EDATADecrypter::ReadData(u64 pos, u8* data, u64 size)
|
||||
{
|
||||
size = std::min<u64>(size, pos > edatHeader.file_size ? 0 : edatHeader.file_size - pos);
|
||||
|
||||
if (!size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now we need to offset things to account for the actual 'range' requested
|
||||
const u64 startOffset = pos % edatHeader.block_size;
|
||||
|
||||
const u64 num_blocks = utils::aligned_div(startOffset + size, edatHeader.block_size);
|
||||
|
||||
// Find and decrypt block range covering pos + size
|
||||
const u32 starting_block = ::narrow<u32>(pos / edatHeader.block_size);
|
||||
const u32 ending_block = ::narrow<u32>(std::min<u64>(starting_block + num_blocks, total_blocks));
|
||||
|
||||
u64 writeOffset = 0;
|
||||
|
||||
std::vector<u8> data_buf(edatHeader.block_size + 16);
|
||||
|
||||
for (u32 i = starting_block; i < ending_block; i++)
|
||||
{
|
||||
u64 res = decrypt_block(&edata_file, data_buf.data(), &edatHeader, &npdHeader, reinterpret_cast<uchar*>(&dec_key), i, total_blocks, edatHeader.file_size, true);
|
||||
|
||||
if (res == umax)
|
||||
{
|
||||
edat_log.error("Error Decrypting data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const usz skip_start = (i == starting_block ? startOffset : 0);
|
||||
|
||||
if (skip_start >= res)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const usz end_pos = (i != total_blocks - 1 ? edatHeader.block_size : (edatHeader.file_size - 1) % edatHeader.block_size + 1);
|
||||
const usz read_end = std::min<usz>(res, i == ending_block - 1 ? std::min<usz>(end_pos, (startOffset + size - 1) % edatHeader.block_size + 1) : end_pos);
|
||||
|
||||
std::memcpy(data + writeOffset, data_buf.data() + skip_start, read_end - skip_start);
|
||||
std::memset(data_buf.data(), 0, read_end - skip_start);
|
||||
|
||||
writeOffset += read_end - skip_start;
|
||||
}
|
||||
|
||||
return writeOffset;
|
||||
}
|
||||
167
rpcs3/Crypto/unedat.h
Normal file
167
rpcs3/Crypto/unedat.h
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "util/File.h"
|
||||
|
||||
constexpr u32 SDAT_FLAG = 0x01000000;
|
||||
constexpr u32 EDAT_COMPRESSED_FLAG = 0x00000001;
|
||||
constexpr u32 EDAT_FLAG_0x02 = 0x00000002;
|
||||
constexpr u32 EDAT_ENCRYPTED_KEY_FLAG = 0x00000008;
|
||||
constexpr u32 EDAT_FLAG_0x10 = 0x00000010;
|
||||
constexpr u32 EDAT_FLAG_0x20 = 0x00000020;
|
||||
constexpr u32 EDAT_DEBUG_DATA_FLAG = 0x80000000;
|
||||
|
||||
struct loaded_npdrm_keys
|
||||
{
|
||||
atomic_t<u128> dec_keys[16]{};
|
||||
atomic_t<u64> dec_keys_pos = 0;
|
||||
u128 one_time_key{}; // For savestates
|
||||
atomic_t<u32> npdrm_fds{0};
|
||||
|
||||
void install_decryption_key(u128 key)
|
||||
{
|
||||
dec_keys_pos.atomic_op([&](u64& pos)
|
||||
{
|
||||
dec_keys[pos++ % std::size(dec_keys)] = key;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Check if correct for ELF files usage
|
||||
u128 last_key(usz backwards = 0) const
|
||||
{
|
||||
backwards++;
|
||||
const usz pos = dec_keys_pos;
|
||||
return pos >= backwards ? dec_keys[(pos - backwards) % std::size(dec_keys)].load() : u128{};
|
||||
}
|
||||
|
||||
SAVESTATE_INIT_POS(2);
|
||||
loaded_npdrm_keys() = default;
|
||||
loaded_npdrm_keys(utils::serial& ar);
|
||||
void save(utils::serial& ar);
|
||||
};
|
||||
|
||||
struct NPD_HEADER
|
||||
{
|
||||
u32 magic;
|
||||
s32 version;
|
||||
s32 license;
|
||||
s32 type;
|
||||
char content_id[0x30];
|
||||
u8 digest[0x10];
|
||||
u8 title_hash[0x10];
|
||||
u8 dev_hash[0x10];
|
||||
s64 activate_time;
|
||||
s64 expire_time;
|
||||
};
|
||||
|
||||
struct EDAT_HEADER
|
||||
{
|
||||
s32 flags;
|
||||
s32 block_size;
|
||||
u64 file_size;
|
||||
};
|
||||
|
||||
// Decrypts full file, or null/empty file
|
||||
extern fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8* custom_klic);
|
||||
|
||||
extern void read_npd_edat_header(const fs::file* input, NPD_HEADER& NPD, EDAT_HEADER& EDAT);
|
||||
extern bool VerifyEDATHeaderWithKLicense(const fs::file& input, const std::string& input_file_name, const u8* custom_klic, NPD_HEADER* npd_out = nullptr);
|
||||
|
||||
u128 GetEdatRifKeyFromRapFile(const fs::file& rap_file);
|
||||
|
||||
struct EDATADecrypter final : fs::file_base
|
||||
{
|
||||
// file stream
|
||||
fs::file m_edata_file;
|
||||
const fs::file& edata_file;
|
||||
std::string m_file_name;
|
||||
bool m_is_key_final = true;
|
||||
u64 file_size{0};
|
||||
u32 total_blocks{0};
|
||||
u64 pos{0};
|
||||
|
||||
NPD_HEADER npdHeader{};
|
||||
EDAT_HEADER edatHeader{};
|
||||
|
||||
u128 dec_key{};
|
||||
|
||||
public:
|
||||
EDATADecrypter(fs::file&& input, u128 dec_key = {}, std::string file_name = {}, bool is_key_final = true) noexcept
|
||||
: m_edata_file(std::move(input)), edata_file(m_edata_file), m_file_name(std::move(file_name)), m_is_key_final(is_key_final), dec_key(dec_key)
|
||||
{
|
||||
}
|
||||
|
||||
EDATADecrypter(const fs::file& input, u128 dec_key = {}, std::string file_name = {}, bool is_key_final = true) noexcept
|
||||
: m_edata_file(fs::file{}), edata_file(input), m_file_name(std::move(file_name)), m_is_key_final(is_key_final), dec_key(dec_key)
|
||||
{
|
||||
}
|
||||
|
||||
// false if invalid
|
||||
bool ReadHeader();
|
||||
u64 ReadData(u64 pos, u8* data, u64 size);
|
||||
|
||||
fs::stat_t get_stat() override
|
||||
{
|
||||
fs::stat_t stats = edata_file.get_stat();
|
||||
stats.is_writable = false; // TODO
|
||||
stats.size = file_size;
|
||||
return stats;
|
||||
}
|
||||
|
||||
bool trunc(u64) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 read(void* buffer, u64 size) override
|
||||
{
|
||||
const u64 bytesRead = ReadData(pos, static_cast<u8*>(buffer), size);
|
||||
pos += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||
{
|
||||
return ReadData(offset, static_cast<u8*>(buffer), size);
|
||||
}
|
||||
|
||||
u64 write(const void*, u64) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 seek(s64 offset, fs::seek_mode whence) override
|
||||
{
|
||||
const s64 new_pos =
|
||||
whence == fs::seek_set ? offset :
|
||||
whence == fs::seek_cur ? offset + pos :
|
||||
whence == fs::seek_end ? offset + size() :
|
||||
-1;
|
||||
|
||||
if (new_pos < 0)
|
||||
{
|
||||
fs::g_tls_error = fs::error::inval;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = new_pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
u64 size() override
|
||||
{
|
||||
return file_size;
|
||||
}
|
||||
|
||||
fs::file_id get_id() override
|
||||
{
|
||||
fs::file_id id = edata_file.get_id();
|
||||
id.type.insert(0, "EDATADecrypter: "sv);
|
||||
return id;
|
||||
}
|
||||
|
||||
u128 get_key() const
|
||||
{
|
||||
return dec_key;
|
||||
}
|
||||
};
|
||||
1485
rpcs3/Crypto/unpkg.cpp
Normal file
1485
rpcs3/Crypto/unpkg.cpp
Normal file
File diff suppressed because it is too large
Load diff
413
rpcs3/Crypto/unpkg.h
Normal file
413
rpcs3/Crypto/unpkg.h
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
#pragma once
|
||||
|
||||
#include "Loader/PSF.h"
|
||||
#include "util/endian.hpp"
|
||||
#include "util/types.hpp"
|
||||
#include "util/File.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <span>
|
||||
#include <deque>
|
||||
|
||||
// Constants
|
||||
enum : u32
|
||||
{
|
||||
PKG_HEADER_SIZE = 0xC0, // sizeof(pkg_header) + sizeof(pkg_unk_checksum)
|
||||
PKG_HEADER_SIZE2 = 0x280,
|
||||
PKG_MAX_FILENAME_SIZE = 256,
|
||||
};
|
||||
|
||||
enum : u16
|
||||
{
|
||||
PKG_RELEASE_TYPE_RELEASE = 0x8000,
|
||||
PKG_RELEASE_TYPE_DEBUG = 0x0000,
|
||||
|
||||
PKG_PLATFORM_TYPE_PS3 = 0x0001,
|
||||
PKG_PLATFORM_TYPE_PSP_PSVITA = 0x0002,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
PKG_FILE_ENTRY_NPDRM = 1,
|
||||
PKG_FILE_ENTRY_NPDRMEDAT = 2,
|
||||
PKG_FILE_ENTRY_REGULAR = 3,
|
||||
PKG_FILE_ENTRY_FOLDER = 4,
|
||||
PKG_FILE_ENTRY_UNK0 = 5,
|
||||
PKG_FILE_ENTRY_UNK1 = 6,
|
||||
PKG_FILE_ENTRY_SDAT = 9,
|
||||
|
||||
PKG_FILE_ENTRY_OVERWRITE = 0x80000000,
|
||||
PKG_FILE_ENTRY_PSP = 0x10000000,
|
||||
|
||||
PKG_FILE_ENTRY_KNOWN_BITS = 0xff | PKG_FILE_ENTRY_PSP | PKG_FILE_ENTRY_OVERWRITE,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
PKG_CONTENT_TYPE_UNKNOWN_1 = 0x01, // ?
|
||||
PKG_CONTENT_TYPE_UNKNOWN_2 = 0x02, // ?
|
||||
PKG_CONTENT_TYPE_UNKNOWN_3 = 0x03, // ?
|
||||
PKG_CONTENT_TYPE_GAME_DATA = 0x04, // GameData (also patches)
|
||||
PKG_CONTENT_TYPE_GAME_EXEC = 0x05, // GameExec
|
||||
PKG_CONTENT_TYPE_PS1_EMU = 0x06, // PS1emu
|
||||
PKG_CONTENT_TYPE_PC_ENGINE = 0x07, // PSP & PCEngine
|
||||
PKG_CONTENT_TYPE_UNKNOWN_4 = 0x08, // ?
|
||||
PKG_CONTENT_TYPE_THEME = 0x09, // Theme
|
||||
PKG_CONTENT_TYPE_WIDGET = 0x0A, // Widget
|
||||
PKG_CONTENT_TYPE_LICENSE = 0x0B, // License
|
||||
PKG_CONTENT_TYPE_VSH_MODULE = 0x0C, // VSHModule
|
||||
PKG_CONTENT_TYPE_PSN_AVATAR = 0x0D, // PSN Avatar
|
||||
PKG_CONTENT_TYPE_PSP_GO = 0x0E, // PSPgo
|
||||
PKG_CONTENT_TYPE_MINIS = 0x0F, // Minis
|
||||
PKG_CONTENT_TYPE_NEOGEO = 0x10, // NEOGEO
|
||||
PKG_CONTENT_TYPE_VMC = 0x11, // VMC
|
||||
PKG_CONTENT_TYPE_PS2_CLASSIC = 0x12, // ?PS2Classic? Seen on PS2 classic
|
||||
PKG_CONTENT_TYPE_UNKNOWN_5 = 0x13, // ?
|
||||
PKG_CONTENT_TYPE_PSP_REMASTERED = 0x14, // ?
|
||||
PKG_CONTENT_TYPE_PSP2_GD = 0x15, // PSVita Game Data
|
||||
PKG_CONTENT_TYPE_PSP2_AC = 0x16, // PSVita Additional Content
|
||||
PKG_CONTENT_TYPE_PSP2_LA = 0x17, // PSVita LiveArea
|
||||
PKG_CONTENT_TYPE_PSM_1 = 0x18, // PSVita PSM ?
|
||||
PKG_CONTENT_TYPE_WT = 0x19, // Web TV ?
|
||||
PKG_CONTENT_TYPE_UNKNOWN_6 = 0x1A, // ?
|
||||
PKG_CONTENT_TYPE_UNKNOWN_7 = 0x1B, // ?
|
||||
PKG_CONTENT_TYPE_UNKNOWN_8 = 0x1C, // ?
|
||||
PKG_CONTENT_TYPE_PSM_2 = 0x1D, // PSVita PSM ?
|
||||
PKG_CONTENT_TYPE_UNKNOWN_9 = 0x1E, // ?
|
||||
PKG_CONTENT_TYPE_PSP2_THEME = 0x1F, // PSVita Theme
|
||||
};
|
||||
|
||||
// Structs
|
||||
struct PKGHeader
|
||||
{
|
||||
le_t<u32> pkg_magic; // Magic (0x7f504b47) (" PKG")
|
||||
be_t<u16> pkg_type; // Release type (Retail:0x8000, Debug:0x0000)
|
||||
be_t<u16> pkg_platform; // Platform type (PS3:0x0001, PSP:0x0002)
|
||||
be_t<u32> meta_offset; // Metadata offset. Usually 0xC0 for PS3, usually 0x280 for PSP and PSVita
|
||||
be_t<u32> meta_count; // Metadata item count
|
||||
be_t<u32> meta_size; // Metadata size.
|
||||
be_t<u32> file_count; // Number of files
|
||||
be_t<u64> pkg_size; // PKG size in bytes
|
||||
be_t<u64> data_offset; // Encrypted data offset
|
||||
be_t<u64> data_size; // Encrypted data size in bytes
|
||||
char title_id[48]; // Title ID
|
||||
be_t<u64> qa_digest[2]; // This should be the hash of "files + attribs"
|
||||
be_t<u128> klicensee; // Nonce
|
||||
// + some stuff
|
||||
};
|
||||
|
||||
// Extended header in PSP and PSVita packages
|
||||
struct PKGExtHeader
|
||||
{
|
||||
le_t<u32> magic; // 0x7F657874 (" ext")
|
||||
be_t<u32> unknown_1; // Maybe version. always 1
|
||||
be_t<u32> ext_hdr_size; // Extended header size. ex: 0x40
|
||||
be_t<u32> ext_data_size; // ex: 0x180
|
||||
be_t<u32> main_and_ext_headers_hmac_offset; // ex: 0x100
|
||||
be_t<u32> metadata_header_hmac_offset; // ex: 0x360, 0x390, 0x490
|
||||
be_t<u64> tail_offset; // tail size seams to be always 0x1A0
|
||||
be_t<u32> padding1;
|
||||
be_t<u32> pkg_key_id; // Id of the AES key used for decryption. PSP = 0x1, PSVita = 0xC0000002, PSM = 0xC0000004
|
||||
be_t<u32> full_header_hmac_offset; // ex: none (old pkg): 0, 0x930
|
||||
u8 padding2[20];
|
||||
};
|
||||
|
||||
struct PKGEntry
|
||||
{
|
||||
be_t<u32> name_offset; // File name offset
|
||||
be_t<u32> name_size; // File name size
|
||||
be_t<u64> file_offset; // File offset
|
||||
be_t<u64> file_size; // File size
|
||||
be_t<u32> type; // File type
|
||||
be_t<u32> pad; // Padding (zeros)
|
||||
};
|
||||
|
||||
// https://www.psdevwiki.com/ps3/PKG_files#PKG_Metadata
|
||||
struct PKGMetaData
|
||||
{
|
||||
private:
|
||||
static std::string to_hex_string(u8 buf[], usz size)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
for (usz i = 0; i < size; i++)
|
||||
{
|
||||
sstream << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(buf[i]);
|
||||
}
|
||||
return sstream.str();
|
||||
}
|
||||
static std::string to_hex_string(u8 buf[], usz size, usz dotpos)
|
||||
{
|
||||
std::string result = to_hex_string(buf, size);
|
||||
if (result.size() > dotpos)
|
||||
{
|
||||
result.insert(dotpos, 1, '.');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
be_t<u32> drm_type{0};
|
||||
be_t<u32> content_type{0};
|
||||
be_t<u32> package_type{0};
|
||||
be_t<u64> package_size{0};
|
||||
u8 qa_digest[24]{0};
|
||||
|
||||
be_t<u64> unk_0x9{0};
|
||||
be_t<u64> unk_0xB{0};
|
||||
|
||||
struct package_revision
|
||||
{
|
||||
struct package_revision_data
|
||||
{
|
||||
u8 make_package_npdrm_ver[2]{0};
|
||||
u8 version[2]{0};
|
||||
} data{};
|
||||
|
||||
std::string make_package_npdrm_ver;
|
||||
std::string version;
|
||||
|
||||
void interpret_data()
|
||||
{
|
||||
make_package_npdrm_ver = to_hex_string(data.make_package_npdrm_ver, sizeof(data.make_package_npdrm_ver));
|
||||
version = to_hex_string(data.version, sizeof(data.version), 2);
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("make package npdrm version: %s, version: %s", make_package_npdrm_ver, version);
|
||||
}
|
||||
} package_revision;
|
||||
|
||||
struct software_revision
|
||||
{
|
||||
struct software_revision_data
|
||||
{
|
||||
u8 unk[1]{0};
|
||||
u8 firmware_version[3]{0};
|
||||
u8 version[2]{0};
|
||||
u8 app_version[2]{0};
|
||||
} data{};
|
||||
|
||||
std::string unk; // maybe hardware id
|
||||
std::string firmware_version;
|
||||
std::string version;
|
||||
std::string app_version;
|
||||
|
||||
void interpret_data()
|
||||
{
|
||||
unk = to_hex_string(data.unk, sizeof(data.unk));
|
||||
firmware_version = to_hex_string(data.firmware_version, sizeof(data.firmware_version), 2);
|
||||
version = to_hex_string(data.version, sizeof(data.version), 2);
|
||||
app_version = to_hex_string(data.app_version, sizeof(data.app_version), 2);
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("unk: %s, firmware version: %s, version: %s, app version: %s",
|
||||
unk, firmware_version, version, app_version);
|
||||
}
|
||||
} software_revision;
|
||||
|
||||
std::string title_id;
|
||||
std::string install_dir;
|
||||
|
||||
// PSVita stuff
|
||||
|
||||
struct vita_item_info // size is 0x28 (40)
|
||||
{
|
||||
be_t<u32> offset{0};
|
||||
be_t<u32> size{0};
|
||||
u8 sha256[32]{0};
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("offset: 0x%x, size: 0x%x, sha256: 0x%x", offset, size, sha256);
|
||||
}
|
||||
} item_info;
|
||||
|
||||
struct vita_sfo_info // size is 0x38 (56)
|
||||
{
|
||||
be_t<u32> param_offset{0};
|
||||
be_t<u16> param_size{0};
|
||||
be_t<u32> unk_1{0}; // seen values: 0x00000001-0x00000018, 0x0000001b-0x0000001c
|
||||
be_t<u32> psp2_system_ver{0}; // BCD encoded
|
||||
u8 unk_2[8]{0};
|
||||
u8 param_digest[32]{0}; // SHA256 of param_data. Called ParamDigest: This is sha256 digest of param.sfo.
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("param_offset: 0x%x, param_size: 0x%x, unk_1: 0x%x, psp2_system_ver: 0x%x, unk_2: 0x%x, param_digest: 0x%x",
|
||||
param_offset, param_size, unk_1, psp2_system_ver, unk_2, param_digest);
|
||||
}
|
||||
} sfo_info;
|
||||
|
||||
struct vita_unknown_data_info // size is 0x48 (72)
|
||||
{
|
||||
be_t<u32> unknown_data_offset{0};
|
||||
be_t<u16> unknown_data_size{0}; // ex: 0x320
|
||||
u8 unk[32]{0};
|
||||
u8 unknown_data_sha256[32]{0};
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("unknown_data_offset: 0x%x, unknown_data_size: 0x%x, unk: 0x%x, unknown_data_sha256: 0x%x",
|
||||
unknown_data_offset, unknown_data_size, unk, unknown_data_sha256);
|
||||
}
|
||||
} unknown_data_info;
|
||||
|
||||
struct vita_entirety_info // size is 0x38 (56)
|
||||
{
|
||||
be_t<u32> entirety_data_offset{0}; // located just before SFO
|
||||
be_t<u32> entirety_data_size{0}; // ex: 0xA0, C0, 0x100, 0x120, 0x160
|
||||
be_t<u16> flags{0}; // ex: EE 00, FE 10, FE 78, FE F8, FF 10, FF 90, FF D0, flags indicating which digests it embeds
|
||||
be_t<u16> unk_1{0}; // always 00 00
|
||||
be_t<u32> unk_2{0}; // ex: 1, 0
|
||||
u8 unk_3[8]{0};
|
||||
u8 entirety_digest[32]{0};
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("entirety_data_offset: 0x%x, entirety_data_size: 0x%x, flags: 0x%x, unk_1: 0x%x, unk_2: 0x%x, unk_3: 0x%x, entirety_digest: 0x%x",
|
||||
entirety_data_offset, entirety_data_size, flags, unk_1, unk_2, unk_3, entirety_digest);
|
||||
}
|
||||
} entirety_info;
|
||||
|
||||
struct vita_version_info // size is 0x28 (40)
|
||||
{
|
||||
be_t<u32> publishing_tools_version{0};
|
||||
be_t<u32> psf_builder_version{0};
|
||||
u8 padding[32]{0};
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("publishing_tools_version: 0x%x, psf_builder_version: 0x%x, padding: 0x%x",
|
||||
publishing_tools_version, psf_builder_version, padding);
|
||||
}
|
||||
} version_info;
|
||||
|
||||
struct vita_self_info // size is 0x38 (56)
|
||||
{
|
||||
be_t<u32> self_info_offset{0}; // offset to the first self_info_data_element
|
||||
be_t<u32> self_info_size{0}; // usually 0x10 or 0x20
|
||||
u8 unk[16]{0};
|
||||
u8 self_sha256[32]{0};
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return fmt::format("self_info_offset: 0x%x, self_info_size: 0x%x, unk: 0x%x, self_sha256: 0x%x",
|
||||
self_info_offset, self_info_size, unk, self_sha256);
|
||||
}
|
||||
} self_info;
|
||||
};
|
||||
|
||||
struct package_install_result
|
||||
{
|
||||
enum class error_type
|
||||
{
|
||||
no_error,
|
||||
app_version,
|
||||
other
|
||||
} error = error_type::no_error;
|
||||
struct version
|
||||
{
|
||||
std::string expected;
|
||||
std::string found;
|
||||
} version;
|
||||
};
|
||||
|
||||
class package_reader
|
||||
{
|
||||
struct install_entry
|
||||
{
|
||||
typename std::map<std::string, install_entry*>::value_type* weak_reference{};
|
||||
std::string name;
|
||||
|
||||
u64 file_offset{};
|
||||
u64 file_size{};
|
||||
u32 type{};
|
||||
u32 pad{};
|
||||
|
||||
// Check if the entry is the same one registered in entries to install
|
||||
bool is_dominating() const
|
||||
{
|
||||
return weak_reference->second == this;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
package_reader(const std::string& path, fs::file file = {});
|
||||
~package_reader();
|
||||
|
||||
enum result
|
||||
{
|
||||
not_started,
|
||||
started,
|
||||
success,
|
||||
aborted,
|
||||
aborted_dirty,
|
||||
error,
|
||||
error_dirty
|
||||
};
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return m_is_valid;
|
||||
}
|
||||
package_install_result check_target_app_version() const;
|
||||
static package_install_result extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths);
|
||||
const psf::registry& get_psf() const
|
||||
{
|
||||
return m_psf;
|
||||
}
|
||||
result get_result() const
|
||||
{
|
||||
return m_result;
|
||||
};
|
||||
|
||||
int get_progress(int maximum = 100) const;
|
||||
|
||||
void abort_extract();
|
||||
|
||||
fs::file& file()
|
||||
{
|
||||
return m_file;
|
||||
}
|
||||
|
||||
private:
|
||||
bool read_header();
|
||||
bool read_metadata();
|
||||
bool read_param_sfo();
|
||||
bool set_decryption_key();
|
||||
bool read_entries(std::vector<PKGEntry>& entries);
|
||||
void archive_seek(s64 new_offset, const fs::seek_mode damode = fs::seek_set);
|
||||
u64 archive_read(void* data_ptr, u64 num_bytes);
|
||||
bool set_install_path();
|
||||
bool fill_data(std::map<std::string, install_entry*>& all_install_entries);
|
||||
std::span<const char> archive_read_block(u64 offset, void* data_ptr, u64 num_bytes);
|
||||
usz decrypt(u64 offset, u64 size, const uchar* key, void* local_buf);
|
||||
void extract_worker();
|
||||
|
||||
std::deque<install_entry> m_install_entries;
|
||||
std::string m_install_path;
|
||||
atomic_t<bool> m_aborted = false;
|
||||
atomic_t<usz> m_num_failures = 0;
|
||||
atomic_t<usz> m_entry_indexer = 0;
|
||||
atomic_t<usz> m_written_bytes = 0;
|
||||
bool m_was_null = false;
|
||||
|
||||
static constexpr usz BUF_SIZE = 8192 * 1024; // 8 MB
|
||||
static constexpr usz BUF_PADDING = 32;
|
||||
|
||||
bool m_is_valid = false;
|
||||
result m_result = result::not_started;
|
||||
|
||||
std::string m_path{};
|
||||
std::string m_install_dir{};
|
||||
fs::file m_file{};
|
||||
std::array<uchar, 16> m_dec_key{};
|
||||
|
||||
PKGHeader m_header{};
|
||||
PKGMetaData m_metadata{};
|
||||
psf::registry m_psf{};
|
||||
|
||||
// Expose bootable file installed (if installed such)
|
||||
std::string m_bootable_file_path;
|
||||
};
|
||||
1492
rpcs3/Crypto/unself.cpp
Normal file
1492
rpcs3/Crypto/unself.cpp
Normal file
File diff suppressed because it is too large
Load diff
583
rpcs3/Crypto/unself.h
Normal file
583
rpcs3/Crypto/unself.h
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
#pragma once
|
||||
|
||||
#include "key_vault.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "util/File.h"
|
||||
#include "util/logs.hpp"
|
||||
|
||||
#include "unedat.h"
|
||||
|
||||
LOG_CHANNEL(self_log, "SELF");
|
||||
|
||||
// SCE-specific definitions for e_type:
|
||||
enum
|
||||
{
|
||||
ET_SCE_EXEC = 0xFE00, // SCE Executable - PRX2
|
||||
ET_SCE_RELEXEC = 0xFE04, // SCE Relocatable Executable - PRX2
|
||||
ET_SCE_STUBLIB = 0xFE0C, // SCE SDK Stubs
|
||||
ET_SCE_DYNEXEC = 0xFE10, // SCE EXEC_ASLR (PS4 Executable with ASLR)
|
||||
ET_SCE_DYNAMIC = 0xFE18, // ?
|
||||
ET_SCE_IOPRELEXEC = 0xFF80, // SCE IOP Relocatable Executable
|
||||
ET_SCE_IOPRELEXEC2 = 0xFF81, // SCE IOP Relocatable Executable Version 2
|
||||
ET_SCE_EERELEXEC = 0xFF90, // SCE EE Relocatable Executable
|
||||
ET_SCE_EERELEXEC2 = 0xFF91, // SCE EE Relocatable Executable Version 2
|
||||
ET_SCE_PSPRELEXEC = 0xFFA0, // SCE PSP Relocatable Executable
|
||||
ET_SCE_PPURELEXEC = 0xFFA4, // SCE PPU Relocatable Executable
|
||||
ET_SCE_ARMRELEXEC = 0xFFA5, // ?SCE ARM Relocatable Executable (PS Vita System Software earlier or equal 0.931.010)
|
||||
ET_SCE_PSPOVERLAY = 0xFFA8, // ?
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ELFOSABI_CELL_LV2 = 102 // CELL LV2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PT_SCE_RELA = 0x60000000,
|
||||
PT_SCE_LICINFO_1 = 0x60000001,
|
||||
PT_SCE_LICINFO_2 = 0x60000002,
|
||||
PT_SCE_DYNLIBDATA = 0x61000000,
|
||||
PT_SCE_PROCPARAM = 0x61000001,
|
||||
PT_SCE_UNK_61000010 = 0x61000010,
|
||||
PT_SCE_COMMENT = 0x6FFFFF00,
|
||||
PT_SCE_LIBVERSION = 0x6FFFFF01,
|
||||
PT_SCE_UNK_70000001 = 0x70000001,
|
||||
PT_SCE_IOPMOD = 0x70000080,
|
||||
PT_SCE_EEMOD = 0x70000090,
|
||||
PT_SCE_PSPRELA = 0x700000A0,
|
||||
PT_SCE_PSPRELA2 = 0x700000A1,
|
||||
PT_SCE_PPURELA = 0x700000A4,
|
||||
PT_SCE_SEGSYM = 0x700000A8,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PF_SPU_X = 0x00100000,
|
||||
PF_SPU_W = 0x00200000,
|
||||
PF_SPU_R = 0x00400000,
|
||||
PF_RSX_X = 0x01000000,
|
||||
PF_RSX_W = 0x02000000,
|
||||
PF_RSX_R = 0x04000000,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SHT_SCE_RELA = 0x60000000,
|
||||
SHT_SCE_NID = 0x61000001,
|
||||
SHT_SCE_IOPMOD = 0x70000080,
|
||||
SHT_SCE_EEMOD = 0x70000090,
|
||||
SHT_SCE_PSPRELA = 0x700000A0,
|
||||
SHT_SCE_PPURELA = 0x700000A4,
|
||||
};
|
||||
|
||||
struct program_identification_header
|
||||
{
|
||||
u64 program_authority_id;
|
||||
u32 program_vendor_id;
|
||||
u32 program_type;
|
||||
u64 program_sceversion;
|
||||
u64 padding;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct segment_ext_header
|
||||
{
|
||||
u64 offset; // Offset to data
|
||||
u64 size; // Size of data
|
||||
u32 compression; // 1 = plain, 2 = zlib
|
||||
u32 unknown; // Always 0, as far as I know.
|
||||
u64 encryption; // 0 = unrequested, 1 = completed, 2 = requested
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct version_header
|
||||
{
|
||||
u32 subheader_type; // 1 - sceversion
|
||||
u32 present; // 0 = false, 1 = true
|
||||
u32 size; // usually 0x10
|
||||
u32 unknown4;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct supplemental_header
|
||||
{
|
||||
u32 type; // 1=PS3 plaintext_capability; 2=PS3 ELF digest; 3=PS3 NPDRM, 4=PS Vita ELF digest; 5=PS Vita NPDRM; 6=PS Vita boot param; 7=PS Vita shared secret
|
||||
u32 size;
|
||||
u64 next; // 1 if another Supplemental Header element follows else 0
|
||||
|
||||
union
|
||||
{
|
||||
// type 1, 0x30 bytes
|
||||
struct // 0x20 bytes of data
|
||||
{
|
||||
u32 ctrl_flag1;
|
||||
u32 unknown1;
|
||||
u32 unknown2;
|
||||
u32 unknown3;
|
||||
u32 unknown4;
|
||||
u32 unknown5;
|
||||
u32 unknown6;
|
||||
u32 unknown7;
|
||||
} PS3_plaintext_capability_header;
|
||||
|
||||
// type 2, 0x40 bytes
|
||||
struct // 0x30 bytes of data
|
||||
{
|
||||
u8 constant[0x14]; // same for every PS3/PS Vita SELF, hardcoded in make_fself.exe: 627CB1808AB938E32C8C091708726A579E2586E4
|
||||
u8 elf_digest[0x14]; // SHA-1. Hash F2C552BF716ED24759CBE8A0A9A6DB9965F3811C is blacklisted by appldr
|
||||
u64 required_system_version; // filled on Sony authentication server, contains decimal PS3_SYSTEM_VER value from PARAM.SFO
|
||||
} PS3_elf_digest_header_40;
|
||||
|
||||
// type 2, 0x30 bytes
|
||||
struct // 0x20 bytes of data
|
||||
{
|
||||
u8 constant_or_elf_digest[0x14];
|
||||
u8 padding[0xC];
|
||||
} PS3_elf_digest_header_30;
|
||||
|
||||
// type 3, 0x90 bytes
|
||||
struct // 0x80 bytes of data
|
||||
{
|
||||
NPD_HEADER npd;
|
||||
} PS3_npdrm_header;
|
||||
};
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct MetadataInfo
|
||||
{
|
||||
u8 key[0x10];
|
||||
u8 key_pad[0x10];
|
||||
u8 iv[0x10];
|
||||
u8 iv_pad[0x10];
|
||||
|
||||
void Load(u8* in);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct MetadataHeader
|
||||
{
|
||||
u64 signature_input_length;
|
||||
u32 unknown1;
|
||||
u32 section_count;
|
||||
u32 key_count;
|
||||
u32 opt_header_size;
|
||||
u32 unknown2;
|
||||
u32 unknown3;
|
||||
|
||||
void Load(u8* in);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct MetadataSectionHeader
|
||||
{
|
||||
u64 data_offset;
|
||||
u64 data_size;
|
||||
u32 type;
|
||||
u32 program_idx;
|
||||
u32 hashed;
|
||||
u32 sha1_idx;
|
||||
u32 encrypted;
|
||||
u32 key_idx;
|
||||
u32 iv_idx;
|
||||
u32 compressed;
|
||||
|
||||
void Load(u8* in);
|
||||
void Show() const;
|
||||
};
|
||||
|
||||
struct SectionHash
|
||||
{
|
||||
u8 sha1[20];
|
||||
u8 padding[12];
|
||||
u8 hmac_key[64];
|
||||
|
||||
void Load(const fs::file& f);
|
||||
};
|
||||
|
||||
struct CapabilitiesInfo
|
||||
{
|
||||
u32 type;
|
||||
u32 capabilities_size;
|
||||
u32 next;
|
||||
u32 unknown1;
|
||||
u64 unknown2;
|
||||
u64 unknown3;
|
||||
u64 flags;
|
||||
u32 unknown4;
|
||||
u32 unknown5;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
};
|
||||
|
||||
struct Signature
|
||||
{
|
||||
u8 r[21];
|
||||
u8 s[21];
|
||||
u8 padding[6];
|
||||
|
||||
void Load(const fs::file& f);
|
||||
};
|
||||
|
||||
struct SelfSection
|
||||
{
|
||||
u8* data;
|
||||
u64 size;
|
||||
u64 offset;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
};
|
||||
|
||||
struct Elf32_Ehdr
|
||||
{
|
||||
// u8 e_ident[16]; // ELF identification
|
||||
u32 e_magic;
|
||||
u8 e_class;
|
||||
u8 e_data;
|
||||
u8 e_curver;
|
||||
u8 e_os_abi;
|
||||
u64 e_abi_ver;
|
||||
u16 e_type; // object file type
|
||||
u16 e_machine; // machine type
|
||||
u32 e_version; // object file version
|
||||
u32 e_entry; // entry point address
|
||||
u32 e_phoff; // program header offset
|
||||
u32 e_shoff; // section header offset
|
||||
u32 e_flags; // processor-specific flags
|
||||
u16 e_ehsize; // ELF header size
|
||||
u16 e_phentsize; // size of program header entry
|
||||
u16 e_phnum; // number of program header entries
|
||||
u16 e_shentsize; // size of section header entry
|
||||
u16 e_shnum; // number of section header entries
|
||||
u16 e_shstrndx; // section name string table index
|
||||
|
||||
void Load(const fs::file& f);
|
||||
static void Show() {}
|
||||
bool IsLittleEndian() const
|
||||
{
|
||||
return e_data == 1;
|
||||
}
|
||||
bool CheckMagic() const
|
||||
{
|
||||
return e_magic == 0x7F454C46;
|
||||
}
|
||||
u32 GetEntry() const
|
||||
{
|
||||
return e_entry;
|
||||
}
|
||||
};
|
||||
|
||||
struct Elf32_Shdr
|
||||
{
|
||||
u32 sh_name; // section name
|
||||
u32 sh_type; // section type
|
||||
u32 sh_flags; // section attributes
|
||||
u32 sh_addr; // virtual address in memory
|
||||
u32 sh_offset; // offset in file
|
||||
u32 sh_size; // size of section
|
||||
u32 sh_link; // link to other section
|
||||
u32 sh_info; // miscellaneous information
|
||||
u32 sh_addralign; // address alignment boundary
|
||||
u32 sh_entsize; // size of entries, if section has table
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
static void Show() {}
|
||||
};
|
||||
|
||||
struct Elf32_Phdr
|
||||
{
|
||||
u32 p_type; // Segment type
|
||||
u32 p_offset; // Segment file offset
|
||||
u32 p_vaddr; // Segment virtual address
|
||||
u32 p_paddr; // Segment physical address
|
||||
u32 p_filesz; // Segment size in file
|
||||
u32 p_memsz; // Segment size in memory
|
||||
u32 p_flags; // Segment flags
|
||||
u32 p_align; // Segment alignment
|
||||
|
||||
void Load(const fs::file& f);
|
||||
void LoadLE(const fs::file& f);
|
||||
static void Show() {}
|
||||
};
|
||||
|
||||
struct Elf64_Ehdr
|
||||
{
|
||||
// u8 e_ident[16]; // ELF identification
|
||||
u32 e_magic;
|
||||
u8 e_class;
|
||||
u8 e_data;
|
||||
u8 e_curver;
|
||||
u8 e_os_abi;
|
||||
u64 e_abi_ver;
|
||||
u16 e_type; // object file type
|
||||
u16 e_machine; // machine type
|
||||
u32 e_version; // object file version
|
||||
u64 e_entry; // entry point address
|
||||
u64 e_phoff; // program header offset
|
||||
u64 e_shoff; // section header offset
|
||||
u32 e_flags; // processor-specific flags
|
||||
u16 e_ehsize; // ELF header size
|
||||
u16 e_phentsize; // size of program header entry
|
||||
u16 e_phnum; // number of program header entries
|
||||
u16 e_shentsize; // size of section header entry
|
||||
u16 e_shnum; // number of section header entries
|
||||
u16 e_shstrndx; // section name string table index
|
||||
|
||||
void Load(const fs::file& f);
|
||||
static void Show() {}
|
||||
bool CheckMagic() const
|
||||
{
|
||||
return e_magic == 0x7F454C46;
|
||||
}
|
||||
u64 GetEntry() const
|
||||
{
|
||||
return e_entry;
|
||||
}
|
||||
};
|
||||
|
||||
struct Elf64_Shdr
|
||||
{
|
||||
u32 sh_name; // section name
|
||||
u32 sh_type; // section type
|
||||
u64 sh_flags; // section attributes
|
||||
u64 sh_addr; // virtual address in memory
|
||||
u64 sh_offset; // offset in file
|
||||
u64 sh_size; // size of section
|
||||
u32 sh_link; // link to other section
|
||||
u32 sh_info; // miscellaneous information
|
||||
u64 sh_addralign; // address alignment boundary
|
||||
u64 sh_entsize; // size of entries, if section has table
|
||||
|
||||
void Load(const fs::file& f);
|
||||
static void Show() {}
|
||||
};
|
||||
|
||||
struct Elf64_Phdr
|
||||
{
|
||||
u32 p_type; // Segment type
|
||||
u32 p_flags; // Segment flags
|
||||
u64 p_offset; // Segment file offset
|
||||
u64 p_vaddr; // Segment virtual address
|
||||
u64 p_paddr; // Segment physical address
|
||||
u64 p_filesz; // Segment size in file
|
||||
u64 p_memsz; // Segment size in memory
|
||||
u64 p_align; // Segment alignment
|
||||
|
||||
void Load(const fs::file& f);
|
||||
static void Show() {}
|
||||
};
|
||||
|
||||
struct SceHeader
|
||||
{
|
||||
u32 se_magic;
|
||||
u32 se_hver;
|
||||
u16 se_flags;
|
||||
u16 se_type;
|
||||
u32 se_meta;
|
||||
u64 se_hsize;
|
||||
u64 se_esize;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
static void Show() {}
|
||||
bool CheckMagic() const
|
||||
{
|
||||
return se_magic == 0x53434500;
|
||||
}
|
||||
};
|
||||
|
||||
struct ext_hdr
|
||||
{
|
||||
u64 ext_hdr_version;
|
||||
u64 program_identification_hdr_offset;
|
||||
u64 ehdr_offset;
|
||||
u64 phdr_offset;
|
||||
u64 shdr_offset;
|
||||
u64 segment_ext_hdr_offset;
|
||||
u64 version_hdr_offset;
|
||||
u64 supplemental_hdr_offset;
|
||||
u64 supplemental_hdr_size;
|
||||
u64 padding;
|
||||
|
||||
void Load(const fs::file& f);
|
||||
static void Show() {}
|
||||
};
|
||||
|
||||
struct SelfAdditionalInfo
|
||||
{
|
||||
bool valid = false;
|
||||
std::vector<supplemental_header> supplemental_hdr;
|
||||
program_identification_header prog_id_hdr;
|
||||
};
|
||||
|
||||
class SCEDecrypter
|
||||
{
|
||||
protected:
|
||||
// Main SELF file stream.
|
||||
const fs::file& sce_f;
|
||||
|
||||
// SCE headers.
|
||||
SceHeader sce_hdr{};
|
||||
|
||||
// Metadata structs.
|
||||
MetadataInfo meta_info{};
|
||||
MetadataHeader meta_hdr{};
|
||||
std::vector<MetadataSectionHeader> meta_shdr{};
|
||||
|
||||
// Internal data buffers.
|
||||
std::unique_ptr<u8[]> data_keys{};
|
||||
u32 data_keys_length{};
|
||||
std::unique_ptr<u8[]> data_buf{};
|
||||
u32 data_buf_length{};
|
||||
|
||||
public:
|
||||
SCEDecrypter(const fs::file& s);
|
||||
std::vector<fs::file> MakeFile();
|
||||
bool LoadHeaders();
|
||||
bool LoadMetadata(const u8 erk[32], const u8 riv[16]);
|
||||
bool DecryptData();
|
||||
};
|
||||
|
||||
class SELFDecrypter
|
||||
{
|
||||
// Main SELF file stream.
|
||||
const fs::file& self_f;
|
||||
|
||||
// SCE, SELF and APP headers.
|
||||
SceHeader sce_hdr{};
|
||||
ext_hdr m_ext_hdr{};
|
||||
program_identification_header m_prog_id_hdr{};
|
||||
|
||||
// ELF64 header and program header/section header arrays.
|
||||
Elf64_Ehdr elf64_hdr{};
|
||||
std::vector<Elf64_Shdr> shdr64_arr{};
|
||||
std::vector<Elf64_Phdr> phdr64_arr{};
|
||||
|
||||
// ELF32 header and program header/section header arrays.
|
||||
Elf32_Ehdr elf32_hdr{};
|
||||
std::vector<Elf32_Shdr> shdr32_arr{};
|
||||
std::vector<Elf32_Phdr> phdr32_arr{};
|
||||
|
||||
// Decryption info structs.
|
||||
std::vector<segment_ext_header> m_seg_ext_hdr{};
|
||||
version_header m_version_hdr{};
|
||||
std::vector<supplemental_header> m_supplemental_hdr_arr{};
|
||||
|
||||
// Metadata structs.
|
||||
MetadataInfo meta_info{};
|
||||
MetadataHeader meta_hdr{};
|
||||
std::vector<MetadataSectionHeader> meta_shdr{};
|
||||
|
||||
// Internal data buffers.
|
||||
std::unique_ptr<u8[]> data_keys{};
|
||||
u32 data_keys_length{};
|
||||
std::unique_ptr<u8[]> data_buf{};
|
||||
u32 data_buf_length{};
|
||||
|
||||
// Main key vault instance.
|
||||
KeyVault key_v{};
|
||||
|
||||
public:
|
||||
SELFDecrypter(const fs::file& s);
|
||||
fs::file MakeElf(bool isElf32);
|
||||
bool LoadHeaders(bool isElf32, SelfAdditionalInfo* out_info = nullptr);
|
||||
void ShowHeaders(bool isElf32);
|
||||
bool LoadMetadata(const u8* klic_key);
|
||||
bool DecryptData();
|
||||
bool DecryptNPDRM(u8* metadata, u32 metadata_size);
|
||||
const NPD_HEADER* GetNPDHeader() const;
|
||||
static bool GetKeyFromRap(const char* content_id, u8* npdrm_key);
|
||||
|
||||
private:
|
||||
template <typename EHdr, typename SHdr, typename PHdr>
|
||||
void WriteElf(fs::file& e, EHdr ehdr, SHdr shdr, PHdr phdr)
|
||||
{
|
||||
// Set initial offset.
|
||||
u32 data_buf_offset = 0;
|
||||
|
||||
// Write ELF header.
|
||||
WriteEhdr(e, ehdr);
|
||||
|
||||
// Write program headers.
|
||||
for (u32 i = 0; i < ehdr.e_phnum; ++i)
|
||||
{
|
||||
WritePhdr(e, phdr[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
|
||||
{
|
||||
// PHDR type.
|
||||
if (meta_shdr[i].type == 2)
|
||||
{
|
||||
// Decompress if necessary.
|
||||
if (meta_shdr[i].compressed == 2)
|
||||
{
|
||||
const auto filesz = phdr[meta_shdr[i].program_idx].p_filesz;
|
||||
|
||||
// Create a pointer to a buffer for decompression.
|
||||
std::unique_ptr<u8[]> decomp_buf(new u8[filesz]);
|
||||
|
||||
// Create a buffer separate from data_buf to uncompress.
|
||||
std::unique_ptr<u8[]> zlib_buf(new u8[data_buf_length]);
|
||||
memcpy(zlib_buf.get(), data_buf.get(), data_buf_length);
|
||||
|
||||
uLongf decomp_buf_length = ::narrow<uLongf>(filesz);
|
||||
|
||||
// Use zlib uncompress on the new buffer.
|
||||
// decomp_buf_length changes inside the call to uncompress
|
||||
const int rv = uncompress(decomp_buf.get(), &decomp_buf_length, zlib_buf.get() + data_buf_offset, data_buf_length);
|
||||
|
||||
// Check for errors (TODO: Probably safe to remove this once these changes have passed testing.)
|
||||
switch (rv)
|
||||
{
|
||||
case Z_MEM_ERROR: self_log.error("MakeELF encountered a Z_MEM_ERROR!"); break;
|
||||
case Z_BUF_ERROR: self_log.error("MakeELF encountered a Z_BUF_ERROR!"); break;
|
||||
case Z_DATA_ERROR: self_log.error("MakeELF encountered a Z_DATA_ERROR!"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr[meta_shdr[i].program_idx].p_offset);
|
||||
e.write(decomp_buf.get(), filesz);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seek to the program header data offset and write the data.
|
||||
e.seek(phdr[meta_shdr[i].program_idx].p_offset);
|
||||
e.write(data_buf.get() + data_buf_offset, meta_shdr[i].data_size);
|
||||
}
|
||||
|
||||
// Advance the data buffer offset by data size.
|
||||
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Write section headers.
|
||||
if (m_ext_hdr.shdr_offset != 0)
|
||||
{
|
||||
e.seek(ehdr.e_shoff);
|
||||
|
||||
for (u32 i = 0; i < ehdr.e_shnum; ++i)
|
||||
{
|
||||
WriteShdr(e, shdr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fs::file decrypt_self(const fs::file& elf_or_self, const u8* klic_key = nullptr, SelfAdditionalInfo* additional_info = nullptr);
|
||||
bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key = nullptr, NPD_HEADER* npd_out = nullptr);
|
||||
bool get_npdrm_self_header(const fs::file& self, NPD_HEADER& npd);
|
||||
|
||||
u128 get_default_self_klic();
|
||||
170
rpcs3/Crypto/unzip.cpp
Normal file
170
rpcs3/Crypto/unzip.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include "stdafx.h"
|
||||
#include "unzip.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "util/serialization_ext.hpp"
|
||||
|
||||
std::vector<u8> unzip(const void* src, usz size)
|
||||
{
|
||||
if (!src || !size) [[unlikely]]
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uchar> out(size * 6);
|
||||
|
||||
z_stream zs{};
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
int res = inflateInit2(&zs, 16 + 15);
|
||||
if (res != Z_OK)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
zs.avail_in = static_cast<uInt>(size);
|
||||
zs.next_in = reinterpret_cast<const u8*>(src);
|
||||
zs.avail_out = static_cast<uInt>(out.size());
|
||||
zs.next_out = out.data();
|
||||
|
||||
while (zs.avail_in)
|
||||
{
|
||||
switch (inflate(&zs, Z_FINISH))
|
||||
{
|
||||
case Z_OK:
|
||||
case Z_STREAM_END:
|
||||
break;
|
||||
case Z_BUF_ERROR:
|
||||
if (zs.avail_in)
|
||||
break;
|
||||
[[fallthrough]];
|
||||
default:
|
||||
inflateEnd(&zs);
|
||||
return out;
|
||||
}
|
||||
|
||||
if (zs.avail_in)
|
||||
{
|
||||
const auto cur_size = zs.next_out - out.data();
|
||||
out.resize(out.size() + 65536);
|
||||
zs.avail_out = static_cast<uInt>(out.size() - cur_size);
|
||||
zs.next_out = &out[cur_size];
|
||||
}
|
||||
}
|
||||
|
||||
out.resize(zs.next_out - out.data());
|
||||
|
||||
res = inflateEnd(&zs);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool unzip(const void* src, usz size, fs::file& out)
|
||||
{
|
||||
if (!src || !size || !out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_valid = true;
|
||||
|
||||
constexpr usz BUFSIZE = 32ULL * 1024ULL;
|
||||
std::vector<u8> tempbuf(BUFSIZE);
|
||||
z_stream strm{};
|
||||
strm.avail_in = ::narrow<uInt>(size);
|
||||
strm.avail_out = static_cast<uInt>(tempbuf.size());
|
||||
strm.next_in = reinterpret_cast<const u8*>(src);
|
||||
strm.next_out = tempbuf.data();
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
int res = inflateInit(&strm);
|
||||
if (res != Z_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
while (strm.avail_in)
|
||||
{
|
||||
res = inflate(&strm, Z_NO_FLUSH);
|
||||
if (res == Z_STREAM_END)
|
||||
break;
|
||||
if (res != Z_OK)
|
||||
is_valid = false;
|
||||
|
||||
if (strm.avail_out)
|
||||
break;
|
||||
|
||||
if (out.write(tempbuf.data(), tempbuf.size()) != tempbuf.size())
|
||||
{
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
strm.next_out = tempbuf.data();
|
||||
strm.avail_out = static_cast<uInt>(tempbuf.size());
|
||||
}
|
||||
|
||||
res = inflate(&strm, Z_FINISH);
|
||||
|
||||
if (res != Z_STREAM_END)
|
||||
is_valid = false;
|
||||
|
||||
if (strm.avail_out < tempbuf.size())
|
||||
{
|
||||
const usz bytes_to_write = tempbuf.size() - strm.avail_out;
|
||||
|
||||
if (out.write(tempbuf.data(), bytes_to_write) != bytes_to_write)
|
||||
{
|
||||
is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
res = inflateEnd(&strm);
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
bool zip(const void* src, usz size, fs::file& out, bool multi_thread_it)
|
||||
{
|
||||
if (!src || !size || !out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
utils::serial compressor;
|
||||
compressor.set_expect_little_data(!multi_thread_it || size < 0x40'0000);
|
||||
compressor.m_file_handler = make_compressed_serialization_file_handler(out);
|
||||
|
||||
std::string_view buffer_view{static_cast<const char*>(src), size};
|
||||
|
||||
while (!buffer_view.empty())
|
||||
{
|
||||
if (!compressor.m_file_handler->is_valid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string_view slice = buffer_view.substr(0, 0x50'0000);
|
||||
|
||||
compressor(slice);
|
||||
compressor.breathe();
|
||||
buffer_view = buffer_view.substr(slice.size());
|
||||
}
|
||||
|
||||
compressor.m_file_handler->finalize(compressor);
|
||||
|
||||
if (!compressor.m_file_handler->is_valid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
25
rpcs3/Crypto/unzip.h
Normal file
25
rpcs3/Crypto/unzip.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
std::vector<u8> unzip(const void* src, usz size);
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<u8> unzip(const T& src)
|
||||
{
|
||||
return unzip(src.data(), src.size());
|
||||
}
|
||||
|
||||
bool unzip(const void* src, usz size, fs::file& out);
|
||||
|
||||
template <typename T>
|
||||
inline bool unzip(const std::vector<u8>& src, fs::file& out)
|
||||
{
|
||||
return unzip(src.data(), src.size(), out);
|
||||
}
|
||||
|
||||
bool zip(const void* src, usz size, fs::file& out, bool multi_thread_it = false);
|
||||
|
||||
template <typename T>
|
||||
inline bool zip(const T& src, fs::file& out)
|
||||
{
|
||||
return zip(src.data(), src.size(), out);
|
||||
}
|
||||
242
rpcs3/Crypto/utils.cpp
Normal file
242
rpcs3/Crypto/utils.cpp
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 2.0 or later versions.
|
||||
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
|
||||
#include "utils.h"
|
||||
#include "aes.h"
|
||||
#include "sha1.h"
|
||||
#include "sha256.h"
|
||||
#include "key_vault.h"
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "util/StrUtil.h"
|
||||
#include "util/File.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <span>
|
||||
|
||||
// Auxiliary functions (endian swap, xor).
|
||||
|
||||
// Hex string conversion auxiliary functions.
|
||||
u64 hex_to_u64(const char* hex_str)
|
||||
{
|
||||
auto length = std::strlen(hex_str);
|
||||
u64 tmp = 0;
|
||||
u64 result = 0;
|
||||
char c;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
c = *hex_str++;
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
tmp = c - '0';
|
||||
else if ((c >= 'a') && (c <= 'f'))
|
||||
tmp = c - 'a' + 10;
|
||||
else if ((c >= 'A') && (c <= 'F'))
|
||||
tmp = c - 'A' + 10;
|
||||
else
|
||||
tmp = 0;
|
||||
result |= (tmp << (length * 4));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void hex_to_bytes(unsigned char* data, const char* hex_str, unsigned int str_length)
|
||||
{
|
||||
const auto strn_length = (str_length > 0) ? str_length : std::strlen(hex_str);
|
||||
auto data_length = strn_length / 2;
|
||||
char tmp_buf[3] = {0, 0, 0};
|
||||
|
||||
// Don't convert if the string length is odd.
|
||||
if ((strn_length % 2) == 0)
|
||||
{
|
||||
while (data_length--)
|
||||
{
|
||||
tmp_buf[0] = *hex_str++;
|
||||
tmp_buf[1] = *hex_str++;
|
||||
|
||||
*data++ = static_cast<u8>(hex_to_u64(tmp_buf) & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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, usz 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 aescbc128_encrypt(unsigned char* key, unsigned char* iv, unsigned char* in, unsigned char* out, usz len)
|
||||
{
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_crypt_cbc(&ctx, AES_ENCRYPT, 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, usz in_len, unsigned char* hash, usz hash_len)
|
||||
{
|
||||
const std::unique_ptr<u8[]> out(new u8[key_len]);
|
||||
|
||||
sha1_hmac(key, key_len, in, in_len, out.get());
|
||||
|
||||
return std::memcmp(out.get(), hash, hash_len) == 0;
|
||||
}
|
||||
|
||||
void hmac_hash_forge(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash)
|
||||
{
|
||||
sha1_hmac(key, key_len, in, in_len, hash);
|
||||
}
|
||||
|
||||
bool cmac_hash_compare(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash, usz hash_len)
|
||||
{
|
||||
const std::unique_ptr<u8[]> out(new u8[key_len]);
|
||||
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_cmac(&ctx, in_len, in, out.get());
|
||||
|
||||
return std::memcmp(out.get(), hash, hash_len) == 0;
|
||||
}
|
||||
|
||||
void cmac_hash_forge(unsigned char* key, int /*key_len*/, unsigned char* in, usz in_len, unsigned char* hash)
|
||||
{
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_cmac(&ctx, in_len, in, hash);
|
||||
}
|
||||
|
||||
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH])
|
||||
{
|
||||
std::string_view v(file_path);
|
||||
|
||||
if (const auto pos = v.find_last_of(fs::delim); pos != umax)
|
||||
{
|
||||
v.remove_prefix(pos + 1);
|
||||
}
|
||||
|
||||
std::span r(real_file_name, CRYPTO_MAX_PATH);
|
||||
strcpy_trunc(r, v);
|
||||
return real_file_name;
|
||||
}
|
||||
|
||||
std::string sha256_get_hash(const char* data, usz size, bool lower_case)
|
||||
{
|
||||
u8 res_hash[32];
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
mbedtls_sha256_starts_ret(&ctx, 0);
|
||||
mbedtls_sha256_update_ret(&ctx, reinterpret_cast<const unsigned char*>(data), size);
|
||||
mbedtls_sha256_finish_ret(&ctx, res_hash);
|
||||
|
||||
std::string res_hash_string("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
for (usz index = 0; index < 32; index++)
|
||||
{
|
||||
const auto pal = lower_case ? "0123456789abcdef" : "0123456789ABCDEF";
|
||||
res_hash_string[index * 2] = pal[res_hash[index] >> 4];
|
||||
res_hash_string[(index * 2) + 1] = pal[res_hash[index] & 15];
|
||||
}
|
||||
|
||||
return res_hash_string;
|
||||
}
|
||||
|
||||
void mbedtls_zeroize(void* v, size_t n)
|
||||
{
|
||||
static void* (*const volatile unop_memset)(void*, int, size_t) = &memset;
|
||||
(void)unop_memset(v, 0, n);
|
||||
}
|
||||
|
||||
// SC passphrase crypto
|
||||
|
||||
void sc_form_key(const u8* sc_key, const std::array<u8, PASSPHRASE_KEY_LEN>& laid_paid, u8* key)
|
||||
{
|
||||
for (u32 i = 0; i < PASSPHRASE_KEY_LEN; i++)
|
||||
{
|
||||
key[i] = static_cast<u8>(sc_key[i] ^ laid_paid[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<u8, PASSPHRASE_KEY_LEN> sc_combine_laid_paid(s64 laid, s64 paid)
|
||||
{
|
||||
const std::string paid_laid = fmt::format("%016llx%016llx", laid, paid);
|
||||
std::array<u8, PASSPHRASE_KEY_LEN> out{};
|
||||
hex_to_bytes(out.data(), paid_laid.c_str(), PASSPHRASE_KEY_LEN * 2);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::array<u8, PASSPHRASE_KEY_LEN> vtrm_get_laid_paid_from_type(int type)
|
||||
{
|
||||
// No idea what this type stands for
|
||||
switch (type)
|
||||
{
|
||||
case 0: return sc_combine_laid_paid(0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL);
|
||||
case 1: return sc_combine_laid_paid(LAID_2, 0x1070000000000001L);
|
||||
case 2: return sc_combine_laid_paid(LAID_2, 0x0000000000000000L);
|
||||
case 3: return sc_combine_laid_paid(LAID_2, PAID_69);
|
||||
default:
|
||||
fmt::throw_exception("vtrm_get_laid_paid_from_type: Wrong type specified (type=%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<u8, PASSPHRASE_KEY_LEN> vtrm_portability_laid_paid()
|
||||
{
|
||||
// 107000002A000001
|
||||
return sc_combine_laid_paid(0x0000000000000000L, 0x0000000000000000L);
|
||||
}
|
||||
|
||||
int sc_decrypt(const u8* sc_key, const std::array<u8, PASSPHRASE_KEY_LEN>& laid_paid, u8* iv, u8* input, u8* output)
|
||||
{
|
||||
aes_context ctx;
|
||||
u8 key[PASSPHRASE_KEY_LEN];
|
||||
sc_form_key(sc_key, laid_paid, key);
|
||||
aes_setkey_dec(&ctx, key, 128);
|
||||
return aes_crypt_cbc(&ctx, AES_DECRYPT, PASSPHRASE_OUT_LEN, iv, input, output);
|
||||
}
|
||||
|
||||
int vtrm_decrypt(int type, u8* iv, u8* input, u8* output)
|
||||
{
|
||||
return sc_decrypt(SC_ISO_SERIES_KEY_2, vtrm_get_laid_paid_from_type(type), iv, input, output);
|
||||
}
|
||||
|
||||
int vtrm_decrypt_master(s64 laid, s64 paid, u8* iv, u8* input, u8* output)
|
||||
{
|
||||
return sc_decrypt(SC_ISO_SERIES_INTERNAL_KEY_3, sc_combine_laid_paid(laid, paid), iv, input, output);
|
||||
}
|
||||
|
||||
const u8* vtrm_portability_type_mapper(int type)
|
||||
{
|
||||
// No idea what this type stands for
|
||||
switch (type)
|
||||
{
|
||||
// case 0: return key_for_type_1;
|
||||
case 1: return SC_ISO_SERIES_KEY_2;
|
||||
case 2: return SC_ISO_SERIES_KEY_1;
|
||||
case 3: return SC_KEY_FOR_MASTER_2;
|
||||
default:
|
||||
fmt::throw_exception("vtrm_portability_type_mapper: Wrong type specified (type=%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
int vtrm_decrypt_with_portability(int type, u8* iv, u8* input, u8* output)
|
||||
{
|
||||
return sc_decrypt(vtrm_portability_type_mapper(type), vtrm_portability_laid_paid(), iv, input, output);
|
||||
}
|
||||
38
rpcs3/Crypto/utils.h
Normal file
38
rpcs3/Crypto/utils.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 2.0 or later versions.
|
||||
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
|
||||
#include "util/types.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
enum
|
||||
{
|
||||
CRYPTO_MAX_PATH = 4096
|
||||
};
|
||||
|
||||
char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PATH]);
|
||||
|
||||
std::string sha256_get_hash(const char* data, usz size, bool lower_case);
|
||||
|
||||
// Hex string conversion auxiliary functions.
|
||||
u64 hex_to_u64(const char* hex_str);
|
||||
void hex_to_bytes(unsigned char* data, const char* hex_str, unsigned int str_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, usz len);
|
||||
void aescbc128_encrypt(unsigned char* key, unsigned char* iv, unsigned char* in, unsigned char* out, usz 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, usz in_len, unsigned char* hash, usz hash_len);
|
||||
void hmac_hash_forge(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash);
|
||||
bool cmac_hash_compare(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash, usz hash_len);
|
||||
void cmac_hash_forge(unsigned char* key, int key_len, unsigned char* in, usz in_len, unsigned char* hash);
|
||||
void mbedtls_zeroize(void* v, size_t n);
|
||||
|
||||
// SC passphrase crypto
|
||||
|
||||
int vtrm_decrypt(int type, u8* iv, u8* input, u8* output);
|
||||
int vtrm_decrypt_master(s64 laid, s64 paid, u8* iv, u8* input, u8* output);
|
||||
int vtrm_decrypt_with_portability(int type, u8* iv, u8* input, u8* output);
|
||||
Loading…
Add table
Add a link
Reference in a new issue