1 /********************************************************************************/
3 /* LibTPM TPM 1.2 call interface functions */
4 /* Written by Stefan Berger */
5 /* IBM Thomas J. Watson Research Center */
7 /* (c) Copyright IBM Corporation 2015. */
9 /* All rights reserved. */
11 /* Redistribution and use in source and binary forms, with or without */
12 /* modification, are permitted provided that the following conditions are */
15 /* Redistributions of source code must retain the above copyright notice, */
16 /* this list of conditions and the following disclaimer. */
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. */
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. */
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 /********************************************************************************/
48 #include "tpm12/tpm_debug.h"
49 #include "tpm_error.h"
50 #include "tpm12/tpm_init.h"
51 #include "tpm_library_intern.h"
52 #include "tpm12/tpm_process.h"
53 #include "tpm12/tpm_startup.h"
54 #include "tpm12/tpm_global.h"
55 #include "tpm12/tpm_permanent.h"
56 #include "tpm12/tpm_nvfile.h"
58 TPM_RESULT
TPM12_MainInit(void)
60 return TPM_MainInit();
63 void TPM12_Terminate(void)
65 TPM_Global_Delete(tpm_instances
[0]);
66 free(tpm_instances
[0]);
67 tpm_instances
[0] = NULL
;
70 TPM_RESULT
TPM12_Process(unsigned char **respbuffer
, uint32_t *resp_size
,
71 uint32_t *respbufsize
,
72 unsigned char *command
, uint32_t command_size
)
75 return TPM_ProcessA(respbuffer
, resp_size
, respbufsize
,
76 command
, command_size
);
79 TPM_RESULT
TPM12_VolatileAllStore(unsigned char **buffer
,
84 TPM_Sbuffer_Init(&tsb
);
88 assert(tpm_instances
[0] != NULL
);
91 rc
= TPM_VolatileAll_Store(&tsb
, tpm_instances
[0]);
93 if (rc
== TPM_SUCCESS
) {
94 /* caller now owns the buffer and needs to free it */
95 TPM_Sbuffer_GetAll(&tsb
, buffer
, buflen
, &total
);
97 TPM_Sbuffer_Delete(&tsb
);
105 TPM_RESULT
TPM12_CancelCommand(void)
107 return TPM_FAIL
; /* not supported */
111 TPM_RESULT
TPM12_GetTPMProperty(enum TPMLIB_TPMProperty prop
,
115 case TPMPROP_TPM_RSA_KEY_LENGTH_MAX
:
116 *result
= TPM_RSA_KEY_LENGTH_MAX
;
119 case TPMPROP_TPM_KEY_HANDLES
:
120 *result
= TPM_KEY_HANDLES
;
123 case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES
:
124 *result
= TPM_OWNER_EVICT_KEY_HANDLES
;
127 case TPMPROP_TPM_MIN_AUTH_SESSIONS
:
128 *result
= TPM_MIN_AUTH_SESSIONS
;
131 case TPMPROP_TPM_MIN_TRANS_SESSIONS
:
132 *result
= TPM_MIN_TRANS_SESSIONS
;
135 case TPMPROP_TPM_MIN_DAA_SESSIONS
:
136 *result
= TPM_MIN_DAA_SESSIONS
;
139 case TPMPROP_TPM_MIN_SESSION_LIST
:
140 *result
= TPM_MIN_SESSION_LIST
;
143 case TPMPROP_TPM_MIN_COUNTERS
:
144 *result
= TPM_MIN_COUNTERS
;
147 case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN
:
148 *result
= TPM_NUM_FAMILY_TABLE_ENTRY_MIN
;
151 case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN
:
152 *result
= TPM_NUM_DELEGATE_TABLE_ENTRY_MIN
;
155 case TPMPROP_TPM_SPACE_SAFETY_MARGIN
:
156 *result
= TPM_SPACE_SAFETY_MARGIN
;
159 case TPMPROP_TPM_MAX_NV_SPACE
:
160 /* fill up 20 kb.; this provides some safety margin (currently
161 >4Kb) for possible future expansion of this blob */
162 *result
= ROUNDUP(TPM_MAX_NV_SPACE
, 20 * 1024);
165 case TPMPROP_TPM_MAX_SAVESTATE_SPACE
:
166 *result
= TPM_MAX_SAVESTATE_SPACE
;
169 case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE
:
170 *result
= TPM_MAX_VOLATILESTATE_SPACE
;
183 * @flags: logical or of flags that query for information
185 * Return a JSON document with contents queried for by the user's passed flags
187 char *TPM12_GetInfo(enum TPMLIB_InfoFlags flags
)
189 const char *tpmspec
=
190 "\"TPMSpecification\":{"
191 "\"family\":\"1.2\","
195 const char *tpmattrs
=
196 "\"TPMAttributes\":{"
197 "\"manufacturer\":\"id:00001014\","
198 "\"version\":\"id:00740001\"," /* 146.1 */
199 "\"model\":\"swtpm\""
201 char *fmt
= NULL
, *buffer
;
202 bool printed
= false;
204 if (!(buffer
= strdup("{%s%s%s}")))
207 if ((flags
& TPMLIB_INFO_TPMSPECIFICATION
)) {
210 if (asprintf(&buffer
, fmt
, "", tpmspec
, "%s%s%s") < 0)
215 if ((flags
& TPMLIB_INFO_TPMATTRIBUTES
)) {
218 if (asprintf(&buffer
, fmt
, printed
? "," : "",
219 tpmattrs
, "%s%s%s") < 0)
225 /* nothing else to add */
228 if (asprintf(&buffer
, fmt
, "", "", "") < 0)
241 static uint32_t tpm12_buffersize
= TPM_BUFFER_MAX
;
243 uint32_t TPM12_SetBufferSize(uint32_t wanted_size
,
248 *min_size
= TPM_BUFFER_MIN
;
250 *max_size
= TPM_BUFFER_MAX
;
252 if (wanted_size
== 0)
253 return tpm12_buffersize
;
255 if (wanted_size
> TPM_BUFFER_MAX
)
256 wanted_size
= TPM_BUFFER_MAX
;
257 else if (wanted_size
< TPM_BUFFER_MIN
)
258 wanted_size
= TPM_BUFFER_MIN
;
260 tpm12_buffersize
= wanted_size
;
262 return tpm12_buffersize
;
265 uint32_t TPM12_GetBufferSize(void)
267 return TPM12_SetBufferSize(0, NULL
, NULL
);
270 TPM_RESULT
TPM12_ValidateState(enum TPMLIB_StateType st
,
273 TPM_RESULT ret
= TPM_SUCCESS
;
274 tpm_state_t tpm_state
;
275 enum TPMLIB_StateType sts
[] = {
276 TPMLIB_STATE_PERMANENT
,
277 TPMLIB_STATE_VOLATILE
,
278 TPMLIB_STATE_SAVE_STATE
,
281 enum TPMLIB_StateType c_st
;
284 #ifdef TPM_LIBTPMS_CALLBACKS
285 struct libtpms_callbacks
*cbs
= TPMLIB_GetCallbacks();
287 if (cbs
->tpm_nvram_init
) {
288 ret
= cbs
->tpm_nvram_init();
289 if (ret
!= TPM_SUCCESS
)
294 ret
= TPM_Global_Init(&tpm_state
);
295 tpm_state
.tpm_number
= 0;
297 if (ret
== TPM_SUCCESS
) {
298 /* permanent state needs to be there and loaded first */
299 ret
= TPM_PermanentAll_NVLoad(&tpm_state
);
302 for (i
= 0; sts
[i
] && ret
== TPM_SUCCESS
; i
++) {
305 /* 'cached' state is known to 'work', so skip it */
306 if (!c_st
|| HasCachedState(c_st
))
310 case TPMLIB_STATE_PERMANENT
:
312 case TPMLIB_STATE_VOLATILE
:
313 ret
= TPM_VolatileAll_NVLoad(&tpm_state
);
315 case TPMLIB_STATE_SAVE_STATE
:
316 ret
= TPM_SaveState_NVLoad(&tpm_state
);
321 TPM_Global_Delete(&tpm_state
);
326 static TPM_RESULT
_TPM_PermanentAll_Store(TPM_STORE_BUFFER
*sbuffer
,
327 tpm_state_t
*tpm_state
)
329 const unsigned char *buffer
= NULL
;
332 return TPM_PermanentAll_Store(sbuffer
, &buffer
, &buflen
, tpm_state
);
336 * TPM_PermanentAll_NVLoad_Preserve
338 * @tpm_state: The tpm_state to load the permanent state into
340 * Call TPM_PermanentAll_NVLoad and preserve any cached data that a call
341 * to TPM_PermanentAll_NVLoad (TPM_NVRAM_LoadData) may otherwise consume
342 * and remove if it was available.
344 static TPM_RESULT
TPM_PermanentAll_NVLoad_Preserve(tpm_state_t
*tpm_state
)
347 unsigned char *buffer
= NULL
;
349 bool is_empty_buffer
;
351 ret
= CopyCachedState(TPMLIB_STATE_PERMANENT
,
352 &buffer
, &buffer_len
, &is_empty_buffer
);
353 if (ret
== TPM_SUCCESS
) {
354 ret
= TPM_PermanentAll_NVLoad(tpm_state
);
356 /* restore a previous empty buffer or any valid buffer */
357 if (is_empty_buffer
|| buffer
!= NULL
)
358 SetCachedState(TPMLIB_STATE_PERMANENT
, buffer
, buffer_len
);
365 * Get the state blob of the given type. If we TPM is not running, we
366 * get the cached state blobs, if available, otherwise we try to read
367 * it from files. In case the TPM is running, we get it from the running
370 TPM_RESULT
TPM12_GetState(enum TPMLIB_StateType st
,
371 unsigned char **buffer
, uint32_t *buflen
)
373 TPM_RESULT ret
= TPM_FAIL
;
374 TPM_STORE_BUFFER tsb
;
377 /* TPM not running ? */
378 if (tpm_instances
[0] == NULL
) {
379 struct libtpms_callbacks
*cbs
= TPMLIB_GetCallbacks();
380 bool is_empty_buffer
;
382 /* try cached blob before file */
383 ret
= CopyCachedState(st
, buffer
, buflen
, &is_empty_buffer
);
384 if (ret
!= TPM_SUCCESS
|| *buffer
!= NULL
|| is_empty_buffer
)
387 if (cbs
->tpm_nvram_init
) {
388 ret
= cbs
->tpm_nvram_init();
389 if (ret
!= TPM_SUCCESS
)
392 ret
= TPM_NVRAM_LoadData(buffer
, buflen
, 0,
393 TPMLIB_StateTypeToName(st
));
400 TPM_Sbuffer_Init(&tsb
);
403 case TPMLIB_STATE_PERMANENT
:
404 ret
= _TPM_PermanentAll_Store(&tsb
, tpm_instances
[0]);
406 case TPMLIB_STATE_VOLATILE
:
407 ret
= TPM_VolatileAll_Store(&tsb
, tpm_instances
[0]);
409 case TPMLIB_STATE_SAVE_STATE
:
410 ret
= TPM_SaveState_Store(&tsb
, tpm_instances
[0]);
414 if (ret
== TPM_SUCCESS
) {
415 /* caller now owns the buffer and needs to free it */
416 TPM_Sbuffer_GetAll(&tsb
, buffer
, buflen
, &total
);
418 TPM_Sbuffer_Delete(&tsb
);
427 * Set the state the TPM 1.2 will use upon next TPM_MainInit(). The TPM 1.2
428 * must not have been started, yet, or it must have been terminated for this
429 * function to set the state.
431 * @st: The TPMLIB_StateType describing the type of blob in the buffer
432 * @buffer: pointer to the buffer containing the state blob; NULL pointer clears
434 * @buflen: length of the buffer
436 TPM_RESULT
TPM12_SetState(enum TPMLIB_StateType st
,
437 const unsigned char *buffer
, uint32_t buflen
)
439 TPM_RESULT ret
= TPM_SUCCESS
;
440 unsigned char *stream
= NULL
, *orig_stream
= NULL
;
441 uint32_t stream_size
= buflen
;
442 tpm_state_t
*tpm_state
= NULL
;
444 if (buffer
== NULL
) {
445 SetCachedState(st
, NULL
, 0);
449 if (tpm_instances
[0])
450 return TPM_INVALID_POSTINIT
;
452 if (ret
== TPM_SUCCESS
) {
453 stream
= malloc(buflen
);
455 TPMLIB_LogError("Could not allocate %u bytes.\n", buflen
);
460 if (ret
== TPM_SUCCESS
) {
461 orig_stream
= stream
;
462 memcpy(stream
, buffer
, buflen
);
464 tpm_state
= malloc(sizeof(tpm_state_t
));
466 TPMLIB_LogError("Could not allocated %zu bytes.\n",
467 sizeof(tpm_state_t
));
472 if (ret
== TPM_SUCCESS
) {
473 ret
= TPM_Global_Init(tpm_state
);
476 /* test whether we can accept the blob */
477 if (ret
== TPM_SUCCESS
) {
478 tpm_state
->tpm_number
= 0;
481 case TPMLIB_STATE_PERMANENT
:
482 ret
= TPM_PermanentAll_Load(tpm_state
, &stream
, &stream_size
);
484 case TPMLIB_STATE_VOLATILE
:
485 /* permanent state needs to be there and loaded first */
486 ret
= TPM_PermanentAll_NVLoad_Preserve(tpm_state
);
487 if (ret
== TPM_SUCCESS
)
488 ret
= TPM_VolatileAll_Load(tpm_state
, &stream
, &stream_size
);
490 case TPMLIB_STATE_SAVE_STATE
:
491 ret
= TPM_PermanentAll_NVLoad_Preserve(tpm_state
);
492 if (ret
== TPM_SUCCESS
)
493 ret
= TPM_SaveState_Load(tpm_state
, &stream
, &stream_size
);
497 ClearAllCachedState();
500 /* cache the blob for the TPM_MainInit() to pick it up */
501 if (ret
== TPM_SUCCESS
) {
502 SetCachedState(st
, orig_stream
, buflen
);
507 TPM_Global_Delete(tpm_state
);
513 const struct tpm_interface TPM12Interface
= {
514 .MainInit
= TPM12_MainInit
,
515 .Terminate
= TPM12_Terminate
,
516 .Process
= TPM12_Process
,
517 .VolatileAllStore
= TPM12_VolatileAllStore
,
518 .CancelCommand
= TPM12_CancelCommand
,
519 .GetTPMProperty
= TPM12_GetTPMProperty
,
520 .GetInfo
= TPM12_GetInfo
,
521 .TpmEstablishedGet
= TPM12_IO_TpmEstablished_Get
,
522 .TpmEstablishedReset
= TPM12_IO_TpmEstablished_Reset
,
523 .HashStart
= TPM12_IO_Hash_Start
,
524 .HashData
= TPM12_IO_Hash_Data
,
525 .HashEnd
= TPM12_IO_Hash_End
,
526 .SetBufferSize
= TPM12_SetBufferSize
,
527 .ValidateState
= TPM12_ValidateState
,
528 .SetState
= TPM12_SetState
,
529 .GetState
= TPM12_GetState
,