/* * Create an object specific authorisation protocol (OSAP) session */ static int osap(struct tpm_buf *tb, struct osapsess *s, const unsigned char *key, uint16_t type, uint32_t handle) { unsigned char enonce[TPM_NONCE_SIZE]; unsigned char ononce[TPM_NONCE_SIZE]; int ret; ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE); if (ret != TPM_NONCE_SIZE) return ret; INIT_BUF(tb); store16(tb, TPM_TAG_RQU_COMMAND); store32(tb, TPM_OSAP_SIZE); store32(tb, TPM_ORD_OSAP); store16(tb, type); store32(tb, handle); storebytes(tb, ononce, TPM_NONCE_SIZE); ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); if (ret < 0) return ret; s->handle = LOAD32(tb->data, TPM_DATA_OFFSET); memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)]), TPM_NONCE_SIZE); memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) + TPM_NONCE_SIZE]), TPM_NONCE_SIZE); return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, 0, 0); }
uint32_t TPM_ReadStartupEffects(const unsigned char *buffer, TPM_STARTUP_EFFECTS * se) { uint32_t offset = 0; *se = LOAD32(buffer, offset); offset += 4; return offset; }
static uint32_t TPM_ReceiveSocket(int sock_fd, struct tpm_buffer *tb) { uint32_t rc = 0; uint32_t paramSize = 0; uint32_t addsize = 0; unsigned char *buffer = tb->buffer; if (TPM_LowLevel_Use_VTPM()) addsize = sizeof(uint32_t); /* read the tag and paramSize */ if (rc == 0) { rc = TPM_ReceiveBytes(sock_fd, buffer, addsize + TPM_U16_SIZE + TPM_U32_SIZE); } /* extract the paramSize */ if (rc == 0) { paramSize = LOAD32(buffer, addsize + TPM_PARAMSIZE_OFFSET); if (paramSize > TPM_MAX_BUFF_SIZE) { printf ("TPM_ReceiveSocket: ERROR: paramSize %u greater than %u\n", paramSize, TPM_MAX_BUFF_SIZE); rc = ERR_BAD_RESP; } } /* read the rest of the packet */ if (rc == 0) { rc = TPM_ReceiveBytes(sock_fd, buffer + addsize + TPM_U16_SIZE + TPM_U32_SIZE, paramSize - (TPM_U16_SIZE + TPM_U32_SIZE)); } /* read the TPM return code from the packet */ if (rc == 0) { showBuff(buffer, "TPM_ReceiveSocket: From TPM"); rc = LOAD32(buffer, addsize + TPM_RETURN_OFFSET); tb->used = addsize + paramSize; } return rc; }
static uint32_t TPM_ReceiveCharDev(int sock_fd, struct tpm_buffer *tb) { uint32_t rc = 0; uint32_t paramSize = 0; unsigned char *buffer = tb->buffer; #ifndef USE_PARTIAL_READ /* read the whole packet */ if (rc == 0) { int nread; nread = read(sock_fd, tb->buffer, tb->size); if (nread < 0) { rc = ERR_IO; } else { tb->used = nread; } } #endif #ifdef USE_PARTIAL_READ /* read the tag and paramSize */ if (rc == 0) { rc = TPM_ReceiveBytes(sock_fd, buffer, TPM_U16_SIZE + TPM_U32_SIZE); } #endif /* extract the paramSize */ if (rc == 0) { paramSize = LOAD32(buffer, TPM_PARAMSIZE_OFFSET); if (paramSize > TPM_MAX_BUFF_SIZE) { printf("TPM_ReceiveCharDev: paramSize %u greater than %u\n", paramSize, TPM_MAX_BUFF_SIZE); rc = ERR_BAD_RESP; } } #ifdef USE_PARTIAL_READ /* read the rest of the packet */ if (rc == 0) { rc = TPM_ReceiveBytes(sock_fd, buffer + TPM_U16_SIZE + TPM_U32_SIZE, paramSize - (TPM_U16_SIZE + TPM_U32_SIZE)); } #endif /* read the TPM return code from the packet */ if (rc == 0) { showBuff(buffer, "TPM_ReceiveCharDev: From TPM"); tb->used = paramSize; tpm_buffer_load32(tb, TPM_RETURN_OFFSET, &rc); } return rc; }
uint32_t TPM_ReadCounterValue(const unsigned char *buffer, TPM_COUNTER_VALUE * counter) { uint32_t offset = 0; counter->tag = LOAD16(buffer, offset); offset += TPM_U16_SIZE; if (counter->tag != TPM_TAG_COUNTER_VALUE) return ERR_STRUCTURE; memcpy(&counter->label[0], &buffer[offset], sizeof(counter->label)); offset += sizeof(counter->label); counter->counter = LOAD32(buffer, offset); return 0; }
/* * Create an object independent authorisation protocol (oiap) session */ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) { int ret; INIT_BUF(tb); store16(tb, TPM_TAG_RQU_COMMAND); store32(tb, TPM_OIAP_SIZE); store32(tb, TPM_ORD_OIAP); ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); if (ret < 0) return ret; *handle = LOAD32(tb->data, TPM_DATA_OFFSET); memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)], TPM_NONCE_SIZE); return 0; }
int main(int argc, char *argv[]) { int ret = 0; uint32_t handle; int listsize; int offset; int i; /* argc iterator */ TPM_setlog(0); /* turn off verbose output */ for (i=1 ; i<argc ; i++) { if (!strcmp(argv[i], "-h")) { printUsage(); } else if (!strcmp(argv[i], "-v")) { TPM_setlog(1); } else { printf("\n%s is not a valid option\n", argv[i]); printUsage(); } } STACK_TPM_BUFFER(response); if (ret == 0) { ret = TPM_GetCapability(0x0000007,NULL,&response); if (ret != 0) { printf("Error %s from TPM_GetCapability\n",TPM_GetErrMsg(ret)); exit(1); } listsize = LOAD16(response.buffer,0); offset = 2; for (i = 0; i < listsize; ++i) { handle = LOAD32(response.buffer,offset); printf("Key handle %02d %08x\n",i,handle); offset += 4; } } exit(0); }
uint32_t TPM_ReadMSAFile(const char * filename, TPM_MSA_COMPOSITE * msaList) { uint32_t ret; unsigned char * buffer = NULL; uint32_t buffersize = 0; ret = TPM_ReadFile(filename, &buffer, &buffersize); if ( (ret & ERR_MASK) != 0 ) { return ret; } msaList->MSAlist = LOAD32(buffer, 0); if (msaList->MSAlist * TPM_HASH_SIZE + 4 == buffersize) { msaList->migAuthDigest = malloc( msaList->MSAlist * TPM_HASH_SIZE ); if (NULL == msaList->migAuthDigest) { return ERR_MEM_ERR; } memcpy(msaList->migAuthDigest, buffer+sizeof(uint32_t), msaList->MSAlist * TPM_HASH_SIZE); } else { return ERR_BAD_FILE; } return 0; }
_CODE_ACCESS off_t HOSTlseek(int dev_fd, off_t offset, int origin) { off_t result; /*-----------------------------------------------------------------------*/ /* CRITICAL REGION TO PROTECT ACCESSES TO parmbuf[] AND _CIOBUF_ (see */ /* file header comment above for more about mutexes and data coherency). */ /*-----------------------------------------------------------------------*/ __TI_resource_lock(__TI_LOCK_HOST_CIO); LOADSHORT(parmbuf,dev_fd,0); LOAD32(parmbuf,offset,2); LOADSHORT(parmbuf,origin,6); __TI_writemsg(_DTLSEEK,parmbuf,NULL,0); __TI_readmsg(parmbuf,NULL); result = UNLOAD32(parmbuf,0); __TI_data_synch_WBINV(&parmbuf, sizeof(parmbuf)); __TI_resource_unlock(__TI_LOCK_HOST_CIO); return result; }
/* Process 2OPI Integer instructions */ bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c) { #ifdef DEBUG char Name[20] = "ILLEGAL_2OPI"; #endif /* 0x0E ... 0x2B */ /* 0xB0 ... 0xDF */ switch(c->raw2) { case 0x0E: /* ADDI */ { #ifdef DEBUG strncpy(Name, "ADDI", 19); #elif TRACE record_trace("ADDI"); #endif ADDI(vm, c); break; } case 0x0F: /* ADDUI */ { #ifdef DEBUG strncpy(Name, "ADDUI", 19); #elif TRACE record_trace("ADDUI"); #endif ADDUI(vm, c); break; } case 0x10: /* SUBI */ { #ifdef DEBUG strncpy(Name, "SUBI", 19); #elif TRACE record_trace("SUBI"); #endif SUBI(vm, c); break; } case 0x11: /* SUBUI */ { #ifdef DEBUG strncpy(Name, "SUBUI", 19); #elif TRACE record_trace("SUBUI"); #endif SUBUI(vm, c); break; } case 0x12: /* CMPI */ { #ifdef DEBUG strncpy(Name, "CMPI", 19); #elif TRACE record_trace("CMPI"); #endif CMPI(vm, c); break; } case 0x13: /* LOAD */ { #ifdef DEBUG strncpy(Name, "LOAD", 19); #elif TRACE record_trace("LOAD"); #endif LOAD(vm, c); break; } case 0x14: /* LOAD8 */ { #ifdef DEBUG strncpy(Name, "LOAD8", 19); #elif TRACE record_trace("LOAD8"); #endif LOAD8(vm, c); break; } case 0x15: /* LOADU8 */ { #ifdef DEBUG strncpy(Name, "LOADU8", 19); #elif TRACE record_trace("LOADU8"); #endif LOADU8(vm, c); break; } case 0x16: /* LOAD16 */ { #ifdef DEBUG strncpy(Name, "LOAD16", 19); #elif TRACE record_trace("LOAD16"); #endif LOAD16(vm, c); break; } case 0x17: /* LOADU16 */ { #ifdef DEBUG strncpy(Name, "LOADU16", 19); #elif TRACE record_trace("LOADU16"); #endif LOADU16(vm, c); break; } case 0x18: /* LOAD32 */ { #ifdef DEBUG strncpy(Name, "LOAD32", 19); #elif TRACE record_trace("LOAD32"); #endif LOAD32(vm, c); break; } case 0x19: /* LOADU32 */ { #ifdef DEBUG strncpy(Name, "LOADU32", 19); #elif TRACE record_trace("LOADU32"); #endif LOADU32(vm, c); break; } case 0x1F: /* CMPUI */ { #ifdef DEBUG strncpy(Name, "CMPUI", 19); #elif TRACE record_trace("CMPUI"); #endif CMPUI(vm, c); break; } case 0x20: /* STORE */ { #ifdef DEBUG strncpy(Name, "STORE", 19); #elif TRACE record_trace("STORE"); #endif STORE(vm, c); break; } case 0x21: /* STORE8 */ { #ifdef DEBUG strncpy(Name, "STORE8", 19); #elif TRACE record_trace("STORE8"); #endif STORE8(vm, c); break; } case 0x22: /* STORE16 */ { #ifdef DEBUG strncpy(Name, "STORE16", 19); #elif TRACE record_trace("STORE16"); #endif STORE16(vm, c); break; } case 0x23: /* STORE32 */ { #ifdef DEBUG strncpy(Name, "STORE32", 19); #elif TRACE record_trace("STORE32"); #endif STORE32(vm, c); break; } case 0xB0: /* ANDI */ { #ifdef DEBUG strncpy(Name, "ANDI", 19); #elif TRACE record_trace("ANDI"); #endif ANDI(vm, c); break; } case 0xB1: /* ORI */ { #ifdef DEBUG strncpy(Name, "ORI", 19); #elif TRACE record_trace("ORI"); #endif ORI(vm, c); break; } case 0xB2: /* XORI */ { #ifdef DEBUG strncpy(Name, "XORI", 19); #elif TRACE record_trace("XORI"); #endif XORI(vm, c); break; } case 0xB3: /* NANDI */ { #ifdef DEBUG strncpy(Name, "NANDI", 19); #elif TRACE record_trace("NANDI"); #endif NANDI(vm, c); break; } case 0xB4: /* NORI */ { #ifdef DEBUG strncpy(Name, "NORI", 19); #elif TRACE record_trace("NORI"); #endif NORI(vm, c); break; } case 0xB5: /* XNORI */ { #ifdef DEBUG strncpy(Name, "XNORI", 19); #elif TRACE record_trace("XNORI"); #endif XNORI(vm, c); break; } case 0xC0: /* CMPJUMPI.G */ { #ifdef DEBUG strncpy(Name, "CMPJUMPI.G", 19); #elif TRACE record_trace("CMPJUMPI.G"); #endif CMPJUMPI_G(vm, c); break; } case 0xC1: /* CMPJUMPI.GE */ { #ifdef DEBUG strncpy(Name, "CMPJUMPI.GE", 19); #elif TRACE record_trace("CMPJUMPI.GE"); #endif CMPJUMPI_GE(vm, c); break; } case 0xC2: /* CMPJUMPI.E */ { #ifdef DEBUG strncpy(Name, "CMPJUMPI.E", 19); #elif TRACE record_trace("CMPJUMPI.E"); #endif CMPJUMPI_E(vm, c); break; } case 0xC3: /* CMPJUMPI.NE */ { #ifdef DEBUG strncpy(Name, "CMPJUMPI.NE", 19); #elif TRACE record_trace("CMPJUMPI.NE"); #endif CMPJUMPI_NE(vm, c); break; } case 0xC4: /* CMPJUMPI.LE */ { #ifdef DEBUG strncpy(Name, "CMPJUMPI.LE", 19); #elif TRACE record_trace("CMPJUMPI.LE"); #endif CMPJUMPI_LE(vm, c); break; } case 0xC5: /* CMPJUMPI.L */ { #ifdef DEBUG strncpy(Name, "CMPJUMPI.L", 19); #elif TRACE record_trace("CMPJUMPI.L"); #endif CMPJUMPI_L(vm, c); break; } case 0xD0: /* CMPJUMPUI.G */ { #ifdef DEBUG strncpy(Name, "CMPJUMPUI.G", 19); #elif TRACE record_trace("CMPJUMPUI.G"); #endif CMPJUMPUI_G(vm, c); break; } case 0xD1: /* CMPJUMPUI.GE */ { #ifdef DEBUG strncpy(Name, "CMPJUMPUI.GE", 19); #elif TRACE record_trace("CMPJUMPUI.GE"); #endif CMPJUMPUI_GE(vm, c); break; } case 0xD4: /* CMPJUMPUI.LE */ { #ifdef DEBUG strncpy(Name, "CMPJUMPUI.LE", 19); #elif TRACE record_trace("CMPJUMPUI.LE"); #endif CMPJUMPUI_LE(vm, c); break; } case 0xD5: /* CMPJUMPUI.L */ { #ifdef DEBUG strncpy(Name, "CMPJUMPUI.L", 19); #elif TRACE record_trace("CMPJUMPUI.L"); #endif CMPJUMPUI_L(vm, c); break; } default: { illegal_instruction(vm, c); break; } } #ifdef DEBUG fprintf(stdout, "# %s reg%u reg%u %i\n", Name, c->reg0, c->reg1, c->raw_Immediate); #endif return false; }
/* * Sign a blob provided by userspace (that has had the hash function applied) * using a specific key handle. The handle is assumed to have been previously * loaded by e.g. LoadKey2. * * Note that the key signature scheme of the used key should be set to * TPM_SS_RSASSAPKCS1v15_DER. This allows the hashed input to be of any size * up to key_length_in_bytes - 11 and not be limited to size 20 like the * TPM_SS_RSASSAPKCS1v15_SHA1 signature scheme. */ static int tpm_sign(struct tpm_buf *tb, uint32_t keyhandle, unsigned char *keyauth, const unsigned char *blob, uint32_t bloblen, void *out, uint32_t outlen) { unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char enonce[TPM_NONCE_SIZE]; unsigned char authdata[SHA1_DIGEST_SIZE]; uint32_t authhandle = 0; unsigned char cont = 0; uint32_t ordinal; uint32_t datalen; int ret; ordinal = htonl(TPM_ORD_SIGN); datalen = htonl(bloblen); /* session for loading the key */ ret = oiap(tb, &authhandle, enonce); if (ret < 0) { pr_info("oiap failed (%d)\n", ret); return ret; } /* generate odd nonce */ ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE); if (ret < 0) { pr_info("tpm_get_random failed (%d)\n", ret); return ret; } /* calculate authorization HMAC value */ ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce, nonceodd, cont, sizeof(uint32_t), &ordinal, sizeof(uint32_t), &datalen, bloblen, blob, 0, 0); if (ret < 0) return ret; /* build the request buffer */ INIT_BUF(tb); store16(tb, TPM_TAG_RQU_AUTH1_COMMAND); store32(tb, TPM_SIGN_SIZE + bloblen); store32(tb, TPM_ORD_SIGN); store32(tb, keyhandle); store32(tb, bloblen); storebytes(tb, blob, bloblen); store32(tb, authhandle); storebytes(tb, nonceodd, TPM_NONCE_SIZE); store8(tb, cont); storebytes(tb, authdata, SHA1_DIGEST_SIZE); ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); if (ret < 0) { pr_info("authhmac failed (%d)\n", ret); return ret; } datalen = LOAD32(tb->data, TPM_DATA_OFFSET); ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, keyauth, SHA1_DIGEST_SIZE, sizeof(uint32_t), TPM_DATA_OFFSET, datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0, 0); if (ret < 0) { pr_info("TSS_checkhmac1 failed (%d)\n", ret); return ret; } memcpy(out, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), min(datalen, outlen)); return datalen; }
int main(int argc, char *argv[]) { uint32_t ret; STACK_TPM_BUFFER(resp); int index = 0; STACK_TPM_BUFFER( subcap );; TPM_setlog(0); /* turn off verbose output */ ParseArgs(argc, argv); while ((int)matrx[index].cap != -1) { if (cap == matrx[index].cap) { break; } index++; } if (-1 == (int)matrx[index].cap) { printf("Unknown or unsupported capability!\n"); exit(-1); } subcap.used = 0; if (matrx[index].subcap_size > 0) { if ((int)scap == -1) { printf("Need subcap parameter for this capability!\n"); exit(-1); } if (0 == prepare_subcap(cap, &subcap, scap)) { if (2 == matrx[index].subcap_size) { STORE16(subcap.buffer,0,scap); subcap.used = 2; } else if (matrx[index].subcap_size >= 4) { STORE32(subcap.buffer,0,scap); subcap.used = 4; } } } #if 0 /* This was for VTPM extensions and needs retest */ if (cap == TPM_CAP_MFR) { int idx2 = 0; while ((int)mfr_matrix[idx2].cap != -1) { if (mfr_matrix[idx2].cap == scap) { break; } idx2++; } if (mfr_matrix[idx2].subcap_size > 0) { uint32_t used = subcap.used + mfr_matrix[idx2].subcap_size; while (subcap.used < used) { if (argc <= nxtarg) { printf("Need one more parameter for this " "capability!\n"); exit(-1); } if (!strncmp("0x",argv[nxtarg],2)) { sscanf(argv[nxtarg],"%x",&sscap); } else { sscanf(argv[nxtarg],"%d",&sscap); } nxtarg++; if (2 == matrx[index].subcap_size) { STORE16(subcap.buffer, subcap.used,sscap); subcap.used += 2; } else if (matrx[index].subcap_size >= 4) { STORE32(subcap.buffer, subcap.used,sscap); subcap.used += 4; } } } } #endif if (0 == sikeyhandle) { ret = TPM_GetCapability(cap, &subcap, &resp); if (0 != ret) { printf("TPM_GetCapability returned %s.\n", TPM_GetErrMsg(ret)); exit(ret); } } else { unsigned char antiReplay[TPM_HASH_SIZE]; unsigned char signature[2048]; uint32_t signaturelen = sizeof(signature); pubkeydata pubkey; RSA * rsa; unsigned char sighash[TPM_HASH_SIZE]; unsigned char * buffer = NULL; unsigned char * sigkeyhashptr = NULL; unsigned char sigkeypasshash[TPM_HASH_SIZE]; if (NULL != sikeypass) { TSS_sha1(sikeypass,strlen(sikeypass),sigkeypasshash); sigkeyhashptr = sigkeypasshash; } TSS_gennonce(antiReplay); ret = TPM_GetPubKey(sikeyhandle, sigkeyhashptr, &pubkey); if (0 != ret) { printf("Error while trying to access the signing key's public key.\n"); exit(-1); } rsa = TSS_convpubkey(&pubkey); ret = TPM_GetCapabilitySigned(sikeyhandle, sigkeyhashptr, antiReplay, cap, &subcap, &resp, signature, &signaturelen); if (0 != ret) { printf("TPM_GetCapabilitySigned returned %s.\n", TPM_GetErrMsg(ret)); exit(ret); } buffer = malloc(resp.used+TPM_NONCE_SIZE); if (NULL == buffer) { printf("Could not allocate buffer.\n"); exit(-1); } memcpy(&buffer[0], resp.buffer, resp.used); memcpy(&buffer[resp.used], antiReplay, TPM_NONCE_SIZE); TSS_sha1(buffer, resp.used+TPM_NONCE_SIZE, sighash); free(buffer); ret = RSA_verify(NID_sha1, sighash,TPM_HASH_SIZE, signature,signaturelen, rsa); if (1 != ret) { printf("Error: Signature verification failed.\n"); exit(-1); } } if (0 == resp.used) { printf("Empty response.\n"); } else { if (-1 == (int)scap) { printf("Result for capability 0x%x is : ",cap); } else { printf("Result for capability 0x%x, subcapability 0x%x is : ",cap,scap); } if (TYPE_BOOL == matrx[index].result_size) { if (resp.buffer[0] == 0) { printf("FALSE\n"); } else { printf("TRUE\n"); } } else if (TYPE_UINT32 == matrx[index].result_size) { uint32_t rsp; rsp = LOAD32(resp.buffer,0); printf("0x%08X = %d\n",rsp,rsp); } else if (TYPE_UINT32_ARRAY == matrx[index].result_size) { int i = 0; printf("\n"); while (i+3 < (int)resp.used) { uint32_t rsp = LOAD32(resp.buffer,i); i+=4; if (TPM_CAP_NV_LIST == cap) { /* don't zero extend, grep needs the exact value for test suite */ printf("%d. Index : %d = 0x%x.\n", i/4, rsp, rsp); } else if (TPM_CAP_KEY_HANDLE == cap) { printf("%d. keyhandle : %d.\n", i/4, rsp); } else { printf("%d. item : %d.\n", i/4, rsp); } } } else if (TYPE_STRUCTURE == matrx[index].result_size) { switch(cap) { case TPM_CAP_FLAG: { if (scap == TPM_CAP_FLAG_PERMANENT) { TPM_PERMANENT_FLAGS pf; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadPermanentFlags(&tb, 0, &pf, resp.used); if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showPermanentFlags(&pf, resp.used); } else if (scap == TPM_CAP_FLAG_VOLATILE) { TPM_STCLEAR_FLAGS sf; STACK_TPM_BUFFER(tb); TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadSTClearFlags(&tb, 0, &sf); if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showVolatileFlags(&sf); } } break; case TPM_CAP_KEY_HANDLE: { uint16_t num = LOAD16(resp.buffer, 0); uint32_t i = 0; uint32_t handle; printf("\n"); while (i < num) { handle = LOAD32(resp.buffer,2+i*4); printf("%d. handle: 0x%08X\n", i, handle); i++; } } break; case TPM_CAP_NV_INDEX: { //char scratch_info[256]; unsigned char scratch_info[256]; uint32_t scratch_info_len; TPM_NV_DATA_PUBLIC ndp; uint32_t i, c; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadNVDataPublic(&tb, 0, &ndp); if ( ( ret & ERR_MASK) != 0) { printf("Could not deserialize the TPM_NV_DATA_PUBLIC structure.\n"); exit(-1); } printf("permission.attributes : %08X\n",(unsigned int)ndp.permission.attributes); printf("ReadSTClear : %02X\n",ndp.bReadSTClear); printf("WriteSTClear : %02X\n",ndp.bWriteSTClear); printf("WriteDefine : %02X\n",ndp.bWriteDefine); printf("dataSize : %08X = %d",(unsigned int)ndp.dataSize, (unsigned int)ndp.dataSize); c = 0; for (i = 0; i < ndp.pcrInfoRead.pcrSelection.sizeOfSelect*8; i++) { if (ndp.pcrInfoRead.pcrSelection.pcrSelect[(i / 8)] & (1 << (i & 0x7))) { if (!c) printf("\nRead PCRs selected: "); else printf(", "); printf("%d", i); c++; } } if (c) { char pcrmap[4], *pf; memcpy(pcrmap, ndp.pcrInfoRead.pcrSelection.pcrSelect, ndp.pcrInfoRead.pcrSelection.sizeOfSelect); // printf("\npcrmap: %02x%02x%02x%02x\n", pcrmap[0], pcrmap[1], // pcrmap[2], pcrmap[3]); ret = TSS_GenPCRInfo(*(uint32_t *)pcrmap, scratch_info, &scratch_info_len); printf("\nRead PCR Composite: "); for (i = 0; i < 20; i++) printf("%02x", ndp.pcrInfoRead.digestAtRelease[i] & 0xff); printf("\n"); #if 1 pf = &scratch_info[5]; printf("\nCurrent PCR composite: "); for (i = 0; i < 20; i++) //printf("%02x", scratch_info.digestAtRelease[i] & 0xff); printf("%02x", pf[i] & 0xff); printf("\n"); #endif if (!ret) { printf("Matches current TPM state: "); if (!memcmp(&scratch_info[5], &ndp.pcrInfoRead.digestAtRelease, 20)) { printf("Yes\n"); } else { printf("No\n"); } } } c = 0; for (i = 0; i < ndp.pcrInfoWrite.pcrSelection.sizeOfSelect*8; i++) { if (ndp.pcrInfoWrite.pcrSelection.pcrSelect[(i / 8)] & (1 << (i & 0x7))) { if (!c) printf("\nWrite PCRs selected: "); else printf(", "); printf("%d", i); c++; } } if (c) { printf("\nWrite PCR Composite: "); for (i = 0; i < 20; i++) printf("%02x", ndp.pcrInfoWrite.digestAtRelease[i] & 0xff); printf("\n"); } } break; case TPM_CAP_HANDLE: { uint16_t num = LOAD16(resp.buffer, 0); uint16_t x = 0; while (x < num) { uint32_t handle = LOAD32(resp.buffer, sizeof(num)+4*x); printf("%02d. 0x%08X\n",x,handle); x++; } } break; case TPM_CAP_VERSION_VAL: { int i = 0; TPM_CAP_VERSION_INFO cvi; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadCapVersionInfo(&tb, 0, &cvi); if ( ( ret & ERR_MASK) != 0) { printf("Could not read the version info structure.\n"); exit(-1); } printf("\n"); printf("major : 0x%02X\n",cvi.version.major); printf("minor : 0x%02X\n",cvi.version.minor); printf("revMajor : 0x%02X\n",cvi.version.revMajor); printf("revMinor : 0x%02X\n",cvi.version.revMinor); printf("specLevel : 0x%04X\n",cvi.specLevel); printf("errataRev : 0x%02X\n",cvi.errataRev); printf("VendorID : "); while (i < 4) { printf("%02X ",cvi.tpmVendorID[i]); i++; } printf("\n"); /* Print vendor ID in text if printable */ for (i=0 ; i<4 ; i++) { if (isprint(cvi.tpmVendorID[i])) { if (i == 0) { printf("VendorID : "); } printf("%c", cvi.tpmVendorID[i]); } else { break; } } printf("\n"); printf("[not displaying vendor specific information]\n"); } break; #if 0 /* kgold: I don't think these are valid cap values */ case TPM_CAP_FLAG_PERMANENT: { TPM_PERMANENT_FLAGS pf; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); if (resp.used == 21) { ret = TPM_ReadPermanentFlagsPre103(&tb, 0, &pf); } else { ret = TPM_ReadPermanentFlags(&tb, 0, &pf); } if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showPermanentFlags(&pf, resp.used); } break; case TPM_CAP_FLAG_VOLATILE: { TPM_STCLEAR_FLAGS sf; STACK_TPM_BUFFER(tb); TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadSTClearFlags(&tb, 0, &sf); if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showVolatileFlags(&sf); } break; #endif case TPM_CAP_DA_LOGIC: { uint32_t ctr; TPM_BOOL lim = FALSE; TPM_DA_INFO dainfo; TPM_DA_INFO_LIMITED dainfo_lim; STACK_TPM_BUFFER(tb); TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadDAInfo(&tb, 0, &dainfo); if ( ( ret & ERR_MASK) != 0 || ret > resp.used) { ret = TPM_ReadDAInfoLimited(&tb, 0, &dainfo_lim); if ( (ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } else { lim = TRUE; } } printf("\n"); if (lim) { printf("State : %d\n",dainfo_lim.state); printf("Actions : 0x%08x\n",dainfo_lim.actionAtThreshold.actions); ctr = 0; while (ctr < dainfo_lim.vendorData.size) { printf("%02x ",(unsigned char)dainfo_lim.vendorData.buffer[ctr]); ctr++; } } else { printf("State : %d\n",dainfo.state); printf("currentCount : %d\n",dainfo.currentCount); printf("thresholdCount : %d\n",dainfo.thresholdCount); printf("Actions : 0x%08x\n",dainfo.actionAtThreshold.actions); printf("actionDependValue : %d\n",dainfo.actionDependValue); #if 0 ctr = 0; while (ctr < dainfo_lim.vendorData.size) { printf("%02x ",(unsigned char)dainfo_lim.vendorData.buffer[ctr]); ctr++; } #endif } } break; } } else if (TYPE_VARIOUS == matrx[index].result_size) { switch(cap) { case TPM_CAP_MFR: switch (scap) { case TPM_CAP_PROCESS_ID: { uint32_t rsp; rsp = LOAD32(resp.buffer,0); printf("%d\n",rsp); } break; } break; /* TPM_CAP_MFR */ default: /* Show booleans */ if (scap == TPM_CAP_PROP_OWNER || scap == TPM_CAP_PROP_DAA_INTERRUPT ) { if (0 == resp.buffer[0]) { printf("FALSE\n"); } else { printf("TRUE\n"); } } else /* check for array of 4 UINTs */ if (scap == TPM_CAP_PROP_TIS_TIMEOUT /* || scap == TPM_CAP_PROP_TIMEOUTS */) { int i = 0; while (i < 4) { uint32_t val = LOAD32(resp.buffer,i * 4); printf("%d ", val); i++; } printf("\n"); } else /* check for TPM_STARTUP_EFFECTS */ if (scap == TPM_CAP_PROP_STARTUP_EFFECT) { TPM_STARTUP_EFFECTS se = 0; ret = TPM_ReadStartupEffects(resp.buffer, &se); if ( ( ret & ERR_MASK ) != 0 ) { printf("Could not read startup effects structure.\n"); exit(-1); } printf("0x%08X=%d\n", (unsigned int)se, (unsigned int)se); printf("\n"); printf("Startup effects:\n"); printf("Effect on audit digest: %s\n", (se & (1 << 7)) ? "none" : "active"); printf("Audit Digest on TPM_Startup(ST_CLEAR): %s\n", ( se & (1 << 6)) ? "set to NULL" : "not set to NULL" ); printf("Audit Digest on TPM_Startup(any) : %s\n", ( se & (1 << 5)) ? "set to NULL" : "not set to NULL" ); printf("TPM_RT_KEY resource initialized on TPM_Startup(ST_ANY) : %s\n", (se & ( 1 << 4)) ? "yes" : "no"); printf("TPM_RT_AUTH resource initialized on TPM_Startup(ST_STATE) : %s\n", (se & ( 1 << 3)) ? "yes" : "no"); printf("TPM_RT_HASH resource initialized on TPM_Startup(ST_STATE) : %s\n", (se & ( 1 << 2)) ? "yes" : "no"); printf("TPM_RT_TRANS resource initialized on TPM_Startup(ST_STATE) : %s\n", (se & ( 1 << 1)) ? "yes" : "no"); printf("TPM_RT_CONTEXT session initialized on TPM_Startup(ST_STATE): %s\n", (se & ( 1 << 0)) ? "yes" : "no"); } else /* check for array of 3 UINTs */ if (scap == TPM_CAP_PROP_DURATION) { int i = 0; while (i < 4*3) { uint32_t val = LOAD32(resp.buffer,i); printf("%d ", val); i+= 4; } printf("\n"); } else /* check for TPM_COUNT_ID */ if (scap == TPM_CAP_PROP_ACTIVE_COUNTER) { uint32_t val = LOAD32(resp.buffer,0); printf("0x%08X=%d",val,val); if (0xffffffff == val) { printf(" (no counter is active)"); } printf("\n"); } else { /* just a single UINT32 */ printf("%ld=0x%08lX.\n", (long)LOAD32(resp.buffer, 0), (long)LOAD32(resp.buffer, 0)); } } } } printf("\n"); exit(0); }
/* * Have the TPM seal(encrypt) the trusted key, possibly based on * Platform Configuration Registers (PCRs). AUTH1 for sealing key. */ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, uint32_t keyhandle, const unsigned char *keyauth, const unsigned char *data, uint32_t datalen, unsigned char *blob, uint32_t *bloblen, const unsigned char *blobauth, const unsigned char *pcrinfo, uint32_t pcrinfosize) { struct osapsess sess; struct tpm_digests *td; unsigned char cont; uint32_t ordinal; uint32_t pcrsize; uint32_t datsize; int sealinfosize; int encdatasize; int storedsize; int ret; int i; /* alloc some work space for all the hashes */ td = kmalloc(sizeof *td, GFP_KERNEL); if (!td) return -ENOMEM; /* get session for sealing key */ ret = osap(tb, &sess, keyauth, keytype, keyhandle); if (ret < 0) goto out; dump_sess(&sess); /* calculate encrypted authorization value */ memcpy(td->xorwork, sess.secret, SHA1_DIGEST_SIZE); memcpy(td->xorwork + SHA1_DIGEST_SIZE, sess.enonce, SHA1_DIGEST_SIZE); ret = TSS_sha1(td->xorwork, SHA1_DIGEST_SIZE * 2, td->xorhash); if (ret < 0) goto out; ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE); if (ret != TPM_NONCE_SIZE) goto out; ordinal = htonl(TPM_ORD_SEAL); datsize = htonl(datalen); pcrsize = htonl(pcrinfosize); cont = 0; /* encrypt data authorization key */ for (i = 0; i < SHA1_DIGEST_SIZE; ++i) td->encauth[i] = td->xorhash[i] ^ blobauth[i]; /* calculate authorization HMAC value */ if (pcrinfosize == 0) { /* no pcr info specified */ ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, sess.enonce, td->nonceodd, cont, sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, td->encauth, sizeof(uint32_t), &pcrsize, sizeof(uint32_t), &datsize, datalen, data, 0, 0); } else { /* pcr info specified */ ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, sess.enonce, td->nonceodd, cont, sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, td->encauth, sizeof(uint32_t), &pcrsize, pcrinfosize, pcrinfo, sizeof(uint32_t), &datsize, datalen, data, 0, 0); } if (ret < 0) goto out; /* build and send the TPM request packet */ INIT_BUF(tb); store16(tb, TPM_TAG_RQU_AUTH1_COMMAND); store32(tb, TPM_SEAL_SIZE + pcrinfosize + datalen); store32(tb, TPM_ORD_SEAL); store32(tb, keyhandle); storebytes(tb, td->encauth, SHA1_DIGEST_SIZE); store32(tb, pcrinfosize); storebytes(tb, pcrinfo, pcrinfosize); store32(tb, datalen); storebytes(tb, data, datalen); store32(tb, sess.handle); storebytes(tb, td->nonceodd, TPM_NONCE_SIZE); store8(tb, cont); storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE); ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); if (ret < 0) goto out; /* calculate the size of the returned Blob */ sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t)); encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize); storedsize = sizeof(uint32_t) + sizeof(uint32_t) + sealinfosize + sizeof(uint32_t) + encdatasize; /* check the HMAC in the response */ ret = TSS_checkhmac1(tb->data, ordinal, td->nonceodd, sess.secret, SHA1_DIGEST_SIZE, storedsize, TPM_DATA_OFFSET, 0, 0); /* copy the returned blob to caller */ if (!ret) { memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize); *bloblen = storedsize; } out: kfree(td); return ret; }
/* * use the AUTH2_COMMAND form of unseal, to authorize both key and blob */ static int tpm_unseal(struct tpm_buf *tb, uint32_t keyhandle, const unsigned char *keyauth, const unsigned char *blob, int bloblen, const unsigned char *blobauth, unsigned char *data, unsigned int *datalen) { unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char enonce1[TPM_NONCE_SIZE]; unsigned char enonce2[TPM_NONCE_SIZE]; unsigned char authdata1[SHA1_DIGEST_SIZE]; unsigned char authdata2[SHA1_DIGEST_SIZE]; uint32_t authhandle1 = 0; uint32_t authhandle2 = 0; unsigned char cont = 0; uint32_t ordinal; uint32_t keyhndl; int ret; /* sessions for unsealing key and data */ ret = oiap(tb, &authhandle1, enonce1); if (ret < 0) { pr_info("trusted_key: oiap failed (%d)\n", ret); return ret; } ret = oiap(tb, &authhandle2, enonce2); if (ret < 0) { pr_info("trusted_key: oiap failed (%d)\n", ret); return ret; } ordinal = htonl(TPM_ORD_UNSEAL); keyhndl = htonl(SRKHANDLE); ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE); if (ret != TPM_NONCE_SIZE) { pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); return ret; } ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, enonce1, nonceodd, cont, sizeof(uint32_t), &ordinal, bloblen, blob, 0, 0); if (ret < 0) return ret; ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE, enonce2, nonceodd, cont, sizeof(uint32_t), &ordinal, bloblen, blob, 0, 0); if (ret < 0) return ret; /* build and send TPM request packet */ INIT_BUF(tb); store16(tb, TPM_TAG_RQU_AUTH2_COMMAND); store32(tb, TPM_UNSEAL_SIZE + bloblen); store32(tb, TPM_ORD_UNSEAL); store32(tb, keyhandle); storebytes(tb, blob, bloblen); store32(tb, authhandle1); storebytes(tb, nonceodd, TPM_NONCE_SIZE); store8(tb, cont); storebytes(tb, authdata1, SHA1_DIGEST_SIZE); store32(tb, authhandle2); storebytes(tb, nonceodd, TPM_NONCE_SIZE); store8(tb, cont); storebytes(tb, authdata2, SHA1_DIGEST_SIZE); ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); if (ret < 0) { pr_info("trusted_key: authhmac failed (%d)\n", ret); return ret; } *datalen = LOAD32(tb->data, TPM_DATA_OFFSET); ret = TSS_checkhmac2(tb->data, ordinal, nonceodd, keyauth, SHA1_DIGEST_SIZE, blobauth, SHA1_DIGEST_SIZE, sizeof(uint32_t), TPM_DATA_OFFSET, *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0, 0); if (ret < 0) { pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret); return ret; } memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen); return 0; }
/* * verify the AUTH2_COMMAND (unseal) result from TPM */ static int TSS_checkhmac2(unsigned char *buffer, const uint32_t command, const unsigned char *ononce, const unsigned char *key1, unsigned int keylen1, const unsigned char *key2, unsigned int keylen2, ...) { uint32_t bufsize; uint16_t tag; uint32_t ordinal; uint32_t result; unsigned char *enonce1; unsigned char *continueflag1; unsigned char *authdata1; unsigned char *enonce2; unsigned char *continueflag2; unsigned char *authdata2; unsigned char testhmac1[SHA1_DIGEST_SIZE]; unsigned char testhmac2[SHA1_DIGEST_SIZE]; unsigned char paramdigest[SHA1_DIGEST_SIZE]; struct sdesc *sdesc; unsigned int dlen; unsigned int dpos; va_list argp; int ret; bufsize = LOAD32(buffer, TPM_SIZE_OFFSET); tag = LOAD16(buffer, 0); ordinal = command; result = LOAD32N(buffer, TPM_RETURN_OFFSET); if (tag == TPM_TAG_RSP_COMMAND) return 0; if (tag != TPM_TAG_RSP_AUTH2_COMMAND) return -EINVAL; authdata1 = buffer + bufsize - (SHA1_DIGEST_SIZE + 1 + SHA1_DIGEST_SIZE + SHA1_DIGEST_SIZE); authdata2 = buffer + bufsize - (SHA1_DIGEST_SIZE); continueflag1 = authdata1 - 1; continueflag2 = authdata2 - 1; enonce1 = continueflag1 - TPM_NONCE_SIZE; enonce2 = continueflag2 - TPM_NONCE_SIZE; sdesc = init_sdesc(hashalg); if (IS_ERR(sdesc)) { pr_info("trusted_key: can't alloc %s\n", hash_alg); return PTR_ERR(sdesc); } ret = crypto_shash_init(&sdesc->shash); if (ret < 0) goto out; ret = crypto_shash_update(&sdesc->shash, (const u8 *)&result, sizeof result); if (ret < 0) goto out; ret = crypto_shash_update(&sdesc->shash, (const u8 *)&ordinal, sizeof ordinal); if (ret < 0) goto out; va_start(argp, keylen2); for (;;) { dlen = va_arg(argp, unsigned int); if (dlen == 0) break; dpos = va_arg(argp, unsigned int); ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); if (ret < 0) break; } va_end(argp); if (!ret) ret = crypto_shash_final(&sdesc->shash, paramdigest); if (ret < 0) goto out; ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce1, TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); if (ret < 0) goto out; if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { ret = -EINVAL; goto out; } ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, paramdigest, TPM_NONCE_SIZE, enonce2, TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); if (ret < 0) goto out; if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) ret = -EINVAL; out: kfree(sdesc); return ret; }
/* * Load a TPM key from the blob provided by userspace */ static int tpm_loadkey2(struct tpm_buf *tb, uint32_t keyhandle, unsigned char *keyauth, const unsigned char *keyblob, int keybloblen, uint32_t *newhandle) { unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char enonce[TPM_NONCE_SIZE]; unsigned char authdata[SHA1_DIGEST_SIZE]; uint32_t authhandle = 0; unsigned char cont = 0; uint32_t ordinal; int ret; ordinal = htonl(TPM_ORD_LOADKEY2); /* session for loading the key */ ret = oiap(tb, &authhandle, enonce); if (ret < 0) { pr_info("oiap failed (%d)\n", ret); return ret; } /* generate odd nonce */ ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE); if (ret < 0) { pr_info("tpm_get_random failed (%d)\n", ret); return ret; } /* calculate authorization HMAC value */ ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce, nonceodd, cont, sizeof(uint32_t), &ordinal, keybloblen, keyblob, 0, 0); if (ret < 0) return ret; /* build the request buffer */ INIT_BUF(tb); store16(tb, TPM_TAG_RQU_AUTH1_COMMAND); store32(tb, TPM_LOADKEY2_SIZE + keybloblen); store32(tb, TPM_ORD_LOADKEY2); store32(tb, keyhandle); storebytes(tb, keyblob, keybloblen); store32(tb, authhandle); storebytes(tb, nonceodd, TPM_NONCE_SIZE); store8(tb, cont); storebytes(tb, authdata, SHA1_DIGEST_SIZE); ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); if (ret < 0) { pr_info("authhmac failed (%d)\n", ret); return ret; } ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, keyauth, SHA1_DIGEST_SIZE, 0, 0); if (ret < 0) { pr_info("TSS_checkhmac1 failed (%d)\n", ret); return ret; } *newhandle = LOAD32(tb->data, TPM_DATA_OFFSET); return 0; }
uint32_t TPM_CreateMigrationBlob(unsigned int keyhandle, unsigned char *keyauth, unsigned char *migauth, int migtype, unsigned char *migblob, unsigned int migblen, unsigned char *keyblob, unsigned int keyblen, unsigned char *rndblob, unsigned int *rndblen, unsigned char *outblob, unsigned int *outblen) { unsigned char create_mig_fmt[] = "00 c3 T l l s % @ l % o % l % o %"; unsigned char create_mig_fmt_noauth[] = "00 c2 T l l s % @ l % o %"; uint32_t ret; unsigned char tpmdata[TPM_MAX_BUFF_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char enonce1[TPM_NONCE_SIZE]; unsigned char enonce2[TPM_NONCE_SIZE]; unsigned char c; uint32_t ordinal; uint32_t keyhndl; uint32_t datsize; uint16_t migscheme; uint32_t authhandle1; uint32_t authhandle2; unsigned char authdata1[TPM_HASH_SIZE]; unsigned char authdata2[TPM_HASH_SIZE]; uint32_t size1; uint32_t size2; keydata k; /* check input arguments */ if (migauth == NULL || migblob == NULL || keyblob == NULL) return ERR_NULL_ARG; if (rndblob == NULL || rndblen == NULL || outblob == NULL || outblen == NULL) return ERR_NULL_ARG; if (migtype != 1 && migtype != 2) return ERR_BAD_ARG; TSS_KeyExtract(keyblob, &k); /* move data to Network byte order variables for HMAC calculation */ ordinal = htonl(0x28); keyhndl = htonl(keyhandle); migscheme = htons(migtype); datsize = htonl(k.privkeylen); /* generate odd nonce */ TSS_gennonce(nonceodd); c = 0; if (keyauth != NULL) { /* parent key password is required */ /* open TWO OIAP sessions: Parent and Migrating Key */ ret = TSS_OIAPopen(&authhandle1, enonce1); if (ret != 0) return ret; ret = TSS_OIAPopen(&authhandle2, enonce2); if (ret != 0) return ret; /* calculate Parent KEY authorization HMAC value */ ret = TSS_authhmac(authdata1, keyauth, TPM_HASH_SIZE, enonce1, nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_U16_SIZE, &migscheme, migblen, migblob, TPM_U32_SIZE, &datsize, k.privkeylen, k.encprivkey, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* calculate Migration authorization HMAC value */ ret = TSS_authhmac(authdata2, migauth, TPM_HASH_SIZE, enonce2, nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_U16_SIZE, &migscheme, migblen, migblob, TPM_U32_SIZE, &datsize, k.privkeylen, k.encprivkey, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* build the request buffer */ ret = TSS_buildbuff(create_mig_fmt, tpmdata, ordinal, keyhndl, migscheme, migblen, migblob, k.privkeylen, k.encprivkey, authhandle1, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata1, authhandle2, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata2); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* transmit buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "CreateMigrationBlob"); if (ret != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* validate HMAC in response */ size1 = LOAD32(tpmdata, TPM_DATA_OFFSET); size2 = LOAD32(tpmdata, TPM_DATA_OFFSET + TPM_U32_SIZE + size1); if (size1 != 0) { ret = TSS_checkhmac2(tpmdata, ordinal, nonceodd, keyauth, TPM_HASH_SIZE, migauth, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, size1, TPM_DATA_OFFSET + TPM_U32_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET + TPM_U32_SIZE + size1, size2, TPM_DATA_OFFSET + TPM_U32_SIZE + size1 + TPM_U32_SIZE, 0, 0); } else { ret = TSS_checkhmac2(tpmdata, ordinal, nonceodd, keyauth, TPM_HASH_SIZE, migauth, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, TPM_U32_SIZE, TPM_DATA_OFFSET + TPM_U32_SIZE, size2, TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE, 0, 0); } TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); if (ret != 0) return ret; } else { /* no parent key password required */ /* open OIAP session for the Migrating Key */ ret = TSS_OIAPopen(&authhandle1, enonce1); if (ret != 0) return ret; /* calculate Migration authorization HMAC value */ ret = TSS_authhmac(authdata1, migauth, TPM_HASH_SIZE, enonce1, nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_U16_SIZE, &migscheme, migblen, migblob, TPM_U32_SIZE, &datsize, k.privkeylen, k.encprivkey, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle1); return ret; } /* build the request buffer */ ret = TSS_buildbuff(create_mig_fmt_noauth, tpmdata, ordinal, keyhndl, migscheme, migblen, migblob, k.privkeylen, k.encprivkey, authhandle1, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata1); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle1); return ret; } /* transmit buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "CreateMigrationBlob"); if (ret != 0) { TSS_OIAPclose(authhandle1); return ret; } /* check HMAC in response */ size1 = LOAD32(tpmdata, TPM_DATA_OFFSET); size2 = LOAD32(tpmdata, TPM_DATA_OFFSET + TPM_U32_SIZE + size1); if (size1 != 0) { ret = TSS_checkhmac1(tpmdata, ordinal, nonceodd, migauth, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, size1, TPM_DATA_OFFSET + TPM_U32_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET + TPM_U32_SIZE + size1, size2, TPM_DATA_OFFSET + TPM_U32_SIZE + size1 + TPM_U32_SIZE, 0, 0); } else { ret = TSS_checkhmac1(tpmdata, ordinal, nonceodd, migauth, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, TPM_U32_SIZE, TPM_DATA_OFFSET + TPM_U32_SIZE, size2, TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE, 0, 0); } TSS_OIAPclose(authhandle1); if (ret != 0) return ret; } memcpy(rndblob, tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE, size1); memcpy(outblob, tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE + size1 + TPM_U32_SIZE, size2); *rndblen = size1; *outblen = size2; return 0; }
uint32_t TPM_ConvertMigrationBlob(unsigned int keyhandle, unsigned char *keyauth, unsigned char *rndblob, unsigned int rndblen, unsigned char *keyblob, unsigned int keyblen, unsigned char *encblob, unsigned int *encblen) { unsigned char convert_mig_fmt[] = "00 c2 T l l @ @ l % o %"; uint32_t ret; unsigned char tpmdata[TPM_MAX_BUFF_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char evennonce[TPM_NONCE_SIZE]; unsigned char pubauth[TPM_HASH_SIZE]; unsigned char c; uint32_t ordinal; uint32_t authhandle; uint32_t keyhndl; uint32_t rndsize; uint32_t datsize; int size; /* check input arguments */ if (keyauth == NULL || rndblob == NULL || keyblob == NULL || encblob == NULL || encblen == NULL) return ERR_NULL_ARG; /* generate odd nonce */ TSS_gennonce(nonceodd); /* Open OIAP Session */ ret = TSS_OIAPopen(&authhandle, evennonce); if (ret != 0) return ret; /* move Network byte order data to variables for hmac calculation */ ordinal = htonl(0x2A); keyhndl = htonl(keyhandle); rndsize = htonl(rndblen); datsize = htonl(keyblen); c = 0; /* calculate authorization HMAC value */ ret = TSS_authhmac(pubauth, keyauth, TPM_HASH_SIZE, evennonce, nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_U32_SIZE, &datsize, keyblen, keyblob, TPM_U32_SIZE, &rndsize, rndblen, rndblob, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle); return ret; } /* build the request buffer */ ret = TSS_buildbuff(convert_mig_fmt, tpmdata, ordinal, keyhndl, keyblen, keyblob, rndblen, rndblob, authhandle, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, pubauth); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "ConvertMigrationBlob"); if (ret != 0) { TSS_OIAPclose(authhandle); return ret; } TSS_OIAPclose(authhandle); size = LOAD32(tpmdata, TPM_DATA_OFFSET); ret = TSS_checkhmac1(tpmdata, ordinal, nonceodd, keyauth, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, size, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0); if (ret != 0) return ret; memcpy(encblob, tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE, size); *encblen = size; return 0; }
int main(int argc, char *argv[]) { int ret; unsigned char familyTable[256]; uint32_t familyTableSize = sizeof(familyTable); unsigned char delegateTable[256]; uint32_t delegateTableSize = sizeof(delegateTable); uint32_t i = 0; (void)argv; (void)argc; TPM_setlog(0); ret = TPM_Delegate_ReadTable(familyTable, &familyTableSize, delegateTable, &delegateTableSize); if (0 != ret) { printf("Delegate_ReadTable returned error '%s' (%d).\n", TPM_GetErrMsg(ret), ret); } else { STACK_TPM_BUFFER( buffer ) i = 0; SET_TPM_BUFFER( &buffer, familyTable, familyTableSize) while (i < familyTableSize) { TPM_FAMILY_TABLE_ENTRY fte; ret = TPM_ReadFamilyTableEntry(&buffer, i, &fte); if (0 == (ret & ERR_MASK) && ret > 0) { printf("Family Table Entry:\n" "familyLabel : %d\n" "familyID : "OUT_FORMAT("%d","%d")"\n" "verificationCount : "OUT_FORMAT("%d","%d")"\n" "flags : "OUT_FORMAT("0x%x","0x%x")"\n\n", fte.familyLabel, fte.familyID, fte.verificationCount, fte.flags); } else { printf("Error %s from TPM_ReadFamilyTableEntry.\n", TPM_GetErrMsg(ret)); return ret; } i += ret; } SET_TPM_BUFFER( &buffer, delegateTable, delegateTableSize); i = 0; while (i < delegateTableSize) { TPM_DELEGATE_PUBLIC dtp; TPM_DELEGATE_INDEX didx = LOAD32(buffer.buffer, i); i += 4; ret = TPM_ReadDelegatePublic(&buffer, i, &dtp); if (0 == (ret & ERR_MASK) && ret > 0) { printf("\n\nDelegate Table Entry:\n" "index : "OUT_FORMAT("%d","%d")"\n" "rowLabel : %d\n" "permissions : "OUT_FORMAT("0x%08x, 0x%08x","0x%08x, 0x%08x")"\n" "familyID : "OUT_FORMAT("%d","%d")"\n" "verificationCount : "OUT_FORMAT("%d","%d")"\n", didx, dtp.rowLabel, dtp.permissions.per1, dtp.permissions.per2, dtp.familyID, dtp.verificationCount); } else { printf("Error %s from TPM_ReadDelegatePublic.\n", TPM_GetErrMsg(ret)); exit(ret); } i += ret; } printf("\n"); ret = 0; } exit(ret); }
int main(int argc, char * argv[]) { uint32_t ret = 0; int i = 0; int verbose = FALSE; uint32_t migkeyhandle = 0; char * filename = NULL; unsigned char * buffer = NULL; unsigned char keypasshash[TPM_HASH_SIZE]; char * keypass = NULL; uint16_t migscheme = TPM_MS_MIGRATE; unsigned char * keyhashptr = NULL; i = 1; TPM_setlog(0); while (i < argc) { if (!strcmp("-if",argv[i])) { i++; if (i < argc) { filename = argv[i]; } else { printf("Missing mandatory parameter for -if.\n"); usage(); } } else if (!strcmp("-hp",argv[i])) { i++; if (i < argc) { sscanf(argv[i],"%x",&migkeyhandle); } else { printf("Missing mandatory parameter for -hp.\n"); usage(); } } else if (!strcmp("-pwdp",argv[i])) { i++; if (i < argc) { keypass = argv[i]; } else { printf("Missing mandatory parameter for -pwdp.\n"); usage(); } } else if (!strcmp("-rewrap",argv[i])) { migscheme = TPM_MS_REWRAP; } else if (!strcmp("-v",argv[i])) { verbose = TRUE; TPM_setlog(1); } else if (!strcmp("-h",argv[i])) { usage(); } else { printf("\n%s is not a valid option\n", argv[i]); usage(); } i++; } if (0 == migkeyhandle || NULL == filename) { printf("Missing mandatory parameter.\n"); usage(); } if (NULL != keypass) { TSS_sha1(keypass,strlen(keypass),keypasshash); keyhashptr = keypasshash; } else { keyhashptr = NULL; } buffer = readFile(filename); if (NULL != buffer) { int offset = 0; unsigned char * encblob = NULL; uint32_t encsize = 0; unsigned char * rndblob = NULL; uint32_t rndsize = 0; uint32_t keysize = 0; unsigned char * keyblob = NULL; unsigned char * outblob = NULL; uint32_t outblen; keydata newkey; STACK_TPM_BUFFER( tb ); rndsize = LOAD32(buffer,offset); offset += 4; rndblob = &buffer[offset]; offset += rndsize; encsize = LOAD32(buffer,offset); offset += 4; encblob = &buffer[offset]; offset += encsize; keysize = LOAD32(buffer,offset); offset += 4; keyblob = &buffer[offset]; offset += keysize; SET_TPM_BUFFER(&tb, keyblob, keysize); TSS_KeyExtract(&tb, 0,&newkey); outblob = malloc(encsize); if (NULL == outblob) { printf("Error allocating memory for decrypted blob.\n"); exit(-1); } outblen = encsize; if (TPM_MS_REWRAP == migscheme || 0 == rndsize) { memcpy(newkey.encData.buffer, encblob, encsize); newkey.encData.size = outblen; ret = 0; } else { ret = TPM_ConvertMigrationBlob(migkeyhandle, keyhashptr, rndblob, rndsize, encblob, encsize, outblob, &outblen); if (0 == ret) { memcpy(newkey.encData.buffer, outblob, outblen); newkey.encData.size = outblen; } else { printf("ConvertMigrationBlob returned '%s' (0x%x).\n", TPM_GetErrMsg(ret), ret); } } if (0 == ret) { uint32_t newhandle; ret = TPM_LoadKey(migkeyhandle, keyhashptr, &newkey, &newhandle); if (0 == ret) { printf("Successfully loaded key into TPM.\n" "New Key Handle = %08X\n", newhandle); } else { printf("LoadKey returned '%s' (0x%x).\n", TPM_GetErrMsg(ret), ret); } } } return ret; }
int main(int argc, char * argv[]) { char * migrationkeyfile = NULL; char * filename = NULL; char * migrationKeyPassword = NULL; unsigned char migrationkeyUsageAuth[TPM_DIGEST_SIZE]; unsigned char * passptr = NULL; uint32_t ret = 0; int i = 0; keydata migrationkey; int verbose = FALSE; uint32_t migrationkeyhandle = 0; unsigned char * buffer = NULL; uint32_t bufferSize = 0; i = 1; TPM_setlog(0); while (i < argc) { if (!strcmp("-if",argv[i])) { i++; if (i < argc) { filename = argv[i]; } else { printf("Missing parameter for -if.\n"); usage(); exit(-1); } } else if (!strcmp("-pwdm",argv[i])) { i++; if (i < argc) { migrationKeyPassword = argv[i]; } else { printf("Missing parameter for -pwdm.\n"); usage(); exit(-1); } } else if (!strcmp("-hm",argv[i])) { i++; if (i < argc) { sscanf(argv[i],"%x",&migrationkeyhandle); } else { printf("Missing parameter for -hm.\n"); usage(); exit(-1); } } else if (!strcmp("-ik",argv[i])) { i++; if (i < argc) { migrationkeyfile = argv[i]; } else { printf("Missing parameter for -ik.\n"); usage(); exit(-1); } } else if (!strcmp("-v",argv[i])) { verbose = TRUE; TPM_setlog(1); } else if (!strcmp("-h",argv[i])) { usage(); exit(-1); } else { printf("\n%s is not a valid option\n", argv[i]); usage(); exit(-1); } i++; } if (NULL == migrationkeyfile || NULL == filename || -1 == (int)migrationkeyhandle) { printf("Missing or wrong parameter.\n"); usage(); exit(-1); } if (NULL != migrationKeyPassword) { TSS_sha1(migrationKeyPassword, strlen(migrationKeyPassword), migrationkeyUsageAuth); passptr = migrationkeyUsageAuth; } /* * load the key to be migrated from a file. */ ret = 0; buffer = readFile(filename, &bufferSize); if (NULL != buffer) { unsigned int offset = 0; unsigned char * encblob = NULL; uint32_t encsize = 0; unsigned char * rndblob = NULL; uint32_t rndsize = 0; uint32_t keysize = 0; unsigned char * keyblob = NULL; keydata tobemigkey; STACK_TPM_BUFFER(tb) rndsize = LOAD32(buffer,offset); offset += 4; if (offset > bufferSize) { printf("Bad input file. Exiting.\n"); return -1; } rndblob = &buffer[offset]; offset += rndsize; if (offset > bufferSize) { printf("Bad input file. Exiting.\n"); return -1; } encsize = LOAD32(buffer,offset); offset += 4; if (offset > bufferSize) { printf("Bad input file. Exiting.\n"); return -1; } encblob = &buffer[offset]; offset += encsize; if (offset > bufferSize) { printf("Bad input file. Exiting.\n"); return -1; } keysize = LOAD32(buffer,offset); offset += 4; if (offset > bufferSize) { printf("Bad input file. Exiting.\n"); return -1; } keyblob = &buffer[offset]; offset += keysize; if (offset != bufferSize) { printf("Bad input file. Exiting"); return -1; } SET_TPM_BUFFER(&tb, keyblob, keysize); TSS_KeyExtract(&tb,0,&tobemigkey); /* * load the migration key from the destination * TPM from a file. Need the public key part of * that key. */ ret = loadKey(migrationkeyfile, &migrationkey); if (0 == ret) { STACK_TPM_BUFFER(keyblob) uint32_t keyblen = 0; unsigned char * reencData = malloc(encsize); uint32_t reencDataSize = encsize; if (NULL == encblob || NULL == reencData) { printf("Could not get memory for encryted private key blob.\n"); exit (-1); } ret = TPM_WriteKeyPub(&keyblob, &migrationkey); if (ret & ERR_MASK) { printf("Could not serialize the keydata!\n"); free(reencData); exit(-1); } keyblen = ret; ret = TPM_MigrateKey(migrationkeyhandle, passptr, keyblob.buffer, keyblen, encblob, encsize, reencData, &reencDataSize); if (0 == ret) { STACK_TPM_BUFFER(keybuf) // serialize the key to be migrated ret = TPM_WriteKey(&keybuf,&tobemigkey); if (ret > 0) { unsigned int keybuflen = ret; FILE * f = fopen(filename,"wb"); if (NULL != f) { struct tpm_buffer *filebuf = TSS_AllocTPMBuffer(10240); if (NULL != filebuf) { int l; l = TSS_buildbuff("@ @ @",filebuf, rndsize, rndblob, reencDataSize, reencData, keybuflen, keybuf.buffer); fwrite(filebuf->buffer, l, 1, f); fclose(f); printf("Wrote migration blob and associated data to file.\n"); ret = 0; TSS_FreeTPMBuffer(filebuf); } else { printf("Error. Could not allocate memory.\n"); ret = -1; } } } } else { printf("MigrateKey returned '%s' (0x%x).\n", TPM_GetErrMsg(ret), ret); } free(reencData); } else { printf("Error. Could not load the migration key."); } } else { printf("Error. Could not load the blob from file '%s'.\n", filename); } return ret; }
uint32_t TPM_Seal(uint32_t keyhandle, unsigned char *pcrinfo, uint32_t pcrinfosize, unsigned char *keyauth, unsigned char *dataauth, unsigned char *data, unsigned int datalen, unsigned char *blob, unsigned int *bloblen) { unsigned char seal_fmt[] = "00 C2 T l l % @ @ l % o %"; uint32_t ret; int i; unsigned char tpmdata[TPM_MAX_BUFF_SIZE]; osapsess sess; unsigned char encauth[TPM_HASH_SIZE]; unsigned char pubauth[TPM_HASH_SIZE]; unsigned char xorwork[TPM_HASH_SIZE * 2]; unsigned char xorhash[TPM_HASH_SIZE]; unsigned char dummyauth[TPM_HASH_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char c; uint32_t ordinal; uint32_t pcrsize; uint32_t datsize; uint32_t keyhndl; uint16_t keytype; unsigned char *passptr1; unsigned char *passptr2; int sealinfosize; int encdatasize; int storedsize; memset(dummyauth, 0, sizeof dummyauth); /* check input arguments */ if (data == NULL || blob == NULL) return ERR_NULL_ARG; if (pcrinfosize != 0 && pcrinfo == NULL) return ERR_NULL_ARG; if (keyhandle == 0x40000000) keytype = 0x0004; else keytype = 0x0001; if (keyauth == NULL) passptr1 = dummyauth; else passptr1 = keyauth; if (dataauth == NULL) passptr2 = dummyauth; else passptr2 = dataauth; /* Open OSAP Session */ ret = TSS_OSAPopen(&sess, passptr1, keytype, keyhandle); if (ret != 0) return ret; /* calculate encrypted authorization value */ memcpy(xorwork, sess.ssecret, TPM_HASH_SIZE); memcpy(xorwork + TPM_HASH_SIZE, sess.enonce, TPM_HASH_SIZE); TSS_sha1(xorwork, TPM_HASH_SIZE * 2, xorhash); /* generate odd nonce */ TSS_gennonce(nonceodd); /* move Network byte order data to variables for hmac calculation */ ordinal = htonl(0x17); datsize = htonl(datalen); keyhndl = htonl(keyhandle); pcrsize = htonl(pcrinfosize); c = 0; /* encrypt data authorization key */ for (i = 0; i < TPM_HASH_SIZE; ++i) encauth[i] = xorhash[i] ^ passptr2[i]; /* calculate authorization HMAC value */ if (pcrinfosize == 0) { /* no pcr info specified */ ret = TSS_authhmac(pubauth, sess.ssecret, TPM_HASH_SIZE, sess.enonce, nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_HASH_SIZE, encauth, TPM_U32_SIZE, &pcrsize, TPM_U32_SIZE, &datsize, datalen, data, 0, 0); } else { /* pcr info specified */ ret = TSS_authhmac(pubauth, sess.ssecret, TPM_HASH_SIZE, sess.enonce, nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_HASH_SIZE, encauth, TPM_U32_SIZE, &pcrsize, pcrinfosize, pcrinfo, TPM_U32_SIZE, &datsize, datalen, data, 0, 0); } if (ret != 0) { TSS_OSAPclose(&sess); return ret; } /* build the request buffer */ ret = TSS_buildbuff(seal_fmt, tpmdata, ordinal, keyhndl, TPM_HASH_SIZE, encauth, pcrinfosize, pcrinfo, datalen, data, sess.handle, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, pubauth); if ((ret & ERR_MASK) != 0) { TSS_OSAPclose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "Seal"); if (ret != 0) { TSS_OSAPclose(&sess); return ret; } /* calculate the size of the returned Blob */ sealinfosize = LOAD32(tpmdata, TPM_DATA_OFFSET + TPM_U32_SIZE); encdatasize = LOAD32(tpmdata, TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE + sealinfosize); storedsize = TPM_U32_SIZE + TPM_U32_SIZE + sealinfosize + TPM_U32_SIZE + encdatasize; /* check the HMAC in the response */ ret = TSS_checkhmac1(tpmdata, ordinal, nonceodd, sess.ssecret, TPM_HASH_SIZE, storedsize, TPM_DATA_OFFSET, 0, 0); if (ret != 0) { TSS_OSAPclose(&sess); return ret; } /* copy the returned blob to caller */ memcpy(blob, tpmdata + TPM_DATA_OFFSET, storedsize); *bloblen = storedsize; TSS_OSAPclose(&sess); return 0; }
uint32_t TPM_Unseal(uint32_t keyhandle, unsigned char *keyauth, unsigned char *dataauth, unsigned char *blob, unsigned int bloblen, unsigned char *rawdata, unsigned int *datalen) { unsigned char unseal_fmt[] = "00 C3 T l l % l % o % l % o %"; unsigned char unseal_fmt_noauth[] = "00 C2 T l l % l % o %"; uint32_t ret; unsigned char tpmdata[TPM_MAX_BUFF_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char enonce1[TPM_NONCE_SIZE]; unsigned char enonce2[TPM_NONCE_SIZE]; unsigned char dummyauth[TPM_NONCE_SIZE]; unsigned char *passptr2; unsigned char c; uint32_t ordinal; uint32_t keyhndl; uint32_t authhandle1; uint32_t authhandle2; unsigned char authdata1[TPM_HASH_SIZE]; unsigned char authdata2[TPM_HASH_SIZE]; memset(dummyauth, 0, sizeof dummyauth); /* check input arguments */ if (rawdata == NULL || blob == NULL) return ERR_NULL_ARG; if (dataauth == NULL) passptr2 = dummyauth; else passptr2 = dataauth; if (keyauth != NULL) { /* key password specified */ /* open TWO OIAP sessions, Key and Data */ ret = TSS_OIAPopen(&authhandle1, enonce1); if (ret != 0) return ret; ret = TSS_OIAPopen(&authhandle2, enonce2); if (ret != 0) return ret; /* data to Network byte order variables for HMAC calculation */ ordinal = htonl(0x18); keyhndl = htonl(keyhandle); /* generate odd nonce */ TSS_gennonce(nonceodd); c = 0; /* calculate KEY authorization HMAC value */ ret = TSS_authhmac(authdata1, keyauth, TPM_HASH_SIZE, enonce1, nonceodd, c, TPM_U32_SIZE, &ordinal, bloblen, blob, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* calculate DATA authorization HMAC value */ ret = TSS_authhmac(authdata2, passptr2, TPM_NONCE_SIZE, enonce2, nonceodd, c, TPM_U32_SIZE, &ordinal, bloblen, blob, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* build the request buffer */ ret = TSS_buildbuff(unseal_fmt, tpmdata, ordinal, keyhndl, bloblen, blob, authhandle1, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata1, authhandle2, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata2); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } /* transmit buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "Unseal"); if (ret != 0) { TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); return ret; } *datalen = LOAD32(tpmdata, TPM_DATA_OFFSET); /* check HMAC in response */ ret = TSS_checkhmac2(tpmdata, ordinal, nonceodd, keyauth, TPM_HASH_SIZE, passptr2, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, *datalen, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0); TSS_OIAPclose(authhandle1); TSS_OIAPclose(authhandle2); if (ret != 0) return ret; } else { /* no key password */ /* open ONE OIAP session, for the Data */ ret = TSS_OIAPopen(&authhandle2, enonce2); if (ret != 0) return ret; /* data to Network byte order variables for HMAC calculation */ ordinal = htonl(0x18); keyhndl = htonl(keyhandle); /* generate odd nonce */ TSS_gennonce(nonceodd); c = 0; /* calculate DATA authorization HMAC value */ ret = TSS_authhmac(authdata2, passptr2, TPM_NONCE_SIZE, enonce2, nonceodd, c, TPM_U32_SIZE, &ordinal, bloblen, blob, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle2); return ret; } /* build the request buffer */ ret = TSS_buildbuff(unseal_fmt_noauth, tpmdata, ordinal, keyhndl, bloblen, blob, authhandle2, TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata2); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle2); return ret; } /* transmit buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "Unseal"); if (ret != 0) { TSS_OIAPclose(authhandle2); return ret; } *datalen = LOAD32(tpmdata, TPM_DATA_OFFSET); /* check HMAC in response */ ret = TSS_checkhmac1(tpmdata, ordinal, nonceodd, passptr2, TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, *datalen, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0); TSS_OIAPclose(authhandle2); if (ret != 0) return ret; } /* copy decrypted data back to caller */ memcpy(rawdata, tpmdata + TPM_DATA_OFFSET + TPM_U32_SIZE, *datalen); return 0; }