tcs_pbg.c revision 1.1.1.1.4.2
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
35TSS_RESULT
36tpm_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" */
915TSS_RESULT
916tpm_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