From 1242b9ab2bd306df0df51ca9ee7801f572ce1e28 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Tue, 16 Jan 2024 10:02:47 -0500 Subject: [PATCH 1/4] 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 --- src/shared/tpm2-util.c | 12 ++++++++++-- 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"); } From 910caa2443c8558029eb048132d86c40bd11fdd1 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Tue, 16 Jan 2024 12:26:45 -0500 Subject: [PATCH 2/4] test: verify PEM->TPM2B_PUBLIC conversion for RSA key with non-default exponent The tpm2 test currently verifies PEM->TPM2B_PUBLIC conversion for an RSA key with the default exponent (0x10001); this adds verification for an RSA key with a non-default exponent. --- src/test/test-tpm2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c index c318ef33b3..7ff7e51dbf 100644 --- a/src/test/test-tpm2.c +++ b/src/test/test-tpm2.c @@ -849,6 +849,20 @@ TEST(tpm2b_public_from_openssl_pkey) { assert_se(p->parameters.rsaDetail.exponent == 0x10001); check_tpm2b_public_fingerprint(&public, "d9186d13a7fd5b3644cee05448f49ad3574e82a2942ff93cf89598d36cca78a9"); + + /* RSA key with non-default (i.e. not 0x10001) exponent */ + DEFINE_HEX_PTR(key_rsa2, "2d2d2d2d2d424547494e2050524956415445204b45592d2d2d2d2d0a4d494945765149424144414e42676b71686b6947397730424151454641415343424b63776767536a41674541416f49424151444a57573542387135564370694e0a6d6f4b4e374f2f6f306d6864347579696e2b75394b35397a5444754a4d773678574142533174424e45394e43746533326c354c4d4b6c454f42774c4636534e4d0a414e61764c51715a6a475050726a43574f6e5158316a7a5346794f5351727467417a66524e3873556436583775363047796e436f45584f6637786c39685778490a497232784f6d6a5756727564495a41323142616a6f4d6e7156466e654f43615a6335704d564d426f54516b4c366b56634778554f717959585a337a722f5531430a6f6d356c424e465a6446794a4f6b31666d386a4c2f752b53566d4f46534a4758473831673433536c783239496e766f32306963505051632b6a426e796c6b51340a7a386b51356a46724d736d4e306a6f4f546c484a6a6e485a6e496a732b315750525a4b73464534794b6a3641743555544d4c6a685864337a566e774e447855330a63754a744454656c41674d424141554367674541465770724b555838387a543366304a79464e524b77324d496b4d6d2b55506a443348546b6c6e47736f4e48640a4e38555164333171427843336869507855794d78756d5467564d6452412b34667a5965584d414176667257345655365276444963764c566e50796967536e354b0a724e6f58586e6c42364b7a4b744e6848527a4f4769412f71352b324d4a324137536d66562f4473555856363437544d65386d70464d522b3175374d38617666620a3262494a446362764442316268667844494d62466a2f69726a49376778727353387849555274636e704755594d517364325a664a2f714b52676b3635427a50300a6271736c70477a38574539437255464d58666149726f767a5a2b38584331592b574f68307745386e52346769714d4b47535a5a454a45495155446b39396174750a59613870564d62474131325a686e4732384773313756417337346238685871643152666a44454c7834514b4267514470357338326f59774a674e65626a6f78740a4341574b4d515a6b354d4d46444c4569784c6d616c48766c7332576b665573342f4d6a546b5739762f6876424e634a6d42353149617a5a365078544751484d2b0a34376a6258315156586170336f7a37664632415a733358566d3835464e4e7154756a4a5a684b6b42774143742b696c412f5a503562325a46366c6377626641610a526b6f79467131666e5933582b5563734a6e79384f3071336c774b42675144635830354b4c734c585673686839344e384531797952735030626a6a50687566510a706c6b334564696e4d4a464e52624b4648765563776a763276644f3276465567746667636c64744f546b6236674554413754624e6d334553384f7a59582f58490a576d4d774e4e4e782b753166775474774d4c66332f597a3851515573394f664c504f376d4f5a524b2f367a47717035685549567475357065453747536e6c53700a323869304343365349774b42674837355269492b2b716148684f656e3169394754587070683351432b5630502b5a364c436a6762676458447674795a676d58740a4a6e6b7a64366c4c65714834514b64573334336942784973676932794f74572f506a424a6946744c71454259437a71764d453069627332456156353967444a770a4f6f4a3675386237564c584c34596754776748426c4a4d5141484f56665530684a555146415a682f733348393539454e3837514341463833416f4741536c61660a4f3043414c70353476316b41575844552b4765766774394578414c68302b574b367a4a6f5239576d534838527a7a6d326469526a2f7268756579512f547131360a4556706a57516b424775715248505131304f33557a306a4571754f412f424d3579426c5a756c6f514a42582b76453578392b7073354e55444d757563504734660a505954484a4331754356744f5a374a676c334c7478416e326e504a6a4f65466f3356665435743843675945417a6c4170686c37522f6d6e4677757939464872490a714e456d6571654d556d6f584d4c59487444435964534d5246684d37394772737032574c5145775270775674416a5a6c53424d454c47716c542b77324d636a350a412b5453394c79445158446f7633444e462b6b705934664a654d335339757077415973344e645250423578526d4e575a4f5067307047476a695553767035634b0a46564c6c72464e59437555736c5950794331766f4a42513d0a2d2d2d2d2d454e442050524956415445204b45592d2d2d2d2d0a"); + get_tpm2b_public_from_pem(key_rsa2, key_rsa2_len, &public); + + DEFINE_HEX_PTR(expected_n2, "00c9596e41f2ae550a988d9a828decefe8d2685de2eca29febbd2b9f734c3b89330eb1580052d6d04d13d342b5edf69792cc2a510e0702c5e9234c00d6af2d0a998c63cfae30963a7417d63cd217239242bb600337d137cb1477a5fbbbad06ca70a811739fef197d856c4822bdb13a68d656bb9d219036d416a3a0c9ea5459de382699739a4c54c0684d090bea455c1b150eab2617677cebfd4d42a26e6504d159745c893a4d5f9bc8cbfeef925663854891971bcd60e374a5c76f489efa36d2270f3d073e8c19f2964438cfc910e6316b32c98dd23a0e4e51c98e71d99c88ecfb558f4592ac144e322a3e80b7951330b8e15dddf3567c0d0f153772e26d0d37a5"); + assert_se(p->unique.rsa.size == expected_n2_len); + assert_se(memcmp(p->unique.rsa.buffer, expected_n2, expected_n2_len) == 0); + + assert_se(p->parameters.rsaDetail.keyBits == expected_n2_len * 8); + + assert_se(p->parameters.rsaDetail.exponent == 0x10005); + + check_tpm2b_public_fingerprint(&public, "e037697b827a730d107fda6117c0affcff3e8648d15a62e52b251649b8f67e47"); } #endif From e2e8d8f2a2a710a7bfec8200022066717c739c0e Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Tue, 16 Jan 2024 13:49:45 -0500 Subject: [PATCH 3/4] test: check TPM2B_PUBLIC "name" during PEM->TPM2B_PUBLIC conversion tests Check the calculated TPM2B_PUBLIC key "name" to verify our PEM->TPM2B_PUBLIC function remains consistent with previous code. This is important as the TPM2B_PUBLIC "name" is used in the Authorize policy and so any change to a key "name" would break unsealing for previously-sealed objects (see bug #30546). Note that the tpm2_tpm2b_public_from_openssl_pkey() function results in a TPM2B_PUBLIC with the same "name" as using the tpm2-tools program tpm2_loadexternal, at least as of tpm2-tools version 5.6.18, with the test keys from TEST(tpm2b_public_from_openssl_pkey) in src/test/test-tpm2. --- src/test/test-tpm2.c | 77 +++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c index 7ff7e51dbf..254c4c5e8b 100644 --- a/src/test/test-tpm2.c +++ b/src/test/test-tpm2.c @@ -819,50 +819,75 @@ static void check_tpm2b_public_fingerprint(const TPM2B_PUBLIC *public, const cha assert_se(memcmp_nn(fp, fp_size, expected, expected_len) == 0); } -TEST(tpm2b_public_from_openssl_pkey) { - TPM2B_PUBLIC public; +static void check_tpm2b_public_name(const TPM2B_PUBLIC *public, const char *hexname) { + DEFINE_HEX_PTR(expected, hexname); + TPM2B_NAME name = {}; + + assert_se(tpm2_calculate_pubkey_name(&public->publicArea, &name) >= 0); + assert_se(memcmp_nn(name.name, name.size, expected, expected_len) == 0); +} + +static void check_tpm2b_public_from_ecc_pem(const char *pem, const char *hexx, const char *hexy, const char *hexfp, const char *hexname) { + TPM2B_PUBLIC public = {}; TPMT_PUBLIC *p = &public.publicArea; - DEFINE_HEX_PTR(key_ecc, "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145726a6e4575424c73496c3972687068777976584e50686a346a426e500a44586e794a304b395579724e6764365335413532542b6f5376746b436a365a726c34685847337741515558706f426c532b7448717452714c35513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a"); - get_tpm2b_public_from_pem(key_ecc, key_ecc_len, &public); + DEFINE_HEX_PTR(key, pem); + get_tpm2b_public_from_pem(key, key_len, &public); assert_se(p->type == TPM2_ALG_ECC); assert_se(p->parameters.eccDetail.curveID == TPM2_ECC_NIST_P256); - DEFINE_HEX_PTR(expected_x, "ae39c4b812ec225f6b869870caf5cd3e18f88c19cf0d79f22742bd532acd81de"); + DEFINE_HEX_PTR(expected_x, hexx); assert_se(memcmp_nn(p->unique.ecc.x.buffer, p->unique.ecc.x.size, expected_x, expected_x_len) == 0); - DEFINE_HEX_PTR(expected_y, "92e40e764fea12bed9028fa66b9788571b7c004145e9a01952fad1eab51a8be5"); + DEFINE_HEX_PTR(expected_y, hexy); assert_se(memcmp_nn(p->unique.ecc.y.buffer, p->unique.ecc.y.size, expected_y, expected_y_len) == 0); - check_tpm2b_public_fingerprint(&public, "cd3373293b62a52b48c12100e80ea9bfd806266ce76893a5ec31cb128052d97c"); + check_tpm2b_public_fingerprint(&public, hexfp); + check_tpm2b_public_name(&public, hexname); +} - DEFINE_HEX_PTR(key_rsa, "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541795639434950652f505852337a436f63787045300a6a575262546c3568585844436b472f584b79374b6d2f4439584942334b734f5a31436a5937375571372f674359363170697838697552756a73413464503165380a593445336c68556d374a332b6473766b626f4b64553243626d52494c2f6675627771694c4d587a41673342575278747234547545443533527a373634554650640a307a70304b68775231496230444c67772f344e67566f314146763378784b4d6478774d45683567676b73733038326332706c354a504e32587677426f744e6b4d0a5471526c745a4a35355244436170696e7153334577376675646c4e735851357746766c7432377a7637344b585165616d704c59433037584f6761304c676c536b0a79754774586b6a50542f735542544a705374615769674d5a6f714b7479563463515a58436b4a52684459614c47587673504233687a766d5671636e6b47654e540a65774944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a"); - get_tpm2b_public_from_pem(key_rsa, key_rsa_len, &public); +static void check_tpm2b_public_from_rsa_pem(const char *pem, const char *hexn, uint32_t exponent, const char *hexfp, const char *hexname) { + TPM2B_PUBLIC public = {}; + TPMT_PUBLIC *p = &public.publicArea; - DEFINE_HEX_PTR(expected_n, "c95f4220f7bf3d7477cc2a1cc691348d645b4e5e615d70c2906fd72b2eca9bf0fd5c80772ac399d428d8efb52aeff80263ad698b1f22b91ba3b00e1d3f57bc638137961526ec9dfe76cbe46e829d53609b99120bfdfb9bc2a88b317cc0837056471b6be13b840f9dd1cfbeb85053ddd33a742a1c11d486f40cb830ff8360568d4016fdf1c4a31dc7030487982092cb34f36736a65e493cdd97bf0068b4d90c4ea465b59279e510c26a98a7a92dc4c3b7ee76536c5d0e7016f96ddbbcefef829741e6a6a4b602d3b5ce81ad0b8254a4cae1ad5e48cf4ffb140532694ad6968a0319a2a2adc95e1c4195c29094610d868b197bec3c1de1cef995a9c9e419e3537b"); - assert_se(p->unique.rsa.size == expected_n_len); - assert_se(memcmp(p->unique.rsa.buffer, expected_n, expected_n_len) == 0); + DEFINE_HEX_PTR(key, pem); + get_tpm2b_public_from_pem(key, key_len, &public); + + assert_se(p->type == TPM2_ALG_RSA); + + DEFINE_HEX_PTR(expected_n, hexn); + assert_se(memcmp_nn(p->unique.rsa.buffer, p->unique.rsa.size, expected_n, expected_n_len) == 0); assert_se(p->parameters.rsaDetail.keyBits == expected_n_len * 8); - assert_se(p->parameters.rsaDetail.exponent == 0x10001); + assert_se(p->parameters.rsaDetail.exponent == exponent); - check_tpm2b_public_fingerprint(&public, "d9186d13a7fd5b3644cee05448f49ad3574e82a2942ff93cf89598d36cca78a9"); + check_tpm2b_public_fingerprint(&public, hexfp); + check_tpm2b_public_name(&public, hexname); +} + +TEST(tpm2b_public_from_openssl_pkey) { + /* standard ECC key */ + check_tpm2b_public_from_ecc_pem("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145726a6e4575424c73496c3972687068777976584e50686a346a426e500a44586e794a304b395579724e6764365335413532542b6f5376746b436a365a726c34685847337741515558706f426c532b7448717452714c35513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a", + "ae39c4b812ec225f6b869870caf5cd3e18f88c19cf0d79f22742bd532acd81de", + "92e40e764fea12bed9028fa66b9788571b7c004145e9a01952fad1eab51a8be5", + "cd3373293b62a52b48c12100e80ea9bfd806266ce76893a5ec31cb128052d97c", + "000b5c127e4dbaf8fb7bac641e8db25a84a48db876ca7ee3bd317ae1a4554ff72f17"); + + /* standard RSA key */ + check_tpm2b_public_from_rsa_pem("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541795639434950652f505852337a436f63787045300a6a575262546c3568585844436b472f584b79374b6d2f4439584942334b734f5a31436a5937375571372f674359363170697838697552756a73413464503165380a593445336c68556d374a332b6473766b626f4b64553243626d52494c2f6675627771694c4d587a41673342575278747234547545443533527a373634554650640a307a70304b68775231496230444c67772f344e67566f314146763378784b4d6478774d45683567676b73733038326332706c354a504e32587677426f744e6b4d0a5471526c745a4a35355244436170696e7153334577376675646c4e735851357746766c7432377a7637344b585165616d704c59433037584f6761304c676c536b0a79754774586b6a50542f735542544a705374615769674d5a6f714b7479563463515a58436b4a52684459614c47587673504233687a766d5671636e6b47654e540a65774944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a", + "c95f4220f7bf3d7477cc2a1cc691348d645b4e5e615d70c2906fd72b2eca9bf0fd5c80772ac399d428d8efb52aeff80263ad698b1f22b91ba3b00e1d3f57bc638137961526ec9dfe76cbe46e829d53609b99120bfdfb9bc2a88b317cc0837056471b6be13b840f9dd1cfbeb85053ddd33a742a1c11d486f40cb830ff8360568d4016fdf1c4a31dc7030487982092cb34f36736a65e493cdd97bf0068b4d90c4ea465b59279e510c26a98a7a92dc4c3b7ee76536c5d0e7016f96ddbbcefef829741e6a6a4b602d3b5ce81ad0b8254a4cae1ad5e48cf4ffb140532694ad6968a0319a2a2adc95e1c4195c29094610d868b197bec3c1de1cef995a9c9e419e3537b", + 0x10001, + "d9186d13a7fd5b3644cee05448f49ad3574e82a2942ff93cf89598d36cca78a9", + "000be1bd75c7976e7a30e9e82223b81a9eff0d42c30618e588db592ed5da94455e81"); /* RSA key with non-default (i.e. not 0x10001) exponent */ - DEFINE_HEX_PTR(key_rsa2, "2d2d2d2d2d424547494e2050524956415445204b45592d2d2d2d2d0a4d494945765149424144414e42676b71686b6947397730424151454641415343424b63776767536a41674541416f49424151444a57573542387135564370694e0a6d6f4b4e374f2f6f306d6864347579696e2b75394b35397a5444754a4d773678574142533174424e45394e43746533326c354c4d4b6c454f42774c4636534e4d0a414e61764c51715a6a475050726a43574f6e5158316a7a5346794f5351727467417a66524e3873556436583775363047796e436f45584f6637786c39685778490a497232784f6d6a5756727564495a41323142616a6f4d6e7156466e654f43615a6335704d564d426f54516b4c366b56634778554f717959585a337a722f5531430a6f6d356c424e465a6446794a4f6b31666d386a4c2f752b53566d4f46534a4758473831673433536c783239496e766f32306963505051632b6a426e796c6b51340a7a386b51356a46724d736d4e306a6f4f546c484a6a6e485a6e496a732b315750525a4b73464534794b6a3641743555544d4c6a685864337a566e774e447855330a63754a744454656c41674d424141554367674541465770724b555838387a543366304a79464e524b77324d496b4d6d2b55506a443348546b6c6e47736f4e48640a4e38555164333171427843336869507855794d78756d5467564d6452412b34667a5965584d414176667257345655365276444963764c566e50796967536e354b0a724e6f58586e6c42364b7a4b744e6848527a4f4769412f71352b324d4a324137536d66562f4473555856363437544d65386d70464d522b3175374d38617666620a3262494a446362764442316268667844494d62466a2f69726a49376778727353387849555274636e704755594d517364325a664a2f714b52676b3635427a50300a6271736c70477a38574539437255464d58666149726f767a5a2b38584331592b574f68307745386e52346769714d4b47535a5a454a45495155446b39396174750a59613870564d62474131325a686e4732384773313756417337346238685871643152666a44454c7834514b4267514470357338326f59774a674e65626a6f78740a4341574b4d515a6b354d4d46444c4569784c6d616c48766c7332576b665573342f4d6a546b5739762f6876424e634a6d42353149617a5a365078544751484d2b0a34376a6258315156586170336f7a37664632415a733358566d3835464e4e7154756a4a5a684b6b42774143742b696c412f5a503562325a46366c6377626641610a526b6f79467131666e5933582b5563734a6e79384f3071336c774b42675144635830354b4c734c585673686839344e384531797952735030626a6a50687566510a706c6b334564696e4d4a464e52624b4648765563776a763276644f3276465567746667636c64744f546b6236674554413754624e6d334553384f7a59582f58490a576d4d774e4e4e782b753166775474774d4c66332f597a3851515573394f664c504f376d4f5a524b2f367a47717035685549567475357065453747536e6c53700a323869304343365349774b42674837355269492b2b716148684f656e3169394754587070683351432b5630502b5a364c436a6762676458447674795a676d58740a4a6e6b7a64366c4c65714834514b64573334336942784973676932794f74572f506a424a6946744c71454259437a71764d453069627332456156353967444a770a4f6f4a3675386237564c584c34596754776748426c4a4d5141484f56665530684a555146415a682f733348393539454e3837514341463833416f4741536c61660a4f3043414c70353476316b41575844552b4765766774394578414c68302b574b367a4a6f5239576d534838527a7a6d326469526a2f7268756579512f547131360a4556706a57516b424775715248505131304f33557a306a4571754f412f424d3579426c5a756c6f514a42582b76453578392b7073354e55444d757563504734660a505954484a4331754356744f5a374a676c334c7478416e326e504a6a4f65466f3356665435743843675945417a6c4170686c37522f6d6e4677757939464872490a714e456d6571654d556d6f584d4c59487444435964534d5246684d37394772737032574c5145775270775674416a5a6c53424d454c47716c542b77324d636a350a412b5453394c79445158446f7633444e462b6b705934664a654d335339757077415973344e645250423578526d4e575a4f5067307047476a695553767035634b0a46564c6c72464e59437555736c5950794331766f4a42513d0a2d2d2d2d2d454e442050524956415445204b45592d2d2d2d2d0a"); - get_tpm2b_public_from_pem(key_rsa2, key_rsa2_len, &public); - - DEFINE_HEX_PTR(expected_n2, "00c9596e41f2ae550a988d9a828decefe8d2685de2eca29febbd2b9f734c3b89330eb1580052d6d04d13d342b5edf69792cc2a510e0702c5e9234c00d6af2d0a998c63cfae30963a7417d63cd217239242bb600337d137cb1477a5fbbbad06ca70a811739fef197d856c4822bdb13a68d656bb9d219036d416a3a0c9ea5459de382699739a4c54c0684d090bea455c1b150eab2617677cebfd4d42a26e6504d159745c893a4d5f9bc8cbfeef925663854891971bcd60e374a5c76f489efa36d2270f3d073e8c19f2964438cfc910e6316b32c98dd23a0e4e51c98e71d99c88ecfb558f4592ac144e322a3e80b7951330b8e15dddf3567c0d0f153772e26d0d37a5"); - assert_se(p->unique.rsa.size == expected_n2_len); - assert_se(memcmp(p->unique.rsa.buffer, expected_n2, expected_n2_len) == 0); - - assert_se(p->parameters.rsaDetail.keyBits == expected_n2_len * 8); - - assert_se(p->parameters.rsaDetail.exponent == 0x10005); - - check_tpm2b_public_fingerprint(&public, "e037697b827a730d107fda6117c0affcff3e8648d15a62e52b251649b8f67e47"); + check_tpm2b_public_from_rsa_pem("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b434151454179566c7551664b75565171596a5a71436a657a760a364e4a6f58654c736f702f72765375666330773769544d4f73566741557462515452505451725874397065537a4370524467634378656b6a544144577279304b0a6d59786a7a3634776c6a7030463959383068636a6b6b4b3759414d333054664c4648656c2b377574427370777142467a6e2b385a6659567353434b397354706f0a316c61376e5347514e7451576f36444a366c525a336a676d6d584f61544654416145304a432b7046584273564471736d46326438362f314e51714a755a5154520a575852636954704e58357649792f37766b6c5a6a685569526c78764e594f4e3070636476534a37364e74496e447a3048506f775a38705a454f4d2f4a454f59780a617a4c4a6a644936446b355279593578325a7949375074566a3057537242524f4d696f2b674c6556457a43343456336438315a38445138564e334c69625130330a70514944415141460a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a", + "c9596e41f2ae550a988d9a828decefe8d2685de2eca29febbd2b9f734c3b89330eb1580052d6d04d13d342b5edf69792cc2a510e0702c5e9234c00d6af2d0a998c63cfae30963a7417d63cd217239242bb600337d137cb1477a5fbbbad06ca70a811739fef197d856c4822bdb13a68d656bb9d219036d416a3a0c9ea5459de382699739a4c54c0684d090bea455c1b150eab2617677cebfd4d42a26e6504d159745c893a4d5f9bc8cbfeef925663854891971bcd60e374a5c76f489efa36d2270f3d073e8c19f2964438cfc910e6316b32c98dd23a0e4e51c98e71d99c88ecfb558f4592ac144e322a3e80b7951330b8e15dddf3567c0d0f153772e26d0d37a5", + 0x10005, + "c8ca80a687d5972e1d961aaa2cfde2ff2e7a20d85e3ea0382804e70e013d65af", + "000beb8974d36d8cf58fdc87460dda00319e10c94c1b9f222ac9ce29d1c4776246cc"); } #endif From fda3e844657b61b69f8d0badffb6239840ef9e97 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Tue, 16 Jan 2024 10:39:06 -0500 Subject: [PATCH 4/4] tpm2: If unsealing results in policy hash mismatch when using RSA pubkey, possibly retry The commit e3acb4d24c68291376b11bea5787112978e2775f changed how we format a TPM2B_PUBLIC object from an openssl PEM RSA key if it used the TPM-defined "default" RSA exponent, to instead set the TPM2B_PUBLIC RSA exponent to the special-case value of 0. This broke backwards compatibility with previously-sealed data. The previous commit fixed our code to no longer use the "special case" exponent value of 0, while this commit adds a fallback check for any sealed data that used the exponent value of 0. Now unsealing should work for sealed data that used either method (either 0 or the actual value). --- src/shared/tpm2-util.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 470ee68322..770a1e2b14 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -5557,11 +5557,25 @@ int tpm2_unseal(Tpm2Context *c, /* If we know the policy hash to expect, and it doesn't match, we can shortcut things here, and not * wait until the TPM2 tells us to go away. */ - if (iovec_is_set(known_policy_hash) && - memcmp_nn(policy_digest->buffer, policy_digest->size, known_policy_hash->iov_base, known_policy_hash->iov_len) != 0) + if (iovec_is_set(known_policy_hash) && memcmp_nn(policy_digest->buffer, + policy_digest->size, + known_policy_hash->iov_base, + known_policy_hash->iov_len) != 0) { +#if HAVE_OPENSSL + if (iovec_is_set(pubkey) && + pubkey_tpm2b.publicArea.type == TPM2_ALG_RSA && + pubkey_tpm2b.publicArea.parameters.rsaDetail.exponent == TPM2_RSA_DEFAULT_EXPONENT) { + /* Due to bug #30546, if using RSA pubkey with the default exponent, we may + * need to set the exponent to the TPM special-case value of 0 and retry. */ + log_debug("Policy hash mismatch, retrying with RSA pubkey exponent set to 0."); + pubkey_tpm2b.publicArea.parameters.rsaDetail.exponent = 0; + continue; + } else +#endif return log_debug_errno(SYNTHETIC_ERRNO(EPERM), "Current policy digest does not match stored policy digest, cancelling " "TPM2 authentication attempt."); + } log_debug("Unsealing HMAC key.");