CCCPaste

make_rif.c

#include 
#include 
#include 
#include 
#include 
#include "common.h"
#include "mappath.h"
#include "modulespatch.h"
#include "ps3mapi_core.h"
#include "make_rif.h"

#define ACCOUNTID						1
#define READ 							0

#define XREGISTRY_FILE 					"/dev_flash2/etc/xRegistry.sys"

static uint8_t empty[0x10] = 
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


unsigned char RAP_KEY[] =  { 0x86, 0x9F, 0x77, 0x45, 0xC1, 0x3F, 0xD8, 0x90, 0xCC, 0xF2, 0x91, 0x88, 0xE3, 0xCC, 0x3E, 0xDF };
unsigned char RAP_PBOX[] = { 0x0C, 0x03, 0x06, 0x04, 0x01, 0x0B, 0x0F, 0x08, 0x02, 0x07, 0x00, 0x05, 0x0A, 0x0E, 0x0D, 0x09 };
unsigned char RAP_E1[] =   { 0xA9, 0x3E, 0x1F, 0xD6, 0x7C, 0x55, 0xA3, 0x29, 0xB7, 0x5F, 0xDD, 0xA6, 0x2A, 0x95, 0xC7, 0xA5 };
unsigned char RAP_E2[] =   { 0x67, 0xD4, 0x5D, 0xA3, 0x29, 0x6D, 0x00, 0x6A, 0x4E, 0x7C, 0x53, 0x7B, 0xF5, 0x53, 0x8C, 0x74 };

uint32_t userID;
uint8_t skip_existing_rif = 0;
uint8_t account_id[0x10];

static int xreg_data(char *value)
{
    int fd, result = -1; 
    uint16_t offset = 0;
    uint64_t read, seek;    

    if(cellFsOpen(XREGISTRY_FILE, CELL_FS_O_RDWR, &fd, 0666, NULL, 0) != SUCCEEDED)
		return result;

	char *buffer = malloc(0x2A);    

    if(!buffer)
		return result;

    // Get offset
    for(int i = 0; i < 0x10000; i++)
    {       
        cellFsLseek(fd, i, SEEK_SET, &seek);
        cellFsRead(fd, buffer, 0x31 + 1, &read);

        // Found offset
        if(strcmp(buffer, value) == 0) 
        {
            offset = i - 0x15;
            uint8_t *data = NULL;

            // Search value from value table
            for(int i = 0x10000; i < 0x15000; i++)
            {
            	data = (uint8_t *) malloc(0x17);

            	if(!data)
            	{
            		free(buffer);
            		return result;
            	}

                cellFsLseek(fd, i, SEEK_SET, &seek);
                cellFsRead(fd, data, 0x17, &read);
                
                // Found value
                if (memcmp(data, &offset, 2) == 0 && data[4] == 0x00 && data[5] == 0x11 && data[6] == 0x02)
                {       
                    result = 0;   

                    memcpy(&account_id, data + 7, 0x10);

                    if(memcmp(data + 7, empty, 0x10) != SUCCEEDED)                        
                        result = 1;                                                                    

                    free(data);
					free(buffer);
					cellFsClose(fd);
					
					return result;
                }

                free(data);
            }
        }
    }

    free(buffer);
    cellFsClose(fd);    

    return result;
}

static void get_rif_key(unsigned char* rap, unsigned char* rif)
{
	int i;
	int round;

	unsigned char key[0x10];
	unsigned char iv[0x10];
	memset(key, 0, 0x10);
	memset(iv, 0, 0x10);

	// Initial decrypt.
	aescbccfb_dec(key, rap, 0x10, RAP_KEY, 0x80, iv);
	memset(iv, 0, 0x10);

	// rap2rifkey round.
	for (round = 0; round < 5; ++round)
	{
		for (i = 0; i < 16; ++i)
		{
			int p = RAP_PBOX[i];
			key[p] ^= RAP_E1[p];
		}

		for (i = 15; i >= 1; --i)
		{
			int p = RAP_PBOX[i];
			int pp = RAP_PBOX[i - 1];
			key[p] ^= key[pp];
		}

		int o = 0;

		for (i = 0; i < 16; ++i)
		{
			int p = RAP_PBOX[i];
			unsigned char kc = key[p] - o;
			unsigned char ec2 = RAP_E2[p];
			if (o != 1 || kc != 0xFF)
			{
				o = kc < ec2 ? 1 : 0;
				key[p] = kc - ec2;
			}
			else if (kc == 0xFF)			
				key[p] = kc - ec2;			
			else			
				key[p] = kc;			
		}
	}

	memcpy(rif, key, 0x10);
}

static void read_act_dat_and_make_rif(uint8_t *rap, uint8_t *act_dat, const char *content_id, const char *rif_path)
{
	int fd;

	if(cellFsOpen(rif_path, CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_TRUNC, &fd, 0666, NULL, 0) == SUCCEEDED)
	{
		uint8_t idps_const[0x10]    = { 0x5E, 0x06, 0xE0, 0x4F, 0xD9, 0x4A, 0x71, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
		uint8_t rif_key_const[0x10] = { 0xDA, 0x7D, 0x4B, 0x5E, 0x49, 0x9A, 0x4F, 0x53, 0xB1, 0xC1, 0xA1, 0x4A, 0x74, 0x84, 0x44, 0x3B };

		uint8_t *rif = ALLOC_RIF_BUFFER;
		uint8_t *key_index = rif + 0x40;
		uint8_t *rif_key = rif + 0x50;
		memset(rif, 0, 0x70);

		get_rif_key(rap, rif_key); //convert rap to rifkey (klicensee)

		uint8_t *iv = rif + 0x60;
		aescbccfb_enc(idps_const, idps_const, 0x10, (void*)PS3MAPI_IDPS_2, IDPS_KEYBITS, iv);

		uint8_t *act_dat_key = rap;
		memcpy(act_dat_key, act_dat + 0x10, 0x10);

		memset(iv, 0, 0x10);
		aescbccfb_dec(act_dat_key, act_dat_key, 0x10, idps_const, IDPS_KEYBITS, iv);

		memset(iv, 0, 0x10);
		aescbccfb_enc(rif_key, rif_key, 0x10, act_dat_key, ACT_DAT_KEYBITS, iv);

		memset(iv, 0, 0x10);
		aescbccfb_enc(key_index, key_index, 0x10, rif_key_const, RIF_KEYBITS, iv);

		const uint32_t version_number = 1;
		const uint32_t license_type = 0x00010002;
		const uint64_t timestamp = 0x000001619BF6DDCA;
		const uint64_t expiration_time = 0;

		memcpy(rif,        &version_number,  4); // 0x00 version_number
		memcpy(rif + 0x04, &license_type,    4); // 0x04 license_type
		memcpy(rif + 0x08, act_dat + 0x8,    8); // 0x08 account_id
		memcpy(rif + 0x10, content_id,    0x24); // 0x10 content_id
												 // 0x40 encrypted key index (Used for choosing act.dat key)
												 // 0x50 encrypted rif_key
		memcpy(rif + 0x60, ×tamp,       8); // 0x60 timestamp
		memcpy(rif + 0x68, &expiration_time, 8); // 0x68 expiration time

		uint64_t size;
		memset(rif + 0x70, 0x11, 0x28);			 // 0x70 ECDSA Signature
		cellFsWrite(fd, rif, 0x98, &size);
		cellFsClose(fd);
	}
}

int create_act_dat(const char *userid)
{
	int fd;
	uint64_t size;
	char full_path[120], exdata_dir[120];
	CellFsStat stat;

	//DPRINTF("Creating act.dat for userID %s...\n", userid);

	uint8_t timedata[0x10] = 
	{ 
		0x00, 0x00, 0x01, 0x2F, 0x3F, 0xFF, 0x00, 0x00, 
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};

	const uint64_t header = 0x0000000100000002;

	uint64_t accountID = (uint64_t)strtoull((const char*)account_id, NULL, 16);
	accountID = SWAP64(accountID);
	
	uint8_t *actdat = malloc(0x1038);	

	if(!actdat)	
		return 1;
	
	memset(actdat, 0x11, 0x1038);
	memcpy(actdat, &header, 8);
	memcpy(actdat + 8, &accountID, 8);
	memcpy(actdat + 0x870, timedata, 0x10);

	sprintf(exdata_dir, "/dev_hdd0/home/%s/exdata", userid);

	if(cellFsStat(exdata_dir, &stat) != SUCCEEDED)				
		cellFsMkdir(exdata_dir, 0777);		

	sprintf(full_path, "%s/act.dat", exdata_dir);

	cellFsOpen(full_path, CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_TRUNC, &fd, 0666, NULL, 0);
	cellFsWrite(fd, actdat, 0x1038, &size);
	cellFsClose(fd);

	free(actdat);

	return SUCCEEDED;
}

void make_rif(const char *path)
{		
	char buffer[120];	
	int path_len = strlen(path);	
	
	if(!strncmp(path, "/dev_hdd0/home/", 15) && !strcmp(path + path_len - 4, ".rif"))
	{		
		int act_dat_found = 0;
		int fd;
		CellFsStat stat;		
		
		DPRINTF("open_path_hook: %s (looking for rap)\n", path);

		char *content_id = ALLOC_CONTENT_ID;
		memset(content_id, 0, 0x25);
		strncpy(content_id, strrchr(path, '/') + 1, 0x24);

		char *rap_path = ALLOC_PATH_BUFFER;

		uint8_t is_ps2_classic = !strncmp(content_id, "2P0001-PS2U10000_00-0000111122223333", 0x24);
		uint8_t is_psp_launcher = !strncmp(content_id, "UP0001-PSPC66820_00-0000111122223333", 0x24);

		char userid[8];
		strncpy(userid, path + 15, 8);
		userid[8] = '\0';		

		if(!is_ps2_classic && !is_psp_launcher)
		{
			CellFsStat stat;
			const char *ext = "rap";

			// Support for rap and RAP extension (By aldostools)
			for(uint8_t i = 0; i < 2; i++)
			{
				sprintf(rap_path, "/dev_usb000/exdata/%36s.%s", content_id, ext);

				if(cellFsStat(rap_path, &stat) != SUCCEEDED) 
					rap_path[10] = '1'; //dev_usb001
				if(cellFsStat(rap_path, &stat) != SUCCEEDED) 
					sprintf(rap_path, "/dev_hdd0/exdata/%36s.%s", content_id, ext);

				if(cellFsStat(rap_path, &stat) != SUCCEEDED) 
					ext = "RAP"; 
				else 
					break;
			}
		}		

		char rap_bin_dir[120];
		sprintf(rap_bin_dir, "/dev_hdd0/home/%s/exdata/rap.bin", userid);
		cellFsStat(rap_bin_dir, &stat);

		if(is_ps2_classic || is_psp_launcher || cellFsOpen((!rap_mode) ? rap_path : rap_bin_dir, CELL_FS_O_RDONLY, &fd, 0666, NULL, 0) == SUCCEEDED)
		{
			uint64_t nread = 0;
			uint8_t rap[0x10] = { 0xF5, 0xDE, 0xCA, 0xBB, 0x09, 0x88, 0x4F, 0xF4, 0x02, 0xD4, 0x12, 0x3C, 0x25, 0x01, 0x71, 0xD9 };

			if(!is_ps2_classic && !is_psp_launcher)
			{
				if(!rap_mode)
				{
					DPRINTF("rap_path: %s output: %s\n", rap_path, path);
					cellFsRead(fd, rap, 0x10, &nread);
				}
				else
				{						
					// rap2bin-bin2rap by esc0rtd3w
					// All credits goes to him
					int MAGIC_NUMBER = 0xFAF0FAF0;
					uint8_t buffer[0x50];

					//DPRINTF("loading license from rap.bin...\n");

					while(cellFsRead(fd, buffer, 0x50, &nread) == SUCCEEDED)
					{
						if((int)!nread)
							break;

						if(memcmp(buffer, &MAGIC_NUMBER, 4) == SUCCEEDED)
						{						 
						 	if(memcmp(buffer + 0x10, content_id, 0x24) == SUCCEEDED)
							{
								memcpy(rap, buffer + 0x40, 0x10);
								DPRINTF("loaded license from rap.bin for %s\n", content_id);
								break;
							}
						}
					}
				}
				
				cellFsClose(fd);
			}				

			// Search act.dat in home dirs
			for(int i = 1; i < 100; i++)
			{
				sprintf(buffer, ACTDAT_PATH, i);
				
				if(cellFsStat(buffer, &stat) == SUCCEEDED) 
				{
					//DPRINTF("Found act.dat in %08d\n", i);
					act_dat_found = 1;
					break;
				}	
			}						

			sprintf(buffer, ACCOUNTID_VALUE, userid);
			
			if(!act_dat_found && xreg_data(buffer))
				create_act_dat(userid);	

			act_dat_found = 0;

			// Skip the creation of rif license if it already exists - By aldostool
			if(skip_existing_rif && cellFsStat(path, &stat) == SUCCEEDED)			
				return;			
			
			char *act_path = ALLOC_PATH_BUFFER;
			memset(act_path, 0, 0x50);
			strncpy(act_path, path, strrchr(path, '/') - path);
			strcpy(act_path + strlen(act_path), "/act.dat\0");

			DPRINTF("act_path: %s content_id: %s\n", act_path, content_id);

			if(cellFsOpen(act_path, CELL_FS_O_RDONLY, &fd, 0666, NULL, 0) == SUCCEEDED)
			{
				uint8_t *act_dat = ALLOC_ACT_DAT;
				cellFsRead(fd, act_dat, 0x20, &nread); // size: 0x1038 but only first 0x20 are used to make rif
				cellFsClose(fd);

				if(nread == 0x20)
				{
					char *rif_path = ALLOC_PATH_BUFFER;
					sprintf(rif_path, "/%s", path);
					read_act_dat_and_make_rif(rap, act_dat, content_id, rif_path);
				}
			}			
		}
	}
}