1 /********************************************************************************/
2 /* */
3 /* Sign Application */
4 /* Written by Ken Goldman */
5 /* IBM Thomas J. Watson Research Center */
6 /* */
7 /* (c) Copyright IBM Corporation 2015 - 2019. */
8 /* */
9 /* All rights reserved. */
10 /* */
11 /* Redistribution and use in source and binary forms, with or without */
12 /* modification, are permitted provided that the following conditions are */
13 /* met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright notice, */
16 /* this list of conditions and the following disclaimer. */
17 /* */
18 /* Redistributions in binary form must reproduce the above copyright */
19 /* notice, this list of conditions and the following disclaimer in the */
20 /* documentation and/or other materials provided with the distribution. */
21 /* */
22 /* Neither the names of the IBM Corporation nor the names of its */
23 /* contributors may be used to endorse or promote products derived from */
24 /* this software without specific prior written permission. */
25 /* */
26 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
27 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
28 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
29 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
30 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
31 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
32 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
33 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
34 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
35 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
36 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
37 /********************************************************************************/
38
39 /*
40 Demo application, and test of "no file TSS"
41
42 Prerequisite: A provisioned EK certificate. Use 'clientek' in the acs directory to provision a
43 software TPM EK certificate.
44
45 Program steps:
46
47 Create an EK. The EK would not normally be the storage root key, but this demonstrates use of a
48 policy session, creating an EK primary key using the EK template, and validation of the EK
49 against the EK certificate.
50
51 Start a policy session, salt with EK
52
53 Create a signing key, salted policy session
54
55 Load the signing key, salted policy session
56
57 Start an HMAC session, salt with EK, bind to signing key
58
59 Sign a message, verify the signature
60
61 Flush the signing key
62
63 Flush the EK
64 */
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <stdint.h>
70
71 /* Windows 10 crypto API clashes with openssl */
72 #ifdef TPM_WINDOWS
73 #ifndef WIN32_LEAN_AND_MEAN
74 #define WIN32_LEAN_AND_MEAN
75 #endif
76 #endif
77
78 #include <ibmtss/tss.h>
79 #include <ibmtss/tssutils.h>
80 #include <ibmtss/tssresponsecode.h>
81 #include <ibmtss/tssmarshal.h>
82 #include <ibmtss/tsscryptoh.h>
83 #include <ibmtss/tsscrypto.h>
84 #include <ibmtss/Unmarshal_fp.h>
85 #include "ekutils.h"
86 #include "objecttemplates.h"
87
88 #define KEYPWD "keypwd"
89
90 static TPM_RC startSession(TSS_CONTEXT *tssContext,
91 TPMI_SH_AUTH_SESSION *sessionHandle,
92 TPM_SE sessionType,
93 TPMI_DH_OBJECT tpmKey,
94 TPMI_DH_ENTITY bind,
95 const char *bindPassword);
96 static TPM_RC policyRestart(TSS_CONTEXT *tssContext,
97 TPMI_SH_AUTH_SESSION sessionHandle);
98 static TPM_RC policyCommandCode(TSS_CONTEXT *tssContext,
99 TPM_CC commandCode,
100 TPMI_SH_AUTH_SESSION sessionHandle);
101 static TPM_RC policyAuthValue(TSS_CONTEXT *tssContext,
102 TPMI_SH_AUTH_SESSION sessionHandle);
103 static TPM_RC policyPassword(TSS_CONTEXT *tssContext,
104 TPMI_SH_AUTH_SESSION sessionHandle);
105 static TPM_RC policySecret(TSS_CONTEXT *tssContext,
106 TPMI_DH_ENTITY authHandle,
107 TPMI_SH_AUTH_SESSION sessionHandle);
108 static TPM_RC policyGetDigest(TSS_CONTEXT *tssContext,
109 TPMI_SH_AUTH_SESSION sessionHandle);
110 static TPM_RC createKey(TSS_CONTEXT *tssContext,
111 TPM2B_PRIVATE *outPrivate,
112 TPM2B_PUBLIC *outPublic,
113 TPMI_SH_AUTH_SESSION policySessionHandle,
114 TPM_HANDLE parentHandle,
115 const char *keyPassword,
116 int pwSession);
117 static TPM_RC loadKey(TSS_CONTEXT *tssContext,
118 TPM_HANDLE *keyHandle,
119 TPM_HANDLE parentHandle,
120 TPMI_SH_AUTH_SESSION policySessionHandle,
121 TPM2B_PRIVATE *outPrivate,
122 TPM2B_PUBLIC *outPublic,
123 int pwSession);
124 static TPM_RC sign(TSS_CONTEXT *tssContext,
125 TPMT_SIGNATURE *signature,
126 TPM_HANDLE keyHandle,
127 TPMI_SH_AUTH_SESSION sessionHandle,
128 uint32_t sizeInBytes,
129 TPMT_HA *messageDigest);
130 static TPM_RC verify(TSS_CONTEXT *tssContext,
131 TPM_HANDLE keyHandle,
132 uint32_t sizeInBytes,
133 TPMT_HA *messageDigest,
134 TPMT_SIGNATURE *signature);
135 static TPM_RC flush(TSS_CONTEXT *tssContext,
136 TPMI_DH_CONTEXT flushHandle);
137 static void printUsage(void);
138
139 extern int tssUtilsVerbose;
140
main(int argc,char * argv[])141 int main(int argc, char *argv[])
142 {
143 TPM_RC rc = 0;
144 int i; /* argc iterator */
145 TSS_CONTEXT *tssContext = NULL;
146 int pwSession = FALSE; /* default HMAC session */
147 const char *messageString = NULL;
148 uint32_t sizeInBytes;
149 TPMT_HA messageDigest; /* digest of the message */
150 TPMI_SH_AUTH_SESSION policySessionHandle = TPM_RH_NULL;
151 TPMI_SH_AUTH_SESSION sessionHandle = TPM_RH_NULL;
152 TPM_HANDLE ekKeyHandle = TPM_RH_NULL; /* primary key handle */
153 TPM2B_PRIVATE outPrivate;
154 TPM2B_PUBLIC outPublic;
155 TPM_HANDLE keyHandle = TPM_RH_NULL; /* signing key handle */
156 TPMT_SIGNATURE signature;
157
158 setvbuf(stdout, 0, _IONBF, 0); /* output may be going through pipe to log file */
159 TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "1");
160 tssUtilsVerbose = FALSE;
161
162 /* command line argument defaults */
163 for (i=1 ; (i<argc) && (rc == 0) ; i++) {
164 if (strcmp(argv[i],"-pwsess") == 0) {
165 pwSession = TRUE;
166 }
167 else if (strcmp(argv[i],"-ic") == 0) {
168 i++;
169 if (i < argc) {
170 messageString = argv[i];
171 }
172 else {
173 printf("-ic option needs a value\n");
174 printUsage();
175 }
176 }
177 else if (strcmp(argv[i],"-h") == 0) {
178 printUsage();
179 }
180 else if (strcmp(argv[i],"-v") == 0) {
181 tssUtilsVerbose = TRUE;
182 TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "2");
183 }
184 else {
185 printf("\n%s is not a valid option\n", argv[i]);
186 printUsage();
187 }
188 }
189 if (messageString == NULL) {
190 printf("Missing message -ic\n");
191 printUsage();
192 }
193 /* hash the message file */
194 if (rc == 0) {
195 messageDigest.hashAlg = TPM_ALG_SHA256;
196 /* hash algorithm mapped to size */
197 sizeInBytes = TSS_GetDigestSize(messageDigest.hashAlg);
198 rc = TSS_Hash_Generate(&messageDigest,
199 strlen(messageString), messageString,
200 0, NULL);
201 }
202 /* Start a TSS context */
203 if (rc == 0) {
204 if (tssUtilsVerbose) printf("INFO: Create a TSS context\n");
205 rc = TSS_Create(&tssContext);
206 }
207 /* createprimary first for salt. processPrimary() also reads the EK certificate and validates
208 it against the primary key. It doesn't walk the certificate chain. */
209 if (rc == 0) {
210 if (tssUtilsVerbose) printf("INFO: Create a primary EK for the salt\n");
211 rc = processPrimary(tssContext,
212 &ekKeyHandle,
213 EK_CERT_RSA_INDEX, EK_NONCE_RSA_INDEX, EK_TEMPLATE_RSA_INDEX,
214 TRUE, tssUtilsVerbose); /* do not flush */
215 if (tssUtilsVerbose) printf("INFO: Primary EK handle %08x\n", ekKeyHandle);
216 }
217 /* start a policy session */
218 if (rc == 0) {
219 TPM_HANDLE saltHandle;
220 if (tssUtilsVerbose) printf("INFO: Start a policy session\n");
221 if (!pwSession) {
222 saltHandle = ekKeyHandle;
223 }
224 else {
225 saltHandle = TPM_RH_NULL; /* primary key handle */
226 }
227 rc = startSession(tssContext,
228 &policySessionHandle,
229 TPM_SE_POLICY,
230 saltHandle, TPM_RH_NULL, /* salt, no bind */
231 NULL); /* no bind password */
232 if (tssUtilsVerbose) printf("INFO: Policy session %08x\n", policySessionHandle);
233 }
234 /* EK needs policy secret with endorsement auth */
235 if (rc == 0) {
236 if (tssUtilsVerbose) printf("INFO: Satisfy the policy session %08x\n", policySessionHandle);
237 rc = policySecret(tssContext,
238 TPM_RH_ENDORSEMENT,
239 policySessionHandle);
240 }
241 if (rc == 0) {
242 if (tssUtilsVerbose) printf("INFO: Dump the policy session %08x\n", policySessionHandle);
243 rc = policyGetDigest(tssContext,
244 policySessionHandle);
245 }
246 /* Create the signing key */
247 if (rc == 0) {
248 if (tssUtilsVerbose) printf("INFO: Create a signing key under the EK %08x\n", ekKeyHandle);
249 rc = createKey(tssContext,
250 &outPrivate,
251 &outPublic,
252 policySessionHandle, /* continue */
253 ekKeyHandle, /* parent */
254 KEYPWD, /* password for the signing key */
255 pwSession);
256 }
257 /* reuse the policy session to load the signing key under the EK storage key */
258 if (rc == 0) {
259 if (tssUtilsVerbose) printf("INFO: Restart the policy session %08x\n", policySessionHandle);
260 rc = policyRestart(tssContext,
261 policySessionHandle);
262 }
263 /* EK needs policy secret with endorsement auth */
264 if (rc == 0) {
265 if (tssUtilsVerbose) printf("INFO: Satisfy the policy session %08x\n", policySessionHandle);
266 rc = policySecret(tssContext,
267 TPM_RH_ENDORSEMENT,
268 policySessionHandle);
269 }
270 /* Load the signing key. flush the policy session. */
271 if (rc == 0) {
272 if (tssUtilsVerbose) printf("INFO: Load a signing key under the EK %08x\n", ekKeyHandle);
273 rc = loadKey(tssContext,
274 &keyHandle, /* signing key */
275 ekKeyHandle, /* parent */
276 policySessionHandle, /* no flush */
277 &outPrivate,
278 &outPublic,
279 pwSession);
280 if (tssUtilsVerbose) printf("INFO: Loaded key handle %08x\n", keyHandle);
281 }
282 /* start an HMAC session, salt with EK, bind with signing key */
283 if (rc == 0) {
284 if (!pwSession) {
285 if (tssUtilsVerbose) printf("INFO: Start a salt and bind session\n");
286 rc = startSession(tssContext,
287 &sessionHandle, /* salt, bind */
288 TPM_SE_HMAC,
289 ekKeyHandle, /* salt */
290 keyHandle, /* bind */
291 KEYPWD); /* bind with signing key password */
292
293 if (tssUtilsVerbose) printf("INFO: Salt and bind session %08x\n", sessionHandle);
294 }
295 else {
296 sessionHandle = TPM_RS_PW;
297 }
298 }
299 /*
300 sign and verify using an HMAC or password
301 */
302 /* Sign the message digest */
303 if (rc == 0) {
304 if (tssUtilsVerbose) printf("INFO: Sign with the signing key %08x\n", keyHandle);
305 rc = sign(tssContext,
306 &signature,
307 keyHandle, /* signing key */
308 sessionHandle, /* continue */
309 sizeInBytes, /* hash algorithm mapped to size */
310 &messageDigest); /* digest of the message */
311 }
312 /* Verify the signature */
313 if (rc == 0) {
314 if (tssUtilsVerbose) printf("INFO: Verify the signature %08x\n", keyHandle);
315 rc = verify(tssContext,
316 keyHandle, /* verification public key */
317 sizeInBytes, /* hash algorithm mapped to size */
318 &messageDigest, /* digest of the message */
319 &signature);
320 }
321 /*
322 sign and verify using a policy session, policy authvalue or policy password
323 */
324 if (rc == 0) {
325 if (tssUtilsVerbose) printf("INFO: Restart the policy session %08x\n", policySessionHandle);
326 rc = policyRestart(tssContext,
327 policySessionHandle);
328 }
329 /* policy command code */
330 if (rc == 0) {
331 if (tssUtilsVerbose) printf("INFO: Satisfy the policy session %08x\n", policySessionHandle);
332 rc = policyCommandCode(tssContext,
333 TPM_CC_Sign,
334 policySessionHandle);
335 }
336 /* policy authvalue or policypassword */
337 if (rc == 0) {
338 if (tssUtilsVerbose) printf("INFO: Satisfy the policy session %08x\n", policySessionHandle);
339 if (!pwSession) {
340 rc = policyAuthValue(tssContext,
341 policySessionHandle);
342 }
343 else {
344 rc = policyPassword(tssContext,
345 policySessionHandle);
346 }
347 }
348 if (rc == 0) {
349 if (tssUtilsVerbose) printf("INFO: Dump the policy session %08x\n", policySessionHandle);
350 rc = policyGetDigest(tssContext,
351 policySessionHandle);
352 }
353 /* Sign the message digest */
354 if (rc == 0) {
355 if (tssUtilsVerbose) printf("INFO: Sign with the signing key %08x\n", keyHandle);
356 rc = sign(tssContext,
357 &signature,
358 keyHandle, /* signing key */
359 policySessionHandle, /* continue */
360 sizeInBytes, /* hash algorithm mapped to size */
361 &messageDigest); /* digest of the message */
362 }
363 /* Verify the signature */
364 if (rc == 0) {
365 if (tssUtilsVerbose) printf("INFO: Verify the signature %08x\n", keyHandle);
366 rc = verify(tssContext,
367 keyHandle, /* verification public key */
368 sizeInBytes, /* hash algorithm mapped to size */
369 &messageDigest, /* digest of the message */
370 &signature);
371 }
372 /* flush the policy session, normally fails */
373 if (policySessionHandle != TPM_RH_NULL) {
374 if (tssUtilsVerbose) printf("INFO: Flush the policy session %08x\n", policySessionHandle);
375 flush(tssContext, policySessionHandle);
376 }
377 /* flush the salt and bind session */
378 if (!pwSession) {
379 if (sessionHandle != TPM_RH_NULL) {
380 if (tssUtilsVerbose) printf("INFO: Flush the salt session %08x\n", sessionHandle);
381 flush(tssContext, sessionHandle);
382 }
383 }
384 /* flush the primary key */
385 if (ekKeyHandle != TPM_RH_NULL) {
386 if (tssUtilsVerbose) printf("INFO: Flush the primary key %08x\n", ekKeyHandle);
387 flush(tssContext, ekKeyHandle);
388 }
389 /* flush the signing key */
390 if (keyHandle != TPM_RH_NULL) {
391 if (tssUtilsVerbose) printf("INFO: Flush the signing key %08x\n", keyHandle);
392 flush(tssContext, keyHandle);
393 }
394 {
395 TPM_RC rc1 = TSS_Delete(tssContext);
396 if (rc == 0) {
397 rc = rc1;
398 }
399 }
400 if (rc == 0) {
401 printf("signapp: success\n");
402 }
403 else {
404 const char *msg;
405 const char *submsg;
406 const char *num;
407 printf("signapp: failed, rc %08x\n", rc);
408 TSS_ResponseCode_toString(&msg, &submsg, &num, rc);
409 printf("%s%s%s\n", msg, submsg, num);
410 rc = EXIT_FAILURE;
411 }
412 return rc;
413 }
414
415 /* startSession() starts either a policy or HMAC session.
416
417 If tpmKey is not null, a salted session is used.
418
419 If bind is not null, a bind session is used.
420 */
421
startSession(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION * sessionHandle,TPM_SE sessionType,TPMI_DH_OBJECT tpmKey,TPMI_DH_ENTITY bind,const char * bindPassword)422 static TPM_RC startSession(TSS_CONTEXT *tssContext,
423 TPMI_SH_AUTH_SESSION *sessionHandle,
424 TPM_SE sessionType, /* policy or HMAC */
425 TPMI_DH_OBJECT tpmKey, /* salt key, can be null */
426 TPMI_DH_ENTITY bind, /* bind object, can be null */
427 const char *bindPassword) /* bind object password, can be null */
428 {
429 TPM_RC rc = 0;
430 StartAuthSession_In startAuthSessionIn;
431 StartAuthSession_Out startAuthSessionOut;
432 StartAuthSession_Extra startAuthSessionExtra;
433
434 /* Start an authorization session */
435 if (rc == 0) {
436 startAuthSessionIn.tpmKey = tpmKey; /* salt key */
437 startAuthSessionIn.bind = bind; /* bind object */
438 startAuthSessionExtra.bindPassword = bindPassword; /* bind object password */
439 startAuthSessionIn.sessionType = sessionType; /* HMAC or policy session */
440 startAuthSessionIn.authHash = TPM_ALG_SHA256; /* HMAC algorithm */
441 startAuthSessionIn.symmetric.algorithm = TPM_ALG_AES; /* parameter encryption */
442 startAuthSessionIn.symmetric.keyBits.aes = 128;
443 startAuthSessionIn.symmetric.mode.aes = TPM_ALG_CFB;
444 rc = TSS_Execute(tssContext,
445 (RESPONSE_PARAMETERS *)&startAuthSessionOut,
446 (COMMAND_PARAMETERS *)&startAuthSessionIn,
447 (EXTRA_PARAMETERS *)&startAuthSessionExtra,
448 TPM_CC_StartAuthSession,
449 TPM_RH_NULL, NULL, 0);
450 *sessionHandle = startAuthSessionOut.sessionHandle;
451 }
452 return rc;
453 }
454
policyRestart(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION sessionHandle)455 static TPM_RC policyRestart(TSS_CONTEXT *tssContext,
456 TPMI_SH_AUTH_SESSION sessionHandle)
457 {
458 TPM_RC rc = 0;
459 PolicyRestart_In policyRestartIn;
460
461 if (rc == 0) {
462 policyRestartIn.sessionHandle = sessionHandle;
463 rc = TSS_Execute(tssContext,
464 NULL,
465 (COMMAND_PARAMETERS *)&policyRestartIn,
466 NULL,
467 TPM_CC_PolicyRestart,
468 TPM_RH_NULL, NULL, 0);
469 }
470 return rc;
471 }
472
policyCommandCode(TSS_CONTEXT * tssContext,TPM_CC commandCode,TPMI_SH_AUTH_SESSION sessionHandle)473 static TPM_RC policyCommandCode(TSS_CONTEXT *tssContext,
474 TPM_CC commandCode,
475 TPMI_SH_AUTH_SESSION sessionHandle)
476 {
477 TPM_RC rc = 0;
478 PolicyCommandCode_In policyCommandCodeIn;
479
480 if (rc == 0) {
481 policyCommandCodeIn.policySession = sessionHandle;
482 policyCommandCodeIn.code = commandCode;
483 rc = TSS_Execute(tssContext,
484 NULL,
485 (COMMAND_PARAMETERS *)&policyCommandCodeIn,
486 NULL,
487 TPM_CC_PolicyCommandCode,
488 TPM_RH_NULL, NULL, 0);
489 }
490 return rc;
491 }
492
policyAuthValue(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION sessionHandle)493 static TPM_RC policyAuthValue(TSS_CONTEXT *tssContext,
494 TPMI_SH_AUTH_SESSION sessionHandle)
495 {
496 TPM_RC rc = 0;
497 PolicyAuthValue_In policyAuthValueIn;
498
499 if (rc == 0) {
500 policyAuthValueIn.policySession = sessionHandle;
501 rc = TSS_Execute(tssContext,
502 NULL,
503 (COMMAND_PARAMETERS *)&policyAuthValueIn,
504 NULL,
505 TPM_CC_PolicyAuthValue,
506 TPM_RH_NULL, NULL, 0);
507 }
508 return rc;
509 }
510
policyPassword(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION sessionHandle)511 static TPM_RC policyPassword(TSS_CONTEXT *tssContext,
512 TPMI_SH_AUTH_SESSION sessionHandle)
513 {
514 TPM_RC rc = 0;
515 PolicyPassword_In policyPasswordIn;
516
517 if (rc == 0) {
518 policyPasswordIn.policySession = sessionHandle;
519 rc = TSS_Execute(tssContext,
520 NULL,
521 (COMMAND_PARAMETERS *)&policyPasswordIn,
522 NULL,
523 TPM_CC_PolicyPassword,
524 TPM_RH_NULL, NULL, 0);
525 }
526 return rc;
527 }
528
529 /* policySecret() runs policy secret against the session. It assumes that the secret (the
530 endorsement authorization in this example) is Empty.
531
532 */
533
policySecret(TSS_CONTEXT * tssContext,TPMI_DH_ENTITY authHandle,TPMI_SH_AUTH_SESSION sessionHandle)534 static TPM_RC policySecret(TSS_CONTEXT *tssContext,
535 TPMI_DH_ENTITY authHandle,
536 TPMI_SH_AUTH_SESSION sessionHandle)
537 {
538 TPM_RC rc = 0;
539 PolicySecret_In policySecretIn;
540 PolicySecret_Out policySecretOut;
541
542 if (rc == 0) {
543 policySecretIn.authHandle = authHandle;
544 policySecretIn.policySession = sessionHandle;
545 policySecretIn.nonceTPM.b.size = 0;
546 policySecretIn.cpHashA.b.size = 0;
547 policySecretIn.policyRef.b.size = 0;
548 policySecretIn.expiration = 0;
549 }
550 /* call TSS to execute the command */
551 if (rc == 0) {
552 rc = TSS_Execute(tssContext,
553 (RESPONSE_PARAMETERS *)&policySecretOut,
554 (COMMAND_PARAMETERS *)&policySecretIn,
555 NULL,
556 TPM_CC_PolicySecret,
557 TPM_RS_PW, NULL, 0,
558 TPM_RH_NULL, NULL, 0);
559 }
560 return rc;
561 }
562
563 /* policyGetDigest() traces the session policy digest for debugging. It should be the same as the
564 policy in the EK template.
565
566 */
567
policyGetDigest(TSS_CONTEXT * tssContext,TPMI_SH_AUTH_SESSION sessionHandle)568 static TPM_RC policyGetDigest(TSS_CONTEXT *tssContext,
569 TPMI_SH_AUTH_SESSION sessionHandle)
570 {
571 TPM_RC rc = 0;
572 PolicyGetDigest_In policyGetDigestIn;
573 PolicyGetDigest_Out policyGetDigestOut;
574
575 if (rc == 0) {
576 policyGetDigestIn.policySession = sessionHandle;
577 rc = TSS_Execute(tssContext,
578 (RESPONSE_PARAMETERS *)&policyGetDigestOut,
579 (COMMAND_PARAMETERS *)&policyGetDigestIn,
580 NULL,
581 TPM_CC_PolicyGetDigest,
582 TPM_RH_NULL, NULL, 0);
583 }
584 if (tssUtilsVerbose) TSS_PrintAll("policyGetDigest",
585 policyGetDigestOut.policyDigest.t.buffer,
586 policyGetDigestOut.policyDigest.t.size);
587 return rc;
588 }
589
590 /* createKey() creates a signing key under the EK storage key parentHandle.
591
592 policySessionHandle is a previously satisfied policy session. continue is SET.
593
594 A command decrypt session is used to transfer the signing key userAuth encrypted. A response
595 encrypt session is used just as a demo.
596
597 */
598
createKey(TSS_CONTEXT * tssContext,TPM2B_PRIVATE * outPrivate,TPM2B_PUBLIC * outPublic,TPMI_SH_AUTH_SESSION policySessionHandle,TPM_HANDLE parentHandle,const char * keyPassword,int pwSession)599 static TPM_RC createKey(TSS_CONTEXT *tssContext,
600 TPM2B_PRIVATE *outPrivate,
601 TPM2B_PUBLIC *outPublic,
602 TPMI_SH_AUTH_SESSION policySessionHandle,
603 TPM_HANDLE parentHandle,
604 const char *keyPassword,
605 int pwSession)
606 {
607 TPM_RC rc = 0;
608 Create_In createIn;
609 Create_Out createOut;
610 int attributes;
611 /* hard code the policy since this test is also used for the no file support case */
612 const uint8_t policy[] = {0x7e, 0xa1, 0x0d, 0xe0, 0x05, 0xfc, 0xb2, 0x1d,
613 0x44, 0xf2, 0x4b, 0xc8, 0xf7, 0x4c, 0x28, 0xa8,
614 0xb9, 0xed, 0xf1, 0x4b, 0x1c, 0x53, 0xea, 0x4c,
615 0xcf, 0x3c, 0x5a, 0x4c, 0xe3, 0x8c, 0x75, 0x6e};
616 if (rc == 0) {
617 createIn.parentHandle = parentHandle;
618 rc = TSS_TPM2B_StringCopy(&createIn.inSensitive.sensitive.userAuth.b,
619 keyPassword,
620 sizeof(createIn.inSensitive.sensitive.userAuth.t.buffer));
621 }
622 /* policy command code sign + policy authvalue or policy password */
623 if (rc == 0) {
624 memcpy(&createIn.inPublic.publicArea.authPolicy.b.buffer, policy, sizeof(policy));
625 createIn.inPublic.publicArea.authPolicy.b.size = sizeof(policy);
626 }
627 if (rc == 0) {
628 createIn.inSensitive.sensitive.data.t.size = 0;
629 createIn.inPublic.publicArea.nameAlg = TPM_ALG_SHA256;
630 createIn.inPublic.publicArea.type = TPM_ALG_RSA; /* for the RSA template */
631 createIn.inPublic.publicArea.objectAttributes.val = 0;
632 createIn.inPublic.publicArea.objectAttributes.val |= TPMA_OBJECT_NODA;
633 createIn.inPublic.publicArea.objectAttributes.val |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
634 createIn.inPublic.publicArea.objectAttributes.val |= TPMA_OBJECT_USERWITHAUTH;
635 createIn.inPublic.publicArea.objectAttributes.val &= ~TPMA_OBJECT_ADMINWITHPOLICY;
636 createIn.inPublic.publicArea.objectAttributes.val |= TPMA_OBJECT_SIGN;
637 createIn.inPublic.publicArea.objectAttributes.val &= ~TPMA_OBJECT_DECRYPT;
638 createIn.inPublic.publicArea.objectAttributes.val &= ~TPMA_OBJECT_RESTRICTED;
639 createIn.inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL;
640 createIn.inPublic.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
641 createIn.inPublic.publicArea.parameters.rsaDetail.keyBits = 2048;
642 createIn.inPublic.publicArea.parameters.rsaDetail.exponent = 0;
643 createIn.inPublic.publicArea.unique.rsa.t.size = 0;
644 createIn.outsideInfo.t.size = 0;
645 createIn.creationPCR.count = 0;
646 if (pwSession) {
647 attributes = TPMA_SESSION_CONTINUESESSION;
648 }
649 else {
650 attributes = TPMA_SESSION_ENCRYPT | TPMA_SESSION_DECRYPT | TPMA_SESSION_CONTINUESESSION;
651 }
652 rc = TSS_Execute(tssContext,
653 (RESPONSE_PARAMETERS *)&createOut,
654 (COMMAND_PARAMETERS *)&createIn,
655 NULL,
656 TPM_CC_Create,
657 policySessionHandle, NULL, attributes,
658 TPM_RH_NULL, NULL, 0);
659 }
660 if (rc == 0) {
661 *outPrivate = createOut.outPrivate;
662 *outPublic = createOut.outPublic;
663 }
664 return rc;
665 }
666
667 /* loadKey() loads the signing key under the EK storage key parentHandle.
668
669 policySessionHandle is a previously satisfied policy session. continue is SET.
670
671 A command decrypt and response encrypt session is used just as a demo.
672 */
673
loadKey(TSS_CONTEXT * tssContext,TPM_HANDLE * keyHandle,TPM_HANDLE parentHandle,TPMI_SH_AUTH_SESSION policySessionHandle,TPM2B_PRIVATE * outPrivate,TPM2B_PUBLIC * outPublic,int pwSession)674 static TPM_RC loadKey(TSS_CONTEXT *tssContext,
675 TPM_HANDLE *keyHandle,
676 TPM_HANDLE parentHandle,
677 TPMI_SH_AUTH_SESSION policySessionHandle,
678 TPM2B_PRIVATE *outPrivate,
679 TPM2B_PUBLIC *outPublic,
680 int pwSession)
681 {
682 TPM_RC rc = 0;
683 Load_In loadIn;
684 Load_Out loadOut;
685 int attributes;
686
687 if (rc == 0) {
688 loadIn.parentHandle = parentHandle;
689 loadIn.inPrivate = *outPrivate;
690 loadIn.inPublic = *outPublic;
691 if (pwSession) {
692 attributes = TPMA_SESSION_CONTINUESESSION;
693 }
694 else {
695 attributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_CONTINUESESSION;
696 }
697 rc = TSS_Execute(tssContext,
698 (RESPONSE_PARAMETERS *)&loadOut,
699 (COMMAND_PARAMETERS *)&loadIn,
700 NULL,
701 TPM_CC_Load,
702 policySessionHandle, NULL, attributes,
703 TPM_RH_NULL, NULL, 0);
704 }
705 if (rc == 0) {
706 *keyHandle = loadOut.objectHandle;
707 }
708 return rc;
709 }
710
711 /* sign() signs messageDigest with the signing key keyHandle.
712
713 sessionHandle is a salt and bind session. continue is SET.
714
715 Note that the signing key password is not supplied here. It is supplied when the bind session is
716 created.
717
718 */
719
sign(TSS_CONTEXT * tssContext,TPMT_SIGNATURE * signature,TPM_HANDLE keyHandle,TPMI_SH_AUTH_SESSION sessionHandle,uint32_t sizeInBytes,TPMT_HA * messageDigest)720 static TPM_RC sign(TSS_CONTEXT *tssContext,
721 TPMT_SIGNATURE *signature,
722 TPM_HANDLE keyHandle,
723 TPMI_SH_AUTH_SESSION sessionHandle,
724 uint32_t sizeInBytes, /* hash algorithm mapped to size */
725 TPMT_HA *messageDigest) /* digest of the message */
726 {
727 TPM_RC rc = 0;
728 Sign_In signIn;
729 Sign_Out signOut;
730 const char *pwd;
731 TPM_HT handleType = (TPM_HT) ((sessionHandle & HR_RANGE_MASK) >> HR_SHIFT);
732
733 if (rc == 0) {
734 signIn.keyHandle = keyHandle;
735 signIn.digest.t.size = sizeInBytes;
736 memcpy(&signIn.digest.t.buffer, (uint8_t *)&messageDigest->digest, sizeInBytes);
737 signIn.inScheme.scheme = TPM_ALG_RSASSA;
738 signIn.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA256;
739 signIn.validation.tag = TPM_ST_HASHCHECK; /* optional, to make a ticket */
740 signIn.validation.hierarchy = TPM_RH_NULL;
741 signIn.validation.digest.t.size = 0;
742 /* password session */
743 if (sessionHandle == TPM_RS_PW) {
744 pwd = KEYPWD;
745 }
746 /* policy session is policy password or policy authvalue */
747 else if (handleType == TPM_HT_POLICY_SESSION) {
748 pwd = KEYPWD;
749 }
750 /* HMAC session - bound (password ignored) */
751 else {
752 pwd = NULL;
753 }
754 rc = TSS_Execute(tssContext,
755 (RESPONSE_PARAMETERS *)&signOut,
756 (COMMAND_PARAMETERS *)&signIn,
757 NULL,
758 TPM_CC_Sign,
759 /* bind, observe that no password is required here */
760 sessionHandle, pwd, TPMA_SESSION_CONTINUESESSION,
761 TPM_RH_NULL, NULL, 0);
762 }
763 if (rc == 0) {
764 *signature = signOut.signature;
765 }
766 return rc;
767 }
768
769 /* verify() verifies the signature against the message digest using the previously loaded key in
770 keyHandle.
771
772 */
773
verify(TSS_CONTEXT * tssContext,TPM_HANDLE keyHandle,uint32_t sizeInBytes,TPMT_HA * messageDigest,TPMT_SIGNATURE * signature)774 static TPM_RC verify(TSS_CONTEXT *tssContext,
775 TPM_HANDLE keyHandle,
776 uint32_t sizeInBytes, /* hash algorithm mapped to size */
777 TPMT_HA *messageDigest, /* digest of the message */
778 TPMT_SIGNATURE *signature)
779 {
780 TPM_RC rc = 0;
781 VerifySignature_In verifySignatureIn;
782 VerifySignature_Out verifySignatureOut;
783
784 if (rc == 0) {
785 verifySignatureIn.keyHandle = keyHandle;
786 verifySignatureIn.digest.t.size = sizeInBytes;
787 memcpy(&verifySignatureIn.digest.t.buffer, (uint8_t *)&messageDigest->digest, sizeInBytes);
788 verifySignatureIn.signature = *signature;
789 }
790 if (rc == 0) {
791 rc = TSS_Execute(tssContext,
792 (RESPONSE_PARAMETERS *)&verifySignatureOut,
793 (COMMAND_PARAMETERS *)&verifySignatureIn,
794 NULL,
795 TPM_CC_VerifySignature,
796 TPM_RH_NULL, NULL, 0);
797 }
798 return rc;
799 }
800
801 /* flush() flushes some handle, either a session or the signing key in this demo.
802
803 */
804
flush(TSS_CONTEXT * tssContext,TPMI_DH_CONTEXT flushHandle)805 static TPM_RC flush(TSS_CONTEXT *tssContext,
806 TPMI_DH_CONTEXT flushHandle)
807 {
808 TPM_RC rc = 0;
809 FlushContext_In in;
810
811 if (rc == 0) {
812 in.flushHandle = flushHandle;
813 rc = TSS_Execute(tssContext,
814 NULL,
815 (COMMAND_PARAMETERS *)&in,
816 NULL,
817 TPM_CC_FlushContext,
818 TPM_RH_NULL, NULL, 0);
819 }
820 return rc;
821 }
822
printUsage(void)823 static void printUsage(void)
824 {
825 printf("\n");
826 printf("signapp\n");
827 printf("\n");
828 printf("Runs a TPM2_Sign application, including creating a primary storage key\n");
829 printf("and creating and loading a signing key\n");
830 printf("\n");
831 printf("\t-ic\tinput message to hash and sign\n");
832 printf("\n");
833 printf("\t[-pwsess\tUse a password session, no HMAC or parameter encryption]\n");
834 printf("\n");
835 exit(1);
836 }
837