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:", 10)) {
293 if((rc = parse_auth_string(argv[i] + 10, 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:", 8)) {
301 if((rc = parse_auth_string(argv[i] + 8, vtpm_globals.srk_auth)) != 0) {
302 goto err_invalid;
303 }
304 }
305 else if(!strncmp(argv[i], "tpmdriver=", 10)) {
306 if(!strcmp(argv[i] + 10, "tpm_tis")) {
307 opts->tpmdriver = TPMDRV_TPM_TIS;
308 } else if(!strcmp(argv[i] + 10, "tpmfront")) {
309 opts->tpmdriver = TPMDRV_TPMFRONT;
310 } else {
311 goto err_invalid;
312 }
313 }
314 else if(!strncmp(argv[i], "tpmiomem=",9)) {
315 if(sscanf(argv[i] + 9, "0x%lX", &opts->tpmiomem) != 1) {
316 goto err_invalid;
317 }
318 }
319 else if(!strncmp(argv[i], "tpmirq=",7)) {
320 if(!strcmp(argv[i] + 7, "probe")) {
321 opts->tpmirq = TPM_PROBE_IRQ;
322 } else if( sscanf(argv[i] + 7, "%u", &opts->tpmirq) != 1) {
323 goto err_invalid;
324 }
325 }
326 else if(!strncmp(argv[i], "tpmlocality=",12)) {
327 if(sscanf(argv[i] + 12, "%u", &opts->tpmlocality) != 1 || opts->tpmlocality > 4) {
328 goto err_invalid;
329 }
330 }
331 }
332
333 switch(opts->tpmdriver) {
334 case TPMDRV_TPM_TIS:
335 vtpmloginfo(VTPM_LOG_VTPM, "Option: Using tpm_tis driver\n");
336 break;
337 case TPMDRV_TPMFRONT:
338 vtpmloginfo(VTPM_LOG_VTPM, "Option: Using tpmfront driver\n");
339 break;
340 }
341
342 return 0;
343 err_invalid:
344 vtpmlogerror(VTPM_LOG_VTPM, "Invalid Option %s\n", argv[i]);
345 return -1;
346 }
347
348
349
vtpmmgr_create(void)350 static TPM_RESULT vtpmmgr_create(void) {
351 TPM_RESULT status = TPM_SUCCESS;
352 TPM_AUTH_SESSION osap = TPM_AUTH_SESSION_INIT;
353 TPM_AUTHDATA sharedsecret;
354
355 // Take ownership if TPM is unowned
356 TPMTRYRETURN(try_take_ownership());
357
358 // Generate storage key's auth
359 TPMTRYRETURN( TPM_OSAP(
360 TPM_ET_KEYHANDLE,
361 TPM_SRK_KEYHANDLE,
362 (const TPM_AUTHDATA*)&vtpm_globals.srk_auth,
363 &sharedsecret,
364 &osap) );
365
366 //Make sure TPM has commited changes
367 TPMTRYRETURN( TPM_SaveState() );
368
369 //Create new disk image
370 TPMTRYRETURN(vtpm_new_disk());
371
372 goto egress;
373 abort_egress:
374 egress:
375 vtpmloginfo(VTPM_LOG_VTPM, "Finished initialized new VTPM manager\n");
376
377 //End the OSAP session
378 if(osap.AuthHandle) {
379 TPM_TerminateHandle(osap.AuthHandle);
380 }
381
382 return status;
383 }
384
set_opaque(domid_t domid,unsigned int handle)385 static void set_opaque(domid_t domid, unsigned int handle)
386 {
387 struct tpm_opaque* opq;
388
389 opq = calloc(1, sizeof(*opq));
390 opq->uuid = (uuid_t*)tpmback_get_uuid(domid, handle);
391 opq->domid = domid;
392 opq->handle = handle;
393 tpmback_set_opaque(domid, handle, opq);
394 }
395
free_opaque(domid_t domid,unsigned int handle)396 static void free_opaque(domid_t domid, unsigned int handle)
397 {
398 struct tpm_opaque* opq = tpmback_get_opaque(domid, handle);
399 if (opq && opq->vtpm)
400 opq->vtpm->flags &= ~VTPM_FLAG_OPEN;
401 free(opq);
402 }
403
vtpmmgr_init(int argc,char ** argv)404 TPM_RESULT vtpmmgr_init(int argc, char** argv) {
405 TPM_RESULT status = TPM_SUCCESS;
406
407 /* Default commandline options */
408 struct Opts opts = {
409 .tpmdriver = TPMDRV_TPM_TIS,
410 .tpmiomem = TPM_BASEADDR,
411 .tpmirq = 0,
412 .tpmlocality = 0,
413 .gen_owner_auth = 0,
414 };
415
416 if(parse_cmdline_opts(argc, argv, &opts) != 0) {
417 vtpmlogerror(VTPM_LOG_VTPM, "Command line parsing failed! exiting..\n");
418 status = TPM_BAD_PARAMETER;
419 goto abort_egress;
420 }
421
422 //Setup storage system
423 if(vtpm_storage_init() != 0) {
424 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize storage subsystem!\n");
425 status = TPM_IOERROR;
426 goto abort_egress;
427 }
428
429 //Setup tpmback device
430 init_tpmback(set_opaque, free_opaque);
431
432 //Setup tpm access
433 switch(opts.tpmdriver) {
434 case TPMDRV_TPM_TIS:
435 {
436 struct tpm_chip* tpm;
437 if((tpm = init_tpm_tis(opts.tpmiomem, TPM_TIS_LOCL_INT_TO_FLAG(opts.tpmlocality), opts.tpmirq)) == NULL) {
438 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
439 status = TPM_IOERROR;
440 goto abort_egress;
441 }
442 vtpm_globals.tpm_fd = tpm_tis_open(tpm);
443 tpm_tis_request_locality(tpm, opts.tpmlocality);
444 vtpm_globals.hw_locality = opts.tpmlocality;
445 }
446 break;
447 case TPMDRV_TPMFRONT:
448 {
449 struct tpmfront_dev* tpmfront_dev;
450 if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
451 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
452 status = TPM_IOERROR;
453 goto abort_egress;
454 }
455 vtpm_globals.tpm_fd = tpmfront_open(tpmfront_dev);
456 }
457 break;
458 }
459
460 //Get the version of the tpm
461 TPMTRYRETURN(check_tpm_version());
462
463 // Blow away all stale handles left in the tpm
464 if(flush_tpm() != TPM_SUCCESS) {
465 vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing anyway..\n");
466 }
467
468 /* Initialize the rng */
469 entropy_init(&vtpm_globals.entropy);
470 entropy_add_source(&vtpm_globals.entropy, tpm_entropy_source, NULL, 0);
471 entropy_gather(&vtpm_globals.entropy);
472 ctr_drbg_init(&vtpm_globals.ctr_drbg, entropy_func, &vtpm_globals.entropy, NULL, 0);
473 ctr_drbg_set_prediction_resistance( &vtpm_globals.ctr_drbg, CTR_DRBG_PR_OFF );
474
475 // Generate Auth for Owner
476 if(opts.gen_owner_auth) {
477 vtpmmgr_rand(vtpm_globals.owner_auth, sizeof(TPM_AUTHDATA));
478 }
479
480 // Create OIAP session for service's authorized commands
481 TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) );
482
483 /* Load the Manager data, if it fails create a new manager */
484 // TODO handle upgrade recovery of auth0
485 if (vtpm_load_disk()) {
486 /* If the OIAP session was closed by an error, create a new one */
487 if(vtpm_globals.oiap.AuthHandle == 0) {
488 TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) );
489 }
490 vtpmloginfo(VTPM_LOG_VTPM, "Failed to read manager file. Assuming first time initialization.\n");
491 TPMTRYRETURN( vtpmmgr_create() );
492 }
493
494 goto egress;
495 abort_egress:
496 vtpmmgr_shutdown();
497 egress:
498 return status;
499 }
500
vtpmmgr_shutdown(void)501 void vtpmmgr_shutdown(void)
502 {
503 /* Cleanup TPM resources */
504 TPM_TerminateHandle(vtpm_globals.oiap.AuthHandle);
505
506 /* Close tpmback */
507 shutdown_tpmback();
508
509 /* Close tpmfront/tpm_tis */
510 close(vtpm_globals.tpm_fd);
511
512 vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n");
513 }
514
515 /* TPM 2.0 */
516
tpm2_AuthArea_ctor(const char * authValue,UINT32 authLen,TPM_AuthArea * auth)517 static void tpm2_AuthArea_ctor(const char *authValue, UINT32 authLen,
518 TPM_AuthArea *auth)
519 {
520 auth->sessionHandle = TPM_RS_PW;
521 auth->nonce.size = 0;
522 auth->sessionAttributes = 1;
523 auth->auth.size = authLen;
524 memcpy(auth->auth.buffer, authValue, authLen);
525 auth->size = 9 + authLen;
526 }
527
tpm2_take_ownership(void)528 TPM_RC tpm2_take_ownership(void)
529 {
530 TPM_RC status = TPM_SUCCESS;
531
532 tpm2_AuthArea_ctor(NULL, 0, &vtpm_globals.pw_auth);
533
534 /* create SRK */
535 TPM2_CreatePrimary_Params_in in = {
536 .inSensitive = {
537 .size = 4,
538 .sensitive = {
539 .userAuth.size = 0,
540 .userAuth.buffer = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
541 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
542 .data.size = 0,
543 },
544 },
545 .inPublic = {
546 .size = 60,
547 .publicArea = {
548 .type = TPM2_ALG_RSA,
549 .nameAlg = TPM2_ALG_SHA256,
550 #define SRK_OBJ_ATTR (fixedTPM | fixedParent | userWithAuth | \
551 sensitiveDataOrigin | restricted | decrypt)
552 .objectAttributes = SRK_OBJ_ATTR,
553 .authPolicy.size = 0,
554 .parameters.rsaDetail = {
555 .symmetric = {
556 .algorithm = TPM2_ALG_AES,
557 .keyBits.aes = AES_KEY_SIZES_BITS,
558 .mode.aes = TPM2_ALG_CFB,
559 },
560 .scheme = { TPM2_ALG_NULL },
561 .keyBits = RSA_KEY_SIZES_BITS,
562 .exponent = 0,
563 },
564 .unique.rsa.size = 0,
565 },
566 },
567 .outsideInfo.size = 0,
568 .creationPCR.count = 0,
569 };
570
571 TPMTRYRETURN(TPM2_CreatePrimary(TPM_RH_OWNER,&in,
572 &vtpm_globals.srk_handle, NULL));
573 vtpmloginfo(VTPM_LOG_VTPM, "SRK handle: 0x%X\n", vtpm_globals.srk_handle);
574 {
575 const char data[20] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
576 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
577 tpm2_AuthArea_ctor(data, 20, &vtpm_globals.srk_auth_area);
578 }
579 /*end create SRK*/
580
581 abort_egress:
582 return status;
583 }
584
vtpmmgr2_create(void)585 TPM_RESULT vtpmmgr2_create(void)
586 {
587 TPM_RESULT status = TPM_SUCCESS;
588
589 TPMTRYRETURN(tpm2_take_ownership());
590
591 /* create SK */
592 TPM2_Create_Params_out out;
593 TPM2_Create_Params_in in = {
594 .inSensitive = {
595 .size = 4 + 20,
596 .sensitive = {
597 .userAuth.size = 20,
598 .userAuth.buffer = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
599 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
600 .data.size = 0,
601 },
602 },
603 .inPublic = {
604 .size = (60),
605 .publicArea = {
606 .type = TPM2_ALG_RSA,
607 .nameAlg = TPM2_ALG_SHA256,
608 #define SK_OBJ_ATTR (fixedTPM | fixedParent | userWithAuth |\
609 sensitiveDataOrigin |decrypt)
610 .objectAttributes = SK_OBJ_ATTR,
611 .authPolicy.size = 0,
612 .parameters.rsaDetail = {
613 .symmetric = {
614 .algorithm = TPM2_ALG_NULL,
615 },
616 .scheme = {
617 TPM2_ALG_OAEP,
618 .details.oaep.hashAlg = TPM2_ALG_SHA256,
619 },
620 .keyBits = RSA_KEY_SIZES_BITS,
621 .exponent = 0,
622 },
623 .unique.rsa.size = 0,
624 },
625 },
626 .outsideInfo.size = 0,
627 .creationPCR.count = 0,
628 };/*end in */
629
630 TPMTRYRETURN(TPM2_Create(vtpm_globals.srk_handle, &in, &out));
631 TPMTRYRETURN(TPM2_Load(vtpm_globals.srk_handle,
632 &vtpm_globals.tpm2_storage_key.Private,
633 &vtpm_globals.tpm2_storage_key.Public,
634 &vtpm_globals.sk_handle,
635 &vtpm_globals.sk_name));
636
637 vtpmloginfo(VTPM_LOG_VTPM, "SK HANDLE: 0x%X\n", vtpm_globals.sk_handle);
638
639 /*Create new disk image*/
640 TPMTRYRETURN(vtpm_new_disk());
641
642 goto egress;
643
644 abort_egress:
645 egress:
646 vtpmloginfo(VTPM_LOG_VTPM, "Finished initialized new VTPM manager\n");
647 return status;
648 }
649
tpm2_entropy_source(void * dummy,unsigned char * data,size_t len,size_t * olen)650 static int tpm2_entropy_source(void* dummy, unsigned char* data,
651 size_t len, size_t* olen)
652 {
653 UINT32 sz = len;
654 TPM_RESULT rc = TPM2_GetRandom(&sz, data);
655 *olen = sz;
656 return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
657 }
658
659 /*TPM 2.0 Objects flush */
flush_tpm2(void)660 static TPM_RC flush_tpm2(void)
661 {
662 int i;
663
664 for (i = TRANSIENT_FIRST; i < TRANSIENT_LAST; i++)
665 TPM2_FlushContext(i);
666
667 return TPM_SUCCESS;
668 }
669
vtpmmgr2_init(int argc,char ** argv)670 TPM_RESULT vtpmmgr2_init(int argc, char** argv)
671 {
672 TPM_RESULT status = TPM_SUCCESS;
673
674 /* Default commandline options */
675 struct Opts opts = {
676 .tpmdriver = TPMDRV_TPM_TIS,
677 .tpmiomem = TPM_BASEADDR,
678 .tpmirq = 0,
679 .tpmlocality = 0,
680 .gen_owner_auth = 0,
681 };
682
683 if (parse_cmdline_opts(argc, argv, &opts) != 0) {
684 vtpmlogerror(VTPM_LOG_VTPM, "Command line parsing failed! exiting..\n");
685 status = TPM_BAD_PARAMETER;
686 goto abort_egress;
687 }
688
689 /*Setup storage system*/
690 if (vtpm_storage_init() != 0) {
691 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize storage subsystem!\n");
692 status = TPM_IOERROR;
693 goto abort_egress;
694 }
695
696 /*Setup tpmback device*/
697 init_tpmback(set_opaque, free_opaque);
698
699 /*Setup tpm access*/
700 switch(opts.tpmdriver) {
701 case TPMDRV_TPM_TIS:
702 {
703 struct tpm_chip* tpm;
704 if ((tpm = init_tpm2_tis(opts.tpmiomem, TPM_TIS_LOCL_INT_TO_FLAG(opts.tpmlocality),
705 opts.tpmirq)) == NULL) {
706 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
707 status = TPM_IOERROR;
708 goto abort_egress;
709 }
710 printk("init_tpm2_tis() ...ok\n");
711 vtpm_globals.tpm_fd = tpm_tis_open(tpm);
712 tpm_tis_request_locality(tpm, opts.tpmlocality);
713 }
714 break;
715 case TPMDRV_TPMFRONT:
716 {
717 struct tpmfront_dev* tpmfront_dev;
718 if ((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
719 vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n");
720 status = TPM_IOERROR;
721 goto abort_egress;
722 }
723 vtpm_globals.tpm_fd = tpmfront_open(tpmfront_dev);
724 }
725 break;
726 }
727 printk("TPM 2.0 access ...ok\n");
728 /* Blow away all stale handles left in the tpm*/
729 if (flush_tpm2() != TPM_SUCCESS) {
730 vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing anyway..\n");
731 }
732
733 /* Initialize the rng */
734 entropy_init(&vtpm_globals.entropy);
735 entropy_add_source(&vtpm_globals.entropy, tpm2_entropy_source, NULL, 0);
736 entropy_gather(&vtpm_globals.entropy);
737 ctr_drbg_init(&vtpm_globals.ctr_drbg, entropy_func, &vtpm_globals.entropy, NULL, 0);
738 ctr_drbg_set_prediction_resistance( &vtpm_globals.ctr_drbg, CTR_DRBG_PR_OFF );
739
740 /* Generate Auth for Owner*/
741 if (opts.gen_owner_auth) {
742 vtpmmgr_rand(vtpm_globals.owner_auth, sizeof(TPM_AUTHDATA));
743 }
744
745 /* Load the Manager data, if it fails create a new manager */
746 if (vtpm_load_disk()) {
747 vtpmloginfo(VTPM_LOG_VTPM, "Assuming first time initialization.\n");
748 TPMTRYRETURN(vtpmmgr2_create());
749 }
750
751 goto egress;
752
753 abort_egress:
754 vtpmmgr_shutdown();
755 egress:
756 return status;
757 }
758
tpm2_pcr_read(int index,uint8_t * buf)759 TPM_RC tpm2_pcr_read(int index, uint8_t *buf)
760 {
761 TPM_RESULT status = TPM_SUCCESS;
762 TPML_PCR_SELECTION pcrSelectionIn = {
763 .count = 1,};
764
765 TPMS_PCR_SELECTION tpms_pcr_selection = {
766 .hash = TPM2_ALG_SHA1,
767 .sizeofSelect = PCR_SELECT_MAX,};
768
769 UINT32 pcrUpdateCounter;
770 TPML_PCR_SELECTION pcrSelectionOut;
771 TPML_DIGEST pcrValues;
772 TPM2B_DIGEST tpm2b_digest;
773
774 tpms_pcr_selection.pcrSelect[PCR_SELECT_NUM(index)] = PCR_SELECT_VALUE(index);
775 memcpy(&pcrSelectionIn.pcrSelections[0], &tpms_pcr_selection,
776 sizeof(TPMS_PCR_SELECTION));
777
778 TPMTRYRETURN(TPM2_PCR_Read(pcrSelectionIn, &pcrUpdateCounter,
779 &pcrSelectionOut, &pcrValues));
780
781 if (pcrValues.count < 1)
782 goto egress;
783
784 unpack_TPM2B_DIGEST((uint8_t *) &pcrValues, &tpm2b_digest);
785 memcpy(buf, tpm2b_digest.buffer, SHA1_DIGEST_SIZE);
786
787 abort_egress:
788 egress:
789 return status;
790 }
791