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