salaunch.c 6.57 KB
#include <PR/bcp.h>
#include <PR/R4300.h>
#include <PR/bbsim.h>
#include <PR/bbskapi.h>

#include <PR/os.h>
#include <PR/os_bb.h>
#include <PR/os_bbfs.h>
#include <PR/os_bbatb.h>
#include <PR/os_bbexec.h>
#include <PR/ramrom.h>
#include <PR/ultratypes.h>

#include "PR/bbnand.h"
#include "os_bbsa.h"
#include <sha1.h>

#define ALIGN_DCACHE __attribute__((aligned(DCACHE_LINESIZE)))
static u8 tik_data[PI_FLASH_PAGES_PER_BLOCK * PI_FLASH_PAGE_DATA_SIZE] ALIGN_DCACHE;

/*  Load sysapp tik to iram */
int gng_loadticket(char *fname)
{
    OSBbStatBuf fsStat;
    s32 fd;
    u32 ret = BB_SYSAPP_PASS;
    BbContentMetaDataHead *cmd = (BbContentMetaDataHead *) tik_data;

    fd = osBbFOpen(fname,"r");
    if(fd<0){
        return SAMETA_ERR_FS;
    }
    if( osBbFStat(fd, &fsStat, NULL, 0) < 0){
        ret = SAMETA_ERR_FS;
        goto exit;
    }

    if(fsStat.size > PI_FLASH_PAGES_PER_BLOCK * PI_FLASH_PAGE_DATA_SIZE){
        ret = SAMETA_ERR_MEM;
        goto exit;
    }

    if(osBbFRead(fd, 0, (u8 *) cmd, fsStat.size)<0){
        ret = SAMETA_ERR_FS;
        goto exit;
    }

exit:
    osBbFClose(fd);
    return ret;
}

BbAesKey content_key;
BbAesKey bb_root_key = {0xb8190276, 0x7e25db27, 0x0f3449c5, 0xd94b162f};
int verify_sysapp_tik()
{
    BbCertBase *certs[3];
    BbContentMetaDataHead *cmd = (BbContentMetaDataHead *) tik_data;
    BbShaHash hash_data;
    SHA1Context sha;
    BbAppLaunchCrls appRls;
    char buf[256];
    int ret;

    /*  copy from Andy's sk/boot.c */
    certs[0] = (BbCertBase *)(tik_data +
                           sizeof(BbContentMetaDataHead));
    certs[1] = (BbCertBase *)((u8 *)certs[0] + sizeof(BbRsaCert));
    certs[2] = NULL;

    /* calculate hash data here */
    SHA1Reset(&sha);
    SHA1Input(&sha, (u8 *) cmd, BB_CMD_HEAD_SIGNED_BYTES);
    SHA1Result(&sha, (u8 *) hash_data);

    ret =  aes_SwDecrypt((u8 *) bb_root_key,
                        (u8 *)cmd->commonCmdIv,
                        (u8 *)&(cmd->key),
                        BB_CMD_ENCRYPTED_CHUNK_BYTES,
                        content_key);
    sprintf(buf, "%x %x %x %x", content_key[0],  content_key[1],
           content_key[2], content_key[3]);
    printstr(0xffff, 8, 6, buf);
    osWritebackDCacheAll();
    
    bzero(&appRls, sizeof(BbAppLaunchCrls));
    return skVerifyHash(hash_data, (BbGenericSig *) &cmd->contentMetaDataSign, certs, &appRls);
}

static char block[BB_FL_BLOCK_SIZE] ALIGN_DCACHE;
static char block_enc[BB_FL_BLOCK_SIZE] ALIGN_DCACHE;
int verify_load_app(char *fname)
{
    OSBbStatBuf fsStat;
    BbContentMetaDataHead *cmd = (BbContentMetaDataHead *) tik_data;
    int fd, rv;
    unsigned int addr, off;
    BbShaHash hash_data;
    SHA1Context sha;
    u32  code_rom_start, code_rom_end, code_start, code_end,
         bss_start, bss_end, data_start, data_end;
    int (*f) ();
    char buf[128];

    osSyncPrintf("Hello !\n");
    fd = osBbFOpen(fname,"r");
    if(fd<0)  return SAMETA_ERR_FS;

    if (osBbFStat(fd, &fsStat, NULL, 0) < 0){
        osBbFClose(fd);
        return SAMETA_ERR_FS;
    }

    SHA1Reset(&sha);

    rv = osBbFRead(fd, 0, block_enc, BB_FL_BLOCK_SIZE);
    osSyncPrintf("Decode 1st block \n");

    /* for (rv = 0; rv < BB_FL_BLOCK_SIZE; rv+=128) {
       aes_SwDecrypt((u8 *) content_key,
                   (u8 *)cmd->iv,
                   block_enc+rv,
                   128,
                   block+rv);
       osSyncPrintf("Hi %d \n", rv);
    } */
    aes_SwDecrypt((u8 *) content_key,
                   (u8 *)cmd->iv,
                   block_enc,
                   BB_FL_BLOCK_SIZE,
                   block); 
    osSyncPrintf("Decode 1st block done\n");
    
    code_rom_start = *(unsigned int*)(block);
    code_rom_end = *(unsigned int*)(block+4);
    code_start = *(unsigned int*)(block+8);
    code_end = *(unsigned int*)(block+0xc);
    bss_start = *(unsigned int*)(block+0x10);
    bss_end = *(unsigned int*)(block+0x14);
    data_start = *(unsigned int*)(block+0x18);
    data_end = *(unsigned int*)(block+0x1c);

    /* XXXXX Todo:  make sure code_start > code_rom_start */
    addr = code_start - code_rom_start - 8 * sizeof(int);
    bcopy(block, (void*)addr, BB_FL_BLOCK_SIZE);

    addr += BB_FL_BLOCK_SIZE;
    off = BB_FL_BLOCK_SIZE;
    SHA1Input(&sha, (u8 *) block, BB_FL_BLOCK_SIZE);

    while (rv >= 0 && off < fsStat.size) {
        rv = osBbFRead(fd, off, (void*)block_enc, BB_FL_BLOCK_SIZE);
        aes_SwDecrypt((u8 *) content_key,
                   (u8 *)cmd->iv,
                   block_enc,
                   BB_FL_BLOCK_SIZE,
                   addr);
        osSyncPrintf("Decode block at 0x%x \n", off);
        SHA1Input(&sha, (u8 *) addr,  BB_FL_BLOCK_SIZE);
        if (rv <= 0) break;
        addr += BB_FL_BLOCK_SIZE;
        off += BB_FL_BLOCK_SIZE;
    }
    if (rv < 0) return rv;
    osBbFClose(fd);

    printstr(0xffff, 8, 6, "Oh..., Security passed!");
    sprintf(buf, "c_rom 0x%x 0x%x", code_rom_start, code_rom_end);
    printstr(0xffff, 4, 7, buf);
    sprintf(buf, "c_ddr 0x%x 0x%x", code_start, code_end);
    printstr(0xffff, 4, 8, buf);
    sprintf(buf, "bss 0x%x 0x%x", bss_start, bss_end);
    printstr(0xffff, 4, 9, buf);
    sprintf(buf, "data 0x%x 0x%x", data_start, data_end);
    printstr(0xffff, 4, 10, buf);
    osWritebackDCacheAll();

    SHA1Result(&sha, (u8 *) hash_data);
    if (bcmp(hash_data, cmd->hash, sizeof(hash_data)) != 0)
        return -1;

    osRomBase = PI_DOM1_ADDR2;
    osMemSize =  0x800000;
    osTvType =  OS_TV_NTSC;
    osWritebackDCacheAll();
    IO_WRITE(MI_INTR_MASK_REG, 
             MI_INTR_MASK_CLR_SP |
             MI_INTR_MASK_CLR_SI |
             MI_INTR_MASK_CLR_AI |
             MI_INTR_MASK_CLR_VI |
             MI_INTR_MASK_CLR_PI |
             MI_INTR_MASK_CLR_DP);
    IO_WRITE(MI_INTR_EMASK_REG, 
             MI_INTR_MASK_CLR_FLASH |
             MI_INTR_MASK_CLR_AES |
             MI_INTR_MASK_CLR_PI_ERR |
             MI_INTR_MASK_CLR_USB0 |
             MI_INTR_MASK_CLR_USB1 |
             MI_INTR_MASK_CLR_BUT |
             MI_INTR_MASK_CLR_MD);
    __osDisableInt();

    IO_WRITE(PI_ACCESS_REG, PI_ACCESS_ALL);
    IO_WRITE(PI_ERROR_REG, PI_ERROR_KERNEL_INTR);
    IO_WRITE(USB0_SECURE_MODE_REG, USB_SECURE_MODE_OFF);
    IO_WRITE(USB1_SECURE_MODE_REG, USB_SECURE_MODE_OFF);
    IO_WRITE(MI_SEC_MODE_REG, MI_SEC_MODE_IRAM_ACCESS|MI_SEC_MODE_BUT_TRAP_EN);
    osInvalICache((void*) code_start, code_end - code_start);
    osInvalDCache((void*) data_start, data_end - data_start);
    bzero((void *)bss_start, bss_end - bss_start);    

    f = (void *) code_start;
    (*f)();    

    printstr(0xff01, 8, 8, "Oh..., Why am I here?");
    osWritebackDCacheAll();
    for (;;);
    
    return 0;
}