diff options
Diffstat (limited to 'src/tcs/tcs_pbg.c')
-rw-r--r-- | src/tcs/tcs_pbg.c | 2201 |
1 files changed, 2201 insertions, 0 deletions
diff --git a/src/tcs/tcs_pbg.c b/src/tcs/tcs_pbg.c new file mode 100644 index 0000000..39c688c --- /dev/null +++ b/src/tcs/tcs_pbg.c @@ -0,0 +1,2201 @@ + +/* + * 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 <stdarg.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 "tcs_tsp.h" +#include "tcs_utils.h" +#include "tcs_int_literals.h" +#include "capabilities.h" +#include "tcsps.h" +#include "tcslog.h" + + +#define TSS_TPM_RSP_BLOB_AUTH_LEN (sizeof(TPM_NONCE) + sizeof(TPM_DIGEST) + sizeof(TPM_BOOL)) + +TSS_RESULT +tpm_rsp_parse(TPM_COMMAND_CODE ordinal, BYTE *b, UINT32 len, ...) +{ + TSS_RESULT result = TSS_SUCCESS; + UINT64 offset1, offset2; + va_list ap; + + DBG_ASSERT(ordinal); + DBG_ASSERT(b); + + va_start(ap, len); + + switch (ordinal) { + case TPM_ORD_ExecuteTransport: + { + UINT32 *val1 = va_arg(ap, UINT32 *); + UINT32 *val2 = va_arg(ap, UINT32 *); + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (auth1 && auth2) { + offset1 = offset2 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN); + UnloadBlob_Auth(&offset1, b, auth1); + UnloadBlob_Auth(&offset1, b, auth2); + } else if (auth1) { + offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } else if (auth2) { + offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth2); + } else + offset2 = len; + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + if (val1) + UnloadBlob_UINT32(&offset1, val1, b); + if (val2) + UnloadBlob_UINT32(&offset1, val2, b); + + *len1 = offset2 - offset1; + if (*len1) { + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len1, b, *blob1); + } else + *blob1 = NULL; + + break; + } +#ifdef TSS_BUILD_TICK + /* TPM BLOB: TPM_CURRENT_TICKS, UINT32, BLOB, optional AUTH */ + case TPM_ORD_TickStampBlob: + { + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + UINT32 *len2 = va_arg(ap, UINT32 *); + BYTE **blob2 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!len1 || !blob1 || !len2 || !blob2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_CURRENT_TICKS(&offset2, b, NULL); + *len1 = (UINT32)offset2 - offset1; + + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, *len1, b, *blob1); + UnloadBlob_UINT32(&offset1, len2, b); + + if ((*blob2 = malloc(*len2)) == NULL) { + LogError("malloc of %u bytes failed", *len2); + free(*blob1); + *blob1 = NULL; + *len1 = 0; + *len2 = 0; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len2, b, *blob2); + + break; + } +#endif +#ifdef TSS_BUILD_QUOTE + /* TPM BLOB: TPM_PCR_COMPOSITE, UINT32, BLOB, 1 optional AUTH + * return UINT32*, BYTE**, UINT32*, BYTE**, 1 optional AUTH */ + case TPM_ORD_Quote: + { + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + UINT32 *len2 = va_arg(ap, UINT32 *); + BYTE **blob2 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!len1 || !blob1 || !len2 || !blob2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_PCR_COMPOSITE(&offset2, b, NULL); + *len1 = offset2 - offset1; + + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len1, b, *blob1); + UnloadBlob_UINT32(&offset1, len2, b); + + if ((*blob2 = malloc(*len2)) == NULL) { + LogError("malloc of %u bytes failed", *len2); + free(*blob1); + *blob1 = NULL; + *len1 = 0; + *len2 = 0; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len2, b, *blob2); + + break; + } +#endif +#ifdef TSS_BUILD_TSS12 + /* TPM BLOB: TPM_PCR_INFO_SHORT, (UINT32, BLOB,) UINT32, BLOB, 1 optional AUTH */ + case TPM_ORD_Quote2: + { + UINT32 *len1 = va_arg(ap, UINT32 *); /* pcrDataSizeOut */ + BYTE **blob1 = va_arg(ap, BYTE **); /* pcrDataOut */ + TSS_BOOL *addVersion = va_arg(ap, TSS_BOOL *); /* addVersion */ + UINT32 *len2 = va_arg(ap, UINT32 *); /* versionInfoSize */ + BYTE **blob2 = va_arg(ap, BYTE **); /* versionInfo */ + UINT32 *len3 = va_arg(ap, UINT32 *); /* sigSize */ + BYTE **blob3 = va_arg(ap, BYTE **); /* sig */ + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); /* privAuth */ + va_end(ap); + + if (!len1 || !blob1 || !len2 || !blob2 || !len3 || !blob3 || !addVersion) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + /* Adjust the offset to take the TPM_PCR_INFO_SHORT size: + * need to allocate this size into blob1 + */ + UnloadBlob_PCR_INFO_SHORT(&offset2, b, NULL); + + /* Get the size of the TSS_TPM_INFO_SHORT + * and copy it into blob1 */ + *len1 = offset2 - offset1; + LogDebugFn("QUOTE2 Core: PCR_INFO_SHORT is %u size", *len1); + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len1, b, *blob1); /* TPM_PCR_INFO_SHORT */ + + UnloadBlob_UINT32(&offset1, len2,b); /* versionInfoSize */ + LogDebugFn("QUOTE2 Core: versionInfoSize=%u", *len2); + if ((*blob2 = malloc(*len2)) == NULL) { + LogError("malloc of %u bytes failed", *len2); + free(*blob1); + *blob1 = NULL; + *len1 = 0; + *len2 = 0; + *len3 = 0; + *blob3 = NULL; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len2, b, *blob2); + + /* Take the sigSize */ + UnloadBlob_UINT32(&offset1, len3, b); + LogDebugFn("QUOTE2 Core: sigSize=%u", *len3); + /* sig */ + if ((*blob3 = malloc(*len3)) == NULL) { + LogError("malloc of %u bytes failed", *len3); + free(*blob1); + *blob1 = NULL; + if (*len2 > 0){ + free(*blob2); + *blob2 = NULL; + } + *len1 = 0; + *len2 = 0; + *len3 = 0; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len3, b, *blob3); + break; + } +#endif + /* TPM BLOB: TPM_CERTIFY_INFO, UINT32, BLOB, 2 optional AUTHs + * return UINT32*, BYTE**, UINT32*, BYTE**, 2 optional AUTHs */ + case TPM_ORD_CertifyKey: + { + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + UINT32 *len2 = va_arg(ap, UINT32 *); + BYTE **blob2 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!len1 || !blob1 || !len2 || !blob2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1 && auth2) { + offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN); + UnloadBlob_Auth(&offset1, b, auth1); + UnloadBlob_Auth(&offset1, b, auth2); + } else if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } else if (auth2) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth2); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_CERTIFY_INFO(&offset2, b, NULL); + *len1 = offset2 - offset1; + + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len1, b, *blob1); + UnloadBlob_UINT32(&offset1, len2, b); + + if ((*blob2 = malloc(*len2)) == NULL) { + LogError("malloc of %u bytes failed", *len2); + free(*blob1); + *blob1 = NULL; + *len1 = 0; + *len2 = 0; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len2, b, *blob2); + + break; + } +#ifdef TSS_BUILD_AUDIT + /* TPM_BLOB: TPM_COUNTER_VALUE, DIGEST, DIGEST, UINT32, BLOB, optional AUTH + * return: UINT32*, BYTE**, DIGEST*, DIGEST*, UINT32*, BYTE**, optional AUTH */ + case TPM_ORD_GetAuditDigestSigned: + { + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + TPM_DIGEST *digest1 = va_arg(ap, TPM_DIGEST *); + TPM_DIGEST *digest2 = va_arg(ap, TPM_DIGEST *); + UINT32 *len2 = va_arg(ap, UINT32 *); + BYTE **blob2 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !digest2 || !len1 || !blob1 || !len2 || !blob2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_COUNTER_VALUE(&offset2, b, NULL); + *len1 = offset2 - offset1; + + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len1, b, *blob1); + + UnloadBlob_DIGEST(&offset1, b, digest1); + UnloadBlob_DIGEST(&offset1, b, digest2); + UnloadBlob_UINT32(&offset1, len2, b); + + if ((*blob2 = malloc(*len2)) == NULL) { + LogError("malloc of %u bytes failed", *len2); + free(*blob1); + *blob1 = NULL; + *len1 = 0; + *len2 = 0; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len2, b, *blob2); + + if (auth1) + UnloadBlob_Auth(&offset1, b, auth1); + + break; + } + /* TPM_BLOB: TPM_COUNTER_VALUE, DIGEST, BOOL, UINT32, BLOB + * return: DIGEST*, UINT32*, BYTE**, BOOL, UINT32*, BYTE** */ + case TPM_ORD_GetAuditDigest: + { + TPM_DIGEST *digest1 = va_arg(ap, TPM_DIGEST *); + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + TSS_BOOL *bool1 = va_arg(ap, TSS_BOOL *); + UINT32 *len2 = va_arg(ap, UINT32 *); + BYTE **blob2 = va_arg(ap, BYTE **); + va_end(ap); + + if (!digest1 || !len1 || !blob1 || !len2 || !blob2 || !bool1) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_COUNTER_VALUE(&offset2, b, NULL); + *len1 = offset2 - offset1; + + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len1, b, *blob1); + + UnloadBlob_DIGEST(&offset1, b, digest1); + UnloadBlob_BOOL(&offset1, bool1, b); + UnloadBlob_UINT32(&offset1, len2, b); + + if ((*blob2 = malloc(*len2)) == NULL) { + LogError("malloc of %u bytes failed", *len2); + free(*blob1); + *blob1 = NULL; + *len1 = 0; + *len2 = 0; + return TCSERR(TSS_E_OUTOFMEMORY); + } + UnloadBlob(&offset1, *len2, b, *blob2); + + break; + } +#endif +#ifdef TSS_BUILD_COUNTER + /* optional UINT32, TPM_COUNTER_VALUE, optional AUTH */ + case TPM_ORD_ReadCounter: + case TPM_ORD_CreateCounter: + case TPM_ORD_IncrementCounter: + { + UINT32 *val1 = va_arg(ap, UINT32 *); + TPM_COUNTER_VALUE *ctr = va_arg(ap, TPM_COUNTER_VALUE *); + TPM_AUTH * auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!ctr) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + if (val1) + UnloadBlob_UINT32(&offset1, val1, b); + UnloadBlob_COUNTER_VALUE(&offset1, b, ctr); + + break; + } +#endif + /* TPM BLOB: UINT32, BLOB, UINT32, BLOB, optional AUTH, optional AUTH */ + case TPM_ORD_CreateMaintenanceArchive: + case TPM_ORD_CreateMigrationBlob: + case TPM_ORD_Delegate_ReadTable: + case TPM_ORD_CMK_CreateBlob: + { + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + UINT32 *len2 = va_arg(ap, UINT32 *); + BYTE **blob2 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!len1 || !blob1 || !len2 || !blob2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1 && auth2) { + offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN); + UnloadBlob_Auth(&offset1, b, auth1); + UnloadBlob_Auth(&offset1, b, auth2); + } else if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } else if (auth2) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth2); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_UINT32(&offset1, len1, b); + if ((*blob1 = malloc(*len1)) == NULL) { + LogError("malloc of %u bytes failed", *len1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, *len1, b, *blob1); + + UnloadBlob_UINT32(&offset1, len2, b); + if ((*blob2 = malloc(*len2)) == NULL) { + free(*blob1); + LogError("malloc of %u bytes failed", *len2); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, *len2, b, *blob2); + + break; + } + /* TPM BLOB: BLOB, optional AUTH, AUTH + * return: UINT32 *, BYTE **, optional AUTH, AUTH */ + case TPM_ORD_ActivateIdentity: + { + UINT32 *len1 = va_arg(ap, UINT32 *); + BYTE **blob1 = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!len1 || !blob1 || !auth2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1 && auth2) { + offset1 = offset2 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN); + UnloadBlob_Auth(&offset1, b, auth1); + UnloadBlob_Auth(&offset1, b, auth2); + } else if (auth2) { + offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth2); + } else + offset2 = len; + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + offset2 -= TSS_TPM_TXBLOB_HDR_LEN; + if ((*blob1 = malloc(offset2)) == NULL) { + LogError("malloc of %zd bytes failed", (size_t)offset2); + return TCSERR(TSS_E_OUTOFMEMORY); + } + *len1 = offset2; + UnloadBlob(&offset1, *len1, b, *blob1); + + break; + } + /* TPM BLOB: TPM_KEY, UINT32, BLOB, optional AUTH, AUTH + * return: UINT32 *, BYTE **, UINT32 *, BYTE **, optional AUTH, AUTH */ + case TPM_ORD_MakeIdentity: + { + UINT32 *len1, *len2; + BYTE **blob1, **blob2; + TPM_AUTH *auth1, *auth2; + + len1 = va_arg(ap, UINT32 *); + blob1 = va_arg(ap, BYTE **); + len2 = va_arg(ap, UINT32 *); + blob2 = va_arg(ap, BYTE **); + auth1 = va_arg(ap, TPM_AUTH *); + auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!len1 || !blob1 || !len2 || !blob2 || !auth2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_TSS_KEY(&offset1, b, NULL); + offset1 -= TSS_TPM_TXBLOB_HDR_LEN; + + if ((*blob1 = malloc(offset1)) == NULL) { + LogError("malloc of %zd bytes failed", (size_t)offset1); + return TCSERR(TSS_E_OUTOFMEMORY); + } + *len1 = offset1; + + UnloadBlob(&offset2, offset1, b, *blob1); + + /* offset2 points to the stuff after the key */ + UnloadBlob_UINT32(&offset2, len2, b); + + if ((*blob2 = malloc(*len2)) == NULL) { + free(*blob1); + LogError("malloc of %u bytes failed", *len2); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset2, *len2, b, *blob2); + + if (auth1) + UnloadBlob_Auth(&offset2, b, auth1); + UnloadBlob_Auth(&offset2, b, auth2); + + break; + } + /* 1 TPM_VERSION, 2 UINT32s, 1 optional AUTH */ + case TPM_ORD_GetCapabilityOwner: + { + TPM_VERSION *ver1 = va_arg(ap, TPM_VERSION *); + UINT32 *data1 = va_arg(ap, UINT32 *); + UINT32 *data2 = va_arg(ap, UINT32 *); + TPM_AUTH *auth = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!data1 || !data2 || !ver1) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_VERSION(&offset1, b, ver1); + UnloadBlob_UINT32(&offset1, data1, b); + UnloadBlob_UINT32(&offset1, data2, b); + break; + } + /* TPM BLOB: 1 UINT32, 1 BLOB, 2 optional AUTHs + * return: UINT32 *, BYTE**, 2 optional AUTHs */ + case TPM_ORD_Sign: + case TPM_ORD_GetTestResult: + case TPM_ORD_CertifySelfTest: + case TPM_ORD_Unseal: + case TPM_ORD_GetRandom: + case TPM_ORD_DAA_Join: + case TPM_ORD_DAA_Sign: + case TPM_ORD_ChangeAuth: + case TPM_ORD_GetCapability: + case TPM_ORD_LoadMaintenanceArchive: + case TPM_ORD_ConvertMigrationBlob: + case TPM_ORD_NV_ReadValue: + case TPM_ORD_NV_ReadValueAuth: + case TPM_ORD_Delegate_Manage: + case TPM_ORD_Delegate_CreateKeyDelegation: + case TPM_ORD_Delegate_CreateOwnerDelegation: + case TPM_ORD_Delegate_UpdateVerification: + case TPM_ORD_CMK_ConvertMigration: + { + UINT32 *data_len = va_arg(ap, UINT32 *); + BYTE **data = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!data || !data_len) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1 && auth2) { + offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN); + UnloadBlob_Auth(&offset1, b, auth1); + UnloadBlob_Auth(&offset1, b, auth2); + } else if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } else if (auth2) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth2); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_UINT32(&offset1, data_len, b); + if ((*data = malloc(*data_len)) == NULL) { + LogError("malloc of %u bytes failed", *data_len); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, *data_len, b, *data); + break; + } + /* TPM BLOB: 1 UINT32, 1 BLOB, 1 optional AUTH + * return: UINT32 *, BYTE**, 1 optional AUTH*/ + case TPM_ORD_UnBind: + { + UINT32 *data_len = va_arg(ap, UINT32 *); + BYTE **data = va_arg(ap, BYTE **); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!data || !data_len) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth1) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth1); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_UINT32(&offset1, data_len, b); + if ((*data = malloc(*data_len)) == NULL) { + LogError("malloc of %u bytes failed", *data_len); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, *data_len, b, *data); + break; + } + /* TPM BLOB: 1 BLOB, 1 optional AUTH + * return: UINT32 *, BYTE**, 1 optional AUTH*/ + case TPM_ORD_GetTicks: + case TPM_ORD_Seal: + case TPM_ORD_Sealx: + case TPM_ORD_FieldUpgrade: + case TPM_ORD_CreateWrapKey: + case TPM_ORD_GetPubKey: + case TPM_ORD_OwnerReadPubek: + case TPM_ORD_OwnerReadInternalPub: + case TPM_ORD_AuthorizeMigrationKey: + case TPM_ORD_TakeOwnership: + case TPM_ORD_CMK_CreateKey: + { + UINT32 *data_len = va_arg(ap, UINT32 *); + BYTE **data = va_arg(ap, BYTE **); + TPM_AUTH *auth = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!data || !data_len) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + /* remove the auth data from the back end of the data */ + if (auth) { + offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth); + } else + offset2 = len; + + /* everything after the header is returned as the blob */ + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + offset2 -= offset1; + if ((*data = malloc((size_t)offset2)) == NULL) { + LogError("malloc of %zd bytes failed", (size_t)offset2); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + if ((offset1 + offset2) > TSS_TPM_TXBLOB_SIZE) + return TCSERR(TSS_E_INTERNAL_ERROR); + + memcpy(*data, &b[offset1], offset2); + *data_len = offset2; + break; + } + /* TPM BLOB: BLOB, optional DIGEST */ + case TPM_ORD_CreateEndorsementKeyPair: + case TPM_ORD_ReadPubek: + { + UINT32 *data_len = va_arg(ap, UINT32 *); + BYTE **data = va_arg(ap, BYTE **); + BYTE *digest1 = va_arg(ap, BYTE *); + va_end(ap); + + if (!data || !data_len) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if ((offset2 + TPM_DIGEST_SIZE) > TSS_TPM_TXBLOB_SIZE) + return TCSERR(TSS_E_INTERNAL_ERROR); + + if (digest1) { + offset1 = offset2 = len - TPM_DIGEST_SIZE; + memcpy(digest1, &b[offset2], TPM_DIGEST_SIZE); + } else + offset2 = len; + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + offset2 -= offset1; + if ((*data = malloc((size_t)offset2)) == NULL) { + LogError("malloc of %zd bytes failed", (size_t)offset2); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, offset2, b, *data); + *data_len = offset2; + break; + } +#ifdef TSS_BUILD_TSS12 + /* TPM BLOB: BLOB, DIGEST, DIGEST + * return: UINT32 *, BYTE**, DIGEST, DIGEST */ + case TPM_ORD_CreateRevocableEK: + { + UINT32 *data_len = va_arg(ap, UINT32 *); + BYTE **data = va_arg(ap, BYTE **); + BYTE *digest1 = va_arg(ap, BYTE *); + BYTE *digest2 = va_arg(ap, BYTE *); + va_end(ap); + + if (!data || !data_len || !digest1 || !digest2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (len > TSS_TPM_TXBLOB_SIZE) + return TCSERR(TSS_E_INTERNAL_ERROR); + + offset2 = len - TPM_DIGEST_SIZE; + memcpy(digest2, &b[offset2], TPM_DIGEST_SIZE); + + offset2 -= TPM_DIGEST_SIZE; + memcpy(digest1, &b[offset2], TPM_DIGEST_SIZE); + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + offset2 -= offset1; + if ((*data = malloc((size_t)offset2)) == NULL) { + LogError("malloc of %zd bytes failed", (size_t)offset2); + return TCSERR(TSS_E_OUTOFMEMORY); + } + + UnloadBlob(&offset1, offset2, b, *data); + *data_len = offset2; + break; + } +#endif + /* 1 UINT32, 1 optional AUTH */ + case TPM_ORD_LoadKey: + case TPM_ORD_LoadKey2: + { + UINT32 *handle; + TPM_AUTH *auth; + + handle = va_arg(ap, UINT32 *); + auth = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!handle) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + if (auth) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_UINT32(&offset1, handle, b); + break; + } + /* 1 optional UINT32, 1 20 byte value */ + case TPM_ORD_DirRead: + case TPM_ORD_OIAP: + case TPM_ORD_LoadManuMaintPub: + case TPM_ORD_ReadManuMaintPub: + case TPM_ORD_Extend: + case TPM_ORD_PcrRead: + { + UINT32 *handle = va_arg(ap, UINT32 *); + BYTE *nonce = va_arg(ap, BYTE *); + va_end(ap); + + if (!nonce) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + if (handle) + UnloadBlob_UINT32(&offset1, handle, b); + UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce); + break; + } + /* 1 UINT32, 2 20 byte values */ + case TPM_ORD_OSAP: + case TPM_ORD_DSAP: + { + UINT32 *handle = va_arg(ap, UINT32 *); + BYTE *nonce1 = va_arg(ap, BYTE *); + BYTE *nonce2 = va_arg(ap, BYTE *); + va_end(ap); + + if (!handle || !nonce1 || !nonce2) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob_UINT32(&offset1, handle, b); + UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce1); + UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce2); + break; + } +#ifdef TSS_BUILD_CMK + /* 1 20 byte value, 1 optional AUTH */ + case TPM_ORD_CMK_ApproveMA: + case TPM_ORD_CMK_CreateTicket: + { + BYTE *hmac1 = va_arg(ap, BYTE *); + TPM_AUTH *auth = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!hmac1) { + LogError("Internal error for ordinal 0x%x", ordinal); + return TCSERR(TSS_E_INTERNAL_ERROR); + } + + offset1 = TSS_TPM_TXBLOB_HDR_LEN; + UnloadBlob(&offset1, TPM_SHA1_160_HASH_LEN, b, hmac1); + if (auth) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth); + } + break; + } +#endif + /* 1 optional AUTH */ + case TPM_ORD_DisablePubekRead: + case TPM_ORD_DirWriteAuth: + case TPM_ORD_ReleaseCounter: + case TPM_ORD_ReleaseCounterOwner: + case TPM_ORD_ChangeAuthOwner: + case TPM_ORD_SetCapability: + case TPM_ORD_SetOrdinalAuditStatus: + case TPM_ORD_ResetLockValue: + case TPM_ORD_SetRedirection: + case TPM_ORD_DisableOwnerClear: + case TPM_ORD_OwnerSetDisable: + case TPM_ORD_SetTempDeactivated: + case TPM_ORD_KillMaintenanceFeature: + case TPM_ORD_NV_DefineSpace: + case TPM_ORD_NV_WriteValue: + case TPM_ORD_NV_WriteValueAuth: + case TPM_ORD_OwnerClear: + case TPM_ORD_Delegate_LoadOwnerDelegation: + case TPM_ORD_CMK_SetRestrictions: + case TPM_ORD_FlushSpecific: + case TPM_ORD_KeyControlOwner: + { + TPM_AUTH *auth = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (auth) { + offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN; + UnloadBlob_Auth(&offset1, b, auth); + } + break; + } + default: + LogError("Unknown ordinal: 0x%x", ordinal); + result = TCSERR(TSS_E_INTERNAL_ERROR); + break; + } + + return result; +} + +/* XXX optimize these cases by always passing in lengths for blobs, no more "20 byte values" */ +TSS_RESULT +tpm_rqu_build(TPM_COMMAND_CODE ordinal, UINT64 *outOffset, BYTE *out_blob, ...) +{ + TSS_RESULT result = TSS_SUCCESS; + UINT64 blob_size; + va_list ap; + + DBG_ASSERT(ordinal); + DBG_ASSERT(outOffset); + DBG_ASSERT(out_blob); + + va_start(ap, out_blob); + + switch (ordinal) { +#ifdef TSS_BUILD_DELEGATION + /* 1 UINT16, 1 UINT32, 1 20 bytes value, 1 UINT32, 1 BLOB */ + case TPM_ORD_DSAP: + { + UINT16 val1 = va_arg(ap, int); + UINT32 handle1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + va_end(ap); + + if (!digest1 || !in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT16(outOffset, val1, out_blob); + LoadBlob_UINT32(outOffset, handle1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 1 BOOL, 1 UINT32, 1 BLOB, 1 20 byte value, 1 AUTH */ + case TPM_ORD_Delegate_CreateOwnerDelegation: + { + TSS_BOOL bool1 = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + BYTE *digest1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!in_len1 || !in_blob1 || !digest1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_BOOL(outOffset, bool1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 2 UINT32's, 1 BLOB, 1 20 byte value, 1 AUTH */ + case TPM_ORD_Delegate_CreateKeyDelegation: + { + UINT32 keyslot1 = va_arg(ap, UINT32); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + BYTE *digest1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keyslot1 || !in_len1 || !in_blob1 || !digest1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keyslot1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif +#ifdef TSS_BUILD_TRANSPORT + /* 3 UINT32's, 1 BLOB, 2 AUTHs */ + case TPM_ORD_ExecuteTransport: + { + UINT32 ord1 = va_arg(ap, UINT32); + UINT32 *keyslot1 = va_arg(ap, UINT32 *); + UINT32 *keyslot2 = va_arg(ap, UINT32 *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + if (keyslot1) + LoadBlob_UINT32(outOffset, *keyslot1, out_blob); + if (keyslot2) + LoadBlob_UINT32(outOffset, *keyslot2, out_blob); + //LoadBlob_UINT32(outOffset, in_len1, out_blob); + if (in_blob1) + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + + if (auth1 && auth2) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ord1, out_blob); + } else if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ord1, out_blob); + } else if (auth2) { + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ord1, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ord1, out_blob); + } + + break; + } +#endif + /* 1 UINT32, 1 UINT16, 1 BLOB, 1 UINT32, 1 BLOB, 1 options AUTH, 1 AUTH */ + case TPM_ORD_CreateMigrationBlob: + { + UINT32 keyslot1 = va_arg(ap, UINT32); + UINT16 type1 = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!in_blob1 || !in_blob2 || !auth2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keyslot1, out_blob); + LoadBlob_UINT16(outOffset, type1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT32, 1 UINT16, 1 20 byte value, 1 UINT16, 1 UINT32, 1 BLOB, 2 AUTHs */ + case TPM_ORD_ChangeAuth: + { + UINT32 keyslot1 = va_arg(ap, UINT32); + UINT16 proto1 = va_arg(ap, int); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT16 entity1 = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !in_blob1 || !auth1 || !auth2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keyslot1, out_blob); + LoadBlob_UINT16(outOffset, proto1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_UINT16(outOffset, entity1, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 2 DIGEST/ENCAUTH's, 1 UINT32, 1 BLOB, 1 optional AUTH, 1 AUTH */ + case TPM_ORD_MakeIdentity: + { + BYTE *dig1, *dig2, *blob1; + UINT32 len1; + TPM_AUTH *auth1, *auth2; + + dig1 = va_arg(ap, BYTE *); + dig2 = va_arg(ap, BYTE *); + len1 = va_arg(ap, UINT32); + blob1 = va_arg(ap, BYTE *); + auth1 = va_arg(ap, TPM_AUTH *); + auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!dig1 || !dig2 || !blob1 || !auth2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, dig1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, dig2); + LoadBlob(outOffset, len1, out_blob, blob1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#if (TSS_BUILD_NV || TSS_BUILD_DELEGATION) + /* 3 UINT32's, 1 BLOB, 1 optional AUTH */ + case TPM_ORD_NV_WriteValue: + case TPM_ORD_NV_WriteValueAuth: + case TPM_ORD_Delegate_Manage: + { + UINT32 i = va_arg(ap, UINT32); + UINT32 j = va_arg(ap, UINT32); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, i, out_blob); + LoadBlob_UINT32(outOffset, j, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#endif + /* 3 UINT32's, 1 optional AUTH */ + case TPM_ORD_NV_ReadValue: + case TPM_ORD_NV_ReadValueAuth: + case TPM_ORD_SetRedirection: + { + UINT32 i = va_arg(ap, UINT32); + UINT32 j = va_arg(ap, UINT32); + UINT32 k = va_arg(ap, UINT32); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, i, out_blob); + LoadBlob_UINT32(outOffset, j, out_blob); + LoadBlob_UINT32(outOffset, k, out_blob); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 20 byte value, 1 UINT32, 1 BLOB */ + case TPM_ORD_CreateEndorsementKeyPair: + { + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + va_end(ap); + + if (!digest1 || !in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#ifdef TSS_BUILD_TSS12 + /* 1 20 byte value, 1 UINT32, 1 BLOB, 1 BOOL, 1 20 byte value */ + case TPM_ORD_CreateRevocableEK: + { + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TSS_BOOL in_bool1 = va_arg(ap, int); + BYTE *digest2 = va_arg(ap, BYTE *); + va_end(ap); + + if (!digest1 || !in_blob1 || !digest2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_BOOL(outOffset, in_bool1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 1 20 byte value */ + case TPM_ORD_RevokeTrust: + { + BYTE *digest1 = va_arg(ap, BYTE *); + va_end(ap); + + if (!digest1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif +#ifdef TSS_BUILD_COUNTER + /* 1 20 byte value, 1 UINT32, 1 BLOB, 1 AUTH */ + case TPM_ORD_CreateCounter: + { + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !in_blob1 || !auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif +#ifdef TSS_BUILD_DAA + /* 1 UINT32, 1 BYTE, 1 UINT32, 1 BLOB, 1 UINT32, 1 BLOB, 1 AUTH */ + case TPM_ORD_DAA_Sign: + case TPM_ORD_DAA_Join: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + BYTE stage1 = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !in_blob1 || !auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob_BOOL(outOffset, stage1, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif + /* 2 UINT32's, 1 BLOB, 1 UINT32, 1 BLOB, 1 optional AUTH */ + case TPM_ORD_ConvertMigrationBlob: + case TPM_ORD_SetCapability: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !in_blob1 || !in_blob2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 2 UINT32's, 1 20 byte value, 2 optional AUTHs */ + case TPM_ORD_CertifyKey: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + UINT32 keySlot2 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !keySlot2 || !digest1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob_UINT32(outOffset, keySlot2, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + if (auth1 && auth2) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob); + } else if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else if (auth2) { + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 2 UINT32's, 1 BLOB, 1 optional AUTH */ + case TPM_ORD_Delegate_LoadOwnerDelegation: + case TPM_ORD_GetCapability: + case TPM_ORD_UnBind: + case TPM_ORD_Sign: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (in_len1 && !in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + if (in_len1) + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT32, 1 20 byte value, 1 UINT32, 1 optional BLOB, 1 UINT32, 1 BLOB, 1 AUTH */ + case TPM_ORD_Seal: + case TPM_ORD_Sealx: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + blob_size = in_len1 + in_len2 + TPM_DIGEST_SIZE + sizeof(TPM_AUTH); + if (blob_size > TSS_TPM_TXBLOB_SIZE) { + result = TCSERR(TSS_E_BAD_PARAMETER); + LogError("Oversized input when building ordinal 0x%x", ordinal); + break; + } + + if (!keySlot1 || !in_blob2 || !auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 2 UINT32's, 1 BLOB, 1 optional AUTH, 1 AUTH */ + case TPM_ORD_ActivateIdentity: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !in_blob1 || !auth2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT32, 1 20-byte blob, 1 BLOB, 1 optional AUTH */ + case TPM_ORD_Quote: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !digest1 || !in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#ifdef TSS_BUILD_TSS12 + /* 1 UINT32, 1 20-byte blob, 1 BLOB, 1 BOOL, 1 optional AUTH */ + case TPM_ORD_Quote2: + { + /* Input vars */ + UINT32 keySlot1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TSS_BOOL* addVersion = va_arg(ap,TSS_BOOL *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !digest1 || !in_blob1 || !addVersion) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + + /* Load the addVersion Bool */ + LoadBlob_BOOL(outOffset,*addVersion,out_blob); + + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif + /* 1 UINT32, 2 20-byte blobs, 1 BLOB, 1 optional AUTH */ + case TPM_ORD_CreateWrapKey: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + BYTE *digest2 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !digest1 || !digest2 || !in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 2 BLOBs, 1 optional AUTH */ + case TPM_ORD_NV_DefineSpace: + case TPM_ORD_LoadManuMaintPub: + { + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!in_blob1 || !in_blob2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#ifdef TSS_BUILD_TICK + /* 1 UINT32, 2 20-byte blobs, 1 optional AUTH */ + case TPM_ORD_TickStampBlob: + { + UINT32 keySlot1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + BYTE *digest2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!keySlot1 || !digest1 || !digest2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keySlot1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2); + + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif + /* 1 BLOB */ + case TPM_ORD_ReadManuMaintPub: + case TPM_ORD_ReadPubek: + case TPM_ORD_PCR_Reset: + case TPM_ORD_SetOperatorAuth: + { + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + va_end(ap); + + if (!in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 1 UINT32, 1 BLOB, 2 optional AUTHs */ + case TPM_ORD_LoadKey: + case TPM_ORD_LoadKey2: + case TPM_ORD_DirWriteAuth: + case TPM_ORD_CertifySelfTest: + case TPM_ORD_Unseal: + case TPM_ORD_Extend: + case TPM_ORD_StirRandom: + case TPM_ORD_LoadMaintenanceArchive: /* XXX */ + case TPM_ORD_FieldUpgrade: + case TPM_ORD_Delegate_UpdateVerification: + case TPM_ORD_Delegate_VerifyDelegation: + { + UINT32 val1 = va_arg(ap, UINT32); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (in_len1 && !in_blob1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, val1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + if (auth1 && auth2) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob); + } else if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else if (auth2) { + LoadBlob_Auth(outOffset, out_blob, auth2); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT16, 1 BLOB, 1 AUTH */ + case TPM_ORD_AuthorizeMigrationKey: + { + UINT16 scheme1 = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!in_blob1 || !auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT16(outOffset, scheme1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 1 UINT16, 1 UINT32, 1 BLOB, 1 UINT32, 2 BLOBs, 1 AUTH */ + case TPM_ORD_TakeOwnership: + { + UINT16 scheme1 = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + UINT32 in_len3 = va_arg(ap, UINT32); + BYTE *in_blob3 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!in_blob1 || !in_blob2 || !in_blob3 || !auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT16(outOffset, scheme1, out_blob); + LoadBlob_UINT32(outOffset, in_len1, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + LoadBlob(outOffset, in_len3, out_blob, in_blob3); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#ifdef TSS_BUILD_AUDIT + /* 1 UINT32, 1 BOOL, 1 20 byte value, 1 optional AUTH */ + case TPM_ORD_GetAuditDigestSigned: + { + UINT32 keyslot1 = va_arg(ap, UINT32); + TSS_BOOL bool1 = va_arg(ap, int); + BYTE *digest1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, keyslot1, out_blob); + LoadBlob_BOOL(outOffset, bool1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#endif + /* 1 UINT16, 1 UINT32, 1 20 byte value */ + case TPM_ORD_OSAP: + { + UINT16 type1 = va_arg(ap, int); + UINT32 value1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + va_end(ap); + + if (!digest1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT16(outOffset, type1, out_blob); + LoadBlob_UINT32(outOffset, value1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 1 UINT16, 1 20 byte value, 1 UINT16, 1 AUTH */ + case TPM_ORD_ChangeAuthOwner: + { + UINT16 type1 = va_arg(ap, int); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT16 type2 = va_arg(ap, int); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT16(outOffset, type1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_UINT16(outOffset, type2, out_blob); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#ifdef TSS_BUILD_AUDIT + /* 1 UINT32, 1 BOOL, 1 AUTH */ + case TPM_ORD_SetOrdinalAuditStatus: + { + UINT32 ord1 = va_arg(ap, UINT32); + TSS_BOOL bool1 = va_arg(ap, int); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!auth1) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, ord1, out_blob); + LoadBlob_BOOL(outOffset, bool1, out_blob); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif + /* 1 BOOL, 1 optional AUTH */ + case TPM_ORD_OwnerSetDisable: + case TPM_ORD_PhysicalSetDeactivated: + case TPM_ORD_CreateMaintenanceArchive: + case TPM_ORD_SetOwnerInstall: + { + TSS_BOOL bool1 = va_arg(ap, int); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_BOOL(outOffset, bool1, out_blob); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 optional AUTH */ + case TPM_ORD_OwnerClear: + case TPM_ORD_DisablePubekRead: + case TPM_ORD_GetCapabilityOwner: + case TPM_ORD_ResetLockValue: + case TPM_ORD_DisableOwnerClear: + case TPM_ORD_SetTempDeactivated: + case TPM_ORD_OIAP: + case TPM_ORD_OwnerReadPubek: + case TPM_ORD_SelfTestFull: + case TPM_ORD_GetTicks: + case TPM_ORD_GetTestResult: + case TPM_ORD_KillMaintenanceFeature: + case TPM_ORD_Delegate_ReadTable: + case TPM_ORD_PhysicalEnable: + case TPM_ORD_DisableForceClear: + case TPM_ORD_ForceClear: + { + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT32, 1 optional AUTH */ + case TPM_ORD_OwnerReadInternalPub: + case TPM_ORD_GetPubKey: + case TPM_ORD_ReleaseCounterOwner: + case TPM_ORD_ReleaseCounter: + case TPM_ORD_IncrementCounter: + case TPM_ORD_PcrRead: + case TPM_ORD_DirRead: + case TPM_ORD_ReadCounter: + case TPM_ORD_Terminate_Handle: + case TPM_ORD_GetAuditDigest: + case TPM_ORD_GetRandom: + case TPM_ORD_CMK_SetRestrictions: + { + UINT32 i = va_arg(ap, UINT32); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, i, out_blob); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#ifdef TSS_BUILD_CMK + /* 1 20 byte value, 1 optional AUTH */ + case TPM_ORD_CMK_ApproveMA: + { + BYTE *digest1 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#endif + /* 1 UINT16 only */ + case TSC_ORD_PhysicalPresence: + { + UINT16 i = va_arg(ap, int); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT16(outOffset, i, out_blob); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#ifdef TSS_BUILD_CMK + /* 1 UINT32, 1 20 byte value, 1 BLOB, 2 20 byte values, 1 optional AUTH */ + case TPM_ORD_CMK_CreateKey: + { + UINT32 key1 = va_arg(ap, UINT32); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + BYTE *digest2 = va_arg(ap, BYTE *); + BYTE *digest3 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !in_blob1 || !digest2 || !digest3) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, key1, out_blob); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest3); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 BLOB, 1 20 byte value, 1 UINT32, 1 BLOB, 1 optional AUTH */ + case TPM_ORD_CMK_CreateTicket: + { + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !in_blob1 || !in_blob2) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT32, 1 UINT16, 1 BLOB, 1 20 byte value, 4 x (1 UINT32, 1 BLOB), 1 optional AUTH */ + case TPM_ORD_CMK_CreateBlob: + { + UINT32 in_key1 = va_arg(ap, UINT32); + UINT16 i = va_arg(ap, int); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + UINT32 in_len3 = va_arg(ap, UINT32); + BYTE *in_blob3 = va_arg(ap, BYTE *); + UINT32 in_len4 = va_arg(ap, UINT32); + BYTE *in_blob4 = va_arg(ap, BYTE *); + UINT32 in_len5 = va_arg(ap, UINT32); + BYTE *in_blob5 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!digest1 || !in_blob1 || !in_blob2 || !in_blob3 || !in_blob4 || !in_blob5) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, in_key1, out_blob); + LoadBlob_UINT16(outOffset, i, out_blob); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + LoadBlob_UINT32(outOffset, in_len3, out_blob); + LoadBlob(outOffset, in_len3, out_blob, in_blob3); + LoadBlob_UINT32(outOffset, in_len4, out_blob); + LoadBlob(outOffset, in_len4, out_blob, in_blob4); + LoadBlob_UINT32(outOffset, in_len5, out_blob); + LoadBlob(outOffset, in_len5, out_blob, in_blob5); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } + /* 1 UINT32, 1 60 byte value, 1 20 byte value, 1 BLOB, 2 x (1 UINT32, 1 BLOB), + * 1 optional AUTH */ + case TPM_ORD_CMK_ConvertMigration: + { + UINT32 key1 = va_arg(ap, UINT32); + BYTE *cmkauth1 = va_arg(ap, BYTE *); + BYTE *digest1 = va_arg(ap, BYTE *); + UINT32 in_len1 = va_arg(ap, UINT32); + BYTE *in_blob1 = va_arg(ap, BYTE *); + UINT32 in_len2 = va_arg(ap, UINT32); + BYTE *in_blob2 = va_arg(ap, BYTE *); + UINT32 in_len3 = va_arg(ap, UINT32); + BYTE *in_blob3 = va_arg(ap, BYTE *); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + if (!cmkauth1 || !digest1 || !in_blob1 || !in_blob2 || !in_blob3) { + result = TCSERR(TSS_E_INTERNAL_ERROR); + LogError("Internal error for ordinal 0x%x", ordinal); + break; + } + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, key1, out_blob); + LoadBlob(outOffset, 3 * TPM_SHA1_160_HASH_LEN, out_blob, cmkauth1); + LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1); + LoadBlob(outOffset, in_len1, out_blob, in_blob1); + LoadBlob_UINT32(outOffset, in_len2, out_blob); + LoadBlob(outOffset, in_len2, out_blob, in_blob2); + LoadBlob_UINT32(outOffset, in_len3, out_blob); + LoadBlob(outOffset, in_len3, out_blob, in_blob3); + if (auth1) { + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + } else { + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + } + + break; + } +#endif +#ifdef TSS_BUILD_TSS12 + case TPM_ORD_FlushSpecific: + { + UINT32 val1 = va_arg(ap, UINT32); + UINT32 val2 = va_arg(ap, UINT32); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, val1, out_blob); + LoadBlob_UINT32(outOffset, val2, out_blob); + LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob); + + break; + } + /* 1 UINT32, 1 BLOB, 1 UINT32, 1 BOOL, 1 AUTH */ + case TPM_ORD_KeyControlOwner: + { + UINT32 i = va_arg(ap, UINT32); + UINT32 len1 = va_arg(ap, UINT32); + BYTE *blob1 = va_arg(ap, BYTE *); + UINT32 j = va_arg(ap, UINT32); + TSS_BOOL bool1 = va_arg(ap, int); + TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); + va_end(ap); + + *outOffset += TSS_TPM_TXBLOB_HDR_LEN; + LoadBlob_UINT32(outOffset, i, out_blob); + LoadBlob(outOffset, len1, out_blob, blob1); + LoadBlob_UINT32(outOffset, j, out_blob); + LoadBlob_BOOL(outOffset, bool1, out_blob); + LoadBlob_Auth(outOffset, out_blob, auth1); + LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob); + + break; + } +#endif + default: + LogError("Unknown ordinal: 0x%x", ordinal); + break; + } + + return result; +} |