Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0250abcd authored by James Morris's avatar James Morris
Browse files

Merge tag 'keys-next-20160505' of...

Merge tag 'keys-next-20160505' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
parents 74f430cd d55201ce
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -823,6 +823,36 @@ The keyctl syscall functions are:
     A process must have search permission on the key for this function to be
     successful.

 (*) Compute a Diffie-Hellman shared secret or public key

       long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
		   char *buffer, size_t buflen);

     The params struct contains serial numbers for three keys:

	 - The prime, p, known to both parties
	 - The local private key
	 - The base integer, which is either a shared generator or the
	   remote public key

     The value computed is:

	result = base ^ private (mod prime)

     If the base is the shared generator, the result is the local
     public key.  If the base is the remote public key, the result is
     the shared secret.

     The buffer length must be at least the length of the prime, or zero.

     If the buffer length is nonzero, the length of the result is
     returned when it is successfully calculated and copied in to the
     buffer. When the buffer length is zero, the minimum required
     buffer length is returned.

     This function will return error EOPNOTSUPP if the key type is not
     supported, error ENOKEY if the key could not be found, or error
     EACCES if the key is not readable by the caller.

===============
KERNEL SERVICES
@@ -999,6 +1029,10 @@ payload contents" for more information.
	struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
				  const struct cred *cred,
				  key_perm_t perm,
				  int (*restrict_link)(struct key *,
						       const struct key_type *,
						       unsigned long,
						       const union key_payload *),
				  unsigned long flags,
				  struct key *dest);

@@ -1010,6 +1044,24 @@ payload contents" for more information.
    KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
    towards the user's quota).  Error ENOMEM can also be returned.

    If restrict_link not NULL, it should point to a function that will be
    called each time an attempt is made to link a key into the new keyring.
    This function is called to check whether a key may be added into the keying
    or not.  Callers of key_create_or_update() within the kernel can pass
    KEY_ALLOC_BYPASS_RESTRICTION to suppress the check.  An example of using
    this is to manage rings of cryptographic keys that are set up when the
    kernel boots where userspace is also permitted to add keys - provided they
    can be verified by a key the kernel already has.

    When called, the restriction function will be passed the keyring being
    added to, the key flags value and the type and payload of the key being
    added.  Note that when a new key is being created, this is called between
    payload preparsing and actual key creation.  The function should return 0
    to allow the link or an error to reject it.

    A convenience function, restrict_link_reject, exists to always return
    -EPERM to in this case.


(*) To check the validity of a key, this function can be called:

+4 −14
Original line number Diff line number Diff line
@@ -19,8 +19,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/efi.h>
#include <linux/verify_pefile.h>
#include <keys/system_keyring.h>
#include <linux/verification.h>

#include <asm/bootparam.h>
#include <asm/setup.h>
@@ -529,18 +528,9 @@ static int bzImage64_cleanup(void *loader_data)
#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
{
	bool trusted;
	int ret;

	ret = verify_pefile_signature(kernel, kernel_len,
				      system_trusted_keyring,
				      VERIFYING_KEXEC_PE_SIGNATURE,
				      &trusted);
	if (ret < 0)
		return ret;
	if (!trusted)
		return -EKEYREJECTED;
	return 0;
	return verify_pefile_signature(kernel, kernel_len,
				       NULL,
				       VERIFYING_KEXEC_PE_SIGNATURE);
}
#endif

+9 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ config MODULE_SIG_KEY
config SYSTEM_TRUSTED_KEYRING
	bool "Provide system-wide ring of trusted keys"
	depends on KEYS
	depends on ASYMMETRIC_KEY_TYPE
	help
	  Provide a system keyring to which trusted keys can be added.  Keys in
	  the keyring are considered to be trusted.  Keys may be added at will
@@ -55,4 +56,12 @@ config SYSTEM_EXTRA_CERTIFICATE_SIZE
	  This is the number of bytes reserved in the kernel image for a
	  certificate to be inserted.

config SECONDARY_TRUSTED_KEYRING
	bool "Provide a keyring to which extra trustable keys may be added"
	depends on SYSTEM_TRUSTED_KEYRING
	help
	  If set, provide a keyring to which extra keys may be added, provided
	  those keys are not blacklisted and are vouched for by a key built
	  into the kernel or already in the secondary trusted keyring.

endmenu
+113 −26
Original line number Diff line number Diff line
@@ -18,29 +18,88 @@
#include <keys/system_keyring.h>
#include <crypto/pkcs7.h>

struct key *system_trusted_keyring;
EXPORT_SYMBOL_GPL(system_trusted_keyring);
static struct key *builtin_trusted_keys;
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
static struct key *secondary_trusted_keys;
#endif

extern __initconst const u8 system_certificate_list[];
extern __initconst const unsigned long system_certificate_list_size;

/**
 * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
 *
 * 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.
 */
int restrict_link_by_builtin_trusted(struct key *keyring,
				     const struct key_type *type,
				     const union key_payload *payload)
{
	return restrict_link_by_signature(builtin_trusted_keys, type, payload);
}

#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
/**
 * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
 *   addition by both builtin and secondary keyrings
 *
 * 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.
 */
int restrict_link_by_builtin_and_secondary_trusted(
	struct key *keyring,
	const struct key_type *type,
	const union key_payload *payload)
{
	/* 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 &&
	    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_signature(secondary_trusted_keys, type, payload);
}
#endif

/*
 * Load the compiled-in keys
 * Create the trusted keyrings
 */
static __init int system_trusted_keyring_init(void)
{
	pr_notice("Initialise system trusted keyring\n");
	pr_notice("Initialise system trusted keyrings\n");

	system_trusted_keyring =
		keyring_alloc(".system_keyring",
	builtin_trusted_keys =
		keyring_alloc(".builtin_trusted_keys",
			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
			      KEY_ALLOC_NOT_IN_QUOTA, NULL);
	if (IS_ERR(system_trusted_keyring))
		panic("Can't allocate system trusted keyring\n");
			      KEY_ALLOC_NOT_IN_QUOTA,
			      NULL, NULL);
	if (IS_ERR(builtin_trusted_keys))
		panic("Can't allocate builtin trusted keyring\n");

#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
	secondary_trusted_keys =
		keyring_alloc(".secondary_trusted_keys",
			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
			       KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
			       KEY_USR_WRITE),
			      KEY_ALLOC_NOT_IN_QUOTA,
			      restrict_link_by_builtin_and_secondary_trusted,
			      NULL);
	if (IS_ERR(secondary_trusted_keys))
		panic("Can't allocate secondary trusted keyring\n");

	if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0)
		panic("Can't link trusted keyrings\n");
#endif

	set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
	return 0;
}

@@ -76,7 +135,7 @@ static __init int load_system_certificate_list(void)
		if (plen > end - p)
			goto dodgy_cert;

		key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
		key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1),
					   "asymmetric",
					   NULL,
					   p,
@@ -84,8 +143,8 @@ static __init int load_system_certificate_list(void)
					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
					   KEY_USR_VIEW | KEY_USR_READ),
					   KEY_ALLOC_NOT_IN_QUOTA |
					   KEY_ALLOC_TRUSTED |
					   KEY_ALLOC_BUILT_IN);
					   KEY_ALLOC_BUILT_IN |
					   KEY_ALLOC_BYPASS_RESTRICTION);
		if (IS_ERR(key)) {
			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
			       PTR_ERR(key));
@@ -108,19 +167,27 @@ late_initcall(load_system_certificate_list);
#ifdef CONFIG_SYSTEM_DATA_VERIFICATION

/**
 * Verify a PKCS#7-based signature on system data.
 * @data: The data to be verified.
 * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
 * @data: The data to be verified (NULL if expecting internal data).
 * @len: Size of @data.
 * @raw_pkcs7: The PKCS#7 message that is the signature.
 * @pkcs7_len: The size of @raw_pkcs7.
 * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
 *					(void *)1UL for all trusted keys).
 * @usage: The use to which the key is being put.
 * @view_content: Callback to gain access to content.
 * @ctx: Context for callback.
 */
int system_verify_data(const void *data, unsigned long len,
int verify_pkcs7_signature(const void *data, size_t len,
			   const void *raw_pkcs7, size_t pkcs7_len,
		       enum key_being_used_for usage)
			   struct key *trusted_keys,
			   enum key_being_used_for usage,
			   int (*view_content)(void *ctx,
					       const void *data, size_t len,
					       size_t asn1hdrlen),
			   void *ctx)
{
	struct pkcs7_message *pkcs7;
	bool trusted;
	int ret;

	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
@@ -128,7 +195,7 @@ int system_verify_data(const void *data, unsigned long len,
		return PTR_ERR(pkcs7);

	/* The data should be detached - so we need to supply it. */
	if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
	if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
		pr_err("PKCS#7 signature with non-detached data\n");
		ret = -EBADMSG;
		goto error;
@@ -138,13 +205,33 @@ int system_verify_data(const void *data, unsigned long len,
	if (ret < 0)
		goto error;

	ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
	if (ret < 0)
	if (!trusted_keys) {
		trusted_keys = builtin_trusted_keys;
	} else if (trusted_keys == (void *)1UL) {
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
		trusted_keys = secondary_trusted_keys;
#else
		trusted_keys = builtin_trusted_keys;
#endif
	}
	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
	if (ret < 0) {
		if (ret == -ENOKEY)
			pr_err("PKCS#7 signature not signed with a trusted key\n");
		goto error;
	}

	if (!trusted) {
		pr_err("PKCS#7 signature not signed with a trusted key\n");
		ret = -ENOKEY;
	if (view_content) {
		size_t asn1hdrlen;

		ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen);
		if (ret < 0) {
			if (ret == -ENODATA)
				pr_devel("PKCS#7 message does not contain data\n");
			goto error;
		}

		ret = view_content(ctx, data, len, asn1hdrlen);
	}

error:
@@ -152,6 +239,6 @@ int system_verify_data(const void *data, unsigned long len,
	pr_devel("<==%s() = %d\n", __func__, ret);
	return ret;
}
EXPORT_SYMBOL_GPL(system_verify_data);
EXPORT_SYMBOL_GPL(verify_pkcs7_signature);

#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
+3 −3
Original line number Diff line number Diff line
menuconfig ASYMMETRIC_KEY_TYPE
	tristate "Asymmetric (public-key cryptographic) key type"
	bool "Asymmetric (public-key cryptographic) key type"
	depends on KEYS
	help
	  This option provides support for a key type that holds the data for
@@ -40,8 +40,7 @@ config PKCS7_MESSAGE_PARSER

config PKCS7_TEST_KEY
	tristate "PKCS#7 testing key type"
	depends on PKCS7_MESSAGE_PARSER
	select SYSTEM_TRUSTED_KEYRING
	depends on SYSTEM_DATA_VERIFICATION
	help
	  This option provides a type of key that can be loaded up from a
	  PKCS#7 message - provided the message is signed by a trusted key.  If
@@ -54,6 +53,7 @@ config PKCS7_TEST_KEY
config SIGNED_PE_FILE_VERIFICATION
	bool "Support for PE file signature verification"
	depends on PKCS7_MESSAGE_PARSER=y
	depends on SYSTEM_DATA_VERIFICATION
	select ASN1
	select OID_REGISTRY
	help
Loading