summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Streetman <ddstreet@ieee.org>2024-01-16 16:02:47 +0100
committerDan Streetman <ddstreet@ieee.org>2024-01-16 20:09:51 +0100
commit1242b9ab2bd306df0df51ca9ee7801f572ce1e28 (patch)
tree30dae11ae4c8831829840523ca294363166fdbe8
parentMerge pull request #30944 from CodethinkLabs/vmspawn/fix_fedora_issues (diff)
downloadsystemd-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.c12
-rw-r--r--src/test/test-tpm2.c2
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");
}