Allows users to enroll their own public key stored in a specific TPM2 NV Index, requiring the absence of the Platform Create and Platform Write attributes on the NV Index, to be loaded on the IMA keyring. Provides a method for users to load keys without the need to recompile the kernel or change the kernel binary, which would require a resign of the kernel image. Signed-off-by: Patrick Uiterwijk <patrick@xxxxxxxxxxxxxx> --- security/integrity/ima/Kconfig | 22 +++++++++++++ security/integrity/ima/ima_init.c | 53 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 12e9250c1bec..28424b930c81 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -291,6 +291,28 @@ config IMA_BLACKLIST_KEYRING the search is successful the requested operation is rejected and an error is returned to the caller. +config IMA_LOAD_CERT_NVINDEX + bool "Load certificate from TPM nvindex into '.ima' trusted keyring" + depends on IMA_TRUSTED_KEYRING && TCG_TPM + default n + help + File signature verification is based on the public keys + loaded on the .ima trusted keyring. These public keys are + X509 certificates signed by a trusted key on the + .system keyring. This option enables X509 certificate + loading by the kernel onto the '.ima' trusted keyring + from a TPM nvindex, bypassing the builtin keyring check. + +config IMA_LOAD_CERT_NVINDEX_INDEX + hex "The TPM NV Index to load into the '.ima' trusted keyring" + depends on IMA_LOAD_CERT_NVINDEX + default 0x184b520 + help + Defines the index of the NV Index that gets loaded into the + '.ima' keyring. + The default is the "0x18" prefix for a non-TCG specified NV Index, + suffixed with ASCII for "KR" (keyring) and then 0 + config IMA_LOAD_X509 bool "Load X509 certificate onto the '.ima' trusted keyring" depends on IMA_TRUSTED_KEYRING diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 6e8742916d1d..ea0949e8df12 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -112,6 +112,55 @@ void __init ima_load_x509(void) } #endif +#ifndef CONFIG_IMA_LOAD_CERT_NVINDEX +int __init ima_load_key_nvindex(void) +{ + return 0; +} +#else +int __init ima_load_key_nvindex(void) +{ + void *cert_buffer; + int rc; + key_perm_t perm; + u32 nvindex_attributes = 0; + + rc = tpm_nv_read(tpm_default_chip(), + CONFIG_IMA_LOAD_CERT_NVINDEX_INDEX, + &nvindex_attributes, &cert_buffer); + if (rc < 0) { + if (rc == -ENODEV) /* No TPM2 */ + rc = 0; + if (rc == -ENOENT) /* No certificate in NV Index */ + rc = 0; + goto out; + } + + pr_info("Loading IMA key from TPM NV Index 0x%x", CONFIG_IMA_LOAD_CERT_NVINDEX_INDEX); + + if (nvindex_attributes & TPM2_ATTR_NV_PLATFORMCREATE) { + pr_err("NV Index has the Platform Create attribute"); + rc = -EACCES; + goto out_free; + } + if (nvindex_attributes & TPM2_ATTR_NV_PPWRITE) { + pr_err("NV Index has the Platform Write attribute"); + rc = -EACCES; + goto out_free; + } + + perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ; + rc = integrity_load_cert(INTEGRITY_KEYRING_IMA, "TPM NV Index", + cert_buffer, rc, perm, + KEY_ALLOC_BYPASS_RESTRICTION); + +out_free: + kvfree(cert_buffer); +out: + return rc; +} +#endif + int __init ima_init(void) { int rc; @@ -124,6 +173,10 @@ int __init ima_init(void) if (rc) return rc; + rc = ima_load_key_nvindex(); + if (rc) + pr_info("Failed to load IMA key from TPM NV Index (%d)", rc); + rc = ima_init_crypto(); if (rc) return rc; -- 2.29.2