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 <string.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/mman.h>
19 #include <fcntl.h>
20 #include <errno.h>
21 
22 #include "trousers/tss.h"
23 #include "trousers_types.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 TCS_CONTEXT_HANDLE InternalContext = 0x30000000;
34 TSS_UUID SRK_UUID = TSS_UUID_SRK;
35 
36 
37 void
LogData(char * string,UINT32 data)38 LogData(char *string, UINT32 data)
39 {
40 #if 0
41           /* commenting out temporarily, logs getting too chatty */
42           LogDebug("%s %08x", string, data);
43 #endif
44 }
45 
46 void
LogResult(char * string,TCPA_RESULT result)47 LogResult(char *string, TCPA_RESULT result)
48 {
49 #if 0
50           /* commenting out temporarily, logs getting too chatty */
51           LogDebug("Leaving %s with result 0x%08x", string, result);
52 #endif
53 }
54 
55 UINT16
Decode_UINT16(BYTE * in)56 Decode_UINT16(BYTE * in)
57 {
58           UINT16 temp = 0;
59           temp = (in[1] & 0xFF);
60           temp |= (in[0] << 8);
61           return temp;
62 }
63 
64 void
UINT64ToArray(UINT64 i,BYTE * out)65 UINT64ToArray(UINT64 i, BYTE * out)
66 {
67           out[0] = (BYTE) ((i >> 56) & 0xFF);
68           out[1] = (BYTE) ((i >> 48) & 0xFF);
69           out[2] = (BYTE) ((i >> 40) & 0xFF);
70           out[3] = (BYTE) ((i >> 32) & 0xFF);
71           out[4] = (BYTE) ((i >> 24) & 0xFF);
72           out[5] = (BYTE) ((i >> 16) & 0xFF);
73           out[6] = (BYTE) ((i >> 8) & 0xFF);
74           out[7] = (BYTE) (i & 0xFF);
75 }
76 
77 void
UINT32ToArray(UINT32 i,BYTE * out)78 UINT32ToArray(UINT32 i, BYTE * out)
79 {
80           out[0] = (BYTE) ((i >> 24) & 0xFF);
81           out[1] = (BYTE) ((i >> 16) & 0xFF);
82           out[2] = (BYTE) ((i >> 8) & 0xFF);
83           out[3] = (BYTE) (i & 0xFF);
84 }
85 
86 void
UINT16ToArray(UINT16 i,BYTE * out)87 UINT16ToArray(UINT16 i, BYTE * out)
88 {
89           out[0] = (BYTE) ((i >> 8) & 0xFF);
90           out[1] = (BYTE) (i & 0xFF);
91 }
92 
93 UINT32
Decode_UINT32(BYTE * y)94 Decode_UINT32(BYTE * y)
95 {
96           UINT32 x = 0;
97 
98           x = y[0];
99           x = ((x << 8) | (y[1] & 0xFF));
100           x = ((x << 8) | (y[2] & 0xFF));
101           x = ((x << 8) | (y[3] & 0xFF));
102 
103           return x;
104 }
105 
106 UINT64
Decode_UINT64(BYTE * y)107 Decode_UINT64(BYTE *y)
108 {
109           UINT64 x = 0;
110 
111           x = y[0];
112           x = ((x << 8) | (y[1] & 0xFF));
113           x = ((x << 8) | (y[2] & 0xFF));
114           x = ((x << 8) | (y[3] & 0xFF));
115           x = ((x << 8) | (y[4] & 0xFF));
116           x = ((x << 8) | (y[5] & 0xFF));
117           x = ((x << 8) | (y[6] & 0xFF));
118           x = ((x << 8) | (y[7] & 0xFF));
119 
120           return x;
121 }
122 
123 void
LoadBlob_UINT64(UINT64 * offset,UINT64 in,BYTE * blob)124 LoadBlob_UINT64(UINT64 *offset, UINT64 in, BYTE * blob)
125 {
126           if (blob)
127                     UINT64ToArray(in, &blob[*offset]);
128           *offset += sizeof(UINT64);
129 }
130 
131 void
LoadBlob_UINT32(UINT64 * offset,UINT32 in,BYTE * blob)132 LoadBlob_UINT32(UINT64 *offset, UINT32 in, BYTE * blob)
133 {
134           if (blob)
135                     UINT32ToArray(in, &blob[*offset]);
136           *offset += sizeof(UINT32);
137 }
138 
139 void
LoadBlob_UINT16(UINT64 * offset,UINT16 in,BYTE * blob)140 LoadBlob_UINT16(UINT64 *offset, UINT16 in, BYTE * blob)
141 {
142           if (blob)
143                     UINT16ToArray(in, &blob[*offset]);
144           *offset += sizeof(UINT16);
145 }
146 
147 void
UnloadBlob_UINT64(UINT64 * offset,UINT64 * out,BYTE * blob)148 UnloadBlob_UINT64(UINT64 *offset, UINT64 * out, BYTE * blob)
149 {
150           if (out)
151                     *out = Decode_UINT64(&blob[*offset]);
152           *offset += sizeof(UINT64);
153 }
154 
155 void
UnloadBlob_UINT32(UINT64 * offset,UINT32 * out,BYTE * blob)156 UnloadBlob_UINT32(UINT64 *offset, UINT32 * out, BYTE * blob)
157 {
158           if (out)
159                     *out = Decode_UINT32(&blob[*offset]);
160           *offset += sizeof(UINT32);
161 }
162 
163 void
UnloadBlob_UINT16(UINT64 * offset,UINT16 * out,BYTE * blob)164 UnloadBlob_UINT16(UINT64 *offset, UINT16 * out, BYTE * blob)
165 {
166           if (out)
167                     *out = Decode_UINT16(&blob[*offset]);
168           *offset += sizeof(UINT16);
169 }
170 
171 void
LoadBlob_BYTE(UINT64 * offset,BYTE data,BYTE * blob)172 LoadBlob_BYTE(UINT64 *offset, BYTE data, BYTE * blob)
173 {
174           if (blob)
175                     blob[*offset] = data;
176           (*offset)++;
177 }
178 
179 void
UnloadBlob_BYTE(UINT64 * offset,BYTE * dataOut,BYTE * blob)180 UnloadBlob_BYTE(UINT64 *offset, BYTE * dataOut, BYTE * blob)
181 {
182           if (dataOut)
183                     *dataOut = blob[*offset];
184           (*offset)++;
185 }
186 
187 void
LoadBlob_BOOL(UINT64 * offset,TSS_BOOL data,BYTE * blob)188 LoadBlob_BOOL(UINT64 *offset, TSS_BOOL data, BYTE * blob)
189 {
190           if (blob)
191                     blob[*offset] = data;
192           (*offset)++;
193 }
194 
195 void
UnloadBlob_BOOL(UINT64 * offset,TSS_BOOL * dataOut,BYTE * blob)196 UnloadBlob_BOOL(UINT64 *offset, TSS_BOOL *dataOut, BYTE * blob)
197 {
198           if (dataOut)
199                     *dataOut = blob[*offset];
200           (*offset)++;
201 }
202 
203 void
LoadBlob(UINT64 * offset,UINT32 size,BYTE * container,BYTE * object)204 LoadBlob(UINT64 *offset, UINT32 size, BYTE *container, BYTE *object)
205 {
206           if (container)
207                     memcpy(&container[*offset], object, size);
208           (*offset) += (UINT64) size;
209 }
210 
211 void
UnloadBlob(UINT64 * offset,UINT32 size,BYTE * container,BYTE * object)212 UnloadBlob(UINT64 *offset, UINT32 size, BYTE *container, BYTE *object)
213 {
214           if (object)
215                     memcpy(object, &container[*offset], size);
216           (*offset) += (UINT64) size;
217 }
218 
219 void
LoadBlob_Header(UINT16 tag,UINT32 paramSize,UINT32 ordinal,BYTE * blob)220 LoadBlob_Header(UINT16 tag, UINT32 paramSize, UINT32 ordinal, BYTE * blob)
221 {
222 
223           UINT16ToArray(tag, &blob[0]);
224           LogData("Header Tag:", tag);
225           UINT32ToArray(paramSize, &blob[2]);
226           LogData("Header ParamSize:", paramSize);
227           UINT32ToArray(ordinal, &blob[6]);
228           LogData("Header Ordinal:", ordinal);
229 #if 0
230           LogInfo("Blob's TPM Ordinal: 0x%x", ordinal);
231 #endif
232 }
233 
234 #ifdef TSS_DEBUG
235 TSS_RESULT
LogUnloadBlob_Header(BYTE * blob,UINT32 * size,char * file,int line)236 LogUnloadBlob_Header(BYTE * blob, UINT32 * size, char *file, int line)
237 {
238           TSS_RESULT result;
239 
240           UINT16 temp = Decode_UINT16(blob);
241           LogData("UnloadBlob_Tag:", (temp));
242           *size = Decode_UINT32(&blob[2]);
243           LogData("UnloadBlob_Header, size:", *size);
244           LogData("UnloadBlob_Header, returnCode:", Decode_UINT32(&blob[6]));
245 
246           if ((result = Decode_UINT32(&blob[6]))) {
247                     LogTPMERR(result, file, line);
248           }
249 
250           return result;
251 }
252 #else
253 TSS_RESULT
UnloadBlob_Header(BYTE * blob,UINT32 * size)254 UnloadBlob_Header(BYTE * blob, UINT32 * size)
255 {
256           UINT16 temp = Decode_UINT16(blob);
257           LogData("UnloadBlob_Tag:", (temp));
258           *size = Decode_UINT32(&blob[2]);
259           LogData("UnloadBlob_Header, size:", *size);
260           LogData("UnloadBlob_Header, returnCode:", Decode_UINT32(&blob[6]));
261           return Decode_UINT32(&blob[6]);
262 }
263 #endif
264 
265 void
LoadBlob_Auth(UINT64 * offset,BYTE * blob,TPM_AUTH * auth)266 LoadBlob_Auth(UINT64 *offset, BYTE * blob, TPM_AUTH * auth)
267 {
268           LoadBlob_UINT32(offset, auth->AuthHandle, blob);
269           LoadBlob(offset, TCPA_NONCE_SIZE, blob, auth->NonceOdd.nonce);
270           LoadBlob_BOOL(offset, auth->fContinueAuthSession, blob);
271           LoadBlob(offset, TCPA_AUTHDATA_SIZE, blob, (BYTE *)&auth->HMAC);
272 }
273 
274 void
UnloadBlob_Auth(UINT64 * offset,BYTE * blob,TPM_AUTH * auth)275 UnloadBlob_Auth(UINT64 *offset, BYTE * blob, TPM_AUTH * auth)
276 {
277           if (!auth) {
278                     UnloadBlob(offset, TCPA_NONCE_SIZE, blob, NULL);
279                     UnloadBlob_BOOL(offset, NULL, blob);
280                     UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, NULL);
281 
282                     return;
283           }
284 
285           UnloadBlob(offset, TCPA_NONCE_SIZE, blob, auth->NonceEven.nonce);
286           UnloadBlob_BOOL(offset, &auth->fContinueAuthSession, blob);
287           UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, (BYTE *)&auth->HMAC);
288 }
289 
290 void
UnloadBlob_VERSION(UINT64 * offset,BYTE * blob,TPM_VERSION * out)291 UnloadBlob_VERSION(UINT64 *offset, BYTE *blob, TPM_VERSION *out)
292 {
293           if (!out) {
294                     *offset += (sizeof(BYTE) * 4);
295                     return;
296           }
297 
298           UnloadBlob_BYTE(offset, &out->major, blob);
299           UnloadBlob_BYTE(offset, &out->minor, blob);
300           UnloadBlob_BYTE(offset, &out->revMajor, blob);
301           UnloadBlob_BYTE(offset, &out->revMinor, blob);
302 }
303 
304 void
LoadBlob_VERSION(UINT64 * offset,BYTE * blob,TPM_VERSION * ver)305 LoadBlob_VERSION(UINT64 *offset, BYTE *blob, TPM_VERSION *ver)
306 {
307           LoadBlob_BYTE(offset, ver->major, blob);
308           LoadBlob_BYTE(offset, ver->minor, blob);
309           LoadBlob_BYTE(offset, ver->revMajor, blob);
310           LoadBlob_BYTE(offset, ver->revMinor, blob);
311 }
312 
313 void
UnloadBlob_TCPA_VERSION(UINT64 * offset,BYTE * blob,TCPA_VERSION * out)314 UnloadBlob_TCPA_VERSION(UINT64 *offset, BYTE *blob, TCPA_VERSION *out)
315 {
316           if (!out) {
317                     *offset += (sizeof(BYTE) * 4);
318                     return;
319           }
320 
321           UnloadBlob_BYTE(offset, &out->major, blob);
322           UnloadBlob_BYTE(offset, &out->minor, blob);
323           UnloadBlob_BYTE(offset, &out->revMajor, blob);
324           UnloadBlob_BYTE(offset, &out->revMinor, blob);
325 }
326 
327 void
LoadBlob_TCPA_VERSION(UINT64 * offset,BYTE * blob,TCPA_VERSION * ver)328 LoadBlob_TCPA_VERSION(UINT64 *offset, BYTE *blob, TCPA_VERSION *ver)
329 {
330           LoadBlob_BYTE(offset, ver->major, blob);
331           LoadBlob_BYTE(offset, ver->minor, blob);
332           LoadBlob_BYTE(offset, ver->revMajor, blob);
333           LoadBlob_BYTE(offset, ver->revMinor, blob);
334 }
335 
336 TSS_RESULT
UnloadBlob_KEY_PARMS(UINT64 * offset,BYTE * blob,TCPA_KEY_PARMS * keyParms)337 UnloadBlob_KEY_PARMS(UINT64 *offset, BYTE *blob, TCPA_KEY_PARMS *keyParms)
338 {
339           if (!keyParms) {
340                     UINT32 parmSize;
341 
342                     UnloadBlob_UINT32(offset, NULL, blob);
343                     UnloadBlob_UINT16(offset, NULL, blob);
344                     UnloadBlob_UINT16(offset, NULL, blob);
345                     UnloadBlob_UINT32(offset, &parmSize, blob);
346 
347                     if (parmSize > 0)
348                               UnloadBlob(offset, parmSize, blob, NULL);
349 
350                     return TSS_SUCCESS;
351           }
352 
353           UnloadBlob_UINT32(offset, &keyParms->algorithmID, blob);
354           UnloadBlob_UINT16(offset, &keyParms->encScheme, blob);
355           UnloadBlob_UINT16(offset, &keyParms->sigScheme, blob);
356           UnloadBlob_UINT32(offset, &keyParms->parmSize, blob);
357 
358           if (keyParms->parmSize == 0)
359                     keyParms->parms = NULL;
360           else {
361                     keyParms->parms = malloc(keyParms->parmSize);
362                     if (keyParms->parms == NULL) {
363                               LogError("malloc of %u bytes failed.", keyParms->parmSize);
364                               keyParms->parmSize = 0;
365                               return TCSERR(TSS_E_OUTOFMEMORY);
366                     }
367 
368                     UnloadBlob(offset, keyParms->parmSize, blob, keyParms->parms);
369           }
370 
371           return TSS_SUCCESS;
372 }
373 
374 void
UnloadBlob_KEY_FLAGS(UINT64 * offset,BYTE * blob,TCPA_KEY_FLAGS * flags)375 UnloadBlob_KEY_FLAGS(UINT64 *offset, BYTE *blob, TCPA_KEY_FLAGS *flags)
376 {
377           if (!flags) {
378                     UnloadBlob_UINT32(offset, NULL, blob);
379 
380                     return;
381           }
382 
383           UnloadBlob_UINT32(offset, flags, blob);
384 }
385 
386 TSS_RESULT
UnloadBlob_CERTIFY_INFO(UINT64 * offset,BYTE * blob,TCPA_CERTIFY_INFO * certify)387 UnloadBlob_CERTIFY_INFO(UINT64 *offset, BYTE *blob, TCPA_CERTIFY_INFO *certify)
388 {
389           TSS_RESULT rc;
390 
391           if (!certify) {
392                     TPM_VERSION version;
393                     UINT32 size;
394 
395                     UnloadBlob_VERSION(offset, blob, &version);
396                     UnloadBlob_UINT16(offset, NULL, blob);
397                     UnloadBlob_KEY_FLAGS(offset, blob, NULL);
398                     UnloadBlob_BOOL(offset, NULL, blob);
399 
400                     if ((rc = UnloadBlob_KEY_PARMS(offset, blob, NULL)))
401                               return rc;
402 
403                     UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, NULL);
404                     UnloadBlob(offset, TCPA_NONCE_SIZE, blob, NULL);
405                     UnloadBlob_BOOL(offset, NULL, blob);
406                     UnloadBlob_UINT32(offset, &size, blob);
407 
408                     if (size > 0)
409                               UnloadBlob(offset, size, blob, NULL);
410 
411                     if (Decode_UINT16((BYTE *) &version) == TPM_TAG_CERTIFY_INFO2){
412                               /* This is a TPM_CERTIFY_INFO2 structure. */
413                               /* Read migrationAuthority. */
414                               UnloadBlob_UINT32(offset, &size, blob);
415                               if (size > 0)
416                                         UnloadBlob(offset, size, blob, NULL);
417                     }
418 
419                     return TSS_SUCCESS;
420           }
421 
422           UnloadBlob_VERSION(offset, blob, (TPM_VERSION *)&certify->version);
423           UnloadBlob_UINT16(offset, &certify->keyUsage, blob);
424           UnloadBlob_KEY_FLAGS(offset, blob, &certify->keyFlags);
425           UnloadBlob_BOOL(offset, (TSS_BOOL *)&certify->authDataUsage, blob);
426 
427           if ((rc = UnloadBlob_KEY_PARMS(offset, blob, &certify->algorithmParms)))
428                     return rc;
429 
430           UnloadBlob(offset, TCPA_DIGEST_SIZE, blob, certify->pubkeyDigest.digest);
431           UnloadBlob(offset, TCPA_NONCE_SIZE, blob, certify->data.nonce);
432           UnloadBlob_BOOL(offset, (TSS_BOOL *)&certify->parentPCRStatus, blob);
433           UnloadBlob_UINT32(offset, &certify->PCRInfoSize, blob);
434 
435           if (certify->PCRInfoSize > 0) {
436                     certify->PCRInfo = (BYTE *)malloc(certify->PCRInfoSize);
437                     if (certify->PCRInfo == NULL) {
438                               LogError("malloc of %u bytes failed.", certify->PCRInfoSize);
439                               certify->PCRInfoSize = 0;
440                               free(certify->algorithmParms.parms);
441                               certify->algorithmParms.parms = NULL;
442                               certify->algorithmParms.parmSize = 0;
443                               return TCSERR(TSS_E_OUTOFMEMORY);
444                     }
445                     UnloadBlob(offset, certify->PCRInfoSize, blob, certify->PCRInfo);
446           } else {
447                     certify->PCRInfo = NULL;
448           }
449 
450           if (Decode_UINT16((BYTE *) &certify->version) == TPM_TAG_CERTIFY_INFO2){
451                     /* This is a TPM_CERTIFY_INFO2 structure. */
452                     /* Read migrationAuthority. */
453                     UINT32 size;
454                     UnloadBlob_UINT32(offset, &size, blob);
455                     if (size > 0)
456                               UnloadBlob(offset, size, blob, NULL);
457           }
458 
459           return TSS_SUCCESS;
460 }
461 
462 TSS_RESULT
UnloadBlob_KEY_HANDLE_LIST(UINT64 * offset,BYTE * blob,TCPA_KEY_HANDLE_LIST * list)463 UnloadBlob_KEY_HANDLE_LIST(UINT64 *offset, BYTE *blob, TCPA_KEY_HANDLE_LIST *list)
464 {
465           UINT16 i;
466 
467           if (!list) {
468                     UINT16 size;
469 
470                     UnloadBlob_UINT16(offset, &size, blob);
471 
472                     *offset += (size * sizeof(UINT32));
473 
474                     return TSS_SUCCESS;
475           }
476 
477           UnloadBlob_UINT16(offset, &list->loaded, blob);
478           if (list->loaded == 0) {
479                     list->handle = NULL;
480                     return TSS_SUCCESS;
481           }
482 
483           list->handle = malloc(list->loaded * sizeof (UINT32));
484         if (list->handle == NULL) {
485                     LogError("malloc of %zd bytes failed.", list->loaded * sizeof (UINT32));
486                     list->loaded = 0;
487                 return TCSERR(TSS_E_OUTOFMEMORY);
488         }
489 
490           for (i = 0; i < list->loaded; i++)
491                     UnloadBlob_UINT32(offset, &list->handle[i], blob);
492 
493           return TSS_SUCCESS;
494 }
495 
496 void
LoadBlob_DIGEST(UINT64 * offset,BYTE * blob,TPM_DIGEST * digest)497 LoadBlob_DIGEST(UINT64 *offset, BYTE *blob, TPM_DIGEST *digest)
498 {
499           LoadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, digest->digest);
500 }
501 
502 void
UnloadBlob_DIGEST(UINT64 * offset,BYTE * blob,TPM_DIGEST * digest)503 UnloadBlob_DIGEST(UINT64 *offset, BYTE *blob, TPM_DIGEST *digest)
504 {
505           UnloadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, digest->digest);
506 }
507 
508 void
LoadBlob_NONCE(UINT64 * offset,BYTE * blob,TPM_NONCE * nonce)509 LoadBlob_NONCE(UINT64 *offset, BYTE *blob, TPM_NONCE *nonce)
510 {
511           LoadBlob(offset, TCPA_NONCE_SIZE, blob, nonce->nonce);
512 }
513 
514 void
UnloadBlob_NONCE(UINT64 * offset,BYTE * blob,TPM_NONCE * nonce)515 UnloadBlob_NONCE(UINT64 *offset, BYTE *blob, TPM_NONCE *nonce)
516 {
517           UnloadBlob(offset, TCPA_NONCE_SIZE, blob, nonce->nonce);
518 }
519 
520 void
LoadBlob_AUTHDATA(UINT64 * offset,BYTE * blob,TPM_AUTHDATA * authdata)521 LoadBlob_AUTHDATA(UINT64 *offset, BYTE *blob, TPM_AUTHDATA *authdata)
522 {
523           LoadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, authdata->authdata);
524 }
525 
526 void
UnloadBlob_AUTHDATA(UINT64 * offset,BYTE * blob,TPM_AUTHDATA * authdata)527 UnloadBlob_AUTHDATA(UINT64 *offset, BYTE *blob, TPM_AUTHDATA *authdata)
528 {
529           UnloadBlob(offset, TPM_SHA1_160_HASH_LEN, blob, authdata->authdata);
530 }
531 
532