Merge: Allow to enroll custom IMA keys

MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/2596

Bugzilla: https://bugzilla.redhat.com/2055205

This patch set allows enrolling customer keys for IMA signatures by enabling the .machine keyring for UEFI-based systems. Users will add their customer IMA CA certifciates/keys to the MOK list and the keys will eventually be loaded to the .machine keyring which is linked the the .secondary_trusted_keys keyring.

Signed-off-by: Coiby Xu <coxu@redhat.com>

Approved-by: Jerry Snitselaar <jsnitsel@redhat.com>
Approved-by: Vladis Dronov <vdronov@redhat.com>

Signed-off-by: Jan Stancek <jstancek@redhat.com>
This commit is contained in:
Jan Stancek 2023-07-04 11:15:01 +02:00
commit c3330aab37
22 changed files with 486 additions and 16 deletions

View File

@ -21,6 +21,9 @@ static struct key *builtin_trusted_keys;
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
static struct key *secondary_trusted_keys;
#endif
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
static struct key *machine_trusted_keys;
#endif
#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
static struct key *platform_trusted_keys;
#endif
@ -30,7 +33,11 @@ extern __initconst const unsigned long system_certificate_list_size;
extern __initconst const unsigned long module_cert_size;
/**
* restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
* restrict_link_by_builtin_trusted - Restrict keyring addition by built-in CA
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @restriction_key: A ring of keys that can be used to vouch for the new cert.
*
* Restrict the addition of keys into a keyring based on the key-to-be-added
* being vouched for by a key in the built in system keyring.
@ -44,10 +51,34 @@ int restrict_link_by_builtin_trusted(struct key *dest_keyring,
builtin_trusted_keys);
}
/**
* restrict_link_by_digsig_builtin - Restrict digitalSignature key additions by the built-in keyring
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @restriction_key: A ring of keys that can be used to vouch for the new cert.
*
* Restrict the addition of keys into a keyring based on the key-to-be-added
* being vouched for by a key in the built in system keyring. The new key
* must have the digitalSignature usage field set.
*/
int restrict_link_by_digsig_builtin(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key)
{
return restrict_link_by_digsig(dest_keyring, type, payload,
builtin_trusted_keys);
}
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
/**
* restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
* addition by both builtin and secondary keyrings
* addition by both built-in and secondary keyrings.
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @restrict_key: A ring of keys that can be used to vouch for the new cert.
*
* Restrict the addition of keys into a keyring based on the key-to-be-added
* being vouched for by a key in either the built-in or the secondary system
@ -73,6 +104,36 @@ int restrict_link_by_builtin_and_secondary_trusted(
}
/**
* restrict_link_by_digsig_builtin_and_secondary - Restrict by digitalSignature.
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @restrict_key: A ring of keys that can be used to vouch for the new cert.
*
* Restrict the addition of keys into a keyring based on the key-to-be-added
* being vouched for by a key in either the built-in or the secondary system
* keyrings. The new key must have the digitalSignature usage field set.
*/
int restrict_link_by_digsig_builtin_and_secondary(
struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restrict_key)
{
/* If we have a secondary trusted keyring, then that contains a link
* through to the builtin keyring and the search will follow that link.
*/
if (type == &key_type_keyring &&
dest_keyring == secondary_trusted_keys &&
payload == &builtin_trusted_keys->payload)
/* Allow the builtin keyring to be added to the secondary */
return 0;
return restrict_link_by_digsig(dest_keyring, type, payload,
secondary_trusted_keys);
}
/*
* Allocate a struct key_restriction for the "builtin and secondary trust"
* keyring. Only for use in system_trusted_keyring_init().
*/
@ -85,11 +146,50 @@ static __init struct key_restriction *get_builtin_and_secondary_restriction(void
if (!restriction)
panic("Can't allocate secondary trusted keyring restriction\n");
restriction->check = restrict_link_by_builtin_and_secondary_trusted;
if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING))
restriction->check = restrict_link_by_builtin_secondary_and_machine;
else
restriction->check = restrict_link_by_builtin_and_secondary_trusted;
return restriction;
}
#endif
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
void __init set_machine_trusted_keys(struct key *keyring)
{
machine_trusted_keys = keyring;
if (key_link(secondary_trusted_keys, machine_trusted_keys) < 0)
panic("Can't link (machine) trusted keyrings\n");
}
/**
* restrict_link_by_builtin_secondary_and_machine - Restrict keyring addition.
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @restrict_key: A ring of keys that can be used to vouch for the new cert.
*
* Restrict the addition of keys into a keyring based on the key-to-be-added
* being vouched for by a key in either the built-in, the secondary, or
* the machine keyrings.
*/
int restrict_link_by_builtin_secondary_and_machine(
struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restrict_key)
{
if (machine_trusted_keys && type == &key_type_keyring &&
dest_keyring == secondary_trusted_keys &&
payload == &machine_trusted_keys->payload)
/* Allow the machine keyring to be added to the secondary */
return 0;
return restrict_link_by_builtin_and_secondary_trusted(dest_keyring, type,
payload, restrict_key);
}
#endif
/*
* Create the trusted keyrings

View File

@ -108,6 +108,90 @@ int restrict_link_by_signature(struct key *dest_keyring,
return ret;
}
/**
* restrict_link_by_ca - Restrict additions to a ring of CA keys
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @trust_keyring: Unused.
*
* Check if the new certificate is a CA. If it is a CA, then mark the new
* certificate as being ok to link.
*
* Returns 0 if the new certificate was accepted, -ENOKEY if the
* certificate is not a CA. -ENOPKG if the signature uses unsupported
* crypto, or some other error if there is a matching certificate but
* the signature check cannot be performed.
*/
int restrict_link_by_ca(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring)
{
const struct public_key *pkey;
if (type != &key_type_asymmetric)
return -EOPNOTSUPP;
pkey = payload->data[asym_crypto];
if (!pkey)
return -ENOPKG;
if (!test_bit(KEY_EFLAG_CA, &pkey->key_eflags))
return -ENOKEY;
if (!test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags))
return -ENOKEY;
if (!IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX))
return 0;
if (test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags))
return -ENOKEY;
return 0;
}
/**
* restrict_link_by_digsig - Restrict additions to a ring of digsig keys
* @dest_keyring: Keyring being linked to.
* @type: The type of key being added.
* @payload: The payload of the new key.
* @trust_keyring: A ring of keys that can be used to vouch for the new cert.
*
* Check if the new certificate has digitalSignature usage set. If it is,
* then mark the new certificate as being ok to link. Afterwards verify
* the new certificate against the ones in the trust_keyring.
*
* Returns 0 if the new certificate was accepted, -ENOKEY if the
* certificate is not a digsig. -ENOPKG if the signature uses unsupported
* crypto, or some other error if there is a matching certificate but
* the signature check cannot be performed.
*/
int restrict_link_by_digsig(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring)
{
const struct public_key *pkey;
if (type != &key_type_asymmetric)
return -EOPNOTSUPP;
pkey = payload->data[asym_crypto];
if (!pkey)
return -ENOPKG;
if (!test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags))
return -ENOKEY;
if (test_bit(KEY_EFLAG_CA, &pkey->key_eflags))
return -ENOKEY;
if (test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags))
return -ENOKEY;
return restrict_link_by_signature(dest_keyring, type, payload,
trust_keyring);
}
static bool match_either_id(const struct asymmetric_key_ids *pair,
const struct asymmetric_key_id *single)
{

View File

@ -564,6 +564,34 @@ int x509_process_extension(void *context, size_t hdrlen,
return 0;
}
if (ctx->last_oid == OID_keyUsage) {
/*
* Get hold of the keyUsage bit string
* v[1] is the encoding size
* (Expect either 0x02 or 0x03, making it 1 or 2 bytes)
* v[2] is the number of unused bits in the bit string
* (If >= 3 keyCertSign is missing when v[1] = 0x02)
* v[3] and possibly v[4] contain the bit string
*
* From RFC 5280 4.2.1.3:
* 0x04 is where keyCertSign lands in this bit string
* 0x80 is where digitalSignature lands in this bit string
*/
if (v[0] != ASN1_BTS)
return -EBADMSG;
if (vlen < 4)
return -EBADMSG;
if (v[2] >= 8)
return -EBADMSG;
if (v[3] & 0x80)
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_DIGITALSIG;
if (v[1] == 0x02 && v[2] <= 2 && (v[3] & 0x04))
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN;
else if (vlen > 4 && v[1] == 0x03 && (v[3] & 0x04))
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN;
return 0;
}
if (ctx->last_oid == OID_authorityKeyIdentifier) {
/* Get hold of the CA key fingerprint */
ctx->raw_akid = v;
@ -571,6 +599,28 @@ int x509_process_extension(void *context, size_t hdrlen,
return 0;
}
if (ctx->last_oid == OID_basicConstraints) {
/*
* Get hold of the basicConstraints
* v[1] is the encoding size
* (Expect 0x2 or greater, making it 1 or more bytes)
* v[2] is the encoding type
* (Expect an ASN1_BOOL for the CA)
* v[3] is the contents of the ASN1_BOOL
* (Expect 1 if the CA is TRUE)
* vlen should match the entire extension size
*/
if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ))
return -EBADMSG;
if (vlen < 2)
return -EBADMSG;
if (v[1] != vlen - 2)
return -EBADMSG;
if (vlen >= 4 && v[1] != 0 && v[2] == ASN1_BOOL && v[3] == 1)
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_CA;
return 0;
}
return 0;
}

View File

@ -4923,12 +4923,14 @@ static const struct alg_test_desc alg_test_descs[] = {
}, {
.alg = "ecdsa-nist-p256",
.test = alg_test_akcipher,
.fips_allowed = 1,
.suite = {
.akcipher = __VECS(ecdsa_nist_p256_tv_template)
}
}, {
.alg = "ecdsa-nist-p384",
.test = alg_test_akcipher,
.fips_allowed = 1,
.suite = {
.akcipher = __VECS(ecdsa_nist_p384_tv_template)
}

View File

@ -28,6 +28,10 @@ struct public_key {
bool key_is_private;
const char *id_type;
const char *pkey_algo;
unsigned long key_eflags; /* key extension flags */
#define KEY_EFLAG_CA 0 /* set if the CA basic constraints is set */
#define KEY_EFLAG_DIGITALSIG 1 /* set if the digitalSignature usage is set */
#define KEY_EFLAG_KEYCERTSIGN 2 /* set if the keyCertSign usage is set */
};
extern void public_key_free(struct public_key *key);
@ -71,6 +75,32 @@ extern int restrict_link_by_key_or_keyring_chain(struct key *trust_keyring,
const union key_payload *payload,
struct key *trusted);
#if IS_REACHABLE(CONFIG_ASYMMETRIC_KEY_TYPE)
extern int restrict_link_by_ca(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring);
int restrict_link_by_digsig(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring);
#else
static inline int restrict_link_by_ca(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring)
{
return 0;
}
static inline int restrict_link_by_digsig(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring)
{
return 0;
}
#endif
extern int query_asymmetric_key(const struct kernel_pkey_params *,
struct kernel_pkey_query *);
@ -80,7 +110,16 @@ extern int create_signature(struct kernel_pkey_params *, const void *, void *);
extern int verify_signature(const struct key *,
const struct public_key_signature *);
#if IS_REACHABLE(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE)
int public_key_verify_signature(const struct public_key *pkey,
const struct public_key_signature *sig);
#else
static inline
int public_key_verify_signature(const struct public_key *pkey,
const struct public_key_signature *sig)
{
return -EINVAL;
}
#endif
#endif /* _LINUX_PUBLIC_KEY_H */

View File

@ -16,10 +16,15 @@ extern int restrict_link_by_builtin_trusted(struct key *keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
int restrict_link_by_digsig_builtin(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
extern __init int load_module_cert(struct key *keyring);
#else
#define restrict_link_by_builtin_trusted restrict_link_reject
#define restrict_link_by_digsig_builtin restrict_link_reject
static inline __init int load_module_cert(struct key *keyring)
{
@ -34,8 +39,28 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
extern int restrict_link_by_digsig_builtin_and_secondary(
struct key *keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
#else
#define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
#define restrict_link_by_digsig_builtin_and_secondary restrict_link_by_digsig_builtin
#endif
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
extern int restrict_link_by_builtin_secondary_and_machine(
struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restrict_key);
extern void __init set_machine_trusted_keys(struct key *keyring);
#else
#define restrict_link_by_builtin_secondary_and_machine restrict_link_by_builtin_trusted
static inline void __init set_machine_trusted_keys(struct key *keyring)
{
}
#endif
extern struct pkcs7_message *pkcs7;

View File

@ -0,0 +1 @@
# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING is not set

View File

@ -0,0 +1 @@
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y

View File

@ -0,0 +1 @@
CONFIG_INTEGRITY_CA_MACHINE_KEYRING=y

View File

@ -0,0 +1 @@
CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX=y

View File

@ -0,0 +1 @@
CONFIG_INTEGRITY_MACHINE_KEYRING=y

View File

@ -1 +1 @@
# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
CONFIG_SECONDARY_TRUSTED_KEYRING=y

View File

@ -62,6 +62,40 @@ config INTEGRITY_PLATFORM_KEYRING
provided by the platform for verifying the kexec'ed kerned image
and, possibly, the initramfs signature.
config INTEGRITY_MACHINE_KEYRING
bool "Provide a keyring to which Machine Owner Keys may be added"
depends on SECONDARY_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
depends on SYSTEM_BLACKLIST_KEYRING
depends on LOAD_UEFI_KEYS
help
If set, provide a keyring to which Machine Owner Keys (MOK) may
be added. This keyring shall contain just MOK keys. Unlike keys
in the platform keyring, keys contained in the .machine keyring will
be trusted within the kernel.
config INTEGRITY_CA_MACHINE_KEYRING
bool "Enforce Machine Keyring CA Restrictions"
depends on INTEGRITY_MACHINE_KEYRING
default n
help
The .machine keyring can be configured to enforce CA restriction
on any key added to it. By default no restrictions are in place
and all Machine Owner Keys (MOK) are added to the machine keyring.
If enabled only CA keys are added to the machine keyring, all
other MOK keys load into the platform keyring.
config INTEGRITY_CA_MACHINE_KEYRING_MAX
bool "Only CA keys without DigitialSignature usage set"
depends on INTEGRITY_CA_MACHINE_KEYRING
default n
help
When selected, only load CA keys are loaded into the machine
keyring that contain the CA bit set along with the keyCertSign
Usage field. Keys containing the digitialSignature Usage field
will not be loaded. The remaining MOK keys are loaded into the
.platform keyring.
config LOAD_UEFI_KEYS
depends on INTEGRITY_PLATFORM_KEYRING
depends on EFI

View File

@ -10,6 +10,7 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += platform_certs/platform_keyring.o
integrity-$(CONFIG_INTEGRITY_MACHINE_KEYRING) += platform_certs/machine_keyring.o
integrity-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/efi_parser.o \
platform_certs/load_uefi.o \
platform_certs/keyring_handler.o

View File

@ -30,12 +30,13 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
".ima",
#endif
".platform",
".machine",
};
#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
#define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted
#define restrict_link_to_ima restrict_link_by_digsig_builtin_and_secondary
#else
#define restrict_link_to_ima restrict_link_by_builtin_trusted
#define restrict_link_to_ima restrict_link_by_digsig_builtin
#endif
static struct key *integrity_keyring_from_id(const unsigned int id)
@ -111,6 +112,8 @@ static int __init __integrity_init_keyring(const unsigned int id,
} else {
if (id == INTEGRITY_KEYRING_PLATFORM)
set_platform_trusted_keys(keyring[id]);
if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist())
set_machine_trusted_keys(keyring[id]);
if (id == INTEGRITY_KEYRING_IMA)
load_module_cert(keyring[id]);
}
@ -126,7 +129,9 @@ int __init integrity_init_keyring(const unsigned int id)
perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
| KEY_USR_READ | KEY_USR_SEARCH;
if (id == INTEGRITY_KEYRING_PLATFORM) {
if (id == INTEGRITY_KEYRING_PLATFORM ||
(id == INTEGRITY_KEYRING_MACHINE &&
!IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING))) {
restriction = NULL;
goto out;
}
@ -138,8 +143,18 @@ int __init integrity_init_keyring(const unsigned int id)
if (!restriction)
return -ENOMEM;
restriction->check = restrict_link_to_ima;
perm |= KEY_USR_WRITE;
if (id == INTEGRITY_KEYRING_MACHINE)
restriction->check = restrict_link_by_ca;
else
restriction->check = restrict_link_to_ima;
/*
* MOK keys can only be added through a read-only runtime services
* UEFI variable during boot. No additional keys shall be allowed to
* load into the machine keyring following init from userspace.
*/
if (id != INTEGRITY_KEYRING_MACHINE)
perm |= KEY_USR_WRITE;
out:
return __integrity_init_keyring(id, perm, restriction);

View File

@ -64,7 +64,8 @@ config EVM_LOAD_X509
This option enables X509 certificate loading from the kernel
onto the '.evm' trusted keyring. A public key can be used to
verify EVM integrity starting from the 'init' process.
verify EVM integrity starting from the 'init' process. The
key must have digitalSignature usage set.
config EVM_X509_PATH
string "EVM X509 certificate path"

View File

@ -263,7 +263,7 @@ config IMA_TRUSTED_KEYRING
This option is deprecated in favor of INTEGRITY_TRUSTED_KEYRING
config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
bool "Permit keys validly signed by a built-in or secondary CA cert (EXPERIMENTAL)"
bool "Permit keys validly signed by a built-in or secondary CA cert"
depends on SYSTEM_TRUSTED_KEYRING
depends on SECONDARY_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
@ -272,7 +272,8 @@ config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
help
Keys may be added to the IMA or IMA blacklist keyrings, if the
key is validly signed by a CA cert in the system built-in or
secondary trusted keyrings.
secondary trusted keyrings. The key must also have the
digitalSignature usage set.
Intermediate keys between those the kernel has compiled in and the
IMA keys to be added may be added to the system secondary keyring,

View File

@ -151,7 +151,8 @@ int integrity_kernel_read(struct file *file, loff_t offset,
#define INTEGRITY_KEYRING_EVM 0
#define INTEGRITY_KEYRING_IMA 1
#define INTEGRITY_KEYRING_PLATFORM 2
#define INTEGRITY_KEYRING_MAX 3
#define INTEGRITY_KEYRING_MACHINE 3
#define INTEGRITY_KEYRING_MAX 4
extern struct dentry *integrity_dir;
@ -283,3 +284,17 @@ static inline void __init add_to_platform_keyring(const char *source,
{
}
#endif
#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
void __init add_to_machine_keyring(const char *source, const void *data, size_t len);
bool __init trust_moklist(void);
#else
static inline void __init add_to_machine_keyring(const char *source,
const void *data, size_t len)
{
}
static inline bool __init trust_moklist(void)
{
return false;
}
#endif

View File

@ -9,6 +9,7 @@
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
#include "../integrity.h"
#include "keyring_handler.h"
static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
static efi_guid_t efi_cert_x509_sha256_guid __initdata =
@ -66,7 +67,7 @@ static __init void uefi_revocation_list_x509(const char *source,
/*
* Return the appropriate handler for particular signature list types found in
* the UEFI db and MokListRT tables.
* the UEFI db tables.
*/
__init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
{
@ -75,6 +76,21 @@ __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
return 0;
}
/*
* Return the appropriate handler for particular signature list types found in
* the MokListRT tables.
*/
__init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
{
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) {
if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) && trust_moklist())
return add_to_machine_keyring;
else
return add_to_platform_keyring;
}
return 0;
}
/*
* Return the appropriate handler for particular signature list types found in
* the UEFI dbx and MokListXRT tables.

View File

@ -24,6 +24,11 @@ void blacklist_binary(const char *source, const void *data, size_t len);
*/
efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type);
/*
* Return the handler for particular signature list types found in the mok.
*/
efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type);
/*
* Return the handler for particular signature list types found in the dbx.
*/

View File

@ -96,7 +96,7 @@ static int __init load_moklist_certs(void)
rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)",
mokvar_entry->data,
mokvar_entry->data_size,
get_handler_for_db);
get_handler_for_mok);
/* All done if that worked. */
if (!rc)
return rc;
@ -111,7 +111,7 @@ static int __init load_moklist_certs(void)
mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
if (mok) {
rc = parse_efi_signature_list("UEFI:MokListRT",
mok, moksize, get_handler_for_db);
mok, moksize, get_handler_for_mok);
kfree(mok);
if (rc)
pr_err("Couldn't parse MokListRT signatures: %d\n", rc);

View File

@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Machine keyring routines.
*
* Copyright (c) 2021, Oracle and/or its affiliates.
*/
#include <linux/efi.h>
#include "../integrity.h"
static bool trust_mok;
static __init int machine_keyring_init(void)
{
int rc;
rc = integrity_init_keyring(INTEGRITY_KEYRING_MACHINE);
if (rc)
return rc;
pr_notice("Machine keyring initialized\n");
return 0;
}
device_initcall(machine_keyring_init);
void __init add_to_machine_keyring(const char *source, const void *data, size_t len)
{
key_perm_t perm;
int rc;
perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
rc = integrity_load_cert(INTEGRITY_KEYRING_MACHINE, source, data, len, perm);
/*
* Some MOKList keys may not pass the machine keyring restrictions.
* If the restriction check does not pass and the platform keyring
* is configured, try to add it into that keyring instead.
*/
if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
data, len, perm);
if (rc)
pr_info("Error adding keys to machine keyring %s\n", source);
}
/*
* Try to load the MokListTrustedRT MOK variable to see if we should trust
* the MOK keys within the kernel. It is not an error if this variable
* does not exist. If it does not exist, MOK keys should not be trusted
* within the machine keyring.
*/
static __init bool uefi_check_trust_mok_keys(void)
{
struct efi_mokvar_table_entry *mokvar_entry;
mokvar_entry = efi_mokvar_entry_find("MokListTrustedRT");
if (mokvar_entry)
return true;
return false;
}
bool __init trust_moklist(void)
{
static bool initialized;
if (!initialized) {
initialized = true;
if (uefi_check_trust_mok_keys())
trust_mok = true;
}
return trust_mok;
}