Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

The value of TPM2_TRANSIENT_LAST is incorrect (off-by-one) #2864

Open
polarina opened this issue Jul 15, 2024 · 1 comment
Open

The value of TPM2_TRANSIENT_LAST is incorrect (off-by-one) #2864

polarina opened this issue Jul 15, 2024 · 1 comment

Comments

@polarina
Copy link

The value of TPM2_TRANSIENT_LAST is defined as 0x80fffffe in tss2/tss2_tpm2_types.h. The defined value should be 0x80ffffff.

The Linux kernel's TPM2 resource manager assigns transient handles counting from 0x80ffffff downwards: https://github.com/torvalds/linux/blob/v6.10/drivers/char/tpm/tpm2-space.c#L374

Here is a program I wrote that asserts whether the TPM2 handle of a transient key (as created by Esys_CreatePrimary) falls within the range of a transient handle.

The program crashes with an assertion failure:

$ gcc esys-transient.c -o esys-transient -ltss2-esys 
$ sudo ./esys-transient
esys-transient: esys-transient.c:64: main: Assertion `esys_is_transient(ctx, primarykey_handle)' failed.
Aborted
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <tss2/tss2_esys.h>

const TPM2B_PUBLIC tpm2_template_null = {
	.publicArea = {
		.type = TPM2_ALG_ECC,
		.nameAlg = TPM2_ALG_SHA256,
		.objectAttributes =
			TPMA_OBJECT_FIXEDTPM |
			TPMA_OBJECT_FIXEDPARENT |
			TPMA_OBJECT_SENSITIVEDATAORIGIN |
			TPMA_OBJECT_USERWITHAUTH |
			TPMA_OBJECT_NODA |
			TPMA_OBJECT_RESTRICTED |
			TPMA_OBJECT_DECRYPT,
		.parameters.eccDetail = {
			.symmetric = {
				.algorithm = TPM2_ALG_AES,
				.keyBits.aes = 128,
				.mode.aes = TPM2_ALG_CFB,
			},
			.scheme.scheme = TPM2_ALG_NULL,
			.curveID = TPM2_ECC_NIST_P256,
			.kdf.scheme = TPM2_ALG_NULL,
		},
	},
};

static bool esys_is_transient(ESYS_CONTEXT *ctx, ESYS_TR handle) {
	TPM2_HANDLE tpm2handle;
	TSS2_RC rc = Esys_TR_GetTpmHandle(ctx, handle, &tpm2handle);
	assert(!rc);

	return tpm2handle >= TPM2_TRANSIENT_FIRST && tpm2handle <= TPM2_TRANSIENT_LAST;
}

int main(void) {
	TSS2_RC rc;
	ESYS_CONTEXT *ctx = NULL;

	ESYS_TR primarykey_handle;
	TPM2B_PUBLIC *primarykey_public = NULL;

	rc = Esys_Initialize(&ctx, NULL, NULL);
	if (rc) goto error;

	rc = Esys_CreatePrimary(ctx,
		/* primaryHandle */  ESYS_TR_RH_NULL,
		/* shandleX */       ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
		/* inSensitive */    &(const TPM2B_SENSITIVE_CREATE) { 0 },
		/* inPublic */       &tpm2_template_null,
		/* outsideInfo */    NULL,
		/* creationPCR */    &(const TPML_PCR_SELECTION) { 0 },
		/* objectHandle */   &primarykey_handle,
		/* outPublic */      &primarykey_public,
		/* creationData */   NULL,
		/* creationHash */   NULL,
		/* creationTicket */ NULL);
	if (rc) goto error;

	assert(esys_is_transient(ctx, primarykey_handle));

	rc = Esys_FlushContext(ctx, primarykey_handle);
	if (rc) goto error;

error:
	printf("rc = %d\n", rc);

	free(primarykey_public);
	if (ctx) Esys_Finalize(&ctx);

	return !!rc;
}
@joholl
Copy link
Collaborator

joholl commented Jul 24, 2024

TPM reference code (not very helpful here):

TRANSIENT_LAST = TRANSIENT_FIRST + MAX_LOADED_OBJECTS - 1
               = 0x80000000 + 3 - 1

Spec:

A similar approach is used for transient objects with the first assigned handle at the bottom of the range
defined by TPM_HT_TRANSIENT and the top of the range determined by the implementation-dependent
value of MAX_LOADED_OBJECTS.

I guess we need to look for the next handle range which starts at TPM_HT_PERSISTENT = 0x81000000, so I think you are right.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants