Skip to content

Commit 63477a7

Browse files
ddstreetbluca
authored andcommitted
tpm2: instead of adjusting authValue trailing 0(s), trim them as required by tpm spec
To keep compatibility with any existing object authValues with trailing 0's, change tpm2_get_pin_auth() to trim trailing 0's, which is what the TPM implementation will do. This should retain compatibility with any existing authValues that contain trailing 0's. Note that any existing authValues with trailing 0's are unlikely to have worked in the way that systemd uses them in object sealing, which is as a bind key for the encryption (and policy) session. However, it is better to be compatible with the TPM spec (and implementations) even if previously created objects that are affected may not have worked. Fixes: #28414
1 parent 73d6f20 commit 63477a7

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

src/shared/tpm2-util.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,8 +2248,36 @@ int tpm2_digest_many_digests(
22482248
* the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
22492249
* Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
22502250
* authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
2251-
* digest that randomly happens to end in 0 must have the final 0 changed, or the TPM will remove it before
2252-
* using the value in its HMAC calculations, resulting in failed HMAC checks. */
2251+
* digest that randomly happens to end in 0 must have the final 0(s) trimmed.
2252+
*
2253+
* This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
2254+
* tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
2255+
* created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
2256+
* requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
2257+
*
2258+
* TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
2259+
* tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
2260+
* open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
2261+
*
2262+
* Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
2263+
* ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
2264+
* work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
2265+
* which we will trim the 0(s) from before sending to the TPM.
2266+
*/
2267+
static void tpm2_trim_auth_value(TPM2B_AUTH *auth) {
2268+
bool trimmed = false;
2269+
2270+
assert(auth);
2271+
2272+
while (auth->size > 0 && auth->buffer[auth->size - 1] == 0) {
2273+
trimmed = true;
2274+
auth->size--;
2275+
}
2276+
2277+
if (trimmed)
2278+
log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
2279+
}
2280+
22532281
static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
22542282
TPM2B_AUTH auth = {};
22552283
int r;
@@ -2261,11 +2289,7 @@ static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *re
22612289
if (r < 0)
22622290
return r;
22632291

2264-
assert(auth.size > 0);
2265-
if (auth.buffer[auth.size - 1] == 0) {
2266-
log_debug("authValue digest ends in 0 which the TPM will remove and cause HMAC authorization failures, adjusting.");
2267-
auth.buffer[auth.size - 1] = 0xff;
2268-
}
2292+
tpm2_trim_auth_value(&auth);
22692293

22702294
*ret_auth = TAKE_STRUCT(auth);
22712295

0 commit comments

Comments
 (0)