Update code

This commit is contained in:
Li 2024-02-15 17:40:56 +13:00
parent 59b7224db4
commit 851182ce7a
4 changed files with 64 additions and 12 deletions

View File

@ -11,7 +11,10 @@
#include "crypto/aes_cbc.h"
#include "crypto/aes_cmac.h"
// game specific keys, (From .vci header)
// game specific keys, used to derive the rif key,
// which is used to decrypt the game klicensee.
// example is from "Smart As."
static char RIF_KEY_BUF[0x20] = { 0x12, 0x53, 0x56, 0x29, 0x00, 0x31, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x42, 0x21, 0x00, 0x00, 0x00, 0x42, 0x02, 0x00, 0x56, 0x29, 0x05, 0x03, 0x31, 0x3D, 0x20, 0x11, 0x00, 0x00, 0x00, 0x00 };
static char KLIC_KEY_BUF[0x20] = { 0x7B, 0x2B, 0xA1, 0xF1, 0xB7, 0x57, 0xF0, 0x35, 0xFA, 0x93, 0x94, 0x0D, 0x1A, 0xB4, 0xD9, 0x1A, 0x18, 0x54, 0xD6, 0xC3, 0xCD, 0xCD, 0x5B, 0x67, 0xE1, 0x07, 0x70, 0xA4, 0x2B, 0x4F, 0xA9, 0x0A };
@ -19,12 +22,23 @@ static char KLIC_KEY_BUF[0x20] = { 0x7B, 0x2B, 0xA1, 0xF1, 0xB7, 0x57, 0xF0, 0x3
static char CMD56_PACKET[0x200];
static char CMD56_PACKET_RESPONSE[0x200];
// cmd56 state
// CART_RANDOM is used to derive the master_key using bbmac 0x305
// and 0x308 (only on RETAIL_KEY_ID)
static char VITA_AUTHENTICITY_KEY[0x30];
static char CART_RANDOM[0x20];
// cart lock status
// cart lock status, unlocked after successful VITA_AUTHENTICITY_CHECK
static uint8_t CART_STATUS = READ_WRITE_LOCK;
// KEY_ID to use, every gc ive ever seen uses RETAIL_KEY_ID (0x1).
// however a PROTOTYPE_KEY_ID1 0x8001 is also allowed,
// PROTOTYPE_KEY_ID actually has worse security in place,
// however sony could easily check for this in a future update
// and can use RETAIL_KEY_ID thanks to the racoon exploit anyway.
// There also exists a PROTOTYPE_KEY_ID2 and 3,0x8002 and 0x8003,
// however these are blacklisted as of fw 1.04.
static uint16_t KEY_ID = RETAIL_KEY_ID;
#define PACKET_RESPONSE_START(resp, pack) \
@ -188,7 +202,7 @@ void handle_vita_random(src_packet_header* packet) {
LOG_BUFFER(vita_random, sizeof(vita_random));
char master_key[0x10];
derive_master_key(master_key, KEY_ID);
derive_master_key(master_key, CART_RANDOM, KEY_ID);
LOG("Master Key: ");
LOG_BUFFER(master_key, sizeof(master_key));
@ -243,6 +257,32 @@ void handle_packet(src_packet_header* packet) {
}
}
// exposed functions :
void cmd56_reset() {
// lock cart for reading/writing
CART_STATUS = READ_WRITE_LOCK;
// set default key id
KEY_ID = RETAIL_KEY_ID;
// reset keys derived from CMD56 algorithm
memset(VITA_AUTHENTICITY_KEY, 0x00, sizeof(VITA_AUTHENTICITY_KEY));
memset(CART_RANDOM, 0x00, sizeof(CART_RANDOM));
// reset packet data
memset(CMD56_PACKET, 0x00, sizeof(CMD56_PACKET));
memset(CMD56_PACKET_RESPONSE, 0x00, sizeof(CMD56_PACKET_RESPONSE));
// reset cart specific keys
memset(RIF_KEY_BUF, 0x00, sizeof(RIF_KEY_BUF));
memset(KLIC_KEY_BUF, 0x00, sizeof(KLIC_KEY_BUF));
}
void cmd56_update_keyid(uint16_t key_id) {
KEY_ID = key_id;
}
void cmd56_set_keys(char* rif_part, char* klic_part) {
memcpy(RIF_KEY_BUF, rif_part, sizeof(RIF_KEY_BUF));
memcpy(KLIC_KEY_BUF, klic_part, sizeof(KLIC_KEY_BUF));

View File

@ -39,7 +39,8 @@ enum PACKET_SUB_COMMANDS {
};
// exposed functions:
void cmd56_reset();
void cmd56_update_keyid(uint16_t key_id);
void cmd56_set_keys(char* rif_part, char* klic_part);
void cmd56_run(char* buffer);

View File

@ -17,23 +17,34 @@ void encrypt_with_master_key(char* masterKey, char* output, char* data, size_t d
AES_CBC_encrypt(data, output, dataLen, masterKey, 0x10, iv);
}
void derive_master_key(char* out, int key_id) {
void derive_master_key(char* masterKey, char* cart_random, int key_id) {
// CART_RANDOM is used to derive the master_key
// it is done by first decrypting bbmac 0x305 with a static key based on the key_id into bbmac 0x21.
// then the resulting 0x21 key is used to create a AES_128_CMAC hash of the CART_RANDOM
// -- on RETAIL_KEY_ID only, the AES_128_CMAC hash is then decrypted using bbmac 0x308 into 0x24,
//
// this is not possible to implement as the bbmac keys are not yet known.
// so instead we have implemented a "replay attack" where we will always use the same VITA_RANDOM every time
// this will mean the vita will derive the same 'master key' every time, and can just use it.
// NOTE: extracting the key RETAIL_KEY_ID requires using the racoon exploit.
switch(key_id) {
case PROTOTYPE_KEY_ID:
memcpy(out, MASTER_KEY_0x8001, sizeof(MASTER_KEY_0x8001));
case PROTOTYPE_KEY_ID1:
memcpy(masterKey, MASTER_KEY_0x8001, sizeof(MASTER_KEY_0x8001));
break;
case PROTOTYPE_KEY_ID2:
break;
case PROTOTYPE_KEY_ID3:
break;
case RETAIL_KEY_ID:
memcpy(out, MASTER_KEY_0x1, sizeof(MASTER_KEY_0x1));
memcpy(masterKey, MASTER_KEY_0x1, sizeof(MASTER_KEY_0x1));
break;
}
}
void decrypt_secondary_key0(char* cart_random, int key_id, char* vita_authenticity_key, char* secondary_key0) {
char master_key[0x10];
derive_master_key(master_key, key_id);
derive_master_key(master_key, cart_random, key_id);
decrypt_with_master_key(master_key, secondary_key0, vita_authenticity_key, 0x10);
}

View File

@ -5,7 +5,7 @@ static char MASTER_KEY_0x8001[0x10] = { 0x39, 0x07, 0xA9, 0x3E, 0x6B, 0x68, 0x8C
static char MASTER_KEY_0x1[0x10] = { 0x16, 0x20, 0x5F, 0xA6, 0x71, 0x35, 0xD6, 0x2B, 0x29, 0x08, 0xE7, 0xEC, 0x78, 0x04, 0x1A, 0xE8 }; // keyid = 0x1
enum KEY_IDS {
PROTOTYPE_KEY_ID = 0x8001,
PROTOTYPE_KEY_ID1 = 0x8001,
// on CEX 1.04+ 8002 and 8003 are hardcoded blocked in gcauthmgr.skprx
PROTOTYPE_KEY_ID2 = 0x8002,
@ -17,7 +17,7 @@ enum KEY_IDS {
void decrypt_with_master_key(char* masterKey, char* output, char* data, size_t dataLen);
void encrypt_with_master_key(char* masterKey, char* output, char* data, size_t dataLen);
void derive_master_key(char* out, int key_id);
void derive_master_key(char* masterKey, char* cart_random, int key_id);
void decrypt_secondary_key0(char* cart_random, int key_id, char* vita_authenticity_key, char* secondary_key0);
#endif