mirror of
https://github.com/stefanberger/swtpm.git
synced 2025-08-22 19:04:35 +00:00
swtpm: Enable sending startup commands before processing commands
The vtpm proxy device requires that the TPM be 'Startup' otherwise it fails sending the first command to it and will send the 'Startup' (SU_CLEAR/TPM_ST_CLEAR) itself while adding a log entry. We want to avoid the kernel log entry. Add options to the existing --flags option that allows one to start up the TPM 1.2 or TPM 2.0 with the startup types 'clear', 'state' and 'deactivate' (TPM 1.2 only). Extend the --print-capabilities to advertise the availability of these options with the string 'flags-opt-startup'. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
99f442f37c
commit
e6bc4bdf0a
@ -59,10 +59,11 @@ int capabilities_print_json(bool cusetpm)
|
|||||||
"{ "
|
"{ "
|
||||||
"\"type\": \"swtpm\", "
|
"\"type\": \"swtpm\", "
|
||||||
"\"features\": [ "
|
"\"features\": [ "
|
||||||
"%s%s%s%s"
|
"%s%s%s%s%s"
|
||||||
" ] "
|
" ] "
|
||||||
"}",
|
"}",
|
||||||
!cusetpm ? "\"tpm-send-command-header\", ": "",
|
!cusetpm ? "\"tpm-send-command-header\", ": "",
|
||||||
|
!cusetpm ? "\"flags-opt-startup\", " : "",
|
||||||
cmdarg_seccomp,
|
cmdarg_seccomp,
|
||||||
true ? "\"cmdarg-key-fd\", " : "",
|
true ? "\"cmdarg-key-fd\", " : "",
|
||||||
true ? "\"cmdarg-pwd-fd\"" : ""
|
true ? "\"cmdarg-pwd-fd\"" : ""
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#include "ctrlchannel.h"
|
#include "ctrlchannel.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "seccomp_profile.h"
|
#include "seccomp_profile.h"
|
||||||
|
#include "tpmlib.h"
|
||||||
|
|
||||||
/* --log %s */
|
/* --log %s */
|
||||||
static const OptionDesc logging_opt_desc[] = {
|
static const OptionDesc logging_opt_desc[] = {
|
||||||
@ -233,6 +234,22 @@ static const OptionDesc flags_opt_desc[] = {
|
|||||||
.name = "not-need-init",
|
.name = "not-need-init",
|
||||||
.type = OPT_TYPE_BOOLEAN,
|
.type = OPT_TYPE_BOOLEAN,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "startup-none",
|
||||||
|
.type = OPT_TYPE_BOOLEAN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "startup-clear",
|
||||||
|
.type = OPT_TYPE_BOOLEAN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "startup-state",
|
||||||
|
.type = OPT_TYPE_BOOLEAN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "startup-deactivated",
|
||||||
|
.type = OPT_TYPE_BOOLEAN,
|
||||||
|
},
|
||||||
END_OPTION_DESC
|
END_OPTION_DESC
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1154,7 +1171,8 @@ int handle_locality_options(char *options, uint32_t *flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_flags_options(char *options, bool *need_init_cmd)
|
static int parse_flags_options(char *options, bool *need_init_cmd,
|
||||||
|
uint16_t *startupType)
|
||||||
{
|
{
|
||||||
OptionValues *ovs = NULL;
|
OptionValues *ovs = NULL;
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
@ -1168,6 +1186,18 @@ static int parse_flags_options(char *options, bool *need_init_cmd)
|
|||||||
if (option_get_bool(ovs, "not-need-init", false))
|
if (option_get_bool(ovs, "not-need-init", false))
|
||||||
*need_init_cmd = false;
|
*need_init_cmd = false;
|
||||||
|
|
||||||
|
if (option_get_bool(ovs, "startup-clear", false))
|
||||||
|
*startupType = TPM_ST_CLEAR;
|
||||||
|
else if (option_get_bool(ovs, "startup-state", false))
|
||||||
|
*startupType = TPM_ST_STATE;
|
||||||
|
else if (option_get_bool(ovs, "startup-deactivated", false))
|
||||||
|
*startupType = TPM_ST_DEACTIVATED;
|
||||||
|
else if (option_get_bool(ovs, "startup-none", false))
|
||||||
|
*startupType = _TPM_ST_NONE;
|
||||||
|
|
||||||
|
if (*startupType != _TPM_ST_NONE)
|
||||||
|
*need_init_cmd = false;
|
||||||
|
|
||||||
option_values_free(ovs);
|
option_values_free(ovs);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1186,12 +1216,13 @@ error:
|
|||||||
*
|
*
|
||||||
* Returns 0 on success, -1 on failure.
|
* Returns 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
int handle_flags_options(char *options, bool *need_init_cmd)
|
int handle_flags_options(char *options, bool *need_init_cmd,
|
||||||
|
uint16_t *startupType)
|
||||||
{
|
{
|
||||||
if (!options)
|
if (!options)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (parse_flags_options(options, need_init_cmd) < 0)
|
if (parse_flags_options(options, need_init_cmd, startupType) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -51,7 +51,8 @@ int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc);
|
|||||||
struct server;
|
struct server;
|
||||||
int handle_server_options(char *options, struct server **s);
|
int handle_server_options(char *options, struct server **s);
|
||||||
int handle_locality_options(char *options, uint32_t *flags);
|
int handle_locality_options(char *options, uint32_t *flags);
|
||||||
int handle_flags_options(char *options, bool *need_init_cmd);
|
int handle_flags_options(char *options, bool *need_init_cmd,
|
||||||
|
uint16_t *startupType);
|
||||||
#ifdef WITH_SECCOMP
|
#ifdef WITH_SECCOMP
|
||||||
int handle_seccomp_options(char *options, unsigned int *seccomp_action);
|
int handle_seccomp_options(char *options, unsigned int *seccomp_action);
|
||||||
#else
|
#else
|
||||||
|
@ -134,6 +134,22 @@ int mainLoop(struct mainLoopParams *mlp,
|
|||||||
|
|
||||||
sockfd = SWTPM_IO_GetSocketFD();
|
sockfd = SWTPM_IO_GetSocketFD();
|
||||||
|
|
||||||
|
if (mlp->startupType != _TPM_ST_NONE) {
|
||||||
|
command_length = tpmlib_create_startup_cmd(
|
||||||
|
mlp->startupType,
|
||||||
|
mlp->tpmversion,
|
||||||
|
command, max_command_length);
|
||||||
|
if (command_length > 0)
|
||||||
|
rc = TPMLIB_Process(&rbuffer, &rlength, &rTotal,
|
||||||
|
command, command_length);
|
||||||
|
|
||||||
|
if (rc || command_length == 0) {
|
||||||
|
mainloop_terminate = true;
|
||||||
|
if (rc)
|
||||||
|
logprintf(STDERR_FILENO, "Could not send Startup: 0x%x\n", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!mainloop_terminate) {
|
while (!mainloop_terminate) {
|
||||||
|
|
||||||
while (rc == 0) {
|
while (rc == 0) {
|
||||||
|
@ -59,6 +59,7 @@ struct mainLoopParams {
|
|||||||
struct ctrlchannel *cc;
|
struct ctrlchannel *cc;
|
||||||
uint32_t locality_flags;
|
uint32_t locality_flags;
|
||||||
TPMLIB_TPMVersion tpmversion;
|
TPMLIB_TPMVersion tpmversion;
|
||||||
|
uint16_t startupType; /* use TPM 1.2 types */
|
||||||
};
|
};
|
||||||
|
|
||||||
int mainLoop(struct mainLoopParams *mlp,
|
int mainLoop(struct mainLoopParams *mlp,
|
||||||
|
@ -168,13 +168,14 @@ static void usage(FILE *file, const char *prgname, const char *iface)
|
|||||||
" can be given with the bindaddr parameter\n"
|
" can be given with the bindaddr parameter\n"
|
||||||
"--server type=unixio[,path=path][,fd=fd][,mode=0...][,uid=uid][,gid=gid]\n"
|
"--server type=unixio[,path=path][,fd=fd][,mode=0...][,uid=uid][,gid=gid]\n"
|
||||||
" : Expect UnixIO connections on the given path; if fd is\n"
|
" : Expect UnixIO connections on the given path; if fd is\n"
|
||||||
" provided, packets wil be read from it directly;\n"
|
" provided, packets will be read from it directly;\n"
|
||||||
" mode allows to set the file mode bits of the socket; the\n"
|
" mode allows to set the file mode bits of the socket; the\n"
|
||||||
" value must be given in octal number format;\n"
|
" value must be given in octal number format;\n"
|
||||||
" uid and gid set the ownership of the Unixio socket's file;\n"
|
" uid and gid set the ownership of the Unixio socket's file;\n"
|
||||||
"--flags [not-need-init]\n"
|
"--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none]\n"
|
||||||
" : not-need-init: commands can be sent without needing to\n"
|
" : not-need-init: commands can be sent without needing to\n"
|
||||||
" send an INIT via control channel;\n"
|
" send an INIT via control channel;\n"
|
||||||
|
" startup-...: send Startup command with this type;\n"
|
||||||
"-r|--runas <user>: change to the given user\n"
|
"-r|--runas <user>: change to the given user\n"
|
||||||
"--tpm2 : choose TPM2 functionality\n"
|
"--tpm2 : choose TPM2 functionality\n"
|
||||||
#ifdef WITH_SECCOMP
|
#ifdef WITH_SECCOMP
|
||||||
@ -214,6 +215,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
|
|||||||
.fd = -1,
|
.fd = -1,
|
||||||
.locality_flags = 0,
|
.locality_flags = 0,
|
||||||
.tpmversion = TPMLIB_TPM_VERSION_1_2,
|
.tpmversion = TPMLIB_TPM_VERSION_1_2,
|
||||||
|
.startupType = _TPM_ST_NONE,
|
||||||
};
|
};
|
||||||
struct server *server = NULL;
|
struct server *server = NULL;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
@ -435,7 +437,8 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
|
|||||||
handle_locality_options(localitydata, &mlp.locality_flags) < 0 ||
|
handle_locality_options(localitydata, &mlp.locality_flags) < 0 ||
|
||||||
handle_tpmstate_options(tpmstatedata) < 0 ||
|
handle_tpmstate_options(tpmstatedata) < 0 ||
|
||||||
handle_seccomp_options(seccompdata, &seccomp_action) < 0 ||
|
handle_seccomp_options(seccompdata, &seccomp_action) < 0 ||
|
||||||
handle_flags_options(flagsdata, &need_init_cmd) < 0) {
|
handle_flags_options(flagsdata, &need_init_cmd,
|
||||||
|
&mlp.startupType) < 0) {
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,10 +193,12 @@ static void usage(FILE *file, const char *prgname, const char *iface)
|
|||||||
"--locality [reject-locality-4][,allow-set-locality]\n"
|
"--locality [reject-locality-4][,allow-set-locality]\n"
|
||||||
" : reject-locality-4: reject any command in locality 4\n"
|
" : reject-locality-4: reject any command in locality 4\n"
|
||||||
" allow-set-locality: accept SetLocality command\n"
|
" allow-set-locality: accept SetLocality command\n"
|
||||||
"--flags [not-need-init]\n"
|
"--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none]\n"
|
||||||
" : not-need-init: commands can be sent without needing to\n"
|
" : not-need-init: commands can be sent without needing to\n"
|
||||||
" send an INIT via control channel; not needed when using\n"
|
" send an INIT via control channel; not needed when using\n"
|
||||||
" --vtpm-proxy\n"
|
" --vtpm-proxy\n"
|
||||||
|
" startup-...: send Startup command with this type;\n"
|
||||||
|
" when --vtpm-proxy is used, startup-clear is used\n"
|
||||||
"--tpm2 : choose TPM2 functionality\n"
|
"--tpm2 : choose TPM2 functionality\n"
|
||||||
#ifdef WITH_SECCOMP
|
#ifdef WITH_SECCOMP
|
||||||
# ifndef SCMP_ACT_LOG
|
# ifndef SCMP_ACT_LOG
|
||||||
@ -234,6 +236,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
|
|||||||
.flags = 0,
|
.flags = 0,
|
||||||
.locality_flags = 0,
|
.locality_flags = 0,
|
||||||
.tpmversion = TPMLIB_TPM_VERSION_1_2,
|
.tpmversion = TPMLIB_TPM_VERSION_1_2,
|
||||||
|
.startupType = _TPM_ST_NONE,
|
||||||
};
|
};
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
char *end_ptr;
|
char *end_ptr;
|
||||||
@ -423,6 +426,11 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
|
|||||||
if (mlp.tpmversion == TPMLIB_TPM_VERSION_2)
|
if (mlp.tpmversion == TPMLIB_TPM_VERSION_2)
|
||||||
vtpm_new_dev.flags = VTPM_PROXY_FLAG_TPM2;
|
vtpm_new_dev.flags = VTPM_PROXY_FLAG_TPM2;
|
||||||
|
|
||||||
|
/* Will be adjusted for TPM 2;
|
||||||
|
* handle_flags_options() will cause need_init_cmd = false to be set
|
||||||
|
*/
|
||||||
|
mlp.startupType = TPM_ST_CLEAR;
|
||||||
|
|
||||||
if (mlp.fd >= 0) {
|
if (mlp.fd >= 0) {
|
||||||
logprintf(STDERR_FILENO,
|
logprintf(STDERR_FILENO,
|
||||||
"Cannot use vTPM proxy with a provided device.\n");
|
"Cannot use vTPM proxy with a provided device.\n");
|
||||||
@ -483,7 +491,8 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
|
|||||||
handle_pid_options(piddata) < 0 ||
|
handle_pid_options(piddata) < 0 ||
|
||||||
handle_tpmstate_options(tpmstatedata) < 0 ||
|
handle_tpmstate_options(tpmstatedata) < 0 ||
|
||||||
handle_seccomp_options(seccompdata, &seccomp_action) < 0 ||
|
handle_seccomp_options(seccompdata, &seccomp_action) < 0 ||
|
||||||
handle_flags_options(flagsdata, &need_init_cmd) < 0) {
|
handle_flags_options(flagsdata, &need_init_cmd,
|
||||||
|
&mlp.startupType) < 0) {
|
||||||
goto exit_failure;
|
goto exit_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,11 +522,6 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
|
|||||||
|
|
||||||
tpmlib_debug_libtpms_parameters(mlp.tpmversion);
|
tpmlib_debug_libtpms_parameters(mlp.tpmversion);
|
||||||
|
|
||||||
#ifdef WITH_VTPM_PROXY
|
|
||||||
if (use_vtpm_proxy)
|
|
||||||
need_init_cmd = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((rc = tpmlib_register_callbacks(&callbacks)))
|
if ((rc = tpmlib_register_callbacks(&callbacks)))
|
||||||
goto error_no_tpm;
|
goto error_no_tpm;
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#ifdef WITH_VTPM_PROXY
|
#ifdef WITH_VTPM_PROXY
|
||||||
#include "vtpm_proxy.h"
|
#include "vtpm_proxy.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert the blobtype integer into a string that libtpms
|
* convert the blobtype integer into a string that libtpms
|
||||||
@ -380,3 +381,46 @@ off_t tpmlib_handle_tcg_tpm2_cmd_header(const unsigned char *command,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a Startup command with the given startupType for the
|
||||||
|
* given TPM version.
|
||||||
|
*/
|
||||||
|
uint32_t tpmlib_create_startup_cmd(uint16_t startupType,
|
||||||
|
TPMLIB_TPMVersion tpmversion,
|
||||||
|
unsigned char *buffer,
|
||||||
|
uint32_t buffersize)
|
||||||
|
{
|
||||||
|
struct tpm_startup ts;
|
||||||
|
uint32_t tocopy = min(sizeof(ts), buffersize);
|
||||||
|
|
||||||
|
ts.hdr.size = htobe32(sizeof(ts));
|
||||||
|
|
||||||
|
switch (tpmversion) {
|
||||||
|
case TPMLIB_TPM_VERSION_1_2:
|
||||||
|
ts.hdr.tag = htobe16(TPM_TAG_RQU_COMMAND);
|
||||||
|
ts.hdr.ordinal = htobe32(TPMLIB_TPM_ORD_Startup);
|
||||||
|
ts.startupType = htobe16(startupType);
|
||||||
|
break;
|
||||||
|
case TPMLIB_TPM_VERSION_2:
|
||||||
|
ts.hdr.tag = htobe16(TPM2_ST_NO_SESSION);
|
||||||
|
ts.hdr.ordinal = htobe32(TPMLIB_TPM2_CC_Startup);
|
||||||
|
switch (startupType) {
|
||||||
|
case TPM_ST_CLEAR:
|
||||||
|
ts.startupType = htobe16(TPM2_SU_CLEAR);
|
||||||
|
break;
|
||||||
|
case TPM_ST_STATE:
|
||||||
|
ts.startupType = htobe16(TPM2_SU_STATE);
|
||||||
|
break;
|
||||||
|
case TPM_ST_DEACTIVATED:
|
||||||
|
tocopy = 0;
|
||||||
|
logprintf(STDERR_FILENO,
|
||||||
|
"TPM 2 does not support startup deactivated.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, &ts, tocopy);
|
||||||
|
return tocopy;
|
||||||
|
}
|
||||||
|
@ -73,6 +73,10 @@ TPM_RESULT tpmlib_process(unsigned char **rbuffer, uint32_t *rlength,
|
|||||||
off_t tpmlib_handle_tcg_tpm2_cmd_header(const unsigned char *command,
|
off_t tpmlib_handle_tcg_tpm2_cmd_header(const unsigned char *command,
|
||||||
uint32_t command_length,
|
uint32_t command_length,
|
||||||
TPM_MODIFIER_INDICATOR *locality);
|
TPM_MODIFIER_INDICATOR *locality);
|
||||||
|
uint32_t tpmlib_create_startup_cmd(uint16_t startupType,
|
||||||
|
TPMLIB_TPMVersion tpmversion,
|
||||||
|
unsigned char *buffer,
|
||||||
|
uint32_t buffersize);
|
||||||
|
|
||||||
struct tpm_req_header {
|
struct tpm_req_header {
|
||||||
uint16_t tag;
|
uint16_t tag;
|
||||||
@ -96,6 +100,12 @@ struct tpm2_resp_prefix {
|
|||||||
uint32_t size; /* size of the following TPM response */
|
uint32_t size; /* size of the following TPM response */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* TPM 1.2 and TPM 2 used the same structured for startup */
|
||||||
|
struct tpm_startup {
|
||||||
|
struct tpm_req_header hdr;
|
||||||
|
uint16_t startupType;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* Commands in tcg_tpm2_cmd_header 'cmd' */
|
/* Commands in tcg_tpm2_cmd_header 'cmd' */
|
||||||
#define TPM2_SEND_COMMAND 8
|
#define TPM2_SEND_COMMAND 8
|
||||||
|
|
||||||
@ -103,9 +113,19 @@ struct tpm2_resp_prefix {
|
|||||||
#define TPM2_ST_NO_SESSION 0x8001
|
#define TPM2_ST_NO_SESSION 0x8001
|
||||||
#define TPM2_ST_SESSIONS 0x8002
|
#define TPM2_ST_SESSIONS 0x8002
|
||||||
|
|
||||||
|
/* Tags supported by TPM 1.2 */
|
||||||
|
#define TPM_TAG_RQU_COMMAND 0x00C1
|
||||||
|
|
||||||
/* TPM 1.2 ordinals */
|
/* TPM 1.2 ordinals */
|
||||||
#define TPMLIB_TPM_ORD_TakeOwnership 0x0000000d
|
#define TPMLIB_TPM_ORD_TakeOwnership 0x0000000d
|
||||||
#define TPMLIB_TPM_ORD_CreateWrapKey 0x0000001f
|
#define TPMLIB_TPM_ORD_CreateWrapKey 0x0000001f
|
||||||
|
#define TPMLIB_TPM_ORD_Startup 0x00000099
|
||||||
|
|
||||||
|
/* TPM 1.2 startup types */
|
||||||
|
#define TPM_ST_CLEAR 0x0001
|
||||||
|
#define TPM_ST_STATE 0x0002
|
||||||
|
#define TPM_ST_DEACTIVATED 0x0003
|
||||||
|
#define _TPM_ST_NONE 0x0000 /* do not send Startup */
|
||||||
|
|
||||||
/* TPM 2 error codes */
|
/* TPM 2 error codes */
|
||||||
#define TPM_RC_INSUFFICIENT 0x09a
|
#define TPM_RC_INSUFFICIENT 0x09a
|
||||||
@ -114,6 +134,11 @@ struct tpm2_resp_prefix {
|
|||||||
|
|
||||||
/* TPM 2 commands */
|
/* TPM 2 commands */
|
||||||
#define TPMLIB_TPM2_CC_CreatePrimary 0x00000131
|
#define TPMLIB_TPM2_CC_CreatePrimary 0x00000131
|
||||||
|
#define TPMLIB_TPM2_CC_Startup 0x00000144
|
||||||
#define TPMLIB_TPM2_CC_Create 0x00000153
|
#define TPMLIB_TPM2_CC_Create 0x00000153
|
||||||
|
|
||||||
|
/* TPM 2 startup types */
|
||||||
|
#define TPM2_SU_CLEAR 0x0000
|
||||||
|
#define TPM2_SU_STATE 0x0001
|
||||||
|
|
||||||
#endif /* _SWTPM_TPMLIB_H_ */
|
#endif /* _SWTPM_TPMLIB_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user