#include #include #include #include #include #include #include #include #include #include #define IDPS_KEYBITS 128 #define ACT_DAT_KEYBITS 128 #define RIF_KEYBITS 128 #define RAP_KEYBITS 128 #include "aes.h" #include "util.h" #include "sha1.h" #include "pkg2zip_aes.h" #ifdef _WIN32 #define fseek _fseeki64 #define ftell _ftelli64 #endif #define _LARGEFILE64_SOURCE #define _FILE_OFFSET_BITS 64 uint8_t p_fixed[20]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; uint8_t a_fixed[20]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC}; uint8_t b_fixed[20]={0xA6,0x8B,0xED,0xC3,0x34,0x18,0x02,0x9C,0x1D,0x3C,0xE3,0x3B,0x9A,0x32,0x1F,0xCC,0xBB,0x9E,0x0F,0x0B}; uint8_t n_fixed[21]={0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xB5,0xAE,0x3C,0x52,0x3E,0x63,0x94,0x4F,0x21,0x27}; uint8_t gx_fixed[20]={0x12,0x8E,0xC4,0x25,0x64,0x87,0xFD,0x8F,0xDF,0x64,0xE2,0x43,0x7B,0xC0,0xA1,0xF6,0xD5,0xAF,0xDE,0x2C}; uint8_t gy_fixed[20]={0x59,0x58,0x55,0x7E,0xB1,0xDB,0x00,0x12,0x60,0x42,0x55,0x24,0xDB,0xC3,0x79,0xD5,0xAC,0x5F,0x4A,0xDF}; uint8_t ec_p_nm[20]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4A, 0x51, 0xC3, 0xAD, 0xC1, 0x9C, 0x6B, 0xB0, 0xDE, 0xD8}; uint8_t ec_a_nm[20]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF ,0xFF ,0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t ec_b_nm[20]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; uint8_t ec_G_nm[40]={0xED, 0x71, 0x3B, 0xDA, 0x9B, 0x78, 0x02, 0x70, 0x20, 0x9B, 0x1D, 0xBC, 0x84, 0x3F, 0x5E, 0x09, 0x2A, 0x50, 0x21, 0xD3, 0xA6, 0xA7, 0xAA, 0x81, 0x4E, 0x24, 0xFF, 0xED, 0x9F, 0xBD, 0xAA, 0xDB, 0x24, 0x3C, 0x86, 0x2A, 0x53, 0xA0, 0xB5, 0x20}; uint8_t ec_N_nm[20]={0x59, 0x74, 0x12, 0x3C, 0xCB, 0xE7, 0xFD, 0x63, 0xE2, 0xC3, 0x1C, 0xC4, 0x65, 0xCD, 0xE0, 0x33, 0x44, 0x61 ,0xF0, 0xF4}; //uint8_t ec_k[21]={0x00,0x42,0x75,0x72,0x6E,0x20,0x49,0x6E,0x20,0x48,0x65,0x6C,0x6C,0x20,0x53,0x6F,0x6E,0x79,0x20,0x21,0x21}; //uint8_t ec_Q_nm[40]={0x7C,0xFD,0x88,0x8E,0xE9,0xDD,0x5F,0x60,0x30,0xA5,0xC1,0xC0,0xA2,0xF9,0x08,0x4A,0x74,0xB1,0x32,0x87,0x33,0x52,0x68,0x11,0xCF,0xBA,0x95,0x35,0x06,0xE4,0x41,0x11,0xF0,0xE2,0xD6,0xF2,0xD1,0x91,0x3E,0x69}; uint8_t ec_k[21]={0x00,0xbf,0x21,0x22,0x4b,0x04,0x1f,0x29,0x54,0x9d,0xb2,0x5e,0x9a,0xad,0xe1,0x9e,0x72,0x0a,0x1f,0xe0,0xf1}; uint8_t ec_Q_nm[40]={0x94,0x8D,0xA1,0x3E,0x8C,0xAF,0xD5,0xBA,0x0E,0x90,0xCE,0x43,0x44,0x61,0xBB,0x32,0x7F,0xE7,0xE0,0x80,0x47,0x5E,0xAA,0x0A,0xD3,0xAD,0x4F,0x5B,0x62,0x47,0xA7,0xFD,0xA8,0x6D,0xF6,0x97,0x90,0x19,0x67,0x73}; struct point { u8 x[20]; u8 y[20]; }; static uint8_t ec_p[20]; static uint8_t ec_a[20]; static uint8_t ec_b[20]; static point ec_G; static point ec_Q; static uint8_t ec_N[21]; #define MT_N 624 #define MT_M 397 #define MT_MATRIX_A 0x9908b0df #define MT_UPPER_MASK 0x80000000 #define MT_LOWER_MASK 0x7fffffff /*! Mersenne-Twister 19937 context. */ typedef struct _mt19937_ctxt { /*! State. */ unsigned int state[MT_N]; /*! Index. */ unsigned int idx; } mt19937_ctxt_t; void mt19937_init(mt19937_ctxt_t *ctxt, unsigned int seed) { ctxt->state[0] = seed; for(ctxt->idx = 1; ctxt->idx < MT_N; ctxt->idx++) ctxt->state[ctxt->idx] = (1812433253 * (ctxt->state[ctxt->idx - 1] ^ (ctxt->state[ctxt->idx - 1] >> 30)) + ctxt->idx); ctxt->idx = MT_M + 1; } unsigned int mt19937_update(mt19937_ctxt_t *ctxt) { unsigned int y, k; static unsigned int mag01[2] = {0, MT_MATRIX_A}; if(ctxt->idx >= MT_N) { for(k = 0; k < MT_N - MT_M; k++) { y = (ctxt->state[k] & MT_UPPER_MASK) | (ctxt->state[k + 1] & MT_LOWER_MASK); ctxt->state[k] = ctxt->state[k + MT_M] ^ (y >> 1) ^ mag01[y & 1]; } for(; k < MT_N - 1; k++) { y = (ctxt->state[k] & MT_UPPER_MASK) | (ctxt->state[k + 1] & MT_LOWER_MASK); ctxt->state[k] = ctxt->state[k + (MT_M - MT_N)] ^ (y >> 1) ^ mag01[y & 1]; } y = (ctxt->state[MT_N - 1] & MT_UPPER_MASK) | (ctxt->state[0] & MT_LOWER_MASK); ctxt->state[MT_N - 1] = ctxt->state[MT_M - 1] ^ (y >> 1) ^ mag01[y & 1]; ctxt->idx = 0; } y = ctxt->state[ctxt->idx++]; y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } static mt19937_ctxt_t _mt19937_ctxt; static BOOL _mt_init = FALSE; u8 _get_rand_byte() { if(_mt_init == FALSE) { _mt_init = TRUE; mt19937_init(&_mt19937_ctxt, clock()); } return (u8)(mt19937_update(&_mt19937_ctxt) & 0xFF); } void _fill_rand_bytes(u8 *dst, u32 len) { u32 i; for(i = 0; i < len; i++) dst[i] = _get_rand_byte(); } static void memcpy_inv(u8 *dst, u8 *src, u32 len) { u32 j; for (j = 0; j < len; j++) dst[j] = ~src[j]; } void bn_print(char *name, u8 *a, u32 n) { u32 i; printf("%s = ", name); for (i = 0; i < n; i++) printf("%02x", a[i]); printf("\n"); } static void bn_zero(u8 *d, u32 n) { memset(d, 0, n); } void bn_copy(u8 *d, u8 *a, u32 n) { memcpy(d, a, n); } int bn_compare(u8 *a, u8 *b, u32 n) { u32 i; for (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, u8 *a, u8 *b, u32 n) { u32 i; u32 dig; u8 c; c = 0; for (i = n - 1; i < n; i--) { dig = a[i] + b[i] + c; c = dig >> 8; d[i] = dig; } return c; } static u8 bn_sub_1(u8 *d, u8 *a, u8 *b, u32 n) { u32 i; u32 dig; u8 c; c = 1; for (i = n - 1; i < n; i--) { dig = a[i] + 255 - b[i] + c; c = dig >> 8; d[i] = dig; } return 1 - c; } void bn_reduce(u8 *d, u8 *N, u32 n) { if (bn_compare(d, N, n) >= 0) bn_sub_1(d, d, N, n); } void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) { if (bn_add_1(d, a, b, n)) bn_sub_1(d, d, N, n); bn_reduce(d, N, n); } void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) { if (bn_sub_1(d, a, b, n)) bn_add_1(d, d, N, n); } static const 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, u8 *a, u8 b, u8 *N, u32 n) { u32 dig; u32 i; u8 z = -(d[n-1] + a[n-1]*b) * inv256[N[n-1]/2]; dig = d[n-1] + a[n-1]*b + N[n-1]*z; dig >>= 8; for (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); } void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) { u8 t[512]; u32 i; bn_zero(t, n); for (i = n - 1; i < n; i--) bn_mon_muladd_dig(t, a, b[i], N, n); bn_copy(d, t, n); } void bn_to_mon(u8 *d, u8 *N, u32 n) { u32 i; for (i = 0; i < 8*n; i++) bn_add(d, d, d, N, n); } void bn_from_mon(u8 *d, u8 *N, u32 n) { u8 t[512]; bn_zero(t, n); t[n-1] = 1; bn_mon_mul(d, d, t, N, n); } static void bn_mon_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en) { u8 t[512]; u32 i; u8 mask; bn_zero(d, n); d[n-1] = 1; bn_to_mon(d, N, n); for (i = 0; i < en; i++) for (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 bn_copy(d, t, n); } } static void elt_copy(u8 *d, u8 *a) { memcpy(d, a, 20); } static void elt_zero(u8 *d) { memset(d, 0, 20); } static int elt_is_zero(u8 *d) { u32 i; for (i = 0; i < 20; i++) if (d[i] != 0) return 0; return 1; } static void elt_add(u8 *d, u8 *a, u8 *b) { bn_add(d, a, b, ec_p, 20); } static void elt_sub(u8 *d, u8 *a, u8 *b) { bn_sub(d, a, b, ec_p, 20); } static void elt_mul(u8 *d, u8 *a, u8 *b) { bn_mon_mul(d, a, b, ec_p, 20); } static void elt_square(u8 *d, u8 *a) { elt_mul(d, a, a); } void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n) { u8 t[512], s[512]; bn_zero(s, n); s[n-1] = 2; bn_sub_1(t, N, s, n); bn_mon_exp(d, a, N, n, t, n); } static void elt_inv(u8 *d, u8 *a) { u8 s[20]; elt_copy(s, a); bn_mon_inv(d, s, ec_p, 20); } static void point_to_mon(struct point *p) { bn_to_mon(p->x, ec_p, 20); bn_to_mon(p->y, ec_p, 20); } static void point_from_mon(struct point *p) { bn_from_mon(p->x, ec_p, 20); bn_from_mon(p->y, ec_p, 20); } static void point_zero(struct point *p) { elt_zero(p->x); elt_zero(p->y); } static int point_is_zero(struct point *p) { return elt_is_zero(p->x) && elt_is_zero(p->y); } static void point_double(struct point *r, struct point *p) { u8 s[20], t[20]; struct point pp; u8 *px, *py, *rx, *ry; pp = *p; px = pp.x; py = pp.y; rx = r->x; 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(struct point *r, struct point *p, struct point *q) { u8 s[20], t[20], u[20]; u8 *px, *py, *qx, *qy, *rx, *ry; struct point pp, qq; pp = *p; qq = *q; px = pp.x; py = pp.y; qx = qq.x; qy = qq.y; rx = r->x; ry = r->y; if (point_is_zero(&pp)) { elt_copy(rx, qx); elt_copy(ry, qy); return; } if (point_is_zero(&qq)) { elt_copy(rx, px); elt_copy(ry, py); 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(struct point *d, u8 *a, struct point *b) // a is bignum { u32 i; u8 mask; point_zero(d); for (i = 0; i < 21; i++) for (mask = 0x80; mask != 0; mask >>= 1) { point_double(d, d); if ((a[i] & mask) != 0) point_add(d, d, b); } } static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash) { u8 e[21]; u8 kk[21]; u8 m[21]; u8 minv[21]; struct point mG; e[0] = 0; memcpy(e + 1, hash, 20); bn_reduce(e, ec_N, 21); try_again: _fill_rand_bytes(m, 21); m[0] = 0; if (bn_compare(m, ec_N, 21) >= 0) goto try_again; // R = (mG).x point_mul(&mG, m, &ec_G); point_from_mon(&mG); R[0] = 0; elt_copy(R+1, mG.x); // S = m**-1*(e + Rk) (mod N) bn_copy(kk, k, 21); bn_reduce(kk, ec_N, 21); bn_to_mon(m, ec_N, 21); bn_to_mon(e, ec_N, 21); bn_to_mon(R, ec_N, 21); bn_to_mon(kk, ec_N, 21); bn_mon_mul(S, R, kk, ec_N, 21); bn_add(kk, S, e, ec_N, 21); bn_mon_inv(minv, m, ec_N, 21); bn_mon_mul(S, minv, kk, ec_N, 21); bn_from_mon(R, ec_N, 21); bn_from_mon(S, ec_N, 21); } int set_vsh_curve(u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy) { memcpy(p,p_fixed, 20); memcpy(a, a_fixed, 20); memcpy(b, b_fixed, 20); memcpy(N, n_fixed, 21); memcpy(Gx, gx_fixed, 20); memcpy(Gy, gy_fixed, 20); return 0; } int ecdsa_set_curve() { set_vsh_curve(ec_p, ec_a, ec_b, ec_N, ec_G.x, ec_G.y); bn_to_mon(ec_a, ec_p, 20); bn_to_mon(ec_b, ec_p, 20); point_to_mon(&ec_G); return 0; } void ecdsa_set_pub() { memcpy(ec_Q.x, ec_Q_nm,20); memcpy(ec_Q.y, ec_Q_nm+20,20); point_to_mon(&ec_Q); } void ecdsa_set_priv() { //ec_k already set } static int check_ecdsa(struct point *Q, u8 *R, u8 *S, 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_sign(u8 *hash, u8 *R, u8 *S) { generate_ecdsa(R, S, ec_k, hash); } //! Byte swap unsigned short uint16_t swap_uint16( uint16_t val ) { return (val << 8) | (val >> 8 ); } //! Byte swap short int16_t swap_int16( int16_t val ) { return (val << 8) | ((val >> 8) & 0xFF); } //! Byte swap unsigned int uint32_t swap_uint32( uint32_t val ) { val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); return (val << 16) | (val >> 16); } //! Byte swap int int32_t swap_int32( int32_t val ) { val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF ); return (val << 16) | ((val >> 16) & 0xFFFF); } int64_t swap_int64( int64_t val ) { val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL); } uint64_t swap_uint64( uint64_t val ) { val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); return (val << 32) | (val >> 32); } long long current_timestamp() { struct timeval te; gettimeofday(&te, NULL); // get current time long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds // printf("milliseconds: %lld\n", milliseconds); return milliseconds; } FILE *forge_act_dat() { uint64_t timestamp=current_timestamp(); //today uint32_t version=1; version=swap_uint32(version); uint32_t unk=2; unk=swap_uint32(unk); uint64_t psn_id=2; psn_id=swap_uint64(psn_id); timestamp=swap_uint64(timestamp); FILE *fp=fopen("act.dat","wb"); uint8_t *act_dat=new uint8_t[0x1038]; memset(act_dat,0x11, 0x1038); memcpy(act_dat, &version, 4); memcpy(act_dat+4, &unk,4); memcpy(act_dat+8, &psn_id, 8); memcpy(act_dat+0x870, ×tamp, 8); fwrite(act_dat, 0x1038,1,fp); fclose(fp); return fp=fopen("act.dat", "rb"); } int read_act_dat_and_make_rif(char *path) { char *content_id=(char *)malloc(256); memset(content_id,0,256); strcpy(content_id, path); char *slash2 = strrchr (content_id, '\\'); if (slash2 != NULL) { *slash2 = '\0'; content_id=slash2+1; } char *slash_rev = strrchr (content_id, '/'); if (slash_rev != NULL) { *slash_rev = '\0'; content_id=slash_rev+1; } char *lastdot = strrchr (content_id, '.'); if (lastdot != NULL) *lastdot = '\0'; uint8_t idps[0x10]; aes_context aes_ctxt; uint8_t idps_const[0x10]={0x5E,0x06,0xE0,0x4F,0xD9,0x4A,0x71,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; uint8_t rif_key_const[0x10]={0xDA,0x7D,0x4B,0x5E,0x49,0x9A,0x4F,0x53,0xB1,0xC1,0xA1,0x4A,0x74,0x84,0x44,0x3B}; printf("reading:idps.hex\n"); FILE *fp=fopen("idps.hex", "rb"); if(!fp) { return -1; } fread(idps, 0x10, 1, fp); fclose(fp); uint8_t act_dat_key[0x10]; uint8_t klicensee[0x10]; uint8_t klicensee_enc_rif[0x10]; uint8_t rap[0x10]; uint64_t account_id; //uint8_t rifkey[0x10]; fp=fopen("act.dat","rb"); if(!fp) { // fp=forge_act_dat(); return -1; } printf("reading:act.dat\n"); fseek(fp,0x8,SEEK_SET); fread(&account_id, 8,1,fp);//skip aa account need fseek(fp,0x10,SEEK_SET); fread(act_dat_key, 0x10,1,fp); //copy first key in primary table of act.dat fclose(fp); printf("reading:%s\n", path); fp=fopen(path, "rb"); if(!fp) { return -1; } fread(rap, 0x10,1,fp); fclose(fp); uint8_t *rif=(uint8_t *)malloc(0x200); memset(rif,0,0x200); get_rif_key(rap, rif+0x50); //convert rap to rifkey(klicensee) aes_setkey_enc(&aes_ctxt, idps, IDPS_KEYBITS); aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, idps_const, idps_const); aes_setkey_dec(&aes_ctxt, idps_const, IDPS_KEYBITS); aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, act_dat_key, act_dat_key); aes_setkey_enc(&aes_ctxt, act_dat_key, ACT_DAT_KEYBITS); aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, rif+0x50, rif+0x50);//encrypt rif with act.dat first key primary key table uint8_t index_act_key[4]={0};//very first key in act.dat primary table uint8_t index_act_key_enc[0x10]; aes_setkey_enc(&aes_ctxt, rif_key_const, RIF_KEYBITS); aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, rif+0x40, rif+0x40); uint64_t timestamp=current_timestamp(); //today timestamp=swap_uint64(timestamp); uint32_t version_number=1; version_number=swap_uint32(version_number); uint32_t license_type=0x00010002; license_type=swap_uint32(license_type); uint64_t expiration_time=0; expiration_time=swap_uint64(expiration_time); memcpy(rif, &version_number,4); memcpy(rif+4, &license_type,4); memcpy(rif+8,&account_id,8); memcpy(rif+0x10, content_id, 0x24); // memcpy(rif+0x40, index_act_key_enc, 0x10); // memcpy(rif+0x50, klicensee_enc_rif,0x10); memcpy(rif+0x60, ×tamp, 8); memcpy(rif+0x68, &expiration_time,8); uint8_t sha1_digest[20]; sha1(rif, 0x70,sha1_digest); ecdsa_set_curve(); ecdsa_set_pub(); ecdsa_set_priv(); uint8_t R[0x15]; uint8_t S[0x15]; ecdsa_sign(sha1_digest, R, S); memcpy(rif+0x70, R+1, 0x14); memcpy(rif+0x70+0x14, S+1, 0x14); sha1(rif, 0xa0,sha1_digest); memcpy(rif+0xa0, sha1_digest,0x10); memcpy(rif+0xb0, sha1_digest,0x10); memset(rif+0xc0, 0, 0x40); _fill_rand_bytes(rif+0x100, 0x100); strcpy(path+strlen(path)-4, ".rif"); printf("writing:%s\n", path); fp=fopen(path, "wb"); fwrite(rif, 0x98,1,fp); //only needed till here fclose(fp); return 0; } int read_rif_key(char *content_id, uint8_t *rifkey) { uint8_t idps[0x10]; aes_context aes_ctxt; uint8_t idps_const[0x10]={0x5E,0x06,0xE0,0x4F,0xD9,0x4A,0x71,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; uint8_t rif_key_const[0x10]={0xDA,0x7D,0x4B,0x5E,0x49,0x9A,0x4F,0x53,0xB1,0xC1,0xA1,0x4A,0x74,0x84,0x44,0x3B}; printf("reading:idps.hex\n"); FILE *fp=fopen("idps.hex", "rb"); if(!fp) { return -1; } fread(idps, 0x10, 1, fp); fclose(fp); uint8_t act_dat_key[0x10]; uint8_t klicensee[0x10]; uint8_t klicensee_enc_rif[0x10]; uint8_t rap[0x10]; fp=fopen("act.dat","rb"); if(!fp) { return -1; } printf("reading:act.dat\n"); fseek(fp,0x8,SEEK_SET); fseek(fp,0x10,SEEK_SET); fread(act_dat_key, 0x10,1,fp); //copy first key in primary table of act.dat fclose(fp); char rap_path[0x80]; strcpy(rap_path, content_id); strcat(rap_path, ".rap"); printf("reading:%s\n", rap_path); fp=fopen(rap_path, "rb"); if(!fp) { return -1; } fread(rap, 0x10,1,fp); fclose(fp); uint8_t *rif=(uint8_t *)malloc(0x200); memset(rif,0,0x200); get_rif_key(rap, rifkey); //convert rap to rifkey(klicensee) return 0; } u8 ps2_iv[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int sign_act_dat() { uint8_t *act_dat_buf=(uint8_t *)malloc(0x2000); printf("reading:act.dat\n"); FILE *fp=fopen("act.dat","rb"); fread(act_dat_buf, 0x1038,1,fp); fclose(fp); uint8_t digest[20]; sha1(act_dat_buf, 0x1010, digest); uint8_t R[0x15]; uint8_t S[0x15]; ecdsa_sign(digest, R,S); memcpy(act_dat_buf+0x1010, R+1, 0x14); memcpy(act_dat_buf+0x1010+0x14, S+1, 0x14); printf("writing:signed_act.dat\n"); fp=fopen("signed_act.dat","wb"); fwrite(act_dat_buf, 0x1038,1,fp); fclose(fp); return 0; } static void set_ps2_iv(u8 iv[]) { memcpy(iv, ps2_iv, 0x10); } static inline u32 be32(u8 *p) { u32 a; a = p[0] << 24; a |= p[1] << 16; a |= p[2] << 8; a |= p[3] << 0; return a; } static inline u32 le32(u8 *p) { u32 a; a = p[3] << 24; a |= p[2] << 16; a |= p[1] << 8; a |= p[0] << 0; return a; } static inline u64 be64(u8 *p) { u32 a, b; a = be32(p); b = be32(p + 4); return ((u64)a<<32) | b; } void dump_meta(char mode[], FILE *in, char meta_file[], uint8_t *klicensee) { #define PS2_META_SEGMENT_START 1 #define PS2_DATA_SEGMENT_START 2 #define PS2_DEFAULT_SEGMENT_SIZE 0x4000 #define PS2_META_ENTRY_SIZE 0x20 u8 ps2_key_cex_meta[] = { 0x38, 0x9D, 0xCB, 0xA5, 0x20, 0x3C, 0x81, 0x59, 0xEC, 0xF9, 0x4C, 0x93, 0x93, 0x16, 0x4C, 0xC9 }; u8 ps2_key_cex_data[] = { 0x10, 0x17, 0x82, 0x34, 0x63, 0xF4, 0x68, 0xC1, 0xAA, 0x41, 0xD7, 0x00, 0xB1, 0x40, 0xF2, 0x57 }; u8 ps2_key_cex_vmc[] = { 0x64, 0xE3, 0x0D, 0x19, 0xA1, 0x69, 0x41, 0xD6, 0x77, 0xE3, 0x2E, 0xEB, 0xE0, 0x7F, 0x45, 0xD2 }; FILE * meta_out; u8 ps2_key_dex_meta[] = { 0x2B, 0x05, 0xF7, 0xC7, 0xAF, 0xD1, 0xB1, 0x69, 0xD6, 0x25, 0x86, 0x50, 0x3A, 0xEA, 0x97, 0x98 }; u8 ps2_key_dex_data[] = { 0x74, 0xFF, 0x7E, 0x5D, 0x1D, 0x7B, 0x96, 0x94, 0x3B, 0xEF, 0xDC, 0xFA, 0x81, 0xFC, 0x20, 0x07 }; u8 ps2_key_dex_vmc[] = { 0x30, 0x47, 0x9D, 0x4B, 0x80, 0xE8, 0x9E, 0x2B, 0x59, 0xE5, 0xC9, 0x14, 0x5E, 0x10, 0x64, 0xA9 }; u8 ps2_data_key[0x10]; u8 ps2_meta_key[0x10]; u8 iv[0x10]; int segment_size; s64 data_size; int i; u8 header[256]; u8 * data_buffer; u8 * meta_buffer; u32 read = 0; int num_child_segments; //open files meta_out = fopen(meta_file, "wb"); //get file info read = fread(header, 256, 1, in); segment_size = be32(header + 0x84); data_size = be64(header + 0x88); num_child_segments = segment_size / PS2_META_ENTRY_SIZE; printf("segment size: %x\ndata_size: %llx\n\n", segment_size, data_size); //alloc buffers data_buffer = (u8 *)malloc(segment_size*num_child_segments); meta_buffer = (u8 *)malloc(segment_size); //generate keys if(strcmp(mode, "cex") == 0) { printf("cex\n"); set_ps2_iv(iv); aescbc128_encrypt(ps2_key_cex_data, iv, klicensee, ps2_data_key, 0x10); aescbc128_encrypt(ps2_key_cex_meta, iv, klicensee, ps2_meta_key, 0x10); }else{ printf("dex\n"); set_ps2_iv(iv); aescbc128_encrypt(ps2_key_dex_data, iv, klicensee, ps2_data_key, 0x10); aescbc128_encrypt(ps2_key_dex_meta, iv, klicensee, ps2_meta_key, 0x10); } //decrypt iso fseek(in, segment_size, SEEK_SET); while(read = fread(meta_buffer, 1, segment_size, in)) { //decrypt meta aescbc128_decrypt(ps2_meta_key, iv, meta_buffer, meta_buffer, read); fwrite(meta_buffer, read, 1, meta_out); read = fread(data_buffer, 1, segment_size*num_child_segments, in); } //cleanup free(data_buffer); free(meta_buffer); fclose(meta_out); fseek(in, 0, SEEK_SET); } int sign_enc(FILE *fp) { uint8_t *buf=(uint8_t *)malloc(0x200); memset(buf,0,0x200); fread(buf, 0x100,1,fp); uint8_t R[0x15]; uint8_t S[0x15]; uint8_t digest[20]; sha1(buf, 0xd8, digest); ecdsa_sign(digest,R,S); fseek(fp, 0xD8, SEEK_SET); fwrite(R+1, 0x14,1,fp); fwrite(S+1,0x14,1,fp); return 0; } static inline void wbe32(u8 *p, u32 v) { p[0] = v >> 24; p[1] = v >> 16; p[2] = v >> 8; p[3] = v; } static inline void wbe64(u8 *p, u64 v) { wbe32(p + 4, v); v >>= 32; wbe32(p, v); } #include #include "pkg2zip_aes_x86.h" static void decrypt_debug_pkg_normal(uint8_t *pkg, uint64_t size, uint64_t offset, int file, uint64_t len) { u8 key[0x40]; u8 bfr[0x1c]; u64 i; memset(key, 0, sizeof key); memcpy(key, pkg + 0x60, 8); memcpy(key + 0x08, pkg + 0x60, 8); memcpy(key + 0x10, pkg + 0x60 + 0x08, 8); memcpy(key + 0x18, pkg + 0x60 + 0x08, 8); sha1(key, sizeof key, bfr); if(len>(10*1024*1024)) { munmap(pkg, 10*1024*1024); } else { munmap(pkg, len); } if(len>(100*1024*1024)) { pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); } else { pkg=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); } uint32_t last_round_size=len; uint64_t count=offset; lseek(file, 0, SEEK_SET); for (i = offset; i < (size+offset); i++, count++) { if (i != offset && (i % 16) == 0) { wbe64(key + 0x38, be64(key + 0x38) + 1); sha1(key, sizeof key, bfr); } if(i%(100*1024*1024)==0) { write(file, pkg, 100*1024*1024); munmap(pkg, 100*1024*1024); lseek(file, i, SEEK_SET); if((size+offset-i)>(100*1024*1024)) { pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); } else { pkg=(uint8_t *)mmap(0, (size+offset-i), PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); lseek(file, i, SEEK_SET); last_round_size=(size+offset-i); } count=0; } pkg[count] ^= bfr[i & 0xf]; } write(file, pkg, last_round_size); munmap(pkg, last_round_size); } static void decrypt_debug_pkg_sse(uint8_t *pkg, uint64_t size, uint64_t offset, int file, uint64_t len) { u8 key[0x40]; u8 bfr[0x1c]; u64 i; u64 ret=0; uint32_t last_round_size=len; memset(key, 0, sizeof key); memcpy(key, pkg + 0x60, 8); memcpy(key + 0x08, pkg + 0x60, 8); memcpy(key + 0x10, pkg + 0x60 + 0x08, 8); memcpy(key + 0x18, pkg + 0x60 + 0x08, 8); SHA1(key, sizeof key, bfr); if(len>(10*1024*1024)) { munmap(pkg, 10*1024*1024); } else { munmap(pkg, len); } if(len>(100*1024*1024)) { pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); } else { pkg=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); } xor1_sse(pkg+offset,pkg+offset,bfr, 0x10); lseek(file, 0, SEEK_SET); uint64_t count=offset+0x10; #pragma unroll for (i = (0x10+offset); i < (size+offset); i+=0x10, count+=0x10) { wbe64(key + 0x38, be64(key + 0x38) + 1); SHA1(key, sizeof key, bfr); if(i%(100*1024*1024)==0) { write(file, pkg, 100*1024*1024); munmap(pkg, 100*1024*1024); lseek(file, i, SEEK_SET); if((size+offset-i)>(100*1024*1024)) { pkg=(uint8_t *)mmap(0, 100*1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); } else { pkg=(uint8_t *)mmap(0, (size+offset-i), PROT_READ | PROT_WRITE, MAP_PRIVATE, file, i); lseek(file, i, SEEK_SET); last_round_size=(size+offset-i); } count=0; } xor1_sse(pkg+count,pkg+count,bfr, 0x10); } write(file, pkg, last_round_size); munmap(pkg, last_round_size); } static void decrypt_debug_pkg(uint8_t *pkg, uint64_t size, uint64_t offset_data, int file, uint64_t len) { if(aes128_supported_x86()) { decrypt_debug_pkg_sse(pkg,size,offset_data, file, len); } else { decrypt_debug_pkg_normal(pkg,size,offset_data, file, len); } } int decrypt_retail_pkg_data(uint8_t *buf, uint64_t size, uint8_t *data_riv, uint8_t *gpkg_key) { aes128ctr(gpkg_key, data_riv, buf, size, buf); return 0; } static void check_ps2_pkg_patch(uint8_t *pkg, uint64_t offset, int fd) { u64 i; u64 n_files; u32 fname_len; u32 fname_off; u64 file_offset; u32 flags; char fname[256]; u8 *tmp; u8 tmp_buf[0x100]; uint8_t digest[20]; uint8_t R[0x15]; uint8_t S[0x15]; u8 magic_ps2[4]={'P','S','2',0x00}; u8 magic_edat[4]={'N','P','D',0x00}; n_files = be32(pkg + 0x14); for (i = 0; i < n_files; i++) { tmp = pkg + offset + i*0x20; fname_off = be32(tmp) + offset; fname_len = be32(tmp + 0x04); file_offset = be64(tmp + 0x08) + offset; uint64_t size = be64(tmp + 0x10); flags = be32(tmp + 0x18); if (fname_len >= sizeof fname) printf("filename too long: %s\n", pkg + fname_off); memset(fname, 0, sizeof fname); memset(tmp_buf, 0, sizeof tmp_buf); strncpy(fname, (char *)(pkg + fname_off), fname_len); flags &= 0xff; printf("%s\n", fname); char *last_slash=strrchr(fname, '/'); if(!last_slash) //we are in root of pkg { continue; } if((strstr(last_slash, ".edat")) || (strstr(last_slash, ".EDAT")) || (strstr(last_slash, "CONFIG")) || (strstr(last_slash, "ISO.BIN.ENC"))) { if(flags != 4) //it is not a directory { printf("found %s..Resigning\n", last_slash); //sign_enc_buf(pkg+file_offset); lseek(fd,file_offset+0x00, SEEK_SET); read(fd, tmp_buf, 0x100); if((memcmp(tmp_buf, magic_ps2, 4)==0) || (memcmp(tmp_buf, magic_edat,4)==0)) //it is indeed a ps2 file or edat { sha1(tmp_buf, 0xd8, digest); ecdsa_sign(digest, R, S); lseek(fd,file_offset+0xd8, SEEK_SET); write(fd, R+1, 0x14); lseek(fd,file_offset+0xd8+0x14, SEEK_SET); write(fd, S+1, 0x14); } } } } } typedef struct __TOC_HEADER { uint32_t fname_offset; uint32_t name_size; uint64_t file_off; uint64_t file_size; uint8_t psp_key_type; uint8_t shit_stuff[7]; } TOC_HEADER; int parse_psp_pkg(uint8_t *pkg, uint32_t toc_len, uint8_t *iv_const, uint32_t data_size, int file_out, uint64_t offset_data) { TOC_HEADER *header=(TOC_HEADER *)malloc(2*1024*1024); uint8_t pkg_key[0x10]={0x2E,0x7B,0x71,0xD7,0xC9,0xC9,0xA1,0x4E,0xA3,0x22,0x1F,0x18,0x88,0x28,0xB8,0xF8}; uint8_t pkg_key_psp[0x10]={0x07,0xF2,0xC6,0x82,0x90,0xB5,0x0D,0x2C,0x33,0x81,0x8D,0x70,0x9B,0x60,0xE6,0x2B}; aes128_key ps3_key; aes128_init(&ps3_key, pkg_key); memcpy(header, pkg, toc_len); int i=0; int number_files=toc_len/0x20; uint8_t main_key[0x10]; uint32_t len_dec_name=0; uint8_t second_last; uint8_t *tmp_buf=(uint8_t *)malloc(100*1024*1024); uint8_t name[4096]={0}; for(i=0;i0x10) { len_dec_name=0x20; } else if(header[i].name_size>0x20) { len_dec_name=0x30; } else { len_dec_name=0x10; } printf("len_dec_name=%x\n", len_dec_name); printf("header[i].fname_offset=%x\n", header[i].fname_offset); printf("header[i].file_off=%x\n", header[i].file_off); printf("header[i].file_size=%x\n", header[i].file_size); printf("number_files=%x\n", number_files); int loop=0; printf("key: "); for (loop = 0; loop < 0x10; loop++) { printf("%02X", main_key[loop]); } printf("\n"); loop=0; printf("iv: "); for (loop = 0; loop < 0x10; loop++) { printf("%02X", iv_const[loop]); } printf("\n"); // aes128ctrxor(main_key, iv_const, pkg+header[i].fname_offset, len_dec_name, pkg+header[i].fname_offset,header[i].fname_offset-toc_len); aes128_ctr_xor(&key, iv_const, ((header[i].fname_offset)-toc_len)/16, pkg+header[i].fname_offset, len_dec_name); aes128_ctr_xor(&key, iv_const, ((header[i].file_off)-toc_len)/16, pkg+header[i].file_off, header[i].file_size); // aes128ctrxor(main_key, iv_const, pkg+header[i].file_off, header[i].file_size, pkg+header[i].file_off,header[i].file_off-toc_len); } return 0; } int main(int argc, char *argv[]) { printf("----------------PS3XPLOIT RESIGNER v3----------------\nHAN v3 tools brought you by W, escortd3w, bguerville, habib\nSpecial thanks to Joonie for testing this tool\n-----------------------------------------------------\n"); if(argc<2) { goto done; } if((strstr(argv[1], ".rap")) || (strstr(argv[1], ".RAP"))) { if(read_act_dat_and_make_rif(argv[1])==0) { sign_act_dat(); printf("\nits done!\npress enter\n"); } else { printf("\nverify your files!"); } getchar(); getchar(); return 0; } else if((strstr(argv[1], ".EDAT")) || (strstr(argv[1], ".edat"))) { char *slash2 = strrchr (argv[1], '\\'); if (slash2 != NULL) { *slash2 = '\0'; argv[1]=slash2+1; } FILE *fp=fopen(argv[1], "rb+"); if(!fp) { printf("edat unreadable!\n"); } uint32_t license; char *content_id_edat=(char *)malloc(0x100); memset(content_id_edat,0,0x100); fread(content_id_edat, 0x34, 1,fp); memcpy(&license, content_id_edat+8, 4); license=swap_uint32(license); content_id_edat+=0x10; uint8_t rifkey[0x10]; /*OLD METHOD!!!!!*/ /* if((license==2) || (license==3)) { read_rif_key(content_id_edat, rifkey); } uint8_t meta_sig_hash_output[20]; uint8_t header_sig_hash_output[20]; unsigned char devklic_edat[16] = {0x52,0xC0,0xB5,0xCA,0x76,0xD6,0x13,0x4B,0xB4,0x5F,0xC6,0x6C,0xA6,0x37,0xF2,0xC1}; FILE *devklic_explicit=fopen("devklic", "rb"); if(devklic_explicit) { printf("using explicit devklic\n"); fread(devklic_edat, 16, 1, devklic_explicit); fclose(devklic_explicit); } if(extract_data_and_sign(fp, devklic_edat, rifkey, 0)) { getchar(); return -1; } */ /*END*/ /* NEW METHOD!!!!!!!!*/ ecdsa_set_curve(); ecdsa_set_pub(); ecdsa_set_priv(); fseek(fp,0,SEEK_SET); sign_enc(fp); /*END*/ fclose(fp); printf("edat resigned!\n"); fp=fopen("ISO.BIN.ENC", "rb+"); if(fp) { // dump_meta((char *)"cex", fp, (char *)"ISO.BIN.ENC_meta_out", rifkey); sign_enc(fp); printf("enc resigned!\n"); fclose(fp); fp=fopen("CONFIG", "rb+"); if(fp) { sign_enc(fp); printf("config resigned!\n"); fclose(fp); } } getchar(); getchar(); return 0; } else if((strstr(argv[1], ".pkg")) || (strstr(argv[1], ".PKG"))) { ecdsa_set_curve(); ecdsa_set_pub(); ecdsa_set_priv(); struct stat stat1; if(stat(argv[1], &stat1)!=0) { printf("cant open file!\n"); getchar(); return -1; } uint64_t len=stat1.st_size; printf("size:%016llx\n", len); int fd=open(argv[1], O_RDONLY); uint8_t *buf2=NULL; char out_path[4096]; strcpy(out_path, argv[1]); strcat(out_path, "_signed.pkg"); int fd_out=open(out_path, O_RDWR|O_CREAT, 0600); lseek(fd_out, 0, SEEK_SET); printf("making backup\n"); uint64_t bkp=0; for(bkp;bkp(10*1024*1024)) { buf=(uint8_t *)mmap(0, 10*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); } else { buf=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); } if(!buf) { printf("not enough free memory!\n"); return -1; } uint64_t data_size=*(uint64_t *)(buf+0x28); uint8_t iv[0x10]; uint64_t offset_data=*(uint64_t *)(buf+0x20); offset_data=swap_uint64(offset_data); uint32_t pkg_info_offset=*(uint32_t *)(buf+0x8); pkg_info_offset=swap_uint32(pkg_info_offset); uint32_t header_size=*(uint32_t *)(buf+0x10); header_size=swap_uint32(header_size); uint32_t toc_size=(swap_uint32(*(uint32_t *)(buf+0x14)))*0x20; uint32_t pkg_type=*(uint32_t *)(buf+pkg_info_offset+0x14); pkg_type=swap_uint32(pkg_type); memcpy(iv, buf+0x70, 0x10); uint8_t iv_bkp[0x10]; memcpy(iv_bkp, iv, 0x10); data_size=swap_uint64(data_size); uint8_t pkg_key[0x10]={0x2E,0x7B,0x71,0xD7,0xC9,0xC9,0xA1,0x4E,0xA3,0x22,0x1F,0x18,0x88,0x28,0xB8,0xF8}; uint8_t pkg_key_psp[0x10]={0x07,0xF2,0xC6,0x82,0x90,0xB5,0x0D,0x2C,0x33,0x81,0x8D,0x70,0x9B,0x60,0xE6,0x2B}; if(*(uint8_t *)&buf[4]!=0x80) { *(uint8_t *)&buf[4]=0x80; uint8_t retail_flag=0x80; if((pkg_type==0xf) || (pkg_type==0x6) || (pkg_type==0x7)) //0xf==minis, 0x6==ps1, 0x7==psp, 0x14==remastered { printf("PKG type PSP/PSX detected\n"); *(uint8_t *)&buf[7]=2; } printf("decrypting debug pkg\n"); decrypt_debug_pkg(buf, data_size, offset_data, fd_out, len); if(len>(10*1024*1024)) { buf=(uint8_t *)mmap(0, 10*1024*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); } else { buf=(uint8_t *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0); } printf("encrypting retail pkg\n"); check_ps2_pkg_patch(buf, offset_data, fd_out); if(*(uint8_t *)&buf[7]==2) { memcpy(iv, iv_bkp, 0x10); parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); memcpy(iv, iv_bkp, 0x10); decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key_psp); memcpy(iv, iv_bkp, 0x10); } else { memcpy(iv, iv_bkp, 0x10); parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); memcpy(iv, iv_bkp, 0x10); decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key); } cmac_hash_forge(pkg_key, 0x10, buf, 0x80, buf+0x80); } else { printf("decrypting retail pkg\n"); if(*(uint8_t *)&buf[7]==2) { printf("type psp detected\n"); decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key_psp); memcpy(iv, iv_bkp, 0x10); parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); } else { memcpy(iv, iv_bkp, 0x10); decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key); memcpy(iv, iv_bkp, 0x10); parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); memcpy(iv, iv_bkp, 0x10); } printf("encrypting retail pkg\n"); check_ps2_pkg_patch(buf, offset_data, fd_out); if(*(uint8_t *)&buf[7]==2) { parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); memcpy(iv, iv_bkp,0x10); decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key_psp); } else { memcpy(iv, iv_bkp,0x10); parse_psp_pkg(buf+offset_data, toc_size, iv, data_size, fd_out, offset_data); memcpy(iv, iv_bkp,0x10); decrypt_retail_pkg_data(buf+offset_data, toc_size, iv, pkg_key); } cmac_hash_forge(pkg_key, 0x10, buf, 0x80, buf+0x80); } uint8_t digest[20]; uint8_t R[0x15]; uint8_t S[0x15]; cmac_hash_forge(pkg_key, 0x10, buf+pkg_info_offset, header_size-0x40, buf+pkg_info_offset+header_size-0x40); if(len>(10*1024*1024)) { munmap(buf, 10*1024*1024); } else { munmap(buf, len); } SHA_CTX ctx; SHA1_Init( &ctx ); uint64_t sha1_loop=0; for(sha1_loop;sha1_loop