xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/tcs_pbg.c (revision 6cd39ddb8550f6fa1bff3fed32053d7f19fd0453)
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 		} else
503 			offset2 = len;
504 
505 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
506 		offset2 -= TSS_TPM_TXBLOB_HDR_LEN;
507 		if ((*blob1 = malloc(offset2)) == NULL) {
508 			LogError("malloc of %zd bytes failed", (size_t)offset2);
509 			return TCSERR(TSS_E_OUTOFMEMORY);
510 		}
511 		*len1 = offset2;
512 		UnloadBlob(&offset1, *len1, b, *blob1);
513 
514 		break;
515 	}
516 	/* TPM BLOB: TPM_KEY, UINT32, BLOB, optional AUTH, AUTH
517 	 * return:   UINT32 *, BYTE **, UINT32 *, BYTE **, optional AUTH, AUTH */
518 	case TPM_ORD_MakeIdentity:
519 	{
520 		UINT32 *len1, *len2;
521 		BYTE **blob1, **blob2;
522 		TPM_AUTH *auth1, *auth2;
523 
524 		len1 = va_arg(ap, UINT32 *);
525 		blob1 = va_arg(ap, BYTE **);
526 		len2 = va_arg(ap, UINT32 *);
527 		blob2 = va_arg(ap, BYTE **);
528 		auth1 = va_arg(ap, TPM_AUTH *);
529 		auth2 = va_arg(ap, TPM_AUTH *);
530 		va_end(ap);
531 
532 		if (!len1 || !blob1 || !len2 || !blob2 || !auth2) {
533 			LogError("Internal error for ordinal 0x%x", ordinal);
534 			return TCSERR(TSS_E_INTERNAL_ERROR);
535 		}
536 
537 		offset1 = offset2 = TSS_TPM_TXBLOB_HDR_LEN;
538 		UnloadBlob_TSS_KEY(&offset1, b, NULL);
539 		offset1 -= TSS_TPM_TXBLOB_HDR_LEN;
540 
541 		if ((*blob1 = malloc(offset1)) == NULL) {
542 			LogError("malloc of %zd bytes failed", (size_t)offset1);
543 			return TCSERR(TSS_E_OUTOFMEMORY);
544 		}
545 		*len1 = offset1;
546 
547 		UnloadBlob(&offset2, offset1, b, *blob1);
548 
549 		/* offset2 points to the stuff after the key */
550 		UnloadBlob_UINT32(&offset2, len2, b);
551 
552 		if ((*blob2 = malloc(*len2)) == NULL) {
553 			free(*blob1);
554 			LogError("malloc of %u bytes failed", *len2);
555 			return TCSERR(TSS_E_OUTOFMEMORY);
556 		}
557 
558 		UnloadBlob(&offset2, *len2, b, *blob2);
559 
560 		if (auth1)
561 			UnloadBlob_Auth(&offset2, b, auth1);
562 		UnloadBlob_Auth(&offset2, b, auth2);
563 
564 		break;
565 	}
566 	/* 1 TPM_VERSION, 2 UINT32s, 1 optional AUTH */
567 	case TPM_ORD_GetCapabilityOwner:
568 	{
569 		TPM_VERSION *ver1 = va_arg(ap, TPM_VERSION *);
570 		UINT32 *data1 = va_arg(ap, UINT32 *);
571 		UINT32 *data2 = va_arg(ap, UINT32 *);
572 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
573 		va_end(ap);
574 
575 		if (!data1 || !data2 || !ver1) {
576 			LogError("Internal error for ordinal 0x%x", ordinal);
577 			return TCSERR(TSS_E_INTERNAL_ERROR);
578 		}
579 
580 		if (auth) {
581 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
582 			UnloadBlob_Auth(&offset1, b, auth);
583 		}
584 
585 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
586 		UnloadBlob_VERSION(&offset1, b, ver1);
587 		UnloadBlob_UINT32(&offset1, data1, b);
588 		UnloadBlob_UINT32(&offset1, data2, b);
589 		break;
590 	}
591 	/* TPM BLOB: 1 UINT32, 1 BLOB, 2 optional AUTHs
592 	 * return: UINT32 *, BYTE**, 2 optional AUTHs */
593 	case TPM_ORD_Sign:
594 	case TPM_ORD_GetTestResult:
595 	case TPM_ORD_CertifySelfTest:
596 	case TPM_ORD_Unseal:
597 	case TPM_ORD_GetRandom:
598 	case TPM_ORD_DAA_Join:
599 	case TPM_ORD_DAA_Sign:
600 	case TPM_ORD_ChangeAuth:
601 	case TPM_ORD_GetCapability:
602 	case TPM_ORD_LoadMaintenanceArchive:
603 	case TPM_ORD_ConvertMigrationBlob:
604 	case TPM_ORD_NV_ReadValue:
605 	case TPM_ORD_NV_ReadValueAuth:
606 	case TPM_ORD_Delegate_Manage:
607 	case TPM_ORD_Delegate_CreateKeyDelegation:
608 	case TPM_ORD_Delegate_CreateOwnerDelegation:
609 	case TPM_ORD_Delegate_UpdateVerification:
610 	case TPM_ORD_CMK_ConvertMigration:
611 	{
612 		UINT32 *data_len = va_arg(ap, UINT32 *);
613 		BYTE **data = va_arg(ap, BYTE **);
614 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
615 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
616 		va_end(ap);
617 
618 		if (!data || !data_len) {
619 			LogError("Internal error for ordinal 0x%x", ordinal);
620 			return TCSERR(TSS_E_INTERNAL_ERROR);
621 		}
622 
623 		if (auth1 && auth2) {
624 			offset1 = len - (2 * TSS_TPM_RSP_BLOB_AUTH_LEN);
625 			UnloadBlob_Auth(&offset1, b, auth1);
626 			UnloadBlob_Auth(&offset1, b, auth2);
627 		} else if (auth1) {
628 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
629 			UnloadBlob_Auth(&offset1, b, auth1);
630 		} else if (auth2) {
631 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
632 			UnloadBlob_Auth(&offset1, b, auth2);
633 		}
634 
635 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
636 		UnloadBlob_UINT32(&offset1, data_len, b);
637 		if ((*data = malloc(*data_len)) == NULL) {
638 			LogError("malloc of %u bytes failed", *data_len);
639 			return TCSERR(TSS_E_OUTOFMEMORY);
640 		}
641 
642 		UnloadBlob(&offset1, *data_len, b, *data);
643 		break;
644 	}
645 	/* TPM BLOB: 1 UINT32, 1 BLOB, 1 optional AUTH
646 	* return: UINT32 *, BYTE**, 1 optional AUTH*/
647 	case TPM_ORD_UnBind:
648 	{
649 		UINT32 *data_len = va_arg(ap, UINT32 *);
650 		BYTE **data = va_arg(ap, BYTE **);
651 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
652 		va_end(ap);
653 
654 		if (!data || !data_len) {
655 			LogError("Internal error for ordinal 0x%x", ordinal);
656 			return TCSERR(TSS_E_INTERNAL_ERROR);
657 		}
658 
659 		if (auth1) {
660 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
661 			UnloadBlob_Auth(&offset1, b, auth1);
662 		}
663 
664 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
665 		UnloadBlob_UINT32(&offset1, data_len, b);
666 		if ((*data = malloc(*data_len)) == NULL) {
667 			LogError("malloc of %u bytes failed", *data_len);
668 			return TCSERR(TSS_E_OUTOFMEMORY);
669 		}
670 
671 		UnloadBlob(&offset1, *data_len, b, *data);
672 		break;
673 	}
674 	/* TPM BLOB: 1 BLOB, 1 optional AUTH
675 	 * return: UINT32 *, BYTE**, 1 optional AUTH*/
676 	case TPM_ORD_GetTicks:
677 	case TPM_ORD_Seal:
678 	case TPM_ORD_Sealx:
679 	case TPM_ORD_FieldUpgrade:
680 	case TPM_ORD_CreateWrapKey:
681 	case TPM_ORD_GetPubKey:
682 	case TPM_ORD_OwnerReadPubek:
683 	case TPM_ORD_OwnerReadInternalPub:
684 	case TPM_ORD_AuthorizeMigrationKey:
685 	case TPM_ORD_TakeOwnership:
686 	case TPM_ORD_CMK_CreateKey:
687 	{
688 		UINT32 *data_len = va_arg(ap, UINT32 *);
689 		BYTE **data = va_arg(ap, BYTE **);
690 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
691 		va_end(ap);
692 
693 		if (!data || !data_len) {
694 			LogError("Internal error for ordinal 0x%x", ordinal);
695 			return TCSERR(TSS_E_INTERNAL_ERROR);
696 		}
697 
698 		/* remove the auth data from the back end of the data */
699 		if (auth) {
700 			offset1 = offset2 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
701 			UnloadBlob_Auth(&offset1, b, auth);
702 		} else
703 			offset2 = len;
704 
705 		/* everything after the header is returned as the blob */
706 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
707 		offset2 -= offset1;
708 		if ((*data = malloc((size_t)offset2)) == NULL) {
709 			LogError("malloc of %zd bytes failed", (size_t)offset2);
710 			return TCSERR(TSS_E_OUTOFMEMORY);
711 		}
712 
713 		memcpy(*data, &b[offset1], offset2);
714 		*data_len = offset2;
715 		break;
716 	}
717 	/* TPM BLOB: BLOB, optional DIGEST */
718 	case TPM_ORD_CreateEndorsementKeyPair:
719 	case TPM_ORD_ReadPubek:
720 	{
721 		UINT32 *data_len = va_arg(ap, UINT32 *);
722 		BYTE **data = va_arg(ap, BYTE **);
723 		BYTE *digest1 = va_arg(ap, BYTE *);
724 		va_end(ap);
725 
726 		if (!data || !data_len) {
727 			LogError("Internal error for ordinal 0x%x", ordinal);
728 			return TCSERR(TSS_E_INTERNAL_ERROR);
729 		}
730 
731 		if (digest1) {
732 			offset1 = offset2 = len - TPM_DIGEST_SIZE;
733 			memcpy(digest1, &b[offset2], TPM_DIGEST_SIZE);
734 		} else
735 			offset2 = len;
736 
737 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
738 		offset2 -= offset1;
739 		if ((*data = malloc((size_t)offset2)) == NULL) {
740 			LogError("malloc of %zd bytes failed", (size_t)offset2);
741 			return TCSERR(TSS_E_OUTOFMEMORY);
742 		}
743 
744 		UnloadBlob(&offset1, offset2, b, *data);
745 		*data_len = offset2;
746 		break;
747 	}
748 #ifdef TSS_BUILD_TSS12
749 	/* TPM BLOB: BLOB, DIGEST, DIGEST
750 	 * return: UINT32 *, BYTE**, DIGEST, DIGEST */
751 	case TPM_ORD_CreateRevocableEK:
752 	{
753 		UINT32 *data_len = va_arg(ap, UINT32 *);
754 		BYTE **data = va_arg(ap, BYTE **);
755 		BYTE *digest1 = va_arg(ap, BYTE *);
756 		BYTE *digest2 = va_arg(ap, BYTE *);
757 		va_end(ap);
758 
759 		if (!data || !data_len || !digest1 || !digest2) {
760 			LogError("Internal error for ordinal 0x%x", ordinal);
761 			return TCSERR(TSS_E_INTERNAL_ERROR);
762 		}
763 
764 		offset2 = len - TPM_DIGEST_SIZE;
765 		memcpy(digest2, &b[offset2], TPM_DIGEST_SIZE);
766 
767 		offset2 -= TPM_DIGEST_SIZE;
768 		memcpy(digest1, &b[offset2], TPM_DIGEST_SIZE);
769 
770 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
771 		offset2 -= offset1;
772 		if ((*data = malloc((size_t)offset2)) == NULL) {
773 			LogError("malloc of %zd bytes failed", (size_t)offset2);
774 			return TCSERR(TSS_E_OUTOFMEMORY);
775 		}
776 
777 		UnloadBlob(&offset1, offset2, b, *data);
778 		*data_len = offset2;
779 		break;
780 	}
781 #endif
782 	/* 1 UINT32, 1 optional AUTH */
783 	case TPM_ORD_LoadKey:
784 	case TPM_ORD_LoadKey2:
785 	{
786 		UINT32 *handle;
787 		TPM_AUTH *auth;
788 
789 		handle = va_arg(ap, UINT32 *);
790 		auth = va_arg(ap, TPM_AUTH *);
791 		va_end(ap);
792 
793 		if (!handle) {
794 			LogError("Internal error for ordinal 0x%x", ordinal);
795 			return TCSERR(TSS_E_INTERNAL_ERROR);
796 		}
797 
798 		if (auth) {
799 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
800 			UnloadBlob_Auth(&offset1, b, auth);
801 		}
802 
803 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
804 		UnloadBlob_UINT32(&offset1, handle, b);
805 		break;
806 	}
807 	/* 1 optional UINT32, 1 20 byte value */
808 	case TPM_ORD_DirRead:
809 	case TPM_ORD_OIAP:
810 	case TPM_ORD_LoadManuMaintPub:
811 	case TPM_ORD_ReadManuMaintPub:
812 	case TPM_ORD_Extend:
813 	case TPM_ORD_PcrRead:
814 	{
815 		UINT32 *handle = va_arg(ap, UINT32 *);
816 		BYTE *nonce = va_arg(ap, BYTE *);
817 		va_end(ap);
818 
819 		if (!nonce) {
820 			LogError("Internal error for ordinal 0x%x", ordinal);
821 			return TCSERR(TSS_E_INTERNAL_ERROR);
822 		}
823 
824 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
825 		if (handle)
826 			UnloadBlob_UINT32(&offset1, handle, b);
827 		UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce);
828 		break;
829 	}
830 	/* 1 UINT32, 2 20 byte values */
831 	case TPM_ORD_OSAP:
832 	case TPM_ORD_DSAP:
833 	{
834 		UINT32 *handle = va_arg(ap, UINT32 *);
835 		BYTE *nonce1 = va_arg(ap, BYTE *);
836 		BYTE *nonce2 = va_arg(ap, BYTE *);
837 		va_end(ap);
838 
839 		if (!handle || !nonce1 || !nonce2) {
840 			LogError("Internal error for ordinal 0x%x", ordinal);
841 			return TCSERR(TSS_E_INTERNAL_ERROR);
842 		}
843 
844 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
845 		UnloadBlob_UINT32(&offset1, handle, b);
846 		UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce1);
847 		UnloadBlob(&offset1, TPM_NONCE_SIZE, b, nonce2);
848 		break;
849 	}
850 #ifdef TSS_BUILD_CMK
851 	/* 1 20 byte value, 1 optional AUTH */
852 	case TPM_ORD_CMK_ApproveMA:
853 	case TPM_ORD_CMK_CreateTicket:
854 	{
855 		BYTE *hmac1 = va_arg(ap, BYTE *);
856 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
857 		va_end(ap);
858 
859 		if (!hmac1) {
860 			LogError("Internal error for ordinal 0x%x", ordinal);
861 			return TCSERR(TSS_E_INTERNAL_ERROR);
862 		}
863 
864 		offset1 = TSS_TPM_TXBLOB_HDR_LEN;
865 		UnloadBlob(&offset1, TPM_SHA1_160_HASH_LEN, b, hmac1);
866 		if (auth) {
867 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
868 			UnloadBlob_Auth(&offset1, b, auth);
869 		}
870 		break;
871 	}
872 #endif
873 	/* 1 optional AUTH */
874 	case TPM_ORD_DisablePubekRead:
875 	case TPM_ORD_DirWriteAuth:
876 	case TPM_ORD_ReleaseCounter:
877 	case TPM_ORD_ReleaseCounterOwner:
878 	case TPM_ORD_ChangeAuthOwner:
879 	case TPM_ORD_SetCapability:
880 	case TPM_ORD_SetOrdinalAuditStatus:
881 	case TPM_ORD_ResetLockValue:
882 	case TPM_ORD_SetRedirection:
883 	case TPM_ORD_DisableOwnerClear:
884 	case TPM_ORD_OwnerSetDisable:
885 	case TPM_ORD_SetTempDeactivated:
886 	case TPM_ORD_KillMaintenanceFeature:
887 	case TPM_ORD_NV_DefineSpace:
888 	case TPM_ORD_NV_WriteValue:
889 	case TPM_ORD_NV_WriteValueAuth:
890 	case TPM_ORD_OwnerClear:
891 	case TPM_ORD_Delegate_LoadOwnerDelegation:
892 	case TPM_ORD_CMK_SetRestrictions:
893 	case TPM_ORD_FlushSpecific:
894 	case TPM_ORD_KeyControlOwner:
895 	{
896 		TPM_AUTH *auth = va_arg(ap, TPM_AUTH *);
897 		va_end(ap);
898 
899 		if (auth) {
900 			offset1 = len - TSS_TPM_RSP_BLOB_AUTH_LEN;
901 			UnloadBlob_Auth(&offset1, b, auth);
902 		}
903 		break;
904 	}
905 	default:
906 		LogError("Unknown ordinal: 0x%x", ordinal);
907 		result = TCSERR(TSS_E_INTERNAL_ERROR);
908 		break;
909 	}
910 
911 	return result;
912 }
913 
914 /* XXX optimize these cases by always passing in lengths for blobs, no more "20 byte values" */
915 TSS_RESULT
916 tpm_rqu_build(TPM_COMMAND_CODE ordinal, UINT64 *outOffset, BYTE *out_blob, ...)
917 {
918 	TSS_RESULT result = TSS_SUCCESS;
919 	UINT64 blob_size;
920 	va_list ap;
921 
922 	DBG_ASSERT(ordinal);
923 	DBG_ASSERT(outOffset);
924 	DBG_ASSERT(out_blob);
925 
926 	va_start(ap, out_blob);
927 
928 	switch (ordinal) {
929 #ifdef TSS_BUILD_DELEGATION
930 	/* 1 UINT16, 1 UINT32, 1 20 bytes value, 1 UINT32, 1 BLOB */
931 	case TPM_ORD_DSAP:
932 	{
933 		UINT16 val1 = va_arg(ap, int);
934 		UINT32 handle1 = va_arg(ap, UINT32);
935 		BYTE *digest1 = va_arg(ap, BYTE *);
936 		UINT32 in_len1 = va_arg(ap, UINT32);
937 		BYTE *in_blob1 = va_arg(ap, BYTE *);
938 		va_end(ap);
939 
940 		if (!digest1 || !in_blob1) {
941 			result = TCSERR(TSS_E_INTERNAL_ERROR);
942 			LogError("Internal error for ordinal 0x%x", ordinal);
943 			break;
944 		}
945 
946 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
947 		LoadBlob_UINT16(outOffset, val1, out_blob);
948 		LoadBlob_UINT32(outOffset, handle1, out_blob);
949 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
950 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
951 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
952 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
953 
954 		break;
955 	}
956 	/* 1 BOOL, 1 UINT32, 1 BLOB, 1 20 byte value, 1 AUTH */
957 	case TPM_ORD_Delegate_CreateOwnerDelegation:
958 	{
959 		TSS_BOOL bool1 = va_arg(ap, int);
960 		UINT32 in_len1 = va_arg(ap, UINT32);
961 		BYTE *in_blob1 = va_arg(ap, BYTE *);
962 		BYTE *digest1 = va_arg(ap, BYTE *);
963 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
964 		va_end(ap);
965 
966 		if (!in_len1 || !in_blob1 || !digest1) {
967 			result = TCSERR(TSS_E_INTERNAL_ERROR);
968 			LogError("Internal error for ordinal 0x%x", ordinal);
969 			break;
970 		}
971 
972 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
973 		LoadBlob_BOOL(outOffset, bool1, out_blob);
974 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
975 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
976 		if (auth1) {
977 			LoadBlob_Auth(outOffset, out_blob, auth1);
978 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
979 		} else
980 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
981 
982 		break;
983 	}
984 	/* 2 UINT32's, 1 BLOB, 1 20 byte value, 1 AUTH */
985 	case TPM_ORD_Delegate_CreateKeyDelegation:
986 	{
987 		UINT32 keyslot1 = va_arg(ap, UINT32);
988 		UINT32 in_len1 = va_arg(ap, UINT32);
989 		BYTE *in_blob1 = va_arg(ap, BYTE *);
990 		BYTE *digest1 = va_arg(ap, BYTE *);
991 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
992 		va_end(ap);
993 
994 		if (!keyslot1 || !in_len1 || !in_blob1 || !digest1) {
995 			result = TCSERR(TSS_E_INTERNAL_ERROR);
996 			LogError("Internal error for ordinal 0x%x", ordinal);
997 			break;
998 		}
999 
1000 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1001 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
1002 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1003 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1004 		if (auth1) {
1005 			LoadBlob_Auth(outOffset, out_blob, auth1);
1006 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1007 		} else
1008 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1009 
1010 		break;
1011 	}
1012 #endif
1013 #ifdef TSS_BUILD_TRANSPORT
1014 	/* 3 UINT32's, 1 BLOB, 2 AUTHs */
1015 	case TPM_ORD_ExecuteTransport:
1016 	{
1017 		UINT32 ord1 = va_arg(ap, UINT32);
1018 		UINT32 *keyslot1 = va_arg(ap, UINT32 *);
1019 		UINT32 *keyslot2 = va_arg(ap, UINT32 *);
1020 		UINT32 in_len1 = va_arg(ap, UINT32);
1021 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1022 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1023 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
1024 		va_end(ap);
1025 
1026 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1027 		if (keyslot1)
1028 			LoadBlob_UINT32(outOffset, *keyslot1, out_blob);
1029 		if (keyslot2)
1030 			LoadBlob_UINT32(outOffset, *keyslot2, out_blob);
1031 		//LoadBlob_UINT32(outOffset, in_len1, out_blob);
1032 		if (in_blob1)
1033 			LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1034 
1035 		if (auth1 && auth2) {
1036 			LoadBlob_Auth(outOffset, out_blob, auth1);
1037 			LoadBlob_Auth(outOffset, out_blob, auth2);
1038 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ord1, out_blob);
1039 		} else if (auth1) {
1040 			LoadBlob_Auth(outOffset, out_blob, auth1);
1041 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ord1, out_blob);
1042 		} else if (auth2) {
1043 			LoadBlob_Auth(outOffset, out_blob, auth2);
1044 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ord1, out_blob);
1045 		} else {
1046 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ord1, out_blob);
1047 		}
1048 
1049 		break;
1050 	}
1051 #endif
1052 	/* 1 UINT32, 1 UINT16, 1 BLOB, 1 UINT32, 1 BLOB, 1 options AUTH, 1 AUTH */
1053 	case TPM_ORD_CreateMigrationBlob:
1054 	{
1055 		UINT32 keyslot1 = va_arg(ap, UINT32);
1056 		UINT16 type1 = va_arg(ap, int);
1057 		UINT32 in_len1 = va_arg(ap, UINT32);
1058 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1059 		UINT32 in_len2 = va_arg(ap, UINT32);
1060 		BYTE *in_blob2 = va_arg(ap, BYTE *);
1061 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1062 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
1063 		va_end(ap);
1064 
1065 		if (!in_blob1 || !in_blob2 || !auth2) {
1066 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1067 			LogError("Internal error for ordinal 0x%x", ordinal);
1068 			break;
1069 		}
1070 
1071 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1072 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
1073 		LoadBlob_UINT16(outOffset, type1, out_blob);
1074 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1075 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
1076 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
1077 		if (auth1) {
1078 			LoadBlob_Auth(outOffset, out_blob, auth1);
1079 			LoadBlob_Auth(outOffset, out_blob, auth2);
1080 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
1081 		} else {
1082 			LoadBlob_Auth(outOffset, out_blob, auth2);
1083 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1084 		}
1085 
1086 		break;
1087 	}
1088 	/* 1 UINT32, 1 UINT16, 1 20 byte value, 1 UINT16, 1 UINT32, 1 BLOB, 2 AUTHs */
1089 	case TPM_ORD_ChangeAuth:
1090 	{
1091 		UINT32 keyslot1 = va_arg(ap, UINT32);
1092 		UINT16 proto1 = va_arg(ap, int);
1093 		BYTE *digest1 = va_arg(ap, BYTE *);
1094 		UINT16 entity1 = va_arg(ap, int);
1095 		UINT32 in_len1 = va_arg(ap, UINT32);
1096 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1097 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1098 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
1099 		va_end(ap);
1100 
1101 		if (!digest1 || !in_blob1 || !auth1 || !auth2) {
1102 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1103 			LogError("Internal error for ordinal 0x%x", ordinal);
1104 			break;
1105 		}
1106 
1107 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1108 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
1109 		LoadBlob_UINT16(outOffset, proto1, out_blob);
1110 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1111 		LoadBlob_UINT16(outOffset, entity1, out_blob);
1112 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1113 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1114 		LoadBlob_Auth(outOffset, out_blob, auth1);
1115 		LoadBlob_Auth(outOffset, out_blob, auth2);
1116 		LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
1117 
1118 		break;
1119 	}
1120 	/* 2 DIGEST/ENCAUTH's, 1 UINT32, 1 BLOB, 1 optional AUTH, 1 AUTH */
1121 	case TPM_ORD_MakeIdentity:
1122 	{
1123 		BYTE *dig1, *dig2, *blob1;
1124 		UINT32 len1;
1125 		TPM_AUTH *auth1, *auth2;
1126 
1127 		dig1 = va_arg(ap, BYTE *);
1128 		dig2 = va_arg(ap, BYTE *);
1129 		len1 = va_arg(ap, UINT32);
1130 		blob1 = va_arg(ap, BYTE *);
1131 		auth1 = va_arg(ap, TPM_AUTH *);
1132 		auth2 = va_arg(ap, TPM_AUTH *);
1133 		va_end(ap);
1134 
1135 		if (!dig1 || !dig2 || !blob1 || !auth2) {
1136 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1137 			LogError("Internal error for ordinal 0x%x", ordinal);
1138 			break;
1139 		}
1140 
1141 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1142 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, dig1);
1143 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, dig2);
1144 		LoadBlob(outOffset, len1, out_blob, blob1);
1145 		if (auth1) {
1146 			LoadBlob_Auth(outOffset, out_blob, auth1);
1147 			LoadBlob_Auth(outOffset, out_blob, auth2);
1148 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
1149 		} else {
1150 			LoadBlob_Auth(outOffset, out_blob, auth2);
1151 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1152 		}
1153 
1154 		break;
1155 	}
1156 #if (TSS_BUILD_NV || TSS_BUILD_DELEGATION)
1157 	/* 3 UINT32's, 1 BLOB, 1 optional AUTH */
1158 	case TPM_ORD_NV_WriteValue:
1159 	case TPM_ORD_NV_WriteValueAuth:
1160 	case TPM_ORD_Delegate_Manage:
1161 	{
1162 		UINT32 i = va_arg(ap, UINT32);
1163 		UINT32 j = va_arg(ap, UINT32);
1164 		UINT32 in_len1 = va_arg(ap, UINT32);
1165 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1166 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1167 		va_end(ap);
1168 
1169 		if (!in_blob1) {
1170 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1171 			LogError("Internal error for ordinal 0x%x", ordinal);
1172 			break;
1173 		}
1174 
1175 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1176 		LoadBlob_UINT32(outOffset, i, out_blob);
1177 		LoadBlob_UINT32(outOffset, j, out_blob);
1178 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1179 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1180 		if (auth1) {
1181 			LoadBlob_Auth(outOffset, out_blob, auth1);
1182 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1183 		} else {
1184 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1185 		}
1186 
1187 		break;
1188 	}
1189 #endif
1190 	/* 3 UINT32's, 1 optional AUTH */
1191 	case TPM_ORD_NV_ReadValue:
1192 	case TPM_ORD_NV_ReadValueAuth:
1193 	case TPM_ORD_SetRedirection:
1194 	{
1195 		UINT32 i = va_arg(ap, UINT32);
1196 		UINT32 j = va_arg(ap, UINT32);
1197 		UINT32 k = va_arg(ap, UINT32);
1198 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1199 		va_end(ap);
1200 
1201 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1202 		LoadBlob_UINT32(outOffset, i, out_blob);
1203 		LoadBlob_UINT32(outOffset, j, out_blob);
1204 		LoadBlob_UINT32(outOffset, k, out_blob);
1205 		if (auth1) {
1206 			LoadBlob_Auth(outOffset, out_blob, auth1);
1207 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1208 		} else {
1209 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1210 		}
1211 
1212 		break;
1213 	}
1214 	/* 1 20 byte value, 1 UINT32, 1 BLOB */
1215 	case TPM_ORD_CreateEndorsementKeyPair:
1216 	{
1217 		BYTE *digest1 = va_arg(ap, BYTE *);
1218 		UINT32 in_len1 = va_arg(ap, UINT32);
1219 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1220 		va_end(ap);
1221 
1222 		if (!digest1 || !in_blob1) {
1223 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1224 			LogError("Internal error for ordinal 0x%x", ordinal);
1225 			break;
1226 		}
1227 
1228 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1229 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1230 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1231 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1232 
1233 		break;
1234 	}
1235 #ifdef TSS_BUILD_TSS12
1236 	/* 1 20 byte value, 1 UINT32, 1 BLOB, 1 BOOL, 1 20 byte value */
1237 	case TPM_ORD_CreateRevocableEK:
1238 	{
1239 		BYTE *digest1 = va_arg(ap, BYTE *);
1240 		UINT32 in_len1 = va_arg(ap, UINT32);
1241 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1242 		TSS_BOOL in_bool1 = va_arg(ap, int);
1243 		BYTE *digest2 = va_arg(ap, BYTE *);
1244 		va_end(ap);
1245 
1246 		if (!digest1 || !in_blob1 || !digest2) {
1247 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1248 			LogError("Internal error for ordinal 0x%x", ordinal);
1249 			break;
1250 		}
1251 
1252 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1253 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1254 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1255 		LoadBlob_BOOL(outOffset, in_bool1, out_blob);
1256 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
1257 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1258 
1259 		break;
1260 	}
1261 	/* 1 20 byte value */
1262 	case TPM_ORD_RevokeTrust:
1263 	{
1264 		BYTE *digest1 = va_arg(ap, BYTE *);
1265 		va_end(ap);
1266 
1267 		if (!digest1) {
1268 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1269 			LogError("Internal error for ordinal 0x%x", ordinal);
1270 			break;
1271 		}
1272 
1273 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1274 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1275 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1276 
1277 		break;
1278 	}
1279 #endif
1280 #ifdef TSS_BUILD_COUNTER
1281 	/* 1 20 byte value, 1 UINT32, 1 BLOB, 1 AUTH */
1282 	case TPM_ORD_CreateCounter:
1283 	{
1284 		BYTE *digest1 = va_arg(ap, BYTE *);
1285 		UINT32 in_len1 = va_arg(ap, UINT32);
1286 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1287 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1288 		va_end(ap);
1289 
1290 		if (!digest1 || !in_blob1 || !auth1) {
1291 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1292 			LogError("Internal error for ordinal 0x%x", ordinal);
1293 			break;
1294 		}
1295 
1296 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1297 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1298 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1299 		LoadBlob_Auth(outOffset, out_blob, auth1);
1300 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1301 
1302 		break;
1303 	}
1304 #endif
1305 #ifdef TSS_BUILD_DAA
1306 	/* 1 UINT32, 1 BYTE, 1 UINT32, 1 BLOB, 1 UINT32, 1 BLOB, 1 AUTH */
1307 	case TPM_ORD_DAA_Sign:
1308 	case TPM_ORD_DAA_Join:
1309 	{
1310 		UINT32 keySlot1 = va_arg(ap, UINT32);
1311 		BYTE stage1 = va_arg(ap, int);
1312 		UINT32 in_len1 = va_arg(ap, UINT32);
1313 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1314 		UINT32 in_len2 = va_arg(ap, UINT32);
1315 		BYTE *in_blob2 = va_arg(ap, BYTE *);
1316 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1317 		va_end(ap);
1318 
1319 		if (!keySlot1 || !in_blob1 || !auth1) {
1320 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1321 			LogError("Internal error for ordinal 0x%x", ordinal);
1322 			break;
1323 		}
1324 
1325 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1326 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1327 		LoadBlob_BOOL(outOffset, stage1, out_blob);
1328 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1329 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1330 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
1331 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
1332 		LoadBlob_Auth(outOffset, out_blob, auth1);
1333 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1334 
1335 		break;
1336 	}
1337 #endif
1338 	/* 2 UINT32's, 1 BLOB, 1 UINT32, 1 BLOB, 1 optional AUTH */
1339 	case TPM_ORD_ConvertMigrationBlob:
1340 	case TPM_ORD_SetCapability:
1341 	{
1342 		UINT32 keySlot1 = va_arg(ap, UINT32);
1343 		UINT32 in_len1 = va_arg(ap, UINT32);
1344 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1345 		UINT32 in_len2 = va_arg(ap, UINT32);
1346 		BYTE *in_blob2 = va_arg(ap, BYTE *);
1347 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1348 		va_end(ap);
1349 
1350 		if (!keySlot1 || !in_blob1 || !in_blob2) {
1351 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1352 			LogError("Internal error for ordinal 0x%x", ordinal);
1353 			break;
1354 		}
1355 
1356 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1357 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1358 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1359 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1360 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
1361 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
1362 		if (auth1) {
1363 			LoadBlob_Auth(outOffset, out_blob, auth1);
1364 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1365 		} else {
1366 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1367 		}
1368 
1369 		break;
1370 	}
1371 	/* 2 UINT32's, 1 20 byte value, 2 optional AUTHs */
1372 	case TPM_ORD_CertifyKey:
1373 	{
1374 		UINT32 keySlot1 = va_arg(ap, UINT32);
1375 		UINT32 keySlot2 = va_arg(ap, UINT32);
1376 		BYTE *digest1 = va_arg(ap, BYTE *);
1377 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1378 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
1379 		va_end(ap);
1380 
1381 		if (!keySlot1 || !keySlot2 || !digest1) {
1382 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1383 			LogError("Internal error for ordinal 0x%x", ordinal);
1384 			break;
1385 		}
1386 
1387 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1388 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1389 		LoadBlob_UINT32(outOffset, keySlot2, out_blob);
1390 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1391 		if (auth1 && auth2) {
1392 			LoadBlob_Auth(outOffset, out_blob, auth1);
1393 			LoadBlob_Auth(outOffset, out_blob, auth2);
1394 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
1395 		} else if (auth1) {
1396 			LoadBlob_Auth(outOffset, out_blob, auth1);
1397 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1398 		} else if (auth2) {
1399 			LoadBlob_Auth(outOffset, out_blob, auth2);
1400 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1401 		} else {
1402 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1403 		}
1404 
1405 		break;
1406 	}
1407 	/* 2 UINT32's, 1 BLOB, 1 optional AUTH */
1408 	case TPM_ORD_Delegate_LoadOwnerDelegation:
1409 	case TPM_ORD_GetCapability:
1410 	case TPM_ORD_UnBind:
1411 	case TPM_ORD_Sign:
1412 	{
1413 		UINT32 keySlot1 = va_arg(ap, UINT32);
1414 		UINT32 in_len1 = va_arg(ap, UINT32);
1415 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1416 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1417 		va_end(ap);
1418 
1419 		if (in_len1 && !in_blob1) {
1420 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1421 			LogError("Internal error for ordinal 0x%x", ordinal);
1422 			break;
1423 		}
1424 
1425 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1426 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1427 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1428 		if (in_len1)
1429 			LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1430 		if (auth1) {
1431 			LoadBlob_Auth(outOffset, out_blob, auth1);
1432 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1433 		} else {
1434 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1435 		}
1436 
1437 		break;
1438 	}
1439 	/* 1 UINT32, 1 20 byte value, 1 UINT32, 1 optional BLOB, 1 UINT32, 1 BLOB, 1 AUTH */
1440 	case TPM_ORD_Seal:
1441 	case TPM_ORD_Sealx:
1442 	{
1443 		UINT32 keySlot1 = va_arg(ap, UINT32);
1444 		BYTE *digest1 = va_arg(ap, BYTE *);
1445 		UINT32 in_len1 = va_arg(ap, UINT32);
1446 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1447 		UINT32 in_len2 = va_arg(ap, UINT32);
1448 		BYTE *in_blob2 = va_arg(ap, BYTE *);
1449 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1450 		va_end(ap);
1451 
1452 		blob_size = in_len1 + in_len2 + TPM_DIGEST_SIZE + sizeof(TPM_AUTH);
1453 		if (blob_size > TSS_TPM_TXBLOB_SIZE) {
1454 			result = TCSERR(TSS_E_BAD_PARAMETER);
1455 			LogError("Oversized input when building ordinal 0x%x", ordinal);
1456 			break;
1457 		}
1458 
1459 		if (!keySlot1 || !in_blob2 || !auth1) {
1460 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1461 			LogError("Internal error for ordinal 0x%x", ordinal);
1462 			break;
1463 		}
1464 
1465 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1466 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1467 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1468 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1469 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1470 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
1471 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
1472 		LoadBlob_Auth(outOffset, out_blob, auth1);
1473 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1474 
1475 		break;
1476 	}
1477 	/* 2 UINT32's, 1 BLOB, 1 optional AUTH, 1 AUTH */
1478 	case TPM_ORD_ActivateIdentity:
1479 	{
1480 		UINT32 keySlot1 = va_arg(ap, UINT32);
1481 		UINT32 in_len1 = va_arg(ap, UINT32);
1482 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1483 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1484 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
1485 		va_end(ap);
1486 
1487 		if (!keySlot1 || !in_blob1 || !auth2) {
1488 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1489 			LogError("Internal error for ordinal 0x%x", ordinal);
1490 			break;
1491 		}
1492 
1493 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1494 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1495 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1496 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1497 		if (auth1) {
1498 			LoadBlob_Auth(outOffset, out_blob, auth1);
1499 			LoadBlob_Auth(outOffset, out_blob, auth2);
1500 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
1501 		} else {
1502 			LoadBlob_Auth(outOffset, out_blob, auth2);
1503 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1504 		}
1505 
1506 		break;
1507 	}
1508 	/* 1 UINT32, 1 20-byte blob, 1 BLOB, 1 optional AUTH */
1509 	case TPM_ORD_Quote:
1510 	{
1511 		UINT32 keySlot1 = va_arg(ap, UINT32);
1512 		BYTE *digest1 = va_arg(ap, BYTE *);
1513 		UINT32 in_len1 = va_arg(ap, UINT32);
1514 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1515 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1516 		va_end(ap);
1517 
1518 		if (!keySlot1 || !digest1 || !in_blob1) {
1519 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1520 			LogError("Internal error for ordinal 0x%x", ordinal);
1521 			break;
1522 		}
1523 
1524 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1525 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1526 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1527 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1528 
1529 		if (auth1) {
1530 			LoadBlob_Auth(outOffset, out_blob, auth1);
1531 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1532 		} else
1533 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1534 
1535 		break;
1536 	}
1537 #ifdef TSS_BUILD_TSS12
1538 	/* 1 UINT32, 1 20-byte blob, 1 BLOB, 1 BOOL, 1 optional AUTH */
1539 	case TPM_ORD_Quote2:
1540 	{
1541 		/* Input vars */
1542 		UINT32 keySlot1 = va_arg(ap, UINT32);
1543 		BYTE *digest1 = va_arg(ap, BYTE *);
1544 		UINT32 in_len1 = va_arg(ap, UINT32);
1545 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1546 		TSS_BOOL* addVersion = va_arg(ap,TSS_BOOL *);
1547 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1548 		va_end(ap);
1549 
1550 		if (!keySlot1 || !digest1 || !in_blob1 || !addVersion) {
1551 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1552 			LogError("Internal error for ordinal 0x%x", ordinal);
1553 			break;
1554 		}
1555 
1556 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1557 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1558 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1559 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1560 
1561 		/* Load the addVersion Bool */
1562 		LoadBlob_BOOL(outOffset,*addVersion,out_blob);
1563 
1564 		if (auth1) {
1565 			LoadBlob_Auth(outOffset, out_blob, auth1);
1566 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1567 		} else
1568 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1569 
1570 		break;
1571 	}
1572 #endif
1573 	/* 1 UINT32, 2 20-byte blobs, 1 BLOB, 1 optional AUTH */
1574 	case TPM_ORD_CreateWrapKey:
1575 	{
1576 		UINT32 keySlot1 = va_arg(ap, UINT32);
1577 		BYTE *digest1 = va_arg(ap, BYTE *);
1578 		BYTE *digest2 = va_arg(ap, BYTE *);
1579 		UINT32 in_len1 = va_arg(ap, UINT32);
1580 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1581 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1582 		va_end(ap);
1583 
1584 		if (!keySlot1 || !digest1 || !digest2 || !in_blob1) {
1585 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1586 			LogError("Internal error for ordinal 0x%x", ordinal);
1587 			break;
1588 		}
1589 
1590 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1591 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1592 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1593 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
1594 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1595 		if (auth1) {
1596 			LoadBlob_Auth(outOffset, out_blob, auth1);
1597 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1598 		} else
1599 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1600 
1601 		break;
1602 	}
1603 	/* 2 BLOBs, 1 optional AUTH */
1604 	case TPM_ORD_NV_DefineSpace:
1605 	case TPM_ORD_LoadManuMaintPub:
1606 	{
1607 		UINT32 in_len1 = va_arg(ap, UINT32);
1608 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1609 		UINT32 in_len2 = va_arg(ap, UINT32);
1610 		BYTE *in_blob2 = va_arg(ap, BYTE *);
1611 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1612 		va_end(ap);
1613 
1614 		if (!in_blob1 || !in_blob2) {
1615 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1616 			LogError("Internal error for ordinal 0x%x", ordinal);
1617 			break;
1618 		}
1619 
1620 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1621 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1622 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
1623 		if (auth1) {
1624 			LoadBlob_Auth(outOffset, out_blob, auth1);
1625 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1626 		} else {
1627 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1628 		}
1629 
1630 		break;
1631 	}
1632 #ifdef TSS_BUILD_TICK
1633 	/* 1 UINT32, 2 20-byte blobs, 1 optional AUTH */
1634 	case TPM_ORD_TickStampBlob:
1635 	{
1636 		UINT32 keySlot1 = va_arg(ap, UINT32);
1637 		BYTE *digest1 = va_arg(ap, BYTE *);
1638 		BYTE *digest2 = va_arg(ap, BYTE *);
1639 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1640 		va_end(ap);
1641 
1642 		if (!keySlot1 || !digest1 || !digest2) {
1643 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1644 			LogError("Internal error for ordinal 0x%x", ordinal);
1645 			break;
1646 		}
1647 
1648 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1649 		LoadBlob_UINT32(outOffset, keySlot1, out_blob);
1650 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1651 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
1652 
1653 		if (auth1) {
1654 			LoadBlob_Auth(outOffset, out_blob, auth1);
1655 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1656 		} else
1657 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1658 
1659 		break;
1660 	}
1661 #endif
1662 	/* 1 BLOB */
1663 	case TPM_ORD_ReadManuMaintPub:
1664 	case TPM_ORD_ReadPubek:
1665 	case TPM_ORD_PCR_Reset:
1666 	case TPM_ORD_SetOperatorAuth:
1667 	{
1668 		UINT32 in_len1 = va_arg(ap, UINT32);
1669 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1670 		va_end(ap);
1671 
1672 		if (!in_blob1) {
1673 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1674 			LogError("Internal error for ordinal 0x%x", ordinal);
1675 			break;
1676 		}
1677 
1678 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1679 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1680 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1681 
1682 		break;
1683 	}
1684 	/* 1 UINT32, 1 BLOB, 2 optional AUTHs */
1685 	case TPM_ORD_LoadKey:
1686 	case TPM_ORD_LoadKey2:
1687 	case TPM_ORD_DirWriteAuth:
1688 	case TPM_ORD_CertifySelfTest:
1689 	case TPM_ORD_Unseal:
1690 	case TPM_ORD_Extend:
1691 	case TPM_ORD_StirRandom:
1692 	case TPM_ORD_LoadMaintenanceArchive: /* XXX */
1693 	case TPM_ORD_FieldUpgrade:
1694 	case TPM_ORD_Delegate_UpdateVerification:
1695 	case TPM_ORD_Delegate_VerifyDelegation:
1696 	{
1697 		UINT32 val1 = va_arg(ap, UINT32);
1698 		UINT32 in_len1 = va_arg(ap, UINT32);
1699 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1700 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1701 		TPM_AUTH *auth2 = va_arg(ap, TPM_AUTH *);
1702 		va_end(ap);
1703 
1704 		if (in_len1 && !in_blob1) {
1705 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1706 			LogError("Internal error for ordinal 0x%x", ordinal);
1707 			break;
1708 		}
1709 
1710 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1711 		LoadBlob_UINT32(outOffset, val1, out_blob);
1712 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1713 		if (auth1 && auth2) {
1714 			LoadBlob_Auth(outOffset, out_blob, auth1);
1715 			LoadBlob_Auth(outOffset, out_blob, auth2);
1716 			LoadBlob_Header(TPM_TAG_RQU_AUTH2_COMMAND, *outOffset, ordinal, out_blob);
1717 		} else if (auth1) {
1718 			LoadBlob_Auth(outOffset, out_blob, auth1);
1719 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1720 		} else if (auth2) {
1721 			LoadBlob_Auth(outOffset, out_blob, auth2);
1722 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1723 		} else {
1724 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1725 		}
1726 
1727 		break;
1728 	}
1729 	/* 1 UINT16, 1 BLOB, 1 AUTH */
1730 	case TPM_ORD_AuthorizeMigrationKey:
1731 	{
1732 		UINT16 scheme1 = va_arg(ap, int);
1733 		UINT32 in_len1 = va_arg(ap, UINT32);
1734 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1735 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1736 		va_end(ap);
1737 
1738 		if (!in_blob1 || !auth1) {
1739 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1740 			LogError("Internal error for ordinal 0x%x", ordinal);
1741 			break;
1742 		}
1743 
1744 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1745 		LoadBlob_UINT16(outOffset, scheme1, out_blob);
1746 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1747 		LoadBlob_Auth(outOffset, out_blob, auth1);
1748 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1749 
1750 		break;
1751 	}
1752 	/* 1 UINT16, 1 UINT32, 1 BLOB, 1 UINT32, 2 BLOBs, 1 AUTH */
1753 	case TPM_ORD_TakeOwnership:
1754 	{
1755 		UINT16 scheme1 = va_arg(ap, int);
1756 		UINT32 in_len1 = va_arg(ap, UINT32);
1757 		BYTE *in_blob1 = va_arg(ap, BYTE *);
1758 		UINT32 in_len2 = va_arg(ap, UINT32);
1759 		BYTE *in_blob2 = va_arg(ap, BYTE *);
1760 		UINT32 in_len3 = va_arg(ap, UINT32);
1761 		BYTE *in_blob3 = va_arg(ap, BYTE *);
1762 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1763 		va_end(ap);
1764 
1765 		if (!in_blob1 || !in_blob2 || !in_blob3 || !auth1) {
1766 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1767 			LogError("Internal error for ordinal 0x%x", ordinal);
1768 			break;
1769 		}
1770 
1771 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1772 		LoadBlob_UINT16(outOffset, scheme1, out_blob);
1773 		LoadBlob_UINT32(outOffset, in_len1, out_blob);
1774 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
1775 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
1776 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
1777 		LoadBlob(outOffset, in_len3, out_blob, in_blob3);
1778 		LoadBlob_Auth(outOffset, out_blob, auth1);
1779 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1780 
1781 		break;
1782 	}
1783 #ifdef TSS_BUILD_AUDIT
1784 	/* 1 UINT32, 1 BOOL, 1 20 byte value, 1 optional AUTH */
1785 	case TPM_ORD_GetAuditDigestSigned:
1786 	{
1787 		UINT32 keyslot1 = va_arg(ap, UINT32);
1788 		TSS_BOOL bool1 = va_arg(ap, int);
1789 		BYTE *digest1 = va_arg(ap, BYTE *);
1790 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1791 		va_end(ap);
1792 
1793 		if (!digest1) {
1794 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1795 			LogError("Internal error for ordinal 0x%x", ordinal);
1796 			break;
1797 		}
1798 
1799 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1800 		LoadBlob_UINT32(outOffset, keyslot1, out_blob);
1801 		LoadBlob_BOOL(outOffset, bool1, out_blob);
1802 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1803 
1804 		if (auth1) {
1805 			LoadBlob_Auth(outOffset, out_blob, auth1);
1806 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1807 		} else {
1808 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1809 		}
1810 
1811 		break;
1812 	}
1813 #endif
1814 	/* 1 UINT16, 1 UINT32, 1 20 byte value */
1815 	case TPM_ORD_OSAP:
1816 	{
1817 		UINT16 type1 = va_arg(ap, int);
1818 		UINT32 value1 = va_arg(ap, UINT32);
1819 		BYTE *digest1 = va_arg(ap, BYTE *);
1820 		va_end(ap);
1821 
1822 		if (!digest1) {
1823 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1824 			LogError("Internal error for ordinal 0x%x", ordinal);
1825 			break;
1826 		}
1827 
1828 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1829 		LoadBlob_UINT16(outOffset, type1, out_blob);
1830 		LoadBlob_UINT32(outOffset, value1, out_blob);
1831 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1832 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1833 
1834 		break;
1835 	}
1836 	/* 1 UINT16, 1 20 byte value, 1 UINT16, 1 AUTH */
1837 	case TPM_ORD_ChangeAuthOwner:
1838 	{
1839 		UINT16 type1 = va_arg(ap, int);
1840 		BYTE *digest1 = va_arg(ap, BYTE *);
1841 		UINT16 type2 = va_arg(ap, int);
1842 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1843 		va_end(ap);
1844 
1845 		if (!digest1 || !auth1) {
1846 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1847 			LogError("Internal error for ordinal 0x%x", ordinal);
1848 			break;
1849 		}
1850 
1851 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1852 		LoadBlob_UINT16(outOffset, type1, out_blob);
1853 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1854 		LoadBlob_UINT16(outOffset, type2, out_blob);
1855 		LoadBlob_Auth(outOffset, out_blob, auth1);
1856 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1857 
1858 		break;
1859 	}
1860 #ifdef TSS_BUILD_AUDIT
1861 	/* 1 UINT32, 1 BOOL, 1 AUTH */
1862 	case TPM_ORD_SetOrdinalAuditStatus:
1863 	{
1864 		UINT32 ord1 = va_arg(ap, UINT32);
1865 		TSS_BOOL bool1 = va_arg(ap, int);
1866 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1867 		va_end(ap);
1868 
1869 		if (!auth1) {
1870 			result = TCSERR(TSS_E_INTERNAL_ERROR);
1871 			LogError("Internal error for ordinal 0x%x", ordinal);
1872 			break;
1873 		}
1874 
1875 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1876 		LoadBlob_UINT32(outOffset, ord1, out_blob);
1877 		LoadBlob_BOOL(outOffset, bool1, out_blob);
1878 		LoadBlob_Auth(outOffset, out_blob, auth1);
1879 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1880 
1881 		break;
1882 	}
1883 #endif
1884 	/* 1 BOOL, 1 optional AUTH */
1885 	case TPM_ORD_OwnerSetDisable:
1886 	case TPM_ORD_PhysicalSetDeactivated:
1887 	case TPM_ORD_CreateMaintenanceArchive:
1888 	case TPM_ORD_SetOwnerInstall:
1889 	{
1890 		TSS_BOOL bool1 = va_arg(ap, int);
1891 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1892 		va_end(ap);
1893 
1894 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1895 		LoadBlob_BOOL(outOffset, bool1, out_blob);
1896 		if (auth1) {
1897 			LoadBlob_Auth(outOffset, out_blob, auth1);
1898 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1899 		} else {
1900 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1901 		}
1902 
1903 		break;
1904 	}
1905 	/* 1 optional AUTH */
1906 	case TPM_ORD_OwnerClear:
1907 	case TPM_ORD_DisablePubekRead:
1908 	case TPM_ORD_GetCapabilityOwner:
1909 	case TPM_ORD_ResetLockValue:
1910 	case TPM_ORD_DisableOwnerClear:
1911 	case TPM_ORD_SetTempDeactivated:
1912 	case TPM_ORD_OIAP:
1913 	case TPM_ORD_OwnerReadPubek:
1914 	case TPM_ORD_SelfTestFull:
1915 	case TPM_ORD_GetTicks:
1916 	case TPM_ORD_GetTestResult:
1917 	case TPM_ORD_KillMaintenanceFeature:
1918 	case TPM_ORD_Delegate_ReadTable:
1919 	case TPM_ORD_PhysicalEnable:
1920 	case TPM_ORD_DisableForceClear:
1921 	case TPM_ORD_ForceClear:
1922 	{
1923 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1924 		va_end(ap);
1925 
1926 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1927 		if (auth1) {
1928 			LoadBlob_Auth(outOffset, out_blob, auth1);
1929 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1930 		} else {
1931 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1932 		}
1933 
1934 		break;
1935 	}
1936 	/* 1 UINT32, 1 optional AUTH */
1937 	case TPM_ORD_OwnerReadInternalPub:
1938 	case TPM_ORD_GetPubKey:
1939 	case TPM_ORD_ReleaseCounterOwner:
1940 	case TPM_ORD_ReleaseCounter:
1941 	case TPM_ORD_IncrementCounter:
1942 	case TPM_ORD_PcrRead:
1943 	case TPM_ORD_DirRead:
1944 	case TPM_ORD_ReadCounter:
1945 	case TPM_ORD_Terminate_Handle:
1946 	case TPM_ORD_GetAuditDigest:
1947 	case TPM_ORD_GetRandom:
1948 	case TPM_ORD_CMK_SetRestrictions:
1949 	{
1950 		UINT32 i = va_arg(ap, UINT32);
1951 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1952 		va_end(ap);
1953 
1954 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1955 		LoadBlob_UINT32(outOffset, i, out_blob);
1956 		if (auth1) {
1957 			LoadBlob_Auth(outOffset, out_blob, auth1);
1958 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1959 		} else {
1960 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1961 		}
1962 
1963 		break;
1964 	}
1965 #ifdef TSS_BUILD_CMK
1966 	/* 1 20 byte value, 1 optional AUTH */
1967 	case TPM_ORD_CMK_ApproveMA:
1968 	{
1969 		BYTE *digest1 = va_arg(ap, BYTE *);
1970 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
1971 		va_end(ap);
1972 
1973 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1974 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
1975 		if (auth1) {
1976 			LoadBlob_Auth(outOffset, out_blob, auth1);
1977 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
1978 		} else {
1979 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1980 		}
1981 
1982 		break;
1983 	}
1984 #endif
1985 	/* 1 UINT16 only */
1986 	case TSC_ORD_PhysicalPresence:
1987 	{
1988 		UINT16 i = va_arg(ap, int);
1989 		va_end(ap);
1990 
1991 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
1992 		LoadBlob_UINT16(outOffset, i, out_blob);
1993 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
1994 
1995 		break;
1996 	}
1997 #ifdef TSS_BUILD_CMK
1998 	/* 1 UINT32, 1 20 byte value, 1 BLOB, 2 20 byte values, 1 optional AUTH */
1999 	case TPM_ORD_CMK_CreateKey:
2000 	{
2001 		UINT32 key1 = va_arg(ap, UINT32);
2002 		BYTE *digest1 = va_arg(ap, BYTE *);
2003 		UINT32 in_len1 = va_arg(ap, UINT32);
2004 		BYTE *in_blob1 = va_arg(ap, BYTE *);
2005 		BYTE *digest2 = va_arg(ap, BYTE *);
2006 		BYTE *digest3 = va_arg(ap, BYTE *);
2007 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
2008 		va_end(ap);
2009 
2010 		if (!digest1 || !in_blob1 || !digest2 || !digest3) {
2011 			result = TCSERR(TSS_E_INTERNAL_ERROR);
2012 			LogError("Internal error for ordinal 0x%x", ordinal);
2013 			break;
2014 		}
2015 
2016 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
2017 		LoadBlob_UINT32(outOffset, key1, out_blob);
2018 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
2019 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
2020 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest2);
2021 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest3);
2022 		if (auth1) {
2023 			LoadBlob_Auth(outOffset, out_blob, auth1);
2024 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
2025 		} else {
2026 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
2027 		}
2028 
2029 		break;
2030 	}
2031 	/* 1 BLOB, 1 20 byte value, 1 UINT32, 1 BLOB, 1 optional AUTH */
2032 	case TPM_ORD_CMK_CreateTicket:
2033 	{
2034 		UINT32 in_len1 = va_arg(ap, UINT32);
2035 		BYTE *in_blob1 = va_arg(ap, BYTE *);
2036 		BYTE *digest1 = va_arg(ap, BYTE *);
2037 		UINT32 in_len2 = va_arg(ap, UINT32);
2038 		BYTE *in_blob2 = va_arg(ap, BYTE *);
2039 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
2040 		va_end(ap);
2041 
2042 		if (!digest1 || !in_blob1 || !in_blob2) {
2043 			result = TCSERR(TSS_E_INTERNAL_ERROR);
2044 			LogError("Internal error for ordinal 0x%x", ordinal);
2045 			break;
2046 		}
2047 
2048 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
2049 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
2050 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
2051 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
2052 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
2053 		if (auth1) {
2054 			LoadBlob_Auth(outOffset, out_blob, auth1);
2055 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
2056 		} else {
2057 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
2058 		}
2059 
2060 		break;
2061 	}
2062 	/* 1 UINT32, 1 UINT16, 1 BLOB, 1 20 byte value, 4 x (1 UINT32, 1 BLOB), 1 optional AUTH */
2063 	case TPM_ORD_CMK_CreateBlob:
2064 	{
2065 		UINT32 in_key1 = va_arg(ap, UINT32);
2066 		UINT16 i = va_arg(ap, int);
2067 		UINT32 in_len1 = va_arg(ap, UINT32);
2068 		BYTE *in_blob1 = va_arg(ap, BYTE *);
2069 		BYTE *digest1 = va_arg(ap, BYTE *);
2070 		UINT32 in_len2 = va_arg(ap, UINT32);
2071 		BYTE *in_blob2 = va_arg(ap, BYTE *);
2072 		UINT32 in_len3 = va_arg(ap, UINT32);
2073 		BYTE *in_blob3 = va_arg(ap, BYTE *);
2074 		UINT32 in_len4 = va_arg(ap, UINT32);
2075 		BYTE *in_blob4 = va_arg(ap, BYTE *);
2076 		UINT32 in_len5 = va_arg(ap, UINT32);
2077 		BYTE *in_blob5 = va_arg(ap, BYTE *);
2078 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
2079 		va_end(ap);
2080 
2081 		if (!digest1 || !in_blob1 || !in_blob2 || !in_blob3 || !in_blob4 || !in_blob5) {
2082 			result = TCSERR(TSS_E_INTERNAL_ERROR);
2083 			LogError("Internal error for ordinal 0x%x", ordinal);
2084 			break;
2085 		}
2086 
2087 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
2088 		LoadBlob_UINT32(outOffset, in_key1, out_blob);
2089 		LoadBlob_UINT16(outOffset, i, out_blob);
2090 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
2091 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
2092 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
2093 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
2094 		LoadBlob_UINT32(outOffset, in_len3, out_blob);
2095 		LoadBlob(outOffset, in_len3, out_blob, in_blob3);
2096 		LoadBlob_UINT32(outOffset, in_len4, out_blob);
2097 		LoadBlob(outOffset, in_len4, out_blob, in_blob4);
2098 		LoadBlob_UINT32(outOffset, in_len5, out_blob);
2099 		LoadBlob(outOffset, in_len5, out_blob, in_blob5);
2100 		if (auth1) {
2101 			LoadBlob_Auth(outOffset, out_blob, auth1);
2102 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
2103 		} else {
2104 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
2105 		}
2106 
2107 		break;
2108 	}
2109 	/* 1 UINT32, 1 60 byte value, 1 20 byte value, 1 BLOB, 2 x (1 UINT32, 1 BLOB),
2110 	 * 1 optional AUTH */
2111 	case TPM_ORD_CMK_ConvertMigration:
2112 	{
2113 		UINT32 key1 = va_arg(ap, UINT32);
2114 		BYTE *cmkauth1 = va_arg(ap, BYTE *);
2115 		BYTE *digest1 = va_arg(ap, BYTE *);
2116 		UINT32 in_len1 = va_arg(ap, UINT32);
2117 		BYTE *in_blob1 = va_arg(ap, BYTE *);
2118 		UINT32 in_len2 = va_arg(ap, UINT32);
2119 		BYTE *in_blob2 = va_arg(ap, BYTE *);
2120 		UINT32 in_len3 = va_arg(ap, UINT32);
2121 		BYTE *in_blob3 = va_arg(ap, BYTE *);
2122 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
2123 		va_end(ap);
2124 
2125 		if (!cmkauth1 || !digest1 || !in_blob1 || !in_blob2 || !in_blob3) {
2126 			result = TCSERR(TSS_E_INTERNAL_ERROR);
2127 			LogError("Internal error for ordinal 0x%x", ordinal);
2128 			break;
2129 		}
2130 
2131 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
2132 		LoadBlob_UINT32(outOffset, key1, out_blob);
2133 		LoadBlob(outOffset, 3 * TPM_SHA1_160_HASH_LEN, out_blob, cmkauth1);
2134 		LoadBlob(outOffset, TPM_SHA1_160_HASH_LEN, out_blob, digest1);
2135 		LoadBlob(outOffset, in_len1, out_blob, in_blob1);
2136 		LoadBlob_UINT32(outOffset, in_len2, out_blob);
2137 		LoadBlob(outOffset, in_len2, out_blob, in_blob2);
2138 		LoadBlob_UINT32(outOffset, in_len3, out_blob);
2139 		LoadBlob(outOffset, in_len3, out_blob, in_blob3);
2140 		if (auth1) {
2141 			LoadBlob_Auth(outOffset, out_blob, auth1);
2142 			LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
2143 		} else {
2144 			LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
2145 		}
2146 
2147 		break;
2148 	}
2149 #endif
2150 #ifdef TSS_BUILD_TSS12
2151 	case TPM_ORD_FlushSpecific:
2152 	{
2153 		UINT32 val1 = va_arg(ap, UINT32);
2154 		UINT32 val2 = va_arg(ap, UINT32);
2155 		va_end(ap);
2156 
2157 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
2158 		LoadBlob_UINT32(outOffset, val1, out_blob);
2159 		LoadBlob_UINT32(outOffset, val2, out_blob);
2160 		LoadBlob_Header(TPM_TAG_RQU_COMMAND, *outOffset, ordinal, out_blob);
2161 
2162 		break;
2163 	}
2164 	/* 1 UINT32, 1 BLOB, 1 UINT32, 1 BOOL, 1 AUTH */
2165 	case TPM_ORD_KeyControlOwner:
2166 	{
2167 		UINT32 i = va_arg(ap, UINT32);
2168 		UINT32 len1 = va_arg(ap, UINT32);
2169 		BYTE *blob1 = va_arg(ap, BYTE *);
2170 		UINT32 j = va_arg(ap, UINT32);
2171 		TSS_BOOL bool1 = va_arg(ap, int);
2172 		TPM_AUTH *auth1 = va_arg(ap, TPM_AUTH *);
2173 	        va_end(ap);
2174 
2175 		*outOffset += TSS_TPM_TXBLOB_HDR_LEN;
2176 		LoadBlob_UINT32(outOffset, i, out_blob);
2177 		LoadBlob(outOffset, len1, out_blob, blob1);
2178 		LoadBlob_UINT32(outOffset, j, out_blob);
2179 		LoadBlob_BOOL(outOffset, bool1, out_blob);
2180 		LoadBlob_Auth(outOffset, out_blob, auth1);
2181 		LoadBlob_Header(TPM_TAG_RQU_AUTH1_COMMAND, *outOffset, ordinal, out_blob);
2182 
2183 		break;
2184 	}
2185 #endif
2186 	default:
2187 		LogError("Unknown ordinal: 0x%x", ordinal);
2188 		break;
2189 	}
2190 
2191 	return result;
2192 }
2193