/* * Licensed Materials - Property of IBM * * trousers - An open source TCG Software Stack * * (C) Copyright International Business Machines Corp. 2004-2007 * */ #include #include #include #include #include #include #include #include #include #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) { 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); }