diff mbox series

[1/3] KEYS: DigitalSignature link restriction

Message ID 20230508220708.2888510-2-eric.snowberg@oracle.com (mailing list archive)
State New, archived
Headers show
Series Add digitalSignature enforcement keyring restrictions | expand

Commit Message

Eric Snowberg May 8, 2023, 10:07 p.m. UTC
Add a new link restriction.  Restrict the addition of keys in a keyring
based on the key having digitalSignature usage set. Additionally, verify
the new certificate against the ones in the system keyrings.  Add two
additional functions to use the new restriction within either the builtin
or secondary keyrings.

Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
---
 certs/system_keyring.c            | 52 +++++++++++++++++++++++++++++++
 crypto/asymmetric_keys/restrict.c | 44 ++++++++++++++++++++++++++
 include/crypto/public_key.h       | 11 +++++++
 include/keys/system_keyring.h     | 11 +++++++
 4 files changed, 118 insertions(+)

Comments

Jarkko Sakkinen May 10, 2023, 10:34 p.m. UTC | #1
On Tue May 9, 2023 at 1:07 AM EEST, Eric Snowberg wrote:
> Add a new link restriction.  Restrict the addition of keys in a keyring
> based on the key having digitalSignature usage set. Additionally, verify
> the new certificate against the ones in the system keyrings.  Add two
> additional functions to use the new restriction within either the builtin
> or secondary keyrings.
>
> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> ---
>  certs/system_keyring.c            | 52 +++++++++++++++++++++++++++++++
>  crypto/asymmetric_keys/restrict.c | 44 ++++++++++++++++++++++++++
>  include/crypto/public_key.h       | 11 +++++++
>  include/keys/system_keyring.h     | 11 +++++++
>  4 files changed, 118 insertions(+)
>
> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> index a7a49b17ceb1..4249c49bd43b 100644
> --- a/certs/system_keyring.c
> +++ b/certs/system_keyring.c
> @@ -51,6 +51,27 @@ 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.

BTW, does checkpatch complain if you put that to a single line (I don't
know this)?

If not, I would just put "Restrict by digitalSignature"

> + * @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
> @@ -83,6 +104,37 @@ int restrict_link_by_builtin_and_secondary_trusted(
>  					  secondary_trusted_keys);
>  }
>  
> +/**
> + * restrict_link_by_digsig_builtin_and_secondary - Restrict digitalSignature
> + *   key additions 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
> + * 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().
> diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
> index 276bdb627498..6b69ea40da23 100644
> --- a/crypto/asymmetric_keys/restrict.c
> +++ b/crypto/asymmetric_keys/restrict.c
> @@ -148,6 +148,50 @@ int restrict_link_by_ca(struct key *dest_keyring,
>  	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_id **pair,
>  			    const struct asymmetric_key_id *single)
>  {
> diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
> index 653992a6e941..8eb5eff059f3 100644
> --- a/include/crypto/public_key.h
> +++ b/include/crypto/public_key.h
> @@ -80,6 +80,10 @@ 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,
> @@ -88,6 +92,13 @@ static inline int restrict_link_by_ca(struct key *dest_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 *,
> diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
> index 91e080efb918..38f63f1c2cbe 100644
> --- a/include/keys/system_keyring.h
> +++ b/include/keys/system_keyring.h
> @@ -23,10 +23,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)
>  {
> @@ -41,8 +46,14 @@ 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
> -- 
> 2.27.0

BR, Jarkko
Eric Snowberg May 11, 2023, 10:48 p.m. UTC | #2
> On May 10, 2023, at 4:34 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> 
> On Tue May 9, 2023 at 1:07 AM EEST, Eric Snowberg wrote:
>> Add a new link restriction.  Restrict the addition of keys in a keyring
>> based on the key having digitalSignature usage set. Additionally, verify
>> the new certificate against the ones in the system keyrings.  Add two
>> additional functions to use the new restriction within either the builtin
>> or secondary keyrings.
>> 
>> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
>> ---
>> certs/system_keyring.c            | 52 +++++++++++++++++++++++++++++++
>> crypto/asymmetric_keys/restrict.c | 44 ++++++++++++++++++++++++++
>> include/crypto/public_key.h       | 11 +++++++
>> include/keys/system_keyring.h     | 11 +++++++
>> 4 files changed, 118 insertions(+)
>> 
>> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
>> index a7a49b17ceb1..4249c49bd43b 100644
>> --- a/certs/system_keyring.c
>> +++ b/certs/system_keyring.c
>> @@ -51,6 +51,27 @@ 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.
> 
> BTW, does checkpatch complain if you put that to a single line (I don't
> know this)?
> 
> If not, I would just put "Restrict by digitalSignatureā€¯

It looks like check patch will allow up to 100 chars.  I will update it to a single line.
Thanks.
Mimi Zohar May 17, 2023, 1:18 a.m. UTC | #3
On Mon, 2023-05-08 at 18:07 -0400, Eric Snowberg wrote:
> Add a new link restriction.  Restrict the addition of keys in a keyring
> based on the key having digitalSignature usage set. Additionally, verify
> the new certificate against the ones in the system keyrings.  Add two
> additional functions to use the new restriction within either the builtin
> or secondary keyrings.
> 
> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>

Thanks, Eric.

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
diff mbox series

Patch

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index a7a49b17ceb1..4249c49bd43b 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -51,6 +51,27 @@  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
@@ -83,6 +104,37 @@  int restrict_link_by_builtin_and_secondary_trusted(
 					  secondary_trusted_keys);
 }
 
+/**
+ * restrict_link_by_digsig_builtin_and_secondary - Restrict digitalSignature
+ *   key additions 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
+ * 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().
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index 276bdb627498..6b69ea40da23 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -148,6 +148,50 @@  int restrict_link_by_ca(struct key *dest_keyring,
 	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_id **pair,
 			    const struct asymmetric_key_id *single)
 {
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 653992a6e941..8eb5eff059f3 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -80,6 +80,10 @@  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,
@@ -88,6 +92,13 @@  static inline int restrict_link_by_ca(struct key *dest_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 *,
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 91e080efb918..38f63f1c2cbe 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -23,10 +23,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)
 {
@@ -41,8 +46,14 @@  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