lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <462886.1749731810@warthog.procyon.org.uk>
Date: Thu, 12 Jun 2025 13:36:50 +0100
From: David Howells <dhowells@...hat.com>
To: keyrings@...r.kernel.org, Jarkko Sakkinen <jarkko@...nel.org>,
    Steve French <sfrench@...ba.org>,
    Chuck Lever <chuck.lever@...cle.com>,
    Mimi Zohar <zohar@...ux.ibm.com>
cc: dhowells@...hat.com, Paulo Alcantara <pc@...guebit.org>,
    Herbert Xu <herbert@...dor.apana.org.au>,
    Jeffrey Altman <jaltman@...istor.com>, hch@...radead.org,
    linux-afs@...ts.infradead.org, linux-nfs@...r.kernel.org,
    linux-cifs@...r.kernel.org, linux-security-module@...r.kernel.org,
    linux-fsdevel@...r.kernel.org, linux-crypto@...r.kernel.org,
    netdev@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [RFC] Keyrings: How to make them more useful

Hi Jarkko, Steve, Chuck, Mimi, et al.,

I think work needs to be done on the keyrings subsystem to make them more
useful for network filesystems and other kernel services such as TLS and
crypto.

There are a number of issues that I think need addressing:

 (1) One of the flaws in the initial design is that whilst keys have a type
     (which is necessary), this has to be specified as part of the lookup or
     the search, which is overly restrictive.

     It probably would have been better to search by description alone and
     then, if a key is found, have any type of key with that description
     returned and let the app/service investigate the key to find the type.

     Now, this is still possible to implement on top of the existing API: just
     allow a NULL type to be passed in - but we might need some way to
     enumerate all the keys with that description, but of different types.
     Possibly, the search function should return all the matching keys.

     Possibly, within the kernel, for each keyring, all the keys of the same
     description can be stored within a group structure, and the search
     returns the group.  This could also have the added benefit of maybe
     making it easier to handle updates.

 (2) For certain applications, keys need versioning - and we need to be able
     to get access to older versions (at least to some extent) of the keys.
     An example of this is cifs where (if I understand it correctly) the key
     version gets cranked, but not all servers may have caught up yet, so we
     need to be able to try the keys in descending order of version.

     This could also work within the group idea mentioned above.

 (3) For certain applications, such as AFS and AF_RXRPC, we may need to be
     able to keep a number of keys around that have the same description
     (e.g. cell name) and basic type (e.g. rxrpc) and version, but that have
     different crypto types (e.g. Rx security classes and Kerberos types, such
     as RxGK+aes256-cts-hmac-sha1-96, RxGK+aes128-cts-hmac-sha256-128 or
     RxKAD) as different servers in the same cell might not support all or we
     might be implementing a server that is offering multiple crypto types.

     So we might need a "subtype" as well as a version.

 (4) I think the keyring ACLs idea need to be revived.  We have a whole bunch
     of different keyrings, each with a specific 'domain' of usage for the
     keys contained therein for checking signatures on things.  Can we reduce
     this to one keyring and use ACLs to declare the specific purposes for
     which a key may be used or the specific tasks that may use it?  Use
     special subject IDs (ie. not simply UIDs/GIDs) to mark this.

 (5) Replace the upcall mechanism with a listenable service channel, so that a
     userspace service (possibly part of systemd or driven from systemd) can
     listen on it and perform key creation/maintenance services.

     From previous discussions with the systemd maintainer, it would be a lot
     easier for them to manage if the key is attached to a file descriptor -
     at least for the duration of the maintenance operation.

     Further, this needs to be containerised in some way so that requests from
     different containers can be handled separately - and can be
     distinguished.

 (6) Move away from keeping DNS records in a keyring, but rather keep them in
     some sort of shrinkable list.  They could still be looked up over a
     secure channel.

To aid with at least (1), (2) and (3) and possibly (4), I think it might be
worth adding an extended add_key() system call that takes an additional
parameter string:

	key_serial_t add_key2(const char *type,
			      const char *description,
			      const char *parameters,
			      const void payload, size_t plen,
			      key_serial_t keyring);

The parameters would get passed to the key type driver for it to extract
things like version number and subtype from without the need to try and fold
it into the payload (which may, for example, be a binary ticket obtained from
kerberos).  Though possibly that is a bad example as the kerberos ticket may
contain multiple keys.

Also, maybe add a multi-key adding syscall for when the payload may contain
multiple keys, each to be added separately:

	int add_keys(const char *type,
		     const char *description,
		     const char *parameters,
		     const void payload, size_t plen,
		     key_serial_t keyring);

When it comes to keyrings, I'm thinking that the keyring needs to change such
that the index holds CoW groups of keys of the same description, but of
different type, version and subtype, e.g.:

	struct key_group {
		struct rcu_head		rcu;
		struct key_group	*replacement;
		char			*description;
		unsigned int		seq;
		refcount_t		ref;
		int			nr_keys;
		struct {
			unsigned long	version;
			struct key __rcu *key;
		} key_list[];
	};

and that these groups should be made available to kernel services upon
searching.  I'm tempted to put the version as part of the group as a whole,
making it easier to ditch a set of the same version, but that could make RCU
CoW-ness tricky.

I could then add two new keyctls, one to unlink all the keys in a keyring that
match description and, optionally, type and parameters (e.g. of a particular
version):

	int keyctl_scrub(const char *type, /* can be NULL */
			 const char *description,
			 const char *parameters, /* can be NULL */
			 key_serial_t keyring);

and one to list all the keys matching a description and, optionally, type and
parameters:

	int list_keys(const char *type, /* can be NULL */
		      const char *description,
		      const char *parameters, /* can be NULL */
		      key_serial_t keyring,
		      key_serial_t *list,
		      size_t list_size);

Thoughts?

Thanks,
David


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ