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:
commit
c3330aab37
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_INTEGRITY_CA_MACHINE_KEYRING=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_INTEGRITY_MACHINE_KEYRING=y
|
|
@ -1 +1 @@
|
|||
# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
|
||||
CONFIG_SECONDARY_TRUSTED_KEYRING=y
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue