mkTicket.c 6.41 KB
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <netinet/in.h>

#include <PR/bcp.h>
#include <PR/bbmetadata.h>
#include <PR/bbcert.h>
#include <PR/bbticket.h>

#include <bbtoolsapi.h>
#include <aes.h>
#include <sha1.h>
#include <algorithms.h>
#include <openssl/rsa.h>
#include <util.h>

#define H2BE4(a) (htonl((a)))
#define H2BE2(a) (htons((a)))
#define BE2H4(a) (ntohl((a)))

#define MAX_KEY_SIZE 4096

void printUsage() {
    fprintf(stderr, "Usage:\n"
            "   mkTicket [-t tid]  [-l code:limit] cmdInFile v2InFile ticketOutFile bbcertInFile\n");
}


int main(int argc, char* argv[]) 
{
    FILE *cmdInFile, *ticketOutFile, *tsKeyDataFile=NULL, *bbcertInFile;
    BbServerName issuername;
    BbEccPrivateKey privkeyserver;
    BbEccPublicKey pubkeyserver;
    BbEccPublicKey pubkeybb;
    BbEccCert bbcert;
    SHA1Context sha;
    RSA *prsa;
    BbTicket ticket;
    BbContentMetaData metadata;
    int size, i, e_size, n_size;
    
    unsigned long certpublickey[128];
    unsigned long certsign[128];
    unsigned long certexponent;
    unsigned char e_string[4096];
    unsigned char n_string[4096];
    unsigned char *padded_data;
    unsigned char customResult[4096];
    unsigned char signature[4096];
    unsigned char hash[20];
    unsigned char *verify;
    char c;
    int count;
    BbAesIv cmdIv;
    u32 tsCrlVersion = 0;
    BbId bbid;
    BbTicketId tid = 0;
    u16 limitCode = 0;
    u16 limit = 0;

    char *root_string;
    char tmp_name[2048];
   
    opterr = 0;
    while((c = getopt(argc, argv, "t:c:l:S:L:")) != (char)-1) {
        switch(c) {
	case 't':
	    tid = strtoul(optarg, 0, 0); break;
	case 'l':
	    if (sscanf(optarg, "%hi:%hi", &limitCode, &limit) == 2)
		break;
	case 'S':
	    if ((tsKeyDataFile= fopen(optarg, "r")) == NULL) {
		perror(optarg);
                return 1;
	    }
	    break;
	case 'L':
	  tsCrlVersion = strtoul(optarg, 0, 0); break;
	default:
            printUsage();
	    return 1;
	}
    }

    if((argc-optind)!=4){
        fprintf(stderr, "mkTicket Error: wrong number of required args (4)\n");
        printUsage();
        return 1;
    }

    if((cmdInFile = fopen(argv[optind], "r"))==NULL){
        fprintf(stderr,"failed to open file %s\n",argv[optind]);
        return 1;
    }

    optind++; /*XXXblythe v2 no longer used*/

    optind++;
    if((ticketOutFile = fopen(argv[optind], "w"))==NULL){
        fprintf(stderr,"failed to open file %s\n",argv[optind]);
        return 1;
    }

    optind++;
    if((bbcertInFile = fopen(argv[optind], "r"))==NULL){
        fprintf(stderr,"failed to open file %s\n",argv[optind]);
        return 1;
    }

    /* read key of signer */
    
    if((root_string = getenv("ROOT")) == NULL){
        fprintf(stderr,"Root not set\n");
        exit(1);
    }
    
    fread(&bbcert, 1, sizeof(BbEccCert), bbcertInFile);
    for(i = 0; i < sizeof bbcert.publicKey/4; i++)
	pubkeybb[i] = ntohl(bbcert.publicKey[i]);

    /* generate server public key from random private key,
     * then generate aes key for use on cmd.
     */

    for(i =0;i < 8; i++){
        privkeyserver[i]  = (u32) i;
    }
    eccGenPublicKey(pubkeyserver, privkeyserver);

    memset(&ticket, 0, sizeof(ticket));
    fread(&metadata,1,sizeof(BbContentMetaData),cmdInFile);
    bbid = strtoul(bbcert.certId.name.bbid+2, 0, 16);
    
    
    cmdIv[0] = (0x01010101);
    cmdIv[1] = (0x02020202);
    cmdIv[2] = (0x03030303);
    cmdIv[3] = (0x04040404);
    
    if(generateUnsignedEncryptedTicket(&metadata,
                                        bbid,
					tid,
					limitCode,
					limit,
                                        tsCrlVersion, 
                                        cmdIv, 
                                        privkeyserver,
                                        pubkeyserver,
                                        pubkeybb,
                                        &ticket
                                        ) < 0){
        fprintf(stderr, "ticket creation error \n");
        return 1;
    }


/* compute keys  XS RSA 
 */
    
    memset(ticket.head.issuer, 0, sizeof issuername);
    prsa = RSA_new();
    if(tsKeyDataFile == NULL){
        sprintf(tmp_name,"%s/usr/host_data/%s", root_string, "tsbindata");
        if ((tsKeyDataFile = fopen(tmp_name,"r")) == NULL) {
            fprintf(stderr,"couldnt find key data for signer\n");
	    return 1;
        }
        strcpy(issuername, "Root-XSCA00010203-XS0a0b0c0d");
    }
    /* for backward compatibility, readRsaDataNamed() will not alter
     * issuername arg if tsbindata file is used (doesn't hold name as
     * new .key file does).
     */
    readRsaDataNamed(tsKeyDataFile, prsa, (char *)issuername);
    memcpy(&ticket.head.issuer, issuername, sizeof issuername);

    size = RSA_size(prsa);	/* assert size = 2048/8 */
    padded_data = (unsigned char *)malloc(size);

    /* compute hash */
    SHA1Reset(&sha);
    SHA1Input(&sha, (u8 *)&(ticket), sizeof(BbTicket) -sizeof(BbRsaSig2048));
    SHA1Result(&sha, hash);
    
    RSA_padding_add_PKCS1_type_2(padded_data, size, hash, sizeof hash);
   
    size = RSA_private_encrypt(size, 
                      padded_data, signature, prsa, RSA_NO_PADDING);
    
    e_size = BN_bn2bin(prsa->e, e_string);
    n_size = BN_bn2bin(prsa->n, n_string);

#define get_word(x)	*(u32*)(x)
    certexponent = get_word(e_string);
    count = 0;
    for(i=0; i< n_size; i= i+4){
        certpublickey[count] = htonl(get_word(n_string + i));
        certsign[count] = htonl(get_word(signature + i));
        count++;
    }
#define VERIFY
#ifdef VERIFY
    size = RSA_size(prsa);
    verify = (unsigned char *) malloc(size);
    memset(verify, 0, size);
    RSA_public_decrypt(size, signature, verify, prsa, RSA_NO_PADDING);
    bsl_rsa_verify(customResult, certsign, certpublickey, &certexponent, 2048);
    if(memcmp(hash, customResult+size-sizeof hash, sizeof hash) != 0 ||
       memcmp(hash, verify+size-sizeof hash, sizeof hash) != 0)
        printf("mkTicket: signature verification FAILED\n");
#endif

    /* copy the sign to its rightful place */
    memset(ticket.head.ticketSign, 0, sizeof ticket.head.ticketSign);
    for(i = 0; i < sizeof(BbRsaSig2048)/sizeof(u32); i++){
        ticket.head.ticketSign[i] = htonl(certsign[i]);
    }
    if (fwrite((void *)&ticket, 1, sizeof(ticket), ticketOutFile) < 0) {
        perror("fwrite");
        return 1;
    }

    fclose(tsKeyDataFile);
    fclose(bbcertInFile);
    fclose(cmdInFile);
    fclose(ticketOutFile);
    return 0;
}