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