uint32_t TPM_GetRandom(uint32_t bytesreq, unsigned char * buffer, uint32_t * bytesret) { uint32_t ret; STACK_TPM_BUFFER( tpmdata ) uint32_t ordinal_no = htonl(TPM_ORD_GetRandom); uint32_t numbytes_no = htonl(bytesreq); TSS_buildbuff("00 c1 T l l",&tpmdata, ordinal_no, numbytes_no); ret = TPM_Transmit(&tpmdata,"GetRandom"); if (0 != ret) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, bytesret); if ((ret & ERR_MASK)) { return ret; } memcpy(buffer, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE], *bytesret); return ret; }
static uint32_t TPM_TransmitCharDev(int sock_fd, struct tpm_buffer *tb, const char *msg) { uint32_t nbytes = 0; ssize_t nwritten = 0; size_t nleft = 0; unsigned int offset = 0; uint32_t ret; char mymsg[1024]; snprintf(mymsg, sizeof(mymsg), "TPM_TransmitCharDev: To TPM [%s]", msg); ret = tpm_buffer_load32(tb, TPM_PARAMSIZE_OFFSET, &nbytes); if ((ret & ERR_MASK)) { return ret; } showBuff(tb->buffer, mymsg); nleft = nbytes; while (nleft > 0) { nwritten = write(sock_fd, &tb->buffer[offset], nleft); if (nwritten < 0) { /* error */ printf("TPM_TransmitCharDev: write error %d\n", (int)nwritten); return nwritten; } nleft -= nwritten; offset += nwritten; } return 0; }
/* * Check whether a key is in the TPM. Returns the index (>=0) at which * slot the key is, -1 otherwise. */ static int IsKeyInTPM(struct tpm_buffer *capabilities, uint32_t shandle) { uint32_t ctr; int rc = 0; uint32_t handle; if (shandle == 0x00000000 || shandle == 0x40000000 || shandle == 0x40000006 || shandle == 0xffffffff) { return 1; } for (ctr = 2; ctr < capabilities->used; ctr += sizeof(handle)) { tpm_buffer_load32(capabilities, ctr, &handle); if (handle == shandle) { rc = 1; break; } } #if 0 if (rc == 1) { printf("key %08x is in TPM\n",shandle); } else { printf("key %08x is NOT in TPM\n", shandle); } #endif return rc; }
uint32_t TPM_LoadAuthContext(unsigned char *authContextBlob, uint32_t authContextSize, uint32_t *authhandle) { uint32_t ret; uint32_t ordinal_no = htonl(TPM_ORD_LoadAuthContext); STACK_TPM_BUFFER(tpmdata); ret = TSS_buildbuff("00 c1 T l @",&tpmdata, ordinal_no, authContextSize, authContextBlob); if ( ( ret & ERR_MASK ) != 0) { return ret; } ret = TPM_Transmit(&tpmdata,"LoadAuthContext"); if (ret != 0) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, authhandle); if ((ret & ERR_MASK)) { return ret; } return ret; }
uint32_t TPM_LoadKeyContext(struct tpm_buffer *context, uint32_t *keyhandle) { uint32_t ret; uint32_t ordinal_no = htonl(TPM_ORD_LoadKeyContext); STACK_TPM_BUFFER(tpmdata); ret = TSS_buildbuff("00 c1 T l @",&tpmdata, ordinal_no, context->used, context->buffer); if ((ret & ERR_MASK) != 0) { return ret; } ret = TPM_Transmit(&tpmdata,"LoadKeyContext"); if (ret != 0) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, keyhandle); if ((ret & ERR_MASK)) { return ret; } return ret; }
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; }
static uint32_t TPM_GetCapability_Internal(uint32_t caparea, struct tpm_buffer *scap, struct tpm_buffer *response, int allowTransport) { uint32_t ret; uint32_t rlen; uint32_t ordinal_no = htonl(TPM_ORD_GetCapability); STACK_TPM_BUFFER(tpmdata) /* request/response buffer */ uint32_t scaplen = 0; unsigned char *buffer = NULL; /* check arguments */ if (scap) { scaplen = scap->used; buffer = scap->buffer; } if (response == NULL) return ERR_NULL_ARG; ret = TSS_buildbuff("00 c1 T l L @", &tpmdata, ordinal_no, caparea, scaplen, buffer); if (ret & ERR_MASK) return ret; /* transmit the request buffer to the TPM device and read the reply */ if (allowTransport) ret = TPM_Transmit(&tpmdata, "GetCapability"); else ret = TPM_Transmit_NoTransport(&tpmdata, "GetCapability"); if (ret) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &rlen); if (ret & ERR_MASK) return ret; if (response) SET_TPM_BUFFER(response, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE], rlen); return 0; }
uint32_t TPM_SHA1Start(uint32_t *maxNumBytes) { uint32_t ordinal_no; uint32_t ret; STACK_TPM_BUFFER(tpmdata) /* move Network byte order data to varaible for hmac calcualtion */ ordinal_no = htonl(TPM_ORD_SHA1Start); TSS_buildbuff("00 c1 T l", &tpmdata, ordinal_no); /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata,"SHA1Start"); if (ret != 0) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, maxNumBytes); return ret; }
uint32_t TPM_SaveKeyContext(uint32_t keyhandle, struct tpm_buffer *context) { uint32_t ret; uint32_t ordinal_no = htonl(TPM_ORD_SaveKeyContext); STACK_TPM_BUFFER(tpmdata) uint32_t keyhandle_no = htonl(keyhandle); uint32_t len; ret = needKeysRoom(keyhandle, 0, 0, 0); if (ret != 0) { return ret; } ret = TSS_buildbuff("00 c1 T l l",&tpmdata, ordinal_no, keyhandle_no); if (( ret & ERR_MASK )!= 0) { return ret; } ret = TPM_Transmit(&tpmdata,"SaveKeyContext"); if (ret != 0) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &len); if ((ret & ERR_MASK)) { return ret; } if (NULL != context) { SET_TPM_BUFFER(context, &tpmdata.buffer[TPM_DATA_OFFSET+TPM_U32_SIZE], len); } return ret; }
static uint32_t swapOutKeys(uint32_t neededslots, uint32_t key1, uint32_t key2, uint32_t key3, struct tpm_buffer *capabilities) { uint32_t ret = 0; uint32_t ctr; uint32_t handle; #if 0 printf("must keep keys %08x %08x %08x room=%d\n", key1,key2,key3,neededslots); #endif ctr = 2; while (ctr < capabilities->used) { tpm_buffer_load32(capabilities, ctr, &handle); if (handle != key1 && handle != key2 && handle != key3) { ret = swapOutKey(handle); } if (ret != 0 && ret != TPM_OWNER_CONTROL) { break; } if (ret == 0) { neededslots--; if (0 == neededslots) { break; } } ctr += sizeof(handle); } return ret; }
uint32_t TPM_SaveAuthContext(uint32_t authhandle, unsigned char * authContextBlob, uint32_t * authContextSize) { uint32_t ret; uint32_t ordinal_no = htonl(TPM_ORD_SaveAuthContext); STACK_TPM_BUFFER(tpmdata) uint32_t authhandle_no = htonl(authhandle); uint32_t len; ret = TSS_buildbuff("00 c1 T l l",&tpmdata, ordinal_no, authhandle_no); if (( ret & ERR_MASK )!= 0) { return ret; } ret = TPM_Transmit(&tpmdata,"SaveAuthContext"); if (ret != 0) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &len); if ((ret & ERR_MASK)) { return ret; } if (NULL != authContextBlob) { *authContextSize = MIN(*authContextSize, len); memcpy(authContextBlob, &tpmdata.buffer[TPM_DATA_OFFSET+TPM_U32_SIZE], *authContextSize); } return ret; }
/* * make sure the given keys are in the TPM and there is * enough room for 'room' keys in the TPM */ static uint32_t needKeysRoom_General(uint32_t key1, uint32_t key2, uint32_t key3, uint32_t room) { uint32_t ret = 0; uint32_t scap_no; STACK_TPM_BUFFER(context); STACK_TPM_BUFFER(scap); STACK_TPM_BUFFER(capabilities); uint32_t tpmkeyroom; uint32_t keysintpm; int intpm1, intpm2, intpm3; uint32_t neededslots; static int in_swapping = 0; char *tmp1; char *tmp2; char *tmp3; /* do NOT allow recursion */ if (in_swapping) { return 0; } tmp1 = getenv("TPM_AUDITING"); tmp2 = getenv("TPM_TRANSPORT"); tmp3 = getenv("TPM_NO_KEY_SWAP"); if ((tmp1 && !strcmp(tmp1,"1") && tmp2 && !strcmp(tmp2,"1")) || (tmp3 && !strcmp(tmp3,"1")) ) { return 0; } in_swapping = 1; #if 0 printf("level: %d\n",g_num_transports); #endif /* * Support for 1.1 TPMs is not possible since the key handle * must be maintained and the old SaveKeyContext functions don't * do that. * * Strategy for 1.2 TPMs: * Check the number of keys the TPM can handle. * Check which keys are in the TPM and how many. * If there's enough room for all keys that need to be loaded in, * just load them in, otherwise swap an unneeded key out first. * If necessary, swap as many keys out such that there's enough * room for 'room' keys. */ scap_no = htonl(TPM_CAP_PROP_MAX_KEYS); // 0x110 SET_TPM_BUFFER(&scap, &scap_no, sizeof(scap_no)); ret = TPM_GetCapability(TPM_CAP_PROPERTY, // 0x5 &scap, &capabilities); if (ret != 0) { /* call may fail at very beginning */ in_swapping = 0; return 0; } else { ret = tpm_buffer_load32(&capabilities, 0, &tpmkeyroom); if (ret != 0) { in_swapping = 0; return ret; } //tpmkeyroom = 10; } scap_no = ntohl(TPM_RT_KEY); SET_TPM_BUFFER(&scap, &scap_no, sizeof(scap_no)); ret = TPM_GetCapability(TPM_CAP_KEY_HANDLE, &scap, &capabilities); if (ret != 0) { in_swapping = 0; printf("Error %s from TPM_GetCapability.\n", TPM_GetErrMsg(ret)); return ret; } neededslots = room; intpm1 = IsKeyInTPM(&capabilities, key1); if (!intpm1) neededslots++; intpm2 = IsKeyInTPM(&capabilities, key2); if (!intpm2) neededslots++; intpm3 = IsKeyInTPM(&capabilities, key3); if (!intpm2) neededslots++; #if 0 uint32_t ctr, handle; for (ctr = 2; ctr < capabilities.used; ctr += sizeof(handle)) { ret = tpm_buffer_load32(&capabilities, ctr, &handle); if (ret != 0) { break; } printf("available key: %08x\n",handle); } #endif keysintpm = (capabilities.used - 2 ) / 4; #if 0 printf("TPM has room for %d keys, holds %d keys.\n", tpmkeyroom,keysintpm); #endif if ((int)neededslots > ((int)tpmkeyroom - (int)keysintpm)) { ret = swapOutKeys((int)neededslots - ((int)tpmkeyroom-(int)keysintpm), key1, key2, key3, &capabilities); #if 0 } else { printf("No need to swap out keys.\n"); #endif } if (ret == 0 && !intpm1) { ret = swapInKey(key1); } if (ret == 0 && !intpm2) { ret = swapInKey(key2); } if (ret == 0 && !intpm3) { ret = swapInKey(key3); } in_swapping = 0; return ret; }
uint32_t TPM_Quote(uint32_t keyhandle, unsigned char *keyauth, unsigned char *externalData, TPM_PCR_SELECTION *tps, TPM_PCR_COMPOSITE *tpc, struct tpm_buffer *signature) { uint32_t ret; STACK_TPM_BUFFER( tpmdata ) session sess; unsigned char pubauth[TPM_HASH_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char c; uint32_t ordinal = htonl(TPM_ORD_Quote); uint32_t keyhndl = htonl(keyhandle); uint16_t pcrselsize; uint32_t valuesize; uint32_t sigsize; uint32_t offset; STACK_TPM_BUFFER( serPcrSel ); /* check input arguments */ if (tpc == NULL || externalData == NULL || signature == NULL) return ERR_NULL_ARG; ret = needKeysRoom(keyhandle, 0, 0, 0); if (ret != 0) { return ret; } ret = TPM_WritePCRSelection(&serPcrSel, tps); if ((ret & ERR_MASK)) return ret; if (keyauth != NULL) /* authdata required */ { /* Open OSAP Session */ ret = TSS_SessionOpen(SESSION_OSAP|SESSION_DSAP,&sess, keyauth,TPM_ET_KEYHANDLE,keyhandle); if (ret != 0) return ret; /* generate odd nonce */ TSS_gennonce(nonceodd); /* move Network byte order data to variables for hmac calculation */ c = 0; /* calculate authorization HMAC value */ ret = TSS_authhmac(pubauth,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,TSS_Session_GetENonce(&sess),nonceodd,c, TPM_U32_SIZE,&ordinal, TPM_HASH_SIZE,externalData, serPcrSel.used,serPcrSel.buffer, 0,0); if (ret != 0) { TSS_SessionClose(&sess); return ret; } /* build the request buffer */ ret = TSS_buildbuff("00 C2 T l l % % L % o %",&tpmdata, ordinal, keyhndl, TPM_HASH_SIZE,externalData, serPcrSel.used, serPcrSel.buffer, TSS_Session_GetHandle(&sess), TPM_NONCE_SIZE,nonceodd, c, TPM_HASH_SIZE,pubauth); if ((ret & ERR_MASK) != 0) { TSS_SessionClose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata,"Quote"); TSS_SessionClose(&sess); if (ret != 0) { return ret; } offset = TPM_DATA_OFFSET; /* calculate the size of the returned Blob */ ret = tpm_buffer_load16(&tpmdata,offset,&pcrselsize); if ((ret & ERR_MASK)) { return ret; } offset += TPM_U16_SIZE + pcrselsize; ret = tpm_buffer_load32(&tpmdata,offset,&valuesize); if ((ret & ERR_MASK)) { return ret; } offset += TPM_U32_SIZE + valuesize; ret = tpm_buffer_load32(&tpmdata,offset, &sigsize); if ((ret & ERR_MASK)) { return ret; } offset += TPM_U32_SIZE; /* check the HMAC in the response */ ret = TSS_checkhmac1(&tpmdata,ordinal,nonceodd,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE, offset-TPM_DATA_OFFSET+sigsize,TPM_DATA_OFFSET, 0,0); if (ret != 0) { return ret; } ret = TPM_ReadPCRComposite(&tpmdata, TPM_DATA_OFFSET, tpc); if ((ret & ERR_MASK)) { return ret; } /* copy the returned blob to caller */ SET_TPM_BUFFER(signature, &tpmdata.buffer[offset], sigsize); } else /* no authdata required */ { /* build the request buffer */ ret = TSS_buildbuff("00 C1 T l l % %",&tpmdata, ordinal, keyhndl, TPM_HASH_SIZE,externalData, serPcrSel.used,serPcrSel.buffer); if ((ret & ERR_MASK) != 0) return ret; /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata,"Quote"); if (ret != 0) return ret; /* calculate the size of the returned Blob */ offset = TPM_DATA_OFFSET; ret = tpm_buffer_load16(&tpmdata,offset, &pcrselsize); if ((ret & ERR_MASK)) { return ret; } offset += TPM_U16_SIZE + pcrselsize; ret = tpm_buffer_load32(&tpmdata,offset, &valuesize); if ((ret & ERR_MASK)) { return ret; } offset += TPM_U32_SIZE + valuesize; ret = tpm_buffer_load32(&tpmdata,offset, &sigsize); if ((ret & ERR_MASK)) { return ret; } offset += TPM_U32_SIZE; /* copy the returned PCR composite to caller */ ret = TPM_ReadPCRComposite(&tpmdata, TPM_DATA_OFFSET, tpc); if ((ret & ERR_MASK)) { return ret; } /* copy the returned blob to caller */ SET_TPM_BUFFER(signature, &tpmdata.buffer[offset], sigsize); } return 0; }
uint32_t TPM_Quote2(uint32_t keyhandle, TPM_PCR_SELECTION * selection, TPM_BOOL addVersion, unsigned char *keyauth, unsigned char *antiReplay, TPM_PCR_INFO_SHORT * pcrinfo, struct tpm_buffer *versionblob, struct tpm_buffer *signature) { uint32_t ret; uint32_t rc; STACK_TPM_BUFFER( tpmdata ) session sess; unsigned char pubauth[TPM_HASH_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char c = 0; uint32_t ordinal_no = htonl(TPM_ORD_Quote2); uint16_t pcrselsize; uint32_t verinfosize; uint32_t sigsize; uint32_t storedsize; uint32_t keyhndl = htonl(keyhandle); uint16_t keytype; struct tpm_buffer * serPCRSelection; uint32_t serPCRSelectionSize; /* check input arguments */ if (pcrinfo == NULL || selection == NULL || antiReplay == NULL) return ERR_NULL_ARG; keytype = 0x0001; ret = needKeysRoom(keyhandle, 0, 0, 0); if (ret != 0) { return ret; } TSS_gennonce(antiReplay); serPCRSelection = TSS_AllocTPMBuffer(TPM_U16_SIZE + selection->sizeOfSelect); if (NULL == serPCRSelection) { return ERR_MEM_ERR; } ret = TPM_WritePCRSelection(serPCRSelection, selection); if (( ret & ERR_MASK) != 0) { TSS_FreeTPMBuffer(serPCRSelection); return ret; } serPCRSelectionSize = ret; if (keyauth != NULL) { /* Open OSAP Session */ ret = TSS_SessionOpen(SESSION_OSAP|SESSION_DSAP,&sess,keyauth,keytype,keyhandle); if (ret != 0) { TSS_FreeTPMBuffer(serPCRSelection); return ret; } /* generate odd nonce */ TSS_gennonce(nonceodd); /* move Network byte order data to variables for hmac calculation */ /* calculate authorization HMAC value */ ret = TSS_authhmac(pubauth,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE,TSS_Session_GetENonce(&sess),nonceodd,c, TPM_U32_SIZE,&ordinal_no, TPM_HASH_SIZE,antiReplay, serPCRSelectionSize, serPCRSelection->buffer, sizeof(TPM_BOOL), &addVersion, 0,0); if (ret != 0) { TSS_FreeTPMBuffer(serPCRSelection); TSS_SessionClose(&sess); return ret; } /* build the request buffer */ ret = TSS_buildbuff("00 C2 T l l % % o L % o %",&tpmdata, ordinal_no, keyhndl, TPM_HASH_SIZE,antiReplay, serPCRSelectionSize,serPCRSelection->buffer, addVersion, TSS_Session_GetHandle(&sess), TPM_NONCE_SIZE,nonceodd, c, TPM_HASH_SIZE,pubauth); TSS_FreeTPMBuffer(serPCRSelection); if ((ret & ERR_MASK) != 0) { TSS_SessionClose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata,"Quote2 - AUTH1"); TSS_SessionClose(&sess); if (ret != 0) { return ret; } } else { /* build the request buffer */ ret = TSS_buildbuff("00 C1 T l l % % o",&tpmdata, ordinal_no, keyhndl, TPM_HASH_SIZE,antiReplay, serPCRSelectionSize,serPCRSelection->buffer, addVersion); TSS_FreeTPMBuffer(serPCRSelection); if ((ret & ERR_MASK) != 0) { TSS_SessionClose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata,"Quote2"); TSS_SessionClose(&sess); if (ret != 0) { return ret; } } /* calculate the size of the returned Blob */ ret = tpm_buffer_load16(&tpmdata,TPM_DATA_OFFSET, &pcrselsize); if ((ret & ERR_MASK)) { return ret; } pcrselsize += TPM_U16_SIZE + 1 + TPM_HASH_SIZE; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + pcrselsize, &verinfosize); if ((ret & ERR_MASK)) { return ret; } ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + pcrselsize + TPM_U32_SIZE + verinfosize, &sigsize); if ((ret & ERR_MASK)) { return ret; } storedsize = pcrselsize + TPM_U32_SIZE + verinfosize + TPM_U32_SIZE + sigsize; if (keyauth != NULL) { /* check the HMAC in the response */ ret = TSS_checkhmac1(&tpmdata,ordinal_no,nonceodd,TSS_Session_GetAuth(&sess),TPM_HASH_SIZE, storedsize,TPM_DATA_OFFSET, 0,0); if (ret != 0) { return ret; } } /* copy the returned PCR composite to caller */ if (pcrselsize != (rc = TPM_ReadPCRInfoShort(&tpmdata, TPM_DATA_OFFSET, pcrinfo))) { if ((rc & ERR_MASK)) return rc; return ERR_BUFFER; } if (NULL != versionblob) { SET_TPM_BUFFER( versionblob, &tpmdata.buffer[TPM_DATA_OFFSET+pcrselsize+TPM_U32_SIZE], verinfosize); } if (NULL != signature) { SET_TPM_BUFFER(signature, &tpmdata.buffer[TPM_DATA_OFFSET+pcrselsize+TPM_U32_SIZE+verinfosize+TPM_U32_SIZE], sigsize); } return ret; }
uint32_t TPM_GetCapabilitySigned(uint32_t keyhandle, unsigned char *keypass, unsigned char *antiReplay, uint32_t caparea, struct tpm_buffer * scap, struct tpm_buffer * resp, unsigned char *sig, uint32_t * siglen) { uint32_t ret; uint32_t rlen; STACK_TPM_BUFFER(tpmdata) /* request/response buffer */ uint32_t ordinal_no = htonl(TPM_ORD_GetCapabilitySigned); uint32_t keyhandle_no = htonl(keyhandle); uint32_t caparea_no = htonl(caparea); unsigned char c = 0; unsigned char authdata[TPM_HASH_SIZE]; uint32_t ssize; unsigned char *buffer = NULL; uint32_t subcaplen = 0; uint32_t subcaplen_no; /* check arguments */ if (scap) { subcaplen = scap->used; buffer = scap->buffer; } subcaplen_no = htonl(subcaplen); ret = needKeysRoom(keyhandle, 0, 0, 0); if (ret) return ret; if (resp == NULL) return ERR_NULL_ARG; if (keypass) { unsigned char nonceodd[TPM_HASH_SIZE]; session sess; ret = TSS_gennonce(nonceodd); if (ret == 0) return ERR_CRYPT_ERR; ret = TSS_SessionOpen(SESSION_OSAP | SESSION_OIAP, &sess, keypass, TPM_ET_KEYHANDLE, keyhandle); if (ret) return ret; /* move Network byte order data to variable for hmac calculation */ ret = TSS_authhmac(authdata, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE, TSS_Session_GetENonce(&sess), nonceodd, c, TPM_U32_SIZE, &ordinal_no, TPM_NONCE_SIZE, antiReplay, TPM_U32_SIZE, &caparea_no, TPM_U32_SIZE, &subcaplen_no, subcaplen, buffer, 0, 0); if (ret) { TSS_SessionClose(&sess); return ret; } ret = TSS_buildbuff("00 c2 T l l % l @ L % o %", &tpmdata, ordinal_no, keyhandle_no, TPM_NONCE_SIZE, antiReplay, caparea_no, subcaplen, buffer, TSS_Session_GetHandle(&sess), TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, authdata); if (ret & ERR_MASK) { TSS_SessionClose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata, "GetCapability - AUTH1"); TSS_SessionClose(&sess); if (ret) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET+TPM_U32_SIZE, &rlen); if (ret & ERR_MASK) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE + rlen, &ssize); if (ret & ERR_MASK) return ret; ret = TSS_checkhmac1(&tpmdata, ordinal_no, nonceodd, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE, TPM_U32_SIZE + TPM_U32_SIZE + rlen + TPM_U32_SIZE + ssize, TPM_DATA_OFFSET, 0, 0); if (ret) return ret; } else { ret = TSS_buildbuff("00 c1 T l l % l @", &tpmdata, ordinal_no, keyhandle_no, TPM_NONCE_SIZE, antiReplay, caparea_no, subcaplen, buffer); if (ret & ERR_MASK) return ret; /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata, "GetCapability - NO AUTH"); if (ret) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET+TPM_U32_SIZE, &rlen); if (ret & ERR_MASK) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE + rlen, &ssize); if (ret & ERR_MASK) return ret; } if (resp) SET_TPM_BUFFER(resp, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE], rlen); if (sig) { *siglen = MIN(*siglen, ssize); memcpy(sig, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE + rlen + TPM_U32_SIZE], *siglen); } return ret; }
uint32_t TPM_GetCapabilityOwner(unsigned char *ownpass, uint32_t * volflags, uint32_t * nvolflags) { uint32_t ret; STACK_TPM_BUFFER(tpmdata) /* data to be inserted into Request Buffer (in Network Byte Order) */ /* the uint32_t and uint16_t values are stored in network byte order so they ** are in the correct format when being hashed by the HMAC calculation */ uint32_t command; /* command ordinal */ unsigned char nonceodd[TPM_HASH_SIZE]; /* odd nonce */ unsigned char authdata[TPM_HASH_SIZE]; /* auth data */ session sess; /* check that parameters are valid */ if (ownpass == NULL || volflags == NULL || nvolflags == NULL) return ERR_NULL_ARG; /* set up command and protocol values for TakeOwnership function */ command = htonl(TPM_ORD_GetCapabilityOwner); /* generate the odd nonce */ ret = TSS_gennonce(nonceodd); if (ret == 0) return ret; /* initiate the OSAP protocol */ ret = TSS_SessionOpen(SESSION_OSAP, &sess, ownpass, TPM_OWNER_ETYPE, TPM_OWNER_EVALUE); if (ret) return ret; /* calculate the Authorization Data */ ret = TSS_authhmac(authdata, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE, TSS_Session_GetENonce(&sess), nonceodd, 0, TPM_U32_SIZE, &command, 0, 0); if (ret) { TSS_SessionClose(&sess); return ret; } /* insert all the calculated fields into the request buffer */ ret = TSS_buildbuff("00 c2 T l L % 00 %", &tpmdata, command, TSS_Session_GetHandle(&sess), TPM_HASH_SIZE, nonceodd, TPM_HASH_SIZE, authdata); if (ret & ERR_MASK) { TSS_SessionClose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata, "GetCapabilityOwner"); TSS_SessionClose(&sess); if (ret) return ret; ret = TSS_checkhmac1(&tpmdata, command, nonceodd, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, TPM_U32_SIZE, TPM_DATA_OFFSET + TPM_U32_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET + TPM_U32_SIZE + TPM_U32_SIZE, 0, 0); if (ret) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + 4, nvolflags); if (ret & ERR_MASK) return ret; ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET + 4 + TPM_U32_SIZE, volflags); if (ret & ERR_MASK) return ret; return 0; }
uint32_t TPM_UnBind(uint32_t keyhandle, unsigned char *keyauth, unsigned char *data, uint32_t datalen, unsigned char *blob, uint32_t * bloblen) { uint32_t ret = 0; STACK_TPM_BUFFER(tpmdata) session sess; unsigned char pubauth[TPM_HASH_SIZE]; unsigned char nonceodd[TPM_NONCE_SIZE]; unsigned char c = 0; uint32_t ordinal = htonl(TPM_ORD_UnBind); uint32_t datsize = htonl(datalen); uint32_t keyhndl = htonl(keyhandle); uint16_t keytype; uint32_t infosize; /* check input arguments */ if (data == NULL || blob == NULL) return ERR_NULL_ARG; if (keyhandle == 0x40000000) keytype = TPM_ET_SRK; else keytype = TPM_ET_KEYHANDLE; ret = needKeysRoom(keyhandle, 0, 0, 0); if (ret) return ret; if (keyauth != NULL) { /* key needs authorization */ /* Open OSAP Session */ ret = TSS_SessionOpen(SESSION_OSAP | SESSION_DSAP, &sess, keyauth, keytype, keyhandle); if (ret) return ret; /* generate odd nonce */ TSS_gennonce(nonceodd); /* move Network byte order data to variables for HMAC calculation */ /* calculate authorization HMAC value */ ret = TSS_authhmac(pubauth, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE, TSS_Session_GetENonce(&sess), nonceodd, c, TPM_U32_SIZE, &ordinal, TPM_U32_SIZE, &datsize, datalen, data, 0, 0); if (ret) { TSS_SessionClose(&sess); return ret; } /* build the request buffer */ ret = TSS_buildbuff("00 C2 T l l @ L % o %", &tpmdata, ordinal, keyhndl, datalen, data, TSS_Session_GetHandle(&sess), TPM_NONCE_SIZE, nonceodd, c, TPM_HASH_SIZE, pubauth); if (ret & ERR_MASK) { TSS_SessionClose(&sess); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata, "UnBind"); TSS_SessionClose(&sess); if (ret) return ret; /* calculate the size of the returned Blob */ ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &infosize); if (ret & ERR_MASK) return ret; /* check the HMAC in the response */ ret = TSS_checkhmac1(&tpmdata, ordinal, nonceodd, TSS_Session_GetAuth(&sess), TPM_HASH_SIZE, TPM_U32_SIZE, TPM_DATA_OFFSET, infosize, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0); if (ret) return ret; /* copy the returned blob to caller */ memcpy(blob, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE], infosize); *bloblen = infosize; } else { /* key needs NO authorization */ /* move Network byte order data to variables for HMAC calculation */ /* build the request buffer */ ret = TSS_buildbuff("00 C1 T l l @", &tpmdata, ordinal, keyhndl, datalen, data); if (ret & ERR_MASK) return ret; /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(&tpmdata, "UnBind"); if (ret) return ret; /* calculate the size of the returned Blob */ ret = tpm_buffer_load32(&tpmdata, TPM_DATA_OFFSET, &infosize); if (ret & ERR_MASK) return ret; /* copy the returned blob to caller */ memcpy(blob, &tpmdata.buffer[TPM_DATA_OFFSET + TPM_U32_SIZE], infosize); *bloblen = infosize; } return ret; }