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
tpm_rsp_parse(TPM_COMMAND_CODE ordinal,BYTE * b,UINT32 len,...)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
tpm_rqu_build(TPM_COMMAND_CODE ordinal,UINT64 * outOffset,BYTE * out_blob,...)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