1 /*
2 * Copyright (c) 2010-2012 United States Government, as represented by
3 * the Secretary of Defense. All rights reserved.
4 *
5 * based off of the original tools/vtpm_manager code base which is:
6 * Copyright (c) 2005, Intel Corp.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of Intel Corporation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 #include <stdint.h>
37 #include <stdlib.h>
38
39 #include <xen/xen.h>
40 #include <mini-os/tpmback.h>
41 #include <mini-os/tpmfront.h>
42 #include <mini-os/tpm_tis.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <polarssl/sha1.h>
48
49 #include "log.h"
50 #include "vtpmmgr.h"
51 #include "vtpm_disk.h"
52 #include "tpm.h"
53 #include "marshal.h"
54 #include "tpm2_marshal.h"
55 #include "tpm2.h"
56
57 struct Opts {
58 enum {
59 TPMDRV_TPM_TIS,
60 TPMDRV_TPMFRONT,
61 } tpmdriver;
62 unsigned long tpmiomem;
63 unsigned int tpmirq;
64 unsigned int tpmlocality;
65 int gen_owner_auth;
66 };
67
68 // --------------------------- Well Known Auths --------------------------
69 const TPM_AUTHDATA WELLKNOWN_AUTH = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
71
72 struct vtpm_globals vtpm_globals = {
73 .tpm_fd = -1,
74 .oiap = { .AuthHandle = 0 },
75 .hw_locality = 0
76 };
77
tpm_entropy_source(void * dummy,unsigned char * data,size_t len,size_t * olen)78 static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len, size_t* olen) {
79 UINT32 sz = len;
80 TPM_RESULT rc = TPM_GetRandom(&sz, data);
81 *olen = sz;
82 return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
83 }
84
check_tpm_version(void)85 static TPM_RESULT check_tpm_version(void) {
86 TPM_RESULT status;
87 UINT32 rsize;
88 BYTE* res = NULL;
89 TPM_CAP_VERSION_INFO vinfo;
90
91 TPMTRYRETURN(TPM_GetCapability(
92 TPM_CAP_VERSION_VAL,
93 0,
94 NULL,
95 &rsize,
96 &res));
97 if(rsize < 4) {
98 vtpmlogerror(VTPM_LOG_VTPM, "Invalid size returned by GetCapability!\n");
99 status = TPM_BAD_PARAMETER;
100 goto abort_egress;
101 }
102
103 unpack_TPM_CAP_VERSION_INFO(res, &vinfo, UNPACK_ALIAS);
104
105 vtpmloginfo(VTPM_LOG_VTPM, "Hardware TPM:\n");
106 vtpmloginfo(VTPM_LOG_VTPM, " version: %hhd %hhd %hhd %hhd\n",
107 vinfo.version.major, vinfo.version.minor, vinfo.version.revMajor, vinfo.version.revMinor);
108 vtpmloginfo(VTPM_LOG_VTPM, " specLevel: %hd\n", vinfo.specLevel);
109 vtpmloginfo(VTPM_LOG_VTPM, " errataRev: %hhd\n", vinfo.errataRev);
110 vtpmloginfo(VTPM_LOG_VTPM, " vendorID: %c%c%c%c\n",
111 vinfo.tpmVendorID[0], vinfo.tpmVendorID[1],
112 vinfo.tpmVendorID[2], vinfo.tpmVendorID[3]);
113 vtpmloginfo(VTPM_LOG_VTPM, " vendorSpecificSize: %hd\n", vinfo.vendorSpecificSize);
114 vtpmloginfo(VTPM_LOG_VTPM, " vendorSpecific: ");
115 for(int i = 0; i < vinfo.vendorSpecificSize; ++i) {
116 vtpmloginfomore(VTPM_LOG_VTPM, "%02hhx", vinfo.vendorSpecific[i]);
117 }
118 vtpmloginfomore(VTPM_LOG_VTPM, "\n");
119
120 abort_egress:
121 free(res);
122 return status;
123 }
124
flush_tpm(void)125 static TPM_RESULT flush_tpm(void) {
126 TPM_RESULT status = TPM_SUCCESS;
127 const TPM_RESOURCE_TYPE reslist[] = { TPM_RT_KEY, TPM_RT_AUTH, TPM_RT_TRANS, TPM_RT_COUNTER, TPM_RT_DAA_TPM, TPM_RT_CONTEXT };
128 BYTE* keylist = NULL;
129 UINT32 keylistSize;
130 BYTE* ptr;
131
132 //Iterate through each resource type and flush all handles
133 for(int i = 0; i < sizeof(reslist) / sizeof(TPM_RESOURCE_TYPE); ++i) {
134 TPM_RESOURCE_TYPE beres = cpu_to_be32(reslist[i]);
135 UINT16 size;
136 TPMTRYRETURN(TPM_GetCapability(
137 TPM_CAP_HANDLE,
138 sizeof(TPM_RESOURCE_TYPE),
139 (BYTE*)(&beres),
140 &keylistSize,
141 &keylist));
142
143 ptr = keylist;
144 ptr = unpack_UINT16(ptr, &size);
145
146 //Flush each handle
147 if(size) {
148 vtpmloginfo(VTPM_LOG_VTPM, "Flushing %u handle(s) of type %lu\n", size, (unsigned long) reslist[i]);
149 for(int j = 0; j < size; ++j) {
150 TPM_HANDLE h;
151 ptr = unpack_TPM_HANDLE(ptr, &h);
152 TPMTRYRETURN(TPM_FlushSpecific(h, reslist[i]));
153 }
154 }
155
156 free(keylist);
157 keylist = NULL;
158 }
159
160 goto egress;
161 abort_egress:
162 free(keylist);
163 egress:
164 return status;
165 }
166
167
try_take_ownership(void)168 static TPM_RESULT try_take_ownership(void) {
169 TPM_RESULT status = TPM_SUCCESS;
170 TPM_PUBKEY pubEK = TPM_PUBKEY_INIT;
171
172 // If we can read PubEK then there is no owner and we should take it.
173 status = TPM_ReadPubek(&pubEK);
174
175 switch(status) {
176 case TPM_DISABLED_CMD:
177 //Cannot read ek? TPM has owner
178 vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n");
179 status = TPM_SUCCESS;
180 break;
181 case TPM_NO_ENDORSEMENT:
182 {
183 //If theres no ek, we have to create one
184 TPM_KEY_PARMS keyInfo = {
185 .algorithmID = TPM_ALG_RSA,
186 .encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1,
187 .sigScheme = TPM_SS_NONE,
188 .parmSize = 12,
189 .parms.rsa = {
190 .keyLength = RSA_KEY_SIZE,
191 .numPrimes = 2,
192 .exponentSize = 0,
193 .exponent = NULL,
194 },
195 };
196 TPMTRYRETURN(TPM_CreateEndorsementKeyPair(&keyInfo, &pubEK));
197 }
198 //fall through to take ownership
199 case TPM_SUCCESS:
200 {
201 //Construct the Srk
202 TPM_KEY srk = {
203 .ver = TPM_STRUCT_VER_1_1,
204 .keyUsage = TPM_KEY_STORAGE,
205 .keyFlags = 0x00,
206 .authDataUsage = TPM_AUTH_ALWAYS,
207 .algorithmParms = {
208 .algorithmID = TPM_ALG_RSA,
209 .encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1,
210 .sigScheme = TPM_SS_NONE,
211 .parmSize = 12,
212 .parms.rsa = {
213 .keyLength = RSA_KEY_SIZE,
214 .numPrimes = 2,
215 .exponentSize = 0,
216 .exponent = NULL,
217 },
218 },
219 .PCRInfoSize = 0,
220 .pubKey = {
221 .keyLength = 0,
222 .key = NULL,
223 },
224 .encDataSize = 0,
225 };
226
227 TPMTRYRETURN(TPM_TakeOwnership(
228 &pubEK,
229 (const TPM_AUTHDATA*)&vtpm_globals.owner_auth,
230 (const TPM_AUTHDATA*)&vtpm_globals.srk_auth,
231 &srk,
232 NULL,
233 &vtpm_globals.oiap));
234
235 TPMTRYRETURN(TPM_DisablePubekRead(
236 (const TPM_AUTHDATA*)&vtpm_globals.owner_auth,
237 &vtpm_globals.oiap));
238 }
239 break;
240 default:
241 break;
242 }
243 abort_egress:
244 free_TPM_PUBKEY(&pubEK);
245 return status;
246 }
247
parse_auth_string(char * authstr,BYTE * target)248 static int parse_auth_string(char* authstr, BYTE* target) {
249 int rc;
250 /* well known owner auth */
251 if(!strcmp(authstr, "well-known")) {
252 return 0;
253 }
254 /* owner auth is a raw hash */
255 else if(!strncmp(authstr, "hash:", 5)) {
256 authstr += 5;
257 if((rc = strlen(authstr)) != 40) {
258 vtpmlogerror(VTPM_LOG_VTPM, "Supplied owner auth hex string `%s' must be exactly 40 characters (20 bytes) long, length=%d\n", authstr, rc);
259 return -1;
260 }
261 for(int j = 0; j < 20; ++j) {
262 if(sscanf(authstr, "%hhX", target + j) != 1) {
263 vtpmlogerror(VTPM_LOG_VTPM, "Supplied owner auth string `%s' is not a valid hex string\n", authstr);
264 return -1;
265 }
266 authstr += 2;
267 }
268 }
269 /* owner auth is a string that will be hashed */
270 else if(!strncmp(authstr, "text:", 5)) {
271 authstr += 5;
272 sha1((const unsigned char*)authstr, strlen(authstr), target);
273 }
274 else {
275 vtpmlogerror(VTPM_LOG_VTPM, "Invalid auth string %s\n", authstr);
276 return -1;
277 }
278
279 return 0;
280 }
281
parse_cmdline_opts(int argc,char ** argv,struct Opts * opts)282 int parse_cmdline_opts(int argc, char** argv, struct Opts* opts)
283 {
284 int rc;
285 int i;
286
287 //Set defaults
288 memcpy(vtpm_globals.owner_auth, WELLKNOWN_AUTH, sizeof(TPM_AUTHDATA));
289 memcpy(vtpm_globals.srk_auth, WELLKNOWN_AUTH, sizeof(TPM_AUTHDATA));
290
291 for(i = 1; i < argc; ++i) {
292 if(!strncmp(argv[i], "owner_auth=", 11)) {
293 if((rc = parse_auth_string(argv[i] + 11, vtpm_globals.owner_auth)) < 0) {
294 goto err_invalid;
295 }
296 if(rc == 1) {
297 opts->gen_owner_auth = 1;
298 }
299 }
300 else if(!strncmp(argv[i], "srk_auth=", 9)) {
301 if((rc = parse_auth_string(argv[i] + 9, vtpm_globals.srk_auth)) != 0) {
302 goto err_invalid;
303 }
304 }
305 else if(!strncmp(argv[i], "srk_handle=", 11)) {
306 if(sscanf(argv[i] + 11, "%x", &vtpm_globals.srk_handle) != 1) {
307 goto err_invalid;
308 }
309 }
310 else if(!strncmp(argv[i], "tpmdriver=", 10)) {
311 if(!strcmp(argv[i] + 10, "tpm_tis")) {
312 opts->tpmdriver = TPMDRV_TPM_TIS;
313 } else if(!strcmp(argv[i] + 10, "tpmfront")) {
314 opts->tpmdriver = TPMDRV_TPMFRONT;
315 } else {
316 goto err_invalid;
317 }
318 }
319 else if(!strncmp(argv[i], "tpmiomem=",9)) {
320 if(sscanf(argv[i] + 9, "0x%lX", &opts->tpmiomem) != 1) {
321 goto err_invalid;
322 }
323 }
324 else if(!strncmp(argv[i], "tpmirq=",7)) {
325 if(!strcmp(argv[i] + 7, "probe")) {
326 opts->tpmirq = TPM_PROBE_IRQ;
327 } else if( sscanf(argv[i] + 7, "%u", &opts->tpmirq) != 1) {
328 goto err_invalid;
329 }
330 }
331 else if(!strncmp(argv[i], "tpmlocality=",12)) {
332 if(sscanf(argv[i] + 12, "%u", &opts->tpmlocality) != 1 || opts->tpmlocality > 4) {
333 goto err_invalid;
334 }
335 }
336 }
337
338 switch(opts->tpmdriver) {
339 case TPMDRV_TPM_TIS:
340 vtpmloginfo(VTPM_LOG_VTPM, "Option: Using tpm_tis driver\n");
341 break;
342 case TPMDRV_TPMFRONT:
343 vtpmloginfo(VTPM_LOG_VTPM, "Option: Using tpmfront driver\n");
344 break;
345 }
346
347 return 0;
348 err_invalid:
349 vtpmlogerror(VTPM_LOG_VTPM, "Invalid Option %s\n", argv[i]);
350 return -1;
351 }
352
353
354
vtpmmgr_create(void)355 static TPM_RESULT vtpmmgr_create(void) {
356 TPM_RESULT status = TPM_SUCCESS;
357 TPM_AUTH_SESSION osap = TPM_AUTH_SESSION_INIT;
358 TPM_AUTHDATA sharedsecret;
359
360 // Take ownership if TPM is unowned
361 TPMTRYRETURN(try_take_ownership());
362
363 // Generate storage key's auth
364 TPMTRYRETURN( TPM_OSAP(
365 TPM_ET_KEYHANDLE,
366 TPM_SRK_KEYHANDLE,
367 (const TPM_AUTHDATA*)&vtpm_globals.srk_auth,
368 &sharedsecret,
369 &osap) );
370
371 //Make sure TPM has commited changes
372 TPMTRYRETURN( TPM_SaveState() );
373
374 //Create new disk image
375 TPMTRYRETURN(vtpm_new_disk());
376
377 goto egress;
378 abort_egress:
379 egress:
380 vtpmloginfo(VTPM_LOG_VTPM, "Finished initialized new VTPM manager\n");
381
382 //End the OSAP session
383 if(osap.AuthHandle) {
384 TPM_TerminateHandle(osap.AuthHandle);
385 }
386
387 return status;
388 }
389
set_opaque(domid_t domid,unsigned int handle)390 static void set_opaque(domid_t domid, unsigned int handle)
391 {
392 struct tpm_opaque* opq;
393
394 opq = calloc(1, sizeof(*opq));
395 opq->uuid = (uuid_t*)tpmback_get_uuid(domid, handle);
396 opq->domid = domid;
397 opq->handle = handle;
398 tpmback_set_opaque(domid, handle, opq);
399 }
400
free_opaque(domid_t domid,unsigned int handle)401 static void free_opaque(domid_t domid, unsigned int handle)
402 {
403 struct tpm_opaque* opq = tpmback_get_opaque(domid, handle);
404 if (opq && opq->vtpm)
405 opq->vtpm->flags &= ~VTPM_FLAG_OPEN;
406 free(opq);
407 }
408
vtpmmgr_init(int argc,char ** argv)409 TPM_RESULT vtpmmgr_init(int argc, char** argv) {
410 TPM_RESULT status = TPM_SUCCESS;
411
412 /* Default commandline options */
413 struct Opts opts = {
414 .tpmdriver = TPMDRV_TPM_TIS,
415 .tpmiomem = TPM_BASEADDR,
416 .tpmirq = 0,
417 .tpmlocality = 0,
418 .gen_owner_auth = 0,
419 };
420
421 if(parse_cmdline_opts(argc, argv, &opts) != 0) {
422 vtpmlogerror(VTPM_LOG_VTPM, "Command line parsing failed! exiting..\n");
423 status = TPM_BAD_PARAMETER;
424 goto abort_egress;
425 }
426
427 //Setup storage system
428 if(vtpm_storage_init() != 0) {
429 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize storage subsystem!\n");
430 status = TPM_IOERROR;
431 goto abort_egress;
432 }
433
434 //Setup tpmback device
435 init_tpmback(set_opaque, free_opaque);
436
437 //Setup tpm access
438 switch(opts.tpmdriver) {
439 case TPMDRV_TPM_TIS:
440 {
441 struct tpm_chip* tpm;
442 if((tpm = init_tpm_tis(opts.tpmiomem, TPM_TIS_LOCL_INT_TO_FLAG(opts.tpmlocality), opts.tpmirq)) == NULL) {
443 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
444 status = TPM_IOERROR;
445 goto abort_egress;
446 }
447 vtpm_globals.tpm_fd = tpm_tis_open(tpm);
448 tpm_tis_request_locality(tpm, opts.tpmlocality);
449 vtpm_globals.hw_locality = opts.tpmlocality;
450 }
451 break;
452 case TPMDRV_TPMFRONT:
453 {
454 struct tpmfront_dev* tpmfront_dev;
455 if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
456 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
457 status = TPM_IOERROR;
458 goto abort_egress;
459 }
460 vtpm_globals.tpm_fd = tpmfront_open(tpmfront_dev);
461 }
462 break;
463 }
464
465 //Get the version of the tpm
466 TPMTRYRETURN(check_tpm_version());
467
468 // Blow away all stale handles left in the tpm
469 if(flush_tpm() != TPM_SUCCESS) {
470 vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing anyway..\n");
471 }
472
473 /* Initialize the rng */
474 entropy_init(&vtpm_globals.entropy);
475 entropy_add_source(&vtpm_globals.entropy, tpm_entropy_source, NULL, 0);
476 entropy_gather(&vtpm_globals.entropy);
477 ctr_drbg_init(&vtpm_globals.ctr_drbg, entropy_func, &vtpm_globals.entropy, NULL, 0);
478 ctr_drbg_set_prediction_resistance( &vtpm_globals.ctr_drbg, CTR_DRBG_PR_OFF );
479
480 // Generate Auth for Owner
481 if(opts.gen_owner_auth) {
482 vtpmmgr_rand(vtpm_globals.owner_auth, sizeof(TPM_AUTHDATA));
483 }
484
485 // Create OIAP session for service's authorized commands
486 TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) );
487
488 /* Load the Manager data, if it fails create a new manager */
489 // TODO handle upgrade recovery of auth0
490 if (vtpm_load_disk()) {
491 /* If the OIAP session was closed by an error, create a new one */
492 if(vtpm_globals.oiap.AuthHandle == 0) {
493 TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) );
494 }
495 vtpmloginfo(VTPM_LOG_VTPM, "Failed to read manager file. Assuming first time initialization.\n");
496 TPMTRYRETURN( vtpmmgr_create() );
497 }
498
499 goto egress;
500 abort_egress:
501 vtpmmgr_shutdown();
502 egress:
503 return status;
504 }
505
506 /* TPM 2.0 */
507
tpm2_AuthArea_ctor(const char * authValue,UINT32 authLen,TPM_AuthArea * auth)508 static void tpm2_AuthArea_ctor(const char *authValue, UINT32 authLen,
509 TPM_AuthArea *auth)
510 {
511 auth->sessionHandle = TPM_RS_PW;
512 auth->nonce.size = 0;
513 auth->sessionAttributes = 1;
514 auth->auth.size = authLen;
515 memcpy(auth->auth.buffer, authValue, authLen);
516 auth->size = 9 + authLen;
517 }
518
tpm2_take_ownership(void)519 TPM_RC tpm2_take_ownership(void)
520 {
521 TPM_RC status = TPM_SUCCESS;
522
523 tpm2_AuthArea_ctor(NULL, 0, &vtpm_globals.pw_auth);
524
525 /* create SRK */
526 TPM2_CreatePrimary_Params_in in = {
527 .inSensitive = {
528 .size = 4,
529 .sensitive = {
530 .userAuth.size = 0,
531 .userAuth.buffer = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
532 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
533 .data.size = 0,
534 },
535 },
536 .inPublic = {
537 .size = 60,
538 .publicArea = {
539 .type = TPM2_ALG_RSA,
540 .nameAlg = TPM2_ALG_SHA256,
541 #define SRK_OBJ_ATTR (fixedTPM | fixedParent | userWithAuth | \
542 sensitiveDataOrigin | restricted | decrypt)
543 .objectAttributes = SRK_OBJ_ATTR,
544 .authPolicy.size = 0,
545 .parameters.rsaDetail = {
546 .symmetric = {
547 .algorithm = TPM2_ALG_AES,
548 .keyBits.aes = AES_KEY_SIZES_BITS,
549 .mode.aes = TPM2_ALG_CFB,
550 },
551 .scheme = { TPM2_ALG_NULL },
552 .keyBits = RSA_KEY_SIZES_BITS,
553 .exponent = 0,
554 },
555 .unique.rsa.size = 0,
556 },
557 },
558 .outsideInfo.size = 0,
559 .creationPCR.count = 0,
560 };
561
562 TPMTRYRETURN(TPM2_CreatePrimary(TPM_RH_OWNER,&in,
563 &vtpm_globals.srk_handle, NULL));
564 vtpmloginfo(VTPM_LOG_VTPM, "SRK handle: 0x%X\n", vtpm_globals.srk_handle);
565 {
566 const char data[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
567 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
568 tpm2_AuthArea_ctor(data, 20, &vtpm_globals.srk_auth_area);
569 }
570 /*end create SRK*/
571
572 abort_egress:
573 return status;
574 }
575
vtpmmgr2_create(void)576 TPM_RESULT vtpmmgr2_create(void)
577 {
578 TPM_RESULT status = TPM_SUCCESS;
579
580 if ( vtpm_globals.srk_handle == 0 ) {
581 TPMTRYRETURN(tpm2_take_ownership());
582 } else {
583 tpm2_AuthArea_ctor(NULL, 0, &vtpm_globals.srk_auth_area);
584 }
585
586 /* create SK */
587 TPM2_Create_Params_out out;
588 TPM2_Create_Params_in in = {
589 .inSensitive = {
590 .size = 4 + 20,
591 .sensitive = {
592 .userAuth.size = 20,
593 .userAuth.buffer = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
594 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
595 .data.size = 0,
596 },
597 },
598 .inPublic = {
599 .size = (60),
600 .publicArea = {
601 .type = TPM2_ALG_RSA,
602 .nameAlg = TPM2_ALG_SHA256,
603 #define SK_OBJ_ATTR (fixedTPM | fixedParent | userWithAuth |\
604 sensitiveDataOrigin |decrypt)
605 .objectAttributes = SK_OBJ_ATTR,
606 .authPolicy.size = 0,
607 .parameters.rsaDetail = {
608 .symmetric = {
609 .algorithm = TPM2_ALG_NULL,
610 },
611 .scheme = {
612 TPM2_ALG_OAEP,
613 .details.oaep.hashAlg = TPM2_ALG_SHA256,
614 },
615 .keyBits = RSA_KEY_SIZES_BITS,
616 .exponent = 0,
617 },
618 .unique.rsa.size = 0,
619 },
620 },
621 .outsideInfo.size = 0,
622 .creationPCR.count = 0,
623 };/*end in */
624
625 TPMTRYRETURN(TPM2_Create(vtpm_globals.srk_handle, &in, &out));
626 TPMTRYRETURN(TPM2_Load(vtpm_globals.srk_handle,
627 &vtpm_globals.tpm2_storage_key.Private,
628 &vtpm_globals.tpm2_storage_key.Public,
629 &vtpm_globals.sk_handle,
630 &vtpm_globals.sk_name));
631
632 vtpmloginfo(VTPM_LOG_VTPM, "SK HANDLE: 0x%X\n", vtpm_globals.sk_handle);
633
634 /*Create new disk image*/
635 TPMTRYRETURN(vtpm_new_disk());
636
637 goto egress;
638
639 abort_egress:
640 egress:
641 vtpmloginfo(VTPM_LOG_VTPM, "Finished initialized new VTPM manager\n");
642 return status;
643 }
644
tpm2_entropy_source(void * dummy,unsigned char * data,size_t len,size_t * olen)645 static int tpm2_entropy_source(void* dummy, unsigned char* data,
646 size_t len, size_t* olen)
647 {
648 UINT32 sz = len;
649 TPM_RESULT rc = TPM2_GetRandom(&sz, data);
650 *olen = sz;
651 return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
652 }
653
654 /*TPM 2.0 Objects flush */
flush_tpm2(void)655 static TPM_RC flush_tpm2(void)
656 {
657 int i;
658
659 for (i = TRANSIENT_FIRST; i <= TRANSIENT_LAST; i++)
660 TPM2_FlushContext(i);
661
662 return TPM_SUCCESS;
663 }
664
vtpmmgr2_init(int argc,char ** argv)665 TPM_RESULT vtpmmgr2_init(int argc, char** argv)
666 {
667 TPM_RESULT status = TPM_SUCCESS;
668
669 /* Default commandline options */
670 struct Opts opts = {
671 .tpmdriver = TPMDRV_TPM_TIS,
672 .tpmiomem = TPM_BASEADDR,
673 .tpmirq = 0,
674 .tpmlocality = 0,
675 .gen_owner_auth = 0,
676 };
677
678 if (parse_cmdline_opts(argc, argv, &opts) != 0) {
679 vtpmlogerror(VTPM_LOG_VTPM, "Command line parsing failed! exiting..\n");
680 status = TPM_BAD_PARAMETER;
681 goto abort_egress;
682 }
683
684 /*Setup storage system*/
685 if (vtpm_storage_init() != 0) {
686 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize storage subsystem!\n");
687 status = TPM_IOERROR;
688 goto abort_egress;
689 }
690
691 /*Setup tpmback device*/
692 init_tpmback(set_opaque, free_opaque);
693
694 /*Setup tpm access*/
695 switch(opts.tpmdriver) {
696 case TPMDRV_TPM_TIS:
697 {
698 struct tpm_chip* tpm;
699 if ((tpm = init_tpm2_tis(opts.tpmiomem, TPM_TIS_LOCL_INT_TO_FLAG(opts.tpmlocality),
700 opts.tpmirq)) == NULL) {
701 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
702 status = TPM_IOERROR;
703 goto abort_egress;
704 }
705 printk("init_tpm2_tis() ...ok\n");
706 vtpm_globals.tpm_fd = tpm_tis_open(tpm);
707 tpm_tis_request_locality(tpm, opts.tpmlocality);
708 }
709 break;
710 case TPMDRV_TPMFRONT:
711 {
712 struct tpmfront_dev* tpmfront_dev;
713 if ((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
714 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
715 status = TPM_IOERROR;
716 goto abort_egress;
717 }
718 vtpm_globals.tpm_fd = tpmfront_open(tpmfront_dev);
719 }
720 break;
721 }
722 printk("TPM 2.0 access ...ok\n");
723 /* Blow away all stale handles left in the tpm*/
724 if (flush_tpm2() != TPM_SUCCESS) {
725 vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing anyway..\n");
726 }
727
728 /* Initialize the rng */
729 entropy_init(&vtpm_globals.entropy);
730 entropy_add_source(&vtpm_globals.entropy, tpm2_entropy_source, NULL, 0);
731 entropy_gather(&vtpm_globals.entropy);
732 ctr_drbg_init(&vtpm_globals.ctr_drbg, entropy_func, &vtpm_globals.entropy, NULL, 0);
733 ctr_drbg_set_prediction_resistance( &vtpm_globals.ctr_drbg, CTR_DRBG_PR_OFF );
734
735 /* Generate Auth for Owner*/
736 if (opts.gen_owner_auth) {
737 vtpmmgr_rand(vtpm_globals.owner_auth, sizeof(TPM_AUTHDATA));
738 }
739
740 /* Load the Manager data, if it fails create a new manager */
741 if (vtpm_load_disk()) {
742 vtpmloginfo(VTPM_LOG_VTPM, "Assuming first time initialization.\n");
743 TPMTRYRETURN(vtpmmgr2_create());
744 }
745
746 goto egress;
747
748 abort_egress:
749 vtpmmgr_shutdown();
750 egress:
751 return status;
752 }
753
tpm2_pcr_read(int index,uint8_t * buf)754 TPM_RC tpm2_pcr_read(int index, uint8_t *buf)
755 {
756 TPM_RESULT status = TPM_SUCCESS;
757 TPML_PCR_SELECTION pcrSelectionIn = {
758 .count = 1,};
759
760 TPMS_PCR_SELECTION tpms_pcr_selection = {
761 .hash = TPM2_ALG_SHA1,
762 .sizeofSelect = PCR_SELECT_MAX,};
763
764 UINT32 pcrUpdateCounter;
765 TPML_PCR_SELECTION pcrSelectionOut;
766 TPML_DIGEST pcrValues;
767 TPM2B_DIGEST tpm2b_digest;
768
769 tpms_pcr_selection.pcrSelect[PCR_SELECT_NUM(index)] = PCR_SELECT_VALUE(index);
770 memcpy(&pcrSelectionIn.pcrSelections[0], &tpms_pcr_selection,
771 sizeof(TPMS_PCR_SELECTION));
772
773 TPMTRYRETURN(TPM2_PCR_Read(pcrSelectionIn, &pcrUpdateCounter,
774 &pcrSelectionOut, &pcrValues));
775
776 if (pcrValues.count < 1)
777 goto egress;
778
779 unpack_TPM2B_DIGEST((uint8_t *) &pcrValues, &tpm2b_digest);
780 memcpy(buf, tpm2b_digest.buffer, SHA1_DIGEST_SIZE);
781
782 abort_egress:
783 egress:
784 return status;
785 }
786
vtpmmgr_shutdown(void)787 void vtpmmgr_shutdown(void)
788 {
789 /* Cleanup TPM resources */
790 TPM_TerminateHandle(vtpm_globals.oiap.AuthHandle);
791
792 /* Close tpmback */
793 shutdown_tpmback();
794
795 if (hw_is_tpm2()) {
796 /* Blow away all stale handles left in the tpm*/
797 if (flush_tpm2() != TPM_SUCCESS) {
798 vtpmlogerror(VTPM_LOG_TPM,
799 "TPM2_FlushResources failed, continuing shutdown..\n");
800 }
801 }
802
803 /* Close tpmfront/tpm_tis */
804 close(vtpm_globals.tpm_fd);
805
806 vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n");
807 }
808