cert.c 3.48 KB
#include "cert.h"

extern const BbRsaPublicKey4096 gRootKey;
extern const BbRsaExponent gRootExp;

int getCertSize(BbCertBase *cert)
{
#ifdef DEBUG
    PRINT_LONG(cert->certType);
#endif
    switch(cert->certType){
    case BB_CERT_TYPE_BB:
        return sizeof(BbEccCert);
    case BB_CERT_TYPE_SERVER:
        return sizeof(BbRsaCert);
    default:
        return SK_FAIL;
    };
}

int getCertSigSize(BbCertBase *cert)
{
    switch(cert->sigType){
    case BB_SIG_TYPE_RSA2048: 
    case BB_SIG_TYPE_RSA4096:
        return sizeof(BbGenericSig);
    case BB_SIG_TYPE_ECC:
        return sizeof(BbEccSig);
    default:
        return SK_FAIL;
    };
}

int getCertSig(BbCertBase *cert,BbGenericSig **sig)
{
    switch(cert->certType){
    case BB_CERT_TYPE_BB: 
        *sig = &((BbEccCert *)cert)->signature;
        break;
    case BB_CERT_TYPE_SERVER:
        *sig = &((BbRsaCert *)cert)->signature;
        break;
    default:
        return SK_FAIL;
    };

    return SK_SUCCESS;
}


int verifyCertSig(BbCertBase *cert, BbCertBase *signer)
{
    SkDataChain dataChain[1];
    int certSize,certSigSize;
    BbGenericSig *sig;

    
    if(cert == NULL)
        return SK_FAIL;

    /* TODO: handle errors from these calls */
    certSize = getCertSize(cert);
    certSigSize = getCertSigSize(cert);
    getCertSig(cert,&sig);

    /* for certs, only one data chunk is needed */
    dataChain[0].data = (u8 *)cert;    
    dataChain[0].size = certSize - certSigSize;
    
    /* sanity check */
    if(strcmp(cert->issuer,BB_CERT_STR_ROOT) != 0 && signer == NULL){
        return SK_FAIL;
    }

    if(strcmp(cert->issuer,BB_CERT_STR_ROOT) == 0){
        /* Root case, assume rsa 4096 sig type */
        return verifyRsaSigDataChain(dataChain,1, (u32 *)gRootKey, gRootExp,
                            BB_SIG_TYPE_RSA4096,
                            sig);
    }

    switch(cert->sigType){
    case BB_SIG_TYPE_RSA2048: 
    case BB_SIG_TYPE_RSA4096:
        return verifyRsaSigDataChain(dataChain,1,
                            ((BbRsaCert *)signer)->publicKey,
                            ((BbRsaCert *)signer)->exponent,
                            cert->sigType,
                            sig);
/*
    case BB_SIG_TYPE_ECC:
        return verifyEccSig(dataChain,
                            ((BbEccCert *)(signer))->publicKey,
                            cert->sigType,
                            sig);
*/
    default:
        return SK_FAIL;
    }
    
    
}

int verifyCertChain(BbCertBase **chain, u32 chainType)
{
    int i;
    char *name = BB_CERT_STR_XS_PREFIX;

    /*
     * check type to insure, for example, a ticket server chain
     * could not have been used to sign content. this way, ticket
     * servers could not be used to sign sysapp cmdh. sufficient
     * to check the CA in the path.
     *
     * NOTE: BbServerName definition in bbtypes.h fixes position of
     *       '-' chars. 
     */
    if(chainType != CHAIN_TYPE_DONT_CARE && 
       chainType == CHAIN_TYPE_CONTENT_PUB){
        name = BB_CERT_STR_CP_PREFIX;
    }

    for(i = 0; i < BB_CERT_CHAIN_MAXLEN; i++){
        /* break out if it is last one */

        if(chainType!=CHAIN_TYPE_DONT_CARE && 
           strncmp(chain[i]->name.server,name,2) != 0){
            return SK_FAIL;
        }

        if(strcmp(chain[i]->issuer,BB_CERT_STR_ROOT) == 0){
            return verifyCertSig(chain[i], NULL);
        }
        
        if(verifyCertSig(chain[i], chain[i+1]) != SK_SUCCESS){
            return SK_FAIL;
        }
    }

    return SK_SUCCESS;
}