├── pkg.cpp ├── pkg.h ├── aes_omac.h ├── ecdsa.h ├── frontend.h ├── ecdsa.cpp ├── list.h ├── np.h ├── mt19937.h ├── tables.h ├── aes_omac.cpp ├── spp.h ├── mt19937.cpp ├── util.h ├── self.h ├── types.h ├── config.h ├── spp.cpp ├── rvk.h ├── Makefile ├── keys.h ├── rvk.cpp ├── getopt.h ├── list.cpp ├── elf_inlines.h ├── sha1.h ├── bn.cpp ├── util.cpp ├── README ├── aes.h ├── sce_inlines.h ├── tables.cpp ├── np.cpp ├── ec.cpp ├── sha1.c ├── main.cpp ├── zconf.h ├── getopt.c ├── sce.h ├── frontend.cpp └── keys.cpp /pkg.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | -------------------------------------------------------------------------------- /pkg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _PKG_H_ 7 | #define _PKG_H_ 8 | 9 | #include "types.h" 10 | #include "sce.h" 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /aes_omac.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_OMAC_H_ 2 | #define _AES_OMAC_H_ 3 | 4 | #include "types.h" 5 | 6 | #define AES_OMAC1_DIGEST_SIZE 0x10 7 | 8 | void aes_omac1(u8 *digest, u8 *input, u32 length, u8 *key, u32 keybits); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /ecdsa.h: -------------------------------------------------------------------------------- 1 | #ifndef _ECDSA_H_ 2 | #define _ECDSA_H_ 3 | 4 | int ecdsa_set_curve(u32 type); 5 | void ecdsa_set_pub(u8 *Q); 6 | void ecdsa_set_priv(u8 *k); 7 | int ecdsa_verify(u8 *hash, u8 *R, u8 *S); 8 | void ecdsa_sign(u8 *hash, u8 *R, u8 *S); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /frontend.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | 7 | #ifndef _FRONTEND_H_ 8 | #define _FRONTEND_H_ 9 | 10 | void frontend_print_infos(s8 *file); 11 | void frontend_decrypt(s8 *file_in, s8 *file_out); 12 | void frontend_encrypt(s8 *file_in, s8 *file_out); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /ecdsa.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "keys.h" 3 | #include "ecdsa.h" 4 | #include "util.h" 5 | 6 | int ecdsa_get_params(u32 type, u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy) 7 | { 8 | curve_t *c; 9 | 10 | if(type & USE_VSH_CURVE) 11 | { 12 | //VSH curve. 13 | if((c = vsh_curve_find(type & ~USE_VSH_CURVE)) == NULL) 14 | return -1; 15 | } 16 | else 17 | { 18 | //Loader curve. 19 | if((c = curve_find(type)) == NULL) 20 | return -1; 21 | } 22 | 23 | _memcpy_inv(p, c->p, 20); 24 | _memcpy_inv(a, c->a, 20); 25 | _memcpy_inv(b, c->b, 20); 26 | _memcpy_inv(N, c->N, 21); 27 | _memcpy_inv(Gx, c->Gx, 20); 28 | _memcpy_inv(Gy, c->Gy, 20); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _LIST_H_ 7 | #define _LIST_H_ 8 | 9 | #include "types.h" 10 | 11 | #define LIST_FOREACH(iter, list) for(lnode_t *iter = list->head; iter != NULL; iter = iter->next) 12 | 13 | typedef struct _lnode 14 | { 15 | void *value; 16 | struct _lnode *next; 17 | } lnode_t; 18 | 19 | typedef struct _list 20 | { 21 | lnode_t *head; 22 | u32 count; 23 | } list_t; 24 | 25 | list_t *list_create(); 26 | void list_destroy(list_t *l); 27 | BOOL list_isempty(list_t *l); 28 | u32 list_count(list_t *l); 29 | BOOL list_push(list_t *l, void *value); 30 | void *list_pop(list_t *l); 31 | BOOL list_add_back(list_t *l, void *value); 32 | void *list_get(list_t *l, u32 idx); 33 | lnode_t *list_get_node(list_t *l, u32 idx); 34 | BOOL list_remove_node(list_t *l, lnode_t *node); 35 | BOOL list_remove_value(list_t *l, void *value); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /np.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _NP_H_ 7 | #define _NP_H_ 8 | 9 | #include "types.h" 10 | #include "sce.h" 11 | 12 | /*! NPDRM config. */ 13 | typedef struct _npdrm_config 14 | { 15 | /*! License type. */ 16 | u32 license_type; 17 | /*! Application type. */ 18 | u32 app_type; 19 | /*! klicensee. */ 20 | u8 *klicensee; 21 | /*! Content ID. */ 22 | u8 content_id[0x30]; 23 | /*! Real file name. */ 24 | s8 *real_fname; 25 | } npdrm_config_t; 26 | 27 | /*! Set klicensee. */ 28 | void np_set_klicensee(u8 *klicensee); 29 | 30 | /*! Remove NPDRM layer. */ 31 | BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt); 32 | 33 | /*! Add NPDRM layer. */ 34 | BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt); 35 | 36 | /*! Create NPDRM control info. */ 37 | BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp); 38 | 39 | /*! Add NP signature to file. */ 40 | BOOL np_sign_file(s8 *fname); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /mt19937.h: -------------------------------------------------------------------------------- 1 | //Mersenne-Twister 19937 pseudorandom number generator. 2 | //Reference implementation at: 3 | //http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c 4 | 5 | #ifndef _MT19937_H_ 6 | #define _MT19937_H_ 7 | 8 | /*! State size. */ 9 | #define MT_N 624 10 | #define MT_M 397 11 | #define MT_MATRIX_A 0x9908b0df 12 | #define MT_UPPER_MASK 0x80000000 13 | #define MT_LOWER_MASK 0x7fffffff 14 | 15 | /*! Mersenne-Twister 19937 context. */ 16 | typedef struct _mt19937_ctxt 17 | { 18 | /*! State. */ 19 | unsigned int state[MT_N]; 20 | /*! Index. */ 21 | unsigned int idx; 22 | } mt19937_ctxt_t; 23 | 24 | /*! 25 | * \brief Initialize Mersenne-Twister 19937 context. 26 | * 27 | * \param ctxt Mersenne-Twister 19937 context. 28 | * \param seed Random seed. 29 | */ 30 | void mt19937_init(mt19937_ctxt_t *ctxt, unsigned int seed); 31 | 32 | /*! 33 | * \brief Update Mersenne-Twister 19937 state. 34 | * 35 | * \param ctxt Mersenne-Twister 19937 context. 36 | * 37 | * \return Generated pseudorandom number. 38 | */ 39 | unsigned int mt19937_update(mt19937_ctxt_t *ctxt); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /tables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _TABLES_H_ 7 | #define _TABLES_H_ 8 | 9 | #include "types.h" 10 | #include "util.h" 11 | 12 | /*! SELF types. */ 13 | extern id_to_name_t _self_types[]; 14 | 15 | /*! SELF types as parameter. */ 16 | extern id_to_name_t _self_types_params[]; 17 | 18 | /* Control info types. */ 19 | extern id_to_name_t _control_info_types[]; 20 | 21 | /*! Optional header types. */ 22 | extern id_to_name_t _optional_header_types[]; 23 | 24 | /*! NPDRM application types. */ 25 | extern id_to_name_t _np_app_types[]; 26 | 27 | /*! Auth IDs. */ 28 | extern id_to_name_t _auth_ids[]; 29 | 30 | /*! Vendor IDs. */ 31 | extern id_to_name_t _vendor_ids[]; 32 | 33 | /*! ELF machines. */ 34 | extern id_to_name_t _e_machines[]; 35 | 36 | /*! ELF types. */ 37 | extern id_to_name_t _e_types[]; 38 | 39 | /*! Section header types. */ 40 | extern id_to_name_t _sh_types[]; 41 | 42 | /*! Program header types. */ 43 | extern id_to_name_t _ph_types[]; 44 | 45 | /*! Key types. */ 46 | extern id_to_name_t _key_types[]; 47 | 48 | /*! Key revisions. */ 49 | //extern const s8 *_key_revisions[]; 50 | 51 | /*! SCE header types. */ 52 | extern id_to_name_t _sce_header_types[]; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /aes_omac.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "aes.h" 3 | 4 | void _gf_mul(unsigned char *pad) 5 | { 6 | unsigned int i; 7 | unsigned cxor = (pad[0] & 0x80) ? 0x87 : 0; 8 | 9 | for(i = 0; i < 15; i++) 10 | pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); 11 | pad[15] = (pad[15] << 1) ^ cxor; 12 | } 13 | 14 | void aes_omac1(u8 *digest, u8 *input, u32 length, u8 *key, u32 keybits) 15 | { 16 | u32 i, j; 17 | u32 overflow; 18 | aes_context ctxt; 19 | unsigned char buffer1[16], buffer2[16], dbuf[16]; 20 | 21 | memset(buffer1, 0, 16); 22 | 23 | aes_setkey_enc(&ctxt, key, keybits); 24 | 25 | aes_crypt_ecb(&ctxt, AES_ENCRYPT, buffer1, buffer2); 26 | _gf_mul(buffer2); 27 | 28 | if(length > 16) 29 | { 30 | for(i = 0; i < length - 16; i += 16) 31 | { 32 | for(j = 0; j < 16; j++) 33 | dbuf[j] = buffer1[j] ^ input[i + j]; 34 | aes_crypt_ecb(&ctxt, AES_ENCRYPT, dbuf, buffer1); 35 | } 36 | } 37 | 38 | overflow = length & 0xf; 39 | if(length % 16 == 0) 40 | overflow = 16; 41 | 42 | memset(dbuf, 0, 16); 43 | memcpy(dbuf, &(input[i]), overflow); 44 | 45 | if(overflow != 16) 46 | { 47 | dbuf[overflow] = 0x80; 48 | _gf_mul(buffer2); 49 | } 50 | 51 | for(i = 0; i < 16; i++) 52 | dbuf[i] ^= buffer1[i] ^ buffer2[i]; 53 | 54 | aes_crypt_ecb(&ctxt, AES_ENCRYPT, dbuf, digest); 55 | } 56 | -------------------------------------------------------------------------------- /spp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _SPP_H_ 7 | #define _SPP_H_ 8 | 9 | #include "types.h" 10 | #include "sce.h" 11 | 12 | /*! SPP entry types. */ 13 | #define SPP_ENTRY_TYPE_1 1 14 | #define SPP_ENTRY_TYPE_2 2 15 | 16 | /*! SPP header. */ 17 | typedef struct _spp_header 18 | { 19 | u16 unk1; 20 | u16 unk2; 21 | u32 spp_size; 22 | u32 unk3; 23 | u32 unk4; 24 | u64 unk5; 25 | u32 entcnt; 26 | u32 unk7; 27 | } spp_header_t; 28 | 29 | static inline void _es_spp_header(spp_header_t *h) 30 | { 31 | h->unk1 = _ES16(h->unk1); 32 | h->unk2 = _ES16(h->unk2); 33 | h->spp_size = _ES32(h->spp_size); 34 | h->unk3 = _ES32(h->unk3); 35 | h->unk4 = _ES32(h->unk4); 36 | h->unk5 = _ES64(h->unk5); 37 | h->entcnt = _ES32(h->entcnt); 38 | h->unk7 = _ES32(h->unk7); 39 | } 40 | 41 | /*! SPP entry header. */ 42 | typedef struct _spp_entry_header 43 | { 44 | u32 entry_size; 45 | u32 type; 46 | u64 laid; 47 | u64 paid; 48 | u8 name[0x20]; 49 | } spp_entry_header_t; 50 | 51 | static inline void _es_spp_entry_header(spp_entry_header_t *h) 52 | { 53 | h->entry_size = _ES32(h->entry_size); 54 | h->type = _ES32(h->type); 55 | h->laid = _ES64(h->laid); 56 | h->paid = _ES64(h->paid); 57 | } 58 | 59 | /*! Print SPP infos. */ 60 | void spp_print(FILE *fp, sce_buffer_ctxt_t *ctxt); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /mt19937.cpp: -------------------------------------------------------------------------------- 1 | #include "mt19937.h" 2 | 3 | void mt19937_init(mt19937_ctxt_t *ctxt, unsigned int seed) 4 | { 5 | ctxt->state[0] = seed; 6 | 7 | for(ctxt->idx = 1; ctxt->idx < MT_N; ctxt->idx++) 8 | ctxt->state[ctxt->idx] = (1812433253 * (ctxt->state[ctxt->idx - 1] ^ (ctxt->state[ctxt->idx - 1] >> 30)) + ctxt->idx); 9 | 10 | ctxt->idx = MT_M + 1; 11 | } 12 | 13 | unsigned int mt19937_update(mt19937_ctxt_t *ctxt) 14 | { 15 | unsigned int y, k; 16 | static unsigned int mag01[2] = {0, MT_MATRIX_A}; 17 | 18 | if(ctxt->idx >= MT_N) 19 | { 20 | for(k = 0; k < MT_N - MT_M; k++) 21 | { 22 | y = (ctxt->state[k] & MT_UPPER_MASK) | 23 | (ctxt->state[k + 1] & MT_LOWER_MASK); 24 | ctxt->state[k] = ctxt->state[k + MT_M] ^ (y >> 1) ^ mag01[y & 1]; 25 | } 26 | 27 | for(; k < MT_N - 1; k++) 28 | { 29 | y = (ctxt->state[k] & MT_UPPER_MASK) | 30 | (ctxt->state[k + 1] & MT_LOWER_MASK); 31 | ctxt->state[k] = ctxt->state[k + (MT_M - MT_N)] ^ (y >> 1) ^ mag01[y & 1]; 32 | } 33 | 34 | y = (ctxt->state[MT_N - 1] & MT_UPPER_MASK) | 35 | (ctxt->state[0] & MT_LOWER_MASK); 36 | ctxt->state[MT_N - 1] = ctxt->state[MT_M - 1] ^ (y >> 1) ^ mag01[y & 1]; 37 | 38 | ctxt->idx = 0; 39 | } 40 | 41 | y = ctxt->state[ctxt->idx++]; 42 | 43 | y ^= (y >> 11); 44 | y ^= (y << 7) & 0x9d2c5680UL; 45 | y ^= (y << 15) & 0xefc60000UL; 46 | y ^= (y >> 18); 47 | 48 | return y; 49 | } 50 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _UTIL_H_ 7 | #define _UTIL_H_ 8 | 9 | #include 10 | 11 | #include "types.h" 12 | 13 | /*! Verbose. */ 14 | extern BOOL _verbose; 15 | #define _LOG_VERBOSE(...) _IF_VERBOSE(printf("[*] " __VA_ARGS__)) 16 | #define _IF_VERBOSE(code) \ 17 | do \ 18 | { \ 19 | if(_verbose == TRUE) \ 20 | { \ 21 | code; \ 22 | } \ 23 | } while(0) 24 | 25 | /*! Raw. */ 26 | extern BOOL _raw; 27 | #define _PRINT_RAW(fp, ...) _IF_RAW(fprintf(fp, __VA_ARGS__)) 28 | #define _IF_RAW(code) \ 29 | do \ 30 | { \ 31 | if(_raw == TRUE) \ 32 | { \ 33 | code; \ 34 | } \ 35 | } while(0) 36 | 37 | /*! ID to name entry. */ 38 | typedef struct _id_to_name 39 | { 40 | u64 id; 41 | const s8 *name; 42 | } id_to_name_t; 43 | 44 | /*! Utility functions. */ 45 | void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, BOOL print_addr); 46 | void _print_align(FILE *fp, const s8 *str, s32 align, s32 len); 47 | u8 *_read_buffer(const s8 *file, u32 *length); 48 | int _write_buffer(const s8 *file, u8 *buffer, u32 length); 49 | const s8 *_get_name(id_to_name_t *tab, u64 id); 50 | u64 _get_id(id_to_name_t *tab, const s8 *name); 51 | void _zlib_inflate(u8 *in, u64 len_in, u8 *out, u64 len_out); 52 | void _zlib_deflate(u8 *in, u64 len_in, u8 *out, u64 len_out); 53 | u8 _get_rand_byte(); 54 | void _fill_rand_bytes(u8 *dst, u32 len); 55 | void _memcpy_inv(u8 *dst, u8 *src, u32 len); 56 | void *_memdup(void *ptr, u32 size); 57 | u64 _x_to_u64(const s8 *hex); 58 | u8 *_x_to_u8_buffer(const s8 *hex); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /self.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _SELF_H_ 7 | #define _SELF_H_ 8 | 9 | #include "types.h" 10 | #include "config.h" 11 | #include "np.h" 12 | 13 | /*! PS3 specific ELF constants. */ 14 | /*! LV2 OS ABI. */ 15 | #define ELFOSABI_CELL_LV2 0x66 16 | /*! PRX ELF type. */ 17 | #define ET_PS3PRX 0xFFA4 18 | /*! PS3 Params. */ 19 | #define PT_PS3_PARAMS 0x60000001 20 | /*! PS3 PRX. */ 21 | #define PT_PS3_PRX 0x60000002 22 | /*! PRX Relocations. */ 23 | #define PT_PS3_PRX_RELOC 0x700000A4 24 | 25 | /*! SELF config. */ 26 | typedef struct _self_config 27 | { 28 | /*! Add section headers. */ 29 | BOOL add_shdrs; 30 | /*! Compress data. */ 31 | BOOL compress_data; 32 | /*! Skip sections. */ 33 | BOOL skip_sections; 34 | 35 | /*! Key revision. */ 36 | u16 key_revision; 37 | /*! Auth ID. */ 38 | u64 auth_id; 39 | /*! Vendor ID. */ 40 | u32 vendor_id; 41 | /*! SELF type. */ 42 | u32 self_type; 43 | /*! Application version. */ 44 | u64 app_version; 45 | /*! Firmware version. */ 46 | u64 fw_version; 47 | 48 | /*! Control flags. */ 49 | u8 *ctrl_flags; 50 | /*! Capability flags. */ 51 | u8 *cap_flags; 52 | #ifdef CONFIG_CUSTOM_INDIV_SEED 53 | /*! Individuals seed. */ 54 | u8 *indiv_seed; 55 | /*! Individuals seed size. */ 56 | u32 indiv_seed_size; 57 | #endif 58 | 59 | /*! NPDRM config (used if not NULL). */ 60 | npdrm_config_t *npdrm_config; 61 | } self_config_t; 62 | 63 | /*! Print SELF info. */ 64 | BOOL self_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt); 65 | 66 | /*! Create ELF from SELF. */ 67 | BOOL self_write_to_elf(sce_buffer_ctxt_t *ctxt, const s8 *elf_out); 68 | 69 | /*! Create SELF from ELF. */ 70 | BOOL self_build_self(sce_buffer_ctxt_t *ctxt, self_config_t *sconf); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #pragma once 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | typedef char s8; 13 | typedef unsigned char u8; 14 | typedef short s16; 15 | typedef unsigned short u16; 16 | typedef int s32; 17 | typedef unsigned int u32; 18 | #if defined(_WIN32) && defined(_MSC_VER) 19 | typedef __int64 s64; 20 | typedef unsigned __int64 u64; 21 | #else 22 | typedef long long int s64; 23 | typedef unsigned long long int u64; 24 | #endif 25 | 26 | #define BOOL int 27 | #define TRUE 1 28 | #define FALSE 0 29 | 30 | //Align. 31 | #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) 32 | 33 | //Bits <-> bytes conversion. 34 | #define BITS2BYTES(x) ((x) / 8) 35 | #define BYTES2BITS(x) ((x) * 8) 36 | 37 | //Endian swap for u16. 38 | #define _ES16(val) \ 39 | ((u16)(((((u16)val) & 0xff00) >> 8) | \ 40 | ((((u16)val) & 0x00ff) << 8))) 41 | 42 | //Endian swap for u32. 43 | #define _ES32(val) \ 44 | ((u32)(((((u32)val) & 0xff000000) >> 24) | \ 45 | ((((u32)val) & 0x00ff0000) >> 8 ) | \ 46 | ((((u32)val) & 0x0000ff00) << 8 ) | \ 47 | ((((u32)val) & 0x000000ff) << 24))) 48 | 49 | //Endian swap for u64. 50 | #define _ES64(val) \ 51 | ((u64)(((((u64)val) & 0xff00000000000000ull) >> 56) | \ 52 | ((((u64)val) & 0x00ff000000000000ull) >> 40) | \ 53 | ((((u64)val) & 0x0000ff0000000000ull) >> 24) | \ 54 | ((((u64)val) & 0x000000ff00000000ull) >> 8 ) | \ 55 | ((((u64)val) & 0x00000000ff000000ull) << 8 ) | \ 56 | ((((u64)val) & 0x0000000000ff0000ull) << 24) | \ 57 | ((((u64)val) & 0x000000000000ff00ull) << 40) | \ 58 | ((((u64)val) & 0x00000000000000ffull) << 56))) 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _CONFIG_H_ 7 | #define _CONFIG_H_ 8 | 9 | /*! scetool base version. */ 10 | #define SCETOOL_VERSION_BASE "0.2.9" 11 | 12 | /*! Private build. */ 13 | //#define CONFIG_PRIVATE_BUILD 14 | #define BUILD_FOR "naehrwert" 15 | //#define BUILD_FOR "unicorns" 16 | 17 | /*! scetool version. */ 18 | #ifdef CONFIG_PRIVATE_BUILD 19 | #ifdef BUILD_FOR 20 | #define SCETOOL_VERSION SCETOOL_VERSION_BASE " " 21 | #else 22 | #error Specify a name in BUILD_FOR. 23 | #endif 24 | #else 25 | #define SCETOOL_VERSION SCETOOL_VERSION_BASE " " 26 | #endif 27 | 28 | /*! Private build options. */ 29 | #ifdef CONFIG_PRIVATE_BUILD 30 | #define CONFIG_CUSTOM_INDIV_SEED 31 | #define CONFIG_DUMP_INDIV_SEED 32 | #endif 33 | 34 | #if 0 35 | /*! scetool API. */ 36 | #define CONFIG_EXPORTS 37 | #ifdef CONFIG_EXPORTS 38 | #define SCETOOL_API __declspec(dllexport) 39 | #else 40 | #define SCETOOL_API __declspec(dllimport) 41 | #endif 42 | #endif 43 | 44 | /*! NPDRM watermark text (16 bytes exactly). */ 45 | //"I like kittens !" 46 | #define CONFIG_NPDRM_WATERMARK "watermarktrololo" 47 | 48 | /*! Environment variables. */ 49 | #define CONFIG_ENV_PS3 "PS3" 50 | 51 | /*! Path configurations. */ 52 | #define CONFIG_KEYS_FILE "keys" 53 | #define CONFIG_KEYS_PATH "./data" 54 | #define CONFIG_CURVES_FILE "ldr_curves" 55 | #define CONFIG_CURVES_PATH "./data" 56 | #define CONFIG_VSH_CURVES_FILE "vsh_curves" 57 | #define CONFIG_VSH_CURVES_PATH "./data" 58 | #define CONFIG_IDPS_FILE "idps" 59 | #define CONFIG_IDPS_PATH "./data" 60 | #define CONFIG_ACT_DAT_FILE "act.dat" 61 | #define CONFIG_ACT_DAT_PATH "./data" 62 | #define CONFIG_RIF_FILE_EXT ".rif" 63 | #define CONFIG_RIF_PATH "./rifs" 64 | #define CONFIG_RAP_FILE_EXT ".rap" 65 | #define CONFIG_RAP_PATH "./raps" 66 | 67 | /*! Key names. */ 68 | #define CONFIG_NP_TID_KNAME "NP_tid" 69 | #define CONFIG_NP_CI_KNAME "NP_ci" 70 | #define CONFIG_NP_KLIC_FREE_KNAME "NP_klic_free" 71 | #define CONFIG_NP_KLIC_KEY_KNAME "NP_klic_key" 72 | #define CONFIG_NP_IDPS_CONST_KNAME "NP_idps_const" 73 | #define CONFIG_NP_RIF_KEY_KNAME "NP_rif_key" 74 | #define CONFIG_NP_SIG_KNAME "NP_sig" 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /spp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | 8 | #include "types.h" 9 | #include "sce.h" 10 | #include "spp.h" 11 | #include "util.h" 12 | 13 | static void _print_spp_header(FILE *fp, spp_header_t *h) 14 | { 15 | fprintf(fp, "[*] SPP Header:\n"); 16 | fprintf(fp, " unk1 0x%04X\n", h->unk1); 17 | fprintf(fp, " unk2 0x%04X\n", h->unk2); 18 | fprintf(fp, " SPP Size 0x%08X\n", h->spp_size); 19 | fprintf(fp, " unk3 0x%08X\n", h->unk3); 20 | fprintf(fp, " unk4 0x%08X\n", h->unk4); 21 | fprintf(fp, " unk5 0x%016llX\n", h->unk5); 22 | fprintf(fp, " Entry Count 0x%08X\n", h->entcnt); 23 | fprintf(fp, " unk7 0x%08X\n", h->unk7); 24 | } 25 | 26 | static void _print_spp_entry_header(FILE *fp, spp_entry_header_t *h, u32 idx) 27 | { 28 | fprintf(fp, "[*] SPP Entry %02d:\n", idx); 29 | fprintf(fp, " Size 0x%08X\n", h->entry_size); 30 | fprintf(fp, " Type 0x%08X\n", h->type); 31 | fprintf(fp, " LPAR Auth-ID 0x%016llX\n", h->laid); 32 | fprintf(fp, " Program Auth-ID 0x%016llX\n", h->paid); 33 | fprintf(fp, " Name %s\n", h->name); 34 | } 35 | 36 | void spp_print(FILE *fp, sce_buffer_ctxt_t *ctxt) 37 | { 38 | u32 i; 39 | 40 | //First section contains the SPP header. 41 | spp_header_t *header = (spp_header_t *)(ctxt->scebuffer + ctxt->metash[0].data_offset); 42 | _es_spp_header(header); 43 | 44 | //Second section contains the entries. 45 | u8 *ent = ctxt->scebuffer + ctxt->metash[1].data_offset; 46 | 47 | _print_spp_header(fp, header); 48 | 49 | for(i = 0; i < header->entcnt; i++) 50 | { 51 | //Get current entry header. 52 | spp_entry_header_t *eh = (spp_entry_header_t *)ent; 53 | _es_spp_entry_header(eh); 54 | 55 | //Print header. 56 | _print_spp_entry_header(fp, eh, i); 57 | 58 | //Print data. 59 | _hexdump(fp, " Data", 0, ent + sizeof(spp_entry_header_t), eh->entry_size - sizeof(spp_entry_header_t), TRUE); 60 | 61 | /* 62 | switch(eh->type) 63 | { 64 | case SPP_ENTRY_TYPE_1: 65 | break; 66 | case SPP_ENTRY_TYPE_2: 67 | break; 68 | default: 69 | printf("[*] Error: Unknown entry type 0x%08X (entry %02d)\n", eh->type, i); 70 | } 71 | */ 72 | 73 | //Move pointer to next entry. 74 | ent += eh->entry_size; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /rvk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _RVK_H_ 7 | #define _RVK_H_ 8 | 9 | #include "types.h" 10 | #include "sce.h" 11 | 12 | /* 13 | header: 14 | 00000200 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 15 | 00000210 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 16 | body: 17 | 00000220 00 00 00 03 00 00 00 01 00 03 00 41 00 00 00 00 00 00 00 00 00 00 00 02 FF FF FF FF FF FF FF FF 18 | 00000240 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 10 70 00 05 FF 00 00 01 FF FF FF FF FF FF FF FF 19 | 00000260 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 10 70 00 05 FE 00 00 01 FF FF FF FF FF FF FF FF 20 | 00000280 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 10 70 00 05 FD 00 00 01 FF FF FF FF FF FF FF FF 21 | 000002A0 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00 10 70 00 05 FC 00 00 01 FF FF FF FF FF FF FF FF 22 | 000002C0 00 00 00 04 00 00 00 03 00 01 00 00 00 00 00 00 10 70 00 04 00 00 00 01 FF FF FF FF FF FF FF FF 23 | */ 24 | 25 | /* 26 | 0 self != rvk 27 | 1 self == rvk 28 | 2 !(rvk <= self) -> self < rvk 29 | 3 self <= rvk 30 | 4 !(self <= rvk) -> self > rvk 31 | 5 rvk <= self -> self >= rvk 32 | */ 33 | #define CHECK_SELF_NEQU_RVK 0 34 | #define CHECK_SELF_EQU_RVK 1 35 | #define CHECK_SELF_LT_RVK 2 36 | #define CHECK_SELF_LTEQU_RVK 3 37 | #define CHECK_SELF_GT_RVK 4 38 | #define CHECK_SELF_GTEQU_RVK 5 39 | 40 | /*! RVK header. */ 41 | typedef struct _rvk_header 42 | { 43 | u32 type_0; 44 | u32 type_1; 45 | u64 opaque; //Program revoke: version, Package revoke: unknown. 46 | u32 entcnt; 47 | u8 padding[12]; 48 | } rvk_header_t; 49 | 50 | static inline void _es_rvk_header(rvk_header_t *h) 51 | { 52 | h->type_0 = _ES32(h->type_0); 53 | h->type_1 = _ES32(h->type_1); 54 | h->opaque = _ES64(h->opaque); 55 | h->entcnt = _ES32(h->entcnt); 56 | } 57 | 58 | /*! Program revoke list entry. */ 59 | typedef struct _prg_rvk_entry 60 | { 61 | u32 self_type; //3, 4 62 | u32 check_type; 63 | u64 version; 64 | union 65 | { 66 | u64 auth_id; 67 | u64 unk_3; 68 | }; 69 | u64 mask; 70 | } prg_rvk_entry_t; 71 | 72 | static inline void _es_prg_rvk_entry(prg_rvk_entry_t *e) 73 | { 74 | e->self_type = _ES32(e->self_type); 75 | e->check_type = _ES32(e->check_type); 76 | e->version = _ES64(e->version); 77 | e->auth_id = _ES64(e->auth_id); 78 | e->mask = _ES64(e->mask); 79 | } 80 | 81 | /*! Print RVK infos. */ 82 | void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-g -O0 -Wall 3 | OS_TARGET=scetool 4 | LDFLAGS=-lz 5 | OBJS=aes.o aes_omac.o bn.o ec.o ecdsa.o frontend.o getopt.o keys.o list.o \ 6 | main.o mt19937.o np.o rvk.o sce.o self.o sha1.o tables.o util.o spp.o 7 | .SILENT: 8 | .SUFFIXES: .c .cpp .o 9 | 10 | $(OS_TARGET): $(OBJS) 11 | ${LINK} 12 | if $(CC) $(CFLAGS) $(OBJS) -o $(OS_TARGET) $(LDFLAGS) $(LIBS); then \ 13 | ${LINK_OK}; \ 14 | else \ 15 | ${LINK_FAILED}; \ 16 | fi 17 | 18 | 19 | %.o: %.c 20 | ${COMPILE_STATUS} 21 | if ${CC} ${CFLAGS} ${CFLAGS} -c -o $@ $<; then \ 22 | ${COMPILE_OK}; \ 23 | else \ 24 | ${COMPILE_FAILED}; \ 25 | fi 26 | 27 | %.o: %.cpp 28 | ${COMPILE_STATUS} 29 | if ${CC} ${CFLAGS} ${CFLAGS} -c -o $@ $<; then \ 30 | ${COMPILE_OK}; \ 31 | else \ 32 | ${COMPILE_FAILED}; \ 33 | fi 34 | 35 | clean: 36 | @printf "\033[K\033[0;32mCleaning\033[1;32m\033[0;32m...\033[0m\n" 37 | rm -rf *.o $(OS_TARGET) 38 | 39 | install: 40 | @printf "\033[K\033[0;32mInstalling\033[1;32m\033[0;32m...\033[0m\n" 41 | install -m755 $(OS_TARGET) $(BINDIR) 42 | 43 | DIR_ENTER = printf "\033[K\033[0;36mEntering directory \033[1;36m$$i\033[0;36m.\033[0m\n"; cd $$i || exit 1 44 | DIR_LEAVE = printf "\033[K\033[0;36mLeaving directory \033[1;36m$$i\033[0;36m.\033[0m\n"; cd .. || exit 1 45 | DEPEND_STATUS = printf "\033[K\033[0;33mGenerating dependencies...\033[0m\r" 46 | DEPEND_OK = printf "\033[K\033[0;32mSuccessfully generated dependencies.\033[0m\n" 47 | DEPEND_FAILED = printf "\033[K\033[0;31mFailed to generate dependencies!\033[0m\n"; exit 1 48 | COMPILE_STATUS = printf "\033[K\033[0;33mCompiling \033[1;33m$<\033[0;33m...\033[0m\r" 49 | COMPILE_OK = printf "\033[K\033[0;32mSuccessfully compiled \033[1;32m$<\033[0;32m.\033[0m\n" 50 | COMPILE_FAILED = printf "\033[K\033[0;31mFailed to compile \033[1;31m$<\033[0;31m!\033[0m\n"; exit 1 51 | LINK_STATUS = printf "\033[K\033[0;33mLinking \033[1;33m$@\033[0;33m...\033[0m\r" 52 | LINK_OK = printf "\033[K\033[0;32mSuccessfully linked \033[1;32m$@\033[0;32m.\033[0m\n" 53 | LINK_FAILED = printf "\033[K\033[0;31mFailed to link \033[1;31m$@\033[0;31m!\033[0m\n"; exit 1 54 | INSTALL_STATUS = printf "\033[K\033[0;33mInstalling \033[1;33m$$i\033[0;33m...\033[0m\r" 55 | INSTALL_OK = printf "\033[K\033[0;32mSuccessfully installed \033[1;32m$$i\033[0;32m.\033[0m\n" 56 | INSTALL_FAILED = printf "\033[K\033[0;31mFailed to install \033[1;31m$$i\033[0;31m!\033[0m\n"; exit 1 57 | DELETE_OK = printf "\033[K\033[0;34mDeleted \033[1;34m$$i\033[0;34m.\033[0m\n" 58 | DELETE_FAILED = printf "\033[K\033[0;31mFailed to delete \033[1;31m$$i\033[0;31m!\033[0m\n"; exit 1 59 | 60 | -------------------------------------------------------------------------------- /keys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _KEYS_H_ 7 | #define _KEYS_H_ 8 | 9 | #include "types.h" 10 | #include "sce.h" 11 | 12 | #define KEYBITS(klen) BYTES2BITS(klen) 13 | 14 | #define KEYTYPE_SELF 1 15 | #define KEYTYPE_RVK 2 16 | #define KEYTYPE_PKG 3 17 | #define KEYTYPE_SPP 4 18 | #define KEYTYPE_OTHER 5 19 | 20 | /*! Flag to use VSH curve. */ 21 | #define USE_VSH_CURVE 0x40 22 | 23 | /*! Length of whole curves file. */ 24 | #define CURVES_LENGTH 0x1E40 25 | #define CTYPE_MIN 0 26 | #define CTYPE_MAX 63 27 | 28 | /*! Length of the whole VSH curves file. */ 29 | #define VSH_CURVES_LENGTH 0x168 30 | #define VSH_CTYPE_MIN 0 31 | #define VSH_CTYPE_MAX 2 32 | 33 | /*! Length of the idps, act.dat, .rif and .rap files. */ 34 | #define IDPS_LENGTH 0x10 35 | #define ACT_DAT_LENGTH 0x1038 36 | #define RIF_LENGTH 0x98 37 | #define RAP_LENGTH 0x10 38 | 39 | /*! IDPS, RIF, act.dat key lengths. */ 40 | #define IDPS_KEYBITS 128 41 | #define ACT_DAT_KEYBITS 128 42 | #define RIF_KEYBITS 128 43 | #define RAP_KEYBITS 128 44 | 45 | /*! Keyset. */ 46 | typedef struct _keyset 47 | { 48 | /*! Name. */ 49 | s8 *name; 50 | /*! Type. */ 51 | u32 type; 52 | /*! Key revision. */ 53 | u16 key_revision; 54 | /*! Version. */ 55 | u64 version; 56 | /*! SELF type. */ 57 | u32 self_type; 58 | /*! Key length. */ 59 | u32 erklen; 60 | /*! Key. */ 61 | u8 *erk; 62 | /*! IV length. */ 63 | u32 rivlen; 64 | /*! IV. */ 65 | u8 *riv; 66 | /*! Pub. */ 67 | u8 *pub; 68 | /*! Priv. */ 69 | u8 *priv; 70 | /*! Curve type. */ 71 | u8 ctype; 72 | } keyset_t; 73 | 74 | /*! Curve entry. */ 75 | typedef struct _curve 76 | { 77 | u8 p[20]; 78 | u8 a[20]; 79 | u8 b[20]; 80 | u8 N[21]; 81 | u8 Gx[20]; 82 | u8 Gy[20]; 83 | } curve_t; 84 | 85 | /*! VSH Curve entry. */ 86 | typedef struct _vsh_curve 87 | { 88 | u8 a[20]; 89 | u8 b[20]; 90 | u8 N[20]; 91 | u8 p[20]; 92 | u8 Gx[20]; 93 | u8 Gy[20]; 94 | } vsh_curve_t; 95 | 96 | /*! act.dat. */ 97 | typedef struct _act_dat 98 | { 99 | u8 account_info[16]; 100 | u8 primary_key_table[2048]; 101 | u8 secondary_key_table[2048]; 102 | u8 signature[40]; 103 | } act_dat_t; 104 | 105 | /*! RIF. */ 106 | typedef struct _rif 107 | { 108 | u8 account_info[16]; 109 | u8 content_id[48]; 110 | u8 act_key_index[16]; 111 | u8 klicensee[16]; 112 | u64 timestamp; 113 | u64 zero; 114 | u8 signature[40]; 115 | } rif_t; 116 | 117 | void _print_key_list(FILE *fp); 118 | 119 | BOOL keys_load(const s8 *kfile); 120 | keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt); 121 | keyset_t *keyset_find_by_name(const s8 *name); 122 | 123 | BOOL curves_load(const s8 *cfile); 124 | curve_t *curve_find(u8 ctype); 125 | 126 | BOOL vsh_curves_load(const s8 *cfile); 127 | curve_t *vsh_curve_find(u8 ctype); 128 | 129 | BOOL klicensee_by_content_id(const s8 *content_id, u8 *klicensee); 130 | 131 | keyset_t *keyset_from_buffer(u8 *keyset); 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /rvk.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | 8 | #include "types.h" 9 | #include "util.h" 10 | #include "sce.h" 11 | #include "rvk.h" 12 | #include "tables.h" 13 | 14 | static void _print_rvk_header(FILE *fp, rvk_header_t *h) 15 | { 16 | fprintf(fp, "[*] Revoke List Header:\n"); 17 | fprintf(fp, " type_0 0x%08X\n", h->type_0); 18 | fprintf(fp, " type_1 0x%08X\n", h->type_1); 19 | 20 | if(h->type_0 == 4) 21 | fprintf(fp, " Version %s\n", sce_version_to_str(h->opaque)); 22 | else 23 | fprintf(fp, " Opaque 0x%016llX\n", h->opaque); 24 | 25 | fprintf(fp, " Entry Count 0x%08X\n", h->entcnt); 26 | } 27 | 28 | /* 29 | typedef struct _prg_rvk_entry 30 | { 31 | u32 self_type; //3, 4 32 | u32 unk_1; //1, 3 33 | union 34 | { 35 | u64 version; //unk_1 == 1 36 | u64 unk_2; //unk_1 == 3 37 | }; 38 | union 39 | { 40 | u64 auth_id; 41 | u64 unk_3; 42 | }; 43 | u8 unk_4[8]; 44 | } prg_rvk_entry_t; 45 | */ 46 | 47 | static void _print_prg_rvk_entry_header(FILE *fp) 48 | { 49 | fprintf(fp, "[*] Program Revoke List Entries:\n"); 50 | fprintf(fp, " Type Check Version Auth-ID/unk_3 Mask\n"); 51 | } 52 | 53 | static id_to_name_t _check_type_values[] = 54 | { 55 | {CHECK_SELF_NEQU_RVK, "!="}, 56 | {CHECK_SELF_EQU_RVK, "=="}, 57 | {CHECK_SELF_LT_RVK, "<"}, 58 | {CHECK_SELF_LTEQU_RVK, "<="}, 59 | {CHECK_SELF_GT_RVK, ">"}, 60 | {CHECK_SELF_GTEQU_RVK, ">="}, 61 | {0, NULL} 62 | }; 63 | 64 | static void _print_prg_rvk_entry(FILE *fp, prg_rvk_entry_t *e) 65 | { 66 | const s8 *name; 67 | 68 | name = _get_name(_self_types, e->self_type); 69 | if(name != NULL) 70 | fprintf(fp, " %-19s ", name); 71 | else 72 | fprintf(fp, " 0x%08X ", e->self_type); 73 | 74 | name = _get_name(_check_type_values, e->check_type); 75 | if(name != NULL) 76 | fprintf(fp, "%-2s ", name); 77 | else 78 | fprintf(fp, "%08X ", e->check_type); 79 | 80 | fprintf(fp, "%s ", sce_version_to_str(e->version)); 81 | 82 | name = _get_name(_auth_ids, e->auth_id); 83 | if(name != NULL) 84 | fprintf(fp, "%-16s ", name); 85 | else 86 | fprintf(fp, "%016llX ", e->auth_id); 87 | 88 | fprintf(fp, "%016llX ", e->mask); 89 | 90 | fprintf(fp, "\n"); 91 | } 92 | 93 | void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt) 94 | { 95 | u32 i; 96 | 97 | rvk_header_t *rvkh = (rvk_header_t *)(ctxt->scebuffer + ctxt->metash[0].data_offset); 98 | _es_rvk_header(rvkh); 99 | 100 | _print_rvk_header(fp, rvkh); 101 | 102 | //Program revoke. 103 | if(rvkh->type_0 == 4) 104 | { 105 | prg_rvk_entry_t *ent = (prg_rvk_entry_t *)(ctxt->scebuffer + ctxt->metash[1].data_offset); 106 | _print_prg_rvk_entry_header(fp); 107 | for(i = 0; i < rvkh->entcnt; i++) 108 | { 109 | _es_prg_rvk_entry(&ent[i]); 110 | _print_prg_rvk_entry(fp, &ent[i]); 111 | } 112 | } 113 | else if(rvkh->type_0 == 3) 114 | { 115 | fprintf(fp, "[*] Package Revoke List Entries:\n"); 116 | u8 *ent = (u8 *)(ctxt->scebuffer + ctxt->metash[1].data_offset); 117 | for(i = 0; i < rvkh->entcnt; i++) 118 | { 119 | _hexdump(fp, " ent", i*0x20, ent, 0x20, TRUE); 120 | ent += 0x20; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /getopt.h: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | 3 | /* Getopt for Microsoft C 4 | This code is a modification of the Free Software Foundation, Inc. 5 | Getopt library for parsing command line argument the purpose was 6 | to provide a Microsoft Visual C friendly derivative. This code 7 | provides functionality for both Unicode and Multibyte builds. 8 | 9 | Date: 02/03/2011 - Ludvik Jerabek - Initial Release 10 | Version: 1.0 11 | Comment: Supports getopt, getopt_long, and getopt_long_only 12 | and POSIXLY_CORRECT environment flag 13 | License: LGPL 14 | 15 | Revisions: 16 | 17 | 02/03/2011 - Ludvik Jerabek - Initial Release 18 | 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 19 | 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs 20 | 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception 21 | 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB 22 | 23 | **DISCLAIMER** 24 | THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 25 | EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE 26 | IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 27 | PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE 28 | EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT 29 | APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY 30 | DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY 31 | USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST 32 | PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON 33 | YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE 34 | EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 35 | */ 36 | #ifndef __GETOPT_H_ 37 | #define __GETOPT_H_ 38 | 39 | #define STATIC_GETOPT 40 | 41 | #ifdef _GETOPT_API 42 | #undef _GETOPT_API 43 | #endif 44 | 45 | #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) 46 | #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually" 47 | #elif defined(STATIC_GETOPT) 48 | #pragma message("Warning static builds of getopt violate the Lesser GNU Public License") 49 | #define _GETOPT_API 50 | #elif defined(EXPORTS_GETOPT) 51 | #pragma message("Exporting getopt library") 52 | #define _GETOPT_API __declspec(dllexport) 53 | #else 54 | #pragma message("Importing getopt library") 55 | #define _GETOPT_API __declspec(dllimport) 56 | #endif 57 | 58 | 59 | #include 60 | 61 | // Standard GNU options 62 | #define null_argument 0 /*Argument Null*/ 63 | #define no_argument 0 /*Argument Switch Only*/ 64 | #define required_argument 1 /*Argument Required*/ 65 | #define optional_argument 2 /*Argument Optional*/ 66 | 67 | // Change behavior for C\C++ 68 | #ifdef __cplusplus 69 | #define _BEGIN_EXTERN_C extern "C" { 70 | #define _END_EXTERN_C } 71 | #define _GETOPT_THROW throw() 72 | #else 73 | #define _BEGIN_EXTERN_C 74 | #define _END_EXTERN_C 75 | #define _GETOPT_THROW 76 | #endif 77 | 78 | _BEGIN_EXTERN_C 79 | 80 | extern _GETOPT_API TCHAR *optarg; 81 | extern _GETOPT_API int optind; 82 | extern _GETOPT_API int opterr; 83 | extern _GETOPT_API int optopt; 84 | 85 | struct option 86 | { 87 | const TCHAR* name; 88 | int has_arg; 89 | int *flag; 90 | TCHAR val; 91 | }; 92 | 93 | extern _GETOPT_API int getopt(int argc, TCHAR *const *argv, const TCHAR *optstring) _GETOPT_THROW; 94 | extern _GETOPT_API int getopt_long(int ___argc, TCHAR *const *___argv, const TCHAR *__shortopts, const struct option *__longopts, int *__longind) _GETOPT_THROW; 95 | extern _GETOPT_API int getopt_long_only(int ___argc, TCHAR *const *___argv, const TCHAR *__shortopts, const struct option *__longopts, int *__longind) _GETOPT_THROW; 96 | _END_EXTERN_C 97 | 98 | // Undefine so the macros are not included 99 | #undef _BEGIN_EXTERN_C 100 | #undef _END_EXTERN_C 101 | #undef _GETOPT_THROW 102 | #undef _GETOPT_API 103 | 104 | #endif // __GETOPT_H_ 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | 8 | #include "types.h" 9 | #include "list.h" 10 | 11 | list_t *list_create() 12 | { 13 | list_t *res; 14 | 15 | if((res = (list_t *)malloc(sizeof(list_t))) == NULL) 16 | return NULL; 17 | 18 | res->head = NULL; 19 | res->count = 0; 20 | 21 | return res; 22 | } 23 | 24 | void list_destroy(list_t *l) 25 | { 26 | if(l == NULL) 27 | return; 28 | 29 | lnode_t *iter = l->head, *tmp; 30 | 31 | while(iter != NULL) 32 | { 33 | tmp = iter; 34 | iter = iter->next; 35 | free(tmp); 36 | } 37 | 38 | free(l); 39 | } 40 | 41 | BOOL list_isempty(list_t *l) 42 | { 43 | if(l == NULL) 44 | return FALSE; 45 | 46 | if(l->count == 0) 47 | return TRUE; 48 | return FALSE; 49 | } 50 | 51 | u32 list_count(list_t *l) 52 | { 53 | if(l == NULL) 54 | return 0; 55 | 56 | return l->count; 57 | } 58 | 59 | BOOL list_push(list_t *l, void *value) 60 | { 61 | if(l == NULL) 62 | return FALSE; 63 | 64 | lnode_t *_new; 65 | 66 | //Allocate new node. 67 | if((_new = (lnode_t *)malloc(sizeof(lnode_t))) == NULL) 68 | return FALSE; 69 | 70 | //Insert. 71 | _new->value = value; 72 | _new->next = l->head; 73 | l->head = _new; 74 | l->count++; 75 | 76 | return TRUE; 77 | } 78 | 79 | void *list_pop(list_t *l) 80 | { 81 | if(l == NULL) 82 | return NULL; 83 | 84 | lnode_t *tmp; 85 | void *res = NULL; 86 | 87 | if(l->head != NULL) 88 | { 89 | res = l->head->value; 90 | tmp = l->head; 91 | l->head = l->head->next; 92 | free(tmp); 93 | l->count--; 94 | } 95 | 96 | return res; 97 | } 98 | 99 | BOOL list_add_back(list_t *l, void *value) 100 | { 101 | if(l == NULL) 102 | return FALSE; 103 | 104 | lnode_t *n, *_new; 105 | 106 | //Allocate new node. 107 | if((_new = (lnode_t *)malloc(sizeof(lnode_t))) == NULL) 108 | return FALSE; 109 | 110 | _new->value = value; 111 | _new->next = NULL; 112 | 113 | if(l->head == NULL) 114 | l->head = _new; 115 | else 116 | { 117 | //Move to the list end. 118 | for(n = l->head; n->next != NULL; n = n->next); 119 | 120 | //Add. 121 | n->next = _new; 122 | l->count++; 123 | } 124 | 125 | return TRUE; 126 | } 127 | 128 | void *list_get(list_t *l, u32 idx) 129 | { 130 | if(l == NULL) 131 | return NULL; 132 | 133 | lnode_t *iter; 134 | void *res = NULL; 135 | 136 | for(iter = l->head; idx-- != 0 && iter != NULL; iter = iter->next); 137 | 138 | if(iter == NULL) 139 | res = NULL; 140 | else 141 | res = iter->value; 142 | 143 | return res; 144 | } 145 | 146 | lnode_t *list_get_node(list_t *l, u32 idx) 147 | { 148 | if(l == NULL) 149 | return NULL; 150 | 151 | lnode_t *iter; 152 | 153 | for(iter = l->head; idx-- != 0 && iter != NULL; iter = iter->next); 154 | 155 | return iter; 156 | } 157 | 158 | BOOL list_remove_node(list_t *l, lnode_t *node) 159 | { 160 | if(l == NULL) 161 | return FALSE; 162 | 163 | lnode_t *iter; 164 | 165 | if(l->head == node) 166 | { 167 | l->head = l->head->next; 168 | free(node); 169 | l->count--; 170 | 171 | return TRUE; 172 | } 173 | 174 | iter = l->head; 175 | while(iter->next != NULL) 176 | { 177 | if(iter->next == node) 178 | { 179 | iter->next = iter->next->next; 180 | free(node); 181 | l->count--; 182 | 183 | return TRUE; 184 | } 185 | iter = iter->next; 186 | } 187 | 188 | return FALSE; 189 | } 190 | 191 | BOOL list_remove_value(list_t *l, void *value) 192 | { 193 | if(l == NULL) 194 | return FALSE; 195 | 196 | lnode_t *tmp, *iter; 197 | 198 | if(l->head->value == value) 199 | { 200 | tmp = l->head; 201 | l->head = l->head->next; 202 | free(tmp); 203 | l->count--; 204 | 205 | return TRUE; 206 | } 207 | 208 | iter = l->head; 209 | while(iter->next != NULL) 210 | { 211 | if(iter->next->value == value) 212 | { 213 | tmp = iter->next; 214 | iter->next = iter->next->next; 215 | free(tmp); 216 | l->count--; 217 | 218 | return TRUE; 219 | } 220 | iter = iter->next; 221 | } 222 | 223 | return FALSE; 224 | } 225 | -------------------------------------------------------------------------------- /elf_inlines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _ELF_INLINES_H_ 7 | #define _ELF_INLINES_H_ 8 | 9 | #include 10 | 11 | #include "types.h" 12 | #include "elf.h" 13 | 14 | static inline void _es_elf32_ehdr(Elf32_Ehdr *h) 15 | { 16 | h->e_type = _ES16(h->e_type); 17 | h->e_machine = _ES16(h->e_machine); 18 | h->e_version = _ES32(h->e_version); 19 | h->e_entry = _ES32(h->e_entry); 20 | h->e_phoff = _ES32(h->e_phoff); 21 | h->e_shoff = _ES32(h->e_shoff); 22 | h->e_flags = _ES32(h->e_flags); 23 | h->e_ehsize = _ES16(h->e_ehsize); 24 | h->e_phentsize = _ES16(h->e_phentsize); 25 | h->e_phnum = _ES16(h->e_phnum); 26 | h->e_shentsize = _ES16(h->e_shentsize); 27 | h->e_shnum = _ES16(h->e_shnum); 28 | h->e_shstrndx = _ES16(h->e_shstrndx); 29 | } 30 | 31 | static inline void _copy_es_elf32_ehdr(Elf32_Ehdr *dst, Elf32_Ehdr *src) 32 | { 33 | memcpy(dst, src, sizeof(Elf32_Ehdr)); 34 | _es_elf32_ehdr(dst); 35 | } 36 | 37 | static inline void _es_elf64_ehdr(Elf64_Ehdr *h) 38 | { 39 | h->e_type = _ES16(h->e_type); 40 | h->e_machine = _ES16(h->e_machine); 41 | h->e_version = _ES32(h->e_version); 42 | h->e_entry = _ES64(h->e_entry); 43 | h->e_phoff = _ES64(h->e_phoff); 44 | h->e_shoff = _ES64(h->e_shoff); 45 | h->e_flags = _ES32(h->e_flags); 46 | h->e_ehsize = _ES16(h->e_ehsize); 47 | h->e_phentsize = _ES16(h->e_phentsize); 48 | h->e_phnum = _ES16(h->e_phnum); 49 | h->e_shentsize = _ES16(h->e_shentsize); 50 | h->e_shnum = _ES16(h->e_shnum); 51 | h->e_shstrndx = _ES16(h->e_shstrndx); 52 | } 53 | 54 | static inline void _copy_es_elf64_ehdr(Elf64_Ehdr *dst, Elf64_Ehdr *src) 55 | { 56 | memcpy(dst, src, sizeof(Elf64_Ehdr)); 57 | _es_elf64_ehdr(dst); 58 | } 59 | 60 | static inline void _es_elf32_shdr(Elf32_Shdr *h) 61 | { 62 | h->sh_name = _ES32(h->sh_name); 63 | h->sh_type = _ES32(h->sh_type); 64 | h->sh_flags = _ES32(h->sh_flags); 65 | h->sh_addr = _ES32(h->sh_addr); 66 | h->sh_offset = _ES32(h->sh_offset); 67 | h->sh_size = _ES32(h->sh_size); 68 | h->sh_link = _ES32(h->sh_link); 69 | h->sh_info = _ES32(h->sh_info); 70 | h->sh_addralign = _ES32(h->sh_addralign); 71 | h->sh_entsize = _ES32(h->sh_entsize); 72 | } 73 | 74 | static inline void _copy_es_elf32_shdr(Elf32_Shdr *dst, Elf32_Shdr *src) 75 | { 76 | memcpy(dst, src, sizeof(Elf32_Shdr)); 77 | _es_elf32_shdr(dst); 78 | } 79 | 80 | static inline void _es_elf64_shdr(Elf64_Shdr *h) 81 | { 82 | h->sh_name = _ES32(h->sh_name); 83 | h->sh_type = _ES32(h->sh_type); 84 | h->sh_flags = _ES64(h->sh_flags); 85 | h->sh_addr = _ES64(h->sh_addr); 86 | h->sh_offset = _ES64(h->sh_offset); 87 | h->sh_size = _ES64(h->sh_size); 88 | h->sh_link = _ES32(h->sh_link); 89 | h->sh_info = _ES32(h->sh_info); 90 | h->sh_addralign = _ES64(h->sh_addralign); 91 | h->sh_entsize = _ES64(h->sh_entsize); 92 | } 93 | 94 | static inline void _copy_es_elf64_shdr(Elf64_Shdr *dst, Elf64_Shdr *src) 95 | { 96 | memcpy(dst, src, sizeof(Elf64_Shdr)); 97 | _es_elf64_shdr(dst); 98 | } 99 | 100 | static inline void _es_elf32_phdr(Elf32_Phdr *h) 101 | { 102 | h->p_type = _ES32(h->p_type); 103 | h->p_offset = _ES32(h->p_offset); 104 | h->p_vaddr = _ES32(h->p_vaddr); 105 | h->p_paddr = _ES32(h->p_paddr); 106 | h->p_filesz = _ES32(h->p_filesz); 107 | h->p_memsz = _ES32(h->p_memsz); 108 | h->p_flags = _ES32(h->p_flags); 109 | h->p_align = _ES32(h->p_align); 110 | } 111 | 112 | static inline void _copy_es_elf32_phdr(Elf32_Phdr *dst, Elf32_Phdr *src) 113 | { 114 | memcpy(dst, src, sizeof(Elf32_Phdr)); 115 | _es_elf32_phdr(dst); 116 | } 117 | 118 | static inline void _es_elf64_phdr(Elf64_Phdr *h) 119 | { 120 | h->p_type = _ES32(h->p_type); 121 | h->p_flags = _ES32(h->p_flags); 122 | h->p_offset = _ES64(h->p_offset); 123 | h->p_vaddr = _ES64(h->p_vaddr); 124 | h->p_paddr = _ES64(h->p_paddr); 125 | h->p_filesz = _ES64(h->p_filesz); 126 | h->p_memsz = _ES64(h->p_memsz); 127 | h->p_align = _ES64(h->p_align); 128 | } 129 | 130 | static inline void _copy_es_elf64_phdr(Elf64_Phdr *dst, Elf64_Phdr *src) 131 | { 132 | memcpy(dst, src, sizeof(Elf64_Phdr)); 133 | _es_elf64_phdr(dst); 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /sha1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file sha1.h 3 | * 4 | * \brief SHA-1 cryptographic hash function 5 | * 6 | * Copyright (C) 2006-2010, Brainspark B.V. 7 | * 8 | * This file is part of PolarSSL (http://www.polarssl.org) 9 | * Lead Maintainer: Paul Bakker 10 | * 11 | * All rights reserved. 12 | * 13 | * This program is free software; you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation; either version 2 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License along 24 | * with this program; if not, write to the Free Software Foundation, Inc., 25 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 26 | */ 27 | #ifndef POLARSSL_SHA1_H 28 | #define POLARSSL_SHA1_H 29 | 30 | #include 31 | 32 | /** 33 | * \brief SHA-1 context structure 34 | */ 35 | typedef struct 36 | { 37 | unsigned long total[2]; /*!< number of bytes processed */ 38 | unsigned long state[5]; /*!< intermediate digest state */ 39 | unsigned char buffer[64]; /*!< data block being processed */ 40 | 41 | unsigned char ipad[64]; /*!< HMAC: inner padding */ 42 | unsigned char opad[64]; /*!< HMAC: outer padding */ 43 | } 44 | sha1_context; 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | /** 51 | * \brief SHA-1 context setup 52 | * 53 | * \param ctx context to be initialized 54 | */ 55 | void sha1_starts( sha1_context *ctx ); 56 | 57 | /** 58 | * \brief SHA-1 process buffer 59 | * 60 | * \param ctx SHA-1 context 61 | * \param input buffer holding the data 62 | * \param ilen length of the input data 63 | */ 64 | void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); 65 | 66 | /** 67 | * \brief SHA-1 final digest 68 | * 69 | * \param ctx SHA-1 context 70 | * \param output SHA-1 checksum result 71 | */ 72 | void sha1_finish( sha1_context *ctx, unsigned char output[20] ); 73 | 74 | /** 75 | * \brief Output = SHA-1( input buffer ) 76 | * 77 | * \param input buffer holding the data 78 | * \param ilen length of the input data 79 | * \param output SHA-1 checksum result 80 | */ 81 | void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); 82 | 83 | /** 84 | * \brief SHA-1 HMAC context setup 85 | * 86 | * \param ctx HMAC context to be initialized 87 | * \param key HMAC secret key 88 | * \param keylen length of the HMAC key 89 | */ 90 | void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ); 91 | 92 | /** 93 | * \brief SHA-1 HMAC process buffer 94 | * 95 | * \param ctx HMAC context 96 | * \param input buffer holding the data 97 | * \param ilen length of the input data 98 | */ 99 | void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); 100 | 101 | /** 102 | * \brief SHA-1 HMAC final digest 103 | * 104 | * \param ctx HMAC context 105 | * \param output SHA-1 HMAC checksum result 106 | */ 107 | void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); 108 | 109 | /** 110 | * \brief SHA-1 HMAC context reset 111 | * 112 | * \param ctx HMAC context to be reset 113 | */ 114 | void sha1_hmac_reset( sha1_context *ctx ); 115 | 116 | /** 117 | * \brief Output = HMAC-SHA-1( hmac key, input buffer ) 118 | * 119 | * \param key HMAC secret key 120 | * \param keylen length of the HMAC key 121 | * \param input buffer holding the data 122 | * \param ilen length of the input data 123 | * \param output HMAC-SHA-1 result 124 | */ 125 | void sha1_hmac( const unsigned char *key, size_t keylen, 126 | const unsigned char *input, size_t ilen, 127 | unsigned char output[20] ); 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | #endif /* sha1.h */ 134 | -------------------------------------------------------------------------------- /bn.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2007,2008,2010 Segher Boessenkool 2 | // Licensed under the terms of the GNU GPL, version 2 3 | // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 4 | 5 | #include 6 | #include 7 | 8 | #include "types.h" 9 | 10 | void bn_print(char *name, u8 *a, u32 n) 11 | { 12 | u32 i; 13 | 14 | printf("%s = ", name); 15 | 16 | for (i = 0; i < n; i++) 17 | printf("%02x", a[i]); 18 | 19 | printf("\n"); 20 | } 21 | 22 | static void bn_zero(u8 *d, u32 n) 23 | { 24 | memset(d, 0, n); 25 | } 26 | 27 | void bn_copy(u8 *d, u8 *a, u32 n) 28 | { 29 | memcpy(d, a, n); 30 | } 31 | 32 | int bn_compare(u8 *a, u8 *b, u32 n) 33 | { 34 | u32 i; 35 | 36 | for (i = 0; i < n; i++) { 37 | if (a[i] < b[i]) 38 | return -1; 39 | if (a[i] > b[i]) 40 | return 1; 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | static u8 bn_add_1(u8 *d, u8 *a, u8 *b, u32 n) 47 | { 48 | u32 i; 49 | u32 dig; 50 | u8 c; 51 | 52 | c = 0; 53 | for (i = n - 1; i < n; i--) { 54 | dig = a[i] + b[i] + c; 55 | c = dig >> 8; 56 | d[i] = dig; 57 | } 58 | 59 | return c; 60 | } 61 | 62 | static u8 bn_sub_1(u8 *d, u8 *a, u8 *b, u32 n) 63 | { 64 | u32 i; 65 | u32 dig; 66 | u8 c; 67 | 68 | c = 1; 69 | for (i = n - 1; i < n; i--) { 70 | dig = a[i] + 255 - b[i] + c; 71 | c = dig >> 8; 72 | d[i] = dig; 73 | } 74 | 75 | return 1 - c; 76 | } 77 | 78 | void bn_reduce(u8 *d, u8 *N, u32 n) 79 | { 80 | if (bn_compare(d, N, n) >= 0) 81 | bn_sub_1(d, d, N, n); 82 | } 83 | 84 | void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) 85 | { 86 | if (bn_add_1(d, a, b, n)) 87 | bn_sub_1(d, d, N, n); 88 | 89 | bn_reduce(d, N, n); 90 | } 91 | 92 | void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) 93 | { 94 | if (bn_sub_1(d, a, b, n)) 95 | bn_add_1(d, d, N, n); 96 | } 97 | 98 | static const u8 inv256[0x80] = { 99 | 0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef, 100 | 0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf, 101 | 0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf, 102 | 0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf, 103 | 0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf, 104 | 0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f, 105 | 0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f, 106 | 0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f, 107 | 0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f, 108 | 0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f, 109 | 0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f, 110 | 0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f, 111 | 0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f, 112 | 0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f, 113 | 0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f, 114 | 0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff, 115 | }; 116 | 117 | static void bn_mon_muladd_dig(u8 *d, u8 *a, u8 b, u8 *N, u32 n) 118 | { 119 | u32 dig; 120 | u32 i; 121 | 122 | u8 z = -(d[n-1] + a[n-1]*b) * inv256[N[n-1]/2]; 123 | 124 | dig = d[n-1] + a[n-1]*b + N[n-1]*z; 125 | dig >>= 8; 126 | 127 | for (i = n - 2; i < n; i--) { 128 | dig += d[i] + a[i]*b + N[i]*z; 129 | d[i+1] = dig; 130 | dig >>= 8; 131 | } 132 | 133 | d[0] = dig; 134 | dig >>= 8; 135 | 136 | if (dig) 137 | bn_sub_1(d, d, N, n); 138 | 139 | bn_reduce(d, N, n); 140 | } 141 | 142 | void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n) 143 | { 144 | u8 t[512]; 145 | u32 i; 146 | 147 | bn_zero(t, n); 148 | 149 | for (i = n - 1; i < n; i--) 150 | bn_mon_muladd_dig(t, a, b[i], N, n); 151 | 152 | bn_copy(d, t, n); 153 | } 154 | 155 | void bn_to_mon(u8 *d, u8 *N, u32 n) 156 | { 157 | u32 i; 158 | 159 | for (i = 0; i < 8*n; i++) 160 | bn_add(d, d, d, N, n); 161 | } 162 | 163 | void bn_from_mon(u8 *d, u8 *N, u32 n) 164 | { 165 | u8 t[512]; 166 | 167 | bn_zero(t, n); 168 | t[n-1] = 1; 169 | bn_mon_mul(d, d, t, N, n); 170 | } 171 | 172 | static void bn_mon_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en) 173 | { 174 | u8 t[512]; 175 | u32 i; 176 | u8 mask; 177 | 178 | bn_zero(d, n); 179 | d[n-1] = 1; 180 | bn_to_mon(d, N, n); 181 | 182 | for (i = 0; i < en; i++) 183 | for (mask = 0x80; mask != 0; mask >>= 1) { 184 | bn_mon_mul(t, d, d, N, n); 185 | if ((e[i] & mask) != 0) 186 | bn_mon_mul(d, t, a, N, n); 187 | else 188 | bn_copy(d, t, n); 189 | } 190 | } 191 | 192 | void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n) 193 | { 194 | u8 t[512], s[512]; 195 | 196 | bn_zero(s, n); 197 | s[n-1] = 2; 198 | bn_sub_1(t, N, s, n); 199 | bn_mon_exp(d, a, N, n, t, n); 200 | } 201 | -------------------------------------------------------------------------------- /util.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "types.h" 12 | #include "util.h" 13 | #include "zlib.h" 14 | #include "mt19937.h" 15 | 16 | void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, BOOL print_addr) 17 | { 18 | int i, j, align = strlen(name) + 1; 19 | 20 | fprintf(fp, "%s ", name); 21 | if(print_addr == TRUE) 22 | fprintf(fp, "%08x: ", offset); 23 | for(i = 0; i < len; i++) 24 | { 25 | if(i % 16 == 0 && i != 0) 26 | { 27 | fprintf(fp, "\n"); 28 | for(j = 0; j < align; j++) 29 | putchar(' '); 30 | if(print_addr == TRUE) 31 | fprintf(fp, "%08X: ", offset + i); 32 | } 33 | fprintf(fp, "%02X ", buf[i]); 34 | } 35 | fprintf(fp, "\n"); 36 | } 37 | 38 | void _print_align(FILE *fp, const s8 *str, s32 align, s32 len) 39 | { 40 | s32 i, tmp; 41 | tmp = align - len; 42 | if(tmp < 0) 43 | tmp = 0; 44 | for(i = 0; i < tmp; i++) 45 | fputs(str, fp); 46 | } 47 | 48 | u8 *_read_buffer(const s8 *file, u32 *length) 49 | { 50 | FILE *fp; 51 | u32 size; 52 | 53 | if((fp = fopen(file, "rb")) == NULL) 54 | return NULL; 55 | 56 | fseek(fp, 0, SEEK_END); 57 | size = ftell(fp); 58 | fseek(fp, 0, SEEK_SET); 59 | 60 | u8 *buffer = (u8 *)malloc(sizeof(u8) * size); 61 | fread(buffer, sizeof(u8), size, fp); 62 | 63 | if(length != NULL) 64 | *length = size; 65 | 66 | fclose(fp); 67 | 68 | return buffer; 69 | } 70 | 71 | int _write_buffer(const s8 *file, u8 *buffer, u32 length) 72 | { 73 | FILE *fp; 74 | 75 | if((fp = fopen(file, "wb")) == NULL) 76 | return 0; 77 | 78 | /**/ 79 | while(length > 0) 80 | { 81 | u32 wrlen = 1024; 82 | if(length < 1024) 83 | wrlen = length; 84 | fwrite(buffer, sizeof(u8), wrlen, fp); 85 | length -= wrlen; 86 | buffer += 1024; 87 | } 88 | /**/ 89 | 90 | //fwrite(buffer, sizeof(u8), length, fp); 91 | 92 | fclose(fp); 93 | 94 | return 1; 95 | } 96 | 97 | const s8 *_get_name(id_to_name_t *tab, u64 id) 98 | { 99 | u32 i = 0; 100 | 101 | while(!(tab[i].name == NULL && tab[i].id == 0)) 102 | { 103 | if(tab[i].id == id) 104 | return tab[i].name; 105 | i++; 106 | } 107 | 108 | return NULL; 109 | } 110 | 111 | u64 _get_id(id_to_name_t *tab, const s8 *name) 112 | { 113 | u32 i = 0; 114 | 115 | while(!(tab[i].name == NULL && tab[i].id == 0)) 116 | { 117 | if(strcmp(tab[i].name, name) == 0) 118 | return tab[i].id; 119 | i++; 120 | } 121 | 122 | return (u64)(-1); 123 | } 124 | 125 | void _zlib_inflate(u8 *in, u64 len_in, u8 *out, u64 len_out) 126 | { 127 | z_stream s; 128 | memset(&s, 0, sizeof(z_stream)); 129 | 130 | s.zalloc = Z_NULL; 131 | s.zfree = Z_NULL; 132 | s.opaque = Z_NULL; 133 | 134 | inflateInit(&s); 135 | 136 | s.avail_in = len_in; 137 | s.next_in = in; 138 | s.avail_out = len_out; 139 | s.next_out = out; 140 | 141 | inflate(&s, Z_FINISH); 142 | 143 | inflateEnd(&s); 144 | } 145 | 146 | void _zlib_deflate(u8 *in, u64 len_in, u8 *out, u64 len_out) 147 | { 148 | z_stream s; 149 | memset(&s, 0, sizeof(z_stream)); 150 | 151 | s.zalloc = Z_NULL; 152 | s.zfree = Z_NULL; 153 | s.opaque = Z_NULL; 154 | 155 | deflateInit(&s, Z_BEST_COMPRESSION); 156 | 157 | s.avail_in = len_in; 158 | s.next_in = in; 159 | s.avail_out = len_out; 160 | s.next_out = out; 161 | 162 | deflate(&s, Z_FINISH); 163 | 164 | deflateEnd(&s); 165 | } 166 | 167 | static mt19937_ctxt_t _mt19937_ctxt; 168 | static BOOL _mt_init = FALSE; 169 | 170 | u8 _get_rand_byte() 171 | { 172 | if(_mt_init == FALSE) 173 | { 174 | _mt_init = TRUE; 175 | mt19937_init(&_mt19937_ctxt, clock()); 176 | } 177 | 178 | return (u8)(mt19937_update(&_mt19937_ctxt) & 0xFF); 179 | } 180 | 181 | void _fill_rand_bytes(u8 *dst, u32 len) 182 | { 183 | u32 i; 184 | 185 | for(i = 0; i < len; i++) 186 | dst[i] = _get_rand_byte(); 187 | } 188 | 189 | void _memcpy_inv(u8 *dst, u8 *src, u32 len) 190 | { 191 | u32 i; 192 | for (i = 0; i < len; i++) 193 | dst[i] = ~src[i]; 194 | } 195 | 196 | void *_memdup(void *ptr, u32 size) 197 | { 198 | void *res = malloc(size); 199 | 200 | if(res != NULL) 201 | memcpy(res, ptr, size); 202 | 203 | return res; 204 | } 205 | 206 | u64 _x_to_u64(const s8 *hex) 207 | { 208 | u64 t = 0, res = 0; 209 | u32 len = strlen(hex); 210 | char c; 211 | 212 | while(len--) 213 | { 214 | c = *hex++; 215 | if(c >= '0' && c <= '9') 216 | t = c - '0'; 217 | else if(c >= 'a' && c <= 'f') 218 | t = c - 'a' + 10; 219 | else if(c >= 'A' && c <= 'F') 220 | t = c - 'A' + 10; 221 | else 222 | t = 0; 223 | res |= t << (len * 4); 224 | } 225 | 226 | return res; 227 | } 228 | 229 | u8 *_x_to_u8_buffer(const s8 *hex) 230 | { 231 | u32 len = strlen(hex); 232 | s8 xtmp[3] = {0, 0, 0}; 233 | 234 | //Must be aligned to 2. 235 | if(len % 2 != 0) 236 | return NULL; 237 | 238 | u8 *res = (u8 *)malloc(sizeof(u8) * len); 239 | u8 *ptr = res; 240 | 241 | while(len--) 242 | { 243 | xtmp[0] = *hex++; 244 | xtmp[1] = *hex++; 245 | 246 | *ptr++ = (u8)_x_to_u64(xtmp); 247 | } 248 | 249 | return res; 250 | } 251 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | scetool (C) 2011-2013 by naehrwert 2 | NP local license handling (C) 2012 by flatz 3 | 4 | ==> Setup <== 5 | - /data/keys : Keyfile. 6 | - /data/ldr_curves : Loader curves (7744 bytes). 7 | - /data/vsh_curves : VSH curves (360 bytes). 8 | - /data/idps : IDPS as binary file 9 | - /data/act.dat : act.dat 10 | - /rifs/* : *.rif files 11 | - /raps/* : *.rap files 12 | 13 | ==> Keyfile Format <== 14 | [keyname] 15 | type={SELF, RVK, PKG, SPP, OTHER} 16 | revision={00, ..., 18, 8000} 17 | version={..., 0001000000000000, ...} 18 | self_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM} 19 | key=... 20 | erk=... 21 | riv=... 22 | pub=... 23 | priv=... 24 | ctype=... 25 | 26 | ==> Keyset Example <== 27 | [metldr] 28 | type=SELF 29 | revision=00 30 | self_type=LDR 31 | erk=0000000000000000000000000000000000000000000000000000000000000000 32 | riv=00000000000000000000000000000000 33 | pub=00000000000000000000000000000000000000000000000000000000000000000000000000000000 34 | priv=000000000000000000000000000000000000000000 35 | ctype=00 36 | 37 | ==> NPDRM Key(set) Names <== 38 | - [NP_tid]: Title ID OMAC1 key. 39 | - [NP_ci]: Control info OMAC1 key. 40 | - [NP_klic_free]: Free klicensee. 41 | - [NP_klic_key]: klicensee key. 42 | - [NP_idps_const]: IDPS constant. 43 | - [NP_rif_key]: rif key. 44 | - [NP_sig]: Footer signature ECDSA keyset. 45 | 46 | ==> Override Keyset <== 47 | It should be a single hex-string consisting of: 48 | 32 bytes (Key) 16 bytes (IV) 40 bytes (Pub) 21 bytes (Priv) 1 byte (CType). 49 | 50 | ==> Help Text <== 51 | USAGE: scetool [options] command 52 | COMMANDS Parameters Explanation 53 | -h, --help Print this help. 54 | -k, --print-keys List keys. 55 | -i, --print-infos File-in Print SCE file info. 56 | -d, --decrypt File-in File-out Decrypt/dump SCE file. 57 | -e, --encrypt File-in File-out Encrypt/create SCE file. 58 | OPTIONS Possible Values Explanation 59 | -v, --verbose Enable verbose output. 60 | -r, --raw Enable raw value output. 61 | -t, --template File-in Template file (SELF only) 62 | -0, --sce-type SELF/RVK/PKG/SPP SCE File Type 63 | -1, --compress-data TRUE/FALSE(default) Whether to compress data or not. 64 | -s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not. 65 | -2, --key-revision e.g. 00,01,...,0A,... Key Revision 66 | -m, --meta-info 64 bytes Use provided meta info to decrypt. 67 | 68 | -K, --keyset 32(Key)16(IV) 69 | 40(Pub)21(Priv)1(CT) Override keyset. 70 | -3, --self-auth-id e.g. 1010000001000003 Authentication ID 71 | -4, --self-vendor-id e.g. 01000002 Vendor ID 72 | -5, --self-type LV0/LV1/LV2/APP/ISO/ 73 | LDR/NPDRM SELF Type 74 | -A, --self-app-version e.g. 0001000000000000 Application Version 75 | -6, --self-fw-version e.g. 0003004100000000 Firmware Version 76 | -7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not. 77 | -8, --self-ctrl-flags 32 bytes Override control flags. 78 | -9, --self-cap-flags 32 bytes Override capability flags. 79 | -b, --np-license-type LOCAL/FREE License Type 80 | -c, --np-app-type SPRX/EXEC/USPRX/UEXEC App Type (U* for updates) 81 | -f, --np-content-id Content ID 82 | -l, --np-klicensee 16 bytes Override klicensee. 83 | -g, --np-real-fname e.g. EBOOT.BIN Real Filename 84 | -j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not. 85 | 86 | ==> History <== 87 | Version 0.2.9 88 | - Plaintext sections will now take less space in metadata header keys array. 89 | - Added option to specifiy a template SELF to take configuration values from. 90 | - Added option to override the keyset used for en-/decryption. 91 | - Fixed NP application types. 92 | - [Firmware Version] will now be written to control info only. 93 | - [Application Version] will now be written to application info only. 94 | Version 0.2.8 (intermediate release): 95 | - Fixed minor bugs where scetool would crash. 96 | - Added SPP parsing. 97 | - Decrypting RVK/SPP will now write header+data to file. 98 | Version 0.2.7: 99 | - Added local NP license handling. 100 | - Added option to override klicensee. 101 | - Added option to disable section skipping (in SELF generation). 102 | Version 0.2.5: 103 | - Added option to use provided metadata info for decryption. 104 | - "PS3" path environment variable will now be searched for keys/ldr_curves/vsh_curves too. 105 | Version 0.2.4: 106 | - Added option to display raw values. 107 | - Moved factory Auth-IDs to (as they are on ps3devwiki now). 108 | Version 0.2.2: 109 | - Added options to override control/capability flags (32 bytes each). 110 | - Fixed where a false keyset would crash scetool when decrypting a file. 111 | - Some source level changes and optimizations. 112 | Version 0.2.1: 113 | - zlib is required to use scetool. 114 | - 'sdk_type' was changed to 'revision' in data/keys. 115 | 116 | ==> Greetings to <== 117 | - ps3dev.net 118 | - you know who you are! 119 | 120 | ==> Trivia <== 121 | http://bit.ly/QUji89 122 | -------------------------------------------------------------------------------- /aes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file aes.h 3 | * 4 | * \brief AES block cipher 5 | * 6 | * Copyright (C) 2006-2010, Brainspark B.V. 7 | * 8 | * This file is part of PolarSSL (http://www.polarssl.org) 9 | * Lead Maintainer: Paul Bakker 10 | * 11 | * All rights reserved. 12 | * 13 | * This program is free software; you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation; either version 2 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License along 24 | * with this program; if not, write to the Free Software Foundation, Inc., 25 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 26 | */ 27 | #ifndef POLARSSL_AES_H 28 | #define POLARSSL_AES_H 29 | 30 | #include 31 | 32 | #define AES_ENCRYPT 1 33 | #define AES_DECRYPT 0 34 | 35 | #define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ 36 | #define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ 37 | 38 | /** 39 | * \brief AES context structure 40 | */ 41 | typedef struct 42 | { 43 | int nr; /*!< number of rounds */ 44 | unsigned long *rk; /*!< AES round keys */ 45 | unsigned long buf[68]; /*!< unaligned data */ 46 | } 47 | aes_context; 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | /** 54 | * \brief AES key schedule (encryption) 55 | * 56 | * \param ctx AES context to be initialized 57 | * \param key encryption key 58 | * \param keysize must be 128, 192 or 256 59 | * 60 | * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH 61 | */ 62 | int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize ); 63 | 64 | /** 65 | * \brief AES key schedule (decryption) 66 | * 67 | * \param ctx AES context to be initialized 68 | * \param key decryption key 69 | * \param keysize must be 128, 192 or 256 70 | * 71 | * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH 72 | */ 73 | int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize ); 74 | 75 | /** 76 | * \brief AES-ECB block encryption/decryption 77 | * 78 | * \param ctx AES context 79 | * \param mode AES_ENCRYPT or AES_DECRYPT 80 | * \param input 16-byte input block 81 | * \param output 16-byte output block 82 | * 83 | * \return 0 if successful 84 | */ 85 | int aes_crypt_ecb( aes_context *ctx, 86 | int mode, 87 | const unsigned char input[16], 88 | unsigned char output[16] ); 89 | 90 | /** 91 | * \brief AES-CBC buffer encryption/decryption 92 | * Length should be a multiple of the block 93 | * size (16 bytes) 94 | * 95 | * \param ctx AES context 96 | * \param mode AES_ENCRYPT or AES_DECRYPT 97 | * \param length length of the input data 98 | * \param iv initialization vector (updated after use) 99 | * \param input buffer holding the input data 100 | * \param output buffer holding the output data 101 | * 102 | * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH 103 | */ 104 | int aes_crypt_cbc( aes_context *ctx, 105 | int mode, 106 | size_t length, 107 | unsigned char iv[16], 108 | const unsigned char *input, 109 | unsigned char *output ); 110 | 111 | /* 112 | * \brief AES-CTR buffer encryption/decryption 113 | * 114 | * Warning: You have to keep the maximum use of your counter in mind! 115 | * 116 | * Note: Due to the nature of CTR you should use the same key schedule for 117 | * both encryption and decryption. So a context initialized with 118 | * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. 119 | * 120 | * \param length The length of the data 121 | * \param nc_off The offset in the current stream_block (for resuming 122 | * within current cipher stream). The offset pointer to 123 | * should be 0 at the start of a stream. 124 | * \param nonce_counter The 128-bit nonce and counter. 125 | * \param stream_block The saved stream-block for resuming. Is overwritten 126 | * by the function. 127 | * \param input The input data stream 128 | * \param output The output data stream 129 | * 130 | * \return 0 if successful 131 | */ 132 | int aes_crypt_ctr( aes_context *ctx, 133 | size_t length, 134 | size_t *nc_off, 135 | unsigned char nonce_counter[16], 136 | unsigned char stream_block[16], 137 | const unsigned char *input, 138 | unsigned char *output ); 139 | 140 | #ifdef __cplusplus 141 | } 142 | #endif 143 | 144 | #endif /* aes.h */ 145 | -------------------------------------------------------------------------------- /sce_inlines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _SCE_INLINES_H_ 7 | #define _SCE_INLINES_H_ 8 | 9 | #include 10 | 11 | #include "types.h" 12 | #include "sce.h" 13 | 14 | static inline void _es_sce_header(sce_header_t *h) 15 | { 16 | h->magic = _ES32(h->magic); 17 | h->version = _ES32(h->version); 18 | h->key_revision = _ES16(h->key_revision); 19 | h->header_type = _ES16(h->header_type); 20 | h->metadata_offset = _ES32(h->metadata_offset); 21 | h->header_len = _ES64(h->header_len); 22 | h->data_len = _ES64(h->data_len); 23 | } 24 | 25 | static inline void _copy_es_sce_header(sce_header_t *dst, sce_header_t *src) 26 | { 27 | memcpy(dst, src, sizeof(sce_header_t)); 28 | _es_sce_header(dst); 29 | } 30 | 31 | static inline void _es_metadata_header(metadata_header_t *h) 32 | { 33 | h->sig_input_length = _ES64(h->sig_input_length); 34 | h->unknown_0 = _ES32(h->unknown_0); 35 | h->section_count = _ES32(h->section_count); 36 | h->key_count = _ES32(h->key_count); 37 | h->opt_header_size = _ES32(h->opt_header_size); 38 | h->unknown_1 = _ES32(h->unknown_1); 39 | h->unknown_2 = _ES32(h->unknown_2); 40 | } 41 | 42 | static inline void _copy_es_metadata_header(metadata_header_t *dst, metadata_header_t *src) 43 | { 44 | memcpy(dst, src, sizeof(metadata_header_t)); 45 | _es_metadata_header(dst); 46 | } 47 | 48 | static inline void _es_metadata_section_header(metadata_section_header_t *h) 49 | { 50 | h->data_offset = _ES64(h->data_offset); 51 | h->data_size = _ES64(h->data_size); 52 | h->type = _ES32(h->type); 53 | h->index = _ES32(h->index); 54 | h->hashed = _ES32(h->hashed); 55 | h->sha1_index = _ES32(h->sha1_index); 56 | h->encrypted = _ES32(h->encrypted); 57 | h->key_index = _ES32(h->key_index); 58 | h->iv_index = _ES32(h->iv_index); 59 | h->compressed = _ES32(h->compressed); 60 | } 61 | 62 | static inline void _copy_es_metadata_section_header(metadata_section_header_t *dst, metadata_section_header_t *src) 63 | { 64 | memcpy(dst, src, sizeof(metadata_section_header_t)); 65 | _es_metadata_section_header(dst); 66 | } 67 | 68 | static inline void _es_self_header(self_header_t *h) 69 | { 70 | h->header_type = _ES64(h->header_type); 71 | h->app_info_offset = _ES64(h->app_info_offset); 72 | h->elf_offset = _ES64(h->elf_offset); 73 | h->phdr_offset = _ES64(h->phdr_offset); 74 | h->shdr_offset = _ES64(h->shdr_offset); 75 | h->section_info_offset = _ES64(h->section_info_offset); 76 | h->sce_version_offset = _ES64(h->sce_version_offset); 77 | h->control_info_offset = _ES64(h->control_info_offset); 78 | h->control_info_size = _ES64(h->control_info_size); 79 | h->padding = _ES64(h->padding); 80 | } 81 | 82 | static inline void _copy_es_self_header(self_header_t *dst, self_header_t *src) 83 | { 84 | memcpy(dst, src, sizeof(self_header_t)); 85 | _es_self_header(dst); 86 | } 87 | 88 | static inline void _es_section_info(section_info_t *si) 89 | { 90 | si->offset = _ES64(si->offset); 91 | si->size = _ES64(si->size); 92 | si->compressed = _ES32(si->compressed); 93 | si->unknown_0 = _ES32(si->unknown_0); 94 | si->unknown_1 = _ES32(si->unknown_1); 95 | si->encrypted = _ES32(si->encrypted); 96 | } 97 | 98 | static inline void _copy_es_section_info(section_info_t *dst, section_info_t *src) 99 | { 100 | memcpy(dst, src, sizeof(section_info_t)); 101 | _es_section_info(dst); 102 | } 103 | 104 | static inline void _es_sce_version(sce_version_t *sv) 105 | { 106 | sv->header_type = _ES32(sv->header_type); 107 | sv->present = _ES32(sv->present); 108 | sv->size = _ES32(sv->size); 109 | sv->unknown_3 = _ES32(sv->unknown_3); 110 | } 111 | 112 | static inline void _copy_es_sce_version(sce_version_t *dst, sce_version_t *src) 113 | { 114 | memcpy(dst, src, sizeof(sce_version_t)); 115 | _es_sce_version(dst); 116 | } 117 | 118 | static inline void _es_app_info(app_info_t *ai) 119 | { 120 | ai->auth_id = _ES64(ai->auth_id); 121 | ai->vendor_id = _ES32(ai->vendor_id); 122 | ai->self_type = _ES32(ai->self_type); 123 | ai->version = _ES64(ai->version); 124 | ai->padding = _ES64(ai->padding); 125 | } 126 | 127 | static inline void _copy_es_app_info(app_info_t *dst, app_info_t *src) 128 | { 129 | memcpy(dst, src, sizeof(app_info_t)); 130 | _es_app_info(dst); 131 | } 132 | 133 | static inline void _es_control_info(control_info_t *ci) 134 | { 135 | ci->type = _ES32(ci->type); 136 | ci->size = _ES32(ci->size); 137 | ci->next = _ES64(ci->next); 138 | } 139 | 140 | static inline void _copy_es_control_info(control_info_t *dst, control_info_t *src) 141 | { 142 | memcpy(dst, src, sizeof(control_info_t)); 143 | _es_control_info(dst); 144 | } 145 | 146 | static inline void _es_ci_data_digest_40(ci_data_digest_40_t *dig) 147 | { 148 | dig->fw_version = _ES64(dig->fw_version); 149 | } 150 | 151 | static inline void _copy_es_ci_data_digest_40(ci_data_digest_40_t *dst, ci_data_digest_40_t *src) 152 | { 153 | memcpy(dst, src, sizeof(ci_data_digest_40_t)); 154 | _es_ci_data_digest_40(dst); 155 | } 156 | 157 | static inline void _es_ci_data_npdrm(ci_data_npdrm_t *np) 158 | { 159 | np->magic = _ES32(np->magic); 160 | np->unknown_0 = _ES32(np->unknown_0); 161 | np->license_type = _ES32(np->license_type); 162 | np->app_type = _ES32(np->app_type); 163 | np->unknown_1 = _ES64(np->unknown_1); 164 | np->unknown_2 = _ES64(np->unknown_2); 165 | } 166 | 167 | static inline void _copy_es_ci_data_npdrm(ci_data_npdrm_t *dst, ci_data_npdrm_t *src) 168 | { 169 | memcpy(dst, src, sizeof(ci_data_npdrm_t)); 170 | _es_ci_data_npdrm(dst); 171 | } 172 | 173 | static inline void _es_opt_header(opt_header_t *oh) 174 | { 175 | oh->type = _ES32(oh->type); 176 | oh->size = _ES32(oh->size); 177 | oh->next = _ES64(oh->next); 178 | } 179 | 180 | static inline void _copy_es_opt_header(opt_header_t *dst, opt_header_t *src) 181 | { 182 | memcpy(dst, src, sizeof(opt_header_t)); 183 | _es_opt_header(dst); 184 | } 185 | 186 | static inline void _es_oh_data_cap_flags(oh_data_cap_flags_t *cf) 187 | { 188 | cf->unk3 = _ES64(cf->unk3); 189 | cf->unk4 = _ES64(cf->unk4); 190 | cf->flags = _ES64(cf->flags); 191 | cf->unk6 = _ES32(cf->unk6); 192 | cf->unk7 = _ES32(cf->unk7); 193 | } 194 | 195 | static inline void _copy_es_cap_flags(oh_data_cap_flags_t *dst, oh_data_cap_flags_t *src) 196 | { 197 | memcpy(dst, src, sizeof(oh_data_cap_flags_t)); 198 | _es_oh_data_cap_flags(dst); 199 | } 200 | 201 | #endif 202 | -------------------------------------------------------------------------------- /tables.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include "types.h" 7 | #include "config.h" 8 | #include "util.h" 9 | #include "sce.h" 10 | #include "elf.h" 11 | #include "self.h" 12 | #include "keys.h" 13 | 14 | /*! SELF types. */ 15 | id_to_name_t _self_types[] = 16 | { 17 | {SELF_TYPE_LV0, "lv0"}, 18 | {SELF_TYPE_LV1, "lv1"}, 19 | {SELF_TYPE_LV2, "lv2"}, 20 | {SELF_TYPE_APP, "Application"}, 21 | {SELF_TYPE_ISO, "Isolated SPU Module"}, 22 | {SELF_TYPE_LDR, "Secure Loader"}, 23 | {SELF_TYPE_UNK_7, "Unknown 7"}, 24 | {SELF_TYPE_NPDRM, "NPDRM Application"}, 25 | {0, NULL} 26 | }; 27 | 28 | /*! SELF types as parameter. */ 29 | id_to_name_t _self_types_params[] = 30 | { 31 | {SELF_TYPE_LV0, "LV0"}, 32 | {SELF_TYPE_LV1, "LV1"}, 33 | {SELF_TYPE_LV2, "LV2"}, 34 | {SELF_TYPE_APP, "APP"}, 35 | {SELF_TYPE_ISO, "ISO"}, 36 | {SELF_TYPE_LDR, "LDR"}, 37 | //{SELF_TYPE_UNK_7, "UNK7"}, 38 | {SELF_TYPE_NPDRM, "NPDRM"}, 39 | {0, NULL} 40 | }; 41 | 42 | /* Control info types. */ 43 | id_to_name_t _control_info_types[] = 44 | { 45 | {CONTROL_INFO_TYPE_FLAGS, "Flags"}, 46 | {CONTROL_INFO_TYPE_DIGEST, "Digest"}, 47 | {CONTROL_INFO_TYPE_NPDRM, "NPDRM"}, 48 | {0, NULL} 49 | }; 50 | 51 | /*! Optional header types. */ 52 | id_to_name_t _optional_header_types[] = 53 | { 54 | {OPT_HEADER_TYPE_CAP_FLAGS, "Capability Flags"}, 55 | #ifdef CONFIG_DUMP_INDIV_SEED 56 | {OPT_HEADER_TYPE_INDIV_SEED, "Individuals Seed"}, 57 | #endif 58 | {0, NULL} 59 | }; 60 | 61 | /*! NPDRM application types. */ 62 | id_to_name_t _np_app_types[] = 63 | { 64 | {NP_TYPE_SPRX, "SPRX"}, 65 | {NP_TYPE_EXEC, "EXEC"}, 66 | {NP_TYPE_USPRX, "USPRX"}, 67 | {NP_TYPE_UEXEC, "UEXEC"}, 68 | {0, NULL}, 69 | }; 70 | 71 | /*! Auth IDs. */ 72 | id_to_name_t _auth_ids[] = 73 | { 74 | {0x1010000001000003, "retail game/update"}, 75 | {0x1020000401000001, "ps2emu"}, 76 | {0x1050000003000001, "lv2_kernel"}, 77 | {0x1070000001000002, "onicore_child"}, 78 | {0x1070000002000002, "mcore"}, 79 | {0x1070000003000002, "mgvideo"}, 80 | {0x1070000004000002, "swagner, swreset"}, 81 | {0x1070000017000001, "ss_init (lv1)"}, 82 | {0x107000001A000001, "ss_sc_init_pu (lv1)"}, 83 | {0x107000001C000001, "updater_frontend (lv1)"}, 84 | {0x107000001D000001, "sysmgr_ss (lv1)"}, 85 | {0x107000001F000001, "sb_iso_spu_module"}, 86 | {0x1070000020000001, "sc_iso, sc_iso_factory"}, 87 | {0x1070000021000001, "spp_verifier"}, 88 | {0x1070000022000001, "spu_pkg_rvk_verifier"}, 89 | {0x1070000023000001, "spu_token_processor"}, 90 | {0x1070000024000001, "sv_iso_spu_module"}, 91 | {0x1070000025000001, "aim_spu_module"}, 92 | {0x1070000026000001, "ss_sc_init"}, 93 | {0x1070000028000001, "factory_data_mngr_server (lv1)"}, 94 | {0x1070000029000001, "fdm_spu_module"}, 95 | {0x1070000032000001, "ss_server1 (lv1)"}, 96 | {0x1070000033000001, "ss_server2 (lv1)"}, 97 | {0x1070000034000001, "ss_server3 (lv1)"}, 98 | {0x1070000037000001, "mc_iso_spu_module"}, 99 | {0x1070000039000001, "bdp_bdmv"}, 100 | {0x107000003A000001, "bdj"}, 101 | {0x1070000040000001, "sys/external modules"}, 102 | {0x1070000041000001, "ps1emu"}, 103 | {0x1070000043000001, "me_iso_spu_module"}, 104 | {0x1070000046000001, "spu_mode_auth"}, 105 | {0x107000004C000001, "spu_utoken_processor"}, 106 | {0x1070000052000001, "sys/internal + vsh/module modules"}, 107 | {0x1070000055000001, "manu_info_spu_module"}, 108 | {0x1070000058000001, "me_iso_for_ps2emu"}, 109 | {0x1070000059000001, "sv_iso_for_ps2emu"}, 110 | {0x1070000300000001, "Lv2diag BD Remarry"}, 111 | {0x10700003FC000001, "emer_init"}, 112 | {0x10700003FD000001, "ps3swu"}, 113 | {0x10700003FF000001, "Lv2diag FW Stuff"}, 114 | {0x1070000409000001, "pspemu"}, 115 | {0x107000040A000001, "psp_translator"}, 116 | {0x107000040B000001, "pspemu modules"}, 117 | {0x107000040C000001, "pspemu drm"}, 118 | {0x1070000500000001, "cellftp"}, 119 | {0x1070000501000001, "hdd_copy"}, 120 | {0x10700005FC000001, "sys_audio"}, 121 | {0x10700005FD000001, "sys_init_osd"}, 122 | {0x10700005FF000001, "vsh"}, 123 | {0x1FF0000001000001, "lv0"}, 124 | {0x1FF0000002000001, "lv1"}, 125 | {0x1FF0000008000001, "lv1ldr"}, 126 | {0x1FF0000009000001, "lv2ldr"}, 127 | {0x1FF000000A000001, "isoldr"}, 128 | {0x1FF000000C000001, "appldr"}, 129 | {0, NULL} 130 | }; 131 | 132 | /*! Vendor IDs. */ 133 | id_to_name_t _vendor_ids[] = 134 | { 135 | {0xFF000000, "hv"}, 136 | {0x07000001, "system"}, 137 | {0x01000002, "normal"}, 138 | {0x05000002, "lv2"}, 139 | {0x02000003, "ps2emu"}, 140 | {0, NULL} 141 | }; 142 | 143 | /*! ELF machines. */ 144 | id_to_name_t _e_machines[] = 145 | { 146 | {EM_PPC, "PPC"}, 147 | {EM_PPC64, "PPC64"}, 148 | {EM_SPU, "SPU"}, 149 | {0, NULL} 150 | }; 151 | 152 | /*! ELF types. */ 153 | id_to_name_t _e_types[] = 154 | { 155 | {ET_EXEC, "EXEC"}, 156 | {ET_PS3PRX, "PRX"}, 157 | {0, NULL} 158 | }; 159 | 160 | /*! Section header types. */ 161 | id_to_name_t _sh_types[] = 162 | { 163 | {SHT_NULL, "NULL"}, 164 | {SHT_PROGBITS, "PROGBITS"}, 165 | {SHT_SYMTAB, "SYMTAB"}, 166 | {SHT_STRTAB, "STRTAB"}, 167 | {SHT_RELA, "RELA"}, 168 | {SHT_HASH, "HASH"}, 169 | {SHT_DYNAMIC, "DYNAMIC"}, 170 | {SHT_NOTE, "NOTE"}, 171 | {SHT_NOBITS, "NOBITS"}, 172 | {SHT_REL, "REL"}, 173 | {SHT_SHLIB, "SHLIB"}, 174 | {SHT_DYNSYM, "DYNSYM"}, 175 | {SHT_INIT_ARRAY, "INIT_ARRAY"}, 176 | {SHT_FINI_ARRAY, "FINI_ARRAY"}, 177 | {SHT_PREINIT_ARRAY, "PREINIT_ARRAY"}, 178 | {SHT_GROUP, "GROUP"}, 179 | {SHT_SYMTAB_SHNDX, "SYMTAB_SHNDX"}, 180 | {0, NULL} 181 | }; 182 | 183 | /*! Program header types. */ 184 | id_to_name_t _ph_types[] = 185 | { 186 | {PT_NULL, "NULL"}, 187 | {PT_LOAD, "LOAD"}, 188 | {PT_DYNAMIC, "DYNAMIC"}, 189 | {PT_INTERP, "INTERP"}, 190 | {PT_NOTE, "NOTE"}, 191 | {PT_SHLIB, "SHLIB"}, 192 | {PT_PHDR, "PHDR"}, 193 | {PT_TLS, "TLS"}, 194 | {PT_NUM, "NUM"}, 195 | {PT_PS3_PARAMS, "PARAMS"}, 196 | {PT_PS3_PRX, "PRX"}, 197 | {PT_PS3_PRX_RELOC, "PRXRELOC"}, 198 | {0, NULL} 199 | }; 200 | 201 | /*! Key types. */ 202 | id_to_name_t _key_types[] = 203 | { 204 | {KEYTYPE_SELF, "SELF"}, 205 | {KEYTYPE_RVK, "RVK"}, 206 | {KEYTYPE_PKG, "PKG"}, 207 | {KEYTYPE_SPP, "SPP"}, 208 | {KEYTYPE_OTHER, "OTHER"}, 209 | {0, NULL} 210 | }; 211 | 212 | /*! Key revisions. */ 213 | /* 214 | const s8 *_key_revisions[] = 215 | { 216 | "Revision 0", 217 | "0.92 - 3.30", 218 | "NP 0x02", 219 | "NP 0x03", 220 | "3.40 - 3.42", 221 | "NP 0x05", 222 | "NP 0x06", 223 | "3.50", 224 | "NP 0x08", 225 | "NP 0x09", 226 | "3.55", 227 | "NP 0x0b", 228 | "NP 0x0c", 229 | "3.56", 230 | "NP 0x0e", 231 | "NP 0x0f", 232 | "3.60 - 3.61", 233 | "NP 0x11", 234 | "NP 0x12", 235 | "3.65", 236 | "NP 0x14", 237 | "NP 0x15", 238 | "3.70 - 3.73", 239 | "NP 0x17", 240 | "NP 0x18", 241 | "0x19", 242 | "0x1A", 243 | "0x1B", 244 | "0x1C", 245 | "0x1D", 246 | "0x1E", 247 | "0x1F" 248 | }; 249 | */ 250 | 251 | /*! SCE header types. */ 252 | id_to_name_t _sce_header_types[] = 253 | { 254 | {SCE_HEADER_TYPE_SELF, "SELF"}, 255 | {SCE_HEADER_TYPE_RVK, "RVK"}, 256 | {SCE_HEADER_TYPE_PKG, "PKG"}, 257 | {SCE_HEADER_TYPE_SPP, "SPP"}, 258 | {0, NULL} 259 | }; 260 | -------------------------------------------------------------------------------- /np.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * Copyright (c) 2012 by flatz 4 | * This file is released under the GPLv2. 5 | */ 6 | 7 | #include 8 | 9 | #include "types.h" 10 | #include "config.h" 11 | #include "np.h" 12 | #include "self.h" 13 | #include "sce.h" 14 | #include "sce_inlines.h" 15 | #include "aes_omac.h" 16 | #include "sha1.h" 17 | #include "ecdsa.h" 18 | #include "keys.h" 19 | #include "aes.h" 20 | #include "util.h" 21 | 22 | /*! klicensee key. */ 23 | static u8 *_klicensee_key; 24 | 25 | static ci_data_npdrm_t *_sce_find_ci_npdrm(sce_buffer_ctxt_t *ctxt) 26 | { 27 | if(ctxt->self.cis != NULL) 28 | { 29 | LIST_FOREACH(iter, ctxt->self.cis) 30 | { 31 | control_info_t *ci = (control_info_t *)iter->value; 32 | 33 | if(ci->type == CONTROL_INFO_TYPE_NPDRM) 34 | { 35 | ci_data_npdrm_t *np = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t)); 36 | //Fixup. 37 | _es_ci_data_npdrm(np); 38 | return np; 39 | } 40 | } 41 | } 42 | 43 | return NULL; 44 | } 45 | 46 | void np_set_klicensee(u8 *klicensee) 47 | { 48 | _klicensee_key = klicensee; 49 | } 50 | 51 | BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt) 52 | { 53 | aes_context aes_ctxt; 54 | keyset_t *ks_np_klic_free, *ks_klic_key; 55 | u8 npdrm_key[0x10]; 56 | u8 npdrm_iv[0x10]; 57 | ci_data_npdrm_t *np; 58 | 59 | if((np = _sce_find_ci_npdrm(ctxt)) == NULL) 60 | return FALSE; 61 | 62 | //Try to find keysets. 63 | ks_klic_key = keyset_find_by_name(CONFIG_NP_KLIC_KEY_KNAME); 64 | if(ks_klic_key == NULL) 65 | return FALSE; 66 | if(_klicensee_key != NULL) 67 | memcpy(npdrm_key, _klicensee_key, 0x10); 68 | else if(np->license_type == NP_LICENSE_FREE) 69 | { 70 | ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME); 71 | if(ks_np_klic_free == NULL) 72 | return FALSE; 73 | memcpy(npdrm_key, ks_np_klic_free->erk, 0x10); 74 | } 75 | else if(np->license_type == NP_LICENSE_LOCAL) 76 | { 77 | if ((klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE) 78 | return FALSE; 79 | } 80 | else 81 | return FALSE; 82 | 83 | aes_setkey_dec(&aes_ctxt, ks_klic_key->erk, METADATA_INFO_KEYBITS); 84 | aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, npdrm_key, npdrm_key); 85 | 86 | memset(npdrm_iv, 0, 0x10); 87 | aes_setkey_dec(&aes_ctxt, npdrm_key, METADATA_INFO_KEYBITS); 88 | aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, sizeof(metadata_info_t), npdrm_iv, (u8 *)ctxt->metai, (u8 *)ctxt->metai); 89 | 90 | return TRUE; 91 | } 92 | 93 | BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt) 94 | { 95 | aes_context aes_ctxt; 96 | keyset_t *ks_np_klic_free, *ks_klic_key; 97 | u8 npdrm_key[0x10]; 98 | u8 npdrm_iv[0x10]; 99 | ci_data_npdrm_t *np; 100 | 101 | if((np = _sce_find_ci_npdrm(ctxt)) == NULL) 102 | return FALSE; 103 | 104 | //Try to find keysets. 105 | ks_klic_key = keyset_find_by_name(CONFIG_NP_KLIC_KEY_KNAME); 106 | if(ks_klic_key == NULL) 107 | return FALSE; 108 | if(_klicensee_key != NULL) 109 | memcpy(npdrm_key, _klicensee_key, 0x10); 110 | else if(np->license_type == NP_LICENSE_FREE) 111 | { 112 | ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME); 113 | if(ks_np_klic_free == NULL) 114 | return FALSE; 115 | memcpy(npdrm_key, ks_np_klic_free->erk, 0x10); 116 | } 117 | else if(np->license_type == NP_LICENSE_LOCAL) 118 | { 119 | if ((klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE) 120 | return FALSE; 121 | } 122 | else 123 | return FALSE; 124 | 125 | aes_setkey_dec(&aes_ctxt, ks_klic_key->erk, METADATA_INFO_KEYBITS); 126 | aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, npdrm_key, npdrm_key); 127 | 128 | memset(npdrm_iv, 0, 0x10); 129 | aes_setkey_enc(&aes_ctxt, npdrm_key, METADATA_INFO_KEYBITS); 130 | aes_crypt_cbc(&aes_ctxt, AES_ENCRYPT, sizeof(metadata_info_t), npdrm_iv, ctxt->scebuffer + ctxt->off_metai, ctxt->scebuffer + ctxt->off_metai); 131 | 132 | return TRUE; 133 | } 134 | 135 | BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp) 136 | { 137 | u32 i, len; 138 | u8 *cid_fname, ci_key[0x10]; 139 | keyset_t *ks_np_tid, *ks_np_ci, *ks_np_klic_free; 140 | u8 npdrm_key[0x10]; 141 | 142 | //Try to find keysets. 143 | ks_np_tid = keyset_find_by_name(CONFIG_NP_TID_KNAME); 144 | ks_np_ci = keyset_find_by_name(CONFIG_NP_CI_KNAME); 145 | if(ks_np_tid == NULL || ks_np_ci == NULL) 146 | return FALSE; 147 | 148 | //Can only create NPDRM SELF with local and free license. 149 | if(_klicensee_key != NULL) 150 | memcpy(npdrm_key, _klicensee_key, 0x10); 151 | else if(npconf->license_type == NP_LICENSE_FREE) 152 | { 153 | ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME); 154 | if(ks_np_klic_free == NULL) 155 | return FALSE; 156 | memcpy(npdrm_key, ks_np_klic_free->erk, 0x10); 157 | } 158 | else if(npconf->license_type == NP_LICENSE_LOCAL) 159 | { 160 | if ((klicensee_by_content_id((s8 *)npconf->content_id, npdrm_key)) == FALSE) 161 | return FALSE; 162 | } 163 | else 164 | return FALSE; 165 | 166 | cinp->magic = NP_CI_MAGIC; 167 | cinp->unknown_0 = 1; 168 | cinp->license_type = npconf->license_type; 169 | cinp->app_type = npconf->app_type; 170 | memcpy(cinp->content_id, npconf->content_id, 0x30); 171 | #ifdef CONFIG_PRIVATE_BUILD 172 | _fill_rand_bytes(cinp->rndpad, 0x10); 173 | #else 174 | //Better than boring random bytes! 175 | memcpy(cinp->rndpad, CONFIG_NPDRM_WATERMARK, 0x10); 176 | #endif 177 | cinp->unknown_1 = 0; 178 | cinp->unknown_2 = 0; 179 | 180 | //Fixup before hashing. 181 | _es_ci_data_npdrm(cinp); 182 | 183 | //Generate control info hash key. 184 | for(i = 0; i < 0x10; i++) 185 | ci_key[i] = ks_np_ci->erk[i] ^ npdrm_key[i]; 186 | 187 | //Create hash of title id and real filename. 188 | len = strlen(npconf->real_fname) + 0x30; 189 | cid_fname = (u8 *)malloc(sizeof(u8) * (len + 1)); 190 | memcpy(cid_fname, cinp->content_id, 0x30); 191 | strcpy((s8 *)(cid_fname + 0x30), npconf->real_fname); 192 | aes_omac1(cinp->hash_cid_fname, cid_fname, len, ks_np_tid->erk, KEYBITS(0x10)); 193 | 194 | //Create control info hash. 195 | aes_omac1(cinp->hash_ci, (u8 *)cinp, 0x60 /* Only the first 0x60 bytes are hashed. */ , ci_key, KEYBITS(0x10)); 196 | 197 | return TRUE; 198 | } 199 | 200 | //TODO: The fwrite/fread error checking was broken. 201 | //Maybe the MS runtime is returning the number of bytes written instead of the element count? 202 | BOOL np_sign_file(s8 *fname) 203 | { 204 | u8 padding_data[0x10] = 205 | { 206 | 0xbc, 0x3f, 0x7a, 0x48, 0xaf, 0x45, 0xef, 0x28, 0x3a, 0x05, 0x98, 0x10, 0xbc, 0x3f, 0x7a, 0x48 207 | }; 208 | 209 | keyset_t *ks; 210 | FILE *fp = NULL; 211 | u8 *buffer = NULL; 212 | u32 length; 213 | u32 padding; 214 | u8 hash[0x14], R[0x15], S[0x15]; 215 | 216 | //Try to find keyset. 217 | if((ks = keyset_find_by_name(CONFIG_NP_SIG_KNAME)) == NULL) 218 | return FALSE; 219 | 220 | if((fp = fopen(fname, "r+b")) == NULL) 221 | return FALSE; 222 | 223 | fseek(fp, 0, SEEK_END); 224 | length = ftell(fp); 225 | 226 | padding = length % 0x10; 227 | if(padding > 0) 228 | { 229 | fwrite(padding_data, sizeof(u8), padding, fp); 230 | length += padding; 231 | } 232 | 233 | fseek(fp, 0, SEEK_SET); 234 | if((buffer = (u8 *)malloc(length)) == NULL) 235 | { 236 | fclose(fp); 237 | return FALSE; 238 | } 239 | fread(buffer, sizeof(u8), length, fp); 240 | 241 | //Generate header hash. 242 | sha1(buffer, length, hash); 243 | 244 | //Generate signature. 245 | /* TODO: Set the right curve and private key */ 246 | ecdsa_set_curve(ks->ctype | USE_VSH_CURVE); 247 | ecdsa_set_pub(ks->pub); 248 | ecdsa_set_priv(ks->priv); 249 | ecdsa_sign(hash, R, S); 250 | fseek(fp, 0, SEEK_END); 251 | fwrite(R + 1, 0x14, 1, fp); 252 | fwrite(S + 1, 0x14, 1, fp); 253 | /* Let's be as stupid as sony here... */ 254 | fwrite(hash + 0xC, 8, 1, fp); 255 | 256 | free(buffer); 257 | fclose(fp); 258 | 259 | return TRUE; 260 | } 261 | -------------------------------------------------------------------------------- /ec.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2007,2008,2010 Segher Boessenkool 2 | // Licensed under the terms of the GNU GPL, version 2 3 | // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 4 | 5 | #include 6 | #include 7 | 8 | #include "types.h" 9 | #include "util.h" 10 | 11 | void bn_copy(u8 *d, u8 *a, u32 n); 12 | int bn_compare(u8 *a, u8 *b, u32 n); 13 | void bn_reduce(u8 *d, u8 *N, u32 n); 14 | void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n); 15 | void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n); 16 | void bn_to_mon(u8 *d, u8 *N, u32 n); 17 | void bn_from_mon(u8 *d, u8 *N, u32 n); 18 | void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n); 19 | void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n); 20 | int ecdsa_get_params(u32 type, u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy); 21 | 22 | struct point { 23 | u8 x[20]; 24 | u8 y[20]; 25 | }; 26 | 27 | static u8 ec_p[20]; 28 | static u8 ec_a[20]; // mon 29 | static u8 ec_b[20]; // mon 30 | static u8 ec_N[21]; 31 | static struct point ec_G; // mon 32 | static struct point ec_Q; // mon 33 | static u8 ec_k[21]; 34 | 35 | static void elt_copy(u8 *d, u8 *a) 36 | { 37 | memcpy(d, a, 20); 38 | } 39 | 40 | static void elt_zero(u8 *d) 41 | { 42 | memset(d, 0, 20); 43 | } 44 | 45 | static int elt_is_zero(u8 *d) 46 | { 47 | u32 i; 48 | 49 | for (i = 0; i < 20; i++) 50 | if (d[i] != 0) 51 | return 0; 52 | 53 | return 1; 54 | } 55 | 56 | static void elt_add(u8 *d, u8 *a, u8 *b) 57 | { 58 | bn_add(d, a, b, ec_p, 20); 59 | } 60 | 61 | static void elt_sub(u8 *d, u8 *a, u8 *b) 62 | { 63 | bn_sub(d, a, b, ec_p, 20); 64 | } 65 | 66 | static void elt_mul(u8 *d, u8 *a, u8 *b) 67 | { 68 | bn_mon_mul(d, a, b, ec_p, 20); 69 | } 70 | 71 | static void elt_square(u8 *d, u8 *a) 72 | { 73 | elt_mul(d, a, a); 74 | } 75 | 76 | static void elt_inv(u8 *d, u8 *a) 77 | { 78 | u8 s[20]; 79 | elt_copy(s, a); 80 | bn_mon_inv(d, s, ec_p, 20); 81 | } 82 | 83 | static void point_to_mon(struct point *p) 84 | { 85 | bn_to_mon(p->x, ec_p, 20); 86 | bn_to_mon(p->y, ec_p, 20); 87 | } 88 | 89 | static void point_from_mon(struct point *p) 90 | { 91 | bn_from_mon(p->x, ec_p, 20); 92 | bn_from_mon(p->y, ec_p, 20); 93 | } 94 | 95 | #if 0 96 | static int point_is_on_curve(u8 *p) 97 | { 98 | u8 s[20], t[20]; 99 | u8 *x, *y; 100 | 101 | x = p; 102 | y = p + 20; 103 | 104 | elt_square(t, x); 105 | elt_mul(s, t, x); 106 | 107 | elt_mul(t, x, ec_a); 108 | elt_add(s, s, t); 109 | 110 | elt_add(s, s, ec_b); 111 | 112 | elt_square(t, y); 113 | elt_sub(s, s, t); 114 | 115 | return elt_is_zero(s); 116 | } 117 | #endif 118 | 119 | static void point_zero(struct point *p) 120 | { 121 | elt_zero(p->x); 122 | elt_zero(p->y); 123 | } 124 | 125 | static int point_is_zero(struct point *p) 126 | { 127 | return elt_is_zero(p->x) && elt_is_zero(p->y); 128 | } 129 | 130 | static void point_double(struct point *r, struct point *p) 131 | { 132 | u8 s[20], t[20]; 133 | struct point pp; 134 | u8 *px, *py, *rx, *ry; 135 | 136 | pp = *p; 137 | 138 | px = pp.x; 139 | py = pp.y; 140 | rx = r->x; 141 | ry = r->y; 142 | 143 | if (elt_is_zero(py)) { 144 | point_zero(r); 145 | return; 146 | } 147 | 148 | elt_square(t, px); // t = px*px 149 | elt_add(s, t, t); // s = 2*px*px 150 | elt_add(s, s, t); // s = 3*px*px 151 | elt_add(s, s, ec_a); // s = 3*px*px + a 152 | elt_add(t, py, py); // t = 2*py 153 | elt_inv(t, t); // t = 1/(2*py) 154 | elt_mul(s, s, t); // s = (3*px*px+a)/(2*py) 155 | 156 | elt_square(rx, s); // rx = s*s 157 | elt_add(t, px, px); // t = 2*px 158 | elt_sub(rx, rx, t); // rx = s*s - 2*px 159 | 160 | elt_sub(t, px, rx); // t = -(rx-px) 161 | elt_mul(ry, s, t); // ry = -s*(rx-px) 162 | elt_sub(ry, ry, py); // ry = -s*(rx-px) - py 163 | } 164 | 165 | static void point_add(struct point *r, struct point *p, struct point *q) 166 | { 167 | u8 s[20], t[20], u[20]; 168 | u8 *px, *py, *qx, *qy, *rx, *ry; 169 | struct point pp, qq; 170 | 171 | pp = *p; 172 | qq = *q; 173 | 174 | px = pp.x; 175 | py = pp.y; 176 | qx = qq.x; 177 | qy = qq.y; 178 | rx = r->x; 179 | ry = r->y; 180 | 181 | if (point_is_zero(&pp)) { 182 | elt_copy(rx, qx); 183 | elt_copy(ry, qy); 184 | return; 185 | } 186 | 187 | if (point_is_zero(&qq)) { 188 | elt_copy(rx, px); 189 | elt_copy(ry, py); 190 | return; 191 | } 192 | 193 | elt_sub(u, qx, px); 194 | 195 | if (elt_is_zero(u)) { 196 | elt_sub(u, qy, py); 197 | if (elt_is_zero(u)) 198 | point_double(r, &pp); 199 | else 200 | point_zero(r); 201 | 202 | return; 203 | } 204 | 205 | elt_inv(t, u); // t = 1/(qx-px) 206 | elt_sub(u, qy, py); // u = qy-py 207 | elt_mul(s, t, u); // s = (qy-py)/(qx-px) 208 | 209 | elt_square(rx, s); // rx = s*s 210 | elt_add(t, px, qx); // t = px+qx 211 | elt_sub(rx, rx, t); // rx = s*s - (px+qx) 212 | 213 | elt_sub(t, px, rx); // t = -(rx-px) 214 | elt_mul(ry, s, t); // ry = -s*(rx-px) 215 | elt_sub(ry, ry, py); // ry = -s*(rx-px) - py 216 | } 217 | 218 | static void point_mul(struct point *d, u8 *a, struct point *b) // a is bignum 219 | { 220 | u32 i; 221 | u8 mask; 222 | 223 | point_zero(d); 224 | 225 | for (i = 0; i < 21; i++) 226 | for (mask = 0x80; mask != 0; mask >>= 1) { 227 | point_double(d, d); 228 | if ((a[i] & mask) != 0) 229 | point_add(d, d, b); 230 | } 231 | } 232 | 233 | static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash) 234 | { 235 | u8 e[21]; 236 | u8 kk[21]; 237 | u8 m[21]; 238 | u8 minv[21]; 239 | struct point mG; 240 | 241 | e[0] = 0; 242 | memcpy(e + 1, hash, 20); 243 | bn_reduce(e, ec_N, 21); 244 | 245 | try_again: 246 | _fill_rand_bytes(m, 21); 247 | m[0] = 0; 248 | if (bn_compare(m, ec_N, 21) >= 0) 249 | goto try_again; 250 | 251 | // R = (mG).x 252 | 253 | point_mul(&mG, m, &ec_G); 254 | point_from_mon(&mG); 255 | R[0] = 0; 256 | elt_copy(R+1, mG.x); 257 | 258 | // S = m**-1*(e + Rk) (mod N) 259 | 260 | bn_copy(kk, k, 21); 261 | bn_reduce(kk, ec_N, 21); 262 | bn_to_mon(m, ec_N, 21); 263 | bn_to_mon(e, ec_N, 21); 264 | bn_to_mon(R, ec_N, 21); 265 | bn_to_mon(kk, ec_N, 21); 266 | 267 | bn_mon_mul(S, R, kk, ec_N, 21); 268 | bn_add(kk, S, e, ec_N, 21); 269 | bn_mon_inv(minv, m, ec_N, 21); 270 | bn_mon_mul(S, minv, kk, ec_N, 21); 271 | 272 | bn_from_mon(R, ec_N, 21); 273 | bn_from_mon(S, ec_N, 21); 274 | } 275 | 276 | static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash) 277 | { 278 | u8 Sinv[21]; 279 | u8 e[21]; 280 | u8 w1[21], w2[21]; 281 | struct point r1, r2; 282 | u8 rr[21]; 283 | 284 | e[0] = 0; 285 | memcpy(e + 1, hash, 20); 286 | bn_reduce(e, ec_N, 21); 287 | 288 | bn_to_mon(R, ec_N, 21); 289 | bn_to_mon(S, ec_N, 21); 290 | bn_to_mon(e, ec_N, 21); 291 | 292 | bn_mon_inv(Sinv, S, ec_N, 21); 293 | 294 | bn_mon_mul(w1, e, Sinv, ec_N, 21); 295 | bn_mon_mul(w2, R, Sinv, ec_N, 21); 296 | 297 | bn_from_mon(w1, ec_N, 21); 298 | bn_from_mon(w2, ec_N, 21); 299 | 300 | point_mul(&r1, w1, &ec_G); 301 | point_mul(&r2, w2, Q); 302 | 303 | point_add(&r1, &r1, &r2); 304 | 305 | point_from_mon(&r1); 306 | 307 | rr[0] = 0; 308 | memcpy(rr + 1, r1.x, 20); 309 | bn_reduce(rr, ec_N, 21); 310 | 311 | bn_from_mon(R, ec_N, 21); 312 | bn_from_mon(S, ec_N, 21); 313 | 314 | return (bn_compare(rr, R, 21) == 0); 315 | } 316 | 317 | #if 0 318 | static void ec_priv_to_pub(u8 *k, u8 *Q) 319 | { 320 | point_mul(Q, k, ec_G); 321 | } 322 | #endif 323 | 324 | int ecdsa_set_curve(u32 type) 325 | { 326 | if (ecdsa_get_params(type, ec_p, ec_a, ec_b, ec_N, ec_G.x, ec_G.y) < 0) 327 | return -1; 328 | 329 | bn_to_mon(ec_a, ec_p, 20); 330 | bn_to_mon(ec_b, ec_p, 20); 331 | 332 | point_to_mon(&ec_G); 333 | 334 | return 0; 335 | } 336 | 337 | void ecdsa_set_pub(u8 *Q) 338 | { 339 | memcpy(ec_Q.x, Q, 20); 340 | memcpy(ec_Q.y, Q+20, 20); 341 | point_to_mon(&ec_Q); 342 | } 343 | 344 | void ecdsa_set_priv(u8 *k) 345 | { 346 | memcpy(ec_k, k, sizeof ec_k); 347 | } 348 | 349 | int ecdsa_verify(u8 *hash, u8 *R, u8 *S) 350 | { 351 | return check_ecdsa(&ec_Q, R, S, hash); 352 | } 353 | 354 | void ecdsa_sign(u8 *hash, u8 *R, u8 *S) 355 | { 356 | generate_ecdsa(R, S, ec_k, hash); 357 | } 358 | -------------------------------------------------------------------------------- /sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FIPS-180-1 compliant SHA-1 implementation 3 | * 4 | * Copyright (C) 2006-2010, Brainspark B.V. 5 | * 6 | * This file is part of PolarSSL (http://www.polarssl.org) 7 | * Lead Maintainer: Paul Bakker 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | */ 25 | /* 26 | * The SHA-1 standard was published by NIST in 1993. 27 | * 28 | * http://www.itl.nist.gov/fipspubs/fip180-1.htm 29 | */ 30 | 31 | #include "sha1.h" 32 | 33 | /* 34 | * 32-bit integer manipulation macros (big endian) 35 | */ 36 | #ifndef GET_ULONG_BE 37 | #define GET_ULONG_BE(n,b,i) \ 38 | { \ 39 | (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ 40 | | ( (unsigned long) (b)[(i) + 1] << 16 ) \ 41 | | ( (unsigned long) (b)[(i) + 2] << 8 ) \ 42 | | ( (unsigned long) (b)[(i) + 3] ); \ 43 | } 44 | #endif 45 | 46 | #ifndef PUT_ULONG_BE 47 | #define PUT_ULONG_BE(n,b,i) \ 48 | { \ 49 | (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 50 | (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 51 | (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 52 | (b)[(i) + 3] = (unsigned char) ( (n) ); \ 53 | } 54 | #endif 55 | 56 | /* 57 | * SHA-1 context setup 58 | */ 59 | void sha1_starts( sha1_context *ctx ) 60 | { 61 | ctx->total[0] = 0; 62 | ctx->total[1] = 0; 63 | 64 | ctx->state[0] = 0x67452301; 65 | ctx->state[1] = 0xEFCDAB89; 66 | ctx->state[2] = 0x98BADCFE; 67 | ctx->state[3] = 0x10325476; 68 | ctx->state[4] = 0xC3D2E1F0; 69 | } 70 | 71 | static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) 72 | { 73 | unsigned long temp, W[16], A, B, C, D, E; 74 | 75 | GET_ULONG_BE( W[ 0], data, 0 ); 76 | GET_ULONG_BE( W[ 1], data, 4 ); 77 | GET_ULONG_BE( W[ 2], data, 8 ); 78 | GET_ULONG_BE( W[ 3], data, 12 ); 79 | GET_ULONG_BE( W[ 4], data, 16 ); 80 | GET_ULONG_BE( W[ 5], data, 20 ); 81 | GET_ULONG_BE( W[ 6], data, 24 ); 82 | GET_ULONG_BE( W[ 7], data, 28 ); 83 | GET_ULONG_BE( W[ 8], data, 32 ); 84 | GET_ULONG_BE( W[ 9], data, 36 ); 85 | GET_ULONG_BE( W[10], data, 40 ); 86 | GET_ULONG_BE( W[11], data, 44 ); 87 | GET_ULONG_BE( W[12], data, 48 ); 88 | GET_ULONG_BE( W[13], data, 52 ); 89 | GET_ULONG_BE( W[14], data, 56 ); 90 | GET_ULONG_BE( W[15], data, 60 ); 91 | 92 | #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 93 | 94 | #define R(t) \ 95 | ( \ 96 | temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ 97 | W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ 98 | ( W[t & 0x0F] = S(temp,1) ) \ 99 | ) 100 | 101 | #define P(a,b,c,d,e,x) \ 102 | { \ 103 | e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ 104 | } 105 | 106 | A = ctx->state[0]; 107 | B = ctx->state[1]; 108 | C = ctx->state[2]; 109 | D = ctx->state[3]; 110 | E = ctx->state[4]; 111 | 112 | #define F(x,y,z) (z ^ (x & (y ^ z))) 113 | #define K 0x5A827999 114 | 115 | P( A, B, C, D, E, W[0] ); 116 | P( E, A, B, C, D, W[1] ); 117 | P( D, E, A, B, C, W[2] ); 118 | P( C, D, E, A, B, W[3] ); 119 | P( B, C, D, E, A, W[4] ); 120 | P( A, B, C, D, E, W[5] ); 121 | P( E, A, B, C, D, W[6] ); 122 | P( D, E, A, B, C, W[7] ); 123 | P( C, D, E, A, B, W[8] ); 124 | P( B, C, D, E, A, W[9] ); 125 | P( A, B, C, D, E, W[10] ); 126 | P( E, A, B, C, D, W[11] ); 127 | P( D, E, A, B, C, W[12] ); 128 | P( C, D, E, A, B, W[13] ); 129 | P( B, C, D, E, A, W[14] ); 130 | P( A, B, C, D, E, W[15] ); 131 | P( E, A, B, C, D, R(16) ); 132 | P( D, E, A, B, C, R(17) ); 133 | P( C, D, E, A, B, R(18) ); 134 | P( B, C, D, E, A, R(19) ); 135 | 136 | #undef K 137 | #undef F 138 | 139 | #define F(x,y,z) (x ^ y ^ z) 140 | #define K 0x6ED9EBA1 141 | 142 | P( A, B, C, D, E, R(20) ); 143 | P( E, A, B, C, D, R(21) ); 144 | P( D, E, A, B, C, R(22) ); 145 | P( C, D, E, A, B, R(23) ); 146 | P( B, C, D, E, A, R(24) ); 147 | P( A, B, C, D, E, R(25) ); 148 | P( E, A, B, C, D, R(26) ); 149 | P( D, E, A, B, C, R(27) ); 150 | P( C, D, E, A, B, R(28) ); 151 | P( B, C, D, E, A, R(29) ); 152 | P( A, B, C, D, E, R(30) ); 153 | P( E, A, B, C, D, R(31) ); 154 | P( D, E, A, B, C, R(32) ); 155 | P( C, D, E, A, B, R(33) ); 156 | P( B, C, D, E, A, R(34) ); 157 | P( A, B, C, D, E, R(35) ); 158 | P( E, A, B, C, D, R(36) ); 159 | P( D, E, A, B, C, R(37) ); 160 | P( C, D, E, A, B, R(38) ); 161 | P( B, C, D, E, A, R(39) ); 162 | 163 | #undef K 164 | #undef F 165 | 166 | #define F(x,y,z) ((x & y) | (z & (x | y))) 167 | #define K 0x8F1BBCDC 168 | 169 | P( A, B, C, D, E, R(40) ); 170 | P( E, A, B, C, D, R(41) ); 171 | P( D, E, A, B, C, R(42) ); 172 | P( C, D, E, A, B, R(43) ); 173 | P( B, C, D, E, A, R(44) ); 174 | P( A, B, C, D, E, R(45) ); 175 | P( E, A, B, C, D, R(46) ); 176 | P( D, E, A, B, C, R(47) ); 177 | P( C, D, E, A, B, R(48) ); 178 | P( B, C, D, E, A, R(49) ); 179 | P( A, B, C, D, E, R(50) ); 180 | P( E, A, B, C, D, R(51) ); 181 | P( D, E, A, B, C, R(52) ); 182 | P( C, D, E, A, B, R(53) ); 183 | P( B, C, D, E, A, R(54) ); 184 | P( A, B, C, D, E, R(55) ); 185 | P( E, A, B, C, D, R(56) ); 186 | P( D, E, A, B, C, R(57) ); 187 | P( C, D, E, A, B, R(58) ); 188 | P( B, C, D, E, A, R(59) ); 189 | 190 | #undef K 191 | #undef F 192 | 193 | #define F(x,y,z) (x ^ y ^ z) 194 | #define K 0xCA62C1D6 195 | 196 | P( A, B, C, D, E, R(60) ); 197 | P( E, A, B, C, D, R(61) ); 198 | P( D, E, A, B, C, R(62) ); 199 | P( C, D, E, A, B, R(63) ); 200 | P( B, C, D, E, A, R(64) ); 201 | P( A, B, C, D, E, R(65) ); 202 | P( E, A, B, C, D, R(66) ); 203 | P( D, E, A, B, C, R(67) ); 204 | P( C, D, E, A, B, R(68) ); 205 | P( B, C, D, E, A, R(69) ); 206 | P( A, B, C, D, E, R(70) ); 207 | P( E, A, B, C, D, R(71) ); 208 | P( D, E, A, B, C, R(72) ); 209 | P( C, D, E, A, B, R(73) ); 210 | P( B, C, D, E, A, R(74) ); 211 | P( A, B, C, D, E, R(75) ); 212 | P( E, A, B, C, D, R(76) ); 213 | P( D, E, A, B, C, R(77) ); 214 | P( C, D, E, A, B, R(78) ); 215 | P( B, C, D, E, A, R(79) ); 216 | 217 | #undef K 218 | #undef F 219 | 220 | ctx->state[0] += A; 221 | ctx->state[1] += B; 222 | ctx->state[2] += C; 223 | ctx->state[3] += D; 224 | ctx->state[4] += E; 225 | } 226 | 227 | /* 228 | * SHA-1 process buffer 229 | */ 230 | void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) 231 | { 232 | size_t fill; 233 | unsigned long left; 234 | 235 | if( ilen <= 0 ) 236 | return; 237 | 238 | left = ctx->total[0] & 0x3F; 239 | fill = 64 - left; 240 | 241 | ctx->total[0] += (unsigned long) ilen; 242 | ctx->total[0] &= 0xFFFFFFFF; 243 | 244 | if( ctx->total[0] < (unsigned long) ilen ) 245 | ctx->total[1]++; 246 | 247 | if( left && ilen >= fill ) 248 | { 249 | memcpy( (void *) (ctx->buffer + left), 250 | (void *) input, fill ); 251 | sha1_process( ctx, ctx->buffer ); 252 | input += fill; 253 | ilen -= fill; 254 | left = 0; 255 | } 256 | 257 | while( ilen >= 64 ) 258 | { 259 | sha1_process( ctx, input ); 260 | input += 64; 261 | ilen -= 64; 262 | } 263 | 264 | if( ilen > 0 ) 265 | { 266 | memcpy( (void *) (ctx->buffer + left), 267 | (void *) input, ilen ); 268 | } 269 | } 270 | 271 | static const unsigned char sha1_padding[64] = 272 | { 273 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 274 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 276 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 277 | }; 278 | 279 | /* 280 | * SHA-1 final digest 281 | */ 282 | void sha1_finish( sha1_context *ctx, unsigned char output[20] ) 283 | { 284 | unsigned long last, padn; 285 | unsigned long high, low; 286 | unsigned char msglen[8]; 287 | 288 | high = ( ctx->total[0] >> 29 ) 289 | | ( ctx->total[1] << 3 ); 290 | low = ( ctx->total[0] << 3 ); 291 | 292 | PUT_ULONG_BE( high, msglen, 0 ); 293 | PUT_ULONG_BE( low, msglen, 4 ); 294 | 295 | last = ctx->total[0] & 0x3F; 296 | padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 297 | 298 | sha1_update( ctx, (unsigned char *) sha1_padding, padn ); 299 | sha1_update( ctx, msglen, 8 ); 300 | 301 | PUT_ULONG_BE( ctx->state[0], output, 0 ); 302 | PUT_ULONG_BE( ctx->state[1], output, 4 ); 303 | PUT_ULONG_BE( ctx->state[2], output, 8 ); 304 | PUT_ULONG_BE( ctx->state[3], output, 12 ); 305 | PUT_ULONG_BE( ctx->state[4], output, 16 ); 306 | } 307 | 308 | /* 309 | * output = SHA-1( input buffer ) 310 | */ 311 | void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) 312 | { 313 | sha1_context ctx; 314 | 315 | sha1_starts( &ctx ); 316 | sha1_update( &ctx, input, ilen ); 317 | sha1_finish( &ctx, output ); 318 | 319 | memset( &ctx, 0, sizeof( sha1_context ) ); 320 | } 321 | 322 | /* 323 | * SHA-1 HMAC context setup 324 | */ 325 | void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen ) 326 | { 327 | size_t i; 328 | unsigned char sum[20]; 329 | 330 | if( keylen > 64 ) 331 | { 332 | sha1( key, keylen, sum ); 333 | keylen = 20; 334 | key = sum; 335 | } 336 | 337 | memset( ctx->ipad, 0x36, 64 ); 338 | memset( ctx->opad, 0x5C, 64 ); 339 | 340 | for( i = 0; i < keylen; i++ ) 341 | { 342 | ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); 343 | ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); 344 | } 345 | 346 | sha1_starts( ctx ); 347 | sha1_update( ctx, ctx->ipad, 64 ); 348 | 349 | memset( sum, 0, sizeof( sum ) ); 350 | } 351 | 352 | /* 353 | * SHA-1 HMAC process buffer 354 | */ 355 | void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) 356 | { 357 | sha1_update( ctx, input, ilen ); 358 | } 359 | 360 | /* 361 | * SHA-1 HMAC final digest 362 | */ 363 | void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) 364 | { 365 | unsigned char tmpbuf[20]; 366 | 367 | sha1_finish( ctx, tmpbuf ); 368 | sha1_starts( ctx ); 369 | sha1_update( ctx, ctx->opad, 64 ); 370 | sha1_update( ctx, tmpbuf, 20 ); 371 | sha1_finish( ctx, output ); 372 | 373 | memset( tmpbuf, 0, sizeof( tmpbuf ) ); 374 | } 375 | 376 | /* 377 | * SHA1 HMAC context reset 378 | */ 379 | void sha1_hmac_reset( sha1_context *ctx ) 380 | { 381 | sha1_starts( ctx ); 382 | sha1_update( ctx, ctx->ipad, 64 ); 383 | } 384 | 385 | /* 386 | * output = HMAC-SHA-1( hmac key, input buffer ) 387 | */ 388 | void sha1_hmac( const unsigned char *key, size_t keylen, 389 | const unsigned char *input, size_t ilen, 390 | unsigned char output[20] ) 391 | { 392 | sha1_context ctx; 393 | 394 | sha1_hmac_starts( &ctx, key, keylen ); 395 | sha1_hmac_update( &ctx, input, ilen ); 396 | sha1_hmac_finish( &ctx, output ); 397 | 398 | memset( &ctx, 0, sizeof( sha1_context ) ); 399 | } 400 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #ifdef _WIN32 13 | #include 14 | #include "getopt.h" 15 | #else 16 | #include 17 | #include 18 | #endif 19 | 20 | #include "types.h" 21 | #include "config.h" 22 | #include "aes.h" 23 | #include "util.h" 24 | #include "keys.h" 25 | #include "sce.h" 26 | #include "np.h" 27 | #include "self.h" 28 | #include "rvk.h" 29 | 30 | #include "frontend.h" 31 | 32 | /*! Shorter Versions of arg options. */ 33 | #define ARG_NULL no_argument 34 | #define ARG_NONE no_argument 35 | #define ARG_REQ required_argument 36 | #define ARG_OPT optional_argument 37 | 38 | /*! Verbose mode. */ 39 | BOOL _verbose = FALSE; 40 | /*! Raw mode. */ 41 | BOOL _raw = FALSE; 42 | 43 | /*! We got work. */ 44 | static BOOL _got_work = FALSE; 45 | /*! List keys. */ 46 | static BOOL _list_keys = FALSE; 47 | /*! Print infos on file. */ 48 | static BOOL _print_info = FALSE; 49 | /*! Decrypt file. */ 50 | static BOOL _decrypt_file = FALSE; 51 | /*! Encrypt file. */ 52 | static BOOL _encrypt_file = FALSE; 53 | 54 | /*! Parameters. */ 55 | s8 *_template = NULL; 56 | s8 *_file_type = NULL; 57 | s8 *_compress_data = NULL; 58 | s8 *_skip_sections = NULL; 59 | s8 *_key_rev = NULL; 60 | s8 *_meta_info = NULL; 61 | s8 *_keyset = NULL; 62 | s8 *_auth_id = NULL; 63 | s8 *_vendor_id = NULL; 64 | s8 *_self_type = NULL; 65 | s8 *_app_version = NULL; 66 | s8 *_fw_version = NULL; 67 | s8 *_add_shdrs = NULL; 68 | s8 *_ctrl_flags = NULL; 69 | s8 *_cap_flags = NULL; 70 | #ifdef CONFIG_CUSTOM_INDIV_SEED 71 | s8 *_indiv_seed = NULL; 72 | #endif 73 | s8 *_license_type = NULL; 74 | s8 *_app_type = NULL; 75 | s8 *_content_id = NULL; 76 | s8 *_klicensee = NULL; 77 | s8 *_real_fname = NULL; 78 | s8 *_add_sig = NULL; 79 | 80 | /*! Input file. */ 81 | static s8 *_file_in = NULL; 82 | /*! Ouput file. */ 83 | static s8 *_file_out = NULL; 84 | 85 | /*! Long option values. */ 86 | #define VAL_TEMPLATE 't' 87 | #define VAL_FILE_TYPE '0' 88 | #define VAL_COMPRESS_DATA '1' 89 | #define VAL_SKIP_SECTIONS 's' 90 | #define VAL_KEY_REV '2' 91 | #define VAL_META_INFO 'm' 92 | #define VAL_KEYSET 'K' 93 | #define VAL_AUTH_ID '3' 94 | #define VAL_VENDOR_ID '4' 95 | #define VAL_SELF_TYPE '5' 96 | #define VAL_APP_VERSION 'A' 97 | #define VAL_FW_VERSION '6' 98 | #define VAL_ADD_SHDRS '7' 99 | #define VAL_CTRL_FLAGS '8' 100 | #define VAL_CAP_FLAGS '9' 101 | #ifdef CONFIG_CUSTOM_INDIV_SEED 102 | #define VAL_INDIV_SEED 'a' 103 | #endif 104 | #define VAL_LICENSE_TYPE 'b' 105 | #define VAL_APP_TYPE 'c' 106 | #define VAL_CONTENT_ID 'f' 107 | #define VAL_KLICENSEE 'l' 108 | #define VAL_REAL_FNAME 'g' 109 | #define VAL_ADD_SIG 'j' 110 | 111 | static struct option options[] = 112 | { 113 | {"help", ARG_NONE, NULL, 'h'}, 114 | {"print-keys", ARG_NONE, NULL, 'k'}, 115 | {"print-infos", ARG_REQ, NULL, 'i'}, 116 | {"decrypt", ARG_REQ, NULL, 'd'}, 117 | {"encrypt", ARG_REQ, NULL, 'e'}, 118 | {"verbose", ARG_NONE, NULL, 'v'}, 119 | {"raw", ARG_NONE, NULL, 'r'}, 120 | {"template", ARG_REQ, NULL, VAL_TEMPLATE}, 121 | {"sce-type", ARG_REQ, NULL, VAL_FILE_TYPE}, 122 | {"compress-data", ARG_REQ, NULL, VAL_COMPRESS_DATA}, 123 | {"skip-sections", ARG_REQ, NULL, VAL_SKIP_SECTIONS}, 124 | {"key-revision", ARG_REQ, NULL, VAL_KEY_REV}, 125 | {"meta-info", ARG_REQ, NULL, VAL_META_INFO}, 126 | {"keyset", ARG_REQ, NULL, VAL_KEYSET}, 127 | {"self-auth-id", ARG_REQ, NULL, VAL_AUTH_ID}, 128 | {"self-vendor-id", ARG_REQ, NULL, VAL_VENDOR_ID}, 129 | {"self-type", ARG_REQ, NULL, VAL_SELF_TYPE}, 130 | {"self-app-version", ARG_REQ, NULL, VAL_APP_VERSION}, 131 | {"self-fw-version", ARG_REQ, NULL, VAL_FW_VERSION}, 132 | {"self-add-shdrs", ARG_REQ, NULL, VAL_ADD_SHDRS}, 133 | {"self-ctrl-flags", ARG_REQ, NULL, VAL_CTRL_FLAGS}, 134 | {"self-cap-flags", ARG_REQ, NULL, VAL_CAP_FLAGS}, 135 | #ifdef CONFIG_CUSTOM_INDIV_SEED 136 | {"self-indiv-seed", ARG_REQ, NULL, VAL_INDIV_SEED}, 137 | #endif 138 | {"np-license-type", ARG_REQ, NULL, VAL_LICENSE_TYPE}, 139 | {"np-app-type", ARG_REQ, NULL, VAL_APP_TYPE}, 140 | {"np-content-id", ARG_REQ, NULL, VAL_CONTENT_ID}, 141 | {"np-klicensee", ARG_REQ, NULL, VAL_KLICENSEE}, 142 | {"np-real-fname", ARG_REQ, NULL, VAL_REAL_FNAME}, 143 | {"np-add-sig", ARG_REQ, NULL, VAL_ADD_SIG}, 144 | {NULL, ARG_NULL, NULL, 0} 145 | }; 146 | 147 | static void print_version() 148 | { 149 | printf("scetool " SCETOOL_VERSION " (C) 2011-2013 by naehrwert\n"); 150 | printf("NP local license handling (C) 2012 by flatz\n"); 151 | //printf("[Build Date/Time: %s/%s]\n", __DATE__, __TIME__); 152 | } 153 | 154 | #include 155 | 156 | static void print_usage() 157 | { 158 | print_version(); 159 | 160 | printf("USAGE: scetool [options] command\n"); 161 | printf("COMMANDS Parameters Explanation\n"); 162 | printf(" -h, --help Print this help.\n"); 163 | printf(" -k, --print-keys List keys.\n"); 164 | printf(" -i, --print-infos File-in Print SCE file info.\n"); 165 | printf(" -d, --decrypt File-in File-out Decrypt/dump SCE file.\n"); 166 | printf(" -e, --encrypt File-in File-out Encrypt/create SCE file.\n"); 167 | printf("OPTIONS Possible Values Explanation\n"); 168 | printf(" -v, --verbose Enable verbose output.\n"); 169 | printf(" -r, --raw Enable raw value output.\n"); 170 | printf(" -t, --template File-in Template file (SELF only)\n"); 171 | printf(" -0, --sce-type SELF/RVK/PKG/SPP SCE File Type\n"); 172 | printf(" -1, --compress-data TRUE/FALSE(default) Whether to compress data or not.\n"); 173 | printf(" -s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not.\n"); 174 | printf(" -2, --key-revision e.g. 00,01,...,0A,... Key Revision\n"); 175 | printf(" -m, --meta-info 64 bytes Use provided meta info to decrypt.\n"); 176 | printf(" -K, --keyset 32(Key)16(IV)\n"); 177 | printf(" 40(Pub)21(Priv)1(CT) Override keyset.\n"); 178 | printf(" -3, --self-auth-id e.g. 1010000001000003 Authentication ID\n"); 179 | printf(" -4, --self-vendor-id e.g. 01000002 Vendor ID\n"); 180 | printf(" -5, --self-type LV0/LV1/LV2/APP/ISO/\n"); 181 | printf(" LDR/NPDRM SELF Type\n"); 182 | printf(" -A, --self-app-version e.g. 0001000000000000 Application Version\n"); 183 | printf(" -6, --self-fw-version e.g. 0003004100000000 Firmware Version\n"); 184 | printf(" -7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not.\n"); 185 | printf(" -8, --self-ctrl-flags 32 bytes Override control flags.\n"); 186 | printf(" -9, --self-cap-flags 32 bytes Override capability flags.\n"); 187 | #ifdef CONFIG_CUSTOM_INDIV_SEED 188 | printf(" -a, --self-indiv-seed 256 bytes Individuals Seed (ISO only)\n"); 189 | #endif 190 | printf(" -b, --np-license-type LOCAL/FREE License Type\n"); 191 | printf(" -c, --np-app-type SPRX/EXEC/USPRX/UEXEC App Type (U* for updates)\n"); 192 | printf(" -f, --np-content-id Content ID\n"); 193 | printf(" -l, --np-klicensee 16 bytes Override klicensee.\n"); 194 | printf(" -g, --np-real-fname e.g. EBOOT.BIN Real Filename\n"); 195 | printf(" -j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not.\n"); 196 | 197 | //getchar(); 198 | 199 | exit(1); 200 | } 201 | 202 | static void parse_args(int argc, char **argv) 203 | { 204 | char c; 205 | 206 | #ifdef CONFIG_CUSTOM_INDIV_SEED 207 | while((c = getopt_long(argc, argv, "hki:d:e:vrt:0:1:s:2:m:K:3:4:5:A:6:7:8:9:a:b:c:f:l:g:j:", options, NULL)) != -1) 208 | #else 209 | while((c = getopt_long(argc, argv, "hki:d:e:vrt:0:1:s:2:m:K:3:4:5:A:6:7:8:9:b:c:f:l:g:j:", options, NULL)) != -1) 210 | #endif 211 | { 212 | switch(c) 213 | { 214 | case 'h': 215 | print_usage(); 216 | break; 217 | case 'k': 218 | _got_work = TRUE; 219 | _list_keys = TRUE; 220 | //Got all args. 221 | return; 222 | break; 223 | case 'i': 224 | _got_work = TRUE; 225 | _print_info = TRUE; 226 | _file_in = optarg; 227 | //Got all args. 228 | return; 229 | break; 230 | case 'd': 231 | _got_work = TRUE; 232 | _decrypt_file = TRUE; 233 | _file_in = optarg; 234 | //Need more args. 235 | goto get_args; 236 | break; 237 | case 'e': 238 | _got_work = TRUE; 239 | _encrypt_file = TRUE; 240 | _file_in = optarg; 241 | //Need more args. 242 | goto get_args; 243 | break; 244 | case 'v': 245 | _verbose = TRUE; 246 | break; 247 | case 'r': 248 | _raw = TRUE; 249 | break; 250 | case VAL_TEMPLATE: 251 | _template = optarg; 252 | break; 253 | case VAL_FILE_TYPE: 254 | _file_type = optarg; 255 | break; 256 | case VAL_COMPRESS_DATA: 257 | _compress_data = optarg; 258 | break; 259 | case VAL_SKIP_SECTIONS: 260 | _skip_sections = optarg; 261 | break; 262 | case VAL_KEY_REV: 263 | _key_rev = optarg; 264 | break; 265 | case VAL_META_INFO: 266 | _meta_info = optarg; 267 | break; 268 | case VAL_KEYSET: 269 | _keyset = optarg; 270 | break; 271 | case VAL_AUTH_ID: 272 | _auth_id = optarg; 273 | break; 274 | case VAL_VENDOR_ID: 275 | _vendor_id = optarg; 276 | break; 277 | case VAL_SELF_TYPE: 278 | _self_type = optarg; 279 | break; 280 | case VAL_APP_VERSION: 281 | _app_version = optarg; 282 | break; 283 | case VAL_FW_VERSION: 284 | _fw_version = optarg; 285 | break; 286 | case VAL_ADD_SHDRS: 287 | _add_shdrs = optarg; 288 | break; 289 | case VAL_CTRL_FLAGS: 290 | _ctrl_flags = optarg; 291 | break; 292 | case VAL_CAP_FLAGS: 293 | _cap_flags = optarg; 294 | break; 295 | #ifdef CONFIG_CUSTOM_INDIV_SEED 296 | case VAL_INDIV_SEED: 297 | _indiv_seed = optarg; 298 | break; 299 | #endif 300 | case VAL_LICENSE_TYPE: 301 | _license_type = optarg; 302 | break; 303 | case VAL_APP_TYPE: 304 | _app_type = optarg; 305 | break; 306 | case VAL_CONTENT_ID: 307 | _content_id = optarg; 308 | break; 309 | case VAL_KLICENSEE: 310 | _klicensee = optarg; 311 | break; 312 | case VAL_REAL_FNAME: 313 | _real_fname = optarg; 314 | break; 315 | case VAL_ADD_SIG: 316 | _add_sig = optarg; 317 | break; 318 | case '?': 319 | print_usage(); 320 | break; 321 | } 322 | } 323 | 324 | get_args:; 325 | 326 | //Additional decrypt args. 327 | if(_decrypt_file) 328 | { 329 | if(argc - optind < 1) 330 | { 331 | printf("[*] Error: Decrypt needs an output file!\n"); 332 | print_usage(); 333 | } 334 | 335 | _file_out = argv[optind]; 336 | } 337 | 338 | //Additional encrypt args. 339 | if(_encrypt_file) 340 | { 341 | if(argc - optind < 1) 342 | { 343 | printf("[*] Error: Encrypt needs an input and output file!\n"); 344 | print_usage(); 345 | } 346 | 347 | _file_out = argv[optind]; 348 | } 349 | } 350 | 351 | #ifndef _DEBUG 352 | int main(int argc, char **argv) 353 | { 354 | s8 *ps3 = NULL, path[256]; 355 | 356 | //Check for args. 357 | if(argc <= 1) 358 | print_usage(); 359 | 360 | //Parse them. 361 | parse_args(argc, argv); 362 | 363 | //Only options won't suffice. 364 | if(_got_work == FALSE) 365 | print_usage(); 366 | 367 | print_version(); 368 | printf("\n"); 369 | 370 | //Try to get path from env:PS3. 371 | if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) 372 | if(access(ps3, 0) != 0) 373 | ps3 = NULL; 374 | 375 | //Load keysets. 376 | if(ps3 != NULL) 377 | { 378 | sprintf(path, "%s/%s", ps3, CONFIG_KEYS_FILE); 379 | if(access(path, 0) != 0) 380 | sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_KEYS_FILE); 381 | } 382 | else 383 | sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_KEYS_FILE); 384 | if(keys_load(path) == TRUE) 385 | _LOG_VERBOSE("Loaded keysets.\n"); 386 | else 387 | { 388 | if(_list_keys == TRUE) 389 | { 390 | printf("[*] Error: Could not load keys.\n"); 391 | return 0; 392 | } 393 | else 394 | printf("[*] Warning: Could not load keys.\n"); 395 | } 396 | 397 | //Load curves. 398 | if(ps3 != NULL) 399 | { 400 | sprintf(path, "%s/%s", ps3, CONFIG_CURVES_FILE); 401 | if(access(path, 0) != 0) 402 | sprintf(path, "%s/%s", CONFIG_CURVES_PATH, CONFIG_CURVES_FILE); 403 | } 404 | else 405 | sprintf(path, "%s/%s", CONFIG_CURVES_PATH, CONFIG_CURVES_FILE); 406 | if(curves_load(path) == TRUE) 407 | _LOG_VERBOSE("Loaded loader curves.\n"); 408 | else 409 | printf("[*] Warning: Could not load loader curves.\n"); 410 | 411 | //Load curves. 412 | if(ps3 != NULL) 413 | { 414 | sprintf(path, "%s/%s", ps3, CONFIG_VSH_CURVES_FILE); 415 | if(access(path, 0) != 0) 416 | sprintf(path, "%s/%s", CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE); 417 | } 418 | else 419 | sprintf(path, "%s/%s", CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE); 420 | if(vsh_curves_load(path) == TRUE) 421 | _LOG_VERBOSE("Loaded vsh curves.\n"); 422 | else 423 | printf("[*] Warning: Could not load vsh curves.\n"); 424 | 425 | //Set klicensee. 426 | if(_klicensee != NULL) 427 | { 428 | if(strlen(_klicensee) != 0x10*2) 429 | { 430 | printf("[*] Error: klicensee needs to be 16 bytes.\n"); 431 | return FALSE; 432 | } 433 | np_set_klicensee(_x_to_u8_buffer(_klicensee)); 434 | } 435 | 436 | if(_list_keys == TRUE) 437 | { 438 | printf("[*] Loaded keysets:\n"); 439 | _print_key_list(stdout); 440 | } 441 | else if(_print_info) 442 | frontend_print_infos(_file_in); 443 | else if(_decrypt_file) 444 | frontend_decrypt(_file_in, _file_out); 445 | else if(_encrypt_file) 446 | frontend_encrypt(_file_in, _file_out); 447 | 448 | return 0; 449 | } 450 | #endif 451 | -------------------------------------------------------------------------------- /zconf.h: -------------------------------------------------------------------------------- 1 | /* zconf.h -- configuration of the zlib compression library 2 | * Copyright (C) 1995-2010 Jean-loup Gailly. 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* @(#) $Id$ */ 7 | 8 | #ifndef ZCONF_H 9 | #define ZCONF_H 10 | 11 | /* 12 | * If you *really* need a unique prefix for all types and library functions, 13 | * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. 14 | * Even better than compiling with -DZ_PREFIX would be to use configure to set 15 | * this permanently in zconf.h using "./configure --zprefix". 16 | */ 17 | #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ 18 | 19 | /* all linked symbols */ 20 | # define _dist_code z__dist_code 21 | # define _length_code z__length_code 22 | # define _tr_align z__tr_align 23 | # define _tr_flush_block z__tr_flush_block 24 | # define _tr_init z__tr_init 25 | # define _tr_stored_block z__tr_stored_block 26 | # define _tr_tally z__tr_tally 27 | # define adler32 z_adler32 28 | # define adler32_combine z_adler32_combine 29 | # define adler32_combine64 z_adler32_combine64 30 | # define compress z_compress 31 | # define compress2 z_compress2 32 | # define compressBound z_compressBound 33 | # define crc32 z_crc32 34 | # define crc32_combine z_crc32_combine 35 | # define crc32_combine64 z_crc32_combine64 36 | # define deflate z_deflate 37 | # define deflateBound z_deflateBound 38 | # define deflateCopy z_deflateCopy 39 | # define deflateEnd z_deflateEnd 40 | # define deflateInit2_ z_deflateInit2_ 41 | # define deflateInit_ z_deflateInit_ 42 | # define deflateParams z_deflateParams 43 | # define deflatePrime z_deflatePrime 44 | # define deflateReset z_deflateReset 45 | # define deflateSetDictionary z_deflateSetDictionary 46 | # define deflateSetHeader z_deflateSetHeader 47 | # define deflateTune z_deflateTune 48 | # define deflate_copyright z_deflate_copyright 49 | # define get_crc_table z_get_crc_table 50 | # define gz_error z_gz_error 51 | # define gz_intmax z_gz_intmax 52 | # define gz_strwinerror z_gz_strwinerror 53 | # define gzbuffer z_gzbuffer 54 | # define gzclearerr z_gzclearerr 55 | # define gzclose z_gzclose 56 | # define gzclose_r z_gzclose_r 57 | # define gzclose_w z_gzclose_w 58 | # define gzdirect z_gzdirect 59 | # define gzdopen z_gzdopen 60 | # define gzeof z_gzeof 61 | # define gzerror z_gzerror 62 | # define gzflush z_gzflush 63 | # define gzgetc z_gzgetc 64 | # define gzgets z_gzgets 65 | # define gzoffset z_gzoffset 66 | # define gzoffset64 z_gzoffset64 67 | # define gzopen z_gzopen 68 | # define gzopen64 z_gzopen64 69 | # define gzprintf z_gzprintf 70 | # define gzputc z_gzputc 71 | # define gzputs z_gzputs 72 | # define gzread z_gzread 73 | # define gzrewind z_gzrewind 74 | # define gzseek z_gzseek 75 | # define gzseek64 z_gzseek64 76 | # define gzsetparams z_gzsetparams 77 | # define gztell z_gztell 78 | # define gztell64 z_gztell64 79 | # define gzungetc z_gzungetc 80 | # define gzwrite z_gzwrite 81 | # define inflate z_inflate 82 | # define inflateBack z_inflateBack 83 | # define inflateBackEnd z_inflateBackEnd 84 | # define inflateBackInit_ z_inflateBackInit_ 85 | # define inflateCopy z_inflateCopy 86 | # define inflateEnd z_inflateEnd 87 | # define inflateGetHeader z_inflateGetHeader 88 | # define inflateInit2_ z_inflateInit2_ 89 | # define inflateInit_ z_inflateInit_ 90 | # define inflateMark z_inflateMark 91 | # define inflatePrime z_inflatePrime 92 | # define inflateReset z_inflateReset 93 | # define inflateReset2 z_inflateReset2 94 | # define inflateSetDictionary z_inflateSetDictionary 95 | # define inflateSync z_inflateSync 96 | # define inflateSyncPoint z_inflateSyncPoint 97 | # define inflateUndermine z_inflateUndermine 98 | # define inflate_copyright z_inflate_copyright 99 | # define inflate_fast z_inflate_fast 100 | # define inflate_table z_inflate_table 101 | # define uncompress z_uncompress 102 | # define zError z_zError 103 | # define zcalloc z_zcalloc 104 | # define zcfree z_zcfree 105 | # define zlibCompileFlags z_zlibCompileFlags 106 | # define zlibVersion z_zlibVersion 107 | 108 | /* all zlib typedefs in zlib.h and zconf.h */ 109 | # define Byte z_Byte 110 | # define Bytef z_Bytef 111 | # define alloc_func z_alloc_func 112 | # define charf z_charf 113 | # define free_func z_free_func 114 | # define gzFile z_gzFile 115 | # define gz_header z_gz_header 116 | # define gz_headerp z_gz_headerp 117 | # define in_func z_in_func 118 | # define intf z_intf 119 | # define out_func z_out_func 120 | # define uInt z_uInt 121 | # define uIntf z_uIntf 122 | # define uLong z_uLong 123 | # define uLongf z_uLongf 124 | # define voidp z_voidp 125 | # define voidpc z_voidpc 126 | # define voidpf z_voidpf 127 | 128 | /* all zlib structs in zlib.h and zconf.h */ 129 | # define gz_header_s z_gz_header_s 130 | # define internal_state z_internal_state 131 | 132 | #endif 133 | 134 | #if defined(__MSDOS__) && !defined(MSDOS) 135 | # define MSDOS 136 | #endif 137 | #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) 138 | # define OS2 139 | #endif 140 | #if defined(_WINDOWS) && !defined(WINDOWS) 141 | # define WINDOWS 142 | #endif 143 | #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) 144 | # ifndef WIN32 145 | # define WIN32 146 | # endif 147 | #endif 148 | #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) 149 | # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) 150 | # ifndef SYS16BIT 151 | # define SYS16BIT 152 | # endif 153 | # endif 154 | #endif 155 | 156 | /* 157 | * Compile with -DMAXSEG_64K if the alloc function cannot allocate more 158 | * than 64k bytes at a time (needed on systems with 16-bit int). 159 | */ 160 | #ifdef SYS16BIT 161 | # define MAXSEG_64K 162 | #endif 163 | #ifdef MSDOS 164 | # define UNALIGNED_OK 165 | #endif 166 | 167 | #ifdef __STDC_VERSION__ 168 | # ifndef STDC 169 | # define STDC 170 | # endif 171 | # if __STDC_VERSION__ >= 199901L 172 | # ifndef STDC99 173 | # define STDC99 174 | # endif 175 | # endif 176 | #endif 177 | #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) 178 | # define STDC 179 | #endif 180 | #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) 181 | # define STDC 182 | #endif 183 | #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) 184 | # define STDC 185 | #endif 186 | #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) 187 | # define STDC 188 | #endif 189 | 190 | #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ 191 | # define STDC 192 | #endif 193 | 194 | #ifndef STDC 195 | # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ 196 | # define const /* note: need a more gentle solution here */ 197 | # endif 198 | #endif 199 | 200 | /* Some Mac compilers merge all .h files incorrectly: */ 201 | #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) 202 | # define NO_DUMMY_DECL 203 | #endif 204 | 205 | /* Maximum value for memLevel in deflateInit2 */ 206 | #ifndef MAX_MEM_LEVEL 207 | # ifdef MAXSEG_64K 208 | # define MAX_MEM_LEVEL 8 209 | # else 210 | # define MAX_MEM_LEVEL 9 211 | # endif 212 | #endif 213 | 214 | /* Maximum value for windowBits in deflateInit2 and inflateInit2. 215 | * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files 216 | * created by gzip. (Files created by minigzip can still be extracted by 217 | * gzip.) 218 | */ 219 | #ifndef MAX_WBITS 220 | # define MAX_WBITS 15 /* 32K LZ77 window */ 221 | #endif 222 | 223 | /* The memory requirements for deflate are (in bytes): 224 | (1 << (windowBits+2)) + (1 << (memLevel+9)) 225 | that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) 226 | plus a few kilobytes for small objects. For example, if you want to reduce 227 | the default memory requirements from 256K to 128K, compile with 228 | make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" 229 | Of course this will generally degrade compression (there's no free lunch). 230 | 231 | The memory requirements for inflate are (in bytes) 1 << windowBits 232 | that is, 32K for windowBits=15 (default value) plus a few kilobytes 233 | for small objects. 234 | */ 235 | 236 | /* Type declarations */ 237 | 238 | #ifndef OF /* function prototypes */ 239 | # ifdef STDC 240 | # define OF(args) args 241 | # else 242 | # define OF(args) () 243 | # endif 244 | #endif 245 | 246 | /* The following definitions for FAR are needed only for MSDOS mixed 247 | * model programming (small or medium model with some far allocations). 248 | * This was tested only with MSC; for other MSDOS compilers you may have 249 | * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, 250 | * just define FAR to be empty. 251 | */ 252 | #ifdef SYS16BIT 253 | # if defined(M_I86SM) || defined(M_I86MM) 254 | /* MSC small or medium model */ 255 | # define SMALL_MEDIUM 256 | # ifdef _MSC_VER 257 | # define FAR _far 258 | # else 259 | # define FAR far 260 | # endif 261 | # endif 262 | # if (defined(__SMALL__) || defined(__MEDIUM__)) 263 | /* Turbo C small or medium model */ 264 | # define SMALL_MEDIUM 265 | # ifdef __BORLANDC__ 266 | # define FAR _far 267 | # else 268 | # define FAR far 269 | # endif 270 | # endif 271 | #endif 272 | 273 | #if defined(WINDOWS) || defined(WIN32) 274 | /* If building or using zlib as a DLL, define ZLIB_DLL. 275 | * This is not mandatory, but it offers a little performance increase. 276 | */ 277 | # ifdef ZLIB_DLL 278 | # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) 279 | # ifdef ZLIB_INTERNAL 280 | # define ZEXTERN extern __declspec(dllexport) 281 | # else 282 | # define ZEXTERN extern __declspec(dllimport) 283 | # endif 284 | # endif 285 | # endif /* ZLIB_DLL */ 286 | /* If building or using zlib with the WINAPI/WINAPIV calling convention, 287 | * define ZLIB_WINAPI. 288 | * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. 289 | */ 290 | # ifdef ZLIB_WINAPI 291 | # ifdef FAR 292 | # undef FAR 293 | # endif 294 | # include 295 | /* No need for _export, use ZLIB.DEF instead. */ 296 | /* For complete Windows compatibility, use WINAPI, not __stdcall. */ 297 | # define ZEXPORT WINAPI 298 | # ifdef WIN32 299 | # define ZEXPORTVA WINAPIV 300 | # else 301 | # define ZEXPORTVA FAR CDECL 302 | # endif 303 | # endif 304 | #endif 305 | 306 | #if defined (__BEOS__) 307 | # ifdef ZLIB_DLL 308 | # ifdef ZLIB_INTERNAL 309 | # define ZEXPORT __declspec(dllexport) 310 | # define ZEXPORTVA __declspec(dllexport) 311 | # else 312 | # define ZEXPORT __declspec(dllimport) 313 | # define ZEXPORTVA __declspec(dllimport) 314 | # endif 315 | # endif 316 | #endif 317 | 318 | #ifndef ZEXTERN 319 | # define ZEXTERN extern 320 | #endif 321 | #ifndef ZEXPORT 322 | # define ZEXPORT 323 | #endif 324 | #ifndef ZEXPORTVA 325 | # define ZEXPORTVA 326 | #endif 327 | 328 | #ifndef FAR 329 | # define FAR 330 | #endif 331 | 332 | #if !defined(__MACTYPES__) 333 | typedef unsigned char Byte; /* 8 bits */ 334 | #endif 335 | typedef unsigned int uInt; /* 16 bits or more */ 336 | typedef unsigned long uLong; /* 32 bits or more */ 337 | 338 | #ifdef SMALL_MEDIUM 339 | /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ 340 | # define Bytef Byte FAR 341 | #else 342 | typedef Byte FAR Bytef; 343 | #endif 344 | typedef char FAR charf; 345 | typedef int FAR intf; 346 | typedef uInt FAR uIntf; 347 | typedef uLong FAR uLongf; 348 | 349 | #ifdef STDC 350 | typedef void const *voidpc; 351 | typedef void FAR *voidpf; 352 | typedef void *voidp; 353 | #else 354 | typedef Byte const *voidpc; 355 | typedef Byte FAR *voidpf; 356 | typedef Byte *voidp; 357 | #endif 358 | 359 | #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ 360 | # define Z_HAVE_UNISTD_H 361 | #endif 362 | 363 | #ifdef STDC 364 | # include /* for off_t */ 365 | #endif 366 | 367 | /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and 368 | * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even 369 | * though the former does not conform to the LFS document), but considering 370 | * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as 371 | * equivalently requesting no 64-bit operations 372 | */ 373 | #if -_LARGEFILE64_SOURCE - -1 == 1 374 | # undef _LARGEFILE64_SOURCE 375 | #endif 376 | 377 | #if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) 378 | # include /* for SEEK_* and off_t */ 379 | # ifdef VMS 380 | # include /* for off_t */ 381 | # endif 382 | # ifndef z_off_t 383 | # define z_off_t off_t 384 | # endif 385 | #endif 386 | 387 | #ifndef SEEK_SET 388 | # define SEEK_SET 0 /* Seek from beginning of file. */ 389 | # define SEEK_CUR 1 /* Seek from current position. */ 390 | # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ 391 | #endif 392 | 393 | #ifndef z_off_t 394 | # define z_off_t long 395 | #endif 396 | 397 | #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 398 | # define z_off64_t off64_t 399 | #else 400 | # define z_off64_t z_off_t 401 | #endif 402 | 403 | #if defined(__OS400__) 404 | # define NO_vsnprintf 405 | #endif 406 | 407 | #if defined(__MVS__) 408 | # define NO_vsnprintf 409 | #endif 410 | 411 | /* MVS linker does not support external names larger than 8 bytes */ 412 | #if defined(__MVS__) 413 | #pragma map(deflateInit_,"DEIN") 414 | #pragma map(deflateInit2_,"DEIN2") 415 | #pragma map(deflateEnd,"DEEND") 416 | #pragma map(deflateBound,"DEBND") 417 | #pragma map(inflateInit_,"ININ") 418 | #pragma map(inflateInit2_,"ININ2") 419 | #pragma map(inflateEnd,"INEND") 420 | #pragma map(inflateSync,"INSY") 421 | #pragma map(inflateSetDictionary,"INSEDI") 422 | #pragma map(compressBound,"CMBND") 423 | #pragma map(inflate_table,"INTABL") 424 | #pragma map(inflate_fast,"INFA") 425 | #pragma map(inflate_copyright,"INCOPY") 426 | #endif 427 | 428 | #endif /* ZCONF_H */ 429 | -------------------------------------------------------------------------------- /getopt.c: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | 3 | /* Getopt for Microsoft C 4 | This code is a modification of the Free Software Foundation, Inc. 5 | Getopt library for parsing command line argument the purpose was 6 | to provide a Microsoft Visual C friendly derivative. This code 7 | provides functionality for both Unicode and Multibyte builds. 8 | 9 | Date: 02/03/2011 - Ludvik Jerabek - Initial Release 10 | Version: 1.0 11 | Comment: Supports getopt, getopt_long, and getopt_long_only 12 | and POSIXLY_CORRECT environment flag 13 | License: LGPL 14 | 15 | Revisions: 16 | 17 | 02/03/2011 - Ludvik Jerabek - Initial Release 18 | 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 19 | 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs 20 | 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception 21 | 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB 22 | 23 | **DISCLAIMER** 24 | THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 25 | EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE 26 | IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 27 | PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE 28 | EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT 29 | APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY 30 | DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY 31 | USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST 32 | PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON 33 | YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE 34 | EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 35 | */ 36 | 37 | #define _CRT_SECURE_NO_WARNINGS 38 | #include 39 | #include 40 | #include "getopt.h" 41 | 42 | enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; 43 | 44 | struct _getopt_data 45 | { 46 | int optind; 47 | int opterr; 48 | int optopt; 49 | TCHAR *optarg; 50 | int __initialized; 51 | TCHAR *__nextchar; 52 | int __ordering; 53 | int __posixly_correct; 54 | int __first_nonopt; 55 | int __last_nonopt; 56 | }; 57 | 58 | static struct _getopt_data getopt_data; 59 | 60 | TCHAR *optarg; 61 | int optind = 1; 62 | int opterr = 1; 63 | int optopt = _T('?'); 64 | 65 | static void exchange(TCHAR **argv, struct _getopt_data *d) 66 | { 67 | int bottom = d->__first_nonopt; 68 | int middle = d->__last_nonopt; 69 | int top = d->optind; 70 | TCHAR *tem; 71 | while (top > middle && middle > bottom) 72 | { 73 | if (top - middle > middle - bottom) 74 | { 75 | int len = middle - bottom; 76 | register int i; 77 | for (i = 0; i < len; i++) 78 | { 79 | tem = argv[bottom + i]; 80 | argv[bottom + i] = argv[top - (middle - bottom) + i]; 81 | argv[top - (middle - bottom) + i] = tem; 82 | } 83 | top -= len; 84 | } 85 | else 86 | { 87 | int len = top - middle; 88 | register int i; 89 | for (i = 0; i < len; i++) 90 | { 91 | tem = argv[bottom + i]; 92 | argv[bottom + i] = argv[middle + i]; 93 | argv[middle + i] = tem; 94 | } 95 | bottom += len; 96 | } 97 | } 98 | d->__first_nonopt += (d->optind - d->__last_nonopt); 99 | d->__last_nonopt = d->optind; 100 | } 101 | 102 | 103 | static const TCHAR *_getopt_initialize (const TCHAR *optstring, struct _getopt_data *d, int posixly_correct) 104 | { 105 | d->__first_nonopt = d->__last_nonopt = d->optind; 106 | d->__nextchar = NULL; 107 | d->__posixly_correct = posixly_correct | !!_tgetenv(_T("POSIXLY_CORRECT")); 108 | 109 | 110 | if (optstring[0] == _T('-')) 111 | { 112 | d->__ordering = RETURN_IN_ORDER; 113 | ++optstring; 114 | } 115 | else if (optstring[0] == _T('+')) 116 | { 117 | d->__ordering = REQUIRE_ORDER; 118 | ++optstring; 119 | } 120 | else if (d->__posixly_correct) 121 | d->__ordering = REQUIRE_ORDER; 122 | else 123 | d->__ordering = PERMUTE; 124 | return optstring; 125 | } 126 | 127 | int _getopt_internal_r (int argc, TCHAR *const *argv, const TCHAR *optstring, const struct option *longopts, int *longind, int long_only, struct _getopt_data *d, int posixly_correct) 128 | { 129 | int print_errors = d->opterr; 130 | 131 | if (argc < 1) 132 | return -1; 133 | 134 | d->optarg = NULL; 135 | 136 | if (d->optind == 0 || !d->__initialized) 137 | { 138 | if (d->optind == 0) 139 | d->optind = 1; 140 | optstring = _getopt_initialize (optstring, d, posixly_correct); 141 | d->__initialized = 1; 142 | } 143 | else if (optstring[0] == _T('-') || optstring[0] == _T('+')) 144 | optstring++; 145 | if (optstring[0] == _T(':')) 146 | print_errors = 0; 147 | 148 | if (d->__nextchar == NULL || *d->__nextchar == _T('\0')) 149 | { 150 | if (d->__last_nonopt > d->optind) 151 | d->__last_nonopt = d->optind; 152 | if (d->__first_nonopt > d->optind) 153 | d->__first_nonopt = d->optind; 154 | 155 | if (d->__ordering == PERMUTE) 156 | { 157 | if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) 158 | exchange ((TCHAR **) argv, d); 159 | else if (d->__last_nonopt != d->optind) 160 | d->__first_nonopt = d->optind; 161 | 162 | while (d->optind < argc && (argv[d->optind][0] != _T('-') || argv[d->optind][1] == _T('\0'))) 163 | d->optind++; 164 | d->__last_nonopt = d->optind; 165 | } 166 | 167 | if (d->optind != argc && !_tcscmp(argv[d->optind], _T("--"))) 168 | { 169 | d->optind++; 170 | 171 | if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) 172 | exchange ((TCHAR **) argv, d); 173 | else if (d->__first_nonopt == d->__last_nonopt) 174 | d->__first_nonopt = d->optind; 175 | d->__last_nonopt = argc; 176 | 177 | d->optind = argc; 178 | } 179 | 180 | if (d->optind == argc) 181 | { 182 | if (d->__first_nonopt != d->__last_nonopt) 183 | d->optind = d->__first_nonopt; 184 | return -1; 185 | } 186 | 187 | if ((argv[d->optind][0] != _T('-') || argv[d->optind][1] == _T('\0'))) 188 | { 189 | if (d->__ordering == REQUIRE_ORDER) 190 | return -1; 191 | d->optarg = argv[d->optind++]; 192 | return 1; 193 | } 194 | 195 | d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == _T('-'))); 196 | } 197 | 198 | if (longopts != NULL && (argv[d->optind][1] == _T('-') || (long_only && (argv[d->optind][2] || !_tcschr(optstring, argv[d->optind][1]))))) 199 | { 200 | TCHAR *nameend; 201 | const struct option *p; 202 | const struct option *pfound = NULL; 203 | int exact = 0; 204 | int ambig = 0; 205 | int indfound = -1; 206 | int option_index; 207 | 208 | for (nameend = d->__nextchar; *nameend && *nameend != _T('='); nameend++); 209 | 210 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 211 | if (!_tcsncmp(p->name, d->__nextchar, nameend - d->__nextchar)) 212 | { 213 | if ((unsigned int)(nameend - d->__nextchar) == (unsigned int)_tcslen(p->name)) 214 | { 215 | pfound = p; 216 | indfound = option_index; 217 | exact = 1; 218 | break; 219 | } 220 | else if (pfound == NULL) 221 | { 222 | pfound = p; 223 | indfound = option_index; 224 | } 225 | else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) 226 | ambig = 1; 227 | } 228 | 229 | if (ambig && !exact) 230 | { 231 | if (print_errors) 232 | { 233 | _ftprintf(stderr, _T("%s: option '%s' is ambiguous\n"), 234 | argv[0], argv[d->optind]); 235 | } 236 | d->__nextchar += _tcslen(d->__nextchar); 237 | d->optind++; 238 | d->optopt = 0; 239 | return _T('?'); 240 | } 241 | 242 | if (pfound != NULL) 243 | { 244 | option_index = indfound; 245 | d->optind++; 246 | if (*nameend) 247 | { 248 | if (pfound->has_arg) 249 | d->optarg = nameend + 1; 250 | else 251 | { 252 | if (print_errors) 253 | { 254 | if (argv[d->optind - 1][1] == _T('-')) 255 | { 256 | _ftprintf(stderr, _T("%s: option '--%s' doesn't allow an argument\n"),argv[0], pfound->name); 257 | } 258 | else 259 | { 260 | _ftprintf(stderr, _T("%s: option '%c%s' doesn't allow an argument\n"),argv[0], argv[d->optind - 1][0],pfound->name); 261 | } 262 | 263 | } 264 | 265 | d->__nextchar += _tcslen(d->__nextchar); 266 | 267 | d->optopt = pfound->val; 268 | return _T('?'); 269 | } 270 | } 271 | else if (pfound->has_arg == 1) 272 | { 273 | if (d->optind < argc) 274 | d->optarg = argv[d->optind++]; 275 | else 276 | { 277 | if (print_errors) 278 | { 279 | _ftprintf(stderr,_T("%s: option '--%s' requires an argument\n"),argv[0], pfound->name); 280 | } 281 | d->__nextchar += _tcslen(d->__nextchar); 282 | d->optopt = pfound->val; 283 | return optstring[0] == _T(':') ? _T(':') : _T('?'); 284 | } 285 | } 286 | d->__nextchar += _tcslen(d->__nextchar); 287 | if (longind != NULL) 288 | *longind = option_index; 289 | if (pfound->flag) 290 | { 291 | *(pfound->flag) = pfound->val; 292 | return 0; 293 | } 294 | return pfound->val; 295 | } 296 | 297 | if (!long_only || argv[d->optind][1] == _T('-') || _tcschr(optstring, *d->__nextchar) == NULL) 298 | { 299 | if (print_errors) 300 | { 301 | if (argv[d->optind][1] == _T('-')) 302 | { 303 | /* --option */ 304 | _ftprintf(stderr, _T("%s: unrecognized option '--%s'\n"),argv[0], d->__nextchar); 305 | } 306 | else 307 | { 308 | /* +option or -option */ 309 | _ftprintf(stderr, _T("%s: unrecognized option '%c%s'\n"),argv[0], argv[d->optind][0], d->__nextchar); 310 | } 311 | } 312 | d->__nextchar = (TCHAR *)_T(""); 313 | d->optind++; 314 | d->optopt = 0; 315 | return _T('?'); 316 | } 317 | } 318 | 319 | { 320 | TCHAR c = *d->__nextchar++; 321 | TCHAR *temp = (TCHAR*)_tcschr(optstring, c); 322 | 323 | if (*d->__nextchar == _T('\0')) 324 | ++d->optind; 325 | 326 | if (temp == NULL || c == _T(':') || c == _T(';')) 327 | { 328 | if (print_errors) 329 | { 330 | _ftprintf(stderr, _T("%s: invalid option -- '%c'\n"), argv[0], c); 331 | } 332 | d->optopt = c; 333 | return _T('?'); 334 | } 335 | if (temp[0] == _T('W') && temp[1] == _T(';')) 336 | { 337 | TCHAR *nameend; 338 | const struct option *p; 339 | const struct option *pfound = NULL; 340 | int exact = 0; 341 | int ambig = 0; 342 | int indfound = 0; 343 | int option_index; 344 | 345 | if (*d->__nextchar != _T('\0')) 346 | { 347 | d->optarg = d->__nextchar; 348 | d->optind++; 349 | } 350 | else if (d->optind == argc) 351 | { 352 | if (print_errors) 353 | { 354 | _ftprintf(stderr, 355 | _T("%s: option requires an argument -- '%c'\n"), 356 | argv[0], c); 357 | } 358 | d->optopt = c; 359 | if (optstring[0] == _T(':')) 360 | c = _T(':'); 361 | else 362 | c = _T('?'); 363 | return c; 364 | } 365 | else 366 | d->optarg = argv[d->optind++]; 367 | 368 | for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != _T('='); nameend++); 369 | 370 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 371 | if (!_tcsncmp(p->name, d->__nextchar, nameend - d->__nextchar)) 372 | { 373 | if ((unsigned int) (nameend - d->__nextchar) == _tcslen(p->name)) 374 | { 375 | pfound = p; 376 | indfound = option_index; 377 | exact = 1; 378 | break; 379 | } 380 | else if (pfound == NULL) 381 | { 382 | pfound = p; 383 | indfound = option_index; 384 | } 385 | else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) 386 | ambig = 1; 387 | } 388 | if (ambig && !exact) 389 | { 390 | if (print_errors) 391 | { 392 | _ftprintf(stderr, _T("%s: option '-W %s' is ambiguous\n"), 393 | argv[0], d->optarg); 394 | } 395 | d->__nextchar += _tcslen(d->__nextchar); 396 | d->optind++; 397 | return _T('?'); 398 | } 399 | if (pfound != NULL) 400 | { 401 | option_index = indfound; 402 | if (*nameend) 403 | { 404 | if (pfound->has_arg) 405 | d->optarg = nameend + 1; 406 | else 407 | { 408 | if (print_errors) 409 | { 410 | _ftprintf(stderr, _T("\ 411 | %s: option '-W %s' doesn't allow an argument\n"), 412 | argv[0], pfound->name); 413 | } 414 | 415 | d->__nextchar += _tcslen(d->__nextchar); 416 | return _T('?'); 417 | } 418 | } 419 | else if (pfound->has_arg == 1) 420 | { 421 | if (d->optind < argc) 422 | d->optarg = argv[d->optind++]; 423 | else 424 | { 425 | if (print_errors) 426 | { 427 | _ftprintf(stderr, _T("\ 428 | %s: option '-W %s' requires an argument\n"), 429 | argv[0], pfound->name); 430 | } 431 | d->__nextchar += _tcslen(d->__nextchar); 432 | return optstring[0] == _T(':') ? _T(':') : _T('?'); 433 | } 434 | } 435 | else 436 | d->optarg = NULL; 437 | d->__nextchar += _tcslen(d->__nextchar); 438 | if (longind != NULL) 439 | *longind = option_index; 440 | if (pfound->flag) 441 | { 442 | *(pfound->flag) = pfound->val; 443 | return 0; 444 | } 445 | return pfound->val; 446 | } 447 | d->__nextchar = NULL; 448 | return _T('W'); 449 | } 450 | if (temp[1] == _T(':')) 451 | { 452 | if (temp[2] == _T(':')) 453 | { 454 | if (*d->__nextchar != _T('\0')) 455 | { 456 | d->optarg = d->__nextchar; 457 | d->optind++; 458 | } 459 | else 460 | d->optarg = NULL; 461 | d->__nextchar = NULL; 462 | } 463 | else 464 | { 465 | if (*d->__nextchar != _T('\0')) 466 | { 467 | d->optarg = d->__nextchar; 468 | d->optind++; 469 | } 470 | else if (d->optind == argc) 471 | { 472 | if (print_errors) 473 | { 474 | _ftprintf(stderr, 475 | _T("%s: option requires an argument -- '%c'\n"), 476 | argv[0], c); 477 | } 478 | d->optopt = c; 479 | if (optstring[0] == _T(':')) 480 | c = _T(':'); 481 | else 482 | c = _T('?'); 483 | } 484 | else 485 | d->optarg = argv[d->optind++]; 486 | d->__nextchar = NULL; 487 | } 488 | } 489 | return c; 490 | } 491 | } 492 | 493 | int _getopt_internal (int argc, TCHAR *const *argv, const TCHAR *optstring, const struct option *longopts, int *longind, int long_only, int posixly_correct) 494 | { 495 | int result; 496 | getopt_data.optind = optind; 497 | getopt_data.opterr = opterr; 498 | result = _getopt_internal_r (argc, argv, optstring, longopts,longind, long_only, &getopt_data,posixly_correct); 499 | optind = getopt_data.optind; 500 | optarg = getopt_data.optarg; 501 | optopt = getopt_data.optopt; 502 | return result; 503 | } 504 | 505 | int getopt (int argc, TCHAR *const *argv, const TCHAR *optstring) 506 | { 507 | return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0, 0); 508 | } 509 | 510 | int getopt_long (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index) 511 | { 512 | return _getopt_internal (argc, argv, options, long_options, opt_index, 0, 0); 513 | } 514 | 515 | int _getopt_long_r (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index, struct _getopt_data *d) 516 | { 517 | return _getopt_internal_r (argc, argv, options, long_options, opt_index,0, d, 0); 518 | } 519 | 520 | int getopt_long_only (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index) 521 | { 522 | return _getopt_internal (argc, argv, options, long_options, opt_index, 1, 0); 523 | } 524 | 525 | int _getopt_long_only_r (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index, struct _getopt_data *d) 526 | { 527 | return _getopt_internal_r (argc, argv, options, long_options, opt_index, 1, d, 0); 528 | } 529 | 530 | #endif 531 | -------------------------------------------------------------------------------- /sce.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #ifndef _SCE_H_ 7 | #define _SCE_H_ 8 | 9 | #include 10 | #include 11 | 12 | #include "types.h" 13 | #include "list.h" 14 | 15 | /*! SCE file align. */ 16 | #define SCE_ALIGN 0x10 17 | /*! Header align. */ 18 | #define HEADER_ALIGN 0x80 19 | 20 | /*! SCE header magic value ("SCE\0"). */ 21 | #define SCE_HEADER_MAGIC 0x53434500 22 | 23 | /*! SCE header versions. */ 24 | /*! Header version 2. */ 25 | #define SCE_HEADER_VERSION_2 2 26 | 27 | /*! Key revisions. */ 28 | #define KEY_REVISION_0 0x00 29 | #define KEY_REVISION_092_330 0x01 30 | #define KEY_REVISION_1 0x02 31 | //#define KEY_REVISION_ 0x03 32 | #define KEY_REVISION_340_342 0x04 33 | //#define KEY_REVISION_ 0x05 34 | //#define KEY_REVISION_ 0x06 35 | #define KEY_REVISION_350 0x07 36 | //#define KEY_REVISION_ 0x08 37 | //#define KEY_REVISION_ 0x09 38 | #define KEY_REVISION_355 0x0a 39 | //#define KEY_REVISION_ 0x0b 40 | //#define KEY_REVISION_ 0x0c 41 | #define KEY_REVISION_356 0x0d 42 | //#define KEY_REVISION_ 0x0e 43 | //#define KEY_REVISION_ 0x0f 44 | #define KEY_REVISION_360_361 0x10 45 | //#define KEY_REVISION_ 0x11 46 | //#define KEY_REVISION_ 0x12 47 | #define KEY_REVISION_365 0x13 48 | //#define KEY_REVISION_ 0x14 49 | //#define KEY_REVISION_ 0x15 50 | #define KEY_REVISION_370_373 0x16 51 | //#define KEY_REVISION_ 0x17 52 | //#define KEY_REVISION_ 0x18 53 | #define KEY_REVISION_DEBUG 0x8000 54 | 55 | /*! SCE header types. */ 56 | /*! SELF header. */ 57 | #define SCE_HEADER_TYPE_SELF 1 58 | /*! RVK header. */ 59 | #define SCE_HEADER_TYPE_RVK 2 60 | /*! PKG header. */ 61 | #define SCE_HEADER_TYPE_PKG 3 62 | /*! SPP header. */ 63 | #define SCE_HEADER_TYPE_SPP 4 64 | 65 | /*! Sub header types. */ 66 | /*! SCE version header. */ 67 | #define SUB_HEADER_TYPE_SCEVERSION 1 68 | /*! SELF header. */ 69 | #define SUB_HEADER_TYPE_SELF 3 70 | 71 | /*! Control info types. */ 72 | /*! Control flags. */ 73 | #define CONTROL_INFO_TYPE_FLAGS 1 74 | /*! Digest. */ 75 | #define CONTROL_INFO_TYPE_DIGEST 2 76 | /*! NPDRM block. */ 77 | #define CONTROL_INFO_TYPE_NPDRM 3 78 | 79 | /*! Optional header types. */ 80 | /*! Capability flags header. */ 81 | #define OPT_HEADER_TYPE_CAP_FLAGS 1 82 | /*! Individuals seed header. */ 83 | #define OPT_HEADER_TYPE_INDIV_SEED 2 84 | 85 | /*! Metadata key/iv lengths. */ 86 | #define METADATA_INFO_KEYBITS 128 87 | #define METADATA_INFO_KEY_LEN 16 88 | #define METADATA_INFO_KEYPAD_LEN 16 89 | #define METADATA_INFO_IV_LEN 16 90 | #define METADATA_INFO_IVPAD_LEN 16 91 | 92 | /*! Metadata section types. */ 93 | /*! Segment header. */ 94 | #define METADATA_SECTION_TYPE_SHDR 1 95 | /*! Program header. */ 96 | #define METADATA_SECTION_TYPE_PHDR 2 97 | /*! Unknown header type 3. */ 98 | #define METADATA_SECTION_TYPE_UNK_3 3 99 | 100 | /*! Section is hashed. */ 101 | #define METADATA_SECTION_HASHED 2 102 | /*! Section is not encrypted. */ 103 | #define METADATA_SECTION_NOT_ENCRYPTED 1 104 | /*! Section is encrypted. */ 105 | #define METADATA_SECTION_ENCRYPTED 3 106 | /*! Section is not compressed. */ 107 | #define METADATA_SECTION_NOT_COMPRESSED 1 108 | /*! Section is compressed. */ 109 | #define METADATA_SECTION_COMPRESSED 2 110 | 111 | /*! Signature sizes. */ 112 | /*! Signature S part size. */ 113 | #define SIGNATURE_S_SIZE 21 114 | /*! Signature R part size. */ 115 | #define SIGNATURE_R_SIZE 21 116 | 117 | /*! Compressed. */ 118 | #define SECTION_INFO_COMPRESSED 2 119 | /*! Not compressed. */ 120 | #define SECTION_INFO_NOT_COMPRESSED 1 121 | 122 | /*! SCE version not present. */ 123 | #define SCE_VERSION_NOT_PRESENT 0 124 | /*! SCE version present. */ 125 | #define SCE_VERSION_PRESENT 1 126 | 127 | /*! SELF types. */ 128 | /*! lv0. */ 129 | #define SELF_TYPE_LV0 1 130 | /*! lv1. */ 131 | #define SELF_TYPE_LV1 2 132 | /*! lv2. */ 133 | #define SELF_TYPE_LV2 3 134 | /*! Application. */ 135 | #define SELF_TYPE_APP 4 136 | /*! Isolated SPU module. */ 137 | #define SELF_TYPE_ISO 5 138 | /*! Secure loader. */ 139 | #define SELF_TYPE_LDR 6 140 | /*! Unknown type 7. */ 141 | #define SELF_TYPE_UNK_7 7 142 | /*! NPDRM application. */ 143 | #define SELF_TYPE_NPDRM 8 144 | 145 | /*! NPDRM control info magic value ("NPD\0"). */ 146 | #define NP_CI_MAGIC 0x4E504400 147 | 148 | /*! NPDRM license types. */ 149 | #define NP_LICENSE_NETWORK 1 150 | #define NP_LICENSE_LOCAL 2 151 | #define NP_LICENSE_FREE 3 152 | 153 | /*! NPDRM application types. */ 154 | #define NP_TYPE_UPDATE 0x20 155 | #define NP_TYPE_SPRX 0 156 | #define NP_TYPE_EXEC 1 157 | #define NP_TYPE_USPRX (NP_TYPE_UPDATE | NP_TYPE_SPRX) 158 | #define NP_TYPE_UEXEC (NP_TYPE_UPDATE | NP_TYPE_EXEC) 159 | 160 | /*! SCE header. */ 161 | typedef struct _sce_header 162 | { 163 | /*! Magic value. */ 164 | u32 magic; 165 | /*! Header version .*/ 166 | u32 version; 167 | /*! Key revision. */ 168 | u16 key_revision; 169 | /*! Header type. */ 170 | u16 header_type; 171 | /*! Metadata offset. */ 172 | u32 metadata_offset; 173 | /*! Header length. */ 174 | u64 header_len; 175 | /*! Length of encapsulated data. */ 176 | u64 data_len; 177 | } sce_header_t; 178 | 179 | /*! SELF header. */ 180 | typedef struct _self_header 181 | { 182 | /*! Header type. */ 183 | u64 header_type; 184 | /*! Application info offset. */ 185 | u64 app_info_offset; 186 | /*! ELF offset. */ 187 | u64 elf_offset; 188 | /*! Program headers offset. */ 189 | u64 phdr_offset; 190 | /*! Section headers offset. */ 191 | u64 shdr_offset; 192 | /*! Section info offset. */ 193 | u64 section_info_offset; 194 | /*! SCE version offset. */ 195 | u64 sce_version_offset; 196 | /*! Control info offset. */ 197 | u64 control_info_offset; 198 | /*! Control info size. */ 199 | u64 control_info_size; 200 | /*! Padding. */ 201 | u64 padding; 202 | } self_header_t; 203 | 204 | /*! Metadata info. */ 205 | typedef struct _metadata_info 206 | { 207 | /*! Key. */ 208 | u8 key[METADATA_INFO_KEY_LEN]; 209 | /*! Key padding. */ 210 | u8 key_pad[METADATA_INFO_KEYPAD_LEN]; 211 | /*! IV. */ 212 | u8 iv[METADATA_INFO_IV_LEN]; 213 | /*! IV padding. */ 214 | u8 iv_pad[METADATA_INFO_IVPAD_LEN]; 215 | } metadata_info_t; 216 | 217 | typedef struct _metadata_header 218 | { 219 | /*! Signature input length. */ 220 | u64 sig_input_length; 221 | u32 unknown_0; 222 | /*! Section count. */ 223 | u32 section_count; 224 | /*! Key count. */ 225 | u32 key_count; 226 | /*! Optional header size. */ 227 | u32 opt_header_size; 228 | u32 unknown_1; 229 | u32 unknown_2; 230 | } metadata_header_t; 231 | 232 | /*! Metadata section header. */ 233 | typedef struct _metadata_section_header 234 | { 235 | /*! Data offset. */ 236 | u64 data_offset; 237 | /*! Data size. */ 238 | u64 data_size; 239 | /*! Type. */ 240 | u32 type; 241 | /*! Index. */ 242 | u32 index; 243 | /*! Hashed. */ 244 | u32 hashed; 245 | /*! SHA1 index. */ 246 | u32 sha1_index; 247 | /*! Encrypted. */ 248 | u32 encrypted; 249 | /*! Key index. */ 250 | u32 key_index; 251 | /*! IV index. */ 252 | u32 iv_index; 253 | /*! Compressed. */ 254 | u32 compressed; 255 | } metadata_section_header_t; 256 | 257 | /*! SCE file signature. */ 258 | typedef struct _signature 259 | { 260 | u8 r[SIGNATURE_R_SIZE]; 261 | u8 s[SIGNATURE_S_SIZE]; 262 | u8 padding[6]; 263 | } signature_t; 264 | 265 | /*! Section info. */ 266 | typedef struct _section_info 267 | { 268 | u64 offset; 269 | u64 size; 270 | u32 compressed; 271 | u32 unknown_0; 272 | u32 unknown_1; 273 | u32 encrypted; 274 | } section_info_t; 275 | 276 | /*! SCE version. */ 277 | typedef struct _sce_version 278 | { 279 | /*! Header type. */ 280 | u32 header_type; 281 | /*! SCE version section present? */ 282 | u32 present; 283 | /*! Size. */ 284 | u32 size; 285 | u32 unknown_3; 286 | } sce_version_t; 287 | 288 | /*! SCE version data 0x30. */ 289 | typedef struct _sce_version_data_30 290 | { 291 | u16 unknown_1; //Dunno. 292 | u16 unknown_2; //0x0001 293 | u32 unknown_3; //Padding? 294 | u32 unknown_4; //Number of sections? 295 | u32 unknown_5; //Padding? 296 | /*! Data offset. */ 297 | u64 offset; 298 | /*! Data size. */ 299 | u64 size; 300 | } sce_version_data_30_t; 301 | 302 | //(auth_id & AUTH_ONE_MASK) has to be 0x1000000000000000 303 | #define AUTH_ONE_MASK 0xF000000000000000 304 | #define AUTH_TERRITORY_MASK 0x0FF0000000000000 305 | #define VENDOR_TERRITORY_MASK 0xFF000000 306 | #define VENDOR_ID_MASK 0x00FFFFFF 307 | 308 | /*! Application info. */ 309 | typedef struct _app_info 310 | { 311 | /*! Auth ID. */ 312 | u64 auth_id; 313 | /*! Vendor ID. */ 314 | u32 vendor_id; 315 | /*! SELF type. */ 316 | u32 self_type; 317 | /*! Version. */ 318 | u64 version; 319 | /*! Padding. */ 320 | u64 padding; 321 | } app_info_t; 322 | 323 | /*! Control info. */ 324 | typedef struct _control_info 325 | { 326 | /*! Control info type. */ 327 | u32 type; 328 | /*! Size of following data. */ 329 | u32 size; 330 | /*! Next flag (1 if another info follows). */ 331 | u64 next; 332 | } control_info_t; 333 | 334 | #define CI_FLAG_00_80 0x80 335 | #define CI_FLAG_00_40 0x40 //root access 336 | #define CI_FLAG_00_20 0x20 //kernel access 337 | 338 | #define CI_FLAG_17_01 0x01 339 | #define CI_FLAG_17_02 0x02 340 | #define CI_FLAG_17_04 0x04 341 | #define CI_FLAG_17_08 0x08 342 | #define CI_FLAG_17_10 0x10 343 | 344 | //1B: 345 | //bdj 0x01, 0x09 346 | //psp_emu 0x08 347 | //psp_transl 0x0C 348 | #define CI_FLAG_1B_01 0x01 //may use shared mem? 349 | #define CI_FLAG_1B_02 0x02 350 | #define CI_FLAG_1B_04 0x04 351 | #define CI_FLAG_1B_08 0x08 //ss 352 | 353 | #define CI_FLAG_1F_SHAREABLE 0x01 354 | #define CI_FLAG_1F_02 0x02 //internal? 355 | #define CI_FLAG_1F_FACTORY 0x04 356 | #define CI_FLAG_1F_08 0x08 //??? 357 | 358 | /*! Control info data flags. */ 359 | typedef struct _ci_data_flags 360 | { 361 | u8 data[0x20]; 362 | } ci_data_flags_t; 363 | 364 | /*! Control info data digest 0x30. */ 365 | typedef struct _ci_data_digest_30 366 | { 367 | u8 digest[20]; 368 | u64 unknown_0; 369 | } ci_data_digest_30_t; 370 | 371 | /*! Control info data digest 0x40. */ 372 | typedef struct _ci_data_digest_40 373 | { 374 | u8 digest1[20]; 375 | u8 digest2[20]; 376 | u64 fw_version; 377 | } ci_data_digest_40_t; 378 | 379 | /*! Control info data NPDRM. */ 380 | typedef struct _ci_data_npdrm 381 | { 382 | /*! Magic. */ 383 | u32 magic; 384 | u32 unknown_0; 385 | /*! License type. */ 386 | u32 license_type; 387 | /*! Application type. */ 388 | u32 app_type; 389 | /*! Content ID. */ 390 | u8 content_id[0x30]; 391 | /*! Random padding. */ 392 | u8 rndpad[0x10]; 393 | /*! ContentID_FileName hash. */ 394 | u8 hash_cid_fname[0x10]; 395 | /*! Control info hash. */ 396 | u8 hash_ci[0x10]; 397 | u64 unknown_1; 398 | u64 unknown_2; 399 | } ci_data_npdrm_t; 400 | 401 | /*! Optional header. */ 402 | typedef struct _opt_header 403 | { 404 | /*! Type. */ 405 | u32 type; 406 | /*! Size. */ 407 | u32 size; 408 | /*! Next flag (1 if another header follows). */ 409 | u64 next; 410 | } opt_header_t; 411 | 412 | /*! Capability flags. */ 413 | #define CAP_FLAG_1 0x01 //only seen in PPU selfs 414 | #define CAP_FLAG_2 0x02 //only seen in PPU selfs 415 | #define CAP_FLAG_4 0x04 //only seen in bdj PPU self 416 | #define CAP_FLAG_REFTOOL 0x08 417 | #define CAP_FLAG_DEBUG 0x10 418 | #define CAP_FLAG_RETAIL 0x20 419 | #define CAP_FLAG_SYSDBG 0x40 420 | 421 | #define UNK7_2000 0x2000 //hddbind? 422 | #define UNK7_20000 0x20000 //flashbind? 423 | #define UNK7_40000 0x40000 //discbind? 424 | #define UNK7_80000 0x80000 425 | 426 | #define UNK7_PS3SWU 0x116000 //dunno... 427 | 428 | /*! SCE file capability flags. */ 429 | typedef struct _oh_data_cap_flags 430 | { 431 | u64 unk3; //0 432 | u64 unk4; //0 433 | /*! Flags. */ 434 | u64 flags; 435 | u32 unk6; 436 | u32 unk7; 437 | } oh_data_cap_flags_t; 438 | 439 | /*! Section context. */ 440 | typedef struct _sce_section_ctxt 441 | { 442 | /*! Data buffer. */ 443 | void *buffer; 444 | /*! Size. */ 445 | u32 size; 446 | /*! Offset. */ 447 | u32 offset; 448 | /*! May be compressed. */ 449 | BOOL may_compr; 450 | } sce_section_ctxt_t; 451 | 452 | typedef struct _makeself_ctxt 453 | { 454 | /*! ELF file buffer (for ELF -> SELF). */ 455 | u8 *elf; 456 | /*! ELF file length. */ 457 | u32 elf_len; 458 | /*! ELF header. */ 459 | void *ehdr; 460 | /*! ELF header size. */ 461 | u32 ehsize; 462 | /*! Program headers. */ 463 | void *phdrs; 464 | /*! Program headers size. */ 465 | u32 phsize; 466 | /*! Section headers. */ 467 | void *shdrs; 468 | /*! Section headers size. */ 469 | u32 shsize; 470 | /*! Section info count. */ 471 | u32 si_cnt; 472 | /*! Number of section infos that are present as data sections. */ 473 | u32 si_sec_cnt; 474 | } makeself_ctxt_t; 475 | 476 | /*! SCE file buffer context. */ 477 | typedef struct _sce_buffer_ctxt 478 | { 479 | /*! SCE file buffer. */ 480 | u8 *scebuffer; 481 | 482 | /*! SCE header. */ 483 | sce_header_t *sceh; 484 | /*! File type dependent header. */ 485 | union 486 | { 487 | struct 488 | { 489 | /*! SELF header. */ 490 | self_header_t *selfh; 491 | /*! Application info. */ 492 | app_info_t *ai; 493 | /*! Section info. */ 494 | section_info_t *si; 495 | /*! SCE version. */ 496 | sce_version_t *sv; 497 | /*! Control infos. */ 498 | list_t *cis; 499 | /*! Optional headers. */ 500 | list_t *ohs; 501 | } self; 502 | }; 503 | /*! Metadata info. */ 504 | metadata_info_t *metai; 505 | /*! Metadata header. */ 506 | metadata_header_t *metah; 507 | /*! Metadata section headers. */ 508 | metadata_section_header_t *metash; 509 | /*! SCE file keys. */ 510 | u8 *keys; 511 | /*! Keys length. */ 512 | u32 keys_len; 513 | /*! Signature. */ 514 | signature_t *sig; 515 | 516 | /*! Metadata decrypted? */ 517 | BOOL mdec; 518 | 519 | /*! Data layout. */ 520 | /*! SCE header offset. */ 521 | u32 off_sceh; 522 | union 523 | { 524 | struct 525 | { 526 | /*! SELF header offset. */ 527 | u32 off_selfh; 528 | /*! Application info offset. */ 529 | u32 off_ai; 530 | /*! ELF header offset. */ 531 | u32 off_ehdr; 532 | /*! Program header offset. */ 533 | u32 off_phdr; 534 | /*! Section info offset. */ 535 | u32 off_si; 536 | /*! SCE version offset. */ 537 | u32 off_sv; 538 | /*! Control infos offset. */ 539 | u32 off_cis; 540 | /*! Optional headers offset. */ 541 | u32 off_ohs; 542 | } off_self; 543 | }; 544 | /*! Metadata info offset. */ 545 | u32 off_metai; 546 | /*! Metadata header offset. */ 547 | u32 off_metah; 548 | /*! Metadata section headers offset. */ 549 | u32 off_metash; 550 | /*! Keys offset. */ 551 | u32 off_keys; 552 | /*! Signature offset. */ 553 | u32 off_sig; 554 | /*! Header padding end offset. */ 555 | u32 off_hdrpad; 556 | 557 | /*! File creation type dependent data. */ 558 | union 559 | { 560 | /*! ELF -> SELF. */ 561 | makeself_ctxt_t *makeself; 562 | }; 563 | 564 | /*! Data sections. */ 565 | list_t *secs; 566 | } sce_buffer_ctxt_t; 567 | 568 | /*! Create SCE file context from SCE file buffer. */ 569 | sce_buffer_ctxt_t *sce_create_ctxt_from_buffer(u8 *scebuffer); 570 | 571 | /*! Create SCE file context for SELF creation. */ 572 | sce_buffer_ctxt_t *sce_create_ctxt_build_self(u8 *elf, u32 elf_len); 573 | 574 | /*! Add data section to SCE context. */ 575 | void sce_add_data_section(sce_buffer_ctxt_t *ctxt, void *buffer, u32 size, BOOL may_compr); 576 | 577 | /*! Set metadata section header. */ 578 | void sce_set_metash(sce_buffer_ctxt_t *ctxt, u32 type, BOOL encrypted, u32 idx); 579 | 580 | /*! Compress data. */ 581 | void sce_compress_data(sce_buffer_ctxt_t *ctxt); 582 | 583 | /*! Layout offsets for SCE file creation. */ 584 | void sce_layout_ctxt(sce_buffer_ctxt_t *ctxt); 585 | 586 | /*! Encrypt context. */ 587 | BOOL sce_encrypt_ctxt(sce_buffer_ctxt_t *ctxt, u8 *keyset); 588 | 589 | /*! Write context to file. */ 590 | BOOL sce_write_ctxt(sce_buffer_ctxt_t *ctxt, s8 *fname); 591 | 592 | /*! Decrypt header (use passed metadata_into if not NULL). */ 593 | BOOL sce_decrypt_header(sce_buffer_ctxt_t *ctxt, u8 *metadata_info, u8 *keyset); 594 | 595 | /*! Decrypt data. */ 596 | BOOL sce_decrypt_data(sce_buffer_ctxt_t *ctxt); 597 | 598 | /*! Print SCE file info. */ 599 | void sce_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt); 600 | 601 | /*! Get version string from version. */ 602 | s8 *sce_version_to_str(u64 version); 603 | 604 | /*! Get version from version string. */ 605 | u64 sce_str_to_version(s8 *version); 606 | 607 | /*! Convert hex version to dec version. */ 608 | u64 sce_hexver_to_decver(u64 version); 609 | 610 | /*! Get control info. */ 611 | control_info_t *sce_get_ctrl_info(sce_buffer_ctxt_t *ctxt, u32 type); 612 | 613 | /*! Get optional header. */ 614 | opt_header_t *sce_get_opt_header(sce_buffer_ctxt_t *ctxt, u32 type); 615 | 616 | #endif 617 | -------------------------------------------------------------------------------- /frontend.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * This file is released under the GPLv2. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "types.h" 10 | #include "config.h" 11 | #include "aes.h" 12 | #include "util.h" 13 | #include "keys.h" 14 | #include "sce.h" 15 | #include "sce_inlines.h" 16 | #include "self.h" 17 | #include "np.h" 18 | #include "rvk.h" 19 | #include "spp.h" 20 | #include "util.h" 21 | #include "tables.h" 22 | 23 | /*! Parameters. */ 24 | extern s8 *_template; 25 | extern s8 *_file_type; 26 | extern s8 *_compress_data; 27 | extern s8 *_skip_sections; 28 | extern s8 *_key_rev; 29 | extern s8 *_meta_info; 30 | extern s8 *_keyset; 31 | extern s8 *_auth_id; 32 | extern s8 *_vendor_id; 33 | extern s8 *_self_type; 34 | extern s8 *_app_version; 35 | extern s8 *_fw_version; 36 | extern s8 *_add_shdrs; 37 | extern s8 *_ctrl_flags; 38 | extern s8 *_cap_flags; 39 | #ifdef CONFIG_CUSTOM_INDIV_SEED 40 | extern s8 *_indiv_seed; 41 | #endif 42 | extern s8 *_license_type; 43 | extern s8 *_app_type; 44 | extern s8 *_content_id; 45 | extern s8 *_real_fname; 46 | extern s8 *_add_sig; 47 | 48 | static BOOL _is_hexdigit(s8 c) 49 | { 50 | if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) 51 | return TRUE; 52 | return FALSE; 53 | } 54 | 55 | static BOOL _is_hexnumber(const s8 *str) 56 | { 57 | u32 i, len = strlen(str); 58 | for(i = 0; i < len; i++) 59 | if(_is_hexdigit(str[i]) == FALSE) 60 | return FALSE; 61 | return TRUE; 62 | } 63 | 64 | static BOOL _fill_self_config_template(s8 *file, self_config_t *sconf) 65 | { 66 | u8 *buf = _read_buffer(file, NULL); 67 | if(buf != NULL) 68 | { 69 | sce_buffer_ctxt_t *ctxt = sce_create_ctxt_from_buffer(buf); 70 | if(ctxt != NULL) 71 | { 72 | if(sce_decrypt_header(ctxt, NULL, NULL)) 73 | { 74 | _LOG_VERBOSE("Template header decrypted.\n"); 75 | 76 | _LOG_VERBOSE("Using:\n"); 77 | sconf->key_revision = ctxt->sceh->key_revision; 78 | _IF_VERBOSE(printf(" Key Revision 0x%04X\n", sconf->key_revision)); 79 | sconf->auth_id = ctxt->self.ai->auth_id; 80 | _IF_VERBOSE(printf(" Auth-ID 0x%016llX\n", sconf->auth_id)); 81 | sconf->vendor_id = ctxt->self.ai->vendor_id; 82 | _IF_VERBOSE(printf(" Vendor-ID 0x%08X\n", sconf->vendor_id)); 83 | sconf->self_type = ctxt->self.ai->self_type; 84 | _IF_VERBOSE(printf(" SELF-Type 0x%08X\n", sconf->self_type)); 85 | sconf->app_version = ctxt->self.ai->version; 86 | _IF_VERBOSE(printf(" APP Version 0x%016llX\n", sconf->app_version)); 87 | 88 | control_info_t *ci = sce_get_ctrl_info(ctxt, CONTROL_INFO_TYPE_DIGEST); 89 | ci_data_digest_40_t *cid = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t)); 90 | _es_ci_data_digest_40(cid); 91 | sconf->fw_version = cid->fw_version; 92 | _IF_VERBOSE(printf(" FW Version 0x%016llX\n", sconf->fw_version)); 93 | 94 | ci = sce_get_ctrl_info(ctxt, CONTROL_INFO_TYPE_FLAGS); 95 | sconf->ctrl_flags = (u8 *)_memdup(((u8 *)ci) + sizeof(control_info_t), 0x20); 96 | _IF_VERBOSE(_hexdump(stdout, " Control Flags ", 0, sconf->ctrl_flags, 0x20, 0)); 97 | 98 | 99 | opt_header_t *oh = sce_get_opt_header(ctxt, OPT_HEADER_TYPE_CAP_FLAGS); 100 | sconf->cap_flags = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), 0x20); 101 | _IF_VERBOSE(_hexdump(stdout, " Capability Flags", 0, sconf->cap_flags, 0x20, 0)); 102 | 103 | #ifdef CONFIG_CUSTOM_INDIV_SEED 104 | sconf->indiv_seed = NULL; 105 | if(ctxt->self.ai->self_type == SELF_TYPE_ISO) 106 | { 107 | oh = sce_get_opt_header(ctxt, OPT_HEADER_TYPE_INDIV_SEED); 108 | sconf->indiv_seed = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), oh->size - sizeof(opt_header_t)); 109 | sconf->indiv_seed_size = oh->size - sizeof(opt_header_t); 110 | _IF_VERBOSE(_hexdump(stdout, " Individuals Seed", 0, sconf->indiv_seed, sconf->indiv_seed_size, 0)); 111 | } 112 | #endif 113 | 114 | sconf->add_shdrs = TRUE; 115 | if(_add_shdrs != NULL) 116 | if(strcmp(_add_shdrs, "FALSE") == 0) 117 | sconf->add_shdrs = FALSE; 118 | 119 | sconf->skip_sections = TRUE; 120 | if(_skip_sections != NULL) 121 | if(strcmp(_skip_sections, "FALSE") == 0) 122 | sconf->skip_sections = FALSE; 123 | 124 | sconf->npdrm_config = NULL; 125 | 126 | return TRUE; 127 | } 128 | else 129 | printf("[*] Warning: Could not decrypt template header.\n"); 130 | free(ctxt); 131 | } 132 | else 133 | printf("[*] Error: Could not process template %s\n", file); 134 | free(buf); 135 | } 136 | else 137 | printf("[*] Error: Could not load template %s\n", file); 138 | 139 | return FALSE; 140 | } 141 | 142 | static BOOL _fill_self_config(self_config_t *sconf) 143 | { 144 | if(_key_rev == NULL) 145 | { 146 | printf("[*] Error: Please specify a key revision.\n"); 147 | return FALSE; 148 | } 149 | if(_is_hexnumber(_key_rev) == FALSE) 150 | { 151 | printf("[*] Error (Key Revision): Please provide a valid hexadecimal number.\n"); 152 | return FALSE; 153 | } 154 | sconf->key_revision = _x_to_u64(_key_rev); 155 | 156 | if(_auth_id == NULL) 157 | { 158 | printf("[*] Error: Please specify an auth ID.\n"); 159 | return FALSE; 160 | } 161 | sconf->auth_id = _x_to_u64(_auth_id); 162 | 163 | if(_vendor_id == NULL) 164 | { 165 | printf("[*] Error: Please specify a vendor ID.\n"); 166 | return FALSE; 167 | } 168 | sconf->vendor_id = _x_to_u64(_vendor_id); 169 | 170 | if(_self_type == NULL) 171 | { 172 | printf("[*] Error: Please specify a SELF type.\n"); 173 | return FALSE; 174 | } 175 | u64 type = _get_id(_self_types_params, _self_type); 176 | if(type == (u64)(-1)) 177 | { 178 | printf("[*] Error: Invalid SELF type.\n"); 179 | return FALSE; 180 | } 181 | sconf->self_type = type; 182 | 183 | if(_app_version == NULL) 184 | { 185 | printf("[*] Error: Please specify an application version.\n"); 186 | return FALSE; 187 | } 188 | sconf->app_version = _x_to_u64(_app_version); 189 | 190 | sconf->fw_version = 0; 191 | if(_fw_version != NULL) 192 | sconf->fw_version = _x_to_u64(_fw_version); 193 | 194 | sconf->add_shdrs = TRUE; 195 | if(_add_shdrs != NULL) 196 | if(strcmp(_add_shdrs, "FALSE") == 0) 197 | sconf->add_shdrs = FALSE; 198 | 199 | sconf->skip_sections = TRUE; 200 | if(_skip_sections != NULL) 201 | if(strcmp(_skip_sections, "FALSE") == 0) 202 | sconf->skip_sections = FALSE; 203 | 204 | sconf->ctrl_flags = NULL; 205 | if(_ctrl_flags != NULL) 206 | { 207 | if(strlen(_ctrl_flags) != 0x20*2) 208 | { 209 | printf("[*] Error: Control flags need to be 32 bytes.\n"); 210 | return FALSE; 211 | } 212 | sconf->ctrl_flags = _x_to_u8_buffer(_ctrl_flags); 213 | } 214 | 215 | sconf->cap_flags = NULL; 216 | if(_cap_flags != NULL) 217 | { 218 | if(strlen(_cap_flags) != 0x20*2) 219 | { 220 | printf("[*] Error: Capability flags need to be 32 bytes.\n"); 221 | return FALSE; 222 | } 223 | sconf->cap_flags = _x_to_u8_buffer(_cap_flags); 224 | } 225 | 226 | #ifdef CONFIG_CUSTOM_INDIV_SEED 227 | sconf->indiv_seed = NULL; 228 | if(_indiv_seed != NULL) 229 | { 230 | u32 len = strlen(_indiv_seed); 231 | if(len > 0x100*2) 232 | { 233 | printf("[*] Error: Individuals seed must be <= 0x100 bytes.\n"); 234 | return FALSE; 235 | } 236 | sconf->indiv_seed = _x_to_u8_buffer(_indiv_seed); 237 | sconf->indiv_seed_size = len / 2; 238 | } 239 | #endif 240 | 241 | sconf->npdrm_config = NULL; 242 | 243 | return TRUE; 244 | } 245 | 246 | static BOOL _fill_npdrm_config(self_config_t *sconf) 247 | { 248 | if((sconf->npdrm_config = (npdrm_config_t *)malloc(sizeof(npdrm_config_t))) == NULL) 249 | return FALSE; 250 | 251 | if(_license_type == NULL) 252 | { 253 | printf("[*] Error: Please specify a license type.\n"); 254 | return FALSE; 255 | } 256 | //TODO! 257 | if(strcmp(_license_type, "FREE") == 0) 258 | sconf->npdrm_config->license_type = NP_LICENSE_FREE; 259 | else if(strcmp(_license_type, "LOCAL") == 0) 260 | sconf->npdrm_config->license_type = NP_LICENSE_LOCAL; 261 | else 262 | { 263 | printf("[*] Error: Only supporting LOCAL and FREE license for now.\n"); 264 | return FALSE; 265 | } 266 | 267 | if(_app_type == NULL) 268 | { 269 | printf("[*] Error: Please specify an application type.\n"); 270 | return FALSE; 271 | } 272 | u64 type = _get_id(_np_app_types, _app_type); 273 | if(type == (u64)(-1)) 274 | { 275 | printf("[*] Error: Invalid application type.\n"); 276 | return FALSE; 277 | } 278 | sconf->npdrm_config->app_type = type; 279 | 280 | if(_content_id == NULL) 281 | { 282 | printf("[*] Error: Please specify a content ID.\n"); 283 | return FALSE; 284 | } 285 | strncpy((s8 *)sconf->npdrm_config->content_id, _content_id, 0x30); 286 | 287 | if(_real_fname == NULL) 288 | { 289 | printf("[*] Error: Please specify a real filename.\n"); 290 | return FALSE; 291 | } 292 | sconf->npdrm_config->real_fname = _real_fname; 293 | 294 | return TRUE; 295 | } 296 | 297 | void frontend_print_infos(s8 *file) 298 | { 299 | u8 *buf = _read_buffer(file, NULL); 300 | if(buf != NULL) 301 | { 302 | sce_buffer_ctxt_t *ctxt = sce_create_ctxt_from_buffer(buf); 303 | if(ctxt != NULL) 304 | { 305 | u8 *meta_info = NULL; 306 | if(_meta_info != NULL) 307 | { 308 | if(strlen(_meta_info) != 0x40*2) 309 | { 310 | printf("[*] Error: Metadata info needs to be 64 bytes.\n"); 311 | return; 312 | } 313 | meta_info = _x_to_u8_buffer(_meta_info); 314 | } 315 | 316 | u8 *keyset = NULL; 317 | if(_keyset != NULL) 318 | { 319 | if(strlen(_keyset) != (0x20 + 0x10 + 0x15 + 0x28 + 0x01)*2) 320 | { 321 | printf("[*] Error: Keyset has a wrong length.\n"); 322 | return; 323 | } 324 | keyset = _x_to_u8_buffer(_keyset); 325 | } 326 | 327 | if(sce_decrypt_header(ctxt, meta_info, keyset)) 328 | { 329 | _LOG_VERBOSE("Header decrypted.\n"); 330 | if(sce_decrypt_data(ctxt)) 331 | _LOG_VERBOSE("Data decrypted.\n"); 332 | else 333 | printf("[*] Warning: Could not decrypt data.\n"); 334 | } 335 | else 336 | printf("[*] Warning: Could not decrypt header.\n"); 337 | sce_print_info(stdout, ctxt); 338 | if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) 339 | self_print_info(stdout, ctxt); 340 | else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_RVK && ctxt->mdec == TRUE) 341 | rvk_print(stdout, ctxt); 342 | else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SPP && ctxt->mdec == TRUE) 343 | spp_print(stdout, ctxt); 344 | free(ctxt); 345 | } 346 | else 347 | printf("[*] Error: Could not process %s\n", file); 348 | free(buf); 349 | } 350 | else 351 | printf("[*] Error: Could not load %s\n", file); 352 | } 353 | 354 | void frontend_decrypt(s8 *file_in, s8 *file_out) 355 | { 356 | u8 *buf = _read_buffer(file_in, NULL); 357 | if(buf != NULL) 358 | { 359 | sce_buffer_ctxt_t *ctxt = sce_create_ctxt_from_buffer(buf); 360 | if(ctxt != NULL) 361 | { 362 | u8 *meta_info = NULL; 363 | if(_meta_info != NULL) 364 | { 365 | if(strlen(_meta_info) != 0x40*2) 366 | { 367 | printf("[*] Error: Metadata info needs to be 64 bytes.\n"); 368 | return; 369 | } 370 | meta_info = _x_to_u8_buffer(_meta_info); 371 | } 372 | 373 | u8 *keyset = NULL; 374 | if(_keyset != NULL) 375 | { 376 | if(strlen(_keyset) != (0x20 + 0x10 + 0x15 + 0x28 + 0x01)*2) 377 | { 378 | printf("[*] Error: Keyset has a wrong length.\n"); 379 | return; 380 | } 381 | keyset = _x_to_u8_buffer(_keyset); 382 | } 383 | 384 | if(sce_decrypt_header(ctxt, meta_info, keyset)) 385 | { 386 | _LOG_VERBOSE("Header decrypted.\n"); 387 | if(sce_decrypt_data(ctxt)) 388 | { 389 | _LOG_VERBOSE("Data decrypted.\n"); 390 | if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF) 391 | { 392 | if(self_write_to_elf(ctxt, file_out) == TRUE) 393 | printf("[*] ELF written to %s.\n", file_out); 394 | else 395 | printf("[*] Error: Could not write ELF.\n"); 396 | } 397 | else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_RVK) 398 | { 399 | if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset, 400 | ctxt->metash[0].data_size + ctxt->metash[1].data_size)) 401 | printf("[*] RVK written to %s.\n", file_out); 402 | else 403 | printf("[*] Error: Could not write RVK.\n"); 404 | } 405 | else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_PKG) 406 | { 407 | /*if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset, 408 | ctxt->metash[0].data_size + ctxt->metash[1].data_size + ctxt->metash[2].data_size)) 409 | printf("[*] PKG written to %s.\n", file_out); 410 | else 411 | printf("[*] Error: Could not write PKG.\n");*/ 412 | printf("soon...\n"); 413 | } 414 | else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SPP) 415 | { 416 | if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset, 417 | ctxt->metash[0].data_size + ctxt->metash[1].data_size)) 418 | printf("[*] SPP written to %s.\n", file_out); 419 | else 420 | printf("[*] Error: Could not write SPP.\n"); 421 | } 422 | } 423 | else 424 | printf("[*] Error: Could not decrypt data.\n"); 425 | } 426 | else 427 | printf("[*] Error: Could not decrypt header.\n"); 428 | free(ctxt); 429 | } 430 | else 431 | printf("[*] Error: Could not process %s\n", file_in); 432 | free(buf); 433 | } 434 | else 435 | printf("[*] Error: Could not load %s\n", file_in); 436 | } 437 | 438 | void frontend_encrypt(s8 *file_in, s8 *file_out) 439 | { 440 | BOOL can_compress = FALSE; 441 | self_config_t sconf; 442 | sce_buffer_ctxt_t *ctxt; 443 | u32 file_len = 0; 444 | u8 *file; 445 | 446 | if(_file_type == NULL) 447 | { 448 | printf("[*] Error: Please specify a file type.\n"); 449 | return; 450 | } 451 | 452 | u8 *keyset = NULL; 453 | if(_keyset != NULL) 454 | { 455 | if(strlen(_keyset) != (0x20 + 0x10 + 0x15 + 0x28 + 0x01)*2) 456 | { 457 | printf("[*] Error: Keyset has a wrong length.\n"); 458 | return; 459 | } 460 | keyset = _x_to_u8_buffer(_keyset); 461 | } 462 | 463 | if((file = _read_buffer(file_in, &file_len)) == NULL) 464 | { 465 | printf("[*] Error: Could not read %s.\n", file_in); 466 | return; 467 | } 468 | 469 | if(strcmp(_file_type, "SELF") == 0) 470 | { 471 | if(_self_type == NULL && _template == NULL) 472 | { 473 | printf("[*] Error: Please specify a SELF type.\n"); 474 | return; 475 | } 476 | 477 | if(_template != NULL) 478 | { 479 | //Use a template SELF to fill the config. 480 | if(_fill_self_config_template(_template, &sconf) == FALSE) 481 | return; 482 | } 483 | else 484 | { 485 | //Fill the config from command line arguments. 486 | if(_fill_self_config(&sconf) == FALSE) 487 | return; 488 | } 489 | 490 | if(sconf.self_type == SELF_TYPE_NPDRM) 491 | if(_fill_npdrm_config(&sconf) == FALSE) 492 | return; 493 | 494 | ctxt = sce_create_ctxt_build_self(file, file_len); 495 | if(self_build_self(ctxt, &sconf) == TRUE) 496 | printf("[*] SELF built.\n"); 497 | else 498 | { 499 | printf("[*] Error: SELF not built.\n"); 500 | return; 501 | } 502 | 503 | //SPU SELFs may not be compressed. 504 | if(!(sconf.self_type == SELF_TYPE_LDR || sconf.self_type == SELF_TYPE_ISO)) 505 | can_compress = TRUE; 506 | } 507 | else if(strcmp(_file_type, "RVK") == 0) 508 | { 509 | printf("soon...\n"); 510 | return; 511 | } 512 | else if(strcmp(_file_type, "PKG") == 0) 513 | { 514 | printf("soon...\n"); 515 | return; 516 | } 517 | else if(strcmp(_file_type, "SPP") == 0) 518 | { 519 | printf("soon...\n"); 520 | return; 521 | } 522 | 523 | //Compress data if wanted. 524 | if(_compress_data != NULL && strcmp(_compress_data, "TRUE") == 0) 525 | { 526 | if(can_compress == TRUE) 527 | { 528 | sce_compress_data(ctxt); 529 | printf("[*] Data compressed.\n"); 530 | } 531 | else 532 | printf("[*] Warning: This type of file will not be compressed.\n"); 533 | } 534 | 535 | //Layout and encrypt context. 536 | sce_layout_ctxt(ctxt); 537 | if(sce_encrypt_ctxt(ctxt, keyset) == TRUE) 538 | printf("[*] Data encrypted.\n"); 539 | else 540 | { 541 | printf("[*] Error: Data not encrypted.\n"); 542 | return; 543 | } 544 | 545 | //Write file. 546 | if(sce_write_ctxt(ctxt, file_out) == TRUE) 547 | { 548 | printf("[*] %s written.\n", file_out); 549 | //Add NPDRM footer signature. 550 | if(sconf.self_type == SELF_TYPE_NPDRM && _add_sig != NULL && strcmp(_add_sig, "TRUE") == 0) 551 | { 552 | if(np_sign_file(file_out) == TRUE) 553 | printf("[*] Added NPDRM footer signature.\n"); 554 | else 555 | printf("[*] Error: Could not add NPDRM footer signature.\n"); 556 | } 557 | } 558 | else 559 | printf("[*] Error: %s not written.\n", file_out); 560 | } 561 | -------------------------------------------------------------------------------- /keys.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2013 by naehrwert 3 | * Copyright (c) 2012 by flatz 4 | * This file is released under the GPLv2. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #ifdef _WIN32 14 | #include 15 | #else 16 | #include 17 | #endif 18 | 19 | #include "config.h" 20 | #include "types.h" 21 | #include "list.h" 22 | #include "sce.h" 23 | #include "keys.h" 24 | #include "util.h" 25 | #include "tables.h" 26 | #include "aes.h" 27 | 28 | /* 29 | [keyname] 30 | type={SELF, RVK, PKG, SPP, OTHER} 31 | revision={00, ..., 18, 8000} 32 | version={..., 0001000000000000, ...} 33 | self_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM} 34 | key=... 35 | erk=... 36 | riv=... 37 | pub=... 38 | priv=... 39 | ctype=... 40 | */ 41 | 42 | /*! Loaded keysets. */ 43 | list_t *_keysets; 44 | /*! Loaded curves. */ 45 | curve_t *_curves; 46 | /*! Loaded VSH curves. */ 47 | vsh_curve_t *_vsh_curves; 48 | 49 | static u8 rap_init_key[0x10] = 50 | { 51 | 0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF 52 | }; 53 | 54 | static u8 rap_pbox[0x10] = 55 | { 56 | 0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09 57 | }; 58 | 59 | static u8 rap_e1[0x10] = 60 | { 61 | 0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5 62 | }; 63 | 64 | static u8 rap_e2[0x10] = 65 | { 66 | 0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74 67 | }; 68 | 69 | static void _fill_property(keyset_t *ks, s8 *prop, s8 *value) 70 | { 71 | if(strcmp(prop, "type") == 0) 72 | { 73 | if(strcmp(value, "SELF") == 0) 74 | ks->type = KEYTYPE_SELF; 75 | else if(strcmp(value, "RVK") == 0) 76 | ks->type = KEYTYPE_RVK; 77 | else if(strcmp(value, "PKG") == 0) 78 | ks->type = KEYTYPE_PKG; 79 | else if(strcmp(value, "SPP") == 0) 80 | ks->type = KEYTYPE_SPP; 81 | else if(strcmp(value, "OTHER") == 0) 82 | ks->type = KEYTYPE_OTHER; 83 | else 84 | printf("[*] Error: Unknown type '%s'.\n", value); 85 | } 86 | else if(strcmp(prop, "revision") == 0) 87 | ks->key_revision = (u16)_x_to_u64(value); 88 | else if(strcmp(prop, "version") == 0) 89 | ks->version = _x_to_u64(value); 90 | else if(strcmp(prop, "self_type") == 0) 91 | { 92 | if(strcmp(value, "LV0") == 0) 93 | ks->self_type = SELF_TYPE_LV0; 94 | else if(strcmp(value, "LV1") == 0) 95 | ks->self_type = SELF_TYPE_LV1; 96 | else if(strcmp(value, "LV2") == 0) 97 | ks->self_type = SELF_TYPE_LV2; 98 | else if(strcmp(value, "APP") == 0) 99 | ks->self_type = SELF_TYPE_APP; 100 | else if(strcmp(value, "ISO") == 0) 101 | ks->self_type = SELF_TYPE_ISO; 102 | else if(strcmp(value, "LDR") == 0) 103 | ks->self_type = SELF_TYPE_LDR; 104 | else if(strcmp(value, "UNK_7") == 0) 105 | ks->self_type = SELF_TYPE_UNK_7; 106 | else if(strcmp(value, "NPDRM") == 0) 107 | ks->self_type = SELF_TYPE_NPDRM; 108 | else 109 | printf("[*] Error: unknown SELF type '%s'.\n", value); 110 | } 111 | else if(strcmp(prop, "erk") == 0 || strcmp(prop, "key") == 0) 112 | { 113 | ks->erk = _x_to_u8_buffer(value); 114 | ks->erklen = strlen(value) / 2; 115 | } 116 | else if(strcmp(prop, "riv") == 0) 117 | { 118 | ks->riv = _x_to_u8_buffer(value); 119 | ks->rivlen = strlen(value) / 2; 120 | } 121 | else if(strcmp(prop, "pub") == 0) 122 | ks->pub = _x_to_u8_buffer(value); 123 | else if(strcmp(prop, "priv") == 0) 124 | ks->priv = _x_to_u8_buffer(value); 125 | else if(strcmp(prop, "ctype") == 0) 126 | ks->ctype = (u8)_x_to_u64(value); 127 | else 128 | printf("[*] Error: Unknown keyfile property '%s'.\n", prop); 129 | } 130 | 131 | static s64 _compare_keysets(keyset_t *ks1, keyset_t *ks2) 132 | { 133 | s64 res; 134 | 135 | if((res = (s64)ks1->version - (s64)ks2->version) == 0) 136 | res = (s64)ks1->key_revision - (s64)ks2->key_revision; 137 | 138 | return res; 139 | } 140 | 141 | static void _sort_keysets() 142 | { 143 | u32 i, to = _keysets->count; 144 | lnode_t *max; 145 | 146 | list_t *tmp = list_create(); 147 | 148 | for(i = 0; i < to; i++) 149 | { 150 | max = _keysets->head; 151 | LIST_FOREACH(iter, _keysets) 152 | { 153 | if(_compare_keysets((keyset_t *)max->value, (keyset_t *)iter->value) < 0) 154 | max = iter; 155 | } 156 | list_push(tmp, max->value); 157 | list_remove_node(_keysets, max); 158 | } 159 | 160 | list_destroy(_keysets); 161 | _keysets = tmp; 162 | } 163 | 164 | void _print_key_list(FILE *fp) 165 | { 166 | const s8 *name; 167 | s32 len = 0, tmp; 168 | 169 | LIST_FOREACH(iter, _keysets) 170 | if((tmp = strlen(((keyset_t *)iter->value)->name)) > len) 171 | len = tmp; 172 | 173 | fprintf(fp, " Name"); 174 | _print_align(fp, " ", len, 4); 175 | fprintf(fp, " Type Revision Version SELF-Type\n"); 176 | 177 | LIST_FOREACH(iter, _keysets) 178 | { 179 | keyset_t *ks = (keyset_t *)iter->value; 180 | fprintf(fp, " %s", ks->name); 181 | _print_align(fp, " ", len, strlen(ks->name)); 182 | fprintf(fp, " %-5s 0x%04X %s ", _get_name(_key_types, ks->type), ks->key_revision, sce_version_to_str(ks->version)); 183 | if(ks->type == KEYTYPE_SELF) 184 | { 185 | name = _get_name(_self_types, ks->self_type); 186 | if(name != NULL) 187 | fprintf(fp, "[%s]\n", name); 188 | else 189 | fprintf(fp, "0x%08X\n", ks->self_type); 190 | } 191 | else 192 | fprintf(fp, "\n"); 193 | } 194 | } 195 | 196 | #define LINEBUFSIZE 512 197 | BOOL keys_load(const s8 *kfile) 198 | { 199 | u32 i = 0, lblen; 200 | FILE *fp; 201 | s8 lbuf[LINEBUFSIZE]; 202 | keyset_t *cks = NULL; 203 | 204 | if((_keysets = list_create()) == NULL) 205 | return FALSE; 206 | 207 | if((fp = fopen(kfile, "r")) == NULL) 208 | { 209 | list_destroy(_keysets); 210 | return FALSE; 211 | } 212 | 213 | do 214 | { 215 | //Get next line. 216 | lbuf[0] = 0; 217 | fgets(lbuf, LINEBUFSIZE, fp); 218 | lblen = strlen(lbuf); 219 | 220 | //Don't parse empty lines (ignore '\n') and comment lines (starting with '#'). 221 | if(lblen > 1 && lbuf[0] != '#') 222 | { 223 | //Remove '\n'. 224 | lbuf[lblen-1] = 0; 225 | 226 | //Check for keyset entry. 227 | if(lblen > 2 && lbuf[0] == '[') 228 | { 229 | if(cks != NULL) 230 | { 231 | //Add to keyset list. 232 | list_push(_keysets, cks); 233 | cks = NULL; 234 | } 235 | 236 | //Find name end. 237 | for(i = 0; lbuf[i] != ']' && lbuf[i] != '\n' && i < lblen; i++); 238 | lbuf[i] = 0; 239 | 240 | //Allocate keyset and fill name. 241 | cks = (keyset_t *)malloc(sizeof(keyset_t)); 242 | memset(cks, 0, sizeof(keyset_t)); 243 | cks->name = strdup(&lbuf[1]); 244 | } 245 | else if(cks != NULL) 246 | { 247 | //Find property name end. 248 | for(i = 0; lbuf[i] != '=' && lbuf[i] != '\n' && i < lblen; i++); 249 | lbuf[i] = 0; 250 | 251 | //Fill property. 252 | _fill_property(cks, &lbuf[0], &lbuf[i+1]); 253 | } 254 | } 255 | } while(!feof(fp)); 256 | 257 | //Add last keyset to keyset list. 258 | if(cks != NULL) 259 | list_push(_keysets, cks); 260 | 261 | //Sort keysets. 262 | _sort_keysets(); 263 | 264 | return TRUE; 265 | } 266 | #undef LINEBUFSIZE 267 | 268 | static keyset_t *_keyset_find_for_self(u32 self_type, u16 key_revision, u64 version) 269 | { 270 | LIST_FOREACH(iter, _keysets) 271 | { 272 | keyset_t *ks = (keyset_t *)iter->value; 273 | 274 | if(ks->self_type == self_type) 275 | { 276 | switch(self_type) 277 | { 278 | case SELF_TYPE_LV0: 279 | return ks; 280 | break; 281 | case SELF_TYPE_LV1: 282 | if(version <= ks->version) 283 | return ks; 284 | break; 285 | case SELF_TYPE_LV2: 286 | if(version <= ks->version) 287 | return ks; 288 | break; 289 | case SELF_TYPE_APP: 290 | if(key_revision == ks->key_revision) 291 | return ks; 292 | break; 293 | case SELF_TYPE_ISO: 294 | if(version <= ks->version && key_revision == ks->key_revision) 295 | return ks; 296 | break; 297 | case SELF_TYPE_LDR: 298 | return ks; 299 | break; 300 | case SELF_TYPE_NPDRM: 301 | if(key_revision == ks->key_revision) 302 | return ks; 303 | break; 304 | } 305 | } 306 | } 307 | 308 | return NULL; 309 | } 310 | 311 | static keyset_t *_keyset_find_for_rvk(u32 key_revision) 312 | { 313 | LIST_FOREACH(iter, _keysets) 314 | { 315 | keyset_t *ks = (keyset_t *)iter->value; 316 | 317 | if(ks->type == KEYTYPE_RVK && key_revision <= ks->key_revision) 318 | return ks; 319 | } 320 | 321 | return NULL; 322 | } 323 | 324 | static keyset_t *_keyset_find_for_pkg(u16 key_revision) 325 | { 326 | LIST_FOREACH(iter, _keysets) 327 | { 328 | keyset_t *ks = (keyset_t *)iter->value; 329 | 330 | if(ks->type == KEYTYPE_PKG && key_revision <= ks->key_revision) 331 | return ks; 332 | } 333 | 334 | return NULL; 335 | } 336 | 337 | static keyset_t *_keyset_find_for_spp(u16 key_revision) 338 | { 339 | LIST_FOREACH(iter, _keysets) 340 | { 341 | keyset_t *ks = (keyset_t *)iter->value; 342 | 343 | if(ks->type == KEYTYPE_SPP && key_revision <= ks->key_revision) 344 | return ks; 345 | } 346 | 347 | return NULL; 348 | } 349 | 350 | keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt) 351 | { 352 | keyset_t *res = NULL; 353 | 354 | switch(ctxt->sceh->header_type) 355 | { 356 | case SCE_HEADER_TYPE_SELF: 357 | res = _keyset_find_for_self(ctxt->self.ai->self_type, ctxt->sceh->key_revision, ctxt->self.ai->version); 358 | break; 359 | case SCE_HEADER_TYPE_RVK: 360 | res = _keyset_find_for_rvk(ctxt->sceh->key_revision); 361 | break; 362 | case SCE_HEADER_TYPE_PKG: 363 | res = _keyset_find_for_pkg(ctxt->sceh->key_revision); 364 | break; 365 | case SCE_HEADER_TYPE_SPP: 366 | res = _keyset_find_for_spp(ctxt->sceh->key_revision); 367 | break; 368 | } 369 | 370 | if(res == NULL) 371 | printf("[*] Error: Could not find keyset for %s.\n", _get_name(_sce_header_types, ctxt->sceh->header_type)); 372 | 373 | return res; 374 | } 375 | 376 | keyset_t *keyset_find_by_name(const s8 *name) 377 | { 378 | LIST_FOREACH(iter, _keysets) 379 | { 380 | keyset_t *ks = (keyset_t *)iter->value; 381 | if(strcmp(ks->name, name) == 0) 382 | return ks; 383 | } 384 | 385 | printf("[*] Error: Could not find keyset '%s'.\n", name); 386 | 387 | return NULL; 388 | } 389 | 390 | BOOL curves_load(const s8 *cfile) 391 | { 392 | u32 len = 0; 393 | 394 | _curves = (curve_t *)_read_buffer(cfile, &len); 395 | 396 | if(_curves == NULL) 397 | return FALSE; 398 | 399 | if(len != CURVES_LENGTH) 400 | { 401 | free(_curves); 402 | return FALSE; 403 | } 404 | 405 | return TRUE; 406 | } 407 | 408 | curve_t *curve_find(u8 ctype) 409 | { 410 | if(ctype > CTYPE_MAX) 411 | return NULL; 412 | return &_curves[ctype]; 413 | } 414 | 415 | BOOL vsh_curves_load(const s8 *cfile) 416 | { 417 | u32 len = 0; 418 | 419 | _vsh_curves = (vsh_curve_t *)_read_buffer(cfile, &len); 420 | 421 | if(_vsh_curves == NULL) 422 | return FALSE; 423 | 424 | if(len != VSH_CURVES_LENGTH) 425 | { 426 | free(_vsh_curves); 427 | return FALSE; 428 | } 429 | 430 | return TRUE; 431 | } 432 | 433 | static curve_t _tmp_curve; 434 | curve_t *vsh_curve_find(u8 ctype) 435 | { 436 | if(ctype > VSH_CTYPE_MAX) 437 | return NULL; 438 | 439 | _memcpy_inv(_tmp_curve.p, _vsh_curves[ctype].p, 20); 440 | _memcpy_inv(_tmp_curve.a, _vsh_curves[ctype].a, 20); 441 | _memcpy_inv(_tmp_curve.b, _vsh_curves[ctype].b, 20); 442 | _tmp_curve.N[0] = ~0x00; 443 | _memcpy_inv(_tmp_curve.N+1, _vsh_curves[ctype].N, 20); 444 | _memcpy_inv(_tmp_curve.Gx, _vsh_curves[ctype].Gx, 20); 445 | _memcpy_inv(_tmp_curve.Gy, _vsh_curves[ctype].Gx, 20); 446 | 447 | return &_tmp_curve; 448 | } 449 | 450 | static u8 *idps_load() 451 | { 452 | s8 *ps3 = NULL, path[256]; 453 | u8 *idps; 454 | u32 len = 0; 455 | 456 | if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) 457 | if(access(ps3, 0) != 0) 458 | ps3 = NULL; 459 | 460 | if(ps3 != NULL) 461 | { 462 | sprintf(path, "%s/%s", ps3, CONFIG_IDPS_FILE); 463 | if(access(path, 0) != 0) 464 | sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); 465 | } 466 | else 467 | sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE); 468 | 469 | idps = (u8 *)_read_buffer(path, &len); 470 | 471 | if(idps == NULL) 472 | return NULL; 473 | 474 | if(len != IDPS_LENGTH) 475 | { 476 | free(idps); 477 | return NULL; 478 | } 479 | 480 | return idps; 481 | } 482 | 483 | static act_dat_t *act_dat_load() 484 | { 485 | s8 *ps3 = NULL, path[256]; 486 | act_dat_t *act_dat; 487 | u32 len = 0; 488 | 489 | if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) 490 | if(access(ps3, 0) != 0) 491 | ps3 = NULL; 492 | 493 | if(ps3 != NULL) 494 | { 495 | sprintf(path, "%s/%s", ps3, CONFIG_ACT_DAT_FILE); 496 | if(access(path, 0) != 0) 497 | sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); 498 | } 499 | else 500 | sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE); 501 | 502 | act_dat = (act_dat_t *)_read_buffer(path, &len); 503 | 504 | if(act_dat == NULL) 505 | return NULL; 506 | 507 | if(len != ACT_DAT_LENGTH) 508 | { 509 | free(act_dat); 510 | return NULL; 511 | } 512 | 513 | return act_dat; 514 | } 515 | 516 | static rif_t *rif_load(const s8 *content_id) 517 | { 518 | s8 *ps3 = NULL, path[256]; 519 | rif_t *rif; 520 | u32 len = 0; 521 | 522 | if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) 523 | if(access(ps3, 0) != 0) 524 | ps3 = NULL; 525 | 526 | if(ps3 != NULL) 527 | { 528 | sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RIF_FILE_EXT); 529 | if(access(path, 0) != 0) 530 | sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); 531 | } 532 | else 533 | sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT); 534 | 535 | rif = (rif_t *)_read_buffer(path, &len); 536 | if(rif == NULL) 537 | return NULL; 538 | 539 | if(len < RIF_LENGTH) 540 | { 541 | free(rif); 542 | return NULL; 543 | } 544 | 545 | return rif; 546 | } 547 | 548 | static u8 *rap_load(const s8 *content_id) 549 | { 550 | s8 *ps3 = NULL, path[256]; 551 | u8 *rap; 552 | u32 len = 0; 553 | 554 | if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL) 555 | if(access(ps3, 0) != 0) 556 | ps3 = NULL; 557 | 558 | if(ps3 != NULL) 559 | { 560 | sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RAP_FILE_EXT); 561 | if(access(path, 0) != 0) 562 | sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); 563 | } 564 | else 565 | sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT); 566 | 567 | rap = (u8 *)_read_buffer(path, &len); 568 | 569 | if(rap == NULL) 570 | return NULL; 571 | 572 | if(len != RAP_LENGTH) 573 | { 574 | free(rap); 575 | return NULL; 576 | } 577 | 578 | return rap; 579 | } 580 | 581 | static BOOL rap_to_klicensee(const s8 *content_id, u8 *klicensee) 582 | { 583 | u8 *rap; 584 | aes_context aes_ctxt; 585 | int round_num; 586 | int i; 587 | 588 | rap = rap_load(content_id); 589 | if(rap == NULL) 590 | return FALSE; 591 | 592 | aes_setkey_dec(&aes_ctxt, rap_init_key, RAP_KEYBITS); 593 | aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rap, rap); 594 | 595 | for (round_num = 0; round_num < 5; ++round_num) 596 | { 597 | for (i = 0; i < 16; ++i) 598 | { 599 | int p = rap_pbox[i]; 600 | rap[p] ^= rap_e1[p]; 601 | } 602 | for (i = 15; i >= 1; --i) 603 | { 604 | int p = rap_pbox[i]; 605 | int pp = rap_pbox[i - 1]; 606 | rap[p] ^= rap[pp]; 607 | } 608 | int o = 0; 609 | for (i = 0; i < 16; ++i) 610 | { 611 | int p = rap_pbox[i]; 612 | u8 kc = rap[p] - o; 613 | u8 ec2 = rap_e2[p]; 614 | if (o != 1 || kc != 0xFF) 615 | { 616 | o = kc < ec2 ? 1 : 0; 617 | rap[p] = kc - ec2; 618 | } 619 | else if (kc == 0xFF) 620 | rap[p] = kc - ec2; 621 | else 622 | rap[p] = kc; 623 | } 624 | } 625 | 626 | memcpy(klicensee, rap, RAP_LENGTH); 627 | free(rap); 628 | 629 | return TRUE; 630 | } 631 | 632 | BOOL klicensee_by_content_id(const s8 *content_id, u8 *klicensee) 633 | { 634 | aes_context aes_ctxt; 635 | 636 | if(rap_to_klicensee(content_id, klicensee) == FALSE) 637 | { 638 | keyset_t *ks_np_idps_const, *ks_np_rif_key; 639 | rif_t *rif; 640 | u8 idps_const[0x10]; 641 | u8 act_dat_key[0x10]; 642 | u32 act_dat_key_index; 643 | u8 *idps; 644 | act_dat_t *act_dat; 645 | 646 | if((idps = idps_load()) == NULL) 647 | { 648 | printf("[*] Error: Could not load IDPS.\n"); 649 | return FALSE; 650 | } 651 | else 652 | _LOG_VERBOSE("IDPS loaded.\n"); 653 | 654 | if((act_dat = act_dat_load()) == NULL) 655 | { 656 | printf("[*] Error: Could not load act.dat.\n"); 657 | return FALSE; 658 | } 659 | else 660 | _LOG_VERBOSE("act.dat loaded.\n"); 661 | 662 | ks_np_idps_const = keyset_find_by_name(CONFIG_NP_IDPS_CONST_KNAME); 663 | if(ks_np_idps_const == NULL) 664 | return FALSE; 665 | memcpy(idps_const, ks_np_idps_const->erk, 0x10); 666 | 667 | ks_np_rif_key = keyset_find_by_name(CONFIG_NP_RIF_KEY_KNAME); 668 | if(ks_np_rif_key == NULL) 669 | return FALSE; 670 | 671 | rif = rif_load(content_id); 672 | if(rif == NULL) 673 | { 674 | printf("[*] Error: Could not obtain klicensee for '%s'.\n", content_id); 675 | return FALSE; 676 | } 677 | 678 | aes_setkey_dec(&aes_ctxt, ks_np_rif_key->erk, RIF_KEYBITS); 679 | aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->act_key_index, rif->act_key_index); 680 | 681 | act_dat_key_index = _ES32(*(u32 *)(rif->act_key_index + 12)); 682 | if(act_dat_key_index > 127) 683 | { 684 | printf("[*] Error: act.dat key index out of bounds.\n"); 685 | return FALSE; 686 | } 687 | 688 | memcpy(act_dat_key, act_dat->primary_key_table + act_dat_key_index * BITS2BYTES(ACT_DAT_KEYBITS), BITS2BYTES(ACT_DAT_KEYBITS)); 689 | 690 | aes_setkey_enc(&aes_ctxt, idps, IDPS_KEYBITS); 691 | aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, idps_const, idps_const); 692 | 693 | aes_setkey_dec(&aes_ctxt, idps_const, IDPS_KEYBITS); 694 | aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, act_dat_key, act_dat_key); 695 | 696 | aes_setkey_dec(&aes_ctxt, act_dat_key, ACT_DAT_KEYBITS); 697 | aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->klicensee, klicensee); 698 | 699 | free(rif); 700 | 701 | _LOG_VERBOSE("klicensee decrypted.\n"); 702 | } 703 | else 704 | _LOG_VERBOSE("klicensee converted from %s.rap.\n", content_id); 705 | 706 | return TRUE; 707 | } 708 | 709 | keyset_t *keyset_from_buffer(u8 *keyset) 710 | { 711 | keyset_t *ks; 712 | 713 | if((ks = (keyset_t *)malloc(sizeof(keyset_t))) == NULL) 714 | return NULL; 715 | 716 | ks->erk = (u8 *)_memdup(keyset, 0x20); 717 | ks->erklen = 0x20; 718 | ks->riv = (u8 *)_memdup(keyset + 0x20, 0x10); 719 | ks->rivlen = 0x10; 720 | ks->pub = (u8 *)_memdup(keyset + 0x20 + 0x10, 0x28); 721 | ks->priv = (u8 *)_memdup(keyset + 0x20 + 0x10 + 0x28, 0x15); 722 | ks->ctype = (u8)*(keyset + 0x20 + 0x10 + 0x28 + 0x15); 723 | 724 | return ks; 725 | } 726 | --------------------------------------------------------------------------------