Home | History | Annotate | Line # | Download | only in tcs
      1 
      2 /*
      3  * Licensed Materials - Property of IBM
      4  *
      5  * trousers - An open source TCG Software Stack
      6  *
      7  * (C) Copyright International Business Machines Corp. 2004-2007
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <stdarg.h>
     15 #include <string.h>
     16 #include <unistd.h>
     17 #include <sys/types.h>
     18 #include <sys/stat.h>
     19 #include <sys/mman.h>
     20 #include <fcntl.h>
     21 #include <errno.h>
     22 
     23 #include "trousers/tss.h"
     24 #include "trousers_types.h"
     25 #include "tcs_tsp.h"
     26 #include "tcs_utils.h"
     27 #include "tcs_int_literals.h"
     28 #include "capabilities.h"
     29 #include "tcsps.h"
     30 #include "tcslog.h"
     31 
     32 
     33 #define TSS_TPM_RSP_BLOB_AUTH_LEN	(sizeof(TPM_NONCE) + sizeof(TPM_DIGEST) + sizeof(TPM_BOOL))
     34 
     35 TSS_RESULT
     36 tpm_rsp_parse(TPM_COMMAND_CODE ordinal, BYTE *b, UINT32 len, ...)
     37 {
     38 	TSS_RESULT result = TSS_SUCCESS;
     39 	UINT64 offset1, offset2;
     40 	va_list ap;
     41 
     42 	DBG_ASSERT(ordinal);
     43 	DBG_ASSERT(b);
     44 
     45 	va_start(ap, len);
     46 
     47 	switch (ordinal) {
     48 	case TPM_ORD_ExecuteTransport:
     49 	{
     50 		UINT32 *val1 = va_arg(ap, UINT32 *);
     51 		UINT32 *val2 = va_arg(ap, UINT32 *);
     52 		UINT32 *len1 = va_arg(ap, UINT32 *);
     53 		BYTE **blob1 = va_arg(ap, BYTE **);
     54 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
     55 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
     56 		va_end(ap);
     57 
     58 		if (auth1 && auth2) {
     59 			offset1 = offset2 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN);
     60 			UnloadBlob_Auth(&offset1, b, auth1);
     61 			UnloadBlob_Auth(&offset1, b, auth2);
     62 		} else if (auth1) {
     63 			offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
     64 			UnloadBlob_Auth(&offset1, b, auth1);
     65 		} else if (auth2) {
     66 			offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
     67 			UnloadBlob_Auth(&offset1, b, auth2);
     68 		} else
     69 			offset2 = len;
     70 
     71 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
     72 		if (val1)
     73 			UnloadBlob_UINT32(&offset1, val1, b);
     74 		if (val2)
     75 			UnloadBlob_UINT32(&offset1, val2, b);
     76 
     77 		*len1 = offset2 - offset1;
     78 		if (*len1) {
     79 			if ((*blob1 = malloc(*len1)) == NULL) {
     80 				LogError("malloc of %u bytes failed", *len1);
     81 				return TCSERR(TSS_E_OUTOFMEMORY);
     82 			}
     83 			UnloadBlob(&offset1, *len1, b, *blob1);
     84 		} else
     85 			*blob1 = NULL;
     86 
     87 		break;
     88 	}
     89 #ifdef TSS_BUILD_TICK
     90 	/* TPM BLOB: TPM_CURRENT_TICKS, UINT32, BLOB, optional AUTH */
     91 	case TPM_ORD_TickStampBlob:
     92 	{
     93 		UINT32 *len1 = va_arg(ap, UINT32 *);
     94 		BYTE **blob1 = va_arg(ap, BYTE **);
     95 		UINT32 *len2 = va_arg(ap, UINT32 *);
     96 		BYTE **blob2 = va_arg(ap, BYTE **);
     97 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
     98 		va_end(ap);
     99 
    100 		if (!len1 || !blob1 || !len2 || !blob2) {
    101 			LogError("Internal error for ordinal 0x%x", ordinal);
    102 			return TCSERR(TSS_E_INTERNAL_ERROR);
    103 		}
    104 
    105 		if (auth1) {
    106 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    107 			UnloadBlob_Auth(&offset1, b, auth1);
    108 		}
    109 
    110 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    111 		UnloadBlob_CURRENT_TICKS(&offset2, b, NULL);
    112 		*len1 = (UINT32)offset2 - offset1;
    113 
    114 		if ((*blob1 = malloc(*len1)) == NULL) {
    115 			LogError("malloc of %u bytes failed", *len1);
    116 			return TCSERR(TSS_E_OUTOFMEMORY);
    117 		}
    118 
    119 		UnloadBlob(&offset1, *len1, b, *blob1);
    120                 UnloadBlob_UINT32(&offset1, len2, b);
    121 
    122 		if ((*blob2 = malloc(*len2)) == NULL) {
    123 			LogError("malloc of %u bytes failed", *len2);
    124 			free(*blob1);
    125 			*blob1 = NULL;
    126 			*len1 = 0;
    127 			*len2 = 0;
    128 			return TCSERR(TSS_E_OUTOFMEMORY);
    129 		}
    130 		UnloadBlob(&offset1, *len2, b, *blob2);
    131 
    132 		break;
    133 	}
    134 #endif
    135 #ifdef TSS_BUILD_QUOTE
    136 	/* TPM BLOB: TPM_PCR_COMPOSITE, UINT32, BLOB, 1 optional AUTH
    137 	 * return UINT32*, BYTE**, UINT32*, BYTE**, 1 optional AUTH */
    138 	case TPM_ORD_Quote:
    139 	{
    140 		UINT32 *len1 = va_arg(ap, UINT32 *);
    141 		BYTE **blob1 = va_arg(ap, BYTE **);
    142 		UINT32 *len2 = va_arg(ap, UINT32 *);
    143 		BYTE **blob2 = va_arg(ap, BYTE **);
    144 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    145 		va_end(ap);
    146 
    147 		if (!len1 || !blob1 || !len2 || !blob2) {
    148 			LogError("Internal error for ordinal 0x%x", ordinal);
    149 			return TCSERR(TSS_E_INTERNAL_ERROR);
    150 		}
    151 
    152 		if (auth1) {
    153 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    154 			UnloadBlob_Auth(&offset1, b, auth1);
    155 		}
    156 
    157 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    158 		UnloadBlob_PCR_COMPOSITE(&offset2, b, NULL);
    159 		*len1 = offset2 - offset1;
    160 
    161 		if ((*blob1 = malloc(*len1)) == NULL) {
    162 			LogError("malloc of %u bytes failed", *len1);
    163 			return TCSERR(TSS_E_OUTOFMEMORY);
    164 		}
    165 		UnloadBlob(&offset1, *len1, b, *blob1);
    166                 UnloadBlob_UINT32(&offset1, len2, b);
    167 
    168 		if ((*blob2 = malloc(*len2)) == NULL) {
    169 			LogError("malloc of %u bytes failed", *len2);
    170 			free(*blob1);
    171 			*blob1 = NULL;
    172 			*len1 = 0;
    173 			*len2 = 0;
    174 			return TCSERR(TSS_E_OUTOFMEMORY);
    175 		}
    176 		UnloadBlob(&offset1, *len2, b, *blob2);
    177 
    178 		break;
    179 	}
    180 #endif
    181 #ifdef TSS_BUILD_TSS12
    182 	/* TPM BLOB: TPM_PCR_INFO_SHORT, (UINT32, BLOB,) UINT32, BLOB, 1 optional AUTH */
    183 	case TPM_ORD_Quote2:
    184 	{
    185 		UINT32 *len1 = va_arg(ap, UINT32 *); /* pcrDataSizeOut */
    186 		BYTE **blob1 = va_arg(ap, BYTE **);  /* pcrDataOut */
    187 		TSS_BOOL *addVersion = va_arg(ap, TSS_BOOL *); /* addVersion */
    188 		UINT32 *len2 = va_arg(ap, UINT32 *); /* versionInfoSize */
    189 		BYTE **blob2 = va_arg(ap, BYTE **);  /* versionInfo */
    190 		UINT32 *len3 = va_arg(ap, UINT32 *); /* sigSize */
    191 		BYTE **blob3 = va_arg(ap, BYTE **);  /* sig */
    192 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *); /* privAuth */
    193 		va_end(ap);
    194 
    195 		if (!len1 || !blob1 || !len2 || !blob2 || !len3 || !blob3 || !addVersion) {
    196 			LogError("Internal error for ordinal 0x%x", ordinal);
    197 			return TCSERR(TSS_E_INTERNAL_ERROR);
    198 		}
    199 
    200 		if (auth1) {
    201 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    202 			UnloadBlob_Auth(&offset1, b, auth1);
    203 		}
    204 
    205 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    206 		/* Adjust the offset to take the TPM_PCR_INFO_SHORT size:
    207 		 * need to allocate this size into blob1
    208 		 */
    209 		UnloadBlob_PCR_INFO_SHORT(&offset2, b, NULL);
    210 
    211 		/* Get the size of the TSS_TPM_INFO_SHORT
    212 		 * and copy it into blob1 */
    213 		*len1 = offset2 - offset1;
    214 		LogDebugFn("QUOTE2 Core: PCR_INFO_SHORT is %u size", *len1);
    215 		if ((*blob1 = malloc(*len1)) == NULL) {
    216 			LogError("malloc of %u bytes failed", *len1);
    217 			return TCSERR(TSS_E_OUTOFMEMORY);
    218 		}
    219 		UnloadBlob(&offset1, *len1, b, *blob1); /* TPM_PCR_INFO_SHORT */
    220 
    221 		UnloadBlob_UINT32(&offset1, len2,b); /* versionInfoSize */
    222 		LogDebugFn("QUOTE2 Core: versionInfoSize=%u", *len2);
    223 		if ((*blob2 = malloc(*len2)) == NULL) {
    224 			LogError("malloc of %u bytes failed", *len2);
    225 			free(*blob1);
    226 			*blob1 = NULL;
    227 			*len1 = 0;
    228 			*len2 = 0;
    229 			*len3 = 0;
    230 			*blob3 = NULL;
    231 			return TCSERR(TSS_E_OUTOFMEMORY);
    232 		}
    233 		UnloadBlob(&offset1, *len2, b, *blob2);
    234 
    235 		/* Take the sigSize */
    236 		UnloadBlob_UINT32(&offset1, len3, b);
    237 		LogDebugFn("QUOTE2 Core: sigSize=%u", *len3);
    238 		/* sig */
    239 		if ((*blob3 = malloc(*len3)) == NULL) {
    240 			LogError("malloc of %u bytes failed", *len3);
    241 			free(*blob1);
    242 			*blob1 = NULL;
    243 			if (*len2 > 0){
    244 				free(*blob2);
    245 				*blob2 = NULL;
    246 			}
    247 			*len1 = 0;
    248 			*len2 = 0;
    249 			*len3 = 0;
    250 			return TCSERR(TSS_E_OUTOFMEMORY);
    251 		}
    252 		UnloadBlob(&offset1, *len3, b, *blob3);
    253 		break;
    254 	}
    255 #endif
    256 	/* TPM BLOB: TPM_CERTIFY_INFO, UINT32, BLOB, 2 optional AUTHs
    257 	 * return UINT32*, BYTE**, UINT32*, BYTE**, 2 optional AUTHs */
    258 	case TPM_ORD_CertifyKey:
    259 	{
    260 		UINT32 *len1 = va_arg(ap, UINT32 *);
    261 		BYTE **blob1 = va_arg(ap, BYTE **);
    262 		UINT32 *len2 = va_arg(ap, UINT32 *);
    263 		BYTE **blob2 = va_arg(ap, BYTE **);
    264 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    265 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
    266 		va_end(ap);
    267 
    268 		if (!len1 || !blob1 || !len2 || !blob2) {
    269 			LogError("Internal error for ordinal 0x%x", ordinal);
    270 			return TCSERR(TSS_E_INTERNAL_ERROR);
    271 		}
    272 
    273 		if (auth1 && auth2) {
    274 			offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN);
    275 			UnloadBlob_Auth(&offset1, b, auth1);
    276 			UnloadBlob_Auth(&offset1, b, auth2);
    277 		} else if (auth1) {
    278 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    279 			UnloadBlob_Auth(&offset1, b, auth1);
    280 		} else if (auth2) {
    281 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    282 			UnloadBlob_Auth(&offset1, b, auth2);
    283 		}
    284 
    285 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    286 		UnloadBlob_CERTIFY_INFO(&offset2, b, NULL);
    287 		*len1 = offset2 - offset1;
    288 
    289 		if ((*blob1 = malloc(*len1)) == NULL) {
    290 			LogError("malloc of %u bytes failed", *len1);
    291 			return TCSERR(TSS_E_OUTOFMEMORY);
    292 		}
    293 		UnloadBlob(&offset1, *len1, b, *blob1);
    294                 UnloadBlob_UINT32(&offset1, len2, b);
    295 
    296 		if ((*blob2 = malloc(*len2)) == NULL) {
    297 			LogError("malloc of %u bytes failed", *len2);
    298 			free(*blob1);
    299 			*blob1 = NULL;
    300 			*len1 = 0;
    301 			*len2 = 0;
    302 			return TCSERR(TSS_E_OUTOFMEMORY);
    303 		}
    304 		UnloadBlob(&offset1, *len2, b, *blob2);
    305 
    306 		break;
    307 	}
    308 #ifdef TSS_BUILD_AUDIT
    309 	/* TPM_BLOB: TPM_COUNTER_VALUE, DIGEST, DIGEST, UINT32, BLOB, optional AUTH
    310 	 * return: UINT32*, BYTE**, DIGEST*, DIGEST*, UINT32*, BYTE**, optional AUTH */
    311 	case TPM_ORD_GetAuditDigestSigned:
    312 	{
    313 		UINT32 *len1 = va_arg(ap, UINT32 *);
    314 		BYTE **blob1 = va_arg(ap, BYTE **);
    315 		TPM_DIGEST *digest1 = va_arg(ap, TPM_DIGEST *);
    316 		TPM_DIGEST *digest2 = va_arg(ap, TPM_DIGEST *);
    317 		UINT32 *len2 = va_arg(ap, UINT32 *);
    318 		BYTE **blob2 = va_arg(ap, BYTE **);
    319 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    320 		va_end(ap);
    321 
    322 		if (!digest1 || !digest2 || !len1 || !blob1 || !len2 || !blob2) {
    323 			LogError("Internal error for ordinal 0x%x", ordinal);
    324 			return TCSERR(TSS_E_INTERNAL_ERROR);
    325 		}
    326 
    327 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    328 		UnloadBlob_COUNTER_VALUE(&offset2, b, NULL);
    329 		*len1 = offset2 - offset1;
    330 
    331 		if ((*blob1 = malloc(*len1)) == NULL) {
    332 			LogError("malloc of %u bytes failed", *len1);
    333 			return TCSERR(TSS_E_OUTOFMEMORY);
    334 		}
    335 		UnloadBlob(&offset1, *len1, b, *blob1);
    336 
    337 		UnloadBlob_DIGEST(&offset1, b, digest1);
    338 		UnloadBlob_DIGEST(&offset1, b, digest2);
    339                 UnloadBlob_UINT32(&offset1, len2, b);
    340 
    341 		if ((*blob2 = malloc(*len2)) == NULL) {
    342 			LogError("malloc of %u bytes failed", *len2);
    343 			free(*blob1);
    344 			*blob1 = NULL;
    345 			*len1 = 0;
    346 			*len2 = 0;
    347 			return TCSERR(TSS_E_OUTOFMEMORY);
    348 		}
    349 		UnloadBlob(&offset1, *len2, b, *blob2);
    350 
    351 		if (auth1)
    352 			UnloadBlob_Auth(&offset1, b, auth1);
    353 
    354 		break;
    355 	}
    356 	/* TPM_BLOB: TPM_COUNTER_VALUE, DIGEST, BOOL, UINT32, BLOB
    357 	 * return: DIGEST*, UINT32*, BYTE**, BOOL, UINT32*, BYTE** */
    358 	case TPM_ORD_GetAuditDigest:
    359 	{
    360 		TPM_DIGEST *digest1 = va_arg(ap, TPM_DIGEST *);
    361 		UINT32 *len1 = va_arg(ap, UINT32 *);
    362 		BYTE **blob1 = va_arg(ap, BYTE **);
    363 		TSS_BOOL *bool1 = va_arg(ap, TSS_BOOL *);
    364 		UINT32 *len2 = va_arg(ap, UINT32 *);
    365 		BYTE **blob2 = va_arg(ap, BYTE **);
    366 		va_end(ap);
    367 
    368 		if (!digest1 || !len1 || !blob1 || !len2 || !blob2 || !bool1) {
    369 			LogError("Internal error for ordinal 0x%x", ordinal);
    370 			return TCSERR(TSS_E_INTERNAL_ERROR);
    371 		}
    372 
    373 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    374 		UnloadBlob_COUNTER_VALUE(&offset2, b, NULL);
    375 		*len1 = offset2 - offset1;
    376 
    377 		if ((*blob1 = malloc(*len1)) == NULL) {
    378 			LogError("malloc of %u bytes failed", *len1);
    379 			return TCSERR(TSS_E_OUTOFMEMORY);
    380 		}
    381 		UnloadBlob(&offset1, *len1, b, *blob1);
    382 
    383 		UnloadBlob_DIGEST(&offset1, b, digest1);
    384                 UnloadBlob_BOOL(&offset1, bool1, b);
    385                 UnloadBlob_UINT32(&offset1, len2, b);
    386 
    387 		if ((*blob2 = malloc(*len2)) == NULL) {
    388 			LogError("malloc of %u bytes failed", *len2);
    389 			free(*blob1);
    390 			*blob1 = NULL;
    391 			*len1 = 0;
    392 			*len2 = 0;
    393 			return TCSERR(TSS_E_OUTOFMEMORY);
    394 		}
    395 		UnloadBlob(&offset1, *len2, b, *blob2);
    396 
    397 		break;
    398 	}
    399 #endif
    400 #ifdef TSS_BUILD_COUNTER
    401 	/* optional UINT32, TPM_COUNTER_VALUE, optional AUTH */
    402 	case TPM_ORD_ReadCounter:
    403 	case TPM_ORD_CreateCounter:
    404 	case TPM_ORD_IncrementCounter:
    405 	{
    406 		UINT32 *val1 = va_arg(ap, UINT32 *);
    407 		TPM_COUNTER_VALUE *ctr = va_arg(ap, TPM_COUNTER_VALUE *);
    408 		TPM_AUTH * auth1 = va_arg(ap, TPM_AUTH *);
    409 		va_end(ap);
    410 
    411 		if (!ctr) {
    412 			LogError("Internal error for ordinal 0x%x", ordinal);
    413 			return TCSERR(TSS_E_INTERNAL_ERROR);
    414 		}
    415 
    416 		if (auth1) {
    417 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    418 			UnloadBlob_Auth(&offset1, b, auth1);
    419 		}
    420 
    421 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    422 		if (val1)
    423 			UnloadBlob_UINT32(&offset1, val1, b);
    424 		UnloadBlob_COUNTER_VALUE(&offset1, b, ctr);
    425 
    426 		break;
    427 	}
    428 #endif
    429 	/* TPM BLOB: UINT32, BLOB, UINT32, BLOB, optional AUTH, optional AUTH */
    430 	case TPM_ORD_CreateMaintenanceArchive:
    431 	case TPM_ORD_CreateMigrationBlob:
    432 	case TPM_ORD_Delegate_ReadTable:
    433 	case TPM_ORD_CMK_CreateBlob:
    434 	{
    435 		UINT32 *len1 = va_arg(ap, UINT32 *);
    436 		BYTE **blob1 = va_arg(ap, BYTE **);
    437 		UINT32 *len2 = va_arg(ap, UINT32 *);
    438 		BYTE **blob2 = va_arg(ap, BYTE **);
    439 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    440 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
    441 		va_end(ap);
    442 
    443 		if (!len1 || !blob1 || !len2 || !blob2) {
    444 			LogError("Internal error for ordinal 0x%x", ordinal);
    445 			return TCSERR(TSS_E_INTERNAL_ERROR);
    446 		}
    447 
    448 		if (auth1 && auth2) {
    449 			offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN);
    450 			UnloadBlob_Auth(&offset1, b, auth1);
    451 			UnloadBlob_Auth(&offset1, b, auth2);
    452 		} else if (auth1) {
    453 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    454 			UnloadBlob_Auth(&offset1, b, auth1);
    455 		} else if (auth2) {
    456 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    457 			UnloadBlob_Auth(&offset1, b, auth2);
    458 		}
    459 
    460 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    461 		UnloadBlob_UINT32(&offset1, len1, b);
    462 		if ((*blob1 = malloc(*len1)) == NULL) {
    463 			LogError("malloc of %u bytes failed", *len1);
    464 			return TCSERR(TSS_E_OUTOFMEMORY);
    465 		}
    466 
    467 		UnloadBlob(&offset1, *len1, b, *blob1);
    468 
    469 		UnloadBlob_UINT32(&offset1, len2, b);
    470 		if ((*blob2 = malloc(*len2)) == NULL) {
    471 			free(*blob1);
    472 			LogError("malloc of %u bytes failed", *len2);
    473 			return TCSERR(TSS_E_OUTOFMEMORY);
    474 		}
    475 
    476 		UnloadBlob(&offset1, *len2, b, *blob2);
    477 
    478 		break;
    479 	}
    480 	/* TPM BLOB: BLOB, optional AUTH, AUTH
    481 	 * return:   UINT32 *, BYTE **, optional AUTH, AUTH */
    482 	case TPM_ORD_ActivateIdentity:
    483 	{
    484 		UINT32 *len1 = va_arg(ap, UINT32 *);
    485 		BYTE **blob1 = va_arg(ap, BYTE **);
    486 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    487 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
    488 		va_end(ap);
    489 
    490 		if (!len1 || !blob1 || !auth2) {
    491 			LogError("Internal error for ordinal 0x%x", ordinal);
    492 			return TCSERR(TSS_E_INTERNAL_ERROR);
    493 		}
    494 
    495 		if (auth1 && auth2) {
    496 			offset1 = offset2 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN);
    497 			UnloadBlob_Auth(&offset1, b, auth1);
    498 			UnloadBlob_Auth(&offset1, b, auth2);
    499 		} else if (auth2) {
    500 			offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    501 			UnloadBlob_Auth(&offset1, b, auth2);
    502 		}
    503 
    504 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    505 		offset2 -= TSS_TPM_TXBLOB_HDR_LEN;
    506 		if ((*blob1 = malloc(offset2)) == NULL) {
    507 			LogError("malloc of %zd bytes failed", (size_t)offset2);
    508 			return TCSERR(TSS_E_OUTOFMEMORY);
    509 		}
    510 		*len1 = offset2;
    511 		UnloadBlob(&offset1, *len1, b, *blob1);
    512 
    513 		break;
    514 	}
    515 	/* TPM BLOB: TPM_KEY, UINT32, BLOB, optional AUTH, AUTH
    516 	 * return:   UINT32 *, BYTE **, UINT32 *, BYTE **, optional AUTH, AUTH */
    517 	case TPM_ORD_MakeIdentity:
    518 	{
    519 		UINT32 *len1, *len2;
    520 		BYTE **blob1, **blob2;
    521 		TPM_AUTH *auth1, *auth2;
    522 
    523 		len1 = va_arg(ap, UINT32 *);
    524 		blob1 = va_arg(ap, BYTE **);
    525 		len2 = va_arg(ap, UINT32 *);
    526 		blob2 = va_arg(ap, BYTE **);
    527 		auth1 = va_arg(ap, TPM_AUTH *);
    528 		auth2 = va_arg(ap, TPM_AUTH *);
    529 		va_end(ap);
    530 
    531 		if (!len1 || !blob1 || !len2 || !blob2 || !auth2) {
    532 			LogError("Internal error for ordinal 0x%x", ordinal);
    533 			return TCSERR(TSS_E_INTERNAL_ERROR);
    534 		}
    535 
    536 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
    537 		UnloadBlob_TSS_KEY(&offset1, b, NULL);
    538 		offset1 -= TSS_TPM_TXBLOB_HDR_LEN;
    539 
    540 		if ((*blob1 = malloc(offset1)) == NULL) {
    541 			LogError("malloc of %zd bytes failed", (size_t)offset1);
    542 			return TCSERR(TSS_E_OUTOFMEMORY);
    543 		}
    544 		*len1 = offset1;
    545 
    546 		UnloadBlob(&offset2, offset1, b, *blob1);
    547 
    548 		/* offset2 points to the stuff after the key */
    549 		UnloadBlob_UINT32(&offset2, len2, b);
    550 
    551 		if ((*blob2 = malloc(*len2)) == NULL) {
    552 			free(*blob1);
    553 			LogError("malloc of %u bytes failed", *len2);
    554 			return TCSERR(TSS_E_OUTOFMEMORY);
    555 		}
    556 
    557 		UnloadBlob(&offset2, *len2, b, *blob2);
    558 
    559 		if (auth1)
    560 			UnloadBlob_Auth(&offset2, b, auth1);
    561 		UnloadBlob_Auth(&offset2, b, auth2);
    562 
    563 		break;
    564 	}
    565 	/* 1 TPM_VERSION, 2 UINT32s, 1 optional AUTH */
    566 	case TPM_ORD_GetCapabilityOwner:
    567 	{
    568 		TPM_VERSION *ver1 = va_arg(ap, TPM_VERSION *);
    569 		UINT32 *data1 = va_arg(ap, UINT32 *);
    570 		UINT32 *data2 = va_arg(ap, UINT32 *);
    571 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
    572 		va_end(ap);
    573 
    574 		if (!data1 || !data2 || !ver1) {
    575 			LogError("Internal error for ordinal 0x%x", ordinal);
    576 			return TCSERR(TSS_E_INTERNAL_ERROR);
    577 		}
    578 
    579 		if (auth) {
    580 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    581 			UnloadBlob_Auth(&offset1, b, auth);
    582 		}
    583 
    584 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    585 		UnloadBlob_VERSION(&offset1, b, ver1);
    586 		UnloadBlob_UINT32(&offset1, data1, b);
    587 		UnloadBlob_UINT32(&offset1, data2, b);
    588 		break;
    589 	}
    590 	/* TPM BLOB: 1 UINT32, 1 BLOB, 2 optional AUTHs
    591 	 * return: UINT32 *, BYTE**, 2 optional AUTHs */
    592 	case TPM_ORD_Sign:
    593 	case TPM_ORD_GetTestResult:
    594 	case TPM_ORD_CertifySelfTest:
    595 	case TPM_ORD_Unseal:
    596 	case TPM_ORD_GetRandom:
    597 	case TPM_ORD_DAA_Join:
    598 	case TPM_ORD_DAA_Sign:
    599 	case TPM_ORD_ChangeAuth:
    600 	case TPM_ORD_GetCapability:
    601 	case TPM_ORD_LoadMaintenanceArchive:
    602 	case TPM_ORD_ConvertMigrationBlob:
    603 	case TPM_ORD_NV_ReadValue:
    604 	case TPM_ORD_NV_ReadValueAuth:
    605 	case TPM_ORD_Delegate_Manage:
    606 	case TPM_ORD_Delegate_CreateKeyDelegation:
    607 	case TPM_ORD_Delegate_CreateOwnerDelegation:
    608 	case TPM_ORD_Delegate_UpdateVerification:
    609 	case TPM_ORD_CMK_ConvertMigration:
    610 	{
    611 		UINT32 *data_len = va_arg(ap, UINT32 *);
    612 		BYTE **data = va_arg(ap, BYTE **);
    613 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    614 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
    615 		va_end(ap);
    616 
    617 		if (!data || !data_len) {
    618 			LogError("Internal error for ordinal 0x%x", ordinal);
    619 			return TCSERR(TSS_E_INTERNAL_ERROR);
    620 		}
    621 
    622 		if (auth1 && auth2) {
    623 			offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN);
    624 			UnloadBlob_Auth(&offset1, b, auth1);
    625 			UnloadBlob_Auth(&offset1, b, auth2);
    626 		} else if (auth1) {
    627 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    628 			UnloadBlob_Auth(&offset1, b, auth1);
    629 		} else if (auth2) {
    630 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    631 			UnloadBlob_Auth(&offset1, b, auth2);
    632 		}
    633 
    634 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    635 		UnloadBlob_UINT32(&offset1, data_len, b);
    636 		if ((*data = malloc(*data_len)) == NULL) {
    637 			LogError("malloc of %u bytes failed", *data_len);
    638 			return TCSERR(TSS_E_OUTOFMEMORY);
    639 		}
    640 
    641 		UnloadBlob(&offset1, *data_len, b, *data);
    642 		break;
    643 	}
    644 	/* TPM BLOB: 1 UINT32, 1 BLOB, 1 optional AUTH
    645 	* return: UINT32 *, BYTE**, 1 optional AUTH*/
    646 	case TPM_ORD_UnBind:
    647 	{
    648 		UINT32 *data_len = va_arg(ap, UINT32 *);
    649 		BYTE **data = va_arg(ap, BYTE **);
    650 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    651 		va_end(ap);
    652 
    653 		if (!data || !data_len) {
    654 			LogError("Internal error for ordinal 0x%x", ordinal);
    655 			return TCSERR(TSS_E_INTERNAL_ERROR);
    656 		}
    657 
    658 		if (auth1) {
    659 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    660 			UnloadBlob_Auth(&offset1, b, auth1);
    661 		}
    662 
    663 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    664 		UnloadBlob_UINT32(&offset1, data_len, b);
    665 		if ((*data = malloc(*data_len)) == NULL) {
    666 			LogError("malloc of %u bytes failed", *data_len);
    667 			return TCSERR(TSS_E_OUTOFMEMORY);
    668 		}
    669 
    670 		UnloadBlob(&offset1, *data_len, b, *data);
    671 		break;
    672 	}
    673 	/* TPM BLOB: 1 BLOB, 1 optional AUTH
    674 	 * return: UINT32 *, BYTE**, 1 optional AUTH*/
    675 	case TPM_ORD_GetTicks:
    676 	case TPM_ORD_Seal:
    677 	case TPM_ORD_Sealx:
    678 	case TPM_ORD_FieldUpgrade:
    679 	case TPM_ORD_CreateWrapKey:
    680 	case TPM_ORD_GetPubKey:
    681 	case TPM_ORD_OwnerReadPubek:
    682 	case TPM_ORD_OwnerReadInternalPub:
    683 	case TPM_ORD_AuthorizeMigrationKey:
    684 	case TPM_ORD_TakeOwnership:
    685 	case TPM_ORD_CMK_CreateKey:
    686 	{
    687 		UINT32 *data_len = va_arg(ap, UINT32 *);
    688 		BYTE **data = va_arg(ap, BYTE **);
    689 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
    690 		va_end(ap);
    691 
    692 		if (!data || !data_len) {
    693 			LogError("Internal error for ordinal 0x%x", ordinal);
    694 			return TCSERR(TSS_E_INTERNAL_ERROR);
    695 		}
    696 
    697 		/* remove the auth data from the back end of the data */
    698 		if (auth) {
    699 			offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    700 			UnloadBlob_Auth(&offset1, b, auth);
    701 		} else
    702 			offset2 = len;
    703 
    704 		/* everything after the header is returned as the blob */
    705 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    706 		offset2 -= offset1;
    707 		if ((*data = malloc((size_t)offset2)) == NULL) {
    708 			LogError("malloc of %zd bytes failed", (size_t)offset2);
    709 			return TCSERR(TSS_E_OUTOFMEMORY);
    710 		}
    711 
    712 		if ((offset1 + offset2) > TSS_TPM_TXBLOB_SIZE)
    713 			return TCSERR(TSS_E_INTERNAL_ERROR);
    714 
    715 		memcpy(*data, &b[offset1], offset2);
    716 		*data_len = offset2;
    717 		break;
    718 	}
    719 	/* TPM BLOB: TPM_PUBKEY, optional DIGEST */
    720 	case TPM_ORD_CreateEndorsementKeyPair:
    721 	case TPM_ORD_ReadPubek:
    722 	{
    723 		UINT32 *data_len = va_arg(ap, UINT32 *);
    724 		BYTE **data = va_arg(ap, BYTE **);
    725 		BYTE *digest1 = va_arg(ap, BYTE *);
    726 		va_end(ap);
    727 
    728 		if (!data || !data_len) {
    729 			LogError("Internal error for ordinal 0x%x", ordinal);
    730 			return TCSERR(TSS_E_INTERNAL_ERROR);
    731 		}
    732 
    733 		if (digest1) {
    734 			offset1 = offset2 = len - TPM_DIGEST_SIZE;
    735 			memcpy(digest1, &b[offset2], TPM_DIGEST_SIZE);
    736 
    737 			if ((offset2 + TPM_DIGEST_SIZE) > TSS_TPM_TXBLOB_SIZE)
    738 				return TCSERR(TSS_E_INTERNAL_ERROR);
    739 		} else {
    740 			offset2 = len;
    741 
    742 			if (offset2 > TSS_TPM_TXBLOB_SIZE)
    743 				return TCSERR(TSS_E_INTERNAL_ERROR);
    744 		}
    745 
    746 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    747 		offset2 -= offset1;
    748 		if ((*data = malloc((size_t)offset2)) == NULL) {
    749 			LogError("malloc of %zd bytes failed", (size_t)offset2);
    750 			return TCSERR(TSS_E_OUTOFMEMORY);
    751 		}
    752 
    753 		UnloadBlob(&offset1, offset2, b, *data);
    754 		*data_len = offset2;
    755 		break;
    756 	}
    757 #ifdef TSS_BUILD_TSS12
    758 	/* TPM BLOB: BLOB, DIGEST, DIGEST
    759 	 * return: UINT32 *, BYTE**, DIGEST, DIGEST */
    760 	case TPM_ORD_CreateRevocableEK:
    761 	{
    762 		UINT32 *data_len = va_arg(ap, UINT32 *);
    763 		BYTE **data = va_arg(ap, BYTE **);
    764 		BYTE *digest1 = va_arg(ap, BYTE *);
    765 		BYTE *digest2 = va_arg(ap, BYTE *);
    766 		va_end(ap);
    767 
    768 		if (!data || !data_len || !digest1 || !digest2) {
    769 			LogError("Internal error for ordinal 0x%x", ordinal);
    770 			return TCSERR(TSS_E_INTERNAL_ERROR);
    771 		}
    772 
    773 		if (len > TSS_TPM_TXBLOB_SIZE)
    774 			return TCSERR(TSS_E_INTERNAL_ERROR);
    775 
    776 		offset2 = len - TPM_DIGEST_SIZE;
    777 		memcpy(digest2, &b[offset2], TPM_DIGEST_SIZE);
    778 
    779 		offset2 -= TPM_DIGEST_SIZE;
    780 		memcpy(digest1, &b[offset2], TPM_DIGEST_SIZE);
    781 
    782 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    783 		offset2 -= offset1;
    784 		if ((*data = malloc((size_t)offset2)) == NULL) {
    785 			LogError("malloc of %zd bytes failed", (size_t)offset2);
    786 			return TCSERR(TSS_E_OUTOFMEMORY);
    787 		}
    788 
    789 		UnloadBlob(&offset1, offset2, b, *data);
    790 		*data_len = offset2;
    791 		break;
    792 	}
    793 #endif
    794 	/* 1 UINT32, 1 optional AUTH */
    795 	case TPM_ORD_LoadKey:
    796 	case TPM_ORD_LoadKey2:
    797 	{
    798 		UINT32 *handle;
    799 		TPM_AUTH *auth;
    800 
    801 		handle = va_arg(ap, UINT32 *);
    802 		auth = va_arg(ap, TPM_AUTH *);
    803 		va_end(ap);
    804 
    805 		if (!handle) {
    806 			LogError("Internal error for ordinal 0x%x", ordinal);
    807 			return TCSERR(TSS_E_INTERNAL_ERROR);
    808 		}
    809 
    810 		if (auth) {
    811 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    812 			UnloadBlob_Auth(&offset1, b, auth);
    813 		}
    814 
    815 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    816 		UnloadBlob_UINT32(&offset1, handle, b);
    817 		break;
    818 	}
    819 	/* 1 optional UINT32, 1 20 byte value */
    820 	case TPM_ORD_DirRead:
    821 	case TPM_ORD_OIAP:
    822 	case TPM_ORD_LoadManuMaintPub:
    823 	case TPM_ORD_ReadManuMaintPub:
    824 	case TPM_ORD_Extend:
    825 	case TPM_ORD_PcrRead:
    826 	{
    827 		UINT32 *handle = va_arg(ap, UINT32 *);
    828 		BYTE *nonce = va_arg(ap, BYTE *);
    829 		va_end(ap);
    830 
    831 		if (!nonce) {
    832 			LogError("Internal error for ordinal 0x%x", ordinal);
    833 			return TCSERR(TSS_E_INTERNAL_ERROR);
    834 		}
    835 
    836 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    837 		if (handle)
    838 			UnloadBlob_UINT32(&offset1, handle, b);
    839 		UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce);
    840 		break;
    841 	}
    842 	/* 1 UINT32, 2 20 byte values */
    843 	case TPM_ORD_OSAP:
    844 	case TPM_ORD_DSAP:
    845 	{
    846 		UINT32 *handle = va_arg(ap, UINT32 *);
    847 		BYTE *nonce1 = va_arg(ap, BYTE *);
    848 		BYTE *nonce2 = va_arg(ap, BYTE *);
    849 		va_end(ap);
    850 
    851 		if (!handle || !nonce1 || !nonce2) {
    852 			LogError("Internal error for ordinal 0x%x", ordinal);
    853 			return TCSERR(TSS_E_INTERNAL_ERROR);
    854 		}
    855 
    856 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    857 		UnloadBlob_UINT32(&offset1, handle, b);
    858 		UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce1);
    859 		UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce2);
    860 		break;
    861 	}
    862 #ifdef TSS_BUILD_CMK
    863 	/* 1 20 byte value, 1 optional AUTH */
    864 	case TPM_ORD_CMK_ApproveMA:
    865 	case TPM_ORD_CMK_CreateTicket:
    866 	{
    867 		BYTE *hmac1 = va_arg(ap, BYTE *);
    868 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
    869 		va_end(ap);
    870 
    871 		if (!hmac1) {
    872 			LogError("Internal error for ordinal 0x%x", ordinal);
    873 			return TCSERR(TSS_E_INTERNAL_ERROR);
    874 		}
    875 
    876 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
    877 		UnloadBlob(&offset1, TPM_SHA1_160_HASH_LEN, b, hmac1);
    878 		if (auth) {
    879 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    880 			UnloadBlob_Auth(&offset1, b, auth);
    881 		}
    882 		break;
    883 	}
    884 #endif
    885 	/* 1 optional AUTH */
    886 	case TPM_ORD_DisablePubekRead:
    887 	case TPM_ORD_DirWriteAuth:
    888 	case TPM_ORD_ReleaseCounter:
    889 	case TPM_ORD_ReleaseCounterOwner:
    890 	case TPM_ORD_ChangeAuthOwner:
    891 	case TPM_ORD_SetCapability:
    892 	case TPM_ORD_SetOrdinalAuditStatus:
    893 	case TPM_ORD_ResetLockValue:
    894 	case TPM_ORD_SetRedirection:
    895 	case TPM_ORD_DisableOwnerClear:
    896 	case TPM_ORD_OwnerSetDisable:
    897 	case TPM_ORD_SetTempDeactivated:
    898 	case TPM_ORD_KillMaintenanceFeature:
    899 	case TPM_ORD_NV_DefineSpace:
    900 	case TPM_ORD_NV_WriteValue:
    901 	case TPM_ORD_NV_WriteValueAuth:
    902 	case TPM_ORD_OwnerClear:
    903 	case TPM_ORD_Delegate_LoadOwnerDelegation:
    904 	case TPM_ORD_CMK_SetRestrictions:
    905 	case TPM_ORD_FlushSpecific:
    906 	case TPM_ORD_KeyControlOwner:
    907 	{
    908 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
    909 		va_end(ap);
    910 
    911 		if (auth) {
    912 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
    913 			UnloadBlob_Auth(&offset1, b, auth);
    914 		}
    915 		break;
    916 	}
    917 	default:
    918 		LogError("Unknown ordinal: 0x%x", ordinal);
    919 		result = TCSERR(TSS_E_INTERNAL_ERROR);
    920 		va_end(ap);
    921 		break;
    922 	}
    923 
    924 	return result;
    925 }
    926 
    927 /* XXX optimize these cases by always passing in lengths for blobs, no more "20 byte values" */
    928 TSS_RESULT
    929 tpm_rqu_build(TPM_COMMAND_CODE ordinal, UINT64 *outOffset, BYTE *out_blob, ...)
    930 {
    931 	TSS_RESULT result = TSS_SUCCESS;
    932 	UINT64 blob_size;
    933 	va_list ap;
    934 
    935 	DBG_ASSERT(ordinal);
    936 	DBG_ASSERT(outOffset);
    937 	DBG_ASSERT(out_blob);
    938 
    939 	va_start(ap, out_blob);
    940 
    941 	switch (ordinal) {
    942 #ifdef TSS_BUILD_DELEGATION
    943 	/* 1 UINT16, 1 UINT32, 1 20 bytes value, 1 UINT32, 1 BLOB */
    944 	case TPM_ORD_DSAP:
    945 	{
    946 		UINT16 val1 = va_arg(ap, int);
    947 		UINT32 handle1 = va_arg(ap, UINT32);
    948 		BYTE *digest1 = va_arg(ap, BYTE *);
    949 		UINT32 in_len1 = va_arg(ap, UINT32);
    950 		BYTE *in_blob1 = va_arg(ap, BYTE *);
    951 		va_end(ap);
    952 
    953 		if (!digest1 || !in_blob1) {
    954 			result = TCSERR(TSS_E_INTERNAL_ERROR);
    955 			LogError("Internal error for ordinal 0x%x", ordinal);
    956 			break;
    957 		}
    958 
    959 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
    960 		LoadBlob_UINT16(outOffset, val1, out_blob);
    961 		LoadBlob_UINT32(outOffset, handle1, out_blob);
    962 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
    963 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
    964 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
    965 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
    966 
    967 		break;
    968 	}
    969 	/* 1 BOOL, 1 UINT32, 1 BLOB, 1 20 byte value, 1 AUTH */
    970 	case TPM_ORD_Delegate_CreateOwnerDelegation:
    971 	{
    972 		TSS_BOOL bool1 = va_arg(ap, int);
    973 		UINT32 in_len1 = va_arg(ap, UINT32);
    974 		BYTE *in_blob1 = va_arg(ap, BYTE *);
    975 		BYTE *digest1 = va_arg(ap, BYTE *);
    976 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
    977 		va_end(ap);
    978 
    979 		if (!in_len1 || !in_blob1 || !digest1) {
    980 			result = TCSERR(TSS_E_INTERNAL_ERROR);
    981 			LogError("Internal error for ordinal 0x%x", ordinal);
    982 			break;
    983 		}
    984 
    985 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
    986 		LoadBlob_BOOL(outOffset, bool1, out_blob);
    987 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
    988 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
    989 		if (auth1) {
    990 			LoadBlob_Auth(outOffset, out_blob, auth1);
    991 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
    992 		} else
    993 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
    994 
    995 		break;
    996 	}
    997 	/* 2 UINT32's, 1 BLOB, 1 20 byte value, 1 AUTH */
    998 	case TPM_ORD_Delegate_CreateKeyDelegation:
    999 	{
   1000 		UINT32 keyslot1 = va_arg(ap, UINT32);
   1001 		UINT32 in_len1 = va_arg(ap, UINT32);
   1002 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1003 		BYTE *digest1 = va_arg(ap, BYTE *);
   1004 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1005 		va_end(ap);
   1006 
   1007 		if (!keyslot1 || !in_len1 || !in_blob1 || !digest1) {
   1008 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1009 			LogError("Internal error for ordinal 0x%x", ordinal);
   1010 			break;
   1011 		}
   1012 
   1013 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1014 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
   1015 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1016 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1017 		if (auth1) {
   1018 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1019 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1020 		} else
   1021 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1022 
   1023 		break;
   1024 	}
   1025 #endif
   1026 #ifdef TSS_BUILD_TRANSPORT
   1027 	/* 3 UINT32's, 1 BLOB, 2 AUTHs */
   1028 	case TPM_ORD_ExecuteTransport:
   1029 	{
   1030 		UINT32 ord1 = va_arg(ap, UINT32);
   1031 		UINT32 *keyslot1 = va_arg(ap, UINT32 *);
   1032 		UINT32 *keyslot2 = va_arg(ap, UINT32 *);
   1033 		UINT32 in_len1 = va_arg(ap, UINT32);
   1034 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1035 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1036 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
   1037 		va_end(ap);
   1038 
   1039 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1040 		if (keyslot1)
   1041 			LoadBlob_UINT32(outOffset, *keyslot1, out_blob);
   1042 		if (keyslot2)
   1043 			LoadBlob_UINT32(outOffset, *keyslot2, out_blob);
   1044 		//LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1045 		if (in_blob1)
   1046 			LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1047 
   1048 		if (auth1 && auth2) {
   1049 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1050 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1051 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ord1, out_blob);
   1052 		} else if (auth1) {
   1053 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1054 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ord1, out_blob);
   1055 		} else if (auth2) {
   1056 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1057 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ord1, out_blob);
   1058 		} else {
   1059 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ord1, out_blob);
   1060 		}
   1061 
   1062 		break;
   1063 	}
   1064 #endif
   1065 	/* 1 UINT32, 1 UINT16, 1 BLOB, 1 UINT32, 1 BLOB, 1 options AUTH, 1 AUTH */
   1066 	case TPM_ORD_CreateMigrationBlob:
   1067 	{
   1068 		UINT32 keyslot1 = va_arg(ap, UINT32);
   1069 		UINT16 type1 = va_arg(ap, int);
   1070 		UINT32 in_len1 = va_arg(ap, UINT32);
   1071 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1072 		UINT32 in_len2 = va_arg(ap, UINT32);
   1073 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   1074 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1075 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
   1076 		va_end(ap);
   1077 
   1078 		if (!in_blob1 || !in_blob2 || !auth2) {
   1079 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1080 			LogError("Internal error for ordinal 0x%x", ordinal);
   1081 			break;
   1082 		}
   1083 
   1084 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1085 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
   1086 		LoadBlob_UINT16(outOffset, type1, out_blob);
   1087 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1088 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   1089 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   1090 		if (auth1) {
   1091 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1092 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1093 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
   1094 		} else {
   1095 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1096 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1097 		}
   1098 
   1099 		break;
   1100 	}
   1101 	/* 1 UINT32, 1 UINT16, 1 20 byte value, 1 UINT16, 1 UINT32, 1 BLOB, 2 AUTHs */
   1102 	case TPM_ORD_ChangeAuth:
   1103 	{
   1104 		UINT32 keyslot1 = va_arg(ap, UINT32);
   1105 		UINT16 proto1 = va_arg(ap, int);
   1106 		BYTE *digest1 = va_arg(ap, BYTE *);
   1107 		UINT16 entity1 = va_arg(ap, int);
   1108 		UINT32 in_len1 = va_arg(ap, UINT32);
   1109 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1110 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1111 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
   1112 		va_end(ap);
   1113 
   1114 		if (!digest1 || !in_blob1 || !auth1 || !auth2) {
   1115 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1116 			LogError("Internal error for ordinal 0x%x", ordinal);
   1117 			break;
   1118 		}
   1119 
   1120 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1121 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
   1122 		LoadBlob_UINT16(outOffset, proto1, out_blob);
   1123 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1124 		LoadBlob_UINT16(outOffset, entity1, out_blob);
   1125 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1126 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1127 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1128 		LoadBlob_Auth(outOffset, out_blob, auth2);
   1129 		LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
   1130 
   1131 		break;
   1132 	}
   1133 	/* 2 DIGEST/ENCAUTH's, 1 UINT32, 1 BLOB, 1 optional AUTH, 1 AUTH */
   1134 	case TPM_ORD_MakeIdentity:
   1135 	{
   1136 		BYTE *dig1, *dig2, *blob1;
   1137 		UINT32 len1;
   1138 		TPM_AUTH *auth1, *auth2;
   1139 
   1140 		dig1 = va_arg(ap, BYTE *);
   1141 		dig2 = va_arg(ap, BYTE *);
   1142 		len1 = va_arg(ap, UINT32);
   1143 		blob1 = va_arg(ap, BYTE *);
   1144 		auth1 = va_arg(ap, TPM_AUTH *);
   1145 		auth2 = va_arg(ap, TPM_AUTH *);
   1146 		va_end(ap);
   1147 
   1148 		if (!dig1 || !dig2 || !blob1 || !auth2) {
   1149 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1150 			LogError("Internal error for ordinal 0x%x", ordinal);
   1151 			break;
   1152 		}
   1153 
   1154 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1155 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, dig1);
   1156 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, dig2);
   1157 		LoadBlob(outOffset, len1, out_blob, blob1);
   1158 		if (auth1) {
   1159 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1160 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1161 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
   1162 		} else {
   1163 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1164 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1165 		}
   1166 
   1167 		break;
   1168 	}
   1169 #if (TSS_BUILD_NV || TSS_BUILD_DELEGATION)
   1170 	/* 3 UINT32's, 1 BLOB, 1 optional AUTH */
   1171 	case TPM_ORD_NV_WriteValue:
   1172 	case TPM_ORD_NV_WriteValueAuth:
   1173 	case TPM_ORD_Delegate_Manage:
   1174 	{
   1175 		UINT32 i = va_arg(ap, UINT32);
   1176 		UINT32 j = va_arg(ap, UINT32);
   1177 		UINT32 in_len1 = va_arg(ap, UINT32);
   1178 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1179 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1180 		va_end(ap);
   1181 
   1182 		if (!in_blob1) {
   1183 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1184 			LogError("Internal error for ordinal 0x%x", ordinal);
   1185 			break;
   1186 		}
   1187 
   1188 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1189 		LoadBlob_UINT32(outOffset, i, out_blob);
   1190 		LoadBlob_UINT32(outOffset, j, out_blob);
   1191 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1192 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1193 		if (auth1) {
   1194 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1195 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1196 		} else {
   1197 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1198 		}
   1199 
   1200 		break;
   1201 	}
   1202 #endif
   1203 	/* 3 UINT32's, 1 optional AUTH */
   1204 	case TPM_ORD_NV_ReadValue:
   1205 	case TPM_ORD_NV_ReadValueAuth:
   1206 	case TPM_ORD_SetRedirection:
   1207 	{
   1208 		UINT32 i = va_arg(ap, UINT32);
   1209 		UINT32 j = va_arg(ap, UINT32);
   1210 		UINT32 k = va_arg(ap, UINT32);
   1211 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1212 		va_end(ap);
   1213 
   1214 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1215 		LoadBlob_UINT32(outOffset, i, out_blob);
   1216 		LoadBlob_UINT32(outOffset, j, out_blob);
   1217 		LoadBlob_UINT32(outOffset, k, out_blob);
   1218 		if (auth1) {
   1219 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1220 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1221 		} else {
   1222 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1223 		}
   1224 
   1225 		break;
   1226 	}
   1227 	/* 1 20 byte value, 1 UINT32, 1 BLOB */
   1228 	case TPM_ORD_CreateEndorsementKeyPair:
   1229 	{
   1230 		BYTE *digest1 = va_arg(ap, BYTE *);
   1231 		UINT32 in_len1 = va_arg(ap, UINT32);
   1232 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1233 		va_end(ap);
   1234 
   1235 		if (!digest1 || !in_blob1) {
   1236 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1237 			LogError("Internal error for ordinal 0x%x", ordinal);
   1238 			break;
   1239 		}
   1240 
   1241 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1242 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1243 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1244 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1245 
   1246 		break;
   1247 	}
   1248 #ifdef TSS_BUILD_TSS12
   1249 	/* 1 20 byte value, 1 UINT32, 1 BLOB, 1 BOOL, 1 20 byte value */
   1250 	case TPM_ORD_CreateRevocableEK:
   1251 	{
   1252 		BYTE *digest1 = va_arg(ap, BYTE *);
   1253 		UINT32 in_len1 = va_arg(ap, UINT32);
   1254 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1255 		TSS_BOOL in_bool1 = va_arg(ap, int);
   1256 		BYTE *digest2 = va_arg(ap, BYTE *);
   1257 		va_end(ap);
   1258 
   1259 		if (!digest1 || !in_blob1 || !digest2) {
   1260 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1261 			LogError("Internal error for ordinal 0x%x", ordinal);
   1262 			break;
   1263 		}
   1264 
   1265 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1266 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1267 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1268 		LoadBlob_BOOL(outOffset, in_bool1, out_blob);
   1269 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
   1270 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1271 
   1272 		break;
   1273 	}
   1274 	/* 1 20 byte value */
   1275 	case TPM_ORD_RevokeTrust:
   1276 	{
   1277 		BYTE *digest1 = va_arg(ap, BYTE *);
   1278 		va_end(ap);
   1279 
   1280 		if (!digest1) {
   1281 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1282 			LogError("Internal error for ordinal 0x%x", ordinal);
   1283 			break;
   1284 		}
   1285 
   1286 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1287 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1288 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1289 
   1290 		break;
   1291 	}
   1292 #endif
   1293 #ifdef TSS_BUILD_COUNTER
   1294 	/* 1 20 byte value, 1 UINT32, 1 BLOB, 1 AUTH */
   1295 	case TPM_ORD_CreateCounter:
   1296 	{
   1297 		BYTE *digest1 = va_arg(ap, BYTE *);
   1298 		UINT32 in_len1 = va_arg(ap, UINT32);
   1299 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1300 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1301 		va_end(ap);
   1302 
   1303 		if (!digest1 || !in_blob1 || !auth1) {
   1304 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1305 			LogError("Internal error for ordinal 0x%x", ordinal);
   1306 			break;
   1307 		}
   1308 
   1309 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1310 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1311 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1312 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1313 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1314 
   1315 		break;
   1316 	}
   1317 #endif
   1318 #ifdef TSS_BUILD_DAA
   1319 	/* 1 UINT32, 1 BYTE, 1 UINT32, 1 BLOB, 1 UINT32, 1 BLOB, 1 AUTH */
   1320 	case TPM_ORD_DAA_Sign:
   1321 	case TPM_ORD_DAA_Join:
   1322 	{
   1323 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1324 		BYTE stage1 = va_arg(ap, int);
   1325 		UINT32 in_len1 = va_arg(ap, UINT32);
   1326 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1327 		UINT32 in_len2 = va_arg(ap, UINT32);
   1328 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   1329 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1330 		va_end(ap);
   1331 
   1332 		if (!keySlot1 || !in_blob1 || !auth1) {
   1333 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1334 			LogError("Internal error for ordinal 0x%x", ordinal);
   1335 			break;
   1336 		}
   1337 
   1338 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1339 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1340 		LoadBlob_BOOL(outOffset, stage1, out_blob);
   1341 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1342 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1343 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   1344 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   1345 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1346 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1347 
   1348 		break;
   1349 	}
   1350 #endif
   1351 	/* 2 UINT32's, 1 BLOB, 1 UINT32, 1 BLOB, 1 optional AUTH */
   1352 	case TPM_ORD_ConvertMigrationBlob:
   1353 	case TPM_ORD_SetCapability:
   1354 	{
   1355 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1356 		UINT32 in_len1 = va_arg(ap, UINT32);
   1357 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1358 		UINT32 in_len2 = va_arg(ap, UINT32);
   1359 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   1360 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1361 		va_end(ap);
   1362 
   1363 		if (!keySlot1 || !in_blob1 || !in_blob2) {
   1364 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1365 			LogError("Internal error for ordinal 0x%x", ordinal);
   1366 			break;
   1367 		}
   1368 
   1369 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1370 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1371 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1372 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1373 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   1374 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   1375 		if (auth1) {
   1376 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1377 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1378 		} else {
   1379 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1380 		}
   1381 
   1382 		break;
   1383 	}
   1384 	/* 2 UINT32's, 1 20 byte value, 2 optional AUTHs */
   1385 	case TPM_ORD_CertifyKey:
   1386 	{
   1387 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1388 		UINT32 keySlot2 = va_arg(ap, UINT32);
   1389 		BYTE *digest1 = va_arg(ap, BYTE *);
   1390 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1391 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
   1392 		va_end(ap);
   1393 
   1394 		if (!keySlot1 || !keySlot2 || !digest1) {
   1395 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1396 			LogError("Internal error for ordinal 0x%x", ordinal);
   1397 			break;
   1398 		}
   1399 
   1400 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1401 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1402 		LoadBlob_UINT32(outOffset, keySlot2, out_blob);
   1403 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1404 		if (auth1 && auth2) {
   1405 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1406 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1407 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
   1408 		} else if (auth1) {
   1409 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1410 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1411 		} else if (auth2) {
   1412 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1413 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1414 		} else {
   1415 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1416 		}
   1417 
   1418 		break;
   1419 	}
   1420 	/* 2 UINT32's, 1 BLOB, 1 optional AUTH */
   1421 	case TPM_ORD_Delegate_LoadOwnerDelegation:
   1422 	case TPM_ORD_GetCapability:
   1423 	case TPM_ORD_UnBind:
   1424 	case TPM_ORD_Sign:
   1425 	{
   1426 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1427 		UINT32 in_len1 = va_arg(ap, UINT32);
   1428 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1429 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1430 		va_end(ap);
   1431 
   1432 		if (in_len1 && !in_blob1) {
   1433 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1434 			LogError("Internal error for ordinal 0x%x", ordinal);
   1435 			break;
   1436 		}
   1437 
   1438 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1439 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1440 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1441 		if (in_len1)
   1442 			LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1443 		if (auth1) {
   1444 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1445 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1446 		} else {
   1447 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1448 		}
   1449 
   1450 		break;
   1451 	}
   1452 	/* 1 UINT32, 1 20 byte value, 1 UINT32, 1 optional BLOB, 1 UINT32, 1 BLOB, 1 AUTH */
   1453 	case TPM_ORD_Seal:
   1454 	case TPM_ORD_Sealx:
   1455 	{
   1456 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1457 		BYTE *digest1 = va_arg(ap, BYTE *);
   1458 		UINT32 in_len1 = va_arg(ap, UINT32);
   1459 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1460 		UINT32 in_len2 = va_arg(ap, UINT32);
   1461 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   1462 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1463 		va_end(ap);
   1464 
   1465 		blob_size = in_len1 + in_len2 + TPM_DIGEST_SIZE + sizeof(TPM_AUTH);
   1466 		if (blob_size > TSS_TPM_TXBLOB_SIZE) {
   1467 			result = TCSERR(TSS_E_BAD_PARAMETER);
   1468 			LogError("Oversized input when building ordinal 0x%x", ordinal);
   1469 			break;
   1470 		}
   1471 
   1472 		if (!keySlot1 || !in_blob2 || !auth1) {
   1473 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1474 			LogError("Internal error for ordinal 0x%x", ordinal);
   1475 			break;
   1476 		}
   1477 
   1478 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1479 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1480 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1481 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1482 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1483 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   1484 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   1485 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1486 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1487 
   1488 		break;
   1489 	}
   1490 	/* 2 UINT32's, 1 BLOB, 1 optional AUTH, 1 AUTH */
   1491 	case TPM_ORD_ActivateIdentity:
   1492 	{
   1493 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1494 		UINT32 in_len1 = va_arg(ap, UINT32);
   1495 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1496 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1497 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
   1498 		va_end(ap);
   1499 
   1500 		if (!keySlot1 || !in_blob1 || !auth2) {
   1501 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1502 			LogError("Internal error for ordinal 0x%x", ordinal);
   1503 			break;
   1504 		}
   1505 
   1506 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1507 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1508 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1509 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1510 		if (auth1) {
   1511 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1512 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1513 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
   1514 		} else {
   1515 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1516 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1517 		}
   1518 
   1519 		break;
   1520 	}
   1521 	/* 1 UINT32, 1 20-byte blob, 1 BLOB, 1 optional AUTH */
   1522 	case TPM_ORD_Quote:
   1523 	{
   1524 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1525 		BYTE *digest1 = va_arg(ap, BYTE *);
   1526 		UINT32 in_len1 = va_arg(ap, UINT32);
   1527 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1528 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1529 		va_end(ap);
   1530 
   1531 		if (!keySlot1 || !digest1 || !in_blob1) {
   1532 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1533 			LogError("Internal error for ordinal 0x%x", ordinal);
   1534 			break;
   1535 		}
   1536 
   1537 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1538 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1539 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1540 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1541 
   1542 		if (auth1) {
   1543 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1544 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1545 		} else
   1546 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1547 
   1548 		break;
   1549 	}
   1550 #ifdef TSS_BUILD_TSS12
   1551 	/* 1 UINT32, 1 20-byte blob, 1 BLOB, 1 BOOL, 1 optional AUTH */
   1552 	case TPM_ORD_Quote2:
   1553 	{
   1554 		/* Input vars */
   1555 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1556 		BYTE *digest1 = va_arg(ap, BYTE *);
   1557 		UINT32 in_len1 = va_arg(ap, UINT32);
   1558 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1559 		TSS_BOOL* addVersion = va_arg(ap,TSS_BOOL *);
   1560 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1561 		va_end(ap);
   1562 
   1563 		if (!keySlot1 || !digest1 || !in_blob1 || !addVersion) {
   1564 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1565 			LogError("Internal error for ordinal 0x%x", ordinal);
   1566 			break;
   1567 		}
   1568 
   1569 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1570 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1571 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1572 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1573 
   1574 		/* Load the addVersion Bool */
   1575 		LoadBlob_BOOL(outOffset,*addVersion,out_blob);
   1576 
   1577 		if (auth1) {
   1578 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1579 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1580 		} else
   1581 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1582 
   1583 		break;
   1584 	}
   1585 #endif
   1586 	/* 1 UINT32, 2 20-byte blobs, 1 BLOB, 1 optional AUTH */
   1587 	case TPM_ORD_CreateWrapKey:
   1588 	{
   1589 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1590 		BYTE *digest1 = va_arg(ap, BYTE *);
   1591 		BYTE *digest2 = va_arg(ap, BYTE *);
   1592 		UINT32 in_len1 = va_arg(ap, UINT32);
   1593 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1594 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1595 		va_end(ap);
   1596 
   1597 		if (!keySlot1 || !digest1 || !digest2 || !in_blob1) {
   1598 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1599 			LogError("Internal error for ordinal 0x%x", ordinal);
   1600 			break;
   1601 		}
   1602 
   1603 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1604 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1605 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1606 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
   1607 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1608 		if (auth1) {
   1609 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1610 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1611 		} else
   1612 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1613 
   1614 		break;
   1615 	}
   1616 	/* 2 BLOBs, 1 optional AUTH */
   1617 	case TPM_ORD_NV_DefineSpace:
   1618 	case TPM_ORD_LoadManuMaintPub:
   1619 	{
   1620 		UINT32 in_len1 = va_arg(ap, UINT32);
   1621 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1622 		UINT32 in_len2 = va_arg(ap, UINT32);
   1623 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   1624 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1625 		va_end(ap);
   1626 
   1627 		if (!in_blob1 || !in_blob2) {
   1628 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1629 			LogError("Internal error for ordinal 0x%x", ordinal);
   1630 			break;
   1631 		}
   1632 
   1633 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1634 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1635 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   1636 		if (auth1) {
   1637 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1638 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1639 		} else {
   1640 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1641 		}
   1642 
   1643 		break;
   1644 	}
   1645 #ifdef TSS_BUILD_TICK
   1646 	/* 1 UINT32, 2 20-byte blobs, 1 optional AUTH */
   1647 	case TPM_ORD_TickStampBlob:
   1648 	{
   1649 		UINT32 keySlot1 = va_arg(ap, UINT32);
   1650 		BYTE *digest1 = va_arg(ap, BYTE *);
   1651 		BYTE *digest2 = va_arg(ap, BYTE *);
   1652 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1653 		va_end(ap);
   1654 
   1655 		if (!keySlot1 || !digest1 || !digest2) {
   1656 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1657 			LogError("Internal error for ordinal 0x%x", ordinal);
   1658 			break;
   1659 		}
   1660 
   1661 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1662 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
   1663 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1664 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
   1665 
   1666 		if (auth1) {
   1667 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1668 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1669 		} else
   1670 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1671 
   1672 		break;
   1673 	}
   1674 #endif
   1675 	/* 1 BLOB */
   1676 	case TPM_ORD_ReadManuMaintPub:
   1677 	case TPM_ORD_ReadPubek:
   1678 	case TPM_ORD_PCR_Reset:
   1679 	case TPM_ORD_SetOperatorAuth:
   1680 	{
   1681 		UINT32 in_len1 = va_arg(ap, UINT32);
   1682 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1683 		va_end(ap);
   1684 
   1685 		if (!in_blob1) {
   1686 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1687 			LogError("Internal error for ordinal 0x%x", ordinal);
   1688 			break;
   1689 		}
   1690 
   1691 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1692 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1693 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1694 
   1695 		break;
   1696 	}
   1697 	/* 1 UINT32, 1 BLOB, 2 optional AUTHs */
   1698 	case TPM_ORD_LoadKey:
   1699 	case TPM_ORD_LoadKey2:
   1700 	case TPM_ORD_DirWriteAuth:
   1701 	case TPM_ORD_CertifySelfTest:
   1702 	case TPM_ORD_Unseal:
   1703 	case TPM_ORD_Extend:
   1704 	case TPM_ORD_StirRandom:
   1705 	case TPM_ORD_LoadMaintenanceArchive: /* XXX */
   1706 	case TPM_ORD_FieldUpgrade:
   1707 	case TPM_ORD_Delegate_UpdateVerification:
   1708 	case TPM_ORD_Delegate_VerifyDelegation:
   1709 	{
   1710 		UINT32 val1 = va_arg(ap, UINT32);
   1711 		UINT32 in_len1 = va_arg(ap, UINT32);
   1712 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1713 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1714 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
   1715 		va_end(ap);
   1716 
   1717 		if (in_len1 && !in_blob1) {
   1718 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1719 			LogError("Internal error for ordinal 0x%x", ordinal);
   1720 			break;
   1721 		}
   1722 
   1723 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1724 		LoadBlob_UINT32(outOffset, val1, out_blob);
   1725 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1726 		if (auth1 && auth2) {
   1727 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1728 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1729 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
   1730 		} else if (auth1) {
   1731 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1732 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1733 		} else if (auth2) {
   1734 			LoadBlob_Auth(outOffset, out_blob, auth2);
   1735 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1736 		} else {
   1737 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1738 		}
   1739 
   1740 		break;
   1741 	}
   1742 	/* 1 UINT16, 1 BLOB, 1 AUTH */
   1743 	case TPM_ORD_AuthorizeMigrationKey:
   1744 	{
   1745 		UINT16 scheme1 = va_arg(ap, int);
   1746 		UINT32 in_len1 = va_arg(ap, UINT32);
   1747 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1748 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1749 		va_end(ap);
   1750 
   1751 		if (!in_blob1 || !auth1) {
   1752 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1753 			LogError("Internal error for ordinal 0x%x", ordinal);
   1754 			break;
   1755 		}
   1756 
   1757 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1758 		LoadBlob_UINT16(outOffset, scheme1, out_blob);
   1759 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1760 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1761 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1762 
   1763 		break;
   1764 	}
   1765 	/* 1 UINT16, 1 UINT32, 1 BLOB, 1 UINT32, 2 BLOBs, 1 AUTH */
   1766 	case TPM_ORD_TakeOwnership:
   1767 	{
   1768 		UINT16 scheme1 = va_arg(ap, int);
   1769 		UINT32 in_len1 = va_arg(ap, UINT32);
   1770 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   1771 		UINT32 in_len2 = va_arg(ap, UINT32);
   1772 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   1773 		UINT32 in_len3 = va_arg(ap, UINT32);
   1774 		BYTE *in_blob3 = va_arg(ap, BYTE *);
   1775 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1776 		va_end(ap);
   1777 
   1778 		if (!in_blob1 || !in_blob2 || !in_blob3 || !auth1) {
   1779 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1780 			LogError("Internal error for ordinal 0x%x", ordinal);
   1781 			break;
   1782 		}
   1783 
   1784 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1785 		LoadBlob_UINT16(outOffset, scheme1, out_blob);
   1786 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
   1787 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   1788 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   1789 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   1790 		LoadBlob(outOffset, in_len3, out_blob, in_blob3);
   1791 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1792 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1793 
   1794 		break;
   1795 	}
   1796 #ifdef TSS_BUILD_AUDIT
   1797 	/* 1 UINT32, 1 BOOL, 1 20 byte value, 1 optional AUTH */
   1798 	case TPM_ORD_GetAuditDigestSigned:
   1799 	{
   1800 		UINT32 keyslot1 = va_arg(ap, UINT32);
   1801 		TSS_BOOL bool1 = va_arg(ap, int);
   1802 		BYTE *digest1 = va_arg(ap, BYTE *);
   1803 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1804 		va_end(ap);
   1805 
   1806 		if (!digest1) {
   1807 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1808 			LogError("Internal error for ordinal 0x%x", ordinal);
   1809 			break;
   1810 		}
   1811 
   1812 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1813 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
   1814 		LoadBlob_BOOL(outOffset, bool1, out_blob);
   1815 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1816 
   1817 		if (auth1) {
   1818 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1819 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1820 		} else {
   1821 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1822 		}
   1823 
   1824 		break;
   1825 	}
   1826 #endif
   1827 	/* 1 UINT16, 1 UINT32, 1 20 byte value */
   1828 	case TPM_ORD_OSAP:
   1829 	{
   1830 		UINT16 type1 = va_arg(ap, int);
   1831 		UINT32 value1 = va_arg(ap, UINT32);
   1832 		BYTE *digest1 = va_arg(ap, BYTE *);
   1833 		va_end(ap);
   1834 
   1835 		if (!digest1) {
   1836 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1837 			LogError("Internal error for ordinal 0x%x", ordinal);
   1838 			break;
   1839 		}
   1840 
   1841 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1842 		LoadBlob_UINT16(outOffset, type1, out_blob);
   1843 		LoadBlob_UINT32(outOffset, value1, out_blob);
   1844 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1845 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1846 
   1847 		break;
   1848 	}
   1849 	/* 1 UINT16, 1 20 byte value, 1 UINT16, 1 AUTH */
   1850 	case TPM_ORD_ChangeAuthOwner:
   1851 	{
   1852 		UINT16 type1 = va_arg(ap, int);
   1853 		BYTE *digest1 = va_arg(ap, BYTE *);
   1854 		UINT16 type2 = va_arg(ap, int);
   1855 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1856 		va_end(ap);
   1857 
   1858 		if (!digest1 || !auth1) {
   1859 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1860 			LogError("Internal error for ordinal 0x%x", ordinal);
   1861 			break;
   1862 		}
   1863 
   1864 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1865 		LoadBlob_UINT16(outOffset, type1, out_blob);
   1866 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1867 		LoadBlob_UINT16(outOffset, type2, out_blob);
   1868 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1869 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1870 
   1871 		break;
   1872 	}
   1873 #ifdef TSS_BUILD_AUDIT
   1874 	/* 1 UINT32, 1 BOOL, 1 AUTH */
   1875 	case TPM_ORD_SetOrdinalAuditStatus:
   1876 	{
   1877 		UINT32 ord1 = va_arg(ap, UINT32);
   1878 		TSS_BOOL bool1 = va_arg(ap, int);
   1879 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1880 		va_end(ap);
   1881 
   1882 		if (!auth1) {
   1883 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   1884 			LogError("Internal error for ordinal 0x%x", ordinal);
   1885 			break;
   1886 		}
   1887 
   1888 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1889 		LoadBlob_UINT32(outOffset, ord1, out_blob);
   1890 		LoadBlob_BOOL(outOffset, bool1, out_blob);
   1891 		LoadBlob_Auth(outOffset, out_blob, auth1);
   1892 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1893 
   1894 		break;
   1895 	}
   1896 #endif
   1897 	/* 1 BOOL, 1 optional AUTH */
   1898 	case TPM_ORD_OwnerSetDisable:
   1899 	case TPM_ORD_PhysicalSetDeactivated:
   1900 	case TPM_ORD_CreateMaintenanceArchive:
   1901 	case TPM_ORD_SetOwnerInstall:
   1902 	{
   1903 		TSS_BOOL bool1 = va_arg(ap, int);
   1904 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1905 		va_end(ap);
   1906 
   1907 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1908 		LoadBlob_BOOL(outOffset, bool1, out_blob);
   1909 		if (auth1) {
   1910 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1911 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1912 		} else {
   1913 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1914 		}
   1915 
   1916 		break;
   1917 	}
   1918 	/* 1 optional AUTH */
   1919 	case TPM_ORD_OwnerClear:
   1920 	case TPM_ORD_DisablePubekRead:
   1921 	case TPM_ORD_GetCapabilityOwner:
   1922 	case TPM_ORD_ResetLockValue:
   1923 	case TPM_ORD_DisableOwnerClear:
   1924 	case TPM_ORD_SetTempDeactivated:
   1925 	case TPM_ORD_OIAP:
   1926 	case TPM_ORD_OwnerReadPubek:
   1927 	case TPM_ORD_SelfTestFull:
   1928 	case TPM_ORD_GetTicks:
   1929 	case TPM_ORD_GetTestResult:
   1930 	case TPM_ORD_KillMaintenanceFeature:
   1931 	case TPM_ORD_Delegate_ReadTable:
   1932 	case TPM_ORD_PhysicalEnable:
   1933 	case TPM_ORD_DisableForceClear:
   1934 	case TPM_ORD_ForceClear:
   1935 	{
   1936 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1937 		va_end(ap);
   1938 
   1939 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1940 		if (auth1) {
   1941 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1942 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1943 		} else {
   1944 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1945 		}
   1946 
   1947 		break;
   1948 	}
   1949 	/* 1 UINT32, 1 optional AUTH */
   1950 	case TPM_ORD_OwnerReadInternalPub:
   1951 	case TPM_ORD_GetPubKey:
   1952 	case TPM_ORD_ReleaseCounterOwner:
   1953 	case TPM_ORD_ReleaseCounter:
   1954 	case TPM_ORD_IncrementCounter:
   1955 	case TPM_ORD_PcrRead:
   1956 	case TPM_ORD_DirRead:
   1957 	case TPM_ORD_ReadCounter:
   1958 	case TPM_ORD_Terminate_Handle:
   1959 	case TPM_ORD_GetAuditDigest:
   1960 	case TPM_ORD_GetRandom:
   1961 	case TPM_ORD_CMK_SetRestrictions:
   1962 	{
   1963 		UINT32 i = va_arg(ap, UINT32);
   1964 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1965 		va_end(ap);
   1966 
   1967 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1968 		LoadBlob_UINT32(outOffset, i, out_blob);
   1969 		if (auth1) {
   1970 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1971 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1972 		} else {
   1973 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1974 		}
   1975 
   1976 		break;
   1977 	}
   1978 #ifdef TSS_BUILD_CMK
   1979 	/* 1 20 byte value, 1 optional AUTH */
   1980 	case TPM_ORD_CMK_ApproveMA:
   1981 	{
   1982 		BYTE *digest1 = va_arg(ap, BYTE *);
   1983 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   1984 		va_end(ap);
   1985 
   1986 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   1987 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   1988 		if (auth1) {
   1989 			LoadBlob_Auth(outOffset, out_blob, auth1);
   1990 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   1991 		} else {
   1992 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   1993 		}
   1994 
   1995 		break;
   1996 	}
   1997 #endif
   1998 	/* 1 UINT16 only */
   1999 	case TSC_ORD_PhysicalPresence:
   2000 	{
   2001 		UINT16 i = va_arg(ap, int);
   2002 		va_end(ap);
   2003 
   2004 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2005 		LoadBlob_UINT16(outOffset, i, out_blob);
   2006 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   2007 
   2008 		break;
   2009 	}
   2010 #ifdef TSS_BUILD_CMK
   2011 	/* 1 UINT32, 1 20 byte value, 1 BLOB, 2 20 byte values, 1 optional AUTH */
   2012 	case TPM_ORD_CMK_CreateKey:
   2013 	{
   2014 		UINT32 key1 = va_arg(ap, UINT32);
   2015 		BYTE *digest1 = va_arg(ap, BYTE *);
   2016 		UINT32 in_len1 = va_arg(ap, UINT32);
   2017 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   2018 		BYTE *digest2 = va_arg(ap, BYTE *);
   2019 		BYTE *digest3 = va_arg(ap, BYTE *);
   2020 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   2021 		va_end(ap);
   2022 
   2023 		if (!digest1 || !in_blob1 || !digest2 || !digest3) {
   2024 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   2025 			LogError("Internal error for ordinal 0x%x", ordinal);
   2026 			break;
   2027 		}
   2028 
   2029 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2030 		LoadBlob_UINT32(outOffset, key1, out_blob);
   2031 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   2032 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   2033 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
   2034 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest3);
   2035 		if (auth1) {
   2036 			LoadBlob_Auth(outOffset, out_blob, auth1);
   2037 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   2038 		} else {
   2039 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   2040 		}
   2041 
   2042 		break;
   2043 	}
   2044 	/* 1 BLOB, 1 20 byte value, 1 UINT32, 1 BLOB, 1 optional AUTH */
   2045 	case TPM_ORD_CMK_CreateTicket:
   2046 	{
   2047 		UINT32 in_len1 = va_arg(ap, UINT32);
   2048 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   2049 		BYTE *digest1 = va_arg(ap, BYTE *);
   2050 		UINT32 in_len2 = va_arg(ap, UINT32);
   2051 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   2052 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   2053 		va_end(ap);
   2054 
   2055 		if (!digest1 || !in_blob1 || !in_blob2) {
   2056 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   2057 			LogError("Internal error for ordinal 0x%x", ordinal);
   2058 			break;
   2059 		}
   2060 
   2061 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2062 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   2063 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   2064 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   2065 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   2066 		if (auth1) {
   2067 			LoadBlob_Auth(outOffset, out_blob, auth1);
   2068 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   2069 		} else {
   2070 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   2071 		}
   2072 
   2073 		break;
   2074 	}
   2075 	/* 1 UINT32, 1 UINT16, 1 BLOB, 1 20 byte value, 4 x (1 UINT32, 1 BLOB), 1 optional AUTH */
   2076 	case TPM_ORD_CMK_CreateBlob:
   2077 	{
   2078 		UINT32 in_key1 = va_arg(ap, UINT32);
   2079 		UINT16 i = va_arg(ap, int);
   2080 		UINT32 in_len1 = va_arg(ap, UINT32);
   2081 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   2082 		BYTE *digest1 = va_arg(ap, BYTE *);
   2083 		UINT32 in_len2 = va_arg(ap, UINT32);
   2084 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   2085 		UINT32 in_len3 = va_arg(ap, UINT32);
   2086 		BYTE *in_blob3 = va_arg(ap, BYTE *);
   2087 		UINT32 in_len4 = va_arg(ap, UINT32);
   2088 		BYTE *in_blob4 = va_arg(ap, BYTE *);
   2089 		UINT32 in_len5 = va_arg(ap, UINT32);
   2090 		BYTE *in_blob5 = va_arg(ap, BYTE *);
   2091 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   2092 		va_end(ap);
   2093 
   2094 		if (!digest1 || !in_blob1 || !in_blob2 || !in_blob3 || !in_blob4 || !in_blob5) {
   2095 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   2096 			LogError("Internal error for ordinal 0x%x", ordinal);
   2097 			break;
   2098 		}
   2099 
   2100 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2101 		LoadBlob_UINT32(outOffset, in_key1, out_blob);
   2102 		LoadBlob_UINT16(outOffset, i, out_blob);
   2103 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   2104 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   2105 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   2106 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   2107 		LoadBlob_UINT32(outOffset, in_len3, out_blob);
   2108 		LoadBlob(outOffset, in_len3, out_blob, in_blob3);
   2109 		LoadBlob_UINT32(outOffset, in_len4, out_blob);
   2110 		LoadBlob(outOffset, in_len4, out_blob, in_blob4);
   2111 		LoadBlob_UINT32(outOffset, in_len5, out_blob);
   2112 		LoadBlob(outOffset, in_len5, out_blob, in_blob5);
   2113 		if (auth1) {
   2114 			LoadBlob_Auth(outOffset, out_blob, auth1);
   2115 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   2116 		} else {
   2117 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   2118 		}
   2119 
   2120 		break;
   2121 	}
   2122 	/* 1 UINT32, 1 60 byte value, 1 20 byte value, 1 BLOB, 2 x (1 UINT32, 1 BLOB),
   2123 	 * 1 optional AUTH */
   2124 	case TPM_ORD_CMK_ConvertMigration:
   2125 	{
   2126 		UINT32 key1 = va_arg(ap, UINT32);
   2127 		BYTE *cmkauth1 = va_arg(ap, BYTE *);
   2128 		BYTE *digest1 = va_arg(ap, BYTE *);
   2129 		UINT32 in_len1 = va_arg(ap, UINT32);
   2130 		BYTE *in_blob1 = va_arg(ap, BYTE *);
   2131 		UINT32 in_len2 = va_arg(ap, UINT32);
   2132 		BYTE *in_blob2 = va_arg(ap, BYTE *);
   2133 		UINT32 in_len3 = va_arg(ap, UINT32);
   2134 		BYTE *in_blob3 = va_arg(ap, BYTE *);
   2135 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   2136 		va_end(ap);
   2137 
   2138 		if (!cmkauth1 || !digest1 || !in_blob1 || !in_blob2 || !in_blob3) {
   2139 			result = TCSERR(TSS_E_INTERNAL_ERROR);
   2140 			LogError("Internal error for ordinal 0x%x", ordinal);
   2141 			break;
   2142 		}
   2143 
   2144 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2145 		LoadBlob_UINT32(outOffset, key1, out_blob);
   2146 		LoadBlob(outOffset, 3 * TPM_SHA1_160_HASH_LEN, out_blob, cmkauth1);
   2147 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
   2148 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
   2149 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
   2150 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
   2151 		LoadBlob_UINT32(outOffset, in_len3, out_blob);
   2152 		LoadBlob(outOffset, in_len3, out_blob, in_blob3);
   2153 		if (auth1) {
   2154 			LoadBlob_Auth(outOffset, out_blob, auth1);
   2155 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   2156 		} else {
   2157 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   2158 		}
   2159 
   2160 		break;
   2161 	}
   2162 #endif
   2163 #ifdef TSS_BUILD_TSS12
   2164 	case TPM_ORD_FlushSpecific:
   2165 	{
   2166 		UINT32 val1 = va_arg(ap, UINT32);
   2167 		UINT32 val2 = va_arg(ap, UINT32);
   2168 		va_end(ap);
   2169 
   2170 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2171 		LoadBlob_UINT32(outOffset, val1, out_blob);
   2172 		LoadBlob_UINT32(outOffset, val2, out_blob);
   2173 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
   2174 
   2175 		break;
   2176 	}
   2177 	/* 1 UINT32, 1 BLOB, 1 UINT32, 1 BOOL, 1 AUTH */
   2178 	case TPM_ORD_KeyControlOwner:
   2179 	{
   2180 		UINT32 i = va_arg(ap, UINT32);
   2181 		UINT32 len1 = va_arg(ap, UINT32);
   2182 		BYTE *blob1 = va_arg(ap, BYTE *);
   2183 		UINT32 j = va_arg(ap, UINT32);
   2184 		TSS_BOOL bool1 = va_arg(ap, int);
   2185 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
   2186 	        va_end(ap);
   2187 
   2188 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
   2189 		LoadBlob_UINT32(outOffset, i, out_blob);
   2190 		LoadBlob(outOffset, len1, out_blob, blob1);
   2191 		LoadBlob_UINT32(outOffset, j, out_blob);
   2192 		LoadBlob_BOOL(outOffset, bool1, out_blob);
   2193 		LoadBlob_Auth(outOffset, out_blob, auth1);
   2194 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
   2195 
   2196 		break;
   2197 	}
   2198 #endif
   2199 	default:
   2200 		va_end(ap);
   2201 		LogError("Unknown ordinal: 0x%x", ordinal);
   2202 		break;
   2203 	}
   2204 
   2205 	return result;
   2206 }
   2207