listcheck.c 4.79 KB
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <stdlib.h>
#include <string.h>
#include <sha1.h>
#include <PR/bbmetadata.h>
#include <PR/bbcert.h>
#include <stdlib.h>
#include <bb_nn.h>
#include <PR/bbcrl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <algorithms.h>
#include <aes.h>
/*
#define DEBUG
*/


typedef struct {
    BbEccSig signature; /* over all data including numFields and below */
    u32 numFields; 
} BbReEncryptionHead;

typedef struct {
    BbContentId cid;
    BbAesKey key;
    u32 status;
    u32 padding[2]; /* Each field must be a multiple of 16 bytes, since 
                       they are encrypted with AES-128 */
} BbReEncryptionField;


static void
getFieldFromList(BbReEncryptionField *field, BbReEncryptionHead *pKeyList, int num, u32 bbid, BbAesKey key){
  BbAesIv iv;
  int i;

  /* hard code iv to be bbid +i */
  for(i =0 ; i < sizeof(BbAesIv)/sizeof(u32); i++){
    iv[i] = htonl(bbid + i);
  }

  aes_SwDecrypt((u8 *) key, (u8 *)&iv, 
                ((u8 *) pKeyList) + sizeof(BbReEncryptionHead) + 
		num *sizeof(BbReEncryptionField),
                sizeof(BbReEncryptionField), 
                (u8 *) field);
}


#define GET_LIST_SIG_SIZE(__num_fields)  \
    (sizeof(BbReEncryptionHead) - sizeof(BbEccSig) + \
     htonl(__num_fields) * sizeof(BbReEncryptionField))

int verifyEccSig(u8 *data, u32 datasize, BbEccPublicKey public_key, BbEccSig sign, u32 identity){
  boolean res;
  int i;
  for(i=0; i< sizeof(BbEccSig)/sizeof(u32); i++){
    sign[i] = htonl(sign[i]);
  }
  bsl_verify_ecc_sig(data, datasize, public_key, sign, &res, identity);
  if(res != BSL_TRUE){
    return 1;
  }
  return 0;
}

int
verifyList(BbReEncryptionHead *pList, BbEccPublicKey pubkey)
{
    int res;
    int size = GET_LIST_SIG_SIZE(pList->numFields);
    
#define SK_IDENTITY (0x06091968)
    res = verifyEccSig(((u8 *)(pList))+sizeof(BbEccSig), 
		 size, pubkey, pList->signature, SK_IDENTITY);
    if(res != 0){
        return 1;
    }
    
    return 0;
}
 

int asciiToBin(char *str,int bytes,u8 *buf)
{
    int i,j;
    char t;

    for(i=0;i<bytes;i++){
      t = str[2*i];
      if ((t >= '0') && (t <= '9')) 
	j = (t - '0') << 4;
      else if ((t >= 'a') && (t <= 'f')) 
	j = (t - 'a' + 10) << 4;
      else if ((t >= 'A') && (t <= 'F')) 
	j = (t - 'A' + 10) << 4;
      else return -1;
        
      t = str[2*i+1];
      if ((t >= '0') && (t <= '9')) 
	j ^= (t - '0');
      else if ((t >= 'a') && (t <= 'f')) 
	j ^= (t - 'a' + 10);
      else if ((t >= 'A') && (t <= 'F')) 
	j ^= (t - 'A' + 10);
      else return -1;

      buf[i]=j;
    }
    
    return 0;
}
    
int main(int argc, char **argv){
  int i;
  FILE *listptr;
  struct stat statbuf;
  int file_size;
  BbEccCert bbcert;
  FILE *bbcertptr;
  BbEccPublicKey publickey;
  u8 *list;
  BbAesKey key;
  u32 bbid;
  BbReEncryptionField field;
  BbReEncryptionHead *head;
  if(argc != 4){
    fprintf(stderr,"usage: %s listfile bbcertfile re-enc-key\n", argv[0]);
    exit(1);
  }

  /* pull list data from file */
  listptr = fopen(argv[1], "r");
  if(listptr ==0){
    fprintf(stderr,"couldnt find your list data in local directory\n");
    exit(1);
  }
  stat(argv[1], &statbuf);
  file_size = (long) statbuf.st_size;
  list= (u8  *)malloc(file_size);
  fread((void *)list, file_size, 1, listptr);

  
  /* verify a sign from a BB: assumed BBs cert is ecccert.bin */
  if((bbcertptr = fopen(argv[2], "r")) == 0){
    fprintf(stderr,"cant open bb cert file \n");
    exit(1);
  }
  fread((void *) &bbcert, sizeof(BbEccCert), 1, bbcertptr);
  for(i=0; i< sizeof(BbEccPublicKey)/4; i++){
    publickey[i] = ntohl(bbcert.publicKey[i]);
   }
  fclose(bbcertptr); 
  
  /* check signature on key list */
  if(verifyList((BbReEncryptionHead *) list, publickey) ==0){
    printf("List verified!\n");
  }
  else{
    printf("List not verified\n");
  }
  
  /* get key */
  asciiToBin(argv[3], 16, (u8 *)key);
  
  asciiToBin(bbcert.certId.name.bbid +2, 4, (u8 *)&bbid);
  printf("bbid read = %08x\n", htonl(bbid));

  /* decrypt each field */
  head = (BbReEncryptionHead *) list;
  for(i=0; i < htonl(head->numFields); i++){
    getFieldFromList(&field, head, i, htonl(bbid), key);
    printf("entry %d cid = %08x key = %08x%08x%08x%08x\n",
	   i,
	   (unsigned int) htonl(field.cid), 
	   (unsigned int) htonl(field.key[0]),
	   (unsigned int) htonl(field.key[1]),
	   (unsigned int) htonl(field.key[2]),
	   (unsigned int) htonl(field.key[3]));
    if(htonl(field.status) ==1){
      printf("        status = RECRYPT NOT REQUIRED\n");
    }
    else if(htonl(field.status) == 2){
      printf("        status = RECRYPT COMPLETE\n");
    }
    else if(htonl(field.status) == 3){
      printf("        status = RECRYPT INCOMPLETE\n");
    }
    else if(htonl(field.status) == 4){
      printf("        status = RECRYPT NEW\n");
    }
  }
			   
  return 0;
}