mirror of
https://github.com/systemd/systemd
synced 2024-10-15 12:34:37 +00:00
tpm2-setup: also save the SRK to the file system in TPM2_PUBLIC format
We already save it in PEM format, also store it TPM2_PUBLIC format next to it. This is useful for usage with systemd-cryptenroll's --tpm2-device-key= switch.
This commit is contained in:
parent
fadc7d8cd7
commit
fbe7db47f4
|
@ -37,13 +37,15 @@
|
|||
|
||||
<para>The services will store the public key of the SRK key pair in a PEM file in
|
||||
<filename>/run/systemd/tpm2-srk-public-key.pem</filename> and
|
||||
<filename>/var/lib/systemd/tpm2-srk-public-key.pem</filename>.</para>
|
||||
<filename>/var/lib/systemd/tpm2-srk-public-key.pem</filename>. It will also store it in TPM2B_PUBLIC
|
||||
format in <filename>/run/systemd/tpm2-srk-public-key.tpm2_public</filename> and
|
||||
<filename>/var/lib/systemd/tpm2-srk-public-key.tpm2b_public</filename>.</para>
|
||||
|
||||
<para><filename>systemd-tpm2-setup-early.service</filename> runs very early at boot (possibly in the
|
||||
initrd), and writes the SRK public key to <filename>/run/systemd/tpm2-srk-public-key.pem</filename> (as
|
||||
initrd), and writes the SRK public key to <filename>/run/systemd/tpm2-srk-public-key.*</filename> (as
|
||||
<filename>/var/</filename> is generally not accessible this early yet), while
|
||||
<filename>systemd-tpm2-setup.service</filename> runs during a later boot phase and saves the public key
|
||||
to <filename>/var/lib/systemd/tpm2-srk-public-key.pem</filename>.</para>
|
||||
to <filename>/var/lib/systemd/tpm2-srk-public-key.*</filename>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -52,16 +54,18 @@
|
|||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>/run/systemd/tpm2-srk-public-key.pem</filename></term>
|
||||
<term><filename>/run/systemd/tpm2-srk-public-key.tpm2b_public</filename></term>
|
||||
|
||||
<listitem><para>The SRK public key in PEM format, written during early boot.</para>
|
||||
<listitem><para>The SRK public key in PEM and TPM2B_PUBLIC format, written during early boot.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>/var/lib/systemd/tpm2-srk-public-key.pem</filename></term>
|
||||
<term><filename>/var/lib/systemd/tpm2-srk-public-key.tpm2_public</filename></term>
|
||||
|
||||
<listitem><para>The SRK public key in PEM format, written during later boot (once
|
||||
<listitem><para>The SRK public key in PEM and TPM2B_PUBLIC format, written during later boot (once
|
||||
<filename>/var/</filename> is available).</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
|
|
|
@ -2413,7 +2413,7 @@ static int tpm2_unmarshal_private(const void *data, size_t size, TPM2B_PRIVATE *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tpm2_marshal_public(const TPM2B_PUBLIC *public, void **ret, size_t *ret_size) {
|
||||
int tpm2_marshal_public(const TPM2B_PUBLIC *public, void **ret, size_t *ret_size) {
|
||||
size_t max_size = sizeof(*public), blob_size = 0;
|
||||
_cleanup_free_ void *blob = NULL;
|
||||
TSS2_RC rc;
|
||||
|
|
|
@ -126,6 +126,7 @@ int tpm2_create_primary(Tpm2Context *c, const Tpm2Handle *session, const TPM2B_P
|
|||
int tpm2_create(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handle *session, const TPMT_PUBLIC *template, const TPMS_SENSITIVE_CREATE *sensitive, TPM2B_PUBLIC **ret_public, TPM2B_PRIVATE **ret_private);
|
||||
int tpm2_create_loaded(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handle *session, const TPMT_PUBLIC *template, const TPMS_SENSITIVE_CREATE *sensitive, TPM2B_PUBLIC **ret_public, TPM2B_PRIVATE **ret_private, Tpm2Handle **ret_handle);
|
||||
int tpm2_load(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handle *session, const TPM2B_PUBLIC *public, const TPM2B_PRIVATE *private, Tpm2Handle **ret_handle);
|
||||
int tpm2_marshal_public(const TPM2B_PUBLIC *public, void **ret, size_t *ret_size);
|
||||
int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC *nv_public, void **ret, size_t *ret_size);
|
||||
int tpm2_unmarshal_nv_public(const void *data, size_t size, TPM2B_NV_PUBLIC *ret_nv_public);
|
||||
int tpm2_marshal_blob(const TPM2B_PUBLIC *public, const TPM2B_PRIVATE *private, const TPM2B_ENCRYPTED_SECRET *seed, void **ret_blob, size_t *ret_blob_size);
|
||||
|
|
|
@ -24,6 +24,9 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
|||
#define TPM2_SRK_PEM_PERSISTENT_PATH "/var/lib/systemd/tpm2-srk-public-key.pem"
|
||||
#define TPM2_SRK_PEM_RUNTIME_PATH "/run/systemd/tpm2-srk-public-key.pem"
|
||||
|
||||
#define TPM2_SRK_TPM2B_PUBLIC_PERSISTENT_PATH "/var/lib/systemd/tpm2-srk-public-key.tpm2b_public"
|
||||
#define TPM2_SRK_TPM2B_PUBLIC_RUNTIME_PATH "/run/systemd/tpm2-srk-public-key.tpm2b_public"
|
||||
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
|
@ -111,7 +114,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
struct public_key_data {
|
||||
EVP_PKEY *pkey;
|
||||
EVP_PKEY *pkey; /* as OpenSSL object */
|
||||
TPM2B_PUBLIC *public; /* in TPM2 format */
|
||||
void *fingerprint;
|
||||
size_t fingerprint_size;
|
||||
char *fingerprint_hex;
|
||||
|
@ -125,6 +129,10 @@ static void public_key_data_done(struct public_key_data *d) {
|
|||
EVP_PKEY_free(d->pkey);
|
||||
d->pkey = NULL;
|
||||
}
|
||||
if (d->public) {
|
||||
Esys_Freep(&d->public);
|
||||
d->public = NULL;
|
||||
}
|
||||
d->fingerprint = mfree(d->fingerprint);
|
||||
d->fingerprint_size = 0;
|
||||
d->fingerprint_hex = mfree(d->fingerprint_hex);
|
||||
|
@ -192,7 +200,6 @@ static int load_public_key_disk(const char *path, struct public_key_data *ret) {
|
|||
static int load_public_key_tpm2(struct public_key_data *ret) {
|
||||
_cleanup_(public_key_data_done) struct public_key_data data = {};
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
|
||||
_cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
@ -204,7 +211,7 @@ static int load_public_key_tpm2(struct public_key_data *ret) {
|
|||
r = tpm2_get_or_create_srk(
|
||||
c,
|
||||
/* session= */ NULL,
|
||||
&public,
|
||||
&data.public,
|
||||
/* ret_name= */ NULL,
|
||||
/* ret_qname= */ NULL,
|
||||
NULL);
|
||||
|
@ -215,7 +222,7 @@ static int load_public_key_tpm2(struct public_key_data *ret) {
|
|||
else
|
||||
log_info("SRK already stored in the TPM.");
|
||||
|
||||
r = tpm2_tpm2b_public_to_openssl_pkey(public, &data.pkey);
|
||||
r = tpm2_tpm2b_public_to_openssl_pkey(data.public, &data.pkey);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to convert TPM2 SRK public key to OpenSSL public key: %m");
|
||||
|
||||
|
@ -300,28 +307,64 @@ static int run(int argc, char *argv[]) {
|
|||
public_key_data_done(&persistent_key);
|
||||
}
|
||||
|
||||
const char *path = arg_early ? TPM2_SRK_PEM_RUNTIME_PATH : TPM2_SRK_PEM_PERSISTENT_PATH;
|
||||
|
||||
(void) mkdir_parents(path, 0755);
|
||||
const char *pem_path = arg_early ? TPM2_SRK_PEM_RUNTIME_PATH : TPM2_SRK_PEM_PERSISTENT_PATH;
|
||||
(void) mkdir_parents(pem_path, 0755);
|
||||
|
||||
/* Write out public key (note that we only do that as a help to the user, we don't make use of this ever */
|
||||
_cleanup_(unlink_and_freep) char *t = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
r = fopen_tmpfile_linkable(path, O_WRONLY, &t, &f);
|
||||
r = fopen_tmpfile_linkable(pem_path, O_WRONLY, &t, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open SRK public key file '%s' for writing: %m", path);
|
||||
return log_error_errno(r, "Failed to open SRK public key file '%s' for writing: %m", pem_path);
|
||||
|
||||
if (PEM_write_PUBKEY(f, tpm2_key.pkey) <= 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write SRK public key file '%s'.", path);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write SRK public key file '%s'.", pem_path);
|
||||
|
||||
if (fchmod(fileno(f), 0444) < 0)
|
||||
return log_error_errno(errno, "Failed to adjust access mode of SRK public key file '%s' to 0444: %m", path);
|
||||
return log_error_errno(errno, "Failed to adjust access mode of SRK public key file '%s' to 0444: %m", pem_path);
|
||||
|
||||
r = flink_tmpfile(f, t, path, LINK_TMPFILE_SYNC|LINK_TMPFILE_REPLACE);
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to move SRK public key file to '%s': %m", path);
|
||||
return log_error_errno(r, "Failed to sync SRK key to disk: %m");
|
||||
|
||||
log_info("SRK public key saved to '%s'.", path);
|
||||
r = flink_tmpfile(f, t, pem_path, LINK_TMPFILE_SYNC|LINK_TMPFILE_REPLACE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to move SRK public key file to '%s': %m", pem_path);
|
||||
|
||||
f = safe_fclose(f);
|
||||
t = mfree(t);
|
||||
|
||||
log_info("SRK public key saved to '%s' in PEM format.", pem_path);
|
||||
|
||||
const char *tpm2b_public_path = arg_early ? TPM2_SRK_TPM2B_PUBLIC_RUNTIME_PATH : TPM2_SRK_TPM2B_PUBLIC_PERSISTENT_PATH;
|
||||
(void) mkdir_parents(tpm2b_public_path, 0755);
|
||||
|
||||
/* Now also write this out in TPM2B_PUBLIC format */
|
||||
r = fopen_tmpfile_linkable(tpm2b_public_path, O_WRONLY, &t, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open SRK public key file '%s' for writing: %m", tpm2b_public_path);
|
||||
|
||||
_cleanup_free_ void *marshalled = NULL;
|
||||
size_t marshalled_size = 0;
|
||||
r = tpm2_marshal_public(tpm2_key.public, &marshalled, &marshalled_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to marshal TPM2_PUBLIC key.");
|
||||
|
||||
if (fwrite(marshalled, 1, marshalled_size, f) != marshalled_size)
|
||||
return log_error_errno(errno, "Failed to write SRK public key file '%s'.", tpm2b_public_path);
|
||||
|
||||
if (fchmod(fileno(f), 0444) < 0)
|
||||
return log_error_errno(errno, "Failed to adjust access mode of SRK public key file '%s' to 0444: %m", tpm2b_public_path);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to sync SRK key to disk: %m");
|
||||
|
||||
r = flink_tmpfile(f, t, tpm2b_public_path, LINK_TMPFILE_SYNC|LINK_TMPFILE_REPLACE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to move SRK public key file to '%s': %m", tpm2b_public_path);
|
||||
|
||||
log_info("SRK public key saved to '%s' in TPM2B_PUBLIC format.", tpm2b_public_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue