1 /********************************************************************************/
2 /*										*/
3 /*			    TSS Configuration Properties			*/
4 /*			     Written by Ken Goldman				*/
5 /*		       IBM Thomas J. Watson Research Center			*/
6 /*										*/
7 /* (c) Copyright IBM Corporation 2015 - 2020.					*/
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 #include <stdlib.h>
40 #include <string.h>
41 #include <stdarg.h>
42 #include <errno.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 
46 #include <ibmtss/tss.h>
47 #include <ibmtss/tsstransmit.h>
48 #ifndef TPM_TSS_NOCRYPTO
49 #include <ibmtss/tsscrypto.h>
50 #endif
51 #include <ibmtss/tssprint.h>
52 
53 #include "tssproperties.h"
54 
55 /* For systems where there are no environment variables, GETENV returns NULL.  This simulates the
56    situation when an environment variable is not set, causing the compiled in default to be used. */
57 #ifndef TPM_TSS_NOENV
58 #define GETENV(x) getenv(x)
59 #else
60 #define GETENV(x) NULL
61 #endif
62 
63 /* local prototypes */
64 
65 static TPM_RC TSS_SetTraceLevel(const char *value);
66 static TPM_RC TSS_SetDataDirectory(TSS_CONTEXT *tssContext, const char *value);
67 static TPM_RC TSS_SetCommandPort(TSS_CONTEXT *tssContext, const char *value);
68 static TPM_RC TSS_SetPlatformPort(TSS_CONTEXT *tssContext, const char *value);
69 static TPM_RC TSS_SetServerName(TSS_CONTEXT *tssContext, const char *value);
70 static TPM_RC TSS_SetServerType(TSS_CONTEXT *tssContext, const char *value);
71 static TPM_RC TSS_SetInterfaceType(TSS_CONTEXT *tssContext, const char *value);
72 static TPM_RC TSS_SetDevice(TSS_CONTEXT *tssContext, const char *value);
73 static TPM_RC TSS_SetEncryptSessions(TSS_CONTEXT *tssContext, const char *value);
74 
75 /* globals for the library */
76 
77 /* tracing is global to avoid passing the context into every function call */
78 int tssVerbose = TRUE;		/* initial value so TSS_Properties_Init errors emit message */
79 int tssVverbose = FALSE;
80 
81 /* This is a total hack to ensure that the global verbose flags are only set once.  It's used by the
82    two entry points to the TSS, TSS_Create() and TSS_SetProperty() */
83 
84 int tssFirstCall = TRUE;
85 
86 /* defaults for global settings */
87 
88 #ifndef TPM_TRACE_LEVEL_DEFAULT
89 #define TPM_TRACE_LEVEL_DEFAULT 	"0"
90 #endif
91 
92 #ifndef TPM_COMMAND_PORT_DEFAULT
93 #define TPM_COMMAND_PORT_DEFAULT 	"2321"		/* default for MS simulator */
94 #endif
95 
96 #ifndef TPM_PLATFORM_PORT_DEFAULT
97 #define TPM_PLATFORM_PORT_DEFAULT 	"2322"		/* default for MS simulator */
98 #endif
99 
100 #ifndef TPM_SERVER_NAME_DEFAULT
101 #define TPM_SERVER_NAME_DEFAULT		"localhost"	/* default to local machine */
102 #endif
103 
104 #ifndef TPM_SERVER_TYPE_DEFAULT
105 #define TPM_SERVER_TYPE_DEFAULT		"mssim"		/* default to MS simulator format */
106 #endif
107 
108 #ifndef TPM_DATA_DIR_DEFAULT
109 #define TPM_DATA_DIR_DEFAULT		"."		/* default to current working directory */
110 #endif
111 
112 #ifndef TPM_INTERFACE_TYPE_DEFAULT
113 #ifndef TPM_NOSOCKET
114 #define TPM_INTERFACE_TYPE_DEFAULT	"socsim"	/* default to MS simulator interface */
115 #else
116 #define TPM_INTERFACE_TYPE_DEFAULT	"dev"		/* if no sockets, default to device driver */
117 #endif
118 #endif
119 
120 #ifndef TPM_DEVICE_DEFAULT
121 #ifdef TPM_POSIX
122 #define TPM_DEVICE_DEFAULT		"/dev/tpm0"	/* default to Linux device driver */
123 #endif
124 #ifdef TPM_WINDOWS
125 #define TPM_DEVICE_DEFAULT		"tddl.dll"	/* default to Windows TPM interface dll */
126 #endif
127 #endif
128 
129 #ifndef TPM_ENCRYPT_SESSIONS_DEFAULT
130 #define TPM_ENCRYPT_SESSIONS_DEFAULT	"1"
131 #endif
132 
133 /* TSS_GlobalProperties_Init() sets the global verbose trace flags at the first entry points to the
134    TSS */
135 
TSS_GlobalProperties_Init(void)136 TPM_RC TSS_GlobalProperties_Init(void)
137 {
138     TPM_RC		rc = 0;
139     const char 		*value;
140 
141     /* trace level is global, tssContext can be null */
142     if (rc == 0) {
143 	value = GETENV("TPM_TRACE_LEVEL");
144 	rc = TSS_SetTraceLevel(value);
145     }
146     return rc;
147 }
148 
149 
150 /* TSS_Properties_Init() sets the initial TSS_CONTEXT properties based on either the environment
151    variables (if set) or the defaults (if not).
152 */
153 
TSS_Properties_Init(TSS_CONTEXT * tssContext)154 TPM_RC TSS_Properties_Init(TSS_CONTEXT *tssContext)
155 {
156     TPM_RC		rc = 0;
157     const char 		*value;
158 
159     if (rc == 0) {
160 	tssContext->tssAuthContext = NULL;
161 	tssContext->tssFirstTransmit = TRUE;	/* connection not opened */
162 	tssContext->tpm12Command = FALSE;
163 #ifdef TPM_WINDOWS
164 	tssContext->sock_fd = INVALID_SOCKET;
165 #endif
166 #ifdef TPM_POSIX
167 #ifndef TPM_NOSOCKET
168 	tssContext->sock_fd = -1;
169 #endif 	/* TPM_NOSOCKET */
170 	tssContext->dev_fd = -1;
171 #endif	/* TPM_POSIX */
172 
173 #ifdef TPM_SKIBOOT
174 	tssContext->tpm_driver = NULL;
175 	tssContext->tpm_device = NULL;
176 #endif /* TPM_SKIBOOT */
177 
178 #ifndef TPM_TSS_NOCRYPTO
179 #ifndef TPM_TSS_NOFILE
180 	tssContext->tssSessionEncKey = NULL;
181 	tssContext->tssSessionDecKey = NULL;
182 #endif
183 #endif
184     }
185     /* for a minimal TSS with no file support */
186 #ifdef TPM_TSS_NOFILE
187     {
188 	size_t i;
189 	for (i = 0 ; i < (sizeof(tssContext->sessions) / sizeof(TSS_SESSIONS)) ; i++) {
190 	    tssContext->sessions[i].sessionHandle = TPM_RH_NULL;
191 	    tssContext->sessions[i].sessionData = NULL;
192 	    tssContext->sessions[i].sessionDataLength = 0;
193 	}
194 	for (i = 0 ; i < (sizeof(tssContext->objectPublic) / sizeof(TSS_OBJECT_PUBLIC)) ; i++) {
195 	    tssContext->objectPublic[i].objectHandle = TPM_RH_NULL;
196 	}
197 	for (i = 0 ; i < (sizeof(tssContext->nvPublic) / sizeof(TSS_NVPUBLIC)) ; i++) {
198 	    tssContext->nvPublic[i].nvIndex = TPM_RH_NULL;
199 	}
200     }
201 #endif
202     /* data directory */
203     if (rc == 0) {
204 	value = GETENV("TPM_DATA_DIR");
205 	rc = TSS_SetDataDirectory(tssContext, value);
206     }
207     /* flag whether session state should be encrypted */
208     if (rc == 0) {
209 	value = GETENV("TPM_ENCRYPT_SESSIONS");
210 	rc = TSS_SetEncryptSessions(tssContext, value);
211     }
212     /* TPM socket command port */
213     if (rc == 0) {
214 	value = GETENV("TPM_COMMAND_PORT");
215 	rc = TSS_SetCommandPort(tssContext, value);
216     }
217     /* TPM simulator socket platform port */
218     if (rc == 0) {
219 	value = GETENV("TPM_PLATFORM_PORT");
220 	rc = TSS_SetPlatformPort(tssContext, value);
221     }
222     /* TPM socket host name */
223     if (rc == 0) {
224 	value = GETENV("TPM_SERVER_NAME");
225 	rc = TSS_SetServerName(tssContext, value);
226     }
227     /* TPM socket server type */
228     if (rc == 0) {
229 	value = GETENV("TPM_SERVER_TYPE");
230 	rc = TSS_SetServerType(tssContext, value);
231     }
232     /* TPM interface type */
233     if (rc == 0) {
234 	value = GETENV("TPM_INTERFACE_TYPE");
235 	rc = TSS_SetInterfaceType(tssContext, value);
236     }
237     /* TPM device within the interface type */
238     if (rc == 0) {
239 	value = GETENV("TPM_DEVICE");
240 	rc = TSS_SetDevice(tssContext, value);
241     }
242     return rc;
243 }
244 
245 /* TSS_SetProperty() sets the property to the value.
246 
247    The format of the property and value the same as that of the environment variable.
248 
249    A NULL value sets the property to the default.
250 */
251 
TSS_SetProperty(TSS_CONTEXT * tssContext,int property,const char * value)252 TPM_RC TSS_SetProperty(TSS_CONTEXT *tssContext,
253 		       int property,
254 		       const char *value)
255 {
256     TPM_RC		rc = 0;
257 
258     /* at the first call to the TSS, initialize global variables */
259     if (tssFirstCall) {
260 #ifndef TPM_TSS_NOCRYPTO
261 	/* crypto module initializations */
262 	if (rc == 0) {
263 	    rc = TSS_Crypto_Init();
264 	}
265 #endif
266 	if (rc == 0) {
267 	    rc = TSS_GlobalProperties_Init();
268 	}
269 	tssFirstCall = FALSE;
270     }
271     if (rc == 0) {
272 	switch (property) {
273 	  case TPM_TRACE_LEVEL:
274 	    rc = TSS_SetTraceLevel(value);
275 	    break;
276 	  case TPM_DATA_DIR:
277 	    rc = TSS_SetDataDirectory(tssContext, value);
278 	    break;
279 	  case TPM_COMMAND_PORT:
280 	    rc = TSS_SetCommandPort(tssContext, value);
281 	    break;
282 	  case TPM_PLATFORM_PORT:
283 	    rc = TSS_SetPlatformPort(tssContext, value);
284 	    break;
285 	  case TPM_SERVER_NAME:
286 	    rc = TSS_SetServerName(tssContext, value);
287 	    break;
288 	  case TPM_SERVER_TYPE:
289 	    rc = TSS_SetServerType(tssContext, value);
290 	    break;
291 	  case TPM_INTERFACE_TYPE:
292 	    rc = TSS_SetInterfaceType(tssContext, value);
293 	    break;
294 	  case TPM_DEVICE:
295 	    rc = TSS_SetDevice(tssContext, value);
296 	    break;
297 	  case TPM_ENCRYPT_SESSIONS:
298 	    rc = TSS_SetEncryptSessions(tssContext, value);
299 	    break;
300 	  default:
301 	    rc = TSS_RC_BAD_PROPERTY;
302 	}
303     }
304     return rc;
305 }
306 
307 /* TSS_SetTraceLevel() sets the trace level.
308 
309    0:	no printing
310    1:	error printing
311    2:	trace printing
312 */
313 
TSS_SetTraceLevel(const char * value)314 static TPM_RC TSS_SetTraceLevel(const char *value)
315 {
316     TPM_RC		rc = 0;
317     int			irc = 0;
318     int 		level;
319 
320     if (rc == 0) {
321 	if (value == NULL) {
322 	    value = TPM_TRACE_LEVEL_DEFAULT;
323 	}
324     }
325 #if !defined(__ULTRAVISOR__) && !defined(TPM_SKIBOOT)
326     if (rc == 0) {
327 	irc = sscanf(value, "%u", &level);
328 	if (irc != 1) {
329 	    if (tssVerbose) printf("TSS_SetTraceLevel: Error, value invalid\n");
330 	    rc = TSS_RC_BAD_PROPERTY_VALUE;
331 	}
332     }
333     /* disable tracing within the ultravisor and skiboot, which doesn't implement sscanf() anyway */
334 #else
335     irc = irc;
336     level = 0;
337 #endif
338     if (rc == 0) {
339 	switch (level) {
340 	  case 0:
341 	    tssVerbose = FALSE;
342 	    tssVverbose = FALSE;
343 	    break;
344 	  case 1:
345 	    tssVerbose = TRUE;
346 	    tssVverbose = FALSE;
347 	    break;
348 	  default:
349 	    tssVerbose = TRUE;
350 	    tssVverbose = TRUE;
351 	    break;
352 	}
353     }
354     return rc;
355 }
356 
TSS_SetDataDirectory(TSS_CONTEXT * tssContext,const char * value)357 static TPM_RC TSS_SetDataDirectory(TSS_CONTEXT *tssContext, const char *value)
358 {
359     TPM_RC		rc = 0;
360 
361     if (rc == 0) {
362 	if (value == NULL) {
363 	    value = TPM_DATA_DIR_DEFAULT;
364 	}
365     }
366     if (rc == 0) {
367 	tssContext->tssDataDirectory = value;
368 	/* appended to this is 17 characters /cccnnnnnnnn.bin[nul], add a bit of margin for future
369 	   prefixes */
370 	if (strlen(value) > (TPM_DATA_DIR_PATH_LENGTH - 24)) {
371 	    if (tssVerbose) printf("TSS_SetDataDirectory: Error, value too long\n");
372 	    rc = TSS_RC_BAD_PROPERTY_VALUE;
373 	}
374     }
375     return rc;
376 }
377 
TSS_SetCommandPort(TSS_CONTEXT * tssContext,const char * value)378 static TPM_RC TSS_SetCommandPort(TSS_CONTEXT *tssContext, const char *value)
379 {
380     TPM_RC		rc = 0;
381     int			irc = 0;
382 
383     /* close an open connection before changing property */
384     if (rc == 0) {
385 	rc = TSS_Close(tssContext);
386     }
387     if (rc == 0) {
388 	if (value == NULL) {
389 	    value = TPM_COMMAND_PORT_DEFAULT;
390 	}
391     }
392 #ifndef TPM_NOSOCKET
393     if (rc == 0) {
394 	irc = sscanf(value, "%hu", &tssContext->tssCommandPort);
395 	if (irc != 1) {
396 	    if (tssVerbose) printf("TSS_SetCommandPort: Error, value invalid\n");
397 	    rc = TSS_RC_BAD_PROPERTY_VALUE;
398 	}
399     }
400 #else
401     tssContext->tssCommandPort = 0;
402     irc = irc;
403 #endif /* TPM_NOSOCKET */
404     return rc;
405 }
406 
TSS_SetPlatformPort(TSS_CONTEXT * tssContext,const char * value)407 static TPM_RC TSS_SetPlatformPort(TSS_CONTEXT *tssContext, const char *value)
408 {
409     TPM_RC		rc = 0;
410     int			irc = 0;
411 
412     /* close an open connection before changing property */
413     if (rc == 0) {
414 	rc = TSS_Close(tssContext);
415     }
416     if (rc == 0) {
417 	if (value == NULL) {
418 	    value = TPM_PLATFORM_PORT_DEFAULT;
419 	}
420     }
421 #ifndef TPM_NOSOCKET
422    if (rc == 0) {
423 	irc = sscanf(value, "%hu", &tssContext->tssPlatformPort);
424 	if (irc != 1) {
425 	    if (tssVerbose) printf("TSS_SetPlatformPort: Error, , value invalid\n");
426 	    rc = TSS_RC_BAD_PROPERTY_VALUE;
427 	}
428     }
429 #else
430    tssContext->tssPlatformPort = 0;
431     irc = irc;
432 #endif /* TPM_NOSOCKET */
433     return rc;
434 }
435 
TSS_SetServerName(TSS_CONTEXT * tssContext,const char * value)436 static TPM_RC TSS_SetServerName(TSS_CONTEXT *tssContext, const char *value)
437 {
438     TPM_RC		rc = 0;
439 
440     /* close an open connection before changing property */
441     if (rc == 0) {
442 	rc = TSS_Close(tssContext);
443     }
444     if (rc == 0) {
445 	if (value == NULL) {
446 	    value = TPM_SERVER_NAME_DEFAULT;
447 	}
448     }
449     if (rc == 0) {
450 	tssContext->tssServerName = value;
451     }
452     return rc;
453 }
454 
TSS_SetServerType(TSS_CONTEXT * tssContext,const char * value)455 static TPM_RC TSS_SetServerType(TSS_CONTEXT *tssContext, const char *value)
456 {
457     TPM_RC		rc = 0;
458 
459     /* close an open connection before changing property */
460     if (rc == 0) {
461 	rc = TSS_Close(tssContext);
462     }
463     if (rc == 0) {
464 	if (value == NULL) {
465 	    value = TPM_SERVER_TYPE_DEFAULT;
466 	}
467     }
468     if (rc == 0) {
469 	tssContext->tssServerType = value;
470     }
471     return rc;
472 }
473 
TSS_SetInterfaceType(TSS_CONTEXT * tssContext,const char * value)474 static TPM_RC TSS_SetInterfaceType(TSS_CONTEXT *tssContext, const char *value)
475 {
476     TPM_RC		rc = 0;
477 
478     /* close an open connection before changing property */
479     if (rc == 0) {
480 	rc = TSS_Close(tssContext);
481     }
482     if (rc == 0) {
483 	if (value == NULL) {
484 	    value = TPM_INTERFACE_TYPE_DEFAULT;
485 	}
486     }
487     if (rc == 0) {
488 	tssContext->tssInterfaceType = value;
489     }
490     return rc;
491 }
492 
TSS_SetDevice(TSS_CONTEXT * tssContext,const char * value)493 static TPM_RC TSS_SetDevice(TSS_CONTEXT *tssContext, const char *value)
494 {
495     TPM_RC		rc = 0;
496 
497     /* close an open connection before changing property */
498     if (rc == 0) {
499 	rc = TSS_Close(tssContext);
500     }
501     if (rc == 0) {
502 	if (value == NULL) {
503 	    value = TPM_DEVICE_DEFAULT;
504 	}
505     }
506     if (rc == 0) {
507 	tssContext->tssDevice = value;
508     }
509     return rc;
510 }
511 
TSS_SetEncryptSessions(TSS_CONTEXT * tssContext,const char * value)512 static TPM_RC TSS_SetEncryptSessions(TSS_CONTEXT *tssContext, const char *value)
513 {
514     TPM_RC		rc = 0;
515     int			irc = 0;
516 
517     if (rc == 0) {
518 	if (value == NULL) {
519 	    value = TPM_ENCRYPT_SESSIONS_DEFAULT;
520 	}
521     }
522 #ifndef TPM_TSS_NOFILE
523    if (rc == 0) {
524 	irc = sscanf(value, "%u", &tssContext->tssEncryptSessions);
525 	if (irc != 1) {
526 	    if (tssVerbose) printf("TSS_SetEncryptSessions: Error, value invalid\n");
527 	    rc = TSS_RC_BAD_PROPERTY_VALUE;
528 	}
529     }
530 #else
531    tssContext->tssEncryptSessions = TRUE;
532    irc = irc;
533 #endif /* TPM_TSS_NOFILE */
534    return rc;
535 }
536