Message ID | 20210225203229.363302-4-patrick@puiterwijk.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Load keys from TPM2 NV Index on IMA keyring | expand |
On 2/25/21 3:32 PM, Patrick Uiterwijk wrote: > 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@puiterwijk.org> > --- > 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(), You should do chip = tpm_default_chip() so that later on you can do put_device(&chip->dev). > + 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); kfree? > +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;
On 2/26/21 4:47 PM, Stefan Berger wrote: > On 2/25/21 3:32 PM, Patrick Uiterwijk wrote: >> 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@puiterwijk.org> >> --- >> 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(), > > > You should do chip = tpm_default_chip() so that later on you can do > put_device(&chip->dev). ... or just use ima_tpm_chip if != NULL: https://elixir.bootlin.com/linux/latest/source/security/integrity/ima/ima_init.c#L23 > > >> + 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); > > > kfree? > > >> +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;
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;
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@puiterwijk.org> --- security/integrity/ima/Kconfig | 22 +++++++++++++ security/integrity/ima/ima_init.c | 53 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+)