cert.c 3.09 KB
#include <PR/os_bbsa.h>
#include "common.h"

/* 16 KB cert file (cert.sys) */
static u8 gCertBuf[CERTBUF_SIZE] ALIGN_DCACHE;

static BbCertId* gsCertList[SA_MAX_NUM_CERTS];
static int gNumCerts = 0;

int osBbSaCertInit()
{
    int i;
    s32 fd, fsret;
    OSBbStatBuf fsStat;

    fd = osBbFOpen(gSaCertFname,"r");
    if(fd<0){
        return SALAUNCH_ERR_FS;
    }
    fsret = osBbFStat(fd, &fsStat, NULL, 0);
    PRINTF("%s contains %d bytes\n", gSaCertFname,fsStat.size);

    if(fsret !=0)
        return SALAUNCH_ERR_FS;
    if(fsStat.size > sizeof gCertBuf)
        return SALAUNCH_ERR_FS;

    /* read entire cert file into fixed size, global buffer */
    if(osBbFRead(fd, 0, gCertBuf, fsStat.size)<0){
        osBbFClose(fd);
        return SALAUNCH_ERR_FS;
    }

    osBbFClose(fd);

    gNumCerts = *(u32 *)gCertBuf;
    if(gNumCerts >= SA_MAX_NUM_CERTS)
        return SACERT_ERR;

    gsCertList[0] = (BbCertId *)(gCertBuf+sizeof(u32));
    for(i=1;i<gNumCerts;i++){
        switch(gsCertList[i-1]->certType){
        case BB_CERT_TYPE_SERVER:
            gsCertList[i] = (BbCertId *)(((u8 *)gsCertList[i-1]) + 
                                         sizeof(BbRsaCert));
            break;
        case BB_CERT_TYPE_BB:
            gsCertList[i] = (BbCertId *)(((u8 *)gsCertList[i-1]) + 
                                         sizeof(BbEccCert));
            break;
        default:
            return SACERT_ERR;
        }
    }
    gsCertList[i] = NULL;

    return BB_SYSAPP_PASS;
}

int osBbSaCertCreateChain(const char *name,BbCertBase **chain)
{
    int i,j,indx,chainIndx=0;
    char *delims[SA_MAX_NUM_CERTS], *issuer;

    if(name==NULL)
        /* name required to be non-null */
        return SACERT_ERR;

    if((gNumCerts == 0) && (osBbSaCertInit() != BB_SYSAPP_PASS))
        return SACERT_ERR;

    /* use string following last delimiter, if present */
    for(indx=strlen(name)-1; indx>=0; indx--)
        if(name[indx]=='-')
            break;
    indx++;

    for(i=0; 
        (i<gNumCerts) && strcmp(gsCertList[i]->name.server,&(name[indx])); 
        i++){}

    if(i==gNumCerts)
        return SACERT_ERR;

    chain[chainIndx++]=gsCertList[i];
    issuer=(char *)gsCertList[i]->issuer;

    /* find name delimeters */
    indx=0;
    for(i=0;i<sizeof(BbServerName);i++){
        if(issuer[i]=='\0')
            break;
        else if(issuer[i]=='-'){
            if(indx==BB_CERT_CHAIN_MAXLEN)
                /* too many certs in chain */
                return SACERT_ERR;
            delims[indx++]=&issuer[i];
        }
    }
    if(i==sizeof(BbServerName))
        /* chain improperly terminated */
        return SACERT_ERR;

    for(i=indx-1;i>=0;i--){
        for(j=0;j<gNumCerts;j++){
            if(strncmp(gsCertList[j]->name.server,delims[i]+1,
                       i==(indx-1) ? strlen(delims[i]+1) : 
                       delims[i+1]-delims[i]-1)==0){
                chain[chainIndx++]=gsCertList[j];
                break;
            }
        }
        if(j==gNumCerts)
            /* could not find cert specified in chain */
            return SACERT_ERR;
    }

    return BB_SYSAPP_PASS;
}