1 /* SPDX-License-Identifier: BSD-3-Clause */
3 * swtpm.c: Programming of a swtpm using communication via fd-passing
5 * Author: Stefan Berger, stefanb@linux.ibm.com
7 * Copyright (c) IBM Corporation, 2021
16 #include <sys/types.h>
17 #include <sys/socket.h>
24 #include <openssl/bn.h>
25 #include <openssl/evp.h>
26 #include <openssl/hmac.h>
27 #include <openssl/rsa.h>
28 #include <openssl/sha.h>
29 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
30 # include <openssl/core_names.h>
31 # include <openssl/param_build.h>
33 # include <openssl/rsa.h>
37 #include "swtpm_utils.h"
38 #include "tpm_ioctl.h"
39 #include "sys_dependencies.h"
41 #define AS2BE(VAL) (((VAL) >> 8) & 0xff), ((VAL) & 0xff)
42 #define AS4BE(VAL) AS2BE((VAL) >> 16), AS2BE(VAL)
43 #define AS8BE(VAL) AS4BE((VAL) >> 32), AS4BE(VAL)
45 struct tpm_req_header
{
49 } __attribute__((packed
));
51 struct tpm_resp_header
{
55 } __attribute__((packed
));
57 static int swtpm_start(struct swtpm
*self
)
59 g_autofree gchar
*tpmstate
= g_strdup_printf("backend-uri=%s", self
->state_path
);
60 g_autofree gchar
*pidfile_arg
= NULL
;
61 g_autofree gchar
*server_fd
= NULL
;
62 g_autofree gchar
*ctrl_fd
= NULL
;
63 g_autofree gchar
*keyopts
= NULL
;
64 g_autofree gchar
*logop
= NULL
;
65 g_autofree gchar
**argv
= NULL
;
72 char pidfile
[] = "/tmp/.swtpm_setup.pidfile.XXXXXX";
74 pidfile_fd
= mkstemp(pidfile
);
76 logerr(self
->logfile
, "Could not create pidfile: %s\n", strerror(errno
));
79 // pass filename rather than fd (Cygwin)
80 pidfile_arg
= g_strdup_printf("file=%s", pidfile
);
82 argv
= concat_arrays(self
->swtpm_exec_l
,
84 "--flags", "not-need-init,startup-clear",
85 "--tpmstate", tpmstate
,
88 "--log", "file=/tmp/log,level=20",
94 argv
= concat_arrays(argv
, (gchar
*[]){"--tpm2", NULL
}, TRUE
);
96 if (self
->keyopts
!= NULL
) {
97 keyopts
= g_strdup(self
->keyopts
);
98 argv
= concat_arrays(argv
, (gchar
*[]){"--key", keyopts
, NULL
}, TRUE
);
101 if (gl_LOGFILE
!= NULL
) {
102 logop
= g_strdup_printf("file=%s", gl_LOGFILE
);
103 argv
= concat_arrays(argv
, (gchar
*[]){"--log", logop
, NULL
}, TRUE
);
106 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, self
->ctrl_fds
) != 0) {
107 logerr(self
->logfile
, "Could not create socketpair: %s\n", strerror(errno
));
110 ctrl_fd
= g_strdup_printf("type=unixio,clientfd=%d", self
->ctrl_fds
[1]);
112 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, self
->data_fds
) != 0) {
113 logerr(self
->logfile
, "Could not create socketpair: %s\n", strerror(errno
));
116 server_fd
= g_strdup_printf("type=tcp,fd=%d", self
->data_fds
[1]);
118 argv
= concat_arrays(argv
, (gchar
*[]){
119 "--server", server_fd
,
126 g_autofree gchar
*join
= g_strjoinv(" ", argv
);
127 logit(self
->logfile
, "Starting swtpm: %s\n", join
);
131 success
= g_spawn_async(NULL
, argv
, NULL
,
132 G_SPAWN_LEAVE_DESCRIPTORS_OPEN
| G_SPAWN_STDOUT_TO_DEV_NULL
| G_SPAWN_STDERR_TO_DEV_NULL
,
133 NULL
, NULL
, &self
->pid
, &error
);
135 logerr(self
->logfile
, "Could not start swtpm: %s\n", error
->message
);
140 /* wait until the pidfile is written to or swtpm terminates */
141 for (ctr
= 0; ctr
< 1000; ctr
++) {
142 if (kill(self
->pid
, 0) < 0) {
143 /* swtpm terminated */
145 logerr(self
->logfile
, "swtpm process terminated unexpectedly.\n");
146 self
->cops
->stop(self
);
149 if (fstat(pidfile_fd
, &statbuf
) == 0 && statbuf
.st_size
> 0) {
150 printf("TPM is listening on Unix socket.\n");
163 /* Stop a running swtpm instance and close all the file descriptors connecting to it */
164 static void swtpm_stop(struct swtpm
*self
)
167 gboolean ended
= FALSE
;
170 self
->cops
->ctrl_shutdown(self
);
171 for (c
= 0; c
< 500; c
++) {
172 if (kill(self
->pid
, 0) < 0) {
179 kill(self
->pid
, SIGKILL
);
180 waitpid(self
->pid
, NULL
, 0);
185 if (self
->ctrl_fds
[0] >= 0) {
186 close(self
->ctrl_fds
[0]);
187 close(self
->ctrl_fds
[1]);
188 self
->ctrl_fds
[0] = self
->ctrl_fds
[1] = -1;
191 if (self
->data_fds
[0] >= 0) {
192 close(self
->data_fds
[0]);
193 close(self
->data_fds
[1]);
194 self
->data_fds
[0] = self
->data_fds
[1] = -1;
198 /* Destroy a running swtpm instance */
199 static void swtpm_destroy(struct swtpm
*self
)
201 self
->cops
->stop(self
);
204 /* Send a command to swtpm and receive the response either via control or data channel */
205 static int transfer(struct swtpm
*self
, void *buffer
, size_t buffer_len
,
206 const char *cmdname
, gboolean use_ctrl
,
207 void *respbuffer
, size_t *respbuffer_len
)
212 unsigned char resp
[4096];
217 sockfd
= self
->ctrl_fds
[0];
220 sockfd
= self
->data_fds
[0];
224 n
= write(sockfd
, buffer
, buffer_len
);
226 logerr(self
->logfile
, "Could not send %s buffer to swtpm: %s\n",
227 cmdname
, strerror(errno
));
230 if ((size_t)n
!= buffer_len
) {
231 logerr(self
->logfile
, "Could not send all bytes to swtpm: %zu < %zu\n",
232 (size_t)n
, buffer_len
);
236 resplen
= read(sockfd
, resp
, sizeof(resp
));
238 logerr(self
->logfile
, "Could not receive response to %s from swtpm: %s\n",
239 cmdname
, strerror(errno
));
244 if ((size_t)resplen
< sizeof(struct tpm_resp_header
)) {
245 logerr(self
->logfile
,
246 "Response for %s has only %d bytes.\n", cmdname
, resplen
);
249 } else if ((size_t)resplen
< 4) {
250 logerr(self
->logfile
,
251 "Response for %s has only %d bytes.\n", cmdname
, resplen
);
255 memcpy(&returncode
, &resp
[offset
], sizeof(returncode
));
256 returncode
= be32toh(returncode
);
257 if (returncode
!= 0) {
258 logerr(self
->logfile
,
259 "%s failed: 0x%x\n", cmdname
, returncode
);
264 *respbuffer_len
= min((size_t)resplen
, *respbuffer_len
);
265 memcpy(respbuffer
, resp
, *respbuffer_len
);
271 /* Send a CMD_SHUTDOWN over the control channel */
272 static int swtpm_ctrl_shutdown(struct swtpm
*self
)
274 uint32_t cmd
= htobe32(CMD_SHUTDOWN
);
276 return transfer(self
, &cmd
, sizeof(cmd
), "CMD_SHUTDOWN", TRUE
, NULL
, 0);
279 /* Get the TPM specification parameters over the control channel */
280 static int swtpm_ctrl_get_tpm_specs_and_attrs(struct swtpm
*self
, gchar
**result
)
282 unsigned char req
[] = {AS4BE(CMD_GET_INFO
),
283 AS8BE(SWTPM_INFO_TPMSPECIFICATION
| SWTPM_INFO_TPMATTRIBUTES
),
285 unsigned char tpmresp
[1024];
286 size_t tpmresp_len
= sizeof(tpmresp
);
290 ret
= transfer(self
, req
, sizeof(req
), "CMD_GET_INFO", TRUE
, tpmresp
, &tpmresp_len
);
294 if (tpmresp_len
< 8 + sizeof(length
))
296 memcpy(&length
, &tpmresp
[8], sizeof(length
));
297 length
= htobe32(length
);
299 if (tpmresp_len
< 12 + length
)
301 *result
= g_strndup((gchar
*)&tpmresp
[12], length
);
306 logerr(self
->logfile
, "Response from CMD_GET_INFO is too short!\n");
311 static const struct swtpm_cops swtpm_cops
= {
312 .start
= swtpm_start
,
314 .destroy
= swtpm_destroy
,
315 .ctrl_shutdown
= swtpm_ctrl_shutdown
,
316 .ctrl_get_tpm_specs_and_attrs
= swtpm_ctrl_get_tpm_specs_and_attrs
,
323 #define TPM2_ST_NO_SESSIONS 0x8001
324 #define TPM2_ST_SESSIONS 0x8002
326 #define TPM2_CC_EVICTCONTROL 0x00000120
327 #define TPM2_CC_NV_DEFINESPACE 0x0000012a
328 #define TPM2_CC_PCR_ALLOCATE 0x0000012b
329 #define TPM2_CC_CREATEPRIMARY 0x00000131
330 #define TPM2_CC_NV_WRITE 0x00000137
331 #define TPM2_CC_NV_WRITELOCK 0x00000138
332 #define TPM2_CC_SHUTDOWN 0x00000145
333 #define TPM2_CC_GETCAPABILITY 0x0000017a
335 #define TPM2_SU_CLEAR 0x0000
337 #define TPM2_RH_OWNER 0x40000001
338 #define TPM2_RS_PW 0x40000009
339 #define TPM2_RH_ENDORSEMENT 0x4000000b
340 #define TPM2_RH_PLATFORM 0x4000000c
342 #define TPM2_ALG_RSA 0x0001
343 #define TPM2_ALG_SHA1 0x0004
344 #define TPM2_ALG_AES 0x0006
345 #define TPM2_ALG_SHA256 0x000b
346 #define TPM2_ALG_SHA384 0x000c
347 #define TPM2_ALG_SHA512 0x000d
348 #define TPM2_ALG_SHA3_256 0x0027
349 #define TPM2_ALG_SHA3_384 0x0028
350 #define TPM2_ALG_SHA3_512 0x0029
351 #define TPM2_ALG_NULL 0x0010
352 #define TPM2_ALG_SM3 0x0012
353 #define TPM2_ALG_ECC 0x0023
354 #define TPM2_ALG_CFB 0x0043
356 #define TPM2_CAP_PCRS 0x00000005
358 #define TPM2_ECC_NIST_P384 0x0004
360 #define TPMA_NV_PLATFORMCREATE 0x40000000
361 #define TPMA_NV_AUTHREAD 0x40000
362 #define TPMA_NV_NO_DA 0x2000000
363 #define TPMA_NV_PPWRITE 0x1
364 #define TPMA_NV_PPREAD 0x10000
365 #define TPMA_NV_OWNERREAD 0x20000
366 #define TPMA_NV_WRITEDEFINE 0x2000
368 // Use standard EK Cert NVRAM, EK and SRK handles per IWG spec.
369 // "TCG TPM v2.0 Provisioning Guide"; Version 1.0, Rev 1.0, March 15, 2017
371 #define TPM2_NV_INDEX_RSA2048_EKCERT 0x01c00002
372 #define TPM2_NV_INDEX_RSA2048_EKTEMPLATE 0x01c00004
373 #define TPM2_NV_INDEX_RSA3072_HI_EKCERT 0x01c0001c
374 #define TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE 0x01c0001d
375 // For ECC follow "TCG EK Credential Profile For TPM Family 2.0; Level 0"
376 // Specification Version 2.1; Revision 13; 10 December 2018
377 #define TPM2_NV_INDEX_PLATFORMCERT 0x01c08000
379 #define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT 0x01c00016
380 #define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017
382 #define TPM2_EK_RSA_HANDLE 0x81010001
383 #define TPM2_EK_RSA3072_HANDLE 0x8101001c
384 #define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016
385 #define TPM2_SPK_HANDLE 0x81000001
387 #define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \
389 .tag = htobe16(TAG), \
390 .size = htobe32(SIZE), \
391 .ordinal = htobe32(ORD), \
394 struct tpm2_authblock
{
396 uint16_t foo
; // FIXME
397 uint8_t continueSession
;
398 uint16_t bar
; // FIMXE
399 } __attribute__((packed
));
401 #define TPM2_AUTHBLOCK_INITIALIZER(AUTH, FOO, CS, BAR) \
403 .auth = htobe32(AUTH), \
404 .foo = htobe16(FOO), \
405 .continueSession = CS, \
406 .bar = htobe16(BAR), \
409 static const unsigned char NONCE_EMPTY
[2] = {AS2BE(0)};
410 static const unsigned char NONCE_RSA2048
[2+0x100] = {AS2BE(0x100), 0, };
411 static const unsigned char NONCE_RSA3072
[2+0x180] = {AS2BE(0x180), 0, };
412 static const unsigned char NONCE_ECC_384
[2+0x30] = {AS2BE(0x30), 0, };
414 static const struct bank_to_name
{
417 } banks_to_names
[] = {
418 {TPM2_ALG_SHA1
, "sha1"},
419 {TPM2_ALG_SHA256
, "sha256"},
420 {TPM2_ALG_SHA384
, "sha384"},
421 {TPM2_ALG_SHA512
, "sha512"},
422 {TPM2_ALG_SM3
, "sm3-256"},
423 {TPM2_ALG_SHA3_256
, "sha3-256"},
424 {TPM2_ALG_SHA3_384
, "sha3-384"},
425 {TPM2_ALG_SHA3_512
, "sha3-512"},
429 /* function prototypes */
430 static int swtpm_tpm2_createprimary_rsa(struct swtpm
*self
, uint32_t primaryhandle
, unsigned int keyflags
,
431 const unsigned char *symkeydata
, size_t symkeydata_len
,
432 const unsigned char *authpolicy
, size_t authpolicy_len
,
433 unsigned int rsa_keysize
, gboolean havenonce
, size_t off
,
434 uint32_t *curr_handle
,
435 unsigned char *ektemplate
, size_t *ektemplate_len
,
436 gchar
**ekparam
, const gchar
**key_description
);
438 static int swtpm_tpm2_write_nvram(struct swtpm
*self
, uint32_t nvindex
, uint32_t nvindexattrs
,
439 const unsigned char *data
, size_t data_len
, gboolean lock_nvram
,
440 const char *purpose
);
442 /* Given a hash algo identifier, return the name of the hash bank */
443 static const char *get_name_for_bank(uint16_t hashAlg
) {
446 for (i
= 0; banks_to_names
[i
].name
; i
++) {
447 if (banks_to_names
[i
].hashAlg
== hashAlg
)
448 return banks_to_names
[i
].name
;
453 /* Give the name of a hash bank, return its algo identifer */
454 static uint16_t get_hashalg_by_bankname(const char *name
) {
457 for (i
= 0; banks_to_names
[i
].name
; i
++) {
458 if (strcmp(banks_to_names
[i
].name
, name
) == 0)
459 return banks_to_names
[i
].hashAlg
;
464 /* Do an SU_CLEAR shutdown of the TPM 2 */
465 static int swtpm_tpm2_shutdown(struct swtpm
*self
)
467 struct tpm2_shutdown_req
{
468 struct tpm_req_header hdr
;
469 uint16_t shutdownType
;
470 } __attribute__((packed
)) req
= {
471 .hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS
, sizeof(req
), TPM2_CC_SHUTDOWN
),
472 .shutdownType
= htobe16(TPM2_SU_CLEAR
)
475 return transfer(self
, &req
, sizeof(req
), "TPM2_Shutdown", FALSE
, NULL
, NULL
);
478 /* Get all available PCR banks */
479 static int swtpm_tpm2_get_all_pcr_banks(struct swtpm
*self
, gchar
***all_pcr_banks
)
481 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS
, 0, TPM2_CC_GETCAPABILITY
);
482 g_autofree
unsigned char *req
= NULL
;
484 unsigned char tpmresp
[256];
485 size_t tpmresp_len
= sizeof(tpmresp
);
486 uint16_t count
, bank
;
493 req_len
= memconcat(&req
,
495 (unsigned char[]){AS4BE(TPM2_CAP_PCRS
), AS4BE(0), AS4BE(64)}, (size_t)12,
498 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
501 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
503 ret
= transfer(self
, req
, req_len
, "TPM2_GetCapability", FALSE
, tpmresp
, &tpmresp_len
);
507 if (tpmresp_len
< 17 + sizeof(count
))
509 memcpy(&count
, &tpmresp
[17], sizeof(count
));
510 count
= be16toh(count
);
512 *all_pcr_banks
= g_malloc0(sizeof(char *) * (count
+ 1));
516 for (i
= 0; i
< count
; i
++) {
519 if (tpmresp_len
< offset
+ sizeof(bank
))
521 memcpy(&bank
, &tpmresp
[offset
], sizeof(bank
));
522 bank
= be16toh(bank
);
524 if (tpmresp_len
< offset
+ 2 + sizeof(length
))
526 length
= tpmresp
[offset
+ 2];
528 name
= get_name_for_bank(bank
);
532 n
= g_strdup_printf("%02x", bank
);
534 (*all_pcr_banks
)[i
] = n
;
536 offset
+= 2 + 1 + length
;
541 logerr(self
->logfile
, "Response from TPM2_GetCapability is too short!\n");
545 /* Activate all user-chosen PCR banks and deactivate all others */
546 static int swtpm_tpm2_set_active_pcr_banks(struct swtpm
*self
, gchar
**pcr_banks
,
547 gchar
**all_pcr_banks
, gchar
***active
)
549 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, 0, TPM2_CC_PCR_ALLOCATE
);
550 struct tpm2_authblock authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0);
551 unsigned char pcrselects
[6 * 10]; // supports up to 10 PCR banks
552 ssize_t pcrselects_len
= 0;
556 g_autofree
unsigned char *req
= NULL
;
557 ssize_t req_len
, len
;
559 uint64_t activated_mask
= 0;
561 for (idx
= 0; pcr_banks
[idx
] != NULL
; idx
++)
563 *active
= g_malloc0(sizeof(char *) * (idx
+ 1));
565 for (idx
= 0; pcr_banks
[idx
] != NULL
; idx
++) {
567 // Is user-chosen pcr_banks[idx] available?
568 for (j
= 0; all_pcr_banks
[j
] != NULL
; j
++) {
569 if (strcmp(pcr_banks
[idx
], all_pcr_banks
[j
]) == 0) {
570 hashAlg
= get_hashalg_by_bankname(pcr_banks
[idx
]);
574 if (hashAlg
!= 0 && (activated_mask
& (1 << j
)) == 0) {
575 (*active
)[count
] = g_strdup(pcr_banks
[idx
]);
576 len
= concat(&pcrselects
[pcrselects_len
], sizeof(pcrselects
) - pcrselects_len
,
577 (unsigned char[]){AS2BE(hashAlg
), 3, 0xff, 0xff, 0xff} , (size_t)6,
580 logerr(self
->logfile
, "Internal error in %s: pcrselects is too small\n", __func__
);
583 pcrselects_len
+= len
;
585 activated_mask
|= (1 << j
);
590 logerr(self
->logfile
,
591 "No PCR banks could be allocated. None of the selected algorithms are supported.\n");
595 // disable all the other ones not chosen by the user
596 for (idx
= 0; all_pcr_banks
[idx
] != NULL
; idx
++) {
597 gboolean found
= FALSE
;
599 for (j
= 0; pcr_banks
[j
] != NULL
; j
++) {
600 if (strcmp(pcr_banks
[j
], all_pcr_banks
[idx
]) == 0) {
608 /* not found, so not chosen by user */
609 hashAlg
= get_hashalg_by_bankname(all_pcr_banks
[idx
]);
611 len
= concat(&pcrselects
[pcrselects_len
], sizeof(pcrselects
) - pcrselects_len
,
612 (unsigned char[]){AS2BE(hashAlg
), 3, 0, 0, 0}, (size_t)6,
615 logerr(self
->logfile
, "Internal error in %s: pcrselects is too small\n", __func__
);
618 pcrselects_len
+= len
;
622 req_len
= memconcat(&req
,
625 AS4BE(TPM2_RH_PLATFORM
), AS4BE(sizeof(authblock
))
627 &authblock
, sizeof(authblock
),
628 (unsigned char[]){AS4BE(count
)}, (size_t)4,
629 pcrselects
, pcrselects_len
,
632 logerr(self
->logfile
, "Internal error in %s: req is too small\n", __func__
);
635 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
637 ret
= transfer(self
, req
, req_len
, "TPM2_PCR_Allocate", FALSE
, NULL
, 0);
650 /* Make object at the curr_handler permanent with the perm_handle */
651 static int swtpm_tpm2_evictcontrol(struct swtpm
*self
, uint32_t curr_handle
, uint32_t perm_handle
)
653 struct tpm2_evictcontrol_req
{
654 struct tpm_req_header hdr
;
656 uint32_t objectHandle
;
657 uint32_t authblockLen
;
658 struct tpm2_authblock authblock
;
659 uint32_t persistentHandle
;
660 } __attribute__((packed
)) req
= {
661 .hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, sizeof(req
), TPM2_CC_EVICTCONTROL
),
662 .auth
= htobe32(TPM2_RH_OWNER
),
663 .objectHandle
= htobe32(curr_handle
),
664 .authblockLen
= htobe32(sizeof(req
.authblock
)),
665 .authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0),
666 .persistentHandle
= htobe32(perm_handle
),
669 return transfer(self
, &req
, sizeof(req
), "TPM2_EvictControl", FALSE
, NULL
, 0);
672 /* Create an RSA EK */
673 static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm
*self
, unsigned int rsa_keysize
,
674 gboolean allowsigning
, gboolean decryption
,
675 uint32_t *curr_handle
,
676 unsigned char *ektemplate
, size_t *ektemplate_len
,
677 gchar
**ekparam
, const gchar
**key_description
)
679 unsigned char authpolicy
[48];
680 size_t authpolicy_len
;
681 unsigned char symkeydata
[6];
682 size_t symkeydata_len
;
683 unsigned int keyflags
;
684 unsigned int symkeylen
;
688 if (rsa_keysize
== 2048) {
690 memcpy(authpolicy
, ((unsigned char []){
691 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
692 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
693 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
699 } else if (rsa_keysize
== 3072) {
701 memcpy(authpolicy
, ((unsigned char []){
702 0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
703 0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
704 0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
705 0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
712 logerr(self
->logfile
, "Internal error in %s: unsupported RSA keysize %d.\n",
713 __func__
, rsa_keysize
);
717 if (allowsigning
&& decryption
) {
718 // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
719 // adminWithPolicy, sign, decrypt
720 keyflags
|= 0x000600b2;
721 // symmetric: TPM_ALG_NULL
723 memcpy(symkeydata
, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL
)}), symkeydata_len
);
725 } else if (allowsigning
) {
726 // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
727 // adminWithPolicy, sign
728 keyflags
|= 0x000400b2;
729 // symmetric: TPM_ALG_NULL
731 memcpy(symkeydata
, ((unsigned char[]) {AS2BE(TPM2_ALG_NULL
)}), symkeydata_len
);
734 // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
735 // adminWithPolicy, restricted, decrypt
736 keyflags
|= 0x000300b2;
737 // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB
740 ((unsigned char[]) {AS2BE(TPM2_ALG_AES
), AS2BE(symkeylen
), AS2BE(TPM2_ALG_CFB
)}),
745 return swtpm_tpm2_createprimary_rsa(self
, TPM2_RH_ENDORSEMENT
, keyflags
,
746 symkeydata
, symkeydata_len
,
747 authpolicy
, authpolicy_len
, rsa_keysize
,
748 havenonce
, off
, curr_handle
,
749 ektemplate
, ektemplate_len
, ekparam
, key_description
);
752 /* Create an RSA key with the given parameters */
753 static int swtpm_tpm2_createprimary_rsa(struct swtpm
*self
, uint32_t primaryhandle
, unsigned int keyflags
,
754 const unsigned char *symkeydata
, size_t symkeydata_len
,
755 const unsigned char *authpolicy
, size_t authpolicy_len
,
756 unsigned int rsa_keysize
, gboolean havenonce
, size_t off
,
757 uint32_t *curr_handle
,
758 unsigned char *ektemplate
, size_t *ektemplate_len
,
759 gchar
**ekparam
, const gchar
**key_description
)
761 const unsigned char *nonce
;
764 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, 0, TPM2_CC_CREATEPRIMARY
);
765 struct tpm2_authblock authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0);
766 g_autofree
unsigned char *public = NULL
;
768 g_autofree
unsigned char *createprimary
= NULL
;
769 ssize_t createprimary_len
;
771 unsigned char tpmresp
[2048];
772 size_t tpmresp_len
= sizeof(tpmresp
);
775 if (rsa_keysize
== 2048) {
776 nonce
= NONCE_RSA2048
;
777 nonce_len
= sizeof(NONCE_RSA2048
);
778 hashalg
= TPM2_ALG_SHA256
;
780 *key_description
= "rsa2048";
781 } else if (rsa_keysize
== 3072) {
784 nonce_len
= sizeof(NONCE_EMPTY
);
786 nonce
= NONCE_RSA3072
;
787 nonce_len
= sizeof(NONCE_RSA3072
);
789 hashalg
= TPM2_ALG_SHA384
;
791 *key_description
= "rsa3072";
793 logerr(self
->logfile
, "Internal error in %s: unsupported RSA keysize %d.\n",
794 __func__
, rsa_keysize
);
801 AS2BE(TPM2_ALG_RSA
), AS2BE(hashalg
),
802 AS4BE(keyflags
), AS2BE(authpolicy_len
)
804 authpolicy
, authpolicy_len
,
805 symkeydata
, symkeydata_len
,
807 AS2BE(TPM2_ALG_NULL
), AS2BE(rsa_keysize
), AS4BE(0)
811 if (public_len
< 0) {
812 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
816 if (*ektemplate_len
< (size_t)public_len
) {
817 logerr(self
->logfile
, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n",
818 __func__
, public_len
, *ektemplate_len
);
821 memcpy(ektemplate
, public, public_len
);
822 *ektemplate_len
= public_len
;
826 memconcat(&createprimary
,
828 (unsigned char[]) {AS4BE(primaryhandle
), AS4BE(sizeof(authblock
))}, (size_t)8,
829 &authblock
, sizeof(authblock
),
830 (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len
)}, (size_t)8,
832 (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
834 if (createprimary_len
< 0) {
835 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
838 ((struct tpm_req_header
*)createprimary
)->size
= htobe32(createprimary_len
);
840 ret
= transfer(self
, createprimary
, createprimary_len
, "TPM2_CreatePrimary(RSA)", FALSE
,
841 tpmresp
, &tpmresp_len
);
846 if (tpmresp_len
< 10 + sizeof(*curr_handle
))
848 memcpy(curr_handle
, &tpmresp
[10], sizeof(*curr_handle
));
849 *curr_handle
= be32toh(*curr_handle
);
852 if (tpmresp_len
< off
+ sizeof(modlen
))
854 memcpy(&modlen
, &tpmresp
[off
], sizeof(modlen
));
855 modlen
= be16toh(modlen
);
856 if (modlen
!= rsa_keysize
>> 3) {
857 logerr(self
->logfile
, "Internal error in %s: Getting modulus from wrong offset %zu\n",
862 if (tpmresp_len
< off
+ 2 + modlen
)
864 *ekparam
= print_as_hex(&tpmresp
[off
+ 2], modlen
);
870 logerr(self
->logfile
, "Response from TPM2_CreatePrimary(RSA) is too short!\n");
874 /* Create an ECC key with the given parameters */
875 static int swtpm_tpm2_createprimary_ecc(struct swtpm
*self
, uint32_t primaryhandle
, unsigned int keyflags
,
876 const unsigned char *symkeydata
, size_t symkeydata_len
,
877 const unsigned char *authpolicy
, size_t authpolicy_len
,
878 unsigned short curveid
, unsigned short hashalg
,
879 const unsigned char *nonce
, size_t nonce_len
,
880 size_t off
, uint32_t *curr_handle
,
881 unsigned char *ektemplate
, size_t *ektemplate_len
,
882 gchar
**ekparam
, const gchar
**key_description
)
884 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, 0, TPM2_CC_CREATEPRIMARY
);
885 struct tpm2_authblock authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0);
886 g_autofree
unsigned char *public = NULL
;
888 g_autofree
unsigned char *createprimary
= NULL
;
889 ssize_t createprimary_len
;
891 unsigned char tpmresp
[2048];
892 size_t tpmresp_len
= sizeof(tpmresp
);
894 uint16_t exp_ksize
, ksize1
, ksize2
;
900 AS2BE(TPM2_ALG_ECC
), AS2BE(hashalg
), AS4BE(keyflags
), AS2BE(authpolicy_len
)
902 authpolicy
, authpolicy_len
,
903 symkeydata
, symkeydata_len
,
904 (unsigned char[]) {AS2BE(TPM2_ALG_NULL
), AS2BE(curveid
), AS2BE(TPM2_ALG_NULL
)}, (size_t)6,
908 if (public_len
< 0) {
909 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
913 if (*ektemplate_len
< (size_t)public_len
) {
914 logerr(self
->logfile
, "Internal error: Need %zu bytes for ektemplate (ecc) but got only %zu\n",
915 public_len
, ektemplate_len
);
918 memcpy(ektemplate
, public, public_len
);
919 *ektemplate_len
= public_len
;
923 memconcat(&createprimary
,
925 (unsigned char[]) {AS4BE(primaryhandle
), AS4BE(sizeof(authblock
))}, (size_t)8,
926 &authblock
, sizeof(authblock
),
927 (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len
)}, (size_t)8,
929 (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6,
931 if (createprimary_len
< 0) {
932 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
935 ((struct tpm_req_header
*)createprimary
)->size
= htobe32(createprimary_len
);
937 ret
= transfer(self
, createprimary
, createprimary_len
, "TPM2_CreatePrimary(ECC)", FALSE
,
938 tpmresp
, &tpmresp_len
);
942 if (tpmresp_len
< 10 + sizeof(*curr_handle
))
944 memcpy(curr_handle
, &tpmresp
[10], sizeof(*curr_handle
));
945 *curr_handle
= be32toh(*curr_handle
);
948 if (curveid
== TPM2_ECC_NIST_P384
) {
952 *key_description
= cid
;
954 logerr(self
->logfile
, "Unknown curveid 0x%x\n", curveid
);
958 if (tpmresp_len
< off
+ sizeof(ksize1
))
960 memcpy(&ksize1
, &tpmresp
[off
], sizeof(ksize1
));
961 ksize1
= be16toh(ksize1
);
962 off2
= off
+ 2 + ksize1
;
964 if (tpmresp_len
< off2
+ sizeof(ksize2
))
966 memcpy(&ksize2
, &tpmresp
[off2
], sizeof(ksize2
));
967 ksize2
= be16toh(ksize2
);
969 if (ksize1
!= exp_ksize
|| ksize2
!= exp_ksize
) {
970 logerr(self
->logfile
, "ECC: Getting key parameters from wrong offset\n");
975 unsigned char *xparam
= &tpmresp
[off
+ 2];
976 unsigned char *yparam
= &tpmresp
[off2
+ 2];
977 if (tpmresp_len
< off
+ 2 + ksize1
|| tpmresp_len
< off2
+ 2 + ksize2
)
979 g_autofree gchar
*xparam_str
= print_as_hex(xparam
, ksize1
);
980 g_autofree gchar
*yparam_str
= print_as_hex(yparam
, ksize2
);
982 *ekparam
= g_strdup_printf("x=%s,y=%s,id=%s", xparam_str
, yparam_str
, cid
);
988 logerr(self
->logfile
, "Response from TPM2_CreatePrimary(ECC) is too short!\n");
992 static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm
*self
,
993 uint32_t *curr_handle
)
995 unsigned int keyflags
= 0x00030472;
996 const unsigned char authpolicy
[0];
997 size_t authpolicy_len
= sizeof(authpolicy
);
998 const unsigned char symkeydata
[] = {AS2BE(TPM2_ALG_AES
), AS2BE(256), AS2BE(TPM2_ALG_CFB
)};
999 size_t symkeydata_len
= sizeof(symkeydata
);
1002 return swtpm_tpm2_createprimary_ecc(self
, TPM2_RH_OWNER
, keyflags
, symkeydata
, symkeydata_len
,
1003 authpolicy
, authpolicy_len
, TPM2_ECC_NIST_P384
, TPM2_ALG_SHA384
,
1004 NONCE_ECC_384
, sizeof(NONCE_ECC_384
), off
, curr_handle
,
1005 NULL
, 0, NULL
, NULL
);
1008 static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm
*self
, unsigned int rsa_keysize
,
1009 uint32_t *curr_handle
)
1011 unsigned int keyflags
= 0x00030472;
1012 const unsigned char authpolicy
[0];
1013 size_t authpolicy_len
= sizeof(authpolicy
);
1014 unsigned short symkeylen
= 0;
1015 unsigned char symkeydata
[6];
1016 size_t symkeydata_len
;
1019 if (rsa_keysize
== 2048)
1021 else if (rsa_keysize
== 3072)
1026 ((unsigned char[]) {AS2BE(TPM2_ALG_AES
), AS2BE(symkeylen
), AS2BE(TPM2_ALG_CFB
)}),
1029 return swtpm_tpm2_createprimary_rsa(self
, TPM2_RH_OWNER
, keyflags
,
1030 symkeydata
, symkeydata_len
,
1031 authpolicy
, authpolicy_len
, rsa_keysize
, TRUE
,
1032 off
, curr_handle
, NULL
, 0, NULL
, NULL
);
1035 /* Create either an ECC or RSA storage primary key */
1036 static int swtpm_tpm2_create_spk(struct swtpm
*self
, gboolean isecc
, unsigned int rsa_keysize
)
1039 uint32_t curr_handle
;
1042 ret
= swtpm_tpm2_createprimary_spk_ecc_nist_p384(self
, &curr_handle
);
1044 ret
= swtpm_tpm2_createprimary_spk_rsa(self
, rsa_keysize
, &curr_handle
);
1049 ret
= swtpm_tpm2_evictcontrol(self
, curr_handle
, TPM2_SPK_HANDLE
);
1051 logit(self
->logfile
,
1052 "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE
);
1057 /* Create an ECC EK key that may be allowed to sign and/or decrypt */
1058 static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm
*self
, gboolean allowsigning
,
1059 gboolean decryption
, uint32_t *curr_handle
,
1060 unsigned char *ektemplate
, size_t *ektemplate_len
,
1061 gchar
**ekparam
, const char **key_description
)
1063 unsigned char authpolicy
[48]= {
1064 0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC,
1065 0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4,
1066 0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09,
1067 0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12
1069 size_t authpolicy_len
= 48;
1070 unsigned char symkeydata
[6];
1071 size_t symkeydata_len
;
1072 unsigned int keyflags
;
1076 if (allowsigning
&& decryption
) {
1077 // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1078 // userWithAuth, adminWithPolicy, sign, decrypt
1079 keyflags
= 0x000600f2;
1080 // symmetric: TPM_ALG_NULL
1082 memcpy(symkeydata
, ((unsigned char[]){AS2BE(TPM2_ALG_NULL
)}), symkeydata_len
);
1084 } else if (allowsigning
) {
1085 // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1086 // userWithAuth, adminWithPolicy, sign
1087 keyflags
= 0x000400f2;
1088 // symmetric: TPM_ALG_NULL
1090 memcpy(symkeydata
, ((unsigned char[]){AS2BE(TPM2_ALG_NULL
)}), symkeydata_len
);
1093 // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin,
1094 // userWithAuth, adminWithPolicy, restricted, decrypt
1095 keyflags
= 0x000300f2;
1096 // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB
1099 ((unsigned char[]){ AS2BE(TPM2_ALG_AES
), AS2BE(256), AS2BE(TPM2_ALG_CFB
)}),
1104 ret
= swtpm_tpm2_createprimary_ecc(self
, TPM2_RH_ENDORSEMENT
, keyflags
, symkeydata
, symkeydata_len
,
1105 authpolicy
, authpolicy_len
, TPM2_ECC_NIST_P384
, TPM2_ALG_SHA384
,
1106 NONCE_EMPTY
, sizeof(NONCE_EMPTY
), off
, curr_handle
,
1107 ektemplate
, ektemplate_len
, ekparam
, key_description
);
1109 logerr(self
->logfile
, "%s failed\n", __func__
);
1114 /* Create an ECC or RSA EK */
1115 static int swtpm_tpm2_create_ek(struct swtpm
*self
, gboolean isecc
, unsigned int rsa_keysize
,
1116 gboolean allowsigning
, gboolean decryption
, gboolean lock_nvram
,
1117 gchar
**ekparam
, const gchar
**key_description
)
1119 uint32_t tpm2_ek_handle
, nvindex
, curr_handle
;
1120 const char *keytype
;
1122 unsigned char ektemplate
[512];
1123 size_t ektemplate_len
= sizeof(ektemplate
);
1126 tpm2_ek_handle
= TPM2_EK_ECC_SECP384R1_HANDLE
;
1128 nvindex
= TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE
;
1130 if (rsa_keysize
== 2048) {
1131 tpm2_ek_handle
= TPM2_EK_RSA_HANDLE
;
1132 keytype
= "RSA 2048";
1133 nvindex
= TPM2_NV_INDEX_RSA2048_EKTEMPLATE
;
1134 } else if (rsa_keysize
== 3072) {
1135 tpm2_ek_handle
= TPM2_EK_RSA3072_HANDLE
;
1136 keytype
= "RSA 3072";
1137 nvindex
= TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE
;
1139 logerr(self
->logfile
, "Internal error: Unsupported RSA keysize %u.\n", rsa_keysize
);
1144 ret
= swtpm_tpm2_createprimary_ek_ecc_nist_p384(self
, allowsigning
, decryption
, &curr_handle
,
1145 ektemplate
, &ektemplate_len
, ekparam
,
1148 ret
= swtpm_tpm2_createprimary_ek_rsa(self
, rsa_keysize
, allowsigning
, decryption
, &curr_handle
,
1149 ektemplate
, &ektemplate_len
, ekparam
, key_description
);
1152 ret
= swtpm_tpm2_evictcontrol(self
, curr_handle
, tpm2_ek_handle
);
1154 logerr(self
->logfile
, "create_ek failed: 0x%x\n", ret
);
1158 logit(self
->logfile
,
1159 "Successfully created %s EK with handle 0x%x.\n", keytype
, tpm2_ek_handle
);
1162 uint32_t nvindexattrs
= TPMA_NV_PLATFORMCREATE
| \
1163 TPMA_NV_AUTHREAD
| \
1164 TPMA_NV_OWNERREAD
| \
1168 TPMA_NV_WRITEDEFINE
;
1169 ret
= swtpm_tpm2_write_nvram(self
, nvindex
, nvindexattrs
, ektemplate
, ektemplate_len
,
1170 lock_nvram
, "EK template");
1172 logit(self
->logfile
,
1173 "Successfully created NVRAM area 0x%x for %s EK template.\n",
1180 static int swtpm_tpm2_nvdefinespace(struct swtpm
*self
, uint32_t nvindex
, uint32_t nvindexattrs
,
1183 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, 0, TPM2_CC_NV_DEFINESPACE
);
1184 struct tpm2_authblock authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0);
1185 g_autofree
unsigned char *nvpublic
= NULL
;
1186 ssize_t nvpublic_len
;
1187 g_autofree
unsigned char *req
= NULL
;
1190 nvpublic_len
= memconcat(&nvpublic
,
1192 AS4BE(nvindex
), AS2BE(TPM2_ALG_SHA256
), AS4BE(nvindexattrs
),
1193 AS2BE(0), AS2BE(data_len
)}, (size_t)14,
1195 if (nvpublic_len
< 0) {
1196 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
1200 req_len
= memconcat(&req
,
1202 (unsigned char[]){AS4BE(TPM2_RH_PLATFORM
), AS4BE(sizeof(authblock
))}, (size_t)8,
1203 &authblock
, sizeof(authblock
),
1204 (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len
)}, (size_t)4,
1205 nvpublic
, nvpublic_len
,
1208 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
1212 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
1214 return transfer(self
, req
, req_len
, "TPM2_NV_DefineSpace", FALSE
, NULL
, 0);
1217 /* Write the data into the given NVIndex */
1218 static int swtpm_tpm2_nv_write(struct swtpm
*self
, uint32_t nvindex
,
1219 const unsigned char *data
, size_t data_len
)
1221 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, 0, TPM2_CC_NV_WRITE
);
1222 struct tpm2_authblock authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0);
1223 g_autofree
unsigned char *req
= NULL
;
1225 size_t offset
= 0, txlen
;
1228 while (offset
< data_len
) {
1229 txlen
= min(data_len
- offset
, 1024);
1232 req_len
= memconcat(&req
,
1235 AS4BE(TPM2_RH_PLATFORM
), AS4BE(nvindex
), AS4BE(sizeof(authblock
))
1237 &authblock
, sizeof(authblock
),
1238 (unsigned char[]){AS2BE(txlen
)}, (size_t)2,
1239 &data
[offset
], txlen
,
1240 (unsigned char[]){AS2BE(offset
)}, (size_t)2,
1243 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
1246 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
1248 ret
= transfer(self
, req
, req_len
, "TPM2_NV_Write", FALSE
, NULL
, 0);
1257 static int swtpm_tpm2_nv_writelock(struct swtpm
*self
, uint32_t nvindex
)
1259 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS
, 0, TPM2_CC_NV_WRITELOCK
);
1260 struct tpm2_authblock authblock
= TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW
, 0, 0, 0);
1261 g_autofree
unsigned char *req
;
1264 req_len
= memconcat(&req
,
1267 AS4BE(TPM2_RH_PLATFORM
), AS4BE(nvindex
), AS4BE(sizeof(authblock
))
1269 &authblock
, sizeof(authblock
),
1272 logerr(self
->logfile
, "Internal error in %s: memconcat failed\n", __func__
);
1276 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
1278 return transfer(self
, req
, req_len
, "TPM2_NV_WriteLock", FALSE
, NULL
, 0);
1281 static int swtpm_tpm2_write_nvram(struct swtpm
*self
, uint32_t nvindex
, uint32_t nvindexattrs
,
1282 const unsigned char *data
, size_t data_len
, gboolean lock_nvram
,
1283 const char *purpose
)
1285 int ret
= swtpm_tpm2_nvdefinespace(self
, nvindex
, nvindexattrs
, data_len
);
1287 logerr(self
->logfile
, "Could not create NVRAM area 0x%x for %s.\n", nvindex
, purpose
);
1291 ret
= swtpm_tpm2_nv_write(self
, nvindex
, data
, data_len
);
1293 logerr(self
->logfile
,
1294 "Could not write %s into NVRAM area 0x%x.\n", purpose
, nvindex
);
1299 ret
= swtpm_tpm2_nv_writelock(self
, nvindex
);
1301 logerr(self
->logfile
, "Could not lock EK template NVRAM area 0x%x.\n", nvindex
);
1309 /* Write the platform certificate into an NVRAM area */
1310 static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm
*self
, gboolean isecc
,
1311 unsigned int rsa_keysize
, gboolean lock_nvram
,
1312 const unsigned char *data
, size_t data_len
)
1314 uint32_t nvindex
= 0;
1315 g_autofree gchar
*keytype
= NULL
;
1316 uint32_t nvindexattrs
= TPMA_NV_PLATFORMCREATE
|
1322 TPMA_NV_WRITEDEFINE
;
1326 if (rsa_keysize
== 2048)
1327 nvindex
= TPM2_NV_INDEX_RSA2048_EKCERT
;
1328 else if (rsa_keysize
== 3072)
1329 nvindex
= TPM2_NV_INDEX_RSA3072_HI_EKCERT
;
1330 keytype
= g_strdup_printf("RSA %d", rsa_keysize
);
1332 nvindex
= TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT
;
1333 keytype
= g_strdup("ECC");
1336 ret
= swtpm_tpm2_write_nvram(self
, nvindex
, nvindexattrs
, data
, data_len
, lock_nvram
,
1339 logit(self
->logfile
,
1340 "Successfully created NVRAM area 0x%x for %s EK certificate.\n",
1343 logerr(self
->logfile
,
1344 "Could not create NVRAM area 0x%x for %s EK certificate.\n",
1349 static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm
*self
, gboolean lock_nvram
,
1350 const unsigned char *data
, size_t data_len
)
1352 uint32_t nvindex
= TPM2_NV_INDEX_PLATFORMCERT
;
1353 uint32_t nvindexattrs
= TPMA_NV_PLATFORMCREATE
|
1359 TPMA_NV_WRITEDEFINE
;
1362 ret
= swtpm_tpm2_write_nvram(self
, nvindex
, nvindexattrs
, data
, data_len
, lock_nvram
,
1363 "Platform Certificate");
1365 logit(self
->logfile
,
1366 "Successfully created NVRAM area 0x%x for platform certificate.\n", nvindex
);
1368 logerr(self
->logfile
,
1369 "Could not create NVRAM area 0x%x for platform certificate.\n", nvindex
);
1374 static const struct swtpm2_ops swtpm_tpm2_ops
= {
1375 .shutdown
= swtpm_tpm2_shutdown
,
1376 .create_spk
= swtpm_tpm2_create_spk
,
1377 .create_ek
= swtpm_tpm2_create_ek
,
1378 .get_all_pcr_banks
= swtpm_tpm2_get_all_pcr_banks
,
1379 .set_active_pcr_banks
= swtpm_tpm2_set_active_pcr_banks
,
1380 .write_ek_cert_nvram
= swtpm_tpm2_write_ek_cert_nvram
,
1381 .write_platform_cert_nvram
= swtpm_tpm2_write_platform_cert_nvram
,
1387 #define TPM_TAG_RQU_COMMAND 0x00c1
1388 #define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
1390 #define TPM_ORD_OIAP 0x0000000A
1391 #define TPM_ORD_TAKE_OWNERSHIP 0x0000000D
1392 #define TPM_ORD_PHYSICAL_ENABLE 0x0000006F
1393 #define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
1394 #define TPM_ORD_NV_DEFINE_SPACE 0x000000CC
1395 #define TPM_ORD_NV_WRITE_VALUE 0x000000CD
1396 #define TSC_ORD_PHYSICAL_PRESENCE 0x4000000A
1398 #define TPM_ST_CLEAR 0x0001
1400 #define TPM_PHYSICAL_PRESENCE_CMD_ENABLE 0x0020
1401 #define TPM_PHYSICAL_PRESENCE_PRESENT 0x0008
1403 #define TPM_ALG_RSA 0x00000001
1405 #define TPM_KEY_STORAGE 0x0011
1407 #define TPM_AUTH_ALWAYS 0x01
1409 #define TPM_PID_OWNER 0x0005
1411 #define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
1412 #define TPM_SS_NONE 0x0001
1414 #define TPM_TAG_PCR_INFO_LONG 0x0006
1415 #define TPM_TAG_NV_ATTRIBUTES 0x0017
1416 #define TPM_TAG_NV_DATA_PUBLIC 0x0018
1417 #define TPM_TAG_KEY12 0x0028
1419 #define TPM_LOC_ZERO 0x01
1420 #define TPM_LOC_ALL 0x1f
1422 #define TPM_NV_INDEX_D_BIT 0x10000000
1423 #define TPM_NV_INDEX_EKCERT 0xF000
1424 #define TPM_NV_INDEX_PLATFORMCERT 0xF002
1426 #define TPM_NV_INDEX_LOCK 0xFFFFFFFF
1428 #define TPM_NV_PER_OWNERREAD 0x00020000
1429 #define TPM_NV_PER_OWNERWRITE 0x00000002
1431 #define TPM_ET_OWNER 0x02
1432 #define TPM_ET_NV 0x0b
1434 #define TPM_KH_EK 0x40000006
1437 static int swtpm_tpm12_tsc_physicalpresence(struct swtpm
*self
, uint16_t physicalpresence
)
1439 struct tpm12_tsc_physicalpresence
{
1440 struct tpm_req_header hdr
;
1443 .hdr
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND
, sizeof(req
), TSC_ORD_PHYSICAL_PRESENCE
),
1444 .pp
= htobe16(physicalpresence
),
1447 return transfer(self
, &req
, sizeof(req
), "TSC_PhysicalPresence", FALSE
, NULL
, NULL
);
1450 static int swtpm_tpm12_physical_enable(struct swtpm
*self
)
1452 struct tpm_req_header req
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND
, sizeof(req
), TPM_ORD_PHYSICAL_ENABLE
);
1454 return transfer(self
, &req
, sizeof(req
), "TPM_PhysicalEnable", FALSE
, NULL
, NULL
);
1457 static int swtpm_tpm12_physical_set_deactivated(struct swtpm
*self
, uint8_t state
)
1459 struct tpm12_tsc_physical_set_deactivated
{
1460 struct tpm_req_header hdr
;
1463 .hdr
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND
, sizeof(req
), TPM_ORD_PHYSICAL_SET_DEACTIVATED
),
1467 return transfer(self
, &req
, sizeof(req
), "TSC_PhysicalSetDeactivated", FALSE
, NULL
, NULL
);
1470 /* Initialize the TPM1.2 */
1471 static int swtpm_tpm12_run_swtpm_bios(struct swtpm
*self
)
1473 if (swtpm_tpm12_tsc_physicalpresence(self
, TPM_PHYSICAL_PRESENCE_CMD_ENABLE
) ||
1474 swtpm_tpm12_tsc_physicalpresence(self
, TPM_PHYSICAL_PRESENCE_PRESENT
) ||
1475 swtpm_tpm12_physical_enable(self
) ||
1476 swtpm_tpm12_physical_set_deactivated(self
, 0))
1482 static int swptm_tpm12_create_endorsement_keypair(struct swtpm
*self
,
1483 gchar
**pubek
, size_t *pubek_len
)
1485 unsigned char req
[] = {
1486 0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b,
1487 0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00,
1488 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1489 0x00, 0x02, 0x00, 0x00, 0x00, 0x00
1491 unsigned char tpmresp
[512];
1492 size_t tpmresp_len
= sizeof(tpmresp
);
1496 ret
= transfer(self
, &req
, sizeof(req
), "TPM_CreateEndorsementKeyPair", FALSE
, &tpmresp
, &tpmresp_len
);
1500 if (tpmresp_len
< 34 + sizeof(length
))
1502 memcpy(&length
, &tpmresp
[34], sizeof(length
));
1503 length
= be32toh(length
);
1504 if (length
!= 256) {
1505 logerr(self
->logfile
, "Offset to EK Public key is wrong.\n");
1510 if (tpmresp_len
< 38 + *pubek_len
)
1512 *pubek
= g_malloc(256);
1513 memcpy(*pubek
, &tpmresp
[38], *pubek_len
);
1518 logerr(self
->logfile
, "Response from TPM_CreateEndorsementKeyPair is too short!\n");
1522 /* Create an OIAP session */
1523 static int swtpm_tpm12_oiap(struct swtpm
*self
, uint32_t *authhandle
, unsigned char nonce_even
[SHA_DIGEST_LENGTH
])
1525 struct tpm_req_header req
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND
, sizeof(req
), TPM_ORD_OIAP
);
1526 unsigned char tpmresp
[64];
1527 size_t tpmresp_len
= sizeof(tpmresp
);
1530 ret
= transfer(self
, &req
, sizeof(req
), "TPM_OIAP", FALSE
, &tpmresp
, &tpmresp_len
);
1534 if (tpmresp_len
< 10 + sizeof(*authhandle
) || tpmresp_len
< 14 + SHA_DIGEST_LENGTH
)
1536 memcpy(authhandle
, &tpmresp
[10], sizeof(*authhandle
));
1537 *authhandle
= be32toh(*authhandle
);
1538 memcpy(nonce_even
, &tpmresp
[14], SHA_DIGEST_LENGTH
);
1543 logerr(self
->logfile
, "Response from TPM_OIAP is too short!\n");
1547 static int swtpm_tpm12_take_ownership(struct swtpm
*self
, const unsigned char ownerpass_digest
[SHA_DIGEST_LENGTH
],
1548 const unsigned char srkpass_digest
[SHA_DIGEST_LENGTH
],
1549 const unsigned char *pubek
, size_t pubek_len
)
1551 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND
, 0, TPM_ORD_TAKE_OWNERSHIP
);
1552 EVP_PKEY
*pkey
= NULL
;
1553 EVP_PKEY_CTX
*ctx
= NULL
;
1554 BIGNUM
*exp
= BN_new();
1556 #if OPENSSL_VERSION_NUMBER < 0x30000000L
1557 RSA
*rsakey
= RSA_new();
1560 const EVP_MD
*sha1
= EVP_sha1();
1561 g_autofree
unsigned char *enc_owner_auth
= g_malloc(pubek_len
);
1562 size_t enc_owner_auth_len
= pubek_len
;
1563 g_autofree
unsigned char *enc_srk_auth
= g_malloc(pubek_len
);
1564 size_t enc_srk_auth_len
= pubek_len
;
1565 uint32_t auth_handle
;
1566 unsigned char nonce_even
[SHA_DIGEST_LENGTH
];
1567 unsigned char nonce_odd
[SHA_DIGEST_LENGTH
] = {1, 2, 3, 4, 5, 6, };
1568 g_autofree
unsigned char *tpm_rsa_key_parms
= NULL
;
1569 ssize_t tpm_rsa_key_parms_len
;
1570 g_autofree
unsigned char *tpm_key_parms
= NULL
;
1571 ssize_t tpm_key_parms_len
;
1572 g_autofree
unsigned char *tpm_key12
= NULL
;
1573 ssize_t tpm_key12_len
;
1574 g_autofree
unsigned char *in_auth_setup_params
= NULL
;
1575 ssize_t in_auth_setup_params_len
;
1576 g_autofree
unsigned char *macinput
= NULL
;
1577 ssize_t macinput_len
;
1578 unsigned char in_param_digest
[SHA_DIGEST_LENGTH
];
1579 unsigned char owner_auth
[SHA_DIGEST_LENGTH
];
1580 unsigned int owner_auth_len
= sizeof(owner_auth
);
1581 uint8_t continue_auth_session
= 0;
1582 unsigned char req
[1024];
1583 ssize_t req_len
, len
;
1584 struct tpm_req_header
*trh
;
1586 mod
= BN_bin2bn((const unsigned char *)pubek
, pubek_len
, NULL
);
1587 if (exp
== NULL
|| mod
== NULL
||
1588 BN_hex2bn(&exp
, "10001") == 0) {
1589 logerr(self
->logfile
, "Could not create public RSA key!\n");
1593 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1594 ctx
= EVP_PKEY_CTX_new_from_name(NULL
, "rsa", NULL
);
1596 OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
1600 OSSL_PARAM_BLD_push_BN(bld
, OSSL_PKEY_PARAM_RSA_E
, exp
) != 1 ||
1601 OSSL_PARAM_BLD_push_BN(bld
, OSSL_PKEY_PARAM_RSA_N
, mod
) != 1 ||
1602 (params
= OSSL_PARAM_BLD_to_param(bld
)) == NULL
) {
1603 OSSL_PARAM_BLD_free(bld
);
1606 OSSL_PARAM_BLD_free(bld
);
1608 if (EVP_PKEY_fromdata_init(ctx
) != 1 ||
1609 EVP_PKEY_fromdata(ctx
, &pkey
, EVP_PKEY_PUBLIC_KEY
, params
) != 1) {
1610 logerr(self
->logfile
, "Could not set pkey parameters!\n");
1611 OSSL_PARAM_free(params
);
1614 OSSL_PARAM_free(params
);
1616 EVP_PKEY_CTX_free(ctx
);
1618 logerr(self
->logfile
, "Could not create key creation context!\n");
1621 ctx
= EVP_PKEY_CTX_new_from_pkey(NULL
, pkey
, NULL
);
1625 pkey
= EVP_PKEY_new();
1627 logerr(self
->logfile
, "Could not allocate pkey!\n");
1631 # if OPENSSL_VERSION_NUMBER < 0x10100000
1635 if (RSA_set0_key(rsakey
, mod
, exp
, NULL
) != 1) {
1636 logerr(self
->logfile
, "Could not create public RSA key!\n");
1640 if (EVP_PKEY_assign_RSA(pkey
, rsakey
) != 1) {
1641 logerr(self
->logfile
, "Could not create public RSA key!\n");
1642 goto error_free_pkey_and_rsa
;
1645 ctx
= EVP_PKEY_CTX_new(pkey
, NULL
);
1647 goto error_free_pkey
;
1648 #endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1650 if (EVP_PKEY_encrypt_init(ctx
) < 1 ||
1651 EVP_PKEY_CTX_set_rsa_padding(ctx
, RSA_PKCS1_OAEP_PADDING
) < 1 ||
1652 EVP_PKEY_CTX_set_rsa_mgf1_md(ctx
, sha1
) < 1 ||
1653 EVP_PKEY_CTX_set_rsa_oaep_md(ctx
, sha1
) < 1 ||
1654 EVP_PKEY_CTX_set0_rsa_oaep_label(ctx
, strdup("TCPA"), 4) < 1 ||
1655 EVP_PKEY_encrypt(ctx
, enc_owner_auth
, &enc_owner_auth_len
,
1656 ownerpass_digest
, SHA_DIGEST_LENGTH
) < 1||
1657 EVP_PKEY_encrypt(ctx
, enc_srk_auth
, &enc_srk_auth_len
,
1658 srkpass_digest
, SHA_DIGEST_LENGTH
) < 1) {
1659 logerr(self
->logfile
, "Internal error in %s: encryption failed\n", __func__
);
1662 ret
= swtpm_tpm12_oiap(self
, &auth_handle
, nonce_even
);
1666 tpm_rsa_key_parms_len
= memconcat(&tpm_rsa_key_parms
,
1668 AS4BE(2048), AS4BE(2), AS4BE(0)
1671 if (tpm_rsa_key_parms_len
< 0) {
1672 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1676 tpm_key_parms_len
= memconcat(&tpm_key_parms
,
1679 AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1
),
1681 AS4BE(tpm_rsa_key_parms_len
)}, (size_t)12,
1682 tpm_rsa_key_parms
, tpm_rsa_key_parms_len
,
1684 if (tpm_key_parms_len
< 0) {
1685 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1689 tpm_key12_len
= memconcat(&tpm_key12
,
1691 AS2BE(TPM_TAG_KEY12
), AS2BE(0),
1692 AS2BE(TPM_KEY_STORAGE
), AS4BE(0), TPM_AUTH_ALWAYS
1694 tpm_key_parms
, tpm_key_parms_len
,
1695 (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12,
1697 if (tpm_key12_len
< 0) {
1698 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1702 req_len
= concat(req
, sizeof(req
),
1704 (unsigned char[]){AS2BE(TPM_PID_OWNER
), AS4BE(enc_owner_auth_len
)}, (size_t)6,
1705 enc_owner_auth
, enc_owner_auth_len
,
1706 (unsigned char[]){AS4BE(enc_srk_auth_len
)}, (size_t)4,
1707 enc_srk_auth
, enc_srk_auth_len
,
1708 tpm_key12
, tpm_key12_len
,
1711 logerr(self
->logfile
, "Internal error in %s: req is too small\n");
1714 SHA1(&req
[6], req_len
- 6, in_param_digest
);
1716 in_auth_setup_params_len
= memconcat(&in_auth_setup_params
,
1717 nonce_even
, sizeof(nonce_even
),
1718 nonce_odd
, sizeof(nonce_odd
),
1719 &continue_auth_session
, (size_t)1,
1721 if (in_auth_setup_params_len
< 0) {
1722 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1726 macinput_len
= memconcat(&macinput
,
1727 in_param_digest
, sizeof(in_param_digest
),
1728 in_auth_setup_params
, in_auth_setup_params_len
,
1730 if (macinput_len
< 0) {
1731 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1735 HMAC(sha1
, ownerpass_digest
, SHA_DIGEST_LENGTH
, macinput
, macinput_len
,
1736 owner_auth
, &owner_auth_len
);
1738 len
= concat(&req
[req_len
], sizeof(req
) - req_len
,
1739 (unsigned char[]){AS4BE(auth_handle
)}, (size_t)4,
1740 nonce_odd
, sizeof(nonce_odd
),
1741 &continue_auth_session
, (size_t)1,
1742 owner_auth
, owner_auth_len
,
1745 logerr(self
->logfile
, "Internal error in %s: req is too small\n");
1750 trh
= (struct tpm_req_header
*)req
; /* old gcc type-punned pointer */
1751 trh
->size
= htobe32(req_len
);
1753 ret
= transfer(self
, req
, req_len
, "TPM_TakeOwnership", FALSE
, NULL
, 0);
1756 EVP_PKEY_free(pkey
);
1757 EVP_PKEY_CTX_free(ctx
);
1758 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1768 #if OPENSSL_VERSION_NUMBER < 0x30000000L
1769 error_free_pkey_and_rsa
:
1773 EVP_PKEY_CTX_free(ctx
);
1775 EVP_PKEY_free(pkey
);
1780 static int swtpm_tpm12_nv_define_space(struct swtpm
*self
, uint32_t nvindex
,
1781 uint32_t nvindexattrs
, size_t size
)
1783 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND
, 0, TPM_ORD_NV_DEFINE_SPACE
);
1784 g_autofree
unsigned char *pcr_info_short
= NULL
;
1785 ssize_t pcr_info_short_len
;
1786 g_autofree
unsigned char *nv_data_public
= NULL
;
1787 ssize_t nv_data_public_len
;
1788 g_autofree
unsigned char *req
= NULL
;
1790 unsigned char zeroes
[SHA_DIGEST_LENGTH
] = {0, };
1792 pcr_info_short_len
= memconcat(&pcr_info_short
,
1793 (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL
}, (size_t)6,
1794 zeroes
, sizeof(zeroes
),
1796 if (pcr_info_short_len
< 0) {
1797 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1801 nv_data_public_len
= memconcat(&nv_data_public
,
1803 AS2BE(TPM_TAG_NV_DATA_PUBLIC
), AS4BE(nvindex
)
1805 pcr_info_short
, pcr_info_short_len
,
1806 pcr_info_short
, pcr_info_short_len
,
1808 AS2BE(TPM_TAG_NV_ATTRIBUTES
), AS4BE(nvindexattrs
),
1809 0, 0, 0, AS4BE(size
)
1812 if (nv_data_public_len
< 0) {
1813 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1817 req_len
= memconcat(&req
,
1819 nv_data_public
, nv_data_public_len
,
1820 zeroes
, sizeof(zeroes
),
1823 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1827 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
1829 return transfer(self
, req
, req_len
, "TPM_NV_DefineSpace", FALSE
, NULL
, 0);
1832 static int swtpm_tpm12_nv_write_value(struct swtpm
*self
, uint32_t nvindex
,
1833 const unsigned char *data
, size_t data_len
)
1835 struct tpm_req_header hdr
= TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND
, 0, TPM_ORD_NV_WRITE_VALUE
);
1836 g_autofree
unsigned char *req
= NULL
;
1839 req_len
= memconcat(&req
,
1841 (unsigned char[]){AS4BE(nvindex
), AS4BE(0), AS4BE(data_len
)}, (size_t)12,
1845 logerr(self
->logfile
, "Internal error in %s: out of memory\n");
1849 ((struct tpm_req_header
*)req
)->size
= htobe32(req_len
);
1851 return transfer(self
, req
, req_len
, "TPM_NV_DefineSpace", FALSE
, NULL
, 0);
1854 /* Write the EK Certificate into NVRAM */
1855 static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm
*self
,
1856 const unsigned char *data
, size_t data_len
)
1858 uint32_t nvindex
= TPM_NV_INDEX_EKCERT
| TPM_NV_INDEX_D_BIT
;
1859 int ret
= swtpm_tpm12_nv_define_space(self
, nvindex
,
1860 TPM_NV_PER_OWNERREAD
| TPM_NV_PER_OWNERWRITE
, data_len
);
1864 ret
= swtpm_tpm12_nv_write_value(self
, nvindex
, data
, data_len
);
1871 /* Write the Platform Certificate into NVRAM */
1872 static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm
*self
,
1873 const unsigned char *data
, size_t data_len
)
1875 uint32_t nvindex
= TPM_NV_INDEX_PLATFORMCERT
| TPM_NV_INDEX_D_BIT
;
1876 int ret
= swtpm_tpm12_nv_define_space(self
, nvindex
,
1877 TPM_NV_PER_OWNERREAD
| TPM_NV_PER_OWNERWRITE
, data_len
);
1881 ret
= swtpm_tpm12_nv_write_value(self
, nvindex
, data
, data_len
);
1888 static int swtpm_tpm12_nv_lock(struct swtpm
*self
)
1890 return swtpm_tpm12_nv_define_space(self
, TPM_NV_INDEX_LOCK
, 0, 0);
1893 static const struct swtpm12_ops swtpm_tpm12_ops
= {
1894 .run_swtpm_bios
= swtpm_tpm12_run_swtpm_bios
,
1895 .create_endorsement_key_pair
= swptm_tpm12_create_endorsement_keypair
,
1896 .take_ownership
= swtpm_tpm12_take_ownership
,
1897 .write_ek_cert_nvram
= swtpm_tpm12_write_ek_cert_nvram
,
1898 .write_platform_cert_nvram
= swtpm_tpm12_write_platform_cert_nvram
,
1899 .nv_lock
= swtpm_tpm12_nv_lock
,
1902 static void swtpm_init(struct swtpm
*swtpm
,
1903 gchar
**swtpm_exec_l
, const gchar
*state_path
,
1904 const gchar
*keyopts
, const gchar
*logfile
,
1905 int *fds_to_pass
, size_t n_fds_to_pass
,
1908 swtpm
->cops
= &swtpm_cops
;
1909 swtpm
->swtpm_exec_l
= swtpm_exec_l
;
1910 swtpm
->state_path
= state_path
;
1911 swtpm
->keyopts
= keyopts
;
1912 swtpm
->logfile
= logfile
;
1913 swtpm
->fds_to_pass
= fds_to_pass
;
1914 swtpm
->n_fds_to_pass
= n_fds_to_pass
;
1915 swtpm
->is_tpm2
= is_tpm2
;
1918 swtpm
->ctrl_fds
[0] = swtpm
->ctrl_fds
[1] = -1;
1919 swtpm
->data_fds
[0] = swtpm
->data_fds
[1] = -1;
1922 struct swtpm12
*swtpm12_new(gchar
**swtpm_exec_l
, const gchar
*state_path
,
1923 const gchar
*keyopts
, const gchar
*logfile
,
1924 int *fds_to_pass
, size_t n_fds_to_pass
)
1926 struct swtpm12
*swtpm12
= g_malloc0(sizeof(struct swtpm12
));
1928 swtpm_init(&swtpm12
->swtpm
, swtpm_exec_l
, state_path
, keyopts
, logfile
,
1929 fds_to_pass
, n_fds_to_pass
, FALSE
);
1930 swtpm12
->ops
= &swtpm_tpm12_ops
;
1935 struct swtpm2
*swtpm2_new(gchar
**swtpm_exec_l
, const gchar
*state_path
,
1936 const gchar
*keyopts
, const gchar
*logfile
,
1937 int *fds_to_pass
, size_t n_fds_to_pass
)
1939 struct swtpm2
*swtpm2
= g_malloc0(sizeof(struct swtpm2
));
1941 swtpm_init(&swtpm2
->swtpm
, swtpm_exec_l
, state_path
, keyopts
, logfile
,
1942 fds_to_pass
, n_fds_to_pass
, TRUE
);
1943 swtpm2
->ops
= &swtpm_tpm2_ops
;
1948 void swtpm_free(struct swtpm
*swtpm
) {