linux-crypto.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Snowberg <eric.snowberg@oracle.com>
To: linux-security-module@vger.kernel.org
Cc: dhowells@redhat.com, dwmw2@infradead.org,
	herbert@gondor.apana.org.au, davem@davemloft.net,
	ardb@kernel.org, jarkko@kernel.org, paul@paul-moore.com,
	jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com,
	roberto.sassu@huawei.com, dmitry.kasatkin@gmail.com,
	mic@digikod.net, casey@schaufler-ca.com, stefanb@linux.ibm.com,
	eric.snowberg@oracle.com, linux-kernel@vger.kernel.org,
	keyrings@vger.kernel.org, linux-crypto@vger.kernel.org,
	linux-efi@vger.kernel.org, linux-integrity@vger.kernel.org
Subject: [PATCH RFC 7/8] clavis: Introduce a new key type called clavis_key_acl
Date: Mon, 11 Mar 2024 12:11:10 -0400	[thread overview]
Message-ID: <20240311161111.3268190-8-eric.snowberg@oracle.com> (raw)
In-Reply-To: <20240311161111.3268190-1-eric.snowberg@oracle.com>

Introduce a new key type for keyring access control.  The new key type
is called clavis_key_acl.  The clavis_key_acl contains the subject key
identifer along with the allowed usage type for the key.

The format is as follows:

XX:YYYYYYYYYYY

XX - Single byte of the key type
	VERIFYING_MODULE_SIGNATURE            00
	VERIFYING_FIRMWARE_SIGNATURE          01
	VERIFYING_KEXEC_PE_SIGNATURE          02
	VERIFYING_KEY_SIGNATURE               03
	VERIFYING_KEY_SELF_SIGNATURE          04
	VERIFYING_UNSPECIFIED_SIGNATURE       05
:  - ASCII colon
YY - Even number of hexadecimal characters representing the key id

This key type will be used in the clavis keyring for access control. To
be added to the clavis keyring, the clavis_key_acl must be S/MIME signed
by the sole asymmetric key contained within it.

Below is an example of how this could be used. Within the example, the
key (b360d113c848ace3f1e6a80060b43d1206f0487d) is already in the machine
keyring. The intended usage for this key is to validate a signed kernel
for kexec:

echo "02:b360d113c848ace3f1e6a80060b43d1206f0487d" > kernel-acl.txt

The next step is to sign it:

openssl smime -sign -signer clavis-lsm.x509 -inkey clavis-lsm.priv -in \
	kernel-acl.txt  -out kernel-acl.pkcs7 -binary -outform DER \
	-nodetach -noattr

The final step is how to add the acl to the .clavis keyring:

keyctl padd clavis_key_acl "" %:.clavis < kernel-acl.pkcs7

Afterwards the new clavis_key_acl can be seen in the .clavis keyring:

keyctl show %:.clavis
Keyring
  keyring: .clavis
   \_ asymmetric: Clavis LSM key: 4a00ab9f35c9dc3aed7c225d22bafcbd9285e1e8
   \_ clavis_key_acl: 02:b360d113c848ace3f1e6a80060b43d1206f0487d

Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
---
 security/clavis/clavis_keyring.c | 127 +++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/security/clavis/clavis_keyring.c b/security/clavis/clavis_keyring.c
index c5606ed101f6..0ab2341d47b8 100644
--- a/security/clavis/clavis_keyring.c
+++ b/security/clavis/clavis_keyring.c
@@ -1,13 +1,18 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include <linux/security.h>
+#include <linux/ctype.h>
 #include <keys/asymmetric-type.h>
+#include <keys/asymmetric-subtype.h>
 #include <keys/system_keyring.h>
+#include <keys/user-type.h>
+#include <crypto/pkcs7.h>
 #include "clavis.h"
 
 static struct key *clavis_keyring;
 static struct asymmetric_key_id *setup_keyid;
 
+#define MAX_ASCII_KID 64
 #define MAX_BIN_KID   32
 
 static struct {
@@ -15,6 +20,123 @@ static struct {
 	unsigned char data[MAX_BIN_KID];
 } setup_key;
 
+static int pkcs7_preparse_content(void *ctx, const void *data, size_t len,
+			      size_t asn1hdrlen)
+{
+	struct key_preparsed_payload *prep = ctx;
+	const void *saved_prep_data;
+	size_t saved_prep_datalen;
+	const char *p;
+	char *desc;
+	int ret, i;
+
+	/* clavis_free_prepase will free this */
+	desc = kmalloc(len, GFP_KERNEL);
+
+	if (!desc)
+		return -ENOMEM;
+	memcpy(desc, data, len);
+
+	/* remove any white space */
+	for (i = 0, p = desc; i < len; i++, p++) {
+		if (isspace(*p))
+			desc[i] = 0;
+	}
+
+	prep->description = desc;
+	saved_prep_data = prep->data;
+	saved_prep_datalen = prep->datalen;
+	prep->data = desc;
+	prep->datalen = len;
+	ret = user_preparse(prep);
+	prep->data = saved_prep_data;
+	prep->datalen = saved_prep_datalen;
+	return ret;
+}
+
+static void key_acl_free_preparse(struct key_preparsed_payload *prep)
+{
+	kfree(prep->description);
+	user_free_preparse(prep);
+}
+
+static int key_acl_preparse(struct key_preparsed_payload *prep)
+{
+	/* Only allow the description to be set via the pkcs7 data contents */
+	if (prep->orig_description)
+		return -EINVAL;
+
+	return verify_pkcs7_signature(NULL, 0, prep->data, prep->datalen, clavis_keyring,
+				      VERIFYING_CLAVIS_SIGNATURE, pkcs7_preparse_content,
+				      prep);
+}
+
+static int key_acl_instantiate(struct key *key, struct key_preparsed_payload *prep)
+{
+	key->perm |= KEY_USR_READ;
+	key->perm |= KEY_USR_SEARCH;
+	set_bit(KEY_FLAG_KEEP, &key->flags);
+	return generic_key_instantiate(key, prep);
+}
+
+static void key_acl_destroy(struct key *key)
+{
+	/* It should not be possible to get here */
+	pr_info("destroy clavis_key_acl denied\n");
+}
+
+static void key_acl_revoke(struct key *key)
+{
+	/* It should not be possible to get here */
+	pr_info("revoke clavis_key_acl denied\n");
+}
+
+static int key_acl_update(struct key *key, struct key_preparsed_payload *prep)
+{
+	return -EPERM;
+}
+
+static int key_acl_vet_description(const char *desc)
+{
+	unsigned char data[MAX_BIN_KID];
+	int ascii_len, hex_len, error;
+
+	ascii_len = strlen(desc);
+
+	/*
+	 * clavis_acl format:
+	 *    xx:yyyyyyyyy...
+	 *
+	 *    xx   - Single byte of the key type
+	 *    :    - Ascii colon
+	 *    yyyy - Even number of hexadecimal characters representing the keyid
+	 */
+	if (ascii_len < 5 || ascii_len > (MAX_ASCII_KID + 3) || desc[2] != ':')
+		return -EINVAL;
+
+	/* move past the colon */
+	ascii_len -= 3;
+	hex_len = ascii_len / 2;
+	error = hex2bin(data, desc+3, hex_len);
+
+	if (error < 0)
+		pr_err("Unparsable clavis key id\n");
+
+	return error;
+}
+
+static struct key_type clavis_key_acl = {
+	.name			= "clavis_key_acl",
+	.preparse		= key_acl_preparse,
+	.free_preparse		= key_acl_free_preparse,
+	.instantiate		= key_acl_instantiate,
+	.update			= key_acl_update,
+	.revoke			= key_acl_revoke,
+	.destroy		= key_acl_destroy,
+	.vet_description	= key_acl_vet_description,
+	.read			= user_read,
+};
+
 static int restrict_link_for_clavis(struct key *dest_keyring,
 		const struct key_type *type, const union key_payload *payload,
 		struct key *restrict_key)
@@ -30,6 +152,8 @@ static int restrict_link_for_clavis(struct key *dest_keyring,
 		return 0;
 	}
 
+	if (type == &clavis_key_acl)
+		return 0;
 	return -EOPNOTSUPP;
 }
 
@@ -64,6 +188,9 @@ static int __init clavis_keyring_init(void)
 {
 	struct key_restriction *restriction;
 
+	if (register_key_type(&clavis_key_acl) < 0)
+		panic("Can't allocate clavis key type\n");
+
 	restriction = kzalloc(sizeof(*restriction), GFP_KERNEL);
 	if (!restriction)
 		panic("Can't allocate clavis keyring restriction\n");
-- 
2.39.3


  parent reply	other threads:[~2024-03-11 16:19 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-11 16:11 [PATCH RFC 0/8] Clavis LSM Eric Snowberg
2024-03-11 16:11 ` [PATCH RFC 1/8] certs: Introduce ability to link to a system key Eric Snowberg
2024-03-11 19:16   ` Jarkko Sakkinen
2024-03-11 21:29     ` Eric Snowberg
2024-03-11 19:18   ` Jarkko Sakkinen
2024-03-11 21:31     ` Eric Snowberg
2024-03-12 15:18       ` Jarkko Sakkinen
2024-03-12  6:00   ` [EXTERNAL] " Bharat Bhushan
2024-04-04 22:40   ` Mimi Zohar
2024-04-05 12:56     ` Eric Snowberg
2024-03-11 16:11 ` [PATCH RFC 2/8] clavis: Introduce a new system keyring called clavis Eric Snowberg
2024-03-11 16:11 ` [PATCH RFC 3/8] efi: Make clavis boot param persist across kexec Eric Snowberg
2024-03-11 16:11 ` [PATCH RFC 4/8] clavis: Prevent clavis boot param from changing during kexec Eric Snowberg
2024-03-11 16:11 ` [PATCH RFC 5/8] keys: Add new verification type (VERIFYING_CLAVIS_SIGNATURE) Eric Snowberg
2024-03-11 16:11 ` [PATCH RFC 6/8] keys: Add ability to track intended usage of the public key Eric Snowberg
2024-03-11 16:11 ` Eric Snowberg [this message]
2024-03-11 16:11 ` [PATCH RFC 8/8] clavis: Introduce new LSM called clavis Eric Snowberg
2024-03-12  2:45   ` Randy Dunlap
2024-03-12 14:04     ` Eric Snowberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240311161111.3268190-8-eric.snowberg@oracle.com \
    --to=eric.snowberg@oracle.com \
    --cc=ardb@kernel.org \
    --cc=casey@schaufler-ca.com \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=dwmw2@infradead.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=jarkko@kernel.org \
    --cc=jmorris@namei.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mic@digikod.net \
    --cc=paul@paul-moore.com \
    --cc=roberto.sassu@huawei.com \
    --cc=serge@hallyn.com \
    --cc=stefanb@linux.ibm.com \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).