diff options
author | Dan Streetman <ddstreet@ieee.org> | 2024-01-16 16:02:47 +0100 |
---|---|---|
committer | Dan Streetman <ddstreet@ieee.org> | 2024-01-16 20:09:51 +0100 |
commit | 1242b9ab2bd306df0df51ca9ee7801f572ce1e28 (patch) | |
tree | 30dae11ae4c8831829840523ca294363166fdbe8 | |
parent | Merge pull request #30944 from CodethinkLabs/vmspawn/fix_fedora_issues (diff) | |
download | systemd-1242b9ab2bd306df0df51ca9ee7801f572ce1e28.tar.xz systemd-1242b9ab2bd306df0df51ca9ee7801f572ce1e28.zip |
tpm2: Do not use RSA exponent special-case default value in PEM->TPM2B_PUBLIC conversion
The openssl default value for an RSA key exponent value is 0x10001, and the TPM
specification defines a exponent value of 0 as representing this value. The
systemd code that converted an RSA PEM public key to a TPM2B_PUBLIC object
previously used the exponent value directly, but commit
e3acb4d24c68291376b11bea5787112978e2775f changed the conversion to use the
special case exponent value of 0 for any RSA key with an exponent value of
0x10001.
Because the entire TPM2B_PUBLIC object is used to calculate its "name", this
difference in exponent value (0x10001 vs 0) introduced a change in the key
"name". Since the Authorize policy uses the key "name" directly in its policy
session hash value, this change resulted in new systemd code being unable to
properly unseal any data (e.g. a LUKS volume) that was previously sealed.
This reverts the code to no longer override an RSA exponent value of 0x10001
with the special case value of 0.
Fixes a bug introduced by commit e3acb4d24c68291376b11bea5787112978e2775f.
Fixes: #30546
Diffstat (limited to '')
-rw-r--r-- | src/shared/tpm2-util.c | 12 | ||||
-rw-r--r-- | src/test/test-tpm2.c | 2 |
2 files changed, 11 insertions, 3 deletions
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 22b8a872a4..470ee68322 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -4196,6 +4196,11 @@ int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret } } +/* Be careful before changing anything in this function, as the TPM key "name" is calculated using the entire + * TPMT_PUBLIC (after marshalling), and that "name" is used (for example) to calculate the policy hash for + * the Authorize policy. So we must ensure this conversion of a PEM to TPM2B_PUBLIC does not change the + * "name", because it would break unsealing of previously-sealed objects that used (for example) + * tpm2_calculate_policy_authorize(). See bug #30546. */ int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) { int key_id, r; @@ -4274,8 +4279,11 @@ int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) uint32_t exponent = 0; memcpy(&exponent, e, e_size); exponent = be32toh(exponent) >> (32 - e_size * 8); - if (exponent == TPM2_RSA_DEFAULT_EXPONENT) - exponent = 0; + + /* TPM specification Part 2 ("Structures") section for TPMS_RSA_PARAMS states "An exponent of + * zero indicates that the exponent is the default of 2^16 + 1". However, we have no reason + * to special case it in our PEM->TPM2B_PUBLIC conversion, and doing so could break backwards + * compatibility, so even if it is the "default" value of 0x10001, we do not set it to 0. */ public.parameters.rsaDetail.exponent = exponent; break; diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c index eeaf0b7b88..c318ef33b3 100644 --- a/src/test/test-tpm2.c +++ b/src/test/test-tpm2.c @@ -846,7 +846,7 @@ TEST(tpm2b_public_from_openssl_pkey) { assert_se(p->parameters.rsaDetail.keyBits == expected_n_len * 8); - assert_se(p->parameters.rsaDetail.exponent == 0); + assert_se(p->parameters.rsaDetail.exponent == 0x10001); check_tpm2b_public_fingerprint(&public, "d9186d13a7fd5b3644cee05448f49ad3574e82a2942ff93cf89598d36cca78a9"); } |