From d9e77fe068b9004fefd0c58024107cf2e5956d78 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 17 Jun 2021 11:13:58 -0400 Subject: [PATCH 1/4] swtpm_setup: Move functions checking for directory access to library Move code from setpm_setup into new function check_directory_access that checks for existence of directory and access to it. Signed-off-by: Stefan Berger --- src/swtpm_setup/swtpm_setup.c | 16 +--------------- src/utils/swtpm_utils.c | 23 +++++++++++++++++++++++ src/utils/swtpm_utils.h | 4 ++++ 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/swtpm_setup/swtpm_setup.c b/src/swtpm_setup/swtpm_setup.c index f06ef547..5d9df40d 100644 --- a/src/swtpm_setup/swtpm_setup.c +++ b/src/swtpm_setup/swtpm_setup.c @@ -1294,22 +1294,8 @@ int main(int argc, char *argv[]) logerr(gl_LOGFILE, "--tpm-state must be provided\n"); goto error; } - if (stat(tpm_state_path, &statbuf) != 0 || (statbuf.st_mode & S_IFMT) != S_IFDIR) { - logerr(gl_LOGFILE, - "User %s cannot access directory %s. Make sure it exists and is a directory.\n", - curr_user ? curr_user->pw_name : "", tpm_state_path); - goto error; - } - if (access(tpm_state_path, R_OK) != 0) { - logerr(gl_LOGFILE, "Need read rights on directory %s for user %s.\n", - tpm_state_path, curr_user ? curr_user->pw_name : ""); + if (check_directory_access(tpm_state_path, R_OK|W_OK, curr_user) != 0) goto error; - } - if (access(tpm_state_path, W_OK) != 0) { - logerr(gl_LOGFILE, "Need write rights on directory %s for user %s.\n", - tpm_state_path, curr_user ? curr_user->pw_name : ""); - goto error; - } if (flags & SETUP_TPM2_F) { if (flags & SETUP_TAKEOWN_F) { diff --git a/src/utils/swtpm_utils.c b/src/utils/swtpm_utils.c index 3fe09439..0a28c620 100644 --- a/src/utils/swtpm_utils.c +++ b/src/utils/swtpm_utils.c @@ -417,3 +417,26 @@ gchar *str_replace(const char *in, const char *torep, const char *rep) return res; } + +int check_directory_access(const gchar *directory, int mode, const struct passwd *curr_user) +{ + struct stat statbuf; + + if (stat(directory, &statbuf) != 0 || (statbuf.st_mode & S_IFMT) != S_IFDIR) { + logerr(gl_LOGFILE, + "User %s cannot access directory %s. Make sure it exists and is a directory.\n", + curr_user ? curr_user->pw_name : "", directory); + return 1; + } + if ((mode & R_OK) && access(directory, R_OK) != 0) { + logerr(gl_LOGFILE, "Need read rights on directory %s for user %s.\n", + directory, curr_user ? curr_user->pw_name : ""); + return 1; + } + if ((mode & W_OK) && access(directory, W_OK) != 0) { + logerr(gl_LOGFILE, "Need write rights on directory %s for user %s.\n", + directory, curr_user ? curr_user->pw_name : ""); + return 1; + } + return 0; +} diff --git a/src/utils/swtpm_utils.h b/src/utils/swtpm_utils.h index 98b32a10..b5379321 100644 --- a/src/utils/swtpm_utils.h +++ b/src/utils/swtpm_utils.h @@ -10,6 +10,8 @@ #ifndef SWTPM_UTILS_H #define SWTPM_UTILS_H +#include + #include #define min(X,Y) (X) < (Y) ? (X) : (Y) @@ -38,4 +40,6 @@ int write_to_tempfile(gchar **filename, const unsigned char *data, size_t data_l gchar *str_replace(const char *in, const char *torep, const char *rep); +int check_directory_access(const gchar *directory, int mode, const struct passwd *curr_user); + #endif /* SWTPM_UTILS_H */ From 3c182dd6be1863d217a4e6d2628da051bf0344a4 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 10 Jun 2021 20:05:05 -0400 Subject: [PATCH 2/4] swtpm_setup: Get key description from function generating the EK key Pass an optional key_description parameter through the APIs to be able to get the a human readable key description, such as 'rsa2048' or 'secp384r1' of the key that was created. Signed-off-by: Stefan Berger --- src/swtpm_setup/swtpm.c | 31 +++++++++++++++++++------------ src/swtpm_setup/swtpm.h | 2 +- src/swtpm_setup/swtpm_setup.c | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/swtpm_setup/swtpm.c b/src/swtpm_setup/swtpm.c index c55e15d8..5c2aba39 100644 --- a/src/swtpm_setup/swtpm.c +++ b/src/swtpm_setup/swtpm.c @@ -425,7 +425,7 @@ static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhand unsigned int rsa_keysize, gboolean havenonce, size_t off, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, - gchar **ekparam); + gchar **ekparam, const gchar **key_description); static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs, const unsigned char *data, size_t data_len, gboolean lock_nvram, @@ -666,7 +666,7 @@ static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_ gboolean allowsigning, gboolean decryption, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, - gchar **ekparam) + gchar **ekparam, const gchar **key_description) { unsigned char authpolicy[48]; size_t authpolicy_len; @@ -738,7 +738,7 @@ static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_ symkeydata, symkeydata_len, authpolicy, authpolicy_len, rsa_keysize, havenonce, off, curr_handle, - ektemplate, ektemplate_len, ekparam); + ektemplate, ektemplate_len, ekparam, key_description); } /* Create an RSA key with the given parameters */ @@ -748,7 +748,7 @@ static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhand unsigned int rsa_keysize, gboolean havenonce, size_t off, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, - gchar **ekparam) + gchar **ekparam, const gchar **key_description) { const unsigned char *nonce; size_t nonce_len; @@ -768,6 +768,8 @@ static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhand nonce = NONCE_RSA2048; nonce_len = sizeof(NONCE_RSA2048); hashalg = TPM2_ALG_SHA256; + if (key_description) + *key_description = "rsa2048"; } else if (rsa_keysize == 3072) { if (!havenonce) { nonce = NONCE_EMPTY; @@ -777,6 +779,8 @@ static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhand nonce_len = sizeof(NONCE_RSA3072); } hashalg = TPM2_ALG_SHA384; + if (key_description) + *key_description = "rsa3072"; } else { logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n", __func__, rsa_keysize); @@ -867,7 +871,7 @@ static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhand const unsigned char *nonce, size_t nonce_len, size_t off, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, - gchar **ekparam) + gchar **ekparam, const gchar **key_description) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); @@ -936,6 +940,8 @@ static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhand if (curveid == TPM2_ECC_NIST_P384) { exp_ksize = 48; cid = "secp384r1"; + if (key_description) + *key_description = cid; } else { logerr(self->logfile, "Unknown curveid 0x%x\n", curveid); return 1; @@ -988,7 +994,7 @@ static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self, return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, TPM2_ECC_NIST_P384, TPM2_ALG_SHA384, NONCE_ECC_384, sizeof(NONCE_ECC_384), off, curr_handle, - NULL, 0, NULL); + NULL, 0, NULL, NULL); } static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize, @@ -1015,7 +1021,7 @@ static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, rsa_keysize, TRUE, - off, curr_handle, NULL, 0, NULL); + off, curr_handle, NULL, 0, NULL, NULL); } /* Create either an ECC or RSA storage primary key */ @@ -1044,7 +1050,7 @@ static int swtpm_tpm2_create_spk(struct swtpm *self, gboolean isecc, unsigned in static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning, gboolean decryption, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, - gchar **ekparam) + gchar **ekparam, const char **key_description) { unsigned char authpolicy[48]= { 0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC, @@ -1090,7 +1096,7 @@ static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolea ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, TPM2_ECC_NIST_P384, TPM2_ALG_SHA384, NONCE_EMPTY, sizeof(NONCE_EMPTY), off, curr_handle, - ektemplate, ektemplate_len, ekparam); + ektemplate, ektemplate_len, ekparam, key_description); if (ret != 0) logerr(self->logfile, "%s failed\n", __func__); @@ -1100,7 +1106,7 @@ static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolea /* Create an ECC or RSA EK */ static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize, gboolean allowsigning, gboolean decryption, gboolean lock_nvram, - gchar **ekparam) + gchar **ekparam, const gchar **key_description) { uint32_t tpm2_ek_handle, nvindex, curr_handle; const char *keytype; @@ -1128,10 +1134,11 @@ static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int } if (isecc) ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle, - ektemplate, &ektemplate_len, ekparam); + ektemplate, &ektemplate_len, ekparam, + key_description); else ret = swtpm_tpm2_createprimary_ek_rsa(self, rsa_keysize, allowsigning, decryption, &curr_handle, - ektemplate, &ektemplate_len, ekparam); + ektemplate, &ektemplate_len, ekparam, key_description); if (ret == 0) ret = swtpm_tpm2_evictcontrol(self, curr_handle, tpm2_ek_handle); diff --git a/src/swtpm_setup/swtpm.h b/src/swtpm_setup/swtpm.h index fb70b10d..df10b96a 100644 --- a/src/swtpm_setup/swtpm.h +++ b/src/swtpm_setup/swtpm.h @@ -48,7 +48,7 @@ struct swtpm2_ops { int (*create_spk)(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize); int (*create_ek)(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize, gboolean allowsigning, gboolean decryption, gboolean lock_nvram, - gchar **ekparam); + gchar **ekparam, const gchar **key_description); int (*get_all_pcr_banks)(struct swtpm *self, gchar ***all_pcr_banks); int (*set_active_pcr_banks)(struct swtpm *self, gchar **pcr_banks_l, gchar **all_pcr_banks, gchar ***active); diff --git a/src/swtpm_setup/swtpm_setup.c b/src/swtpm_setup/swtpm_setup.c index 5d9df40d..346df252 100644 --- a/src/swtpm_setup/swtpm_setup.c +++ b/src/swtpm_setup/swtpm_setup.c @@ -315,7 +315,7 @@ static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file !!(flags & SETUP_ALLOW_SIGNING_F), !!(flags & SETUP_DECRYPTION_F), !!(flags & SETUP_LOCK_NVRAM_F), - &ekparam); + &ekparam, NULL); if (ret != 0) return 1; } From f9d0e2327932ba2b9428391bcc1ecec8b50172b5 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 10 Jun 2021 20:53:45 -0400 Subject: [PATCH 3/4] swtpm_setup: Support --write-ek-cert-files as an option Write the EK certificate files into the directory specified as parameter to the --write-ek-cert-files option. Signed-off-by: Stefan Berger --- man/man8/swtpm_setup.pod | 17 ++++ src/swtpm_setup/swtpm_setup.c | 122 ++++++++++++++++++++++++---- tests/_test_print_capabilities | 2 +- tests/_test_tpm2_print_capabilities | 2 +- 4 files changed, 124 insertions(+), 19 deletions(-) diff --git a/man/man8/swtpm_setup.pod b/man/man8/swtpm_setup.pod index 28e3135a..8d7ea677 100644 --- a/man/man8/swtpm_setup.pod +++ b/man/man8/swtpm_setup.pod @@ -194,6 +194,7 @@ The output may contain the following: "features": [ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", + "cmdarg-write-ek-cert-files", "tpm2-rsa-keysize-2048", "tpm2-rsa-keysize-3072", "tpm12-not-need-root" @@ -212,6 +213,10 @@ The I<--keyfile-fd> option is supported. The I<--pwdfile-fd> option is supported. +=item B + +The I<--write-ek-cert-files> option is supported + =item B The shown RSA key sizes are supported for a TPM 2's EK key. If none of the @@ -225,6 +230,18 @@ could do that. =back +=item B<--write-ek-cert-files > + +This option causes endorsement key (EK) files to be written into the provided +directory. The files contain the DER-formatted EKs that were written into the +NVRAM locations of the TPM 1.2 or TPM 2. The EK files have the filename pattern +of ek-.crt. Example for filenames are ek-rsa2048.crt, ek-rsa3072.crt, +and ek-secp384r1.crt. + +The keys that are written for a TPM 2 may change over time as the default +strength of the EK keys changes. This means that one should look for all +files with the above filename pattern when looking for the EKs. + =item B<--help, -h> Display the help screen diff --git a/src/swtpm_setup/swtpm_setup.c b/src/swtpm_setup/swtpm_setup.c index 346df252..f7cb1b3d 100644 --- a/src/swtpm_setup/swtpm_setup.c +++ b/src/swtpm_setup/swtpm_setup.c @@ -55,6 +55,7 @@ #define SETUP_CREATE_SPK_F 4096 #define SETUP_DISPLAY_RESULTS_F 8192 #define SETUP_DECRYPTION_F 16384 +#define SETUP_WRITE_EK_CERT_FILES_F 32768 /* default configuration file */ #define SWTPM_SETUP_CONF "swtpm_setup.conf" @@ -72,7 +73,7 @@ static const struct flag_to_certfile { const char *filename; const char *type; } flags_to_certfiles[] = { - {.flag = SETUP_EK_CERT_F , .filename= "ek.cert", .type = "ek" }, + {.flag = SETUP_EK_CERT_F , .filename = "ek.cert", .type = "ek" }, {.flag = SETUP_PLATFORM_CERT_F, .filename = "platform.cert", .type = "platform" }, {.flag = 0, .filename = NULL, .type = NULL}, }; @@ -298,15 +299,69 @@ static int call_create_certs(unsigned long flags, const gchar *configfile, const return ret; } +static char *create_ek_certfile_name(const gchar *user_certsdir, const gchar *key_description) +{ + g_autofree gchar *filename = g_strdup_printf("ek-%s.crt", key_description); + + return g_strjoin(G_DIR_SEPARATOR_S, user_certsdir, filename, NULL); +} + +/* + * Remove the cert file unless the user wants a copy of it (EK only). + */ +static int certfile_move_or_delete(unsigned long flags, gboolean is_ek, const gchar *certfile, + const gchar *user_certsdir, const gchar *key_description) +{ + g_autofree gchar *content = NULL; + g_autofree gchar *cf = NULL; + gsize content_length; + GError *error = NULL; + size_t offset = 0; + + if (is_ek && (flags & SETUP_WRITE_EK_CERT_FILES_F) && user_certsdir != NULL) { + if (!g_file_get_contents(certfile, &content, &content_length, &error)) + goto error; + + cf = create_ek_certfile_name(user_certsdir, key_description); + if (!(flags & SETUP_TPM2_F)) { + /* A TPM 1.2 certificate has a 7 byte header at the beginning + * that we now remove */ + if (content_length >= 8) + offset = 7; + } + if (!g_file_set_contents(cf, &content[offset], content_length - offset, + &error)) + goto error; + if (g_chmod(cf, S_IRUSR | S_IWUSR | S_IRGRP) < 0) { + logerr(gl_LOGFILE, "Failed to chmod file '%s': %s\n", cf, strerror(errno)); + goto error_unlink; + } + } + unlink(certfile); + + return 0; + +error: + logerr(gl_LOGFILE, "%s\n", error->message); + g_error_free(error); + +error_unlink: + unlink(certfile); + + return 1; +} + /* Create EK and certificate for a TPM 2 */ static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file, const gchar *certsdir, const gchar *vmid, - unsigned int rsa_keysize, struct swtpm2 *swtpm2) + unsigned int rsa_keysize, struct swtpm2 *swtpm2, + const gchar *user_certsdir) { g_autofree gchar *filecontent = NULL; size_t filecontent_len; g_autofree gchar *certfile = NULL; g_autofree gchar *ekparam = NULL; + const char *key_description; size_t idx; int ret; @@ -315,7 +370,7 @@ static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file !!(flags & SETUP_ALLOW_SIGNING_F), !!(flags & SETUP_DECRYPTION_F), !!(flags & SETUP_LOCK_NVRAM_F), - &ekparam, NULL); + &ekparam, &key_description); if (ret != 0) return 1; } @@ -346,9 +401,14 @@ static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file !!(flags & SETUP_LOCK_NVRAM_F), (const unsigned char *)filecontent, filecontent_len); } - unlink(certfile); - if (ret != 0) + if (ret != 0) { + unlink(certfile); + return 1; + } + + if (certfile_move_or_delete(flags, !!(flags_to_certfiles[idx].flag & SETUP_EK_CERT_F), + certfile, user_certsdir, key_description) != 0) return 1; } } @@ -360,26 +420,29 @@ static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file /* Create endorsement keys and certificates for a TPM 2 */ static int tpm2_create_eks_and_certs(unsigned long flags, const gchar *config_file, const gchar *certsdir, const gchar *vmid, - unsigned int rsa_keysize, struct swtpm2 *swtpm2) + unsigned int rsa_keysize, struct swtpm2 *swtpm2, + const gchar *user_certsdir) { int ret; /* 1st key will be RSA */ flags = flags & ~SETUP_TPM2_ECC_F; - ret = tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2); + ret = tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2, + user_certsdir); if (ret != 0) return 1; /* 2nd key will be an ECC; no more platform cert */ flags = (flags & ~SETUP_PLATFORM_CERT_F) | SETUP_TPM2_ECC_F; - return tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2); + return tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2, + user_certsdir); } /* Simulate manufacturing a TPM 2: create keys and certificates */ static int init_tpm2(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file, const gchar *tpm2_state_path, const gchar *vmid, const gchar *pcr_banks, const gchar *swtpm_keyopt, int *fds_to_pass, size_t n_fds_to_pass, - unsigned int rsa_keysize) + unsigned int rsa_keysize, const gchar *user_certsdir) { g_autofree gchar *certsdir = g_strdup(tpm2_state_path); struct swtpm2 *swtpm2; @@ -404,7 +467,8 @@ static int init_tpm2(unsigned long flags, gchar **swtpm_prg_l, const gchar *conf goto destroy; } - ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2); + ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2, + user_certsdir); if (ret != 0) goto destroy; @@ -503,7 +567,8 @@ static int tpm12_take_ownership(unsigned long flags, const gchar *ownerpass, /* Create the certificates for a TPM 1.2 */ static int tpm12_create_certs(unsigned long flags, const gchar *config_file, const gchar *certsdir, const gchar *ekparam, - const gchar *vmid, struct swtpm12 *swtpm12) + const gchar *vmid, struct swtpm12 *swtpm12, + const gchar *user_certsdir) { g_autofree gchar *filecontent = NULL; g_autofree gchar *certfile = NULL; @@ -538,8 +603,14 @@ static int tpm12_create_certs(unsigned long flags, const gchar *config_file, if (ret == 0) logit(gl_LOGFILE, "Successfully created NVRAM area for Platform certificate.\n"); } - unlink(certfile); - if (ret != 0) + + if (ret != 0) { + unlink(certfile); + return 1; + } + + if (certfile_move_or_delete(flags, !!(flags_to_certfiles[idx].flag & SETUP_EK_CERT_F), + certfile, user_certsdir, "rsa2048") != 0) return 1; } } @@ -551,7 +622,7 @@ static int tpm12_create_certs(unsigned long flags, const gchar *config_file, static int init_tpm(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file, const gchar *tpm_state_path, const gchar *ownerpass, const gchar *srkpass, const gchar *vmid, const gchar *swtpm_keyopt, - int *fds_to_pass, size_t n_fds_to_pass) + int *fds_to_pass, size_t n_fds_to_pass, const gchar *user_certsdir) { g_autofree gchar *certsdir = g_strdup(tpm_state_path); struct swtpm12 *swtpm12; @@ -596,7 +667,8 @@ static int init_tpm(unsigned long flags, gchar **swtpm_prg_l, const gchar *confi if ((flags & SETUP_EK_CERT_F)) { g_autofree gchar *ekparam = print_as_hex((unsigned char *)pubek, pubek_len); - ret = tpm12_create_certs(flags, config_file, certsdir, ekparam, vmid, swtpm12); + ret = tpm12_create_certs(flags, config_file, certsdir, ekparam, vmid, swtpm12, + user_certsdir); if (ret != 0) goto destroy; } @@ -786,6 +858,9 @@ static void usage(const char *prgname, const char *default_config_file) " if libtpms supports it.\n" " Default: %u\n" "\n" + "--write-ek-cert-files \n" + " : Write EK cert files into the given directory\n" + "\n" "--tcsd-system-ps-file \n" " : This option is deprecated and has no effect.\n" "\n" @@ -902,6 +977,7 @@ static int print_capabilities(char **swtpm_prg_l) printf("{ \"type\": \"swtpm_setup\", " "\"features\": [ \"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\"" + ", \"cmdarg-write-ek-cert-files\"" "%s ] }\n", param); g_strfreev(keysize_strs); @@ -1035,6 +1111,7 @@ int main(int argc, char *argv[]) {"decryption", no_argument, NULL, 'd'}, {"pcr-banks", required_argument, NULL, 'b'}, {"rsa-keysize", required_argument, NULL, 'A'}, + {"write-ek-cert-files", required_argument, NULL, '3'}, {"tcsd-system-ps-file", required_argument, NULL, 'F'}, {"version", no_argument, NULL, '1'}, {"print-capabilities", no_argument, NULL, 'y'}, @@ -1061,6 +1138,7 @@ int main(int argc, char *argv[]) unsigned int rsa_keysize; g_autofree gchar *swtpm_keyopt = NULL; g_autofree gchar *runas = NULL; + g_autofree gchar *user_certsdir = NULL; gchar *tmp; gchar **swtpm_prg_l = NULL; gchar **tmp_l = NULL; @@ -1212,6 +1290,11 @@ int main(int argc, char *argv[]) g_free(rsa_keysize_str); rsa_keysize_str = strdup(optarg); break; + case '3': /* --write-ek-cert-files */ + g_free(user_certsdir); + user_certsdir = g_strdup(optarg); + flags |= SETUP_WRITE_EK_CERT_FILES_F; + break; case 'F': /* --tcsd-system-ps-file */ printf("Warning: --tcsd-system-ps-file is deprecated and has no effect."); break; @@ -1297,6 +1380,11 @@ int main(int argc, char *argv[]) if (check_directory_access(tpm_state_path, R_OK|W_OK, curr_user) != 0) goto error; + if ((flags & SETUP_WRITE_EK_CERT_FILES_F)) { + if (check_directory_access(user_certsdir, W_OK, curr_user) != 0) + goto error; + } + if (flags & SETUP_TPM2_F) { if (flags & SETUP_TAKEOWN_F) { logerr(gl_LOGFILE, "Taking ownership is not supported for TPM 2.\n"); @@ -1431,10 +1519,10 @@ int main(int argc, char *argv[]) if ((flags & SETUP_TPM2_F) == 0) { ret = init_tpm(flags, swtpm_prg_l, config_file, tpm_state_path, ownerpass, srkpass, vmid, - swtpm_keyopt, fds_to_pass, n_fds_to_pass); + swtpm_keyopt, fds_to_pass, n_fds_to_pass, user_certsdir); } else { ret = init_tpm2(flags, swtpm_prg_l, config_file, tpm_state_path, vmid, pcr_banks, - swtpm_keyopt, fds_to_pass, n_fds_to_pass, rsa_keysize); + swtpm_keyopt, fds_to_pass, n_fds_to_pass, rsa_keysize, user_certsdir); } if (ret == 0) { diff --git a/tests/_test_print_capabilities b/tests/_test_print_capabilities index 02abd26e..6b7494ce 100755 --- a/tests/_test_print_capabilities +++ b/tests/_test_print_capabilities @@ -43,7 +43,7 @@ if [ $? -ne 0 ]; then fi # The are some variable parameters at the end, use regex -exp='\{ "type": "swtpm_setup", "features": \[ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \] \}' +exp='\{ "type": "swtpm_setup", "features": \[ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \] \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:" echo "Actual : ${msg}" diff --git a/tests/_test_tpm2_print_capabilities b/tests/_test_tpm2_print_capabilities index d31c8fc4..4e36e236 100755 --- a/tests/_test_tpm2_print_capabilities +++ b/tests/_test_tpm2_print_capabilities @@ -44,7 +44,7 @@ if [ $? -ne 0 ]; then fi # The are some variable parameters at the end, use regex -exp='\{ "type": "swtpm_setup", "features": \[ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \] \}' +exp='\{ "type": "swtpm_setup", "features": \[ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \] \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:" echo "Actual : ${msg}" From 899c657fa9f81c5608d8de05d28bab12db129415 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Mon, 14 Jun 2021 16:02:29 -0400 Subject: [PATCH 4/4] tests: Use the --write-ek-cert-files option and check for files Use the --write-ek-cert-files option in existing test cases and check for written files and correctness of the files. Signed-off-by: Stefan Berger --- tests/test_swtpm_setup_create_cert | 16 ++++++++++- tests/test_tpm2_swtpm_setup_create_cert | 36 ++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/tests/test_swtpm_setup_create_cert b/tests/test_swtpm_setup_create_cert index a0066743..d6617e5a 100755 --- a/tests/test_swtpm_setup_create_cert +++ b/tests/test_swtpm_setup_create_cert @@ -63,7 +63,8 @@ $SWTPM_SETUP \ --create-ek-cert \ --config ${workdir}/swtpm_setup.conf \ --logfile ${workdir}/logfile \ - --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" + --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ + --write-ek-cert-files "${workdir}" if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." @@ -99,6 +100,19 @@ if [ -z "$(grep "ENCRYPTED PRIVATE KEY" ${workdir}/swtpm-localca-rootca-privkey. exit 1 fi +certfile="${workdir}/ek-rsa2048.crt" +if [ ! -f "${certfile}" ]; then + echo "Error: EK file '${certfile}' was not written." + ls -l "${workdir}" + exit 1 +fi + +if [ -z "$($CERTTOOL --inder --infile "${certfile}" -i | grep "2048 bits")" ]; then + echo "Error: EK file '${certfile}' is not an RSA 2048 bit key." + $CERTTOOL --inder --infile "${certfile}" -i + exit 1 +fi + echo "OK" exit 0 diff --git a/tests/test_tpm2_swtpm_setup_create_cert b/tests/test_tpm2_swtpm_setup_create_cert index 63adfcb4..75cbfef9 100755 --- a/tests/test_tpm2_swtpm_setup_create_cert +++ b/tests/test_tpm2_swtpm_setup_create_cert @@ -16,6 +16,8 @@ workdir=$(mktemp -d "/tmp/path with spaces.XXXXXX") SIGNINGKEY=${workdir}/signingkey.pem ISSUERCERT=${workdir}/issuercert.pem CERTSERIAL=${workdir}/certserial +USER_CERTSDIR=${workdir}/mycerts +mkdir -p "${USER_CERTSDIR}" PATH=${TOPBUILD}/src/swtpm_bios:$PATH @@ -76,7 +78,8 @@ for keysize in $(echo $keysizes); do --logfile "${workdir}/logfile" \ --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ --rsa-keysize ${keysize} \ - --overwrite + --overwrite \ + --write-ek-cert-files "${USER_CERTSDIR}" if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." @@ -100,7 +103,20 @@ for keysize in $(echo $keysizes); do exit 1 fi - rm -rf ${SIGNINGKEY} ${ISSUERCERT} ${CERTSERIAL} + certfile="${USER_CERTSDIR}/ek-rsa${keysize}.crt" + if [ ! -f "${certfile}" ]; then + echo "Error: EK file '${certfile}' was not written." + ls -l "${USER_CERTSDIR}" + exit 1 + fi + + if [ -z "$($CERTTOOL --inder --infile "${certfile}" -i | grep "${keysize} bits")" ]; then + echo "Error: EK file '${certfile}' is not an RSA ${keysize} bit key." + $CERTTOOL --inder --infile "${certfile}" -i + exit 1 + fi + + rm -rf "${SIGNINGKEY}" "${ISSUERCERT}" "${CERTSERIAL}" ${USER_CERTSDIR}/ek-*.crt done echo "Test 1: OK" @@ -115,7 +131,8 @@ $SWTPM_SETUP \ --config "${workdir}/swtpm_setup.conf" \ --logfile "${workdir}/logfile" \ --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ - --overwrite + --overwrite \ + --write-ek-cert-files "${workdir}" if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." @@ -139,6 +156,19 @@ if [ ! -r "${CERTSERIAL}" ]; then exit 1 fi +certfile="${workdir}/ek-secp384r1.crt" +if [ ! -f "${certfile}" ]; then + echo "Error: EK file '${certfile}' was not written." + ls -l "${workdir}" + exit 1 +fi + +if [ -z "$($CERTTOOL --inder --infile "${certfile}" -i | grep "384 bits")" ]; then + echo "Error: EK file '${certfile}' is not an ECC 384 bit key." + $CERTTOOL --inder --infile "${certfile}" -i + exit 1 +fi + echo "Test 2: OK" exit 0