| |
| /* |
| * Licensed Materials - Property of IBM |
| * |
| * trousers - An open source TCG Software Stack |
| * |
| * (C) Copyright International Business Machines Corp. 2004-2007 |
| * |
| */ |
| |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/mman.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| |
| #include "trousers/tss.h" |
| #include "trousers_types.h" |
| #include "trousers_types.h" |
| #include "tcs_tsp.h" |
| #include "tcs_utils.h" |
| #include "tcs_int_literals.h" |
| #include "capabilities.h" |
| #include "tcsps.h" |
| #include "tcslog.h" |
| |
| |
| TCS_CONTEXT_HANDLE InternalContext = 0x30000000; |
| TSS_UUID SRK_UUID = TSS_UUID_SRK; |
| |
| |
| void |
| LogData(char *string, UINT32 data) |
| { |
| #if 0 |
| /* commenting out temporarily, logs getting too chatty */ |
| LogDebug("%s %08x", string, data); |
| #endif |
| } |
| |
| void |
| LogResult(char *string, TCPA_RESULT result) |
| { |
| #if 0 |
| /* commenting out temporarily, logs getting too chatty */ |
| LogDebug("Leaving %s with result 0x%08x", string, result); |
| #endif |
| } |
| |
| UINT16 |
| Decode_UINT16(BYTE * in) |
| { |
| UINT16 temp = 0; |
| temp = (in[1] & 0xFF); |
| temp |= (in[0] << 8); |
| return temp; |
| } |
| |
| void |
| UINT64ToArray(UINT64 i, BYTE * out) |
| { |
| out[0] = (BYTE) ((i >> 56) & 0xFF); |
| out[1] = (BYTE) ((i >> 48) & 0xFF); |
| out[2] = (BYTE) ((i >> 40) & 0xFF); |
| out[3] = (BYTE) ((i >> 32) & 0xFF); |
| out[4] = (BYTE) ((i >> 24) & 0xFF); |
| out[5] = (BYTE) ((i >> 16) & 0xFF); |
| out[6] = (BYTE) ((i >> 8) & 0xFF); |
| out[7] = (BYTE) (i & 0xFF); |
| } |
| |
| void |
| UINT32ToArray(UINT32 i, BYTE * out) |
| { |
| out[0] = (BYTE) ((i >> 24) & 0xFF); |
| out[1] = (BYTE) ((i >> 16) & 0xFF); |
| out[2] = (BYTE) ((i >> 8) & 0xFF); |
| out[3] = (BYTE) (i & 0xFF); |
| } |
| |
| void |
| UINT16ToArray(UINT16 i, BYTE * out) |
| { |
| out[0] = (BYTE) ((i >> 8) & 0xFF); |
| out[1] = (BYTE) (i & 0xFF); |
| } |
| |
| UINT32 |
| Decode_UINT32(BYTE * y) |
| { |
| UINT32 x = 0; |
| |
| x = y[0]; |
| x = ((x << 8) | (y[1] & 0xFF)); |
| x = ((x << 8) | (y[2] & 0xFF)); |
| x = ((x << 8) | (y[3] & 0xFF)); |
| |
| return x; |
| } |
| |
| UINT64 |
| Decode_UINT64(BYTE *y) |
| { |
| UINT64 x = 0; |
| |
| x = y[0]; |
| x = ((x << 8) | (y[1] & 0xFF)); |
| x = ((x << 8) | (y[2] & 0xFF)); |
| x = ((x << 8) | (y[3] & 0xFF)); |
| x = ((x << 8) | (y[4] & 0xFF)); |
| x = ((x << 8) | (y[5] & 0xFF)); |
| x = ((x << 8) | (y[6] & 0xFF)); |
| x = ((x << 8) | (y[7] & 0xFF)); |
| |
| return x; |
| } |
| |
| void |
| LoadBlob_UINT64(UINT64 *offset, UINT64 in, BYTE * blob) |
| { |
| if (blob) |
| UINT64ToArray(in, &blob[*offset]); |
| *offset += sizeof(UINT64); |
| } |
| |
| void |
| LoadBlob_UINT32(UINT64 *offset, UINT32 in, BYTE * blob) |
| { |
| if (blob) |
| UINT32ToArray(in, &blob[*offset]); |
| *offset += sizeof(UINT32); |
| } |
| |
| void |
| LoadBlob_UINT16(UINT64 *offset, UINT16 in, BYTE * blob) |
| { |
| if (blob) |
| UINT16ToArray(in, &blob[*offset]); |
| *offset += sizeof(UINT16); |
| } |
| |
| void |
| UnloadBlob_UINT64(UINT64 *offset, UINT64 * out, BYTE * blob) |
| { |
| if (out) |
| *out = Decode_UINT64(&blob[*offset]); |
| *offset += sizeof(UINT64); |
| } |
| |
| void |
| UnloadBlob_UINT32(UINT64 *offset, UINT32 * out, BYTE * blob) |
| { |
| if (out) |
| *out = Decode_UINT32(&blob[*offset]); |
| *offset += sizeof(UINT32); |
| } |
| |
| void |
| UnloadBlob_UINT16(UINT64 *offset, UINT16 * out, BYTE * blob) |
| { |
| if (out) |
| *out = Decode_UINT16(&blob[*offset]); |
| *offset += sizeof(UINT16); |
| } |
| |
| void |
| LoadBlob_BYTE(UINT64 *offset, BYTE data, BYTE * blob) |
| { |
| if (blob) |
| blob[*offset] = data; |
| (*offset)++; |
| } |
| |
| void |
| UnloadBlob_BYTE(UINT64 *offset, BYTE * dataOut, BYTE * blob) |
| { |
| if (dataOut) |
| *dataOut = blob[*offset]; |
| (*offset)++; |
| } |
| |
| void |
| LoadBlob_BOOL(UINT64 *offset, TSS_BOOL data, BYTE * blob) |
| { |
| if (blob) |
| blob[*offset] = data; |
| (*offset)++; |
| } |
| |
| void |
| UnloadBlob_BOOL(UINT64 *offset, TSS_BOOL *dataOut, BYTE * blob) |
| { |
| if (dataOut) |
| *dataOut = blob[*offset]; |
| (*offset)++; |
| } |
| |
| void |
| LoadBlob(UINT64 *offset, UINT32 size, BYTE *container, BYTE *object) |
| { |
| if (container) |
| memcpy(&container[*offset], object, size); |
| (*offset) += (UINT64) size; |
| } |
| |
| void |
| UnloadBlob(UINT64 *offset, UINT32 size, BYTE *container, BYTE *object) |
| { |
| if (object) |
| memcpy(object, &container[*offset], size); |
| (*offset) += (UINT64) size; |
| } |
| |
| void |
| LoadBlob_Header(UINT16 tag, UINT32 paramSize, UINT32 ordinal, BYTE * blob) |
| { |
| if (blob) { |
| UINT16ToArray(tag, &blob[0]); |
| LogData("Header Tag:", tag); |
| UINT32ToArray(paramSize, &blob[2]); |
| LogData("Header ParamSize:", paramSize); |
| UINT32ToArray(ordinal, &blob[6]); |
| LogData("Header Ordinal:", ordinal); |
| } |
| #if 0 |
| LogInfo("Blob's TPM Ordinal: 0x%x", ordinal); |
| #endif |
| } |
| |
| #ifdef TSS_DEBUG |
| TSS_RESULT |
| LogUnloadBlob_Header(BYTE * blob, UINT32 * size, char *file, int line) |
| { |
| TSS_RESULT result; |
| |
| UINT16 temp = Decode_UINT16(blob); |
| LogData("UnloadBlob_Tag:", (temp)); |
| *size = Decode_UINT32(&blob[2]); |
| LogData("UnloadBlob_Header, size:", *size); |
| LogData("UnloadBlob_Header, returnCode:", Decode_UINT32(&blob[6])); |
| |
| if ((result = Decode_UINT32(&blob[6]))) { |
| LogTPMERR(result, file, line); |
| } |
| |
| return result; |
| } |
| #else |
| TSS_RESULT |
| UnloadBlob_Header(BYTE * blob, UINT32 * size) |
| { |
| UINT16 temp = Decode_UINT16(blob); |
| LogData("UnloadBlob_Tag:", (temp)); |
| *size = Decode_UINT32(&blob[2]); |
| LogData("UnloadBlob_Header, size:", *size); |
| LogData("UnloadBlob_Header, returnCode:", Decode_UINT32(&blob[6])); |
| return Decode_UINT32(&blob[6]); |
| } |
| #endif |
| |
| void |
| LoadBlob_Auth(UINT64 *offset, BYTE * blob, TPM_AUTH * auth) |
| { |
| LoadBlob_UINT32(offset, auth->AuthHandle, blob); |
| LoadBlob(offset, TCPA_NONCE_SIZE, blob, auth->NonceOdd.nonce); |
| LoadBlob_BOOL(offset, auth->fContinueAuthSession, blob); |
| LoadBlob(offset, TCPA_AUTHDATA_SIZE, blob, (BYTE *)&auth->HMAC); |
| } |
| |
| void |
| UnloadBlob_Auth(UINT64 *offset, BYTE * blob, TPM_AUTH * auth) |
| { |
| if (!auth) { |
| UnloadBlob(offset, TCPA_NONCE_SIZE, blob, NULL); |
| UnloadBlob_BOOL(offset, NULL, blob); |
| UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, NULL); |
| |
| return; |
| } |
| |
| UnloadBlob(offset, TCPA_NONCE_SIZE, blob, auth->NonceEven.nonce); |
| UnloadBlob_BOOL(offset, &auth->fContinueAuthSession, blob); |
| UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, (BYTE *)&auth->HMAC); |
| } |
| |
| void |
| UnloadBlob_VERSION(UINT64 *offset, BYTE *blob, TPM_VERSION *out) |
| { |
| if (!out) { |
| *offset += (sizeof(BYTE) * 4); |
| return; |
| } |
| |
| UnloadBlob_BYTE(offset, &out->major, blob); |
| UnloadBlob_BYTE(offset, &out->minor, blob); |
| UnloadBlob_BYTE(offset, &out->revMajor, blob); |
| UnloadBlob_BYTE(offset, &out->revMinor, blob); |
| } |
| |
| void |
| LoadBlob_VERSION(UINT64 *offset, BYTE *blob, TPM_VERSION *ver) |
| { |
| LoadBlob_BYTE(offset, ver->major, blob); |
| LoadBlob_BYTE(offset, ver->minor, blob); |
| LoadBlob_BYTE(offset, ver->revMajor, blob); |
| LoadBlob_BYTE(offset, ver->revMinor, blob); |
| } |
| |
| void |
| UnloadBlob_TCPA_VERSION(UINT64 *offset, BYTE *blob, TCPA_VERSION *out) |
| { |
| if (!out) { |
| *offset += (sizeof(BYTE) * 4); |
| return; |
| } |
| |
| UnloadBlob_BYTE(offset, &out->major, blob); |
| UnloadBlob_BYTE(offset, &out->minor, blob); |
| UnloadBlob_BYTE(offset, &out->revMajor, blob); |
| UnloadBlob_BYTE(offset, &out->revMinor, blob); |
| } |
| |
| void |
| LoadBlob_TCPA_VERSION(UINT64 *offset, BYTE *blob, TCPA_VERSION *ver) |
| { |
| LoadBlob_BYTE(offset, ver->major, blob); |
| LoadBlob_BYTE(offset, ver->minor, blob); |
| LoadBlob_BYTE(offset, ver->revMajor, blob); |
| LoadBlob_BYTE(offset, ver->revMinor, blob); |
| } |
| |
| TSS_RESULT |
| UnloadBlob_KEY_PARMS(UINT64 *offset, BYTE *blob, TCPA_KEY_PARMS *keyParms) |
| { |
| if (!keyParms) { |
| UINT32 parmSize; |
| |
| UnloadBlob_UINT32(offset, NULL, blob); |
| UnloadBlob_UINT16(offset, NULL, blob); |
| UnloadBlob_UINT16(offset, NULL, blob); |
| UnloadBlob_UINT32(offset, &parmSize, blob); |
| |
| if (parmSize > 0) |
| UnloadBlob(offset, parmSize, blob, NULL); |
| |
| return TSS_SUCCESS; |
| } |
| |
| UnloadBlob_UINT32(offset, &keyParms->algorithmID, blob); |
| UnloadBlob_UINT16(offset, &keyParms->encScheme, blob); |
| UnloadBlob_UINT16(offset, &keyParms->sigScheme, blob); |
| UnloadBlob_UINT32(offset, &keyParms->parmSize, blob); |
| |
| if (keyParms->parmSize == 0) |
| keyParms->parms = NULL; |
| else { |
| keyParms->parms = malloc(keyParms->parmSize); |
| if (keyParms->parms == NULL) { |
| LogError("malloc of %u bytes failed.", keyParms->parmSize); |
| keyParms->parmSize = 0; |
| return TCSERR(TSS_E_OUTOFMEMORY); |
| } |
| |
| UnloadBlob(offset, keyParms->parmSize, blob, keyParms->parms); |
| } |
| |
| return TSS_SUCCESS; |
| } |
| |
| void |
| UnloadBlob_KEY_FLAGS(UINT64 *offset, BYTE *blob, TCPA_KEY_FLAGS *flags) |
| { |
| if (!flags) { |
| UnloadBlob_UINT32(offset, NULL, blob); |
| |
| return; |
| } |
| |
| UnloadBlob_UINT32(offset, flags, blob); |
| } |
| |
| TSS_RESULT |
| UnloadBlob_CERTIFY_INFO(UINT64 *offset, BYTE *blob, TCPA_CERTIFY_INFO *certify) |
| { |
| TSS_RESULT rc; |
| |
| if (!certify) { |
| TPM_VERSION version; |
| UINT32 size; |
| |
| UnloadBlob_VERSION(offset, blob, &version); |
| UnloadBlob_UINT16(offset, NULL, blob); |
| UnloadBlob_KEY_FLAGS(offset, blob, NULL); |
| UnloadBlob_BOOL(offset, NULL, blob); |
| |
| if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL))) |
| return rc; |
| |
| UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, NULL); |
| UnloadBlob(offset, TCPA_NONCE_SIZE, blob, NULL); |
| UnloadBlob_BOOL(offset, NULL, blob); |
| UnloadBlob_UINT32(offset, &size, blob); |
| |
| if (size > 0) |
| UnloadBlob(offset, size, blob, NULL); |
| |
| if (Decode_UINT16((BYTE *) &version) == TPM_TAG_CERTIFY_INFO2){ |
| /* This is a TPM_CERTIFY_INFO2 structure. */ |
| /* Read migrationAuthority. */ |
| UnloadBlob_UINT32(offset, &size, blob); |
| if (size > 0) |
| UnloadBlob(offset, size, blob, NULL); |
| } |
| |
| return TSS_SUCCESS; |
| } |
| |
| UnloadBlob_VERSION(offset, blob, (TPM_VERSION *)&certify->version); |
| UnloadBlob_UINT16(offset, &certify->keyUsage, blob); |
| UnloadBlob_KEY_FLAGS(offset, blob, &certify->keyFlags); |
| UnloadBlob_BOOL(offset, (TSS_BOOL *)&certify->authDataUsage, blob); |
| |
| if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &certify->algorithmParms))) |
| return rc; |
| |
| UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, certify->pubkeyDigest.digest); |
| UnloadBlob(offset, TCPA_NONCE_SIZE, blob, certify->data.nonce); |
| UnloadBlob_BOOL(offset, (TSS_BOOL *)&certify->parentPCRStatus, blob); |
| UnloadBlob_UINT32(offset, &certify->PCRInfoSize, blob); |
| |
| if (certify->PCRInfoSize > 0) { |
| certify->PCRInfo = (BYTE *)malloc(certify->PCRInfoSize); |
| if (certify->PCRInfo == NULL) { |
| LogError("malloc of %u bytes failed.", certify->PCRInfoSize); |
| certify->PCRInfoSize = 0; |
| free(certify->algorithmParms.parms); |
| certify->algorithmParms.parms = NULL; |
| certify->algorithmParms.parmSize = 0; |
| return TCSERR(TSS_E_OUTOFMEMORY); |
| } |
| UnloadBlob(offset, certify->PCRInfoSize, blob, certify->PCRInfo); |
| } else { |
| certify->PCRInfo = NULL; |
| } |
| |
| if (Decode_UINT16((BYTE *) &certify->version) == TPM_TAG_CERTIFY_INFO2){ |
| /* This is a TPM_CERTIFY_INFO2 structure. */ |
| /* Read migrationAuthority. */ |
| UINT32 size; |
| UnloadBlob_UINT32(offset, &size, blob); |
| if (size > 0) |
| UnloadBlob(offset, size, blob, NULL); |
| } |
| |
| return TSS_SUCCESS; |
| } |
| |
| TSS_RESULT |
| UnloadBlob_KEY_HANDLE_LIST(UINT64 *offset, BYTE *blob, TCPA_KEY_HANDLE_LIST *list) |
| { |
| UINT16 i; |
| |
| if (!list) { |
| UINT16 size; |
| |
| UnloadBlob_UINT16(offset, &size, blob); |
| |
| *offset += (size * sizeof(UINT32)); |
| |
| return TSS_SUCCESS; |
| } |
| |
| UnloadBlob_UINT16(offset, &list->loaded, blob); |
| if (list->loaded == 0) { |
| list->handle = NULL; |
| return TSS_SUCCESS; |
| } |
| |
| list->handle = malloc(list->loaded * sizeof (UINT32)); |
| if (list->handle == NULL) { |
| LogError("malloc of %zd bytes failed.", list->loaded * sizeof (UINT32)); |
| list->loaded = 0; |
| return TCSERR(TSS_E_OUTOFMEMORY); |
| } |
| |
| for (i = 0; i < list->loaded; i++) |
| UnloadBlob_UINT32(offset, &list->handle[i], blob); |
| |
| return TSS_SUCCESS; |
| } |
| |
| void |
| LoadBlob_DIGEST(UINT64 *offset, BYTE *blob, TPM_DIGEST *digest) |
| { |
| LoadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, digest->digest); |
| } |
| |
| void |
| UnloadBlob_DIGEST(UINT64 *offset, BYTE *blob, TPM_DIGEST *digest) |
| { |
| UnloadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, digest->digest); |
| } |
| |
| void |
| LoadBlob_NONCE(UINT64 *offset, BYTE *blob, TPM_NONCE *nonce) |
| { |
| LoadBlob(offset, TCPA_NONCE_SIZE, blob, nonce->nonce); |
| } |
| |
| void |
| UnloadBlob_NONCE(UINT64 *offset, BYTE *blob, TPM_NONCE *nonce) |
| { |
| UnloadBlob(offset, TCPA_NONCE_SIZE, blob, nonce->nonce); |
| } |
| |
| void |
| LoadBlob_AUTHDATA(UINT64 *offset, BYTE *blob, TPM_AUTHDATA *authdata) |
| { |
| LoadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, authdata->authdata); |
| } |
| |
| void |
| UnloadBlob_AUTHDATA(UINT64 *offset, BYTE *blob, TPM_AUTHDATA *authdata) |
| { |
| UnloadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, authdata->authdata); |
| } |
| |