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