1
Fork 0
mirror of https://github.com/naehrwert/scetool.git synced 2025-04-21 20:27:47 +00:00

Initial commit.

This commit is contained in:
naehrwert 2013-05-10 13:02:25 +02:00
commit 5557aa64b1
46 changed files with 14082 additions and 0 deletions

59
Makefile Normal file
View file

@ -0,0 +1,59 @@
CC=gcc
CFLAGS=-g -O0 -Wall
OS_TARGET=scetool
LDFLAGS=-lz
OBJS=aes.o aes_omac.o bignum.o bn.o ec.o ecdsa.o frontend.o getopt.o keys.o list.o \
main.o mt19937.o np.o rvk.o sce.o self.o sha1.o tables.o util.o spp.o
.SILENT:
.SUFFIXES: .c .cpp .o
$(OS_TARGET): $(OBJS)
${LINK}
if $(CC) $(CFLAGS) $(OBJS) -o $(OS_TARGET) $(LDFLAGS) $(LIBS); then \
${LINK_OK}; \
else \
${LINK_FAILED}; \
fi
%.o: %.c
${COMPILE_STATUS}
if ${CC} ${CFLAGS} ${CFLAGS} -c -o $@ $<; then \
${COMPILE_OK}; \
else \
${COMPILE_FAILED}; \
fi
%.o: %.cpp
${COMPILE_STATUS}
if ${CC} ${CFLAGS} ${CFLAGS} -c -o $@ $<; then \
${COMPILE_OK}; \
else \
${COMPILE_FAILED}; \
fi
clean:
@printf "\033[K\033[0;32mCleaning\033[1;32m\033[0;32m...\033[0m\n"
rm -rf *.o $(OS_TARGET)
install:
@printf "\033[K\033[0;32mInstalling\033[1;32m\033[0;32m...\033[0m\n"
install -m755 $(OS_TARGET) $(BINDIR)
DIR_ENTER = printf "\033[K\033[0;36mEntering directory \033[1;36m$$i\033[0;36m.\033[0m\n"; cd $$i || exit 1
DIR_LEAVE = printf "\033[K\033[0;36mLeaving directory \033[1;36m$$i\033[0;36m.\033[0m\n"; cd .. || exit 1
DEPEND_STATUS = printf "\033[K\033[0;33mGenerating dependencies...\033[0m\r"
DEPEND_OK = printf "\033[K\033[0;32mSuccessfully generated dependencies.\033[0m\n"
DEPEND_FAILED = printf "\033[K\033[0;31mFailed to generate dependencies!\033[0m\n"; exit 1
COMPILE_STATUS = printf "\033[K\033[0;33mCompiling \033[1;33m$<\033[0;33m...\033[0m\r"
COMPILE_OK = printf "\033[K\033[0;32mSuccessfully compiled \033[1;32m$<\033[0;32m.\033[0m\n"
COMPILE_FAILED = printf "\033[K\033[0;31mFailed to compile \033[1;31m$<\033[0;31m!\033[0m\n"; exit 1
LINK_STATUS = printf "\033[K\033[0;33mLinking \033[1;33m$@\033[0;33m...\033[0m\r"
LINK_OK = printf "\033[K\033[0;32mSuccessfully linked \033[1;32m$@\033[0;32m.\033[0m\n"
LINK_FAILED = printf "\033[K\033[0;31mFailed to link \033[1;31m$@\033[0;31m!\033[0m\n"; exit 1
INSTALL_STATUS = printf "\033[K\033[0;33mInstalling \033[1;33m$$i\033[0;33m...\033[0m\r"
INSTALL_OK = printf "\033[K\033[0;32mSuccessfully installed \033[1;32m$$i\033[0;32m.\033[0m\n"
INSTALL_FAILED = printf "\033[K\033[0;31mFailed to install \033[1;31m$$i\033[0;31m!\033[0m\n"; exit 1
DELETE_OK = printf "\033[K\033[0;34mDeleted \033[1;34m$$i\033[0;34m.\033[0m\n"
DELETE_FAILED = printf "\033[K\033[0;31mFailed to delete \033[1;31m$$i\033[0;31m!\033[0m\n"; exit 1

121
README Normal file
View file

@ -0,0 +1,121 @@
scetool (C) 2011-2013 by naehrwert
NP local license handling (C) 2012 by flatz
==> Setup <==
- /data/keys : Keyfile.
- /data/ldr_curves : Loader curves (7744 bytes).
- /data/vsh_curves : VSH curves (360 bytes).
- /data/idps : IDPS as binary file
- /data/act.dat : act.dat
- /rifs/* : *.rif files
- /raps/* : *.rap files
==> Keyfile Format <==
[keyname]
type={SELF, RVK, PKG, SPP, OTHER}
revision={00, ..., 18, 8000}
version={..., 0001000000000000, ...}
self_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM}
key=...
erk=...
riv=...
pub=...
priv=...
ctype=...
==> Keyset Example <==
[metldr]
type=SELF
revision=00
self_type=LDR
erk=0000000000000000000000000000000000000000000000000000000000000000
riv=00000000000000000000000000000000
pub=00000000000000000000000000000000000000000000000000000000000000000000000000000000
priv=000000000000000000000000000000000000000000
ctype=00
==> NPDRM Key(set) Names <==
- [NP_tid]: Title ID OMAC1 key.
- [NP_ci]: Control info OMAC1 key.
- [NP_klic_free]: Free klicensee.
- [NP_klic_key]: klicensee key.
- [NP_idps_const]: IDPS constant.
- [NP_rif_key]: rif key.
- [NP_sig]: Footer signature ECDSA keyset.
==> Override Keyset <==
It should be a single hex-string consisting of:
32 bytes (Key) 16 bytes (IV) 40 bytes (Pub) 21 bytes (Priv) 1 byte (CType).
==> Help Text <==
USAGE: scetool [options] command
COMMANDS Parameters Explanation
-h, --help Print this help.
-k, --print-keys List keys.
-i, --print-infos File-in Print SCE file info.
-d, --decrypt File-in File-out Decrypt/dump SCE file.
-e, --encrypt File-in File-out Encrypt/create SCE file.
OPTIONS Possible Values Explanation
-v, --verbose Enable verbose output.
-r, --raw Enable raw value output.
-t, --template File-in Template file (SELF only)
-0, --sce-type SELF/RVK/PKG/SPP SCE File Type
-1, --compress-data TRUE/FALSE(default) Whether to compress data or not.
-s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not.
-2, --key-revision e.g. 00,01,...,0A,... Key Revision
-m, --meta-info 64 bytes Use provided meta info to decrypt.
-K, --keyset 32(Key)16(IV)
40(Pub)21(Priv)1(CT) Override keyset.
-3, --self-auth-id e.g. 1010000001000003 Authentication ID
-4, --self-vendor-id e.g. 01000002 Vendor ID
-5, --self-type LV0/LV1/LV2/APP/ISO/
LDR/NPDRM SELF Type
-A, --self-app-version e.g. 0001000000000000 Application Version
-6, --self-fw-version e.g. 0003004100000000 Firmware Version
-7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not.
-8, --self-ctrl-flags 32 bytes Override control flags.
-9, --self-cap-flags 32 bytes Override capability flags.
-b, --np-license-type LOCAL/FREE License Type
-c, --np-app-type SPRX/EXEC/USPRX/UEXEC App Type (U* for updates)
-f, --np-content-id Content ID
-l, --np-klicensee 16 bytes Override klicensee.
-g, --np-real-fname e.g. EBOOT.BIN Real Filename
-j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not.
==> History <==
Version 0.2.9
- Plaintext sections will now take less space in metadata header keys array.
- Added option to specifiy a template SELF to take configuration values from.
- Added option to override the keyset used for en-/decryption.
- Fixed NP application types.
- [Firmware Version] will now be written to control info only.
- [Application Version] will now be written to application info only.
Version 0.2.8 (intermediate release):
- Fixed minor bugs where scetool would crash.
- Added SPP parsing.
- Decrypting RVK/SPP will now write header+data to file.
Version 0.2.7:
- Added local NP license handling.
- Added option to override klicensee.
- Added option to disable section skipping (in SELF generation).
Version 0.2.5:
- Added option to use provided metadata info for decryption.
- "PS3" path environment variable will now be searched for keys/ldr_curves/vsh_curves too.
Version 0.2.4:
- Added option to display raw values.
- Moved factory Auth-IDs to <public build> (as they are on ps3devwiki now).
Version 0.2.2:
- Added options to override control/capability flags (32 bytes each).
- Fixed where a false keyset would crash scetool when decrypting a file.
- Some source level changes and optimizations.
Version 0.2.1:
- zlib is required to use scetool.
- 'sdk_type' was changed to 'revision' in data/keys.
==> Greetings to <==
- ps3dev.net
- you know who you are!
==> Trivia <==
http://bit.ly/QUji89

695
aes.c Normal file
View file

@ -0,0 +1,695 @@
/*
* FIPS-197 compliant AES implementation
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include "aes.h"
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i) \
{ \
(n) = ( (unsigned long) (b)[(i) ] ) \
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
}
#endif
/*
* Forward S-box
*/
static const unsigned char FSb[256] =
{
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
/*
* Forward tables
*/
#define FT \
\
V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
#define V(a,b,c,d) 0x##a##b##c##d
static const unsigned long FT0[256] = { FT };
#undef V
#define V(a,b,c,d) 0x##b##c##d##a
static const unsigned long FT1[256] = { FT };
#undef V
#define V(a,b,c,d) 0x##c##d##a##b
static const unsigned long FT2[256] = { FT };
#undef V
#define V(a,b,c,d) 0x##d##a##b##c
static const unsigned long FT3[256] = { FT };
#undef V
#undef FT
/*
* Reverse S-box
*/
static const unsigned char RSb[256] =
{
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};
/*
* Reverse tables
*/
#define RT \
\
V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
#define V(a,b,c,d) 0x##a##b##c##d
static const unsigned long RT0[256] = { RT };
#undef V
#define V(a,b,c,d) 0x##b##c##d##a
static const unsigned long RT1[256] = { RT };
#undef V
#define V(a,b,c,d) 0x##c##d##a##b
static const unsigned long RT2[256] = { RT };
#undef V
#define V(a,b,c,d) 0x##d##a##b##c
static const unsigned long RT3[256] = { RT };
#undef V
#undef RT
/*
* Round constants
*/
static const unsigned long RCON[10] =
{
0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x0000001B, 0x00000036
};
/*
* AES key schedule (encryption)
*/
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
{
unsigned int i;
unsigned long *RK;
switch( keysize )
{
case 128: ctx->nr = 10; break;
case 192: ctx->nr = 12; break;
case 256: ctx->nr = 14; break;
default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
}
ctx->rk = RK = ctx->buf;
for( i = 0; i < (keysize >> 5); i++ )
{
GET_ULONG_LE( RK[i], key, i << 2 );
}
switch( ctx->nr )
{
case 10:
for( i = 0; i < 10; i++, RK += 4 )
{
RK[4] = RK[0] ^ RCON[i] ^
( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 );
RK[5] = RK[1] ^ RK[4];
RK[6] = RK[2] ^ RK[5];
RK[7] = RK[3] ^ RK[6];
}
break;
case 12:
for( i = 0; i < 8; i++, RK += 6 )
{
RK[6] = RK[0] ^ RCON[i] ^
( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 );
RK[7] = RK[1] ^ RK[6];
RK[8] = RK[2] ^ RK[7];
RK[9] = RK[3] ^ RK[8];
RK[10] = RK[4] ^ RK[9];
RK[11] = RK[5] ^ RK[10];
}
break;
case 14:
for( i = 0; i < 7; i++, RK += 8 )
{
RK[8] = RK[0] ^ RCON[i] ^
( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 );
RK[9] = RK[1] ^ RK[8];
RK[10] = RK[2] ^ RK[9];
RK[11] = RK[3] ^ RK[10];
RK[12] = RK[4] ^
( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
RK[13] = RK[5] ^ RK[12];
RK[14] = RK[6] ^ RK[13];
RK[15] = RK[7] ^ RK[14];
}
break;
default:
break;
}
return( 0 );
}
/*
* AES key schedule (decryption)
*/
int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
{
int i, j;
aes_context cty;
unsigned long *RK;
unsigned long *SK;
int ret;
switch( keysize )
{
case 128: ctx->nr = 10; break;
case 192: ctx->nr = 12; break;
case 256: ctx->nr = 14; break;
default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
}
ctx->rk = RK = ctx->buf;
ret = aes_setkey_enc( &cty, key, keysize );
if( ret != 0 )
return( ret );
SK = cty.rk + cty.nr * 4;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
{
for( j = 0; j < 4; j++, SK++ )
{
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
}
}
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
*RK++ = *SK++;
memset( &cty, 0, sizeof( aes_context ) );
return( 0 );
}
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y0 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
FT3[ ( Y2 >> 24 ) & 0xFF ]; \
}
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
{ \
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y1 >> 24 ) & 0xFF ]; \
\
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y2 >> 24 ) & 0xFF ]; \
\
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y3 >> 24 ) & 0xFF ]; \
\
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
RT3[ ( Y0 >> 24 ) & 0xFF ]; \
}
/*
* AES-ECB block encryption/decryption
*/
int aes_crypt_ecb( aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
int i;
unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
RK = ctx->rk;
GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++;
GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++;
GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++;
GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
if( mode == AES_DECRYPT )
{
for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
{
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
}
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
X0 = *RK++ ^ \
( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
X1 = *RK++ ^ \
( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
X2 = *RK++ ^ \
( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
X3 = *RK++ ^ \
( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^
( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
}
else /* AES_ENCRYPT */
{
for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
{
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
}
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
X0 = *RK++ ^ \
( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
X1 = *RK++ ^ \
( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
X2 = *RK++ ^ \
( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
X3 = *RK++ ^ \
( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^
( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
}
PUT_ULONG_LE( X0, output, 0 );
PUT_ULONG_LE( X1, output, 4 );
PUT_ULONG_LE( X2, output, 8 );
PUT_ULONG_LE( X3, output, 12 );
return( 0 );
}
/*
* AES-CBC buffer encryption/decryption
*/
int aes_crypt_cbc( aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int i;
unsigned char temp[16];
if( length % 16 )
return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
if( mode == AES_DECRYPT )
{
while( length > 0 )
{
memcpy( temp, input, 16 );
aes_crypt_ecb( ctx, mode, input, output );
for( i = 0; i < 16; i++ )
output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy( iv, temp, 16 );
input += 16;
output += 16;
length -= 16;
}
}
else
{
while( length > 0 )
{
for( i = 0; i < 16; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
aes_crypt_ecb( ctx, mode, output, output );
memcpy( iv, output, 16 );
input += 16;
output += 16;
length -= 16;
}
}
return( 0 );
}
/*
* AES-CTR buffer encryption/decryption
*/
int aes_crypt_ctr( aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
int c, i, cb;
size_t n = *nc_off;
while( length-- )
{
if( n == 0 ) {
aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
i = 15;
do {
nonce_counter[i]++;
cb = nonce_counter[i] == 0;
} while( i-- && cb );
}
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
n = (n + 1) & 0x0F;
}
*nc_off = n;
return( 0 );
}

144
aes.h Normal file
View file

@ -0,0 +1,144 @@
/**
* \file aes.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_AES_H
#define POLARSSL_AES_H
#include <string.h>
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/**
* \brief AES context structure
*/
typedef struct
{
int nr; /*!< number of rounds */
unsigned long *rk; /*!< AES round keys */
unsigned long buf[68]; /*!< unaligned data */
}
aes_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keysize must be 128, 192 or 256
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keysize must be 128, 192 or 256
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/
int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int aes_crypt_ecb( aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
*/
int aes_crypt_cbc( aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/*
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int aes_crypt_ctr( aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

55
aes_omac.cpp Normal file
View file

@ -0,0 +1,55 @@
#include "types.h"
#include "aes.h"
void _gf_mul(unsigned char *pad)
{
unsigned int i;
unsigned cxor = (pad[0] & 0x80) ? 0x87 : 0;
for(i = 0; i < 15; i++)
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
pad[15] = (pad[15] << 1) ^ cxor;
}
void aes_omac1(u8 *digest, u8 *input, u32 length, u8 *key, u32 keybits)
{
u32 i, j;
u32 overflow;
aes_context ctxt;
unsigned char buffer1[16], buffer2[16], dbuf[16];
memset(buffer1, 0, 16);
aes_setkey_enc(&ctxt, key, keybits);
aes_crypt_ecb(&ctxt, AES_ENCRYPT, buffer1, buffer2);
_gf_mul(buffer2);
if(length > 16)
{
for(i = 0; i < length - 16; i += 16)
{
for(j = 0; j < 16; j++)
dbuf[j] = buffer1[j] ^ input[i + j];
aes_crypt_ecb(&ctxt, AES_ENCRYPT, dbuf, buffer1);
}
}
overflow = length & 0xf;
if(length % 16 == 0)
overflow = 16;
memset(dbuf, 0, 16);
memcpy(dbuf, &(input[i]), overflow);
if(overflow != 16)
{
dbuf[overflow] = 0x80;
_gf_mul(buffer2);
}
for(i = 0; i < 16; i++)
dbuf[i] ^= buffer1[i] ^ buffer2[i];
aes_crypt_ecb(&ctxt, AES_ENCRYPT, dbuf, digest);
}

10
aes_omac.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef _AES_OMAC_H_
#define _AES_OMAC_H_
#include "types.h"
#define AES_OMAC1_DIGEST_SIZE 0x10
void aes_omac1(u8 *digest, u8 *input, u32 length, u8 *key, u32 keybits);
#endif

200
bn.cpp Normal file
View file

@ -0,0 +1,200 @@
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include <string.h>
#include <stdio.h>
#include "types.h"
void bn_print(char *name, u8 *a, u32 n)
{
u32 i;
printf("%s = ", name);
for (i = 0; i < n; i++)
printf("%02x", a[i]);
printf("\n");
}
static void bn_zero(u8 *d, u32 n)
{
memset(d, 0, n);
}
void bn_copy(u8 *d, u8 *a, u32 n)
{
memcpy(d, a, n);
}
int bn_compare(u8 *a, u8 *b, u32 n)
{
u32 i;
for (i = 0; i < n; i++) {
if (a[i] < b[i])
return -1;
if (a[i] > b[i])
return 1;
}
return 0;
}
static u8 bn_add_1(u8 *d, u8 *a, u8 *b, u32 n)
{
u32 i;
u32 dig;
u8 c;
c = 0;
for (i = n - 1; i < n; i--) {
dig = a[i] + b[i] + c;
c = dig >> 8;
d[i] = dig;
}
return c;
}
static u8 bn_sub_1(u8 *d, u8 *a, u8 *b, u32 n)
{
u32 i;
u32 dig;
u8 c;
c = 1;
for (i = n - 1; i < n; i--) {
dig = a[i] + 255 - b[i] + c;
c = dig >> 8;
d[i] = dig;
}
return 1 - c;
}
void bn_reduce(u8 *d, u8 *N, u32 n)
{
if (bn_compare(d, N, n) >= 0)
bn_sub_1(d, d, N, n);
}
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
{
if (bn_add_1(d, a, b, n))
bn_sub_1(d, d, N, n);
bn_reduce(d, N, n);
}
void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
{
if (bn_sub_1(d, a, b, n))
bn_add_1(d, d, N, n);
}
static const u8 inv256[0x80] = {
0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef,
0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf,
0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf,
0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf,
0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf,
0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f,
0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f,
0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f,
0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f,
0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f,
0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f,
0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f,
0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f,
0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f,
0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f,
0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff,
};
static void bn_mon_muladd_dig(u8 *d, u8 *a, u8 b, u8 *N, u32 n)
{
u32 dig;
u32 i;
u8 z = -(d[n-1] + a[n-1]*b) * inv256[N[n-1]/2];
dig = d[n-1] + a[n-1]*b + N[n-1]*z;
dig >>= 8;
for (i = n - 2; i < n; i--) {
dig += d[i] + a[i]*b + N[i]*z;
d[i+1] = dig;
dig >>= 8;
}
d[0] = dig;
dig >>= 8;
if (dig)
bn_sub_1(d, d, N, n);
bn_reduce(d, N, n);
}
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
{
u8 t[512];
u32 i;
bn_zero(t, n);
for (i = n - 1; i < n; i--)
bn_mon_muladd_dig(t, a, b[i], N, n);
bn_copy(d, t, n);
}
void bn_to_mon(u8 *d, u8 *N, u32 n)
{
u32 i;
for (i = 0; i < 8*n; i++)
bn_add(d, d, d, N, n);
}
void bn_from_mon(u8 *d, u8 *N, u32 n)
{
u8 t[512];
bn_zero(t, n);
t[n-1] = 1;
bn_mon_mul(d, d, t, N, n);
}
static void bn_mon_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en)
{
u8 t[512];
u32 i;
u8 mask;
bn_zero(d, n);
d[n-1] = 1;
bn_to_mon(d, N, n);
for (i = 0; i < en; i++)
for (mask = 0x80; mask != 0; mask >>= 1) {
bn_mon_mul(t, d, d, N, n);
if ((e[i] & mask) != 0)
bn_mon_mul(d, t, a, N, n);
else
bn_copy(d, t, n);
}
}
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n)
{
u8 t[512], s[512];
bn_zero(s, n);
s[n-1] = 2;
bn_sub_1(t, N, s, n);
bn_mon_exp(d, a, N, n, t, n);
}

76
config.h Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
/*! scetool base version. */
#define SCETOOL_VERSION_BASE "0.2.9"
/*! Private build. */
//#define CONFIG_PRIVATE_BUILD
#define BUILD_FOR "naehrwert"
//#define BUILD_FOR "unicorns"
/*! scetool version. */
#ifdef CONFIG_PRIVATE_BUILD
#ifdef BUILD_FOR
#define SCETOOL_VERSION SCETOOL_VERSION_BASE " <PRIVATE BUILD:" BUILD_FOR ">"
#else
#error Specify a name in BUILD_FOR.
#endif
#else
#define SCETOOL_VERSION SCETOOL_VERSION_BASE " <public build>"
#endif
/*! Private build options. */
#ifdef CONFIG_PRIVATE_BUILD
#define CONFIG_CUSTOM_INDIV_SEED
#define CONFIG_DUMP_INDIV_SEED
#endif
#if 0
/*! scetool API. */
#define CONFIG_EXPORTS
#ifdef CONFIG_EXPORTS
#define SCETOOL_API __declspec(dllexport)
#else
#define SCETOOL_API __declspec(dllimport)
#endif
#endif
/*! NPDRM watermark text (16 bytes exactly). */
//"I like kittens !"
#define CONFIG_NPDRM_WATERMARK "watermarktrololo"
/*! Environment variables. */
#define CONFIG_ENV_PS3 "PS3"
/*! Path configurations. */
#define CONFIG_KEYS_FILE "keys"
#define CONFIG_KEYS_PATH "./data"
#define CONFIG_CURVES_FILE "ldr_curves"
#define CONFIG_CURVES_PATH "./data"
#define CONFIG_VSH_CURVES_FILE "vsh_curves"
#define CONFIG_VSH_CURVES_PATH "./data"
#define CONFIG_IDPS_FILE "idps"
#define CONFIG_IDPS_PATH "./data"
#define CONFIG_ACT_DAT_FILE "act.dat"
#define CONFIG_ACT_DAT_PATH "./data"
#define CONFIG_RIF_FILE_EXT ".rif"
#define CONFIG_RIF_PATH "./rifs"
#define CONFIG_RAP_FILE_EXT ".rap"
#define CONFIG_RAP_PATH "./raps"
/*! Key names. */
#define CONFIG_NP_TID_KNAME "NP_tid"
#define CONFIG_NP_CI_KNAME "NP_ci"
#define CONFIG_NP_KLIC_FREE_KNAME "NP_klic_free"
#define CONFIG_NP_KLIC_KEY_KNAME "NP_klic_key"
#define CONFIG_NP_IDPS_CONST_KNAME "NP_idps_const"
#define CONFIG_NP_RIF_KEY_KNAME "NP_rif_key"
#define CONFIG_NP_SIG_KNAME "NP_sig"
#endif

357
ec.cpp Normal file
View file

@ -0,0 +1,357 @@
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include <string.h>
#include <stdio.h>
#include "types.h"
#include "util.h"
void bn_copy(u8 *d, u8 *a, u32 n);
int bn_compare(u8 *a, u8 *b, u32 n);
void bn_reduce(u8 *d, u8 *N, u32 n);
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
void bn_to_mon(u8 *d, u8 *N, u32 n);
void bn_from_mon(u8 *d, u8 *N, u32 n);
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n);
int ecdsa_get_params(u32 type, u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy);
struct point {
u8 x[20];
u8 y[20];
};
static u8 ec_p[20];
static u8 ec_a[20]; // mon
static u8 ec_b[20]; // mon
static u8 ec_N[21];
static struct point ec_G; // mon
static struct point ec_Q; // mon
static u8 ec_k[21];
static void elt_copy(u8 *d, u8 *a)
{
memcpy(d, a, 20);
}
static void elt_zero(u8 *d)
{
memset(d, 0, 20);
}
static int elt_is_zero(u8 *d)
{
u32 i;
for (i = 0; i < 20; i++)
if (d[i] != 0)
return 0;
return 1;
}
static void elt_add(u8 *d, u8 *a, u8 *b)
{
bn_add(d, a, b, ec_p, 20);
}
static void elt_sub(u8 *d, u8 *a, u8 *b)
{
bn_sub(d, a, b, ec_p, 20);
}
static void elt_mul(u8 *d, u8 *a, u8 *b)
{
bn_mon_mul(d, a, b, ec_p, 20);
}
static void elt_square(u8 *d, u8 *a)
{
elt_mul(d, a, a);
}
static void elt_inv(u8 *d, u8 *a)
{
u8 s[20];
elt_copy(s, a);
bn_mon_inv(d, s, ec_p, 20);
}
static void point_to_mon(struct point *p)
{
bn_to_mon(p->x, ec_p, 20);
bn_to_mon(p->y, ec_p, 20);
}
static void point_from_mon(struct point *p)
{
bn_from_mon(p->x, ec_p, 20);
bn_from_mon(p->y, ec_p, 20);
}
#if 0
static int point_is_on_curve(u8 *p)
{
u8 s[20], t[20];
u8 *x, *y;
x = p;
y = p + 20;
elt_square(t, x);
elt_mul(s, t, x);
elt_mul(t, x, ec_a);
elt_add(s, s, t);
elt_add(s, s, ec_b);
elt_square(t, y);
elt_sub(s, s, t);
return elt_is_zero(s);
}
#endif
static void point_zero(struct point *p)
{
elt_zero(p->x);
elt_zero(p->y);
}
static int point_is_zero(struct point *p)
{
return elt_is_zero(p->x) && elt_is_zero(p->y);
}
static void point_double(struct point *r, struct point *p)
{
u8 s[20], t[20];
struct point pp;
u8 *px, *py, *rx, *ry;
pp = *p;
px = pp.x;
py = pp.y;
rx = r->x;
ry = r->y;
if (elt_is_zero(py)) {
point_zero(r);
return;
}
elt_square(t, px); // t = px*px
elt_add(s, t, t); // s = 2*px*px
elt_add(s, s, t); // s = 3*px*px
elt_add(s, s, ec_a); // s = 3*px*px + a
elt_add(t, py, py); // t = 2*py
elt_inv(t, t); // t = 1/(2*py)
elt_mul(s, s, t); // s = (3*px*px+a)/(2*py)
elt_square(rx, s); // rx = s*s
elt_add(t, px, px); // t = 2*px
elt_sub(rx, rx, t); // rx = s*s - 2*px
elt_sub(t, px, rx); // t = -(rx-px)
elt_mul(ry, s, t); // ry = -s*(rx-px)
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
}
static void point_add(struct point *r, struct point *p, struct point *q)
{
u8 s[20], t[20], u[20];
u8 *px, *py, *qx, *qy, *rx, *ry;
struct point pp, qq;
pp = *p;
qq = *q;
px = pp.x;
py = pp.y;
qx = qq.x;
qy = qq.y;
rx = r->x;
ry = r->y;
if (point_is_zero(&pp)) {
elt_copy(rx, qx);
elt_copy(ry, qy);
return;
}
if (point_is_zero(&qq)) {
elt_copy(rx, px);
elt_copy(ry, py);
return;
}
elt_sub(u, qx, px);
if (elt_is_zero(u)) {
elt_sub(u, qy, py);
if (elt_is_zero(u))
point_double(r, &pp);
else
point_zero(r);
return;
}
elt_inv(t, u); // t = 1/(qx-px)
elt_sub(u, qy, py); // u = qy-py
elt_mul(s, t, u); // s = (qy-py)/(qx-px)
elt_square(rx, s); // rx = s*s
elt_add(t, px, qx); // t = px+qx
elt_sub(rx, rx, t); // rx = s*s - (px+qx)
elt_sub(t, px, rx); // t = -(rx-px)
elt_mul(ry, s, t); // ry = -s*(rx-px)
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
}
static void point_mul(struct point *d, u8 *a, struct point *b) // a is bignum
{
u32 i;
u8 mask;
point_zero(d);
for (i = 0; i < 21; i++)
for (mask = 0x80; mask != 0; mask >>= 1) {
point_double(d, d);
if ((a[i] & mask) != 0)
point_add(d, d, b);
}
}
static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash)
{
u8 e[21];
u8 kk[21];
u8 m[21];
u8 minv[21];
struct point mG;
e[0] = 0;
memcpy(e + 1, hash, 20);
bn_reduce(e, ec_N, 21);
try_again:
_fill_rand_bytes(m, 21);
m[0] = 0;
if (bn_compare(m, ec_N, 21) >= 0)
goto try_again;
// R = (mG).x
point_mul(&mG, m, &ec_G);
point_from_mon(&mG);
R[0] = 0;
elt_copy(R+1, mG.x);
// S = m**-1*(e + Rk) (mod N)
bn_copy(kk, k, 21);
bn_reduce(kk, ec_N, 21);
bn_to_mon(m, ec_N, 21);
bn_to_mon(e, ec_N, 21);
bn_to_mon(R, ec_N, 21);
bn_to_mon(kk, ec_N, 21);
bn_mon_mul(S, R, kk, ec_N, 21);
bn_add(kk, S, e, ec_N, 21);
bn_mon_inv(minv, m, ec_N, 21);
bn_mon_mul(S, minv, kk, ec_N, 21);
bn_from_mon(R, ec_N, 21);
bn_from_mon(S, ec_N, 21);
}
static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash)
{
u8 Sinv[21];
u8 e[21];
u8 w1[21], w2[21];
struct point r1, r2;
u8 rr[21];
e[0] = 0;
memcpy(e + 1, hash, 20);
bn_reduce(e, ec_N, 21);
bn_to_mon(R, ec_N, 21);
bn_to_mon(S, ec_N, 21);
bn_to_mon(e, ec_N, 21);
bn_mon_inv(Sinv, S, ec_N, 21);
bn_mon_mul(w1, e, Sinv, ec_N, 21);
bn_mon_mul(w2, R, Sinv, ec_N, 21);
bn_from_mon(w1, ec_N, 21);
bn_from_mon(w2, ec_N, 21);
point_mul(&r1, w1, &ec_G);
point_mul(&r2, w2, Q);
point_add(&r1, &r1, &r2);
point_from_mon(&r1);
rr[0] = 0;
memcpy(rr + 1, r1.x, 20);
bn_reduce(rr, ec_N, 21);
bn_from_mon(R, ec_N, 21);
bn_from_mon(S, ec_N, 21);
return (bn_compare(rr, R, 21) == 0);
}
#if 0
static void ec_priv_to_pub(u8 *k, u8 *Q)
{
point_mul(Q, k, ec_G);
}
#endif
int ecdsa_set_curve(u32 type)
{
if (ecdsa_get_params(type, ec_p, ec_a, ec_b, ec_N, ec_G.x, ec_G.y) < 0)
return -1;
bn_to_mon(ec_a, ec_p, 20);
bn_to_mon(ec_b, ec_p, 20);
point_to_mon(&ec_G);
return 0;
}
void ecdsa_set_pub(u8 *Q)
{
memcpy(ec_Q.x, Q, 20);
memcpy(ec_Q.y, Q+20, 20);
point_to_mon(&ec_Q);
}
void ecdsa_set_priv(u8 *k)
{
memcpy(ec_k, k, sizeof ec_k);
}
int ecdsa_verify(u8 *hash, u8 *R, u8 *S)
{
return check_ecdsa(&ec_Q, R, S, hash);
}
void ecdsa_sign(u8 *hash, u8 *R, u8 *S)
{
generate_ecdsa(R, S, ec_k, hash);
}

31
ecdsa.cpp Normal file
View file

@ -0,0 +1,31 @@
#include "types.h"
#include "keys.h"
#include "ecdsa.h"
#include "util.h"
int ecdsa_get_params(u32 type, u8 *p, u8 *a, u8 *b, u8 *N, u8 *Gx, u8 *Gy)
{
curve_t *c;
if(type & USE_VSH_CURVE)
{
//VSH curve.
if((c = vsh_curve_find(type & ~USE_VSH_CURVE)) == NULL)
return -1;
}
else
{
//Loader curve.
if((c = curve_find(type)) == NULL)
return -1;
}
_memcpy_inv(p, c->p, 20);
_memcpy_inv(a, c->a, 20);
_memcpy_inv(b, c->b, 20);
_memcpy_inv(N, c->N, 21);
_memcpy_inv(Gx, c->Gx, 20);
_memcpy_inv(Gy, c->Gy, 20);
return 0;
}

10
ecdsa.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef _ECDSA_H_
#define _ECDSA_H_
int ecdsa_set_curve(u32 type);
void ecdsa_set_pub(u8 *Q);
void ecdsa_set_priv(u8 *k);
int ecdsa_verify(u8 *hash, u8 *R, u8 *S);
void ecdsa_sign(u8 *hash, u8 *R, u8 *S);
#endif

2423
elf.h Normal file

File diff suppressed because it is too large Load diff

136
elf_inlines.h Normal file
View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _ELF_INLINES_H_
#define _ELF_INLINES_H_
#include <string.h>
#include "types.h"
#include "elf.h"
static inline void _es_elf32_ehdr(Elf32_Ehdr *h)
{
h->e_type = _ES16(h->e_type);
h->e_machine = _ES16(h->e_machine);
h->e_version = _ES32(h->e_version);
h->e_entry = _ES32(h->e_entry);
h->e_phoff = _ES32(h->e_phoff);
h->e_shoff = _ES32(h->e_shoff);
h->e_flags = _ES32(h->e_flags);
h->e_ehsize = _ES16(h->e_ehsize);
h->e_phentsize = _ES16(h->e_phentsize);
h->e_phnum = _ES16(h->e_phnum);
h->e_shentsize = _ES16(h->e_shentsize);
h->e_shnum = _ES16(h->e_shnum);
h->e_shstrndx = _ES16(h->e_shstrndx);
}
static inline void _copy_es_elf32_ehdr(Elf32_Ehdr *dst, Elf32_Ehdr *src)
{
memcpy(dst, src, sizeof(Elf32_Ehdr));
_es_elf32_ehdr(dst);
}
static inline void _es_elf64_ehdr(Elf64_Ehdr *h)
{
h->e_type = _ES16(h->e_type);
h->e_machine = _ES16(h->e_machine);
h->e_version = _ES32(h->e_version);
h->e_entry = _ES64(h->e_entry);
h->e_phoff = _ES64(h->e_phoff);
h->e_shoff = _ES64(h->e_shoff);
h->e_flags = _ES32(h->e_flags);
h->e_ehsize = _ES16(h->e_ehsize);
h->e_phentsize = _ES16(h->e_phentsize);
h->e_phnum = _ES16(h->e_phnum);
h->e_shentsize = _ES16(h->e_shentsize);
h->e_shnum = _ES16(h->e_shnum);
h->e_shstrndx = _ES16(h->e_shstrndx);
}
static inline void _copy_es_elf64_ehdr(Elf64_Ehdr *dst, Elf64_Ehdr *src)
{
memcpy(dst, src, sizeof(Elf64_Ehdr));
_es_elf64_ehdr(dst);
}
static inline void _es_elf32_shdr(Elf32_Shdr *h)
{
h->sh_name = _ES32(h->sh_name);
h->sh_type = _ES32(h->sh_type);
h->sh_flags = _ES32(h->sh_flags);
h->sh_addr = _ES32(h->sh_addr);
h->sh_offset = _ES32(h->sh_offset);
h->sh_size = _ES32(h->sh_size);
h->sh_link = _ES32(h->sh_link);
h->sh_info = _ES32(h->sh_info);
h->sh_addralign = _ES32(h->sh_addralign);
h->sh_entsize = _ES32(h->sh_entsize);
}
static inline void _copy_es_elf32_shdr(Elf32_Shdr *dst, Elf32_Shdr *src)
{
memcpy(dst, src, sizeof(Elf32_Shdr));
_es_elf32_shdr(dst);
}
static inline void _es_elf64_shdr(Elf64_Shdr *h)
{
h->sh_name = _ES32(h->sh_name);
h->sh_type = _ES32(h->sh_type);
h->sh_flags = _ES64(h->sh_flags);
h->sh_addr = _ES64(h->sh_addr);
h->sh_offset = _ES64(h->sh_offset);
h->sh_size = _ES64(h->sh_size);
h->sh_link = _ES32(h->sh_link);
h->sh_info = _ES32(h->sh_info);
h->sh_addralign = _ES64(h->sh_addralign);
h->sh_entsize = _ES64(h->sh_entsize);
}
static inline void _copy_es_elf64_shdr(Elf64_Shdr *dst, Elf64_Shdr *src)
{
memcpy(dst, src, sizeof(Elf64_Shdr));
_es_elf64_shdr(dst);
}
static inline void _es_elf32_phdr(Elf32_Phdr *h)
{
h->p_type = _ES32(h->p_type);
h->p_offset = _ES32(h->p_offset);
h->p_vaddr = _ES32(h->p_vaddr);
h->p_paddr = _ES32(h->p_paddr);
h->p_filesz = _ES32(h->p_filesz);
h->p_memsz = _ES32(h->p_memsz);
h->p_flags = _ES32(h->p_flags);
h->p_align = _ES32(h->p_align);
}
static inline void _copy_es_elf32_phdr(Elf32_Phdr *dst, Elf32_Phdr *src)
{
memcpy(dst, src, sizeof(Elf32_Phdr));
_es_elf32_phdr(dst);
}
static inline void _es_elf64_phdr(Elf64_Phdr *h)
{
h->p_type = _ES32(h->p_type);
h->p_flags = _ES32(h->p_flags);
h->p_offset = _ES64(h->p_offset);
h->p_vaddr = _ES64(h->p_vaddr);
h->p_paddr = _ES64(h->p_paddr);
h->p_filesz = _ES64(h->p_filesz);
h->p_memsz = _ES64(h->p_memsz);
h->p_align = _ES64(h->p_align);
}
static inline void _copy_es_elf64_phdr(Elf64_Phdr *dst, Elf64_Phdr *src)
{
memcpy(dst, src, sizeof(Elf64_Phdr));
_es_elf64_phdr(dst);
}
#endif

560
frontend.cpp Normal file
View file

@ -0,0 +1,560 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "config.h"
#include "aes.h"
#include "util.h"
#include "keys.h"
#include "sce.h"
#include "sce_inlines.h"
#include "self.h"
#include "np.h"
#include "rvk.h"
#include "spp.h"
#include "util.h"
#include "tables.h"
/*! Parameters. */
extern s8 *_template;
extern s8 *_file_type;
extern s8 *_compress_data;
extern s8 *_skip_sections;
extern s8 *_key_rev;
extern s8 *_meta_info;
extern s8 *_keyset;
extern s8 *_auth_id;
extern s8 *_vendor_id;
extern s8 *_self_type;
extern s8 *_app_version;
extern s8 *_fw_version;
extern s8 *_add_shdrs;
extern s8 *_ctrl_flags;
extern s8 *_cap_flags;
#ifdef CONFIG_CUSTOM_INDIV_SEED
extern s8 *_indiv_seed;
#endif
extern s8 *_license_type;
extern s8 *_app_type;
extern s8 *_content_id;
extern s8 *_real_fname;
extern s8 *_add_sig;
static BOOL _is_hexdigit(s8 c)
{
if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
return TRUE;
return FALSE;
}
static BOOL _is_hexnumber(const s8 *str)
{
u32 i, len = strlen(str);
for(i = 0; i < len; i++)
if(_is_hexdigit(str[i]) == FALSE)
return FALSE;
return TRUE;
}
static BOOL _fill_self_config_template(s8 *file, self_config_t *sconf)
{
u8 *buf = _read_buffer(file, NULL);
if(buf != NULL)
{
sce_buffer_ctxt_t *ctxt = sce_create_ctxt_from_buffer(buf);
if(ctxt != NULL)
{
if(sce_decrypt_header(ctxt, NULL, NULL))
{
_LOG_VERBOSE("Template header decrypted.\n");
_LOG_VERBOSE("Using:\n");
sconf->key_revision = ctxt->sceh->key_revision;
_IF_VERBOSE(printf(" Key Revision 0x%04X\n", sconf->key_revision));
sconf->auth_id = ctxt->self.ai->auth_id;
_IF_VERBOSE(printf(" Auth-ID 0x%016llX\n", sconf->auth_id));
sconf->vendor_id = ctxt->self.ai->vendor_id;
_IF_VERBOSE(printf(" Vendor-ID 0x%08X\n", sconf->vendor_id));
sconf->self_type = ctxt->self.ai->self_type;
_IF_VERBOSE(printf(" SELF-Type 0x%08X\n", sconf->self_type));
sconf->app_version = ctxt->self.ai->version;
_IF_VERBOSE(printf(" APP Version 0x%016llX\n", sconf->app_version));
control_info_t *ci = sce_get_ctrl_info(ctxt, CONTROL_INFO_TYPE_DIGEST);
ci_data_digest_40_t *cid = (ci_data_digest_40_t *)((u8 *)ci + sizeof(control_info_t));
_es_ci_data_digest_40(cid);
sconf->fw_version = cid->fw_version;
_IF_VERBOSE(printf(" FW Version 0x%016llX\n", sconf->fw_version));
ci = sce_get_ctrl_info(ctxt, CONTROL_INFO_TYPE_FLAGS);
sconf->ctrl_flags = (u8 *)_memdup(((u8 *)ci) + sizeof(control_info_t), 0x20);
_IF_VERBOSE(_hexdump(stdout, " Control Flags ", 0, sconf->ctrl_flags, 0x20, 0));
opt_header_t *oh = sce_get_opt_header(ctxt, OPT_HEADER_TYPE_CAP_FLAGS);
sconf->cap_flags = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), 0x20);
_IF_VERBOSE(_hexdump(stdout, " Capability Flags", 0, sconf->cap_flags, 0x20, 0));
#ifdef CONFIG_CUSTOM_INDIV_SEED
sconf->indiv_seed = NULL;
if(ctxt->self.ai->self_type == SELF_TYPE_ISO)
{
oh = sce_get_opt_header(ctxt, OPT_HEADER_TYPE_INDIV_SEED);
sconf->indiv_seed = (u8 *)_memdup(((u8 *)oh) + sizeof(opt_header_t), oh->size - sizeof(opt_header_t));
sconf->indiv_seed_size = oh->size - sizeof(opt_header_t);
_IF_VERBOSE(_hexdump(stdout, " Individuals Seed", 0, sconf->indiv_seed, sconf->indiv_seed_size, 0));
}
#endif
sconf->add_shdrs = TRUE;
if(_add_shdrs != NULL)
if(strcmp(_add_shdrs, "FALSE") == 0)
sconf->add_shdrs = FALSE;
sconf->skip_sections = TRUE;
if(_skip_sections != NULL)
if(strcmp(_skip_sections, "FALSE") == 0)
sconf->skip_sections = FALSE;
sconf->npdrm_config = NULL;
return TRUE;
}
else
printf("[*] Warning: Could not decrypt template header.\n");
free(ctxt);
}
else
printf("[*] Error: Could not process template %s\n", file);
free(buf);
}
else
printf("[*] Error: Could not load template %s\n", file);
return FALSE;
}
static BOOL _fill_self_config(self_config_t *sconf)
{
if(_key_rev == NULL)
{
printf("[*] Error: Please specify a key revision.\n");
return FALSE;
}
if(_is_hexnumber(_key_rev) == FALSE)
{
printf("[*] Error (Key Revision): Please provide a valid hexadecimal number.\n");
return FALSE;
}
sconf->key_revision = _x_to_u64(_key_rev);
if(_auth_id == NULL)
{
printf("[*] Error: Please specify an auth ID.\n");
return FALSE;
}
sconf->auth_id = _x_to_u64(_auth_id);
if(_vendor_id == NULL)
{
printf("[*] Error: Please specify a vendor ID.\n");
return FALSE;
}
sconf->vendor_id = _x_to_u64(_vendor_id);
if(_self_type == NULL)
{
printf("[*] Error: Please specify a SELF type.\n");
return FALSE;
}
u64 type = _get_id(_self_types_params, _self_type);
if(type == (u64)(-1))
{
printf("[*] Error: Invalid SELF type.\n");
return FALSE;
}
sconf->self_type = type;
if(_app_version == NULL)
{
printf("[*] Error: Please specify an application version.\n");
return FALSE;
}
sconf->app_version = _x_to_u64(_app_version);
sconf->fw_version = 0;
if(_fw_version != NULL)
sconf->fw_version = _x_to_u64(_fw_version);
sconf->add_shdrs = TRUE;
if(_add_shdrs != NULL)
if(strcmp(_add_shdrs, "FALSE") == 0)
sconf->add_shdrs = FALSE;
sconf->skip_sections = TRUE;
if(_skip_sections != NULL)
if(strcmp(_skip_sections, "FALSE") == 0)
sconf->skip_sections = FALSE;
sconf->ctrl_flags = NULL;
if(_ctrl_flags != NULL)
{
if(strlen(_ctrl_flags) != 0x20*2)
{
printf("[*] Error: Control flags need to be 32 bytes.\n");
return FALSE;
}
sconf->ctrl_flags = _x_to_u8_buffer(_ctrl_flags);
}
sconf->cap_flags = NULL;
if(_cap_flags != NULL)
{
if(strlen(_cap_flags) != 0x20*2)
{
printf("[*] Error: Capability flags need to be 32 bytes.\n");
return FALSE;
}
sconf->cap_flags = _x_to_u8_buffer(_cap_flags);
}
#ifdef CONFIG_CUSTOM_INDIV_SEED
sconf->indiv_seed = NULL;
if(_indiv_seed != NULL)
{
u32 len = strlen(_indiv_seed);
if(len > 0x100*2)
{
printf("[*] Error: Individuals seed must be <= 0x100 bytes.\n");
return FALSE;
}
sconf->indiv_seed = _x_to_u8_buffer(_indiv_seed);
sconf->indiv_seed_size = len / 2;
}
#endif
sconf->npdrm_config = NULL;
return TRUE;
}
static BOOL _fill_npdrm_config(self_config_t *sconf)
{
if((sconf->npdrm_config = (npdrm_config_t *)malloc(sizeof(npdrm_config_t))) == NULL)
return FALSE;
if(_license_type == NULL)
{
printf("[*] Error: Please specify a license type.\n");
return FALSE;
}
//TODO!
if(strcmp(_license_type, "FREE") == 0)
sconf->npdrm_config->license_type = NP_LICENSE_FREE;
else if(strcmp(_license_type, "LOCAL") == 0)
sconf->npdrm_config->license_type = NP_LICENSE_LOCAL;
else
{
printf("[*] Error: Only supporting LOCAL and FREE license for now.\n");
return FALSE;
}
if(_app_type == NULL)
{
printf("[*] Error: Please specify an application type.\n");
return FALSE;
}
u64 type = _get_id(_np_app_types, _app_type);
if(type == (u64)(-1))
{
printf("[*] Error: Invalid application type.\n");
return FALSE;
}
sconf->npdrm_config->app_type = type;
if(_content_id == NULL)
{
printf("[*] Error: Please specify a content ID.\n");
return FALSE;
}
strncpy((s8 *)sconf->npdrm_config->content_id, _content_id, 0x30);
if(_real_fname == NULL)
{
printf("[*] Error: Please specify a real filename.\n");
return FALSE;
}
sconf->npdrm_config->real_fname = _real_fname;
return TRUE;
}
void frontend_print_infos(s8 *file)
{
u8 *buf = _read_buffer(file, NULL);
if(buf != NULL)
{
sce_buffer_ctxt_t *ctxt = sce_create_ctxt_from_buffer(buf);
if(ctxt != NULL)
{
u8 *meta_info = NULL;
if(_meta_info != NULL)
{
if(strlen(_meta_info) != 0x40*2)
{
printf("[*] Error: Metadata info needs to be 64 bytes.\n");
return;
}
meta_info = _x_to_u8_buffer(_meta_info);
}
u8 *keyset = NULL;
if(_keyset != NULL)
{
if(strlen(_keyset) != (0x20 + 0x10 + 0x15 + 0x28 + 0x01)*2)
{
printf("[*] Error: Keyset has a wrong length.\n");
return;
}
keyset = _x_to_u8_buffer(_keyset);
}
if(sce_decrypt_header(ctxt, meta_info, keyset))
{
_LOG_VERBOSE("Header decrypted.\n");
if(sce_decrypt_data(ctxt))
_LOG_VERBOSE("Data decrypted.\n");
else
printf("[*] Warning: Could not decrypt data.\n");
}
else
printf("[*] Warning: Could not decrypt header.\n");
sce_print_info(stdout, ctxt);
if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF)
self_print_info(stdout, ctxt);
else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_RVK && ctxt->mdec == TRUE)
rvk_print(stdout, ctxt);
else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SPP && ctxt->mdec == TRUE)
spp_print(stdout, ctxt);
free(ctxt);
}
else
printf("[*] Error: Could not process %s\n", file);
free(buf);
}
else
printf("[*] Error: Could not load %s\n", file);
}
void frontend_decrypt(s8 *file_in, s8 *file_out)
{
u8 *buf = _read_buffer(file_in, NULL);
if(buf != NULL)
{
sce_buffer_ctxt_t *ctxt = sce_create_ctxt_from_buffer(buf);
if(ctxt != NULL)
{
u8 *meta_info = NULL;
if(_meta_info != NULL)
{
if(strlen(_meta_info) != 0x40*2)
{
printf("[*] Error: Metadata info needs to be 64 bytes.\n");
return;
}
meta_info = _x_to_u8_buffer(_meta_info);
}
u8 *keyset = NULL;
if(_keyset != NULL)
{
if(strlen(_keyset) != (0x20 + 0x10 + 0x15 + 0x28 + 0x01)*2)
{
printf("[*] Error: Keyset has a wrong length.\n");
return;
}
keyset = _x_to_u8_buffer(_keyset);
}
if(sce_decrypt_header(ctxt, meta_info, keyset))
{
_LOG_VERBOSE("Header decrypted.\n");
if(sce_decrypt_data(ctxt))
{
_LOG_VERBOSE("Data decrypted.\n");
if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SELF)
{
if(self_write_to_elf(ctxt, file_out) == TRUE)
printf("[*] ELF written to %s.\n", file_out);
else
printf("[*] Error: Could not write ELF.\n");
}
else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_RVK)
{
if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset,
ctxt->metash[0].data_size + ctxt->metash[1].data_size))
printf("[*] RVK written to %s.\n", file_out);
else
printf("[*] Error: Could not write RVK.\n");
}
else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_PKG)
{
/*if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset,
ctxt->metash[0].data_size + ctxt->metash[1].data_size + ctxt->metash[2].data_size))
printf("[*] PKG written to %s.\n", file_out);
else
printf("[*] Error: Could not write PKG.\n");*/
printf("soon...\n");
}
else if(ctxt->sceh->header_type == SCE_HEADER_TYPE_SPP)
{
if(_write_buffer(file_out, ctxt->scebuffer + ctxt->metash[0].data_offset,
ctxt->metash[0].data_size + ctxt->metash[1].data_size))
printf("[*] SPP written to %s.\n", file_out);
else
printf("[*] Error: Could not write SPP.\n");
}
}
else
printf("[*] Error: Could not decrypt data.\n");
}
else
printf("[*] Error: Could not decrypt header.\n");
free(ctxt);
}
else
printf("[*] Error: Could not process %s\n", file_in);
free(buf);
}
else
printf("[*] Error: Could not load %s\n", file_in);
}
void frontend_encrypt(s8 *file_in, s8 *file_out)
{
BOOL can_compress = FALSE;
self_config_t sconf;
sce_buffer_ctxt_t *ctxt;
u32 file_len = 0;
u8 *file;
if(_file_type == NULL)
{
printf("[*] Error: Please specify a file type.\n");
return;
}
u8 *keyset = NULL;
if(_keyset != NULL)
{
if(strlen(_keyset) != (0x20 + 0x10 + 0x15 + 0x28 + 0x01)*2)
{
printf("[*] Error: Keyset has a wrong length.\n");
return;
}
keyset = _x_to_u8_buffer(_keyset);
}
if((file = _read_buffer(file_in, &file_len)) == NULL)
{
printf("[*] Error: Could not read %s.\n", file_in);
return;
}
if(strcmp(_file_type, "SELF") == 0)
{
if(_self_type == NULL && _template == NULL)
{
printf("[*] Error: Please specify a SELF type.\n");
return;
}
if(_template != NULL)
{
//Use a template SELF to fill the config.
if(_fill_self_config_template(_template, &sconf) == FALSE)
return;
}
else
{
//Fill the config from command line arguments.
if(_fill_self_config(&sconf) == FALSE)
return;
}
if(sconf.self_type == SELF_TYPE_NPDRM)
if(_fill_npdrm_config(&sconf) == FALSE)
return;
ctxt = sce_create_ctxt_build_self(file, file_len);
if(self_build_self(ctxt, &sconf) == TRUE)
printf("[*] SELF built.\n");
else
{
printf("[*] Error: SELF not built.\n");
return;
}
//SPU SELFs may not be compressed.
if(!(sconf.self_type == SELF_TYPE_LDR || sconf.self_type == SELF_TYPE_ISO))
can_compress = TRUE;
}
else if(strcmp(_file_type, "RVK") == 0)
{
printf("soon...\n");
return;
}
else if(strcmp(_file_type, "PKG") == 0)
{
printf("soon...\n");
return;
}
else if(strcmp(_file_type, "SPP") == 0)
{
printf("soon...\n");
return;
}
//Compress data if wanted.
if(_compress_data != NULL && strcmp(_compress_data, "TRUE") == 0)
{
if(can_compress == TRUE)
{
sce_compress_data(ctxt);
printf("[*] Data compressed.\n");
}
else
printf("[*] Warning: This type of file will not be compressed.\n");
}
//Layout and encrypt context.
sce_layout_ctxt(ctxt);
if(sce_encrypt_ctxt(ctxt, keyset) == TRUE)
printf("[*] Data encrypted.\n");
else
{
printf("[*] Error: Data not encrypted.\n");
return;
}
//Write file.
if(sce_write_ctxt(ctxt, file_out) == TRUE)
{
printf("[*] %s written.\n", file_out);
//Add NPDRM footer signature.
if(sconf.self_type == SELF_TYPE_NPDRM && _add_sig != NULL && strcmp(_add_sig, "TRUE") == 0)
{
if(np_sign_file(file_out) == TRUE)
printf("[*] Added NPDRM footer signature.\n");
else
printf("[*] Error: Could not add NPDRM footer signature.\n");
}
}
else
printf("[*] Error: %s not written.\n", file_out);
}

14
frontend.h Normal file
View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _FRONTEND_H_
#define _FRONTEND_H_
void frontend_print_infos(s8 *file);
void frontend_decrypt(s8 *file_in, s8 *file_out);
void frontend_encrypt(s8 *file_in, s8 *file_out);
#endif

530
getopt.c Normal file
View file

@ -0,0 +1,530 @@
#ifdef _WIN32
/* Getopt for Microsoft C
This code is a modification of the Free Software Foundation, Inc.
Getopt library for parsing command line argument the purpose was
to provide a Microsoft Visual C friendly derivative. This code
provides functionality for both Unicode and Multibyte builds.
Date: 02/03/2011 - Ludvik Jerabek - Initial Release
Version: 1.0
Comment: Supports getopt, getopt_long, and getopt_long_only
and POSIXLY_CORRECT environment flag
License: LGPL
Revisions:
02/03/2011 - Ludvik Jerabek - Initial Release
02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
**DISCLAIMER**
THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include "getopt.h"
enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
struct _getopt_data
{
int optind;
int opterr;
int optopt;
TCHAR *optarg;
int __initialized;
TCHAR *__nextchar;
int __ordering;
int __posixly_correct;
int __first_nonopt;
int __last_nonopt;
};
static struct _getopt_data getopt_data;
TCHAR *optarg;
int optind = 1;
int opterr = 1;
int optopt = _T('?');
static void exchange(TCHAR **argv, struct _getopt_data *d)
{
int bottom = d->__first_nonopt;
int middle = d->__last_nonopt;
int top = d->optind;
TCHAR *tem;
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
int len = middle - bottom;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
top -= len;
}
else
{
int len = top - middle;
register int i;
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
bottom += len;
}
}
d->__first_nonopt += (d->optind - d->__last_nonopt);
d->__last_nonopt = d->optind;
}
static const TCHAR *_getopt_initialize (const TCHAR *optstring, struct _getopt_data *d, int posixly_correct)
{
d->__first_nonopt = d->__last_nonopt = d->optind;
d->__nextchar = NULL;
d->__posixly_correct = posixly_correct | !!_tgetenv(_T("POSIXLY_CORRECT"));
if (optstring[0] == _T('-'))
{
d->__ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == _T('+'))
{
d->__ordering = REQUIRE_ORDER;
++optstring;
}
else if (d->__posixly_correct)
d->__ordering = REQUIRE_ORDER;
else
d->__ordering = PERMUTE;
return optstring;
}
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)
{
int print_errors = d->opterr;
if (argc < 1)
return -1;
d->optarg = NULL;
if (d->optind == 0 || !d->__initialized)
{
if (d->optind == 0)
d->optind = 1;
optstring = _getopt_initialize (optstring, d, posixly_correct);
d->__initialized = 1;
}
else if (optstring[0] == _T('-') || optstring[0] == _T('+'))
optstring++;
if (optstring[0] == _T(':'))
print_errors = 0;
if (d->__nextchar == NULL || *d->__nextchar == _T('\0'))
{
if (d->__last_nonopt > d->optind)
d->__last_nonopt = d->optind;
if (d->__first_nonopt > d->optind)
d->__first_nonopt = d->optind;
if (d->__ordering == PERMUTE)
{
if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
exchange ((TCHAR **) argv, d);
else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
while (d->optind < argc && (argv[d->optind][0] != _T('-') || argv[d->optind][1] == _T('\0')))
d->optind++;
d->__last_nonopt = d->optind;
}
if (d->optind != argc && !_tcscmp(argv[d->optind], _T("--")))
{
d->optind++;
if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
exchange ((TCHAR **) argv, d);
else if (d->__first_nonopt == d->__last_nonopt)
d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
d->optind = argc;
}
if (d->optind == argc)
{
if (d->__first_nonopt != d->__last_nonopt)
d->optind = d->__first_nonopt;
return -1;
}
if ((argv[d->optind][0] != _T('-') || argv[d->optind][1] == _T('\0')))
{
if (d->__ordering == REQUIRE_ORDER)
return -1;
d->optarg = argv[d->optind++];
return 1;
}
d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == _T('-')));
}
if (longopts != NULL && (argv[d->optind][1] == _T('-') || (long_only && (argv[d->optind][2] || !_tcschr(optstring, argv[d->optind][1])))))
{
TCHAR *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = -1;
int option_index;
for (nameend = d->__nextchar; *nameend && *nameend != _T('='); nameend++);
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!_tcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int)(nameend - d->__nextchar) == (unsigned int)_tcslen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
ambig = 1;
}
if (ambig && !exact)
{
if (print_errors)
{
_ftprintf(stderr, _T("%s: option '%s' is ambiguous\n"),
argv[0], argv[d->optind]);
}
d->__nextchar += _tcslen(d->__nextchar);
d->optind++;
d->optopt = 0;
return _T('?');
}
if (pfound != NULL)
{
option_index = indfound;
d->optind++;
if (*nameend)
{
if (pfound->has_arg)
d->optarg = nameend + 1;
else
{
if (print_errors)
{
if (argv[d->optind - 1][1] == _T('-'))
{
_ftprintf(stderr, _T("%s: option '--%s' doesn't allow an argument\n"),argv[0], pfound->name);
}
else
{
_ftprintf(stderr, _T("%s: option '%c%s' doesn't allow an argument\n"),argv[0], argv[d->optind - 1][0],pfound->name);
}
}
d->__nextchar += _tcslen(d->__nextchar);
d->optopt = pfound->val;
return _T('?');
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
_ftprintf(stderr,_T("%s: option '--%s' requires an argument\n"),argv[0], pfound->name);
}
d->__nextchar += _tcslen(d->__nextchar);
d->optopt = pfound->val;
return optstring[0] == _T(':') ? _T(':') : _T('?');
}
}
d->__nextchar += _tcslen(d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
if (!long_only || argv[d->optind][1] == _T('-') || _tcschr(optstring, *d->__nextchar) == NULL)
{
if (print_errors)
{
if (argv[d->optind][1] == _T('-'))
{
/* --option */
_ftprintf(stderr, _T("%s: unrecognized option '--%s'\n"),argv[0], d->__nextchar);
}
else
{
/* +option or -option */
_ftprintf(stderr, _T("%s: unrecognized option '%c%s'\n"),argv[0], argv[d->optind][0], d->__nextchar);
}
}
d->__nextchar = (TCHAR *)_T("");
d->optind++;
d->optopt = 0;
return _T('?');
}
}
{
TCHAR c = *d->__nextchar++;
TCHAR *temp = (TCHAR*)_tcschr(optstring, c);
if (*d->__nextchar == _T('\0'))
++d->optind;
if (temp == NULL || c == _T(':') || c == _T(';'))
{
if (print_errors)
{
_ftprintf(stderr, _T("%s: invalid option -- '%c'\n"), argv[0], c);
}
d->optopt = c;
return _T('?');
}
if (temp[0] == _T('W') && temp[1] == _T(';'))
{
TCHAR *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound = 0;
int option_index;
if (*d->__nextchar != _T('\0'))
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
_ftprintf(stderr,
_T("%s: option requires an argument -- '%c'\n"),
argv[0], c);
}
d->optopt = c;
if (optstring[0] == _T(':'))
c = _T(':');
else
c = _T('?');
return c;
}
else
d->optarg = argv[d->optind++];
for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != _T('='); nameend++);
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!_tcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
{
if ((unsigned int) (nameend - d->__nextchar) == _tcslen(p->name))
{
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
pfound = p;
indfound = option_index;
}
else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
ambig = 1;
}
if (ambig && !exact)
{
if (print_errors)
{
_ftprintf(stderr, _T("%s: option '-W %s' is ambiguous\n"),
argv[0], d->optarg);
}
d->__nextchar += _tcslen(d->__nextchar);
d->optind++;
return _T('?');
}
if (pfound != NULL)
{
option_index = indfound;
if (*nameend)
{
if (pfound->has_arg)
d->optarg = nameend + 1;
else
{
if (print_errors)
{
_ftprintf(stderr, _T("\
%s: option '-W %s' doesn't allow an argument\n"),
argv[0], pfound->name);
}
d->__nextchar += _tcslen(d->__nextchar);
return _T('?');
}
}
else if (pfound->has_arg == 1)
{
if (d->optind < argc)
d->optarg = argv[d->optind++];
else
{
if (print_errors)
{
_ftprintf(stderr, _T("\
%s: option '-W %s' requires an argument\n"),
argv[0], pfound->name);
}
d->__nextchar += _tcslen(d->__nextchar);
return optstring[0] == _T(':') ? _T(':') : _T('?');
}
}
else
d->optarg = NULL;
d->__nextchar += _tcslen(d->__nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
d->__nextchar = NULL;
return _T('W');
}
if (temp[1] == _T(':'))
{
if (temp[2] == _T(':'))
{
if (*d->__nextchar != _T('\0'))
{
d->optarg = d->__nextchar;
d->optind++;
}
else
d->optarg = NULL;
d->__nextchar = NULL;
}
else
{
if (*d->__nextchar != _T('\0'))
{
d->optarg = d->__nextchar;
d->optind++;
}
else if (d->optind == argc)
{
if (print_errors)
{
_ftprintf(stderr,
_T("%s: option requires an argument -- '%c'\n"),
argv[0], c);
}
d->optopt = c;
if (optstring[0] == _T(':'))
c = _T(':');
else
c = _T('?');
}
else
d->optarg = argv[d->optind++];
d->__nextchar = NULL;
}
}
return c;
}
}
int _getopt_internal (int argc, TCHAR *const *argv, const TCHAR *optstring, const struct option *longopts, int *longind, int long_only, int posixly_correct)
{
int result;
getopt_data.optind = optind;
getopt_data.opterr = opterr;
result = _getopt_internal_r (argc, argv, optstring, longopts,longind, long_only, &getopt_data,posixly_correct);
optind = getopt_data.optind;
optarg = getopt_data.optarg;
optopt = getopt_data.optopt;
return result;
}
int getopt (int argc, TCHAR *const *argv, const TCHAR *optstring)
{
return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0, 0);
}
int getopt_long (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0, 0);
}
int _getopt_long_r (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index, struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,0, d, 0);
}
int getopt_long_only (int argc, TCHAR *const *argv, const TCHAR *options, const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1, 0);
}
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)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index, 1, d, 0);
}
#endif

106
getopt.h Normal file
View file

@ -0,0 +1,106 @@
#ifdef _WIN32
/* Getopt for Microsoft C
This code is a modification of the Free Software Foundation, Inc.
Getopt library for parsing command line argument the purpose was
to provide a Microsoft Visual C friendly derivative. This code
provides functionality for both Unicode and Multibyte builds.
Date: 02/03/2011 - Ludvik Jerabek - Initial Release
Version: 1.0
Comment: Supports getopt, getopt_long, and getopt_long_only
and POSIXLY_CORRECT environment flag
License: LGPL
Revisions:
02/03/2011 - Ludvik Jerabek - Initial Release
02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
**DISCLAIMER**
THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef __GETOPT_H_
#define __GETOPT_H_
#define STATIC_GETOPT
#ifdef _GETOPT_API
#undef _GETOPT_API
#endif
#if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
#error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually"
#elif defined(STATIC_GETOPT)
#pragma message("Warning static builds of getopt violate the Lesser GNU Public License")
#define _GETOPT_API
#elif defined(EXPORTS_GETOPT)
#pragma message("Exporting getopt library")
#define _GETOPT_API __declspec(dllexport)
#else
#pragma message("Importing getopt library")
#define _GETOPT_API __declspec(dllimport)
#endif
#include <tchar.h>
// Standard GNU options
#define null_argument 0 /*Argument Null*/
#define no_argument 0 /*Argument Switch Only*/
#define required_argument 1 /*Argument Required*/
#define optional_argument 2 /*Argument Optional*/
// Change behavior for C\C++
#ifdef __cplusplus
#define _BEGIN_EXTERN_C extern "C" {
#define _END_EXTERN_C }
#define _GETOPT_THROW throw()
#else
#define _BEGIN_EXTERN_C
#define _END_EXTERN_C
#define _GETOPT_THROW
#endif
_BEGIN_EXTERN_C
extern _GETOPT_API TCHAR *optarg;
extern _GETOPT_API int optind;
extern _GETOPT_API int opterr;
extern _GETOPT_API int optopt;
struct option
{
const TCHAR* name;
int has_arg;
int *flag;
TCHAR val;
};
extern _GETOPT_API int getopt(int argc, TCHAR *const *argv, const TCHAR *optstring) _GETOPT_THROW;
extern _GETOPT_API int getopt_long(int ___argc, TCHAR *const *___argv, const TCHAR *__shortopts, const struct option *__longopts, int *__longind) _GETOPT_THROW;
extern _GETOPT_API int getopt_long_only(int ___argc, TCHAR *const *___argv, const TCHAR *__shortopts, const struct option *__longopts, int *__longind) _GETOPT_THROW;
_END_EXTERN_C
// Undefine so the macros are not included
#undef _BEGIN_EXTERN_C
#undef _END_EXTERN_C
#undef _GETOPT_THROW
#undef _GETOPT_API
#endif // __GETOPT_H_
#endif

725
keys.cpp Normal file
View file

@ -0,0 +1,725 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* Copyright (c) 2012 by flatz
* This file is released under the GPLv2.
*/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include "config.h"
#include "types.h"
#include "list.h"
#include "sce.h"
#include "keys.h"
#include "util.h"
#include "tables.h"
#include "aes.h"
/*
[keyname]
type={SELF, RVK, PKG, SPP, OTHER}
revision={00, ..., 18, 8000}
version={..., 0001000000000000, ...}
self_type={LV0, LV1, LV2, APP, ISO, LDR, UNK_7, NPDRM}
key=...
erk=...
riv=...
pub=...
priv=...
ctype=...
*/
/*! Loaded keysets. */
list_t *_keysets;
/*! Loaded curves. */
curve_t *_curves;
/*! Loaded VSH curves. */
vsh_curve_t *_vsh_curves;
static u8 rap_init_key[0x10] =
{
0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF
};
static u8 rap_pbox[0x10] =
{
0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09
};
static u8 rap_e1[0x10] =
{
0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5
};
static u8 rap_e2[0x10] =
{
0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74
};
static void _fill_property(keyset_t *ks, s8 *prop, s8 *value)
{
if(strcmp(prop, "type") == 0)
{
if(strcmp(value, "SELF") == 0)
ks->type = KEYTYPE_SELF;
else if(strcmp(value, "RVK") == 0)
ks->type = KEYTYPE_RVK;
else if(strcmp(value, "PKG") == 0)
ks->type = KEYTYPE_PKG;
else if(strcmp(value, "SPP") == 0)
ks->type = KEYTYPE_SPP;
else if(strcmp(value, "OTHER") == 0)
ks->type = KEYTYPE_OTHER;
else
printf("[*] Error: Unknown type '%s'.\n", value);
}
else if(strcmp(prop, "revision") == 0)
ks->key_revision = (u16)_x_to_u64(value);
else if(strcmp(prop, "version") == 0)
ks->version = _x_to_u64(value);
else if(strcmp(prop, "self_type") == 0)
{
if(strcmp(value, "LV0") == 0)
ks->self_type = SELF_TYPE_LV0;
else if(strcmp(value, "LV1") == 0)
ks->self_type = SELF_TYPE_LV1;
else if(strcmp(value, "LV2") == 0)
ks->self_type = SELF_TYPE_LV2;
else if(strcmp(value, "APP") == 0)
ks->self_type = SELF_TYPE_APP;
else if(strcmp(value, "ISO") == 0)
ks->self_type = SELF_TYPE_ISO;
else if(strcmp(value, "LDR") == 0)
ks->self_type = SELF_TYPE_LDR;
else if(strcmp(value, "UNK_7") == 0)
ks->self_type = SELF_TYPE_UNK_7;
else if(strcmp(value, "NPDRM") == 0)
ks->self_type = SELF_TYPE_NPDRM;
else
printf("[*] Error: unknown SELF type '%s'.\n", value);
}
else if(strcmp(prop, "erk") == 0 || strcmp(prop, "key") == 0)
{
ks->erk = _x_to_u8_buffer(value);
ks->erklen = strlen(value) / 2;
}
else if(strcmp(prop, "riv") == 0)
{
ks->riv = _x_to_u8_buffer(value);
ks->rivlen = strlen(value) / 2;
}
else if(strcmp(prop, "pub") == 0)
ks->pub = _x_to_u8_buffer(value);
else if(strcmp(prop, "priv") == 0)
ks->priv = _x_to_u8_buffer(value);
else if(strcmp(prop, "ctype") == 0)
ks->ctype = (u8)_x_to_u64(value);
else
printf("[*] Error: Unknown keyfile property '%s'.\n", prop);
}
static s64 _compare_keysets(keyset_t *ks1, keyset_t *ks2)
{
s64 res;
if((res = (s64)ks1->version - (s64)ks2->version) == 0)
res = (s64)ks1->key_revision - (s64)ks2->key_revision;
return res;
}
static void _sort_keysets()
{
u32 i, to = _keysets->count;
lnode_t *max;
list_t *tmp = list_create();
for(i = 0; i < to; i++)
{
max = _keysets->head;
LIST_FOREACH(iter, _keysets)
{
if(_compare_keysets((keyset_t *)max->value, (keyset_t *)iter->value) < 0)
max = iter;
}
list_push(tmp, max->value);
list_remove_node(_keysets, max);
}
list_destroy(_keysets);
_keysets = tmp;
}
void _print_key_list(FILE *fp)
{
const s8 *name;
s32 len = 0, tmp;
LIST_FOREACH(iter, _keysets)
if((tmp = strlen(((keyset_t *)iter->value)->name)) > len)
len = tmp;
fprintf(fp, " Name");
_print_align(fp, " ", len, 4);
fprintf(fp, " Type Revision Version SELF-Type\n");
LIST_FOREACH(iter, _keysets)
{
keyset_t *ks = (keyset_t *)iter->value;
fprintf(fp, " %s", ks->name);
_print_align(fp, " ", len, strlen(ks->name));
fprintf(fp, " %-5s 0x%04X %s ", _get_name(_key_types, ks->type), ks->key_revision, sce_version_to_str(ks->version));
if(ks->type == KEYTYPE_SELF)
{
name = _get_name(_self_types, ks->self_type);
if(name != NULL)
fprintf(fp, "[%s]\n", name);
else
fprintf(fp, "0x%08X\n", ks->self_type);
}
else
fprintf(fp, "\n");
}
}
#define LINEBUFSIZE 512
BOOL keys_load(const s8 *kfile)
{
u32 i = 0, lblen;
FILE *fp;
s8 lbuf[LINEBUFSIZE];
keyset_t *cks = NULL;
if((_keysets = list_create()) == NULL)
return FALSE;
if((fp = fopen(kfile, "r")) == NULL)
{
list_destroy(_keysets);
return FALSE;
}
do
{
//Get next line.
lbuf[0] = 0;
fgets(lbuf, LINEBUFSIZE, fp);
lblen = strlen(lbuf);
//Don't parse empty lines (ignore '\n') and comment lines (starting with '#').
if(lblen > 1 && lbuf[0] != '#')
{
//Remove '\n'.
lbuf[lblen-1] = 0;
//Check for keyset entry.
if(lblen > 2 && lbuf[0] == '[')
{
if(cks != NULL)
{
//Add to keyset list.
list_push(_keysets, cks);
cks = NULL;
}
//Find name end.
for(i = 0; lbuf[i] != ']' && lbuf[i] != '\n' && i < lblen; i++);
lbuf[i] = 0;
//Allocate keyset and fill name.
cks = (keyset_t *)malloc(sizeof(keyset_t));
memset(cks, 0, sizeof(keyset_t));
cks->name = strdup(&lbuf[1]);
}
else if(cks != NULL)
{
//Find property name end.
for(i = 0; lbuf[i] != '=' && lbuf[i] != '\n' && i < lblen; i++);
lbuf[i] = 0;
//Fill property.
_fill_property(cks, &lbuf[0], &lbuf[i+1]);
}
}
} while(!feof(fp));
//Add last keyset to keyset list.
if(cks != NULL)
list_push(_keysets, cks);
//Sort keysets.
_sort_keysets();
return TRUE;
}
#undef LINEBUFSIZE
static keyset_t *_keyset_find_for_self(u32 self_type, u16 key_revision, u64 version)
{
LIST_FOREACH(iter, _keysets)
{
keyset_t *ks = (keyset_t *)iter->value;
if(ks->self_type == self_type)
{
switch(self_type)
{
case SELF_TYPE_LV0:
return ks;
break;
case SELF_TYPE_LV1:
if(version <= ks->version)
return ks;
break;
case SELF_TYPE_LV2:
if(version <= ks->version)
return ks;
break;
case SELF_TYPE_APP:
if(key_revision == ks->key_revision)
return ks;
break;
case SELF_TYPE_ISO:
if(version <= ks->version && key_revision == ks->key_revision)
return ks;
break;
case SELF_TYPE_LDR:
return ks;
break;
case SELF_TYPE_NPDRM:
if(key_revision == ks->key_revision)
return ks;
break;
}
}
}
return NULL;
}
static keyset_t *_keyset_find_for_rvk(u32 key_revision)
{
LIST_FOREACH(iter, _keysets)
{
keyset_t *ks = (keyset_t *)iter->value;
if(ks->type == KEYTYPE_RVK && key_revision <= ks->key_revision)
return ks;
}
return NULL;
}
static keyset_t *_keyset_find_for_pkg(u16 key_revision)
{
LIST_FOREACH(iter, _keysets)
{
keyset_t *ks = (keyset_t *)iter->value;
if(ks->type == KEYTYPE_PKG && key_revision <= ks->key_revision)
return ks;
}
return NULL;
}
static keyset_t *_keyset_find_for_spp(u16 key_revision)
{
LIST_FOREACH(iter, _keysets)
{
keyset_t *ks = (keyset_t *)iter->value;
if(ks->type == KEYTYPE_SPP && key_revision <= ks->key_revision)
return ks;
}
return NULL;
}
keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt)
{
keyset_t *res = NULL;
switch(ctxt->sceh->header_type)
{
case SCE_HEADER_TYPE_SELF:
res = _keyset_find_for_self(ctxt->self.ai->self_type, ctxt->sceh->key_revision, ctxt->self.ai->version);
break;
case SCE_HEADER_TYPE_RVK:
res = _keyset_find_for_rvk(ctxt->sceh->key_revision);
break;
case SCE_HEADER_TYPE_PKG:
res = _keyset_find_for_pkg(ctxt->sceh->key_revision);
break;
case SCE_HEADER_TYPE_SPP:
res = _keyset_find_for_spp(ctxt->sceh->key_revision);
break;
}
if(res == NULL)
printf("[*] Error: Could not find keyset for %s.\n", _get_name(_sce_header_types, ctxt->sceh->header_type));
return res;
}
keyset_t *keyset_find_by_name(const s8 *name)
{
LIST_FOREACH(iter, _keysets)
{
keyset_t *ks = (keyset_t *)iter->value;
if(strcmp(ks->name, name) == 0)
return ks;
}
printf("[*] Error: Could not find keyset '%s'.\n", name);
return NULL;
}
BOOL curves_load(const s8 *cfile)
{
u32 len = 0;
_curves = (curve_t *)_read_buffer(cfile, &len);
if(_curves == NULL)
return FALSE;
if(len != CURVES_LENGTH)
{
free(_curves);
return FALSE;
}
return TRUE;
}
curve_t *curve_find(u8 ctype)
{
if(ctype > CTYPE_MAX)
return NULL;
return &_curves[ctype];
}
BOOL vsh_curves_load(const s8 *cfile)
{
u32 len = 0;
_vsh_curves = (vsh_curve_t *)_read_buffer(cfile, &len);
if(_vsh_curves == NULL)
return FALSE;
if(len != VSH_CURVES_LENGTH)
{
free(_vsh_curves);
return FALSE;
}
return TRUE;
}
static curve_t _tmp_curve;
curve_t *vsh_curve_find(u8 ctype)
{
if(ctype > VSH_CTYPE_MAX)
return NULL;
_memcpy_inv(_tmp_curve.p, _vsh_curves[ctype].p, 20);
_memcpy_inv(_tmp_curve.a, _vsh_curves[ctype].a, 20);
_memcpy_inv(_tmp_curve.b, _vsh_curves[ctype].b, 20);
_tmp_curve.N[0] = ~0x00;
_memcpy_inv(_tmp_curve.N+1, _vsh_curves[ctype].N, 20);
_memcpy_inv(_tmp_curve.Gx, _vsh_curves[ctype].Gx, 20);
_memcpy_inv(_tmp_curve.Gy, _vsh_curves[ctype].Gx, 20);
return &_tmp_curve;
}
static u8 *idps_load()
{
s8 *ps3 = NULL, path[256];
u8 *idps;
u32 len = 0;
if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL)
if(access(ps3, 0) != 0)
ps3 = NULL;
if(ps3 != NULL)
{
sprintf(path, "%s/%s", ps3, CONFIG_IDPS_FILE);
if(access(path, 0) != 0)
sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE);
}
else
sprintf(path, "%s/%s", CONFIG_IDPS_PATH, CONFIG_IDPS_FILE);
idps = (u8 *)_read_buffer(path, &len);
if(idps == NULL)
return NULL;
if(len != IDPS_LENGTH)
{
free(idps);
return NULL;
}
return idps;
}
static act_dat_t *act_dat_load()
{
s8 *ps3 = NULL, path[256];
act_dat_t *act_dat;
u32 len = 0;
if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL)
if(access(ps3, 0) != 0)
ps3 = NULL;
if(ps3 != NULL)
{
sprintf(path, "%s/%s", ps3, CONFIG_ACT_DAT_FILE);
if(access(path, 0) != 0)
sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE);
}
else
sprintf(path, "%s/%s", CONFIG_ACT_DAT_PATH, CONFIG_ACT_DAT_FILE);
act_dat = (act_dat_t *)_read_buffer(path, &len);
if(act_dat == NULL)
return NULL;
if(len != ACT_DAT_LENGTH)
{
free(act_dat);
return NULL;
}
return act_dat;
}
static rif_t *rif_load(const s8 *content_id)
{
s8 *ps3 = NULL, path[256];
rif_t *rif;
u32 len = 0;
if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL)
if(access(ps3, 0) != 0)
ps3 = NULL;
if(ps3 != NULL)
{
sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RIF_FILE_EXT);
if(access(path, 0) != 0)
sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT);
}
else
sprintf(path, "%s/%s%s", CONFIG_RIF_PATH, content_id, CONFIG_RIF_FILE_EXT);
rif = (rif_t *)_read_buffer(path, &len);
if(rif == NULL)
return NULL;
if(len < RIF_LENGTH)
{
free(rif);
return NULL;
}
return rif;
}
static u8 *rap_load(const s8 *content_id)
{
s8 *ps3 = NULL, path[256];
u8 *rap;
u32 len = 0;
if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL)
if(access(ps3, 0) != 0)
ps3 = NULL;
if(ps3 != NULL)
{
sprintf(path, "%s/%s%s", ps3, content_id, CONFIG_RAP_FILE_EXT);
if(access(path, 0) != 0)
sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT);
}
else
sprintf(path, "%s/%s%s", CONFIG_RAP_PATH, content_id, CONFIG_RAP_FILE_EXT);
rap = (u8 *)_read_buffer(path, &len);
if(rap == NULL)
return NULL;
if(len != RAP_LENGTH)
{
free(rap);
return NULL;
}
return rap;
}
static BOOL rap_to_klicensee(const s8 *content_id, u8 *klicensee)
{
u8 *rap;
aes_context aes_ctxt;
int round_num;
int i;
rap = rap_load(content_id);
if(rap == NULL)
return FALSE;
aes_setkey_dec(&aes_ctxt, rap_init_key, RAP_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rap, rap);
for (round_num = 0; round_num < 5; ++round_num)
{
for (i = 0; i < 16; ++i)
{
int p = rap_pbox[i];
rap[p] ^= rap_e1[p];
}
for (i = 15; i >= 1; --i)
{
int p = rap_pbox[i];
int pp = rap_pbox[i - 1];
rap[p] ^= rap[pp];
}
int o = 0;
for (i = 0; i < 16; ++i)
{
int p = rap_pbox[i];
u8 kc = rap[p] - o;
u8 ec2 = rap_e2[p];
if (o != 1 || kc != 0xFF)
{
o = kc < ec2 ? 1 : 0;
rap[p] = kc - ec2;
}
else if (kc == 0xFF)
rap[p] = kc - ec2;
else
rap[p] = kc;
}
}
memcpy(klicensee, rap, RAP_LENGTH);
free(rap);
return TRUE;
}
BOOL klicensee_by_content_id(const s8 *content_id, u8 *klicensee)
{
aes_context aes_ctxt;
if(rap_to_klicensee(content_id, klicensee) == FALSE)
{
keyset_t *ks_np_idps_const, *ks_np_rif_key;
rif_t *rif;
u8 idps_const[0x10];
u8 act_dat_key[0x10];
u32 act_dat_key_index;
u8 *idps;
act_dat_t *act_dat;
if((idps = idps_load()) == NULL)
{
printf("[*] Error: Could not load IDPS.\n");
return FALSE;
}
else
_LOG_VERBOSE("IDPS loaded.\n");
if((act_dat = act_dat_load()) == NULL)
{
printf("[*] Error: Could not load act.dat.\n");
return FALSE;
}
else
_LOG_VERBOSE("act.dat loaded.\n");
ks_np_idps_const = keyset_find_by_name(CONFIG_NP_IDPS_CONST_KNAME);
if(ks_np_idps_const == NULL)
return FALSE;
memcpy(idps_const, ks_np_idps_const->erk, 0x10);
ks_np_rif_key = keyset_find_by_name(CONFIG_NP_RIF_KEY_KNAME);
if(ks_np_rif_key == NULL)
return FALSE;
rif = rif_load(content_id);
if(rif == NULL)
{
printf("[*] Error: Could not obtain klicensee for '%s'.\n", content_id);
return FALSE;
}
aes_setkey_dec(&aes_ctxt, ks_np_rif_key->erk, RIF_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->act_key_index, rif->act_key_index);
act_dat_key_index = _ES32(*(u32 *)(rif->act_key_index + 12));
if(act_dat_key_index > 127)
{
printf("[*] Error: act.dat key index out of bounds.\n");
return FALSE;
}
memcpy(act_dat_key, act_dat->primary_key_table + act_dat_key_index * BITS2BYTES(ACT_DAT_KEYBITS), BITS2BYTES(ACT_DAT_KEYBITS));
aes_setkey_enc(&aes_ctxt, idps, IDPS_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_ENCRYPT, idps_const, idps_const);
aes_setkey_dec(&aes_ctxt, idps_const, IDPS_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, act_dat_key, act_dat_key);
aes_setkey_dec(&aes_ctxt, act_dat_key, ACT_DAT_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, rif->klicensee, klicensee);
free(rif);
_LOG_VERBOSE("klicensee decrypted.\n");
}
else
_LOG_VERBOSE("klicensee converted from %s.rap.\n", content_id);
return TRUE;
}
keyset_t *keyset_from_buffer(u8 *keyset)
{
keyset_t *ks;
if((ks = (keyset_t *)malloc(sizeof(keyset_t))) == NULL)
return NULL;
ks->erk = (u8 *)_memdup(keyset, 0x20);
ks->erklen = 0x20;
ks->riv = (u8 *)_memdup(keyset + 0x20, 0x10);
ks->rivlen = 0x10;
ks->pub = (u8 *)_memdup(keyset + 0x20 + 0x10, 0x28);
ks->priv = (u8 *)_memdup(keyset + 0x20 + 0x10 + 0x28, 0x15);
ks->ctype = (u8)*(keyset + 0x20 + 0x10 + 0x28 + 0x15);
return ks;
}

133
keys.h Normal file
View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _KEYS_H_
#define _KEYS_H_
#include "types.h"
#include "sce.h"
#define KEYBITS(klen) BYTES2BITS(klen)
#define KEYTYPE_SELF 1
#define KEYTYPE_RVK 2
#define KEYTYPE_PKG 3
#define KEYTYPE_SPP 4
#define KEYTYPE_OTHER 5
/*! Flag to use VSH curve. */
#define USE_VSH_CURVE 0x40
/*! Length of whole curves file. */
#define CURVES_LENGTH 0x1E40
#define CTYPE_MIN 0
#define CTYPE_MAX 63
/*! Length of the whole VSH curves file. */
#define VSH_CURVES_LENGTH 0x168
#define VSH_CTYPE_MIN 0
#define VSH_CTYPE_MAX 2
/*! Length of the idps, act.dat, .rif and .rap files. */
#define IDPS_LENGTH 0x10
#define ACT_DAT_LENGTH 0x1038
#define RIF_LENGTH 0x98
#define RAP_LENGTH 0x10
/*! IDPS, RIF, act.dat key lengths. */
#define IDPS_KEYBITS 128
#define ACT_DAT_KEYBITS 128
#define RIF_KEYBITS 128
#define RAP_KEYBITS 128
/*! Keyset. */
typedef struct _keyset
{
/*! Name. */
s8 *name;
/*! Type. */
u32 type;
/*! Key revision. */
u16 key_revision;
/*! Version. */
u64 version;
/*! SELF type. */
u32 self_type;
/*! Key length. */
u32 erklen;
/*! Key. */
u8 *erk;
/*! IV length. */
u32 rivlen;
/*! IV. */
u8 *riv;
/*! Pub. */
u8 *pub;
/*! Priv. */
u8 *priv;
/*! Curve type. */
u8 ctype;
} keyset_t;
/*! Curve entry. */
typedef struct _curve
{
u8 p[20];
u8 a[20];
u8 b[20];
u8 N[21];
u8 Gx[20];
u8 Gy[20];
} curve_t;
/*! VSH Curve entry. */
typedef struct _vsh_curve
{
u8 a[20];
u8 b[20];
u8 N[20];
u8 p[20];
u8 Gx[20];
u8 Gy[20];
} vsh_curve_t;
/*! act.dat. */
typedef struct _act_dat
{
u8 account_info[16];
u8 primary_key_table[2048];
u8 secondary_key_table[2048];
u8 signature[40];
} act_dat_t;
/*! RIF. */
typedef struct _rif
{
u8 account_info[16];
u8 content_id[48];
u8 act_key_index[16];
u8 klicensee[16];
u64 timestamp;
u64 zero;
u8 signature[40];
} rif_t;
void _print_key_list(FILE *fp);
BOOL keys_load(const s8 *kfile);
keyset_t *keyset_find(sce_buffer_ctxt_t *ctxt);
keyset_t *keyset_find_by_name(const s8 *name);
BOOL curves_load(const s8 *cfile);
curve_t *curve_find(u8 ctype);
BOOL vsh_curves_load(const s8 *cfile);
curve_t *vsh_curve_find(u8 ctype);
BOOL klicensee_by_content_id(const s8 *content_id, u8 *klicensee);
keyset_t *keyset_from_buffer(u8 *keyset);
#endif

224
list.cpp Normal file
View file

@ -0,0 +1,224 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdlib.h>
#include "types.h"
#include "list.h"
list_t *list_create()
{
list_t *res;
if((res = (list_t *)malloc(sizeof(list_t))) == NULL)
return NULL;
res->head = NULL;
res->count = 0;
return res;
}
void list_destroy(list_t *l)
{
if(l == NULL)
return;
lnode_t *iter = l->head, *tmp;
while(iter != NULL)
{
tmp = iter;
iter = iter->next;
free(tmp);
}
free(l);
}
BOOL list_isempty(list_t *l)
{
if(l == NULL)
return FALSE;
if(l->count == 0)
return TRUE;
return FALSE;
}
u32 list_count(list_t *l)
{
if(l == NULL)
return 0;
return l->count;
}
BOOL list_push(list_t *l, void *value)
{
if(l == NULL)
return FALSE;
lnode_t *_new;
//Allocate new node.
if((_new = (lnode_t *)malloc(sizeof(lnode_t))) == NULL)
return FALSE;
//Insert.
_new->value = value;
_new->next = l->head;
l->head = _new;
l->count++;
return TRUE;
}
void *list_pop(list_t *l)
{
if(l == NULL)
return NULL;
lnode_t *tmp;
void *res = NULL;
if(l->head != NULL)
{
res = l->head->value;
tmp = l->head;
l->head = l->head->next;
free(tmp);
l->count--;
}
return res;
}
BOOL list_add_back(list_t *l, void *value)
{
if(l == NULL)
return FALSE;
lnode_t *n, *_new;
//Allocate new node.
if((_new = (lnode_t *)malloc(sizeof(lnode_t))) == NULL)
return FALSE;
_new->value = value;
_new->next = NULL;
if(l->head == NULL)
l->head = _new;
else
{
//Move to the list end.
for(n = l->head; n->next != NULL; n = n->next);
//Add.
n->next = _new;
l->count++;
}
return TRUE;
}
void *list_get(list_t *l, u32 idx)
{
if(l == NULL)
return NULL;
lnode_t *iter;
void *res = NULL;
for(iter = l->head; idx-- != 0 && iter != NULL; iter = iter->next);
if(iter == NULL)
res = NULL;
else
res = iter->value;
return res;
}
lnode_t *list_get_node(list_t *l, u32 idx)
{
if(l == NULL)
return NULL;
lnode_t *iter;
for(iter = l->head; idx-- != 0 && iter != NULL; iter = iter->next);
return iter;
}
BOOL list_remove_node(list_t *l, lnode_t *node)
{
if(l == NULL)
return FALSE;
lnode_t *iter;
if(l->head == node)
{
l->head = l->head->next;
free(node);
l->count--;
return TRUE;
}
iter = l->head;
while(iter->next != NULL)
{
if(iter->next == node)
{
iter->next = iter->next->next;
free(node);
l->count--;
return TRUE;
}
iter = iter->next;
}
return FALSE;
}
BOOL list_remove_value(list_t *l, void *value)
{
if(l == NULL)
return FALSE;
lnode_t *tmp, *iter;
if(l->head->value == value)
{
tmp = l->head;
l->head = l->head->next;
free(tmp);
l->count--;
return TRUE;
}
iter = l->head;
while(iter->next != NULL)
{
if(iter->next->value == value)
{
tmp = iter->next;
iter->next = iter->next->next;
free(tmp);
l->count--;
return TRUE;
}
iter = iter->next;
}
return FALSE;
}

37
list.h Normal file
View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _LIST_H_
#define _LIST_H_
#include "types.h"
#define LIST_FOREACH(iter, list) for(lnode_t *iter = list->head; iter != NULL; iter = iter->next)
typedef struct _lnode
{
void *value;
struct _lnode *next;
} lnode_t;
typedef struct _list
{
lnode_t *head;
u32 count;
} list_t;
list_t *list_create();
void list_destroy(list_t *l);
BOOL list_isempty(list_t *l);
u32 list_count(list_t *l);
BOOL list_push(list_t *l, void *value);
void *list_pop(list_t *l);
BOOL list_add_back(list_t *l, void *value);
void *list_get(list_t *l, u32 idx);
lnode_t *list_get_node(list_t *l, u32 idx);
BOOL list_remove_node(list_t *l, lnode_t *node);
BOOL list_remove_value(list_t *l, void *value);
#endif

450
main.cpp Normal file
View file

@ -0,0 +1,450 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <io.h>
#include "getopt.h"
#else
#include <unistd.h>
#include <getopt.h>
#endif
#include "types.h"
#include "config.h"
#include "aes.h"
#include "util.h"
#include "keys.h"
#include "sce.h"
#include "np.h"
#include "self.h"
#include "rvk.h"
#include "frontend.h"
/*! Shorter Versions of arg options. */
#define ARG_NULL no_argument
#define ARG_NONE no_argument
#define ARG_REQ required_argument
#define ARG_OPT optional_argument
/*! Verbose mode. */
BOOL _verbose = FALSE;
/*! Raw mode. */
BOOL _raw = FALSE;
/*! We got work. */
static BOOL _got_work = FALSE;
/*! List keys. */
static BOOL _list_keys = FALSE;
/*! Print infos on file. */
static BOOL _print_info = FALSE;
/*! Decrypt file. */
static BOOL _decrypt_file = FALSE;
/*! Encrypt file. */
static BOOL _encrypt_file = FALSE;
/*! Parameters. */
s8 *_template = NULL;
s8 *_file_type = NULL;
s8 *_compress_data = NULL;
s8 *_skip_sections = NULL;
s8 *_key_rev = NULL;
s8 *_meta_info = NULL;
s8 *_keyset = NULL;
s8 *_auth_id = NULL;
s8 *_vendor_id = NULL;
s8 *_self_type = NULL;
s8 *_app_version = NULL;
s8 *_fw_version = NULL;
s8 *_add_shdrs = NULL;
s8 *_ctrl_flags = NULL;
s8 *_cap_flags = NULL;
#ifdef CONFIG_CUSTOM_INDIV_SEED
s8 *_indiv_seed = NULL;
#endif
s8 *_license_type = NULL;
s8 *_app_type = NULL;
s8 *_content_id = NULL;
s8 *_klicensee = NULL;
s8 *_real_fname = NULL;
s8 *_add_sig = NULL;
/*! Input file. */
static s8 *_file_in = NULL;
/*! Ouput file. */
static s8 *_file_out = NULL;
/*! Long option values. */
#define VAL_TEMPLATE 't'
#define VAL_FILE_TYPE '0'
#define VAL_COMPRESS_DATA '1'
#define VAL_SKIP_SECTIONS 's'
#define VAL_KEY_REV '2'
#define VAL_META_INFO 'm'
#define VAL_KEYSET 'K'
#define VAL_AUTH_ID '3'
#define VAL_VENDOR_ID '4'
#define VAL_SELF_TYPE '5'
#define VAL_APP_VERSION 'A'
#define VAL_FW_VERSION '6'
#define VAL_ADD_SHDRS '7'
#define VAL_CTRL_FLAGS '8'
#define VAL_CAP_FLAGS '9'
#ifdef CONFIG_CUSTOM_INDIV_SEED
#define VAL_INDIV_SEED 'a'
#endif
#define VAL_LICENSE_TYPE 'b'
#define VAL_APP_TYPE 'c'
#define VAL_CONTENT_ID 'f'
#define VAL_KLICENSEE 'l'
#define VAL_REAL_FNAME 'g'
#define VAL_ADD_SIG 'j'
static struct option options[] =
{
{"help", ARG_NONE, NULL, 'h'},
{"print-keys", ARG_NONE, NULL, 'k'},
{"print-infos", ARG_REQ, NULL, 'i'},
{"decrypt", ARG_REQ, NULL, 'd'},
{"encrypt", ARG_REQ, NULL, 'e'},
{"verbose", ARG_NONE, NULL, 'v'},
{"raw", ARG_NONE, NULL, 'r'},
{"template", ARG_REQ, NULL, VAL_TEMPLATE},
{"sce-type", ARG_REQ, NULL, VAL_FILE_TYPE},
{"compress-data", ARG_REQ, NULL, VAL_COMPRESS_DATA},
{"skip-sections", ARG_REQ, NULL, VAL_SKIP_SECTIONS},
{"key-revision", ARG_REQ, NULL, VAL_KEY_REV},
{"meta-info", ARG_REQ, NULL, VAL_META_INFO},
{"keyset", ARG_REQ, NULL, VAL_KEYSET},
{"self-auth-id", ARG_REQ, NULL, VAL_AUTH_ID},
{"self-vendor-id", ARG_REQ, NULL, VAL_VENDOR_ID},
{"self-type", ARG_REQ, NULL, VAL_SELF_TYPE},
{"self-app-version", ARG_REQ, NULL, VAL_APP_VERSION},
{"self-fw-version", ARG_REQ, NULL, VAL_FW_VERSION},
{"self-add-shdrs", ARG_REQ, NULL, VAL_ADD_SHDRS},
{"self-ctrl-flags", ARG_REQ, NULL, VAL_CTRL_FLAGS},
{"self-cap-flags", ARG_REQ, NULL, VAL_CAP_FLAGS},
#ifdef CONFIG_CUSTOM_INDIV_SEED
{"self-indiv-seed", ARG_REQ, NULL, VAL_INDIV_SEED},
#endif
{"np-license-type", ARG_REQ, NULL, VAL_LICENSE_TYPE},
{"np-app-type", ARG_REQ, NULL, VAL_APP_TYPE},
{"np-content-id", ARG_REQ, NULL, VAL_CONTENT_ID},
{"np-klicensee", ARG_REQ, NULL, VAL_KLICENSEE},
{"np-real-fname", ARG_REQ, NULL, VAL_REAL_FNAME},
{"np-add-sig", ARG_REQ, NULL, VAL_ADD_SIG},
{NULL, ARG_NULL, NULL, 0}
};
static void print_version()
{
printf("scetool " SCETOOL_VERSION " (C) 2011-2013 by naehrwert\n");
printf("NP local license handling (C) 2012 by flatz\n");
//printf("[Build Date/Time: %s/%s]\n", __DATE__, __TIME__);
}
#include <time.h>
static void print_usage()
{
print_version();
printf("USAGE: scetool [options] command\n");
printf("COMMANDS Parameters Explanation\n");
printf(" -h, --help Print this help.\n");
printf(" -k, --print-keys List keys.\n");
printf(" -i, --print-infos File-in Print SCE file info.\n");
printf(" -d, --decrypt File-in File-out Decrypt/dump SCE file.\n");
printf(" -e, --encrypt File-in File-out Encrypt/create SCE file.\n");
printf("OPTIONS Possible Values Explanation\n");
printf(" -v, --verbose Enable verbose output.\n");
printf(" -r, --raw Enable raw value output.\n");
printf(" -t, --template File-in Template file (SELF only)\n");
printf(" -0, --sce-type SELF/RVK/PKG/SPP SCE File Type\n");
printf(" -1, --compress-data TRUE/FALSE(default) Whether to compress data or not.\n");
printf(" -s, --skip-sections TRUE(default)/FALSE Whether to skip sections or not.\n");
printf(" -2, --key-revision e.g. 00,01,...,0A,... Key Revision\n");
printf(" -m, --meta-info 64 bytes Use provided meta info to decrypt.\n");
printf(" -K, --keyset 32(Key)16(IV)\n");
printf(" 40(Pub)21(Priv)1(CT) Override keyset.\n");
printf(" -3, --self-auth-id e.g. 1010000001000003 Authentication ID\n");
printf(" -4, --self-vendor-id e.g. 01000002 Vendor ID\n");
printf(" -5, --self-type LV0/LV1/LV2/APP/ISO/\n");
printf(" LDR/NPDRM SELF Type\n");
printf(" -A, --self-app-version e.g. 0001000000000000 Application Version\n");
printf(" -6, --self-fw-version e.g. 0003004100000000 Firmware Version\n");
printf(" -7, --self-add-shdrs TRUE(default)/FALSE Whether to add ELF shdrs or not.\n");
printf(" -8, --self-ctrl-flags 32 bytes Override control flags.\n");
printf(" -9, --self-cap-flags 32 bytes Override capability flags.\n");
#ifdef CONFIG_CUSTOM_INDIV_SEED
printf(" -a, --self-indiv-seed 256 bytes Individuals Seed (ISO only)\n");
#endif
printf(" -b, --np-license-type LOCAL/FREE License Type\n");
printf(" -c, --np-app-type SPRX/EXEC/USPRX/UEXEC App Type (U* for updates)\n");
printf(" -f, --np-content-id Content ID\n");
printf(" -l, --np-klicensee 16 bytes Override klicensee.\n");
printf(" -g, --np-real-fname e.g. EBOOT.BIN Real Filename\n");
printf(" -j, --np-add-sig TRUE/FALSE(default) Whether to add a NP sig. or not.\n");
//getchar();
exit(1);
}
static void parse_args(int argc, char **argv)
{
char c;
#ifdef CONFIG_CUSTOM_INDIV_SEED
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)
#else
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)
#endif
{
switch(c)
{
case 'h':
print_usage();
break;
case 'k':
_got_work = TRUE;
_list_keys = TRUE;
//Got all args.
return;
break;
case 'i':
_got_work = TRUE;
_print_info = TRUE;
_file_in = optarg;
//Got all args.
return;
break;
case 'd':
_got_work = TRUE;
_decrypt_file = TRUE;
_file_in = optarg;
//Need more args.
goto get_args;
break;
case 'e':
_got_work = TRUE;
_encrypt_file = TRUE;
_file_in = optarg;
//Need more args.
goto get_args;
break;
case 'v':
_verbose = TRUE;
break;
case 'r':
_raw = TRUE;
break;
case VAL_TEMPLATE:
_template = optarg;
break;
case VAL_FILE_TYPE:
_file_type = optarg;
break;
case VAL_COMPRESS_DATA:
_compress_data = optarg;
break;
case VAL_SKIP_SECTIONS:
_skip_sections = optarg;
break;
case VAL_KEY_REV:
_key_rev = optarg;
break;
case VAL_META_INFO:
_meta_info = optarg;
break;
case VAL_KEYSET:
_keyset = optarg;
break;
case VAL_AUTH_ID:
_auth_id = optarg;
break;
case VAL_VENDOR_ID:
_vendor_id = optarg;
break;
case VAL_SELF_TYPE:
_self_type = optarg;
break;
case VAL_APP_VERSION:
_app_version = optarg;
break;
case VAL_FW_VERSION:
_fw_version = optarg;
break;
case VAL_ADD_SHDRS:
_add_shdrs = optarg;
break;
case VAL_CTRL_FLAGS:
_ctrl_flags = optarg;
break;
case VAL_CAP_FLAGS:
_cap_flags = optarg;
break;
#ifdef CONFIG_CUSTOM_INDIV_SEED
case VAL_INDIV_SEED:
_indiv_seed = optarg;
break;
#endif
case VAL_LICENSE_TYPE:
_license_type = optarg;
break;
case VAL_APP_TYPE:
_app_type = optarg;
break;
case VAL_CONTENT_ID:
_content_id = optarg;
break;
case VAL_KLICENSEE:
_klicensee = optarg;
break;
case VAL_REAL_FNAME:
_real_fname = optarg;
break;
case VAL_ADD_SIG:
_add_sig = optarg;
break;
case '?':
print_usage();
break;
}
}
get_args:;
//Additional decrypt args.
if(_decrypt_file)
{
if(argc - optind < 1)
{
printf("[*] Error: Decrypt needs an output file!\n");
print_usage();
}
_file_out = argv[optind];
}
//Additional encrypt args.
if(_encrypt_file)
{
if(argc - optind < 1)
{
printf("[*] Error: Encrypt needs an input and output file!\n");
print_usage();
}
_file_out = argv[optind];
}
}
#ifndef _DEBUG
int main(int argc, char **argv)
{
s8 *ps3 = NULL, path[256];
//Check for args.
if(argc <= 1)
print_usage();
//Parse them.
parse_args(argc, argv);
//Only options won't suffice.
if(_got_work == FALSE)
print_usage();
print_version();
printf("\n");
//Try to get path from env:PS3.
if((ps3 = getenv(CONFIG_ENV_PS3)) != NULL)
if(access(ps3, 0) != 0)
ps3 = NULL;
//Load keysets.
if(ps3 != NULL)
{
sprintf(path, "%s/%s", ps3, CONFIG_KEYS_FILE);
if(access(path, 0) != 0)
sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_KEYS_FILE);
}
else
sprintf(path, "%s/%s", CONFIG_KEYS_PATH, CONFIG_KEYS_FILE);
if(keys_load(path) == TRUE)
_LOG_VERBOSE("Loaded keysets.\n");
else
{
if(_list_keys == TRUE)
{
printf("[*] Error: Could not load keys.\n");
return 0;
}
else
printf("[*] Warning: Could not load keys.\n");
}
//Load curves.
if(ps3 != NULL)
{
sprintf(path, "%s/%s", ps3, CONFIG_CURVES_FILE);
if(access(path, 0) != 0)
sprintf(path, "%s/%s", CONFIG_CURVES_PATH, CONFIG_CURVES_FILE);
}
else
sprintf(path, "%s/%s", CONFIG_CURVES_PATH, CONFIG_CURVES_FILE);
if(curves_load(path) == TRUE)
_LOG_VERBOSE("Loaded loader curves.\n");
else
printf("[*] Warning: Could not load loader curves.\n");
//Load curves.
if(ps3 != NULL)
{
sprintf(path, "%s/%s", ps3, CONFIG_VSH_CURVES_FILE);
if(access(path, 0) != 0)
sprintf(path, "%s/%s", CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE);
}
else
sprintf(path, "%s/%s", CONFIG_VSH_CURVES_PATH, CONFIG_VSH_CURVES_FILE);
if(vsh_curves_load(path) == TRUE)
_LOG_VERBOSE("Loaded vsh curves.\n");
else
printf("[*] Warning: Could not load vsh curves.\n");
//Set klicensee.
if(_klicensee != NULL)
{
if(strlen(_klicensee) != 0x10*2)
{
printf("[*] Error: klicensee needs to be 16 bytes.\n");
return FALSE;
}
np_set_klicensee(_x_to_u8_buffer(_klicensee));
}
if(_list_keys == TRUE)
{
printf("[*] Loaded keysets:\n");
_print_key_list(stdout);
}
else if(_print_info)
frontend_print_infos(_file_in);
else if(_decrypt_file)
frontend_decrypt(_file_in, _file_out);
else if(_encrypt_file)
frontend_encrypt(_file_in, _file_out);
return 0;
}
#endif

49
mt19937.cpp Normal file
View file

@ -0,0 +1,49 @@
#include "mt19937.h"
void mt19937_init(mt19937_ctxt_t *ctxt, unsigned int seed)
{
ctxt->state[0] = seed;
for(ctxt->idx = 1; ctxt->idx < MT_N; ctxt->idx++)
ctxt->state[ctxt->idx] = (1812433253 * (ctxt->state[ctxt->idx - 1] ^ (ctxt->state[ctxt->idx - 1] >> 30)) + ctxt->idx);
ctxt->idx = MT_M + 1;
}
unsigned int mt19937_update(mt19937_ctxt_t *ctxt)
{
unsigned int y, k;
static unsigned int mag01[2] = {0, MT_MATRIX_A};
if(ctxt->idx >= MT_N)
{
for(k = 0; k < MT_N - MT_M; k++)
{
y = (ctxt->state[k] & MT_UPPER_MASK) |
(ctxt->state[k + 1] & MT_LOWER_MASK);
ctxt->state[k] = ctxt->state[k + MT_M] ^ (y >> 1) ^ mag01[y & 1];
}
for(; k < MT_N - 1; k++)
{
y = (ctxt->state[k] & MT_UPPER_MASK) |
(ctxt->state[k + 1] & MT_LOWER_MASK);
ctxt->state[k] = ctxt->state[k + (MT_M - MT_N)] ^ (y >> 1) ^ mag01[y & 1];
}
y = (ctxt->state[MT_N - 1] & MT_UPPER_MASK) |
(ctxt->state[0] & MT_LOWER_MASK);
ctxt->state[MT_N - 1] = ctxt->state[MT_M - 1] ^ (y >> 1) ^ mag01[y & 1];
ctxt->idx = 0;
}
y = ctxt->state[ctxt->idx++];
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}

41
mt19937.h Normal file
View file

@ -0,0 +1,41 @@
//Mersenne-Twister 19937 pseudorandom number generator.
//Reference implementation at:
//http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
#ifndef _MT19937_H_
#define _MT19937_H_
/*! State size. */
#define MT_N 624
#define MT_M 397
#define MT_MATRIX_A 0x9908b0df
#define MT_UPPER_MASK 0x80000000
#define MT_LOWER_MASK 0x7fffffff
/*! Mersenne-Twister 19937 context. */
typedef struct _mt19937_ctxt
{
/*! State. */
unsigned int state[MT_N];
/*! Index. */
unsigned int idx;
} mt19937_ctxt_t;
/*!
* \brief Initialize Mersenne-Twister 19937 context.
*
* \param ctxt Mersenne-Twister 19937 context.
* \param seed Random seed.
*/
void mt19937_init(mt19937_ctxt_t *ctxt, unsigned int seed);
/*!
* \brief Update Mersenne-Twister 19937 state.
*
* \param ctxt Mersenne-Twister 19937 context.
*
* \return Generated pseudorandom number.
*/
unsigned int mt19937_update(mt19937_ctxt_t *ctxt);
#endif

260
np.cpp Normal file
View file

@ -0,0 +1,260 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* Copyright (c) 2012 by flatz
* This file is released under the GPLv2.
*/
#include <stdlib.h>
#include "types.h"
#include "config.h"
#include "np.h"
#include "self.h"
#include "sce.h"
#include "sce_inlines.h"
#include "aes_omac.h"
#include "sha1.h"
#include "ecdsa.h"
#include "keys.h"
#include "aes.h"
#include "util.h"
/*! klicensee key. */
static u8 *_klicensee_key;
static ci_data_npdrm_t *_sce_find_ci_npdrm(sce_buffer_ctxt_t *ctxt)
{
if(ctxt->self.cis != NULL)
{
LIST_FOREACH(iter, ctxt->self.cis)
{
control_info_t *ci = (control_info_t *)iter->value;
if(ci->type == CONTROL_INFO_TYPE_NPDRM)
{
ci_data_npdrm_t *np = (ci_data_npdrm_t *)((u8 *)ci + sizeof(control_info_t));
//Fixup.
_es_ci_data_npdrm(np);
return np;
}
}
}
return NULL;
}
void np_set_klicensee(u8 *klicensee)
{
_klicensee_key = klicensee;
}
BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt)
{
aes_context aes_ctxt;
keyset_t *ks_np_klic_free, *ks_klic_key;
u8 npdrm_key[0x10];
u8 npdrm_iv[0x10];
ci_data_npdrm_t *np;
if((np = _sce_find_ci_npdrm(ctxt)) == NULL)
return FALSE;
//Try to find keysets.
ks_klic_key = keyset_find_by_name(CONFIG_NP_KLIC_KEY_KNAME);
if(ks_klic_key == NULL)
return FALSE;
if(_klicensee_key != NULL)
memcpy(npdrm_key, _klicensee_key, 0x10);
else if(np->license_type == NP_LICENSE_FREE)
{
ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME);
if(ks_np_klic_free == NULL)
return FALSE;
memcpy(npdrm_key, ks_np_klic_free->erk, 0x10);
}
else if(np->license_type == NP_LICENSE_LOCAL)
{
if ((klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE)
return FALSE;
}
else
return FALSE;
aes_setkey_dec(&aes_ctxt, ks_klic_key->erk, METADATA_INFO_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, npdrm_key, npdrm_key);
memset(npdrm_iv, 0, 0x10);
aes_setkey_dec(&aes_ctxt, npdrm_key, METADATA_INFO_KEYBITS);
aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, sizeof(metadata_info_t), npdrm_iv, (u8 *)ctxt->metai, (u8 *)ctxt->metai);
return TRUE;
}
BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt)
{
aes_context aes_ctxt;
keyset_t *ks_np_klic_free, *ks_klic_key;
u8 npdrm_key[0x10];
u8 npdrm_iv[0x10];
ci_data_npdrm_t *np;
if((np = _sce_find_ci_npdrm(ctxt)) == NULL)
return FALSE;
//Try to find keysets.
ks_klic_key = keyset_find_by_name(CONFIG_NP_KLIC_KEY_KNAME);
if(ks_klic_key == NULL)
return FALSE;
if(_klicensee_key != NULL)
memcpy(npdrm_key, _klicensee_key, 0x10);
else if(np->license_type == NP_LICENSE_FREE)
{
ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME);
if(ks_np_klic_free == NULL)
return FALSE;
memcpy(npdrm_key, ks_np_klic_free->erk, 0x10);
}
else if(np->license_type == NP_LICENSE_LOCAL)
{
if ((klicensee_by_content_id((s8 *)np->content_id, npdrm_key)) == FALSE)
return FALSE;
}
else
return FALSE;
aes_setkey_dec(&aes_ctxt, ks_klic_key->erk, METADATA_INFO_KEYBITS);
aes_crypt_ecb(&aes_ctxt, AES_DECRYPT, npdrm_key, npdrm_key);
memset(npdrm_iv, 0, 0x10);
aes_setkey_enc(&aes_ctxt, npdrm_key, METADATA_INFO_KEYBITS);
aes_crypt_cbc(&aes_ctxt, AES_ENCRYPT, sizeof(metadata_info_t), npdrm_iv, ctxt->scebuffer + ctxt->off_metai, ctxt->scebuffer + ctxt->off_metai);
return TRUE;
}
BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp)
{
u32 i, len;
u8 *cid_fname, ci_key[0x10];
keyset_t *ks_np_tid, *ks_np_ci, *ks_np_klic_free;
u8 npdrm_key[0x10];
//Try to find keysets.
ks_np_tid = keyset_find_by_name(CONFIG_NP_TID_KNAME);
ks_np_ci = keyset_find_by_name(CONFIG_NP_CI_KNAME);
if(ks_np_tid == NULL || ks_np_ci == NULL)
return FALSE;
//Can only create NPDRM SELF with local and free license.
if(_klicensee_key != NULL)
memcpy(npdrm_key, _klicensee_key, 0x10);
else if(npconf->license_type == NP_LICENSE_FREE)
{
ks_np_klic_free = keyset_find_by_name(CONFIG_NP_KLIC_FREE_KNAME);
if(ks_np_klic_free == NULL)
return FALSE;
memcpy(npdrm_key, ks_np_klic_free->erk, 0x10);
}
else if(npconf->license_type == NP_LICENSE_LOCAL)
{
if ((klicensee_by_content_id((s8 *)npconf->content_id, npdrm_key)) == FALSE)
return FALSE;
}
else
return FALSE;
cinp->magic = NP_CI_MAGIC;
cinp->unknown_0 = 1;
cinp->license_type = npconf->license_type;
cinp->app_type = npconf->app_type;
memcpy(cinp->content_id, npconf->content_id, 0x30);
#ifdef CONFIG_PRIVATE_BUILD
_fill_rand_bytes(cinp->rndpad, 0x10);
#else
//Better than boring random bytes!
memcpy(cinp->rndpad, CONFIG_NPDRM_WATERMARK, 0x10);
#endif
cinp->unknown_1 = 0;
cinp->unknown_2 = 0;
//Fixup before hashing.
_es_ci_data_npdrm(cinp);
//Generate control info hash key.
for(i = 0; i < 0x10; i++)
ci_key[i] = ks_np_ci->erk[i] ^ npdrm_key[i];
//Create hash of title id and real filename.
len = strlen(npconf->real_fname) + 0x30;
cid_fname = (u8 *)malloc(sizeof(u8) * (len + 1));
memcpy(cid_fname, cinp->content_id, 0x30);
strcpy((s8 *)(cid_fname + 0x30), npconf->real_fname);
aes_omac1(cinp->hash_cid_fname, cid_fname, len, ks_np_tid->erk, KEYBITS(0x10));
//Create control info hash.
aes_omac1(cinp->hash_ci, (u8 *)cinp, 0x60 /* Only the first 0x60 bytes are hashed. */ , ci_key, KEYBITS(0x10));
return TRUE;
}
//TODO: The fwrite/fread error checking was broken.
//Maybe the MS runtime is returning the number of bytes written instead of the element count?
BOOL np_sign_file(s8 *fname)
{
u8 padding_data[0x10] =
{
0xbc, 0x3f, 0x7a, 0x48, 0xaf, 0x45, 0xef, 0x28, 0x3a, 0x05, 0x98, 0x10, 0xbc, 0x3f, 0x7a, 0x48
};
keyset_t *ks;
FILE *fp = NULL;
u8 *buffer = NULL;
u32 length;
u32 padding;
u8 hash[0x14], R[0x15], S[0x15];
//Try to find keyset.
if((ks = keyset_find_by_name(CONFIG_NP_SIG_KNAME)) == NULL)
return FALSE;
if((fp = fopen(fname, "r+b")) == NULL)
return FALSE;
fseek(fp, 0, SEEK_END);
length = ftell(fp);
padding = length % 0x10;
if(padding > 0)
{
fwrite(padding_data, sizeof(u8), padding, fp);
length += padding;
}
fseek(fp, 0, SEEK_SET);
if((buffer = (u8 *)malloc(length)) == NULL)
{
fclose(fp);
return FALSE;
}
fread(buffer, sizeof(u8), length, fp);
//Generate header hash.
sha1(buffer, length, hash);
//Generate signature.
/* TODO: Set the right curve and private key */
ecdsa_set_curve(ks->ctype | USE_VSH_CURVE);
ecdsa_set_pub(ks->pub);
ecdsa_set_priv(ks->priv);
ecdsa_sign(hash, R, S);
fseek(fp, 0, SEEK_END);
fwrite(R + 1, 0x14, 1, fp);
fwrite(S + 1, 0x14, 1, fp);
/* Let's be as stupid as sony here... */
fwrite(hash + 0xC, 8, 1, fp);
free(buffer);
fclose(fp);
return TRUE;
}

42
np.h Normal file
View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _NP_H_
#define _NP_H_
#include "types.h"
#include "sce.h"
/*! NPDRM config. */
typedef struct _npdrm_config
{
/*! License type. */
u32 license_type;
/*! Application type. */
u32 app_type;
/*! klicensee. */
u8 *klicensee;
/*! Content ID. */
u8 content_id[0x30];
/*! Real file name. */
s8 *real_fname;
} npdrm_config_t;
/*! Set klicensee. */
void np_set_klicensee(u8 *klicensee);
/*! Remove NPDRM layer. */
BOOL np_decrypt_npdrm(sce_buffer_ctxt_t *ctxt);
/*! Add NPDRM layer. */
BOOL np_encrypt_npdrm(sce_buffer_ctxt_t *ctxt);
/*! Create NPDRM control info. */
BOOL np_create_ci(npdrm_config_t *npconf, ci_data_npdrm_t *cinp);
/*! Add NP signature to file. */
BOOL np_sign_file(s8 *fname);
#endif

6
pkg.cpp Normal file
View file

@ -0,0 +1,6 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdio.h>

12
pkg.h Normal file
View file

@ -0,0 +1,12 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _PKG_H_
#define _PKG_H_
#include "types.h"
#include "sce.h"
#endif

123
rvk.cpp Normal file
View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdio.h>
#include "types.h"
#include "util.h"
#include "sce.h"
#include "rvk.h"
#include "tables.h"
static void _print_rvk_header(FILE *fp, rvk_header_t *h)
{
fprintf(fp, "[*] Revoke List Header:\n");
fprintf(fp, " type_0 0x%08X\n", h->type_0);
fprintf(fp, " type_1 0x%08X\n", h->type_1);
if(h->type_0 == 4)
fprintf(fp, " Version %s\n", sce_version_to_str(h->opaque));
else
fprintf(fp, " Opaque 0x%016llX\n", h->opaque);
fprintf(fp, " Entry Count 0x%08X\n", h->entcnt);
}
/*
typedef struct _prg_rvk_entry
{
u32 self_type; //3, 4
u32 unk_1; //1, 3
union
{
u64 version; //unk_1 == 1
u64 unk_2; //unk_1 == 3
};
union
{
u64 auth_id;
u64 unk_3;
};
u8 unk_4[8];
} prg_rvk_entry_t;
*/
static void _print_prg_rvk_entry_header(FILE *fp)
{
fprintf(fp, "[*] Program Revoke List Entries:\n");
fprintf(fp, " Type Check Version Auth-ID/unk_3 Mask\n");
}
static id_to_name_t _check_type_values[] =
{
{CHECK_SELF_NEQU_RVK, "!="},
{CHECK_SELF_EQU_RVK, "=="},
{CHECK_SELF_LT_RVK, "<"},
{CHECK_SELF_LTEQU_RVK, "<="},
{CHECK_SELF_GT_RVK, ">"},
{CHECK_SELF_GTEQU_RVK, ">="},
{0, NULL}
};
static void _print_prg_rvk_entry(FILE *fp, prg_rvk_entry_t *e)
{
const s8 *name;
name = _get_name(_self_types, e->self_type);
if(name != NULL)
fprintf(fp, " %-19s ", name);
else
fprintf(fp, " 0x%08X ", e->self_type);
name = _get_name(_check_type_values, e->check_type);
if(name != NULL)
fprintf(fp, "%-2s ", name);
else
fprintf(fp, "%08X ", e->check_type);
fprintf(fp, "%s ", sce_version_to_str(e->version));
name = _get_name(_auth_ids, e->auth_id);
if(name != NULL)
fprintf(fp, "%-16s ", name);
else
fprintf(fp, "%016llX ", e->auth_id);
fprintf(fp, "%016llX ", e->mask);
fprintf(fp, "\n");
}
void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt)
{
u32 i;
rvk_header_t *rvkh = (rvk_header_t *)(ctxt->scebuffer + ctxt->metash[0].data_offset);
_es_rvk_header(rvkh);
_print_rvk_header(fp, rvkh);
//Program revoke.
if(rvkh->type_0 == 4)
{
prg_rvk_entry_t *ent = (prg_rvk_entry_t *)(ctxt->scebuffer + ctxt->metash[1].data_offset);
_print_prg_rvk_entry_header(fp);
for(i = 0; i < rvkh->entcnt; i++)
{
_es_prg_rvk_entry(&ent[i]);
_print_prg_rvk_entry(fp, &ent[i]);
}
}
else if(rvkh->type_0 == 3)
{
fprintf(fp, "[*] Package Revoke List Entries:\n");
u8 *ent = (u8 *)(ctxt->scebuffer + ctxt->metash[1].data_offset);
for(i = 0; i < rvkh->entcnt; i++)
{
_hexdump(fp, " ent", i*0x20, ent, 0x20, TRUE);
ent += 0x20;
}
}
}

84
rvk.h Normal file
View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _RVK_H_
#define _RVK_H_
#include "types.h"
#include "sce.h"
/*
header:
00000200 00 00 00 04 00 00 00 01 00 03 00 41 00 00 00 00
00000210 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00
body:
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
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
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
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
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
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
*/
/*
0 self != rvk
1 self == rvk
2 !(rvk <= self) -> self < rvk
3 self <= rvk
4 !(self <= rvk) -> self > rvk
5 rvk <= self -> self >= rvk
*/
#define CHECK_SELF_NEQU_RVK 0
#define CHECK_SELF_EQU_RVK 1
#define CHECK_SELF_LT_RVK 2
#define CHECK_SELF_LTEQU_RVK 3
#define CHECK_SELF_GT_RVK 4
#define CHECK_SELF_GTEQU_RVK 5
/*! RVK header. */
typedef struct _rvk_header
{
u32 type_0;
u32 type_1;
u64 opaque; //Program revoke: version, Package revoke: unknown.
u32 entcnt;
u8 padding[12];
} rvk_header_t;
static inline void _es_rvk_header(rvk_header_t *h)
{
h->type_0 = _ES32(h->type_0);
h->type_1 = _ES32(h->type_1);
h->opaque = _ES64(h->opaque);
h->entcnt = _ES32(h->entcnt);
}
/*! Program revoke list entry. */
typedef struct _prg_rvk_entry
{
u32 self_type; //3, 4
u32 check_type;
u64 version;
union
{
u64 auth_id;
u64 unk_3;
};
u64 mask;
} prg_rvk_entry_t;
static inline void _es_prg_rvk_entry(prg_rvk_entry_t *e)
{
e->self_type = _ES32(e->self_type);
e->check_type = _ES32(e->check_type);
e->version = _ES64(e->version);
e->auth_id = _ES64(e->auth_id);
e->mask = _ES64(e->mask);
}
/*! Print RVK infos. */
void rvk_print(FILE *fp, sce_buffer_ctxt_t *ctxt);
#endif

1001
sce.cpp Normal file

File diff suppressed because it is too large Load diff

616
sce.h Normal file
View file

@ -0,0 +1,616 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _SCE_H_
#define _SCE_H_
#include <stdio.h>
#include <string.h>
#include "types.h"
#include "list.h"
/*! SCE file align. */
#define SCE_ALIGN 0x10
/*! Header align. */
#define HEADER_ALIGN 0x80
/*! SCE header magic value ("SCE\0"). */
#define SCE_HEADER_MAGIC 0x53434500
/*! SCE header versions. */
/*! Header version 2. */
#define SCE_HEADER_VERSION_2 2
/*! Key revisions. */
#define KEY_REVISION_0 0x00
#define KEY_REVISION_092_330 0x01
#define KEY_REVISION_1 0x02
//#define KEY_REVISION_ 0x03
#define KEY_REVISION_340_342 0x04
//#define KEY_REVISION_ 0x05
//#define KEY_REVISION_ 0x06
#define KEY_REVISION_350 0x07
//#define KEY_REVISION_ 0x08
//#define KEY_REVISION_ 0x09
#define KEY_REVISION_355 0x0a
//#define KEY_REVISION_ 0x0b
//#define KEY_REVISION_ 0x0c
#define KEY_REVISION_356 0x0d
//#define KEY_REVISION_ 0x0e
//#define KEY_REVISION_ 0x0f
#define KEY_REVISION_360_361 0x10
//#define KEY_REVISION_ 0x11
//#define KEY_REVISION_ 0x12
#define KEY_REVISION_365 0x13
//#define KEY_REVISION_ 0x14
//#define KEY_REVISION_ 0x15
#define KEY_REVISION_370_373 0x16
//#define KEY_REVISION_ 0x17
//#define KEY_REVISION_ 0x18
#define KEY_REVISION_DEBUG 0x8000
/*! SCE header types. */
/*! SELF header. */
#define SCE_HEADER_TYPE_SELF 1
/*! RVK header. */
#define SCE_HEADER_TYPE_RVK 2
/*! PKG header. */
#define SCE_HEADER_TYPE_PKG 3
/*! SPP header. */
#define SCE_HEADER_TYPE_SPP 4
/*! Sub header types. */
/*! SCE version header. */
#define SUB_HEADER_TYPE_SCEVERSION 1
/*! SELF header. */
#define SUB_HEADER_TYPE_SELF 3
/*! Control info types. */
/*! Control flags. */
#define CONTROL_INFO_TYPE_FLAGS 1
/*! Digest. */
#define CONTROL_INFO_TYPE_DIGEST 2
/*! NPDRM block. */
#define CONTROL_INFO_TYPE_NPDRM 3
/*! Optional header types. */
/*! Capability flags header. */
#define OPT_HEADER_TYPE_CAP_FLAGS 1
/*! Individuals seed header. */
#define OPT_HEADER_TYPE_INDIV_SEED 2
/*! Metadata key/iv lengths. */
#define METADATA_INFO_KEYBITS 128
#define METADATA_INFO_KEY_LEN 16
#define METADATA_INFO_KEYPAD_LEN 16
#define METADATA_INFO_IV_LEN 16
#define METADATA_INFO_IVPAD_LEN 16
/*! Metadata section types. */
/*! Segment header. */
#define METADATA_SECTION_TYPE_SHDR 1
/*! Program header. */
#define METADATA_SECTION_TYPE_PHDR 2
/*! Unknown header type 3. */
#define METADATA_SECTION_TYPE_UNK_3 3
/*! Section is hashed. */
#define METADATA_SECTION_HASHED 2
/*! Section is not encrypted. */
#define METADATA_SECTION_NOT_ENCRYPTED 1
/*! Section is encrypted. */
#define METADATA_SECTION_ENCRYPTED 3
/*! Section is not compressed. */
#define METADATA_SECTION_NOT_COMPRESSED 1
/*! Section is compressed. */
#define METADATA_SECTION_COMPRESSED 2
/*! Signature sizes. */
/*! Signature S part size. */
#define SIGNATURE_S_SIZE 21
/*! Signature R part size. */
#define SIGNATURE_R_SIZE 21
/*! Compressed. */
#define SECTION_INFO_COMPRESSED 2
/*! Not compressed. */
#define SECTION_INFO_NOT_COMPRESSED 1
/*! SCE version not present. */
#define SCE_VERSION_NOT_PRESENT 0
/*! SCE version present. */
#define SCE_VERSION_PRESENT 1
/*! SELF types. */
/*! lv0. */
#define SELF_TYPE_LV0 1
/*! lv1. */
#define SELF_TYPE_LV1 2
/*! lv2. */
#define SELF_TYPE_LV2 3
/*! Application. */
#define SELF_TYPE_APP 4
/*! Isolated SPU module. */
#define SELF_TYPE_ISO 5
/*! Secure loader. */
#define SELF_TYPE_LDR 6
/*! Unknown type 7. */
#define SELF_TYPE_UNK_7 7
/*! NPDRM application. */
#define SELF_TYPE_NPDRM 8
/*! NPDRM control info magic value ("NPD\0"). */
#define NP_CI_MAGIC 0x4E504400
/*! NPDRM license types. */
#define NP_LICENSE_NETWORK 1
#define NP_LICENSE_LOCAL 2
#define NP_LICENSE_FREE 3
/*! NPDRM application types. */
#define NP_TYPE_UPDATE 0x20
#define NP_TYPE_SPRX 0
#define NP_TYPE_EXEC 1
#define NP_TYPE_USPRX (NP_TYPE_UPDATE | NP_TYPE_SPRX)
#define NP_TYPE_UEXEC (NP_TYPE_UPDATE | NP_TYPE_EXEC)
/*! SCE header. */
typedef struct _sce_header
{
/*! Magic value. */
u32 magic;
/*! Header version .*/
u32 version;
/*! Key revision. */
u16 key_revision;
/*! Header type. */
u16 header_type;
/*! Metadata offset. */
u32 metadata_offset;
/*! Header length. */
u64 header_len;
/*! Length of encapsulated data. */
u64 data_len;
} sce_header_t;
/*! SELF header. */
typedef struct _self_header
{
/*! Header type. */
u64 header_type;
/*! Application info offset. */
u64 app_info_offset;
/*! ELF offset. */
u64 elf_offset;
/*! Program headers offset. */
u64 phdr_offset;
/*! Section headers offset. */
u64 shdr_offset;
/*! Section info offset. */
u64 section_info_offset;
/*! SCE version offset. */
u64 sce_version_offset;
/*! Control info offset. */
u64 control_info_offset;
/*! Control info size. */
u64 control_info_size;
/*! Padding. */
u64 padding;
} self_header_t;
/*! Metadata info. */
typedef struct _metadata_info
{
/*! Key. */
u8 key[METADATA_INFO_KEY_LEN];
/*! Key padding. */
u8 key_pad[METADATA_INFO_KEYPAD_LEN];
/*! IV. */
u8 iv[METADATA_INFO_IV_LEN];
/*! IV padding. */
u8 iv_pad[METADATA_INFO_IVPAD_LEN];
} metadata_info_t;
typedef struct _metadata_header
{
/*! Signature input length. */
u64 sig_input_length;
u32 unknown_0;
/*! Section count. */
u32 section_count;
/*! Key count. */
u32 key_count;
/*! Optional header size. */
u32 opt_header_size;
u32 unknown_1;
u32 unknown_2;
} metadata_header_t;
/*! Metadata section header. */
typedef struct _metadata_section_header
{
/*! Data offset. */
u64 data_offset;
/*! Data size. */
u64 data_size;
/*! Type. */
u32 type;
/*! Index. */
u32 index;
/*! Hashed. */
u32 hashed;
/*! SHA1 index. */
u32 sha1_index;
/*! Encrypted. */
u32 encrypted;
/*! Key index. */
u32 key_index;
/*! IV index. */
u32 iv_index;
/*! Compressed. */
u32 compressed;
} metadata_section_header_t;
/*! SCE file signature. */
typedef struct _signature
{
u8 r[SIGNATURE_R_SIZE];
u8 s[SIGNATURE_S_SIZE];
u8 padding[6];
} signature_t;
/*! Section info. */
typedef struct _section_info
{
u64 offset;
u64 size;
u32 compressed;
u32 unknown_0;
u32 unknown_1;
u32 encrypted;
} section_info_t;
/*! SCE version. */
typedef struct _sce_version
{
/*! Header type. */
u32 header_type;
/*! SCE version section present? */
u32 present;
/*! Size. */
u32 size;
u32 unknown_3;
} sce_version_t;
/*! SCE version data 0x30. */
typedef struct _sce_version_data_30
{
u16 unknown_1; //Dunno.
u16 unknown_2; //0x0001
u32 unknown_3; //Padding?
u32 unknown_4; //Number of sections?
u32 unknown_5; //Padding?
/*! Data offset. */
u64 offset;
/*! Data size. */
u64 size;
} sce_version_data_30_t;
//(auth_id & AUTH_ONE_MASK) has to be 0x1000000000000000
#define AUTH_ONE_MASK 0xF000000000000000
#define AUTH_TERRITORY_MASK 0x0FF0000000000000
#define VENDOR_TERRITORY_MASK 0xFF000000
#define VENDOR_ID_MASK 0x00FFFFFF
/*! Application info. */
typedef struct _app_info
{
/*! Auth ID. */
u64 auth_id;
/*! Vendor ID. */
u32 vendor_id;
/*! SELF type. */
u32 self_type;
/*! Version. */
u64 version;
/*! Padding. */
u64 padding;
} app_info_t;
/*! Control info. */
typedef struct _control_info
{
/*! Control info type. */
u32 type;
/*! Size of following data. */
u32 size;
/*! Next flag (1 if another info follows). */
u64 next;
} control_info_t;
#define CI_FLAG_00_80 0x80
#define CI_FLAG_00_40 0x40 //root access
#define CI_FLAG_00_20 0x20 //kernel access
#define CI_FLAG_17_01 0x01
#define CI_FLAG_17_02 0x02
#define CI_FLAG_17_04 0x04
#define CI_FLAG_17_08 0x08
#define CI_FLAG_17_10 0x10
//1B:
//bdj 0x01, 0x09
//psp_emu 0x08
//psp_transl 0x0C
#define CI_FLAG_1B_01 0x01 //may use shared mem?
#define CI_FLAG_1B_02 0x02
#define CI_FLAG_1B_04 0x04
#define CI_FLAG_1B_08 0x08 //ss
#define CI_FLAG_1F_SHAREABLE 0x01
#define CI_FLAG_1F_02 0x02 //internal?
#define CI_FLAG_1F_FACTORY 0x04
#define CI_FLAG_1F_08 0x08 //???
/*! Control info data flags. */
typedef struct _ci_data_flags
{
u8 data[0x20];
} ci_data_flags_t;
/*! Control info data digest 0x30. */
typedef struct _ci_data_digest_30
{
u8 digest[20];
u64 unknown_0;
} ci_data_digest_30_t;
/*! Control info data digest 0x40. */
typedef struct _ci_data_digest_40
{
u8 digest1[20];
u8 digest2[20];
u64 fw_version;
} ci_data_digest_40_t;
/*! Control info data NPDRM. */
typedef struct _ci_data_npdrm
{
/*! Magic. */
u32 magic;
u32 unknown_0;
/*! License type. */
u32 license_type;
/*! Application type. */
u32 app_type;
/*! Content ID. */
u8 content_id[0x30];
/*! Random padding. */
u8 rndpad[0x10];
/*! ContentID_FileName hash. */
u8 hash_cid_fname[0x10];
/*! Control info hash. */
u8 hash_ci[0x10];
u64 unknown_1;
u64 unknown_2;
} ci_data_npdrm_t;
/*! Optional header. */
typedef struct _opt_header
{
/*! Type. */
u32 type;
/*! Size. */
u32 size;
/*! Next flag (1 if another header follows). */
u64 next;
} opt_header_t;
/*! Capability flags. */
#define CAP_FLAG_1 0x01 //only seen in PPU selfs
#define CAP_FLAG_2 0x02 //only seen in PPU selfs
#define CAP_FLAG_4 0x04 //only seen in bdj PPU self
#define CAP_FLAG_REFTOOL 0x08
#define CAP_FLAG_DEBUG 0x10
#define CAP_FLAG_RETAIL 0x20
#define CAP_FLAG_SYSDBG 0x40
#define UNK7_2000 0x2000 //hddbind?
#define UNK7_20000 0x20000 //flashbind?
#define UNK7_40000 0x40000 //discbind?
#define UNK7_80000 0x80000
#define UNK7_PS3SWU 0x116000 //dunno...
/*! SCE file capability flags. */
typedef struct _oh_data_cap_flags
{
u64 unk3; //0
u64 unk4; //0
/*! Flags. */
u64 flags;
u32 unk6;
u32 unk7;
} oh_data_cap_flags_t;
/*! Section context. */
typedef struct _sce_section_ctxt
{
/*! Data buffer. */
void *buffer;
/*! Size. */
u32 size;
/*! Offset. */
u32 offset;
/*! May be compressed. */
BOOL may_compr;
} sce_section_ctxt_t;
typedef struct _makeself_ctxt
{
/*! ELF file buffer (for ELF -> SELF). */
u8 *elf;
/*! ELF file length. */
u32 elf_len;
/*! ELF header. */
void *ehdr;
/*! ELF header size. */
u32 ehsize;
/*! Program headers. */
void *phdrs;
/*! Program headers size. */
u32 phsize;
/*! Section headers. */
void *shdrs;
/*! Section headers size. */
u32 shsize;
/*! Section info count. */
u32 si_cnt;
/*! Number of section infos that are present as data sections. */
u32 si_sec_cnt;
} makeself_ctxt_t;
/*! SCE file buffer context. */
typedef struct _sce_buffer_ctxt
{
/*! SCE file buffer. */
u8 *scebuffer;
/*! SCE header. */
sce_header_t *sceh;
/*! File type dependent header. */
union
{
struct
{
/*! SELF header. */
self_header_t *selfh;
/*! Application info. */
app_info_t *ai;
/*! Section info. */
section_info_t *si;
/*! SCE version. */
sce_version_t *sv;
/*! Control infos. */
list_t *cis;
/*! Optional headers. */
list_t *ohs;
} self;
};
/*! Metadata info. */
metadata_info_t *metai;
/*! Metadata header. */
metadata_header_t *metah;
/*! Metadata section headers. */
metadata_section_header_t *metash;
/*! SCE file keys. */
u8 *keys;
/*! Keys length. */
u32 keys_len;
/*! Signature. */
signature_t *sig;
/*! Metadata decrypted? */
BOOL mdec;
/*! Data layout. */
/*! SCE header offset. */
u32 off_sceh;
union
{
struct
{
/*! SELF header offset. */
u32 off_selfh;
/*! Application info offset. */
u32 off_ai;
/*! ELF header offset. */
u32 off_ehdr;
/*! Program header offset. */
u32 off_phdr;
/*! Section info offset. */
u32 off_si;
/*! SCE version offset. */
u32 off_sv;
/*! Control infos offset. */
u32 off_cis;
/*! Optional headers offset. */
u32 off_ohs;
} off_self;
};
/*! Metadata info offset. */
u32 off_metai;
/*! Metadata header offset. */
u32 off_metah;
/*! Metadata section headers offset. */
u32 off_metash;
/*! Keys offset. */
u32 off_keys;
/*! Signature offset. */
u32 off_sig;
/*! Header padding end offset. */
u32 off_hdrpad;
/*! File creation type dependent data. */
union
{
/*! ELF -> SELF. */
makeself_ctxt_t *makeself;
};
/*! Data sections. */
list_t *secs;
} sce_buffer_ctxt_t;
/*! Create SCE file context from SCE file buffer. */
sce_buffer_ctxt_t *sce_create_ctxt_from_buffer(u8 *scebuffer);
/*! Create SCE file context for SELF creation. */
sce_buffer_ctxt_t *sce_create_ctxt_build_self(u8 *elf, u32 elf_len);
/*! Add data section to SCE context. */
void sce_add_data_section(sce_buffer_ctxt_t *ctxt, void *buffer, u32 size, BOOL may_compr);
/*! Set metadata section header. */
void sce_set_metash(sce_buffer_ctxt_t *ctxt, u32 type, BOOL encrypted, u32 idx);
/*! Compress data. */
void sce_compress_data(sce_buffer_ctxt_t *ctxt);
/*! Layout offsets for SCE file creation. */
void sce_layout_ctxt(sce_buffer_ctxt_t *ctxt);
/*! Encrypt context. */
BOOL sce_encrypt_ctxt(sce_buffer_ctxt_t *ctxt, u8 *keyset);
/*! Write context to file. */
BOOL sce_write_ctxt(sce_buffer_ctxt_t *ctxt, s8 *fname);
/*! Decrypt header (use passed metadata_into if not NULL). */
BOOL sce_decrypt_header(sce_buffer_ctxt_t *ctxt, u8 *metadata_info, u8 *keyset);
/*! Decrypt data. */
BOOL sce_decrypt_data(sce_buffer_ctxt_t *ctxt);
/*! Print SCE file info. */
void sce_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt);
/*! Get version string from version. */
s8 *sce_version_to_str(u64 version);
/*! Get version from version string. */
u64 sce_str_to_version(s8 *version);
/*! Convert hex version to dec version. */
u64 sce_hexver_to_decver(u64 version);
/*! Get control info. */
control_info_t *sce_get_ctrl_info(sce_buffer_ctxt_t *ctxt, u32 type);
/*! Get optional header. */
opt_header_t *sce_get_opt_header(sce_buffer_ctxt_t *ctxt, u32 type);
#endif

201
sce_inlines.h Normal file
View file

@ -0,0 +1,201 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _SCE_INLINES_H_
#define _SCE_INLINES_H_
#include <string.h>
#include "types.h"
#include "sce.h"
static inline void _es_sce_header(sce_header_t *h)
{
h->magic = _ES32(h->magic);
h->version = _ES32(h->version);
h->key_revision = _ES16(h->key_revision);
h->header_type = _ES16(h->header_type);
h->metadata_offset = _ES32(h->metadata_offset);
h->header_len = _ES64(h->header_len);
h->data_len = _ES64(h->data_len);
}
static inline void _copy_es_sce_header(sce_header_t *dst, sce_header_t *src)
{
memcpy(dst, src, sizeof(sce_header_t));
_es_sce_header(dst);
}
static inline void _es_metadata_header(metadata_header_t *h)
{
h->sig_input_length = _ES64(h->sig_input_length);
h->unknown_0 = _ES32(h->unknown_0);
h->section_count = _ES32(h->section_count);
h->key_count = _ES32(h->key_count);
h->opt_header_size = _ES32(h->opt_header_size);
h->unknown_1 = _ES32(h->unknown_1);
h->unknown_2 = _ES32(h->unknown_2);
}
static inline void _copy_es_metadata_header(metadata_header_t *dst, metadata_header_t *src)
{
memcpy(dst, src, sizeof(metadata_header_t));
_es_metadata_header(dst);
}
static inline void _es_metadata_section_header(metadata_section_header_t *h)
{
h->data_offset = _ES64(h->data_offset);
h->data_size = _ES64(h->data_size);
h->type = _ES32(h->type);
h->index = _ES32(h->index);
h->hashed = _ES32(h->hashed);
h->sha1_index = _ES32(h->sha1_index);
h->encrypted = _ES32(h->encrypted);
h->key_index = _ES32(h->key_index);
h->iv_index = _ES32(h->iv_index);
h->compressed = _ES32(h->compressed);
}
static inline void _copy_es_metadata_section_header(metadata_section_header_t *dst, metadata_section_header_t *src)
{
memcpy(dst, src, sizeof(metadata_section_header_t));
_es_metadata_section_header(dst);
}
static inline void _es_self_header(self_header_t *h)
{
h->header_type = _ES64(h->header_type);
h->app_info_offset = _ES64(h->app_info_offset);
h->elf_offset = _ES64(h->elf_offset);
h->phdr_offset = _ES64(h->phdr_offset);
h->shdr_offset = _ES64(h->shdr_offset);
h->section_info_offset = _ES64(h->section_info_offset);
h->sce_version_offset = _ES64(h->sce_version_offset);
h->control_info_offset = _ES64(h->control_info_offset);
h->control_info_size = _ES64(h->control_info_size);
h->padding = _ES64(h->padding);
}
static inline void _copy_es_self_header(self_header_t *dst, self_header_t *src)
{
memcpy(dst, src, sizeof(self_header_t));
_es_self_header(dst);
}
static inline void _es_section_info(section_info_t *si)
{
si->offset = _ES64(si->offset);
si->size = _ES64(si->size);
si->compressed = _ES32(si->compressed);
si->unknown_0 = _ES32(si->unknown_0);
si->unknown_1 = _ES32(si->unknown_1);
si->encrypted = _ES32(si->encrypted);
}
static inline void _copy_es_section_info(section_info_t *dst, section_info_t *src)
{
memcpy(dst, src, sizeof(section_info_t));
_es_section_info(dst);
}
static inline void _es_sce_version(sce_version_t *sv)
{
sv->header_type = _ES32(sv->header_type);
sv->present = _ES32(sv->present);
sv->size = _ES32(sv->size);
sv->unknown_3 = _ES32(sv->unknown_3);
}
static inline void _copy_es_sce_version(sce_version_t *dst, sce_version_t *src)
{
memcpy(dst, src, sizeof(sce_version_t));
_es_sce_version(dst);
}
static inline void _es_app_info(app_info_t *ai)
{
ai->auth_id = _ES64(ai->auth_id);
ai->vendor_id = _ES32(ai->vendor_id);
ai->self_type = _ES32(ai->self_type);
ai->version = _ES64(ai->version);
ai->padding = _ES64(ai->padding);
}
static inline void _copy_es_app_info(app_info_t *dst, app_info_t *src)
{
memcpy(dst, src, sizeof(app_info_t));
_es_app_info(dst);
}
static inline void _es_control_info(control_info_t *ci)
{
ci->type = _ES32(ci->type);
ci->size = _ES32(ci->size);
ci->next = _ES64(ci->next);
}
static inline void _copy_es_control_info(control_info_t *dst, control_info_t *src)
{
memcpy(dst, src, sizeof(control_info_t));
_es_control_info(dst);
}
static inline void _es_ci_data_digest_40(ci_data_digest_40_t *dig)
{
dig->fw_version = _ES64(dig->fw_version);
}
static inline void _copy_es_ci_data_digest_40(ci_data_digest_40_t *dst, ci_data_digest_40_t *src)
{
memcpy(dst, src, sizeof(ci_data_digest_40_t));
_es_ci_data_digest_40(dst);
}
static inline void _es_ci_data_npdrm(ci_data_npdrm_t *np)
{
np->magic = _ES32(np->magic);
np->unknown_0 = _ES32(np->unknown_0);
np->license_type = _ES32(np->license_type);
np->app_type = _ES32(np->app_type);
np->unknown_1 = _ES64(np->unknown_1);
np->unknown_2 = _ES64(np->unknown_2);
}
static inline void _copy_es_ci_data_npdrm(ci_data_npdrm_t *dst, ci_data_npdrm_t *src)
{
memcpy(dst, src, sizeof(ci_data_npdrm_t));
_es_ci_data_npdrm(dst);
}
static inline void _es_opt_header(opt_header_t *oh)
{
oh->type = _ES32(oh->type);
oh->size = _ES32(oh->size);
oh->next = _ES64(oh->next);
}
static inline void _copy_es_opt_header(opt_header_t *dst, opt_header_t *src)
{
memcpy(dst, src, sizeof(opt_header_t));
_es_opt_header(dst);
}
static inline void _es_oh_data_cap_flags(oh_data_cap_flags_t *cf)
{
cf->unk3 = _ES64(cf->unk3);
cf->unk4 = _ES64(cf->unk4);
cf->flags = _ES64(cf->flags);
cf->unk6 = _ES32(cf->unk6);
cf->unk7 = _ES32(cf->unk7);
}
static inline void _copy_es_cap_flags(oh_data_cap_flags_t *dst, oh_data_cap_flags_t *src)
{
memcpy(dst, src, sizeof(oh_data_cap_flags_t));
_es_oh_data_cap_flags(dst);
}
#endif

1082
self.cpp Normal file

File diff suppressed because it is too large Load diff

72
self.h Normal file
View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _SELF_H_
#define _SELF_H_
#include "types.h"
#include "config.h"
#include "np.h"
/*! PS3 specific ELF constants. */
/*! LV2 OS ABI. */
#define ELFOSABI_CELL_LV2 0x66
/*! PRX ELF type. */
#define ET_PS3PRX 0xFFA4
/*! PS3 Params. */
#define PT_PS3_PARAMS 0x60000001
/*! PS3 PRX. */
#define PT_PS3_PRX 0x60000002
/*! PRX Relocations. */
#define PT_PS3_PRX_RELOC 0x700000A4
/*! SELF config. */
typedef struct _self_config
{
/*! Add section headers. */
BOOL add_shdrs;
/*! Compress data. */
BOOL compress_data;
/*! Skip sections. */
BOOL skip_sections;
/*! Key revision. */
u16 key_revision;
/*! Auth ID. */
u64 auth_id;
/*! Vendor ID. */
u32 vendor_id;
/*! SELF type. */
u32 self_type;
/*! Application version. */
u64 app_version;
/*! Firmware version. */
u64 fw_version;
/*! Control flags. */
u8 *ctrl_flags;
/*! Capability flags. */
u8 *cap_flags;
#ifdef CONFIG_CUSTOM_INDIV_SEED
/*! Individuals seed. */
u8 *indiv_seed;
/*! Individuals seed size. */
u32 indiv_seed_size;
#endif
/*! NPDRM config (used if not NULL). */
npdrm_config_t *npdrm_config;
} self_config_t;
/*! Print SELF info. */
BOOL self_print_info(FILE *fp, sce_buffer_ctxt_t *ctxt);
/*! Create ELF from SELF. */
BOOL self_write_to_elf(sce_buffer_ctxt_t *ctxt, const s8 *elf_out);
/*! Create SELF from ELF. */
BOOL self_build_self(sce_buffer_ctxt_t *ctxt, self_config_t *sconf);
#endif

399
sha1.c Normal file
View file

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

133
sha1.h Normal file
View file

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

76
spp.cpp Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdio.h>
#include "types.h"
#include "sce.h"
#include "spp.h"
#include "util.h"
static void _print_spp_header(FILE *fp, spp_header_t *h)
{
fprintf(fp, "[*] SPP Header:\n");
fprintf(fp, " unk1 0x%04X\n", h->unk1);
fprintf(fp, " unk2 0x%04X\n", h->unk2);
fprintf(fp, " SPP Size 0x%08X\n", h->spp_size);
fprintf(fp, " unk3 0x%08X\n", h->unk3);
fprintf(fp, " unk4 0x%08X\n", h->unk4);
fprintf(fp, " unk5 0x%016llX\n", h->unk5);
fprintf(fp, " Entry Count 0x%08X\n", h->entcnt);
fprintf(fp, " unk7 0x%08X\n", h->unk7);
}
static void _print_spp_entry_header(FILE *fp, spp_entry_header_t *h, u32 idx)
{
fprintf(fp, "[*] SPP Entry %02d:\n", idx);
fprintf(fp, " Size 0x%08X\n", h->entry_size);
fprintf(fp, " Type 0x%08X\n", h->type);
fprintf(fp, " LPAR Auth-ID 0x%016llX\n", h->laid);
fprintf(fp, " Program Auth-ID 0x%016llX\n", h->paid);
fprintf(fp, " Name %s\n", h->name);
}
void spp_print(FILE *fp, sce_buffer_ctxt_t *ctxt)
{
u32 i;
//First section contains the SPP header.
spp_header_t *header = (spp_header_t *)(ctxt->scebuffer + ctxt->metash[0].data_offset);
_es_spp_header(header);
//Second section contains the entries.
u8 *ent = ctxt->scebuffer + ctxt->metash[1].data_offset;
_print_spp_header(fp, header);
for(i = 0; i < header->entcnt; i++)
{
//Get current entry header.
spp_entry_header_t *eh = (spp_entry_header_t *)ent;
_es_spp_entry_header(eh);
//Print header.
_print_spp_entry_header(fp, eh, i);
//Print data.
_hexdump(fp, " Data", 0, ent + sizeof(spp_entry_header_t), eh->entry_size - sizeof(spp_entry_header_t), TRUE);
/*
switch(eh->type)
{
case SPP_ENTRY_TYPE_1:
break;
case SPP_ENTRY_TYPE_2:
break;
default:
printf("[*] Error: Unknown entry type 0x%08X (entry %02d)\n", eh->type, i);
}
*/
//Move pointer to next entry.
ent += eh->entry_size;
}
}

62
spp.h Normal file
View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _SPP_H_
#define _SPP_H_
#include "types.h"
#include "sce.h"
/*! SPP entry types. */
#define SPP_ENTRY_TYPE_1 1
#define SPP_ENTRY_TYPE_2 2
/*! SPP header. */
typedef struct _spp_header
{
u16 unk1;
u16 unk2;
u32 spp_size;
u32 unk3;
u32 unk4;
u64 unk5;
u32 entcnt;
u32 unk7;
} spp_header_t;
static inline void _es_spp_header(spp_header_t *h)
{
h->unk1 = _ES16(h->unk1);
h->unk2 = _ES16(h->unk2);
h->spp_size = _ES32(h->spp_size);
h->unk3 = _ES32(h->unk3);
h->unk4 = _ES32(h->unk4);
h->unk5 = _ES64(h->unk5);
h->entcnt = _ES32(h->entcnt);
h->unk7 = _ES32(h->unk7);
}
/*! SPP entry header. */
typedef struct _spp_entry_header
{
u32 entry_size;
u32 type;
u64 laid;
u64 paid;
u8 name[0x20];
} spp_entry_header_t;
static inline void _es_spp_entry_header(spp_entry_header_t *h)
{
h->entry_size = _ES32(h->entry_size);
h->type = _ES32(h->type);
h->laid = _ES64(h->laid);
h->paid = _ES64(h->paid);
}
/*! Print SPP infos. */
void spp_print(FILE *fp, sce_buffer_ctxt_t *ctxt);
#endif

259
tables.cpp Normal file
View file

@ -0,0 +1,259 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include "types.h"
#include "config.h"
#include "util.h"
#include "sce.h"
#include "elf.h"
#include "self.h"
#include "keys.h"
/*! SELF types. */
id_to_name_t _self_types[] =
{
{SELF_TYPE_LV0, "lv0"},
{SELF_TYPE_LV1, "lv1"},
{SELF_TYPE_LV2, "lv2"},
{SELF_TYPE_APP, "Application"},
{SELF_TYPE_ISO, "Isolated SPU Module"},
{SELF_TYPE_LDR, "Secure Loader"},
{SELF_TYPE_UNK_7, "Unknown 7"},
{SELF_TYPE_NPDRM, "NPDRM Application"},
{0, NULL}
};
/*! SELF types as parameter. */
id_to_name_t _self_types_params[] =
{
{SELF_TYPE_LV0, "LV0"},
{SELF_TYPE_LV1, "LV1"},
{SELF_TYPE_LV2, "LV2"},
{SELF_TYPE_APP, "APP"},
{SELF_TYPE_ISO, "ISO"},
{SELF_TYPE_LDR, "LDR"},
//{SELF_TYPE_UNK_7, "UNK7"},
{SELF_TYPE_NPDRM, "NPDRM"},
{0, NULL}
};
/* Control info types. */
id_to_name_t _control_info_types[] =
{
{CONTROL_INFO_TYPE_FLAGS, "Flags"},
{CONTROL_INFO_TYPE_DIGEST, "Digest"},
{CONTROL_INFO_TYPE_NPDRM, "NPDRM"},
{0, NULL}
};
/*! Optional header types. */
id_to_name_t _optional_header_types[] =
{
{OPT_HEADER_TYPE_CAP_FLAGS, "Capability Flags"},
#ifdef CONFIG_DUMP_INDIV_SEED
{OPT_HEADER_TYPE_INDIV_SEED, "Individuals Seed"},
#endif
{0, NULL}
};
/*! NPDRM application types. */
id_to_name_t _np_app_types[] =
{
{NP_TYPE_SPRX, "SPRX"},
{NP_TYPE_EXEC, "EXEC"},
{NP_TYPE_USPRX, "USPRX"},
{NP_TYPE_UEXEC, "UEXEC"},
{0, NULL},
};
/*! Auth IDs. */
id_to_name_t _auth_ids[] =
{
{0x1010000001000003, "retail game/update"},
{0x1020000401000001, "ps2emu"},
{0x1050000003000001, "lv2_kernel"},
{0x1070000001000002, "onicore_child"},
{0x1070000002000002, "mcore"},
{0x1070000003000002, "mgvideo"},
{0x1070000004000002, "swagner, swreset"},
{0x1070000017000001, "ss_init (lv1)"},
{0x107000001A000001, "ss_sc_init_pu (lv1)"},
{0x107000001C000001, "updater_frontend (lv1)"},
{0x107000001D000001, "sysmgr_ss (lv1)"},
{0x107000001F000001, "sb_iso_spu_module"},
{0x1070000020000001, "sc_iso, sc_iso_factory"},
{0x1070000021000001, "spp_verifier"},
{0x1070000022000001, "spu_pkg_rvk_verifier"},
{0x1070000023000001, "spu_token_processor"},
{0x1070000024000001, "sv_iso_spu_module"},
{0x1070000025000001, "aim_spu_module"},
{0x1070000026000001, "ss_sc_init"},
{0x1070000028000001, "factory_data_mngr_server (lv1)"},
{0x1070000029000001, "fdm_spu_module"},
{0x1070000032000001, "ss_server1 (lv1)"},
{0x1070000033000001, "ss_server2 (lv1)"},
{0x1070000034000001, "ss_server3 (lv1)"},
{0x1070000037000001, "mc_iso_spu_module"},
{0x1070000039000001, "bdp_bdmv"},
{0x107000003A000001, "bdj"},
{0x1070000040000001, "sys/external modules"},
{0x1070000041000001, "ps1emu"},
{0x1070000043000001, "me_iso_spu_module"},
{0x1070000046000001, "spu_mode_auth"},
{0x107000004C000001, "spu_utoken_processor"},
{0x1070000052000001, "sys/internal + vsh/module modules"},
{0x1070000055000001, "manu_info_spu_module"},
{0x1070000058000001, "me_iso_for_ps2emu"},
{0x1070000059000001, "sv_iso_for_ps2emu"},
{0x1070000300000001, "Lv2diag BD Remarry"},
{0x10700003FC000001, "emer_init"},
{0x10700003FD000001, "ps3swu"},
{0x10700003FF000001, "Lv2diag FW Stuff"},
{0x1070000409000001, "pspemu"},
{0x107000040A000001, "psp_translator"},
{0x107000040B000001, "pspemu modules"},
{0x107000040C000001, "pspemu drm"},
{0x1070000500000001, "cellftp"},
{0x1070000501000001, "hdd_copy"},
{0x10700005FC000001, "sys_audio"},
{0x10700005FD000001, "sys_init_osd"},
{0x10700005FF000001, "vsh"},
{0x1FF0000001000001, "lv0"},
{0x1FF0000002000001, "lv1"},
{0x1FF0000008000001, "lv1ldr"},
{0x1FF0000009000001, "lv2ldr"},
{0x1FF000000A000001, "isoldr"},
{0x1FF000000C000001, "appldr"},
{0, NULL}
};
/*! Vendor IDs. */
id_to_name_t _vendor_ids[] =
{
{0xFF000000, "hv"},
{0x07000001, "system"},
{0x01000002, "normal"},
{0x05000002, "lv2"},
{0x02000003, "ps2emu"},
{0, NULL}
};
/*! ELF machines. */
id_to_name_t _e_machines[] =
{
{EM_PPC, "PPC"},
{EM_PPC64, "PPC64"},
{EM_SPU, "SPU"},
{0, NULL}
};
/*! ELF types. */
id_to_name_t _e_types[] =
{
{ET_EXEC, "EXEC"},
{ET_PS3PRX, "PRX"},
{0, NULL}
};
/*! Section header types. */
id_to_name_t _sh_types[] =
{
{SHT_NULL, "NULL"},
{SHT_PROGBITS, "PROGBITS"},
{SHT_SYMTAB, "SYMTAB"},
{SHT_STRTAB, "STRTAB"},
{SHT_RELA, "RELA"},
{SHT_HASH, "HASH"},
{SHT_DYNAMIC, "DYNAMIC"},
{SHT_NOTE, "NOTE"},
{SHT_NOBITS, "NOBITS"},
{SHT_REL, "REL"},
{SHT_SHLIB, "SHLIB"},
{SHT_DYNSYM, "DYNSYM"},
{SHT_INIT_ARRAY, "INIT_ARRAY"},
{SHT_FINI_ARRAY, "FINI_ARRAY"},
{SHT_PREINIT_ARRAY, "PREINIT_ARRAY"},
{SHT_GROUP, "GROUP"},
{SHT_SYMTAB_SHNDX, "SYMTAB_SHNDX"},
{0, NULL}
};
/*! Program header types. */
id_to_name_t _ph_types[] =
{
{PT_NULL, "NULL"},
{PT_LOAD, "LOAD"},
{PT_DYNAMIC, "DYNAMIC"},
{PT_INTERP, "INTERP"},
{PT_NOTE, "NOTE"},
{PT_SHLIB, "SHLIB"},
{PT_PHDR, "PHDR"},
{PT_TLS, "TLS"},
{PT_NUM, "NUM"},
{PT_PS3_PARAMS, "PARAMS"},
{PT_PS3_PRX, "PRX"},
{PT_PS3_PRX_RELOC, "PRXRELOC"},
{0, NULL}
};
/*! Key types. */
id_to_name_t _key_types[] =
{
{KEYTYPE_SELF, "SELF"},
{KEYTYPE_RVK, "RVK"},
{KEYTYPE_PKG, "PKG"},
{KEYTYPE_SPP, "SPP"},
{KEYTYPE_OTHER, "OTHER"},
{0, NULL}
};
/*! Key revisions. */
/*
const s8 *_key_revisions[] =
{
"Revision 0",
"0.92 - 3.30",
"NP 0x02",
"NP 0x03",
"3.40 - 3.42",
"NP 0x05",
"NP 0x06",
"3.50",
"NP 0x08",
"NP 0x09",
"3.55",
"NP 0x0b",
"NP 0x0c",
"3.56",
"NP 0x0e",
"NP 0x0f",
"3.60 - 3.61",
"NP 0x11",
"NP 0x12",
"3.65",
"NP 0x14",
"NP 0x15",
"3.70 - 3.73",
"NP 0x17",
"NP 0x18",
"0x19",
"0x1A",
"0x1B",
"0x1C",
"0x1D",
"0x1E",
"0x1F"
};
*/
/*! SCE header types. */
id_to_name_t _sce_header_types[] =
{
{SCE_HEADER_TYPE_SELF, "SELF"},
{SCE_HEADER_TYPE_RVK, "RVK"},
{SCE_HEADER_TYPE_PKG, "PKG"},
{SCE_HEADER_TYPE_SPP, "SPP"},
{0, NULL}
};

54
tables.h Normal file
View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _TABLES_H_
#define _TABLES_H_
#include "types.h"
#include "util.h"
/*! SELF types. */
extern id_to_name_t _self_types[];
/*! SELF types as parameter. */
extern id_to_name_t _self_types_params[];
/* Control info types. */
extern id_to_name_t _control_info_types[];
/*! Optional header types. */
extern id_to_name_t _optional_header_types[];
/*! NPDRM application types. */
extern id_to_name_t _np_app_types[];
/*! Auth IDs. */
extern id_to_name_t _auth_ids[];
/*! Vendor IDs. */
extern id_to_name_t _vendor_ids[];
/*! ELF machines. */
extern id_to_name_t _e_machines[];
/*! ELF types. */
extern id_to_name_t _e_types[];
/*! Section header types. */
extern id_to_name_t _sh_types[];
/*! Program header types. */
extern id_to_name_t _ph_types[];
/*! Key types. */
extern id_to_name_t _key_types[];
/*! Key revisions. */
//extern const s8 *_key_revisions[];
/*! SCE header types. */
extern id_to_name_t _sce_header_types[];
#endif

63
types.h Normal file
View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef char s8;
typedef unsigned char u8;
typedef short s16;
typedef unsigned short u16;
typedef int s32;
typedef unsigned int u32;
#if defined(_WIN32) && defined(_MSC_VER)
typedef __int64 s64;
typedef unsigned __int64 u64;
#else
typedef long long int s64;
typedef unsigned long long int u64;
#endif
#define BOOL int
#define TRUE 1
#define FALSE 0
//Align.
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
//Bits <-> bytes conversion.
#define BITS2BYTES(x) ((x) / 8)
#define BYTES2BITS(x) ((x) * 8)
//Endian swap for u16.
#define _ES16(val) \
((u16)(((((u16)val) & 0xff00) >> 8) | \
((((u16)val) & 0x00ff) << 8)))
//Endian swap for u32.
#define _ES32(val) \
((u32)(((((u32)val) & 0xff000000) >> 24) | \
((((u32)val) & 0x00ff0000) >> 8 ) | \
((((u32)val) & 0x0000ff00) << 8 ) | \
((((u32)val) & 0x000000ff) << 24)))
//Endian swap for u64.
#define _ES64(val) \
((u64)(((((u64)val) & 0xff00000000000000ull) >> 56) | \
((((u64)val) & 0x00ff000000000000ull) >> 40) | \
((((u64)val) & 0x0000ff0000000000ull) >> 24) | \
((((u64)val) & 0x000000ff00000000ull) >> 8 ) | \
((((u64)val) & 0x00000000ff000000ull) << 8 ) | \
((((u64)val) & 0x0000000000ff0000ull) << 24) | \
((((u64)val) & 0x000000000000ff00ull) << 40) | \
((((u64)val) & 0x00000000000000ffull) << 56)))
#ifdef __cplusplus
}
#endif

250
util.cpp Normal file
View file

@ -0,0 +1,250 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "types.h"
#include "util.h"
#include "zlib.h"
#include "mt19937.h"
void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, BOOL print_addr)
{
int i, j, align = strlen(name) + 1;
fprintf(fp, "%s ", name);
if(print_addr == TRUE)
fprintf(fp, "%08x: ", offset);
for(i = 0; i < len; i++)
{
if(i % 16 == 0 && i != 0)
{
fprintf(fp, "\n");
for(j = 0; j < align; j++)
putchar(' ');
if(print_addr == TRUE)
fprintf(fp, "%08X: ", offset + i);
}
fprintf(fp, "%02X ", buf[i]);
}
fprintf(fp, "\n");
}
void _print_align(FILE *fp, const s8 *str, s32 align, s32 len)
{
s32 i, tmp;
tmp = align - len;
if(tmp < 0)
tmp = 0;
for(i = 0; i < tmp; i++)
fputs(str, fp);
}
u8 *_read_buffer(const s8 *file, u32 *length)
{
FILE *fp;
u32 size;
if((fp = fopen(file, "rb")) == NULL)
return NULL;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
u8 *buffer = (u8 *)malloc(sizeof(u8) * size);
fread(buffer, sizeof(u8), size, fp);
if(length != NULL)
*length = size;
fclose(fp);
return buffer;
}
int _write_buffer(const s8 *file, u8 *buffer, u32 length)
{
FILE *fp;
if((fp = fopen(file, "wb")) == NULL)
return 0;
/**/
while(length > 0)
{
u32 wrlen = 1024;
if(length < 1024)
wrlen = length;
fwrite(buffer, sizeof(u8), wrlen, fp);
length -= wrlen;
buffer += 1024;
}
/**/
//fwrite(buffer, sizeof(u8), length, fp);
fclose(fp);
return 1;
}
const s8 *_get_name(id_to_name_t *tab, u64 id)
{
u32 i = 0;
while(!(tab[i].name == NULL && tab[i].id == 0))
{
if(tab[i].id == id)
return tab[i].name;
i++;
}
return NULL;
}
u64 _get_id(id_to_name_t *tab, const s8 *name)
{
u32 i = 0;
while(!(tab[i].name == NULL && tab[i].id == 0))
{
if(strcmp(tab[i].name, name) == 0)
return tab[i].id;
i++;
}
return (u64)(-1);
}
void _zlib_inflate(u8 *in, u64 len_in, u8 *out, u64 len_out)
{
z_stream s;
memset(&s, 0, sizeof(z_stream));
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
inflateInit(&s);
s.avail_in = len_in;
s.next_in = in;
s.avail_out = len_out;
s.next_out = out;
inflate(&s, Z_FINISH);
inflateEnd(&s);
}
void _zlib_deflate(u8 *in, u64 len_in, u8 *out, u64 len_out)
{
z_stream s;
memset(&s, 0, sizeof(z_stream));
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
deflateInit(&s, Z_BEST_COMPRESSION);
s.avail_in = len_in;
s.next_in = in;
s.avail_out = len_out;
s.next_out = out;
deflate(&s, Z_FINISH);
deflateEnd(&s);
}
static mt19937_ctxt_t _mt19937_ctxt;
static BOOL _mt_init = FALSE;
u8 _get_rand_byte()
{
if(_mt_init == FALSE)
{
_mt_init = TRUE;
mt19937_init(&_mt19937_ctxt, clock());
}
return (u8)(mt19937_update(&_mt19937_ctxt) & 0xFF);
}
void _fill_rand_bytes(u8 *dst, u32 len)
{
u32 i;
for(i = 0; i < len; i++)
dst[i] = _get_rand_byte();
}
void _memcpy_inv(u8 *dst, u8 *src, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
dst[i] = ~src[i];
}
void *_memdup(void *ptr, u32 size)
{
void *res = malloc(size);
if(res != NULL)
memcpy(res, ptr, size);
return res;
}
u64 _x_to_u64(const s8 *hex)
{
u64 t = 0, res = 0;
u32 len = strlen(hex);
char c;
while(len--)
{
c = *hex++;
if(c >= '0' && c <= '9')
t = c - '0';
else if(c >= 'a' && c <= 'f')
t = c - 'a' + 10;
else if(c >= 'A' && c <= 'F')
t = c - 'A' + 10;
else
t = 0;
res |= t << (len * 4);
}
return res;
}
u8 *_x_to_u8_buffer(const s8 *hex)
{
u32 len = strlen(hex);
s8 xtmp[3] = {0, 0, 0};
//Must be aligned to 2.
if(len % 2 != 0)
return NULL;
u8 *res = (u8 *)malloc(sizeof(u8) * len);
u8 *ptr = res;
while(len--)
{
xtmp[0] = *hex++;
xtmp[1] = *hex++;
*ptr++ = (u8)_x_to_u64(xtmp);
}
return res;
}

60
util.h Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011-2013 by naehrwert
* This file is released under the GPLv2.
*/
#ifndef _UTIL_H_
#define _UTIL_H_
#include <stdio.h>
#include "types.h"
/*! Verbose. */
extern BOOL _verbose;
#define _LOG_VERBOSE(...) _IF_VERBOSE(printf("[*] " __VA_ARGS__))
#define _IF_VERBOSE(code) \
do \
{ \
if(_verbose == TRUE) \
{ \
code; \
} \
} while(0)
/*! Raw. */
extern BOOL _raw;
#define _PRINT_RAW(fp, ...) _IF_RAW(fprintf(fp, __VA_ARGS__))
#define _IF_RAW(code) \
do \
{ \
if(_raw == TRUE) \
{ \
code; \
} \
} while(0)
/*! ID to name entry. */
typedef struct _id_to_name
{
u64 id;
const s8 *name;
} id_to_name_t;
/*! Utility functions. */
void _hexdump(FILE *fp, const char *name, u32 offset, u8 *buf, int len, BOOL print_addr);
void _print_align(FILE *fp, const s8 *str, s32 align, s32 len);
u8 *_read_buffer(const s8 *file, u32 *length);
int _write_buffer(const s8 *file, u8 *buffer, u32 length);
const s8 *_get_name(id_to_name_t *tab, u64 id);
u64 _get_id(id_to_name_t *tab, const s8 *name);
void _zlib_inflate(u8 *in, u64 len_in, u8 *out, u64 len_out);
void _zlib_deflate(u8 *in, u64 len_in, u8 *out, u64 len_out);
u8 _get_rand_byte();
void _fill_rand_bytes(u8 *dst, u32 len);
void _memcpy_inv(u8 *dst, u8 *src, u32 len);
void *_memdup(void *ptr, u32 size);
u64 _x_to_u64(const s8 *hex);
u8 *_x_to_u8_buffer(const s8 *hex);
#endif

428
zconf.h Normal file
View file

@ -0,0 +1,428 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
* Even better than compiling with -DZ_PREFIX would be to use configure to set
* this permanently in zconf.h using "./configure --zprefix".
*/
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
/* all linked symbols */
# define _dist_code z__dist_code
# define _length_code z__length_code
# define _tr_align z__tr_align
# define _tr_flush_block z__tr_flush_block
# define _tr_init z__tr_init
# define _tr_stored_block z__tr_stored_block
# define _tr_tally z__tr_tally
# define adler32 z_adler32
# define adler32_combine z_adler32_combine
# define adler32_combine64 z_adler32_combine64
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzgetc z_gzgetc
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzwrite z_gzwrite
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define inflateBackInit_ z_inflateBackInit_
# define inflateCopy z_inflateCopy
# define inflateEnd z_inflateEnd
# define inflateGetHeader z_inflateGetHeader
# define inflateInit2_ z_inflateInit2_
# define inflateInit_ z_inflateInit_
# define inflateMark z_inflateMark
# define inflatePrime z_inflatePrime
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# define uncompress z_uncompress
# define zError z_zError
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
/* all zlib typedefs in zlib.h and zconf.h */
# define Byte z_Byte
# define Bytef z_Bytef
# define alloc_func z_alloc_func
# define charf z_charf
# define free_func z_free_func
# define gzFile z_gzFile
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
# define intf z_intf
# define out_func z_out_func
# define uInt z_uInt
# define uIntf z_uIntf
# define uLong z_uLong
# define uLongf z_uLongf
# define voidp z_voidp
# define voidpc z_voidpc
# define voidpf z_voidpf
/* all zlib structs in zlib.h and zconf.h */
# define gz_header_s z_gz_header_s
# define internal_state z_internal_state
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef STDC
# include <sys/types.h> /* for off_t */
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
# endif
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define z_off64_t off64_t
#else
# define z_off64_t z_off_t
#endif
#if defined(__OS400__)
# define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
#pragma map(deflateInit_,"DEIN")
#pragma map(deflateInit2_,"DEIN2")
#pragma map(deflateEnd,"DEEND")
#pragma map(deflateBound,"DEBND")
#pragma map(inflateInit_,"ININ")
#pragma map(inflateInit2_,"ININ2")
#pragma map(inflateEnd,"INEND")
#pragma map(inflateSync,"INSY")
#pragma map(inflateSetDictionary,"INSEDI")
#pragma map(compressBound,"CMBND")
#pragma map(inflate_table,"INTABL")
#pragma map(inflate_fast,"INFA")
#pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

1613
zlib.h Normal file

File diff suppressed because it is too large Load diff