Weekly Edition Return to the Kernel page |
Kernel key managementFilesystems, especially remote filesystems, may require some authentication or a key to enable access; the kernel key management interface provides hooks to store and manage this kind of information. The hooks come in two flavors; one used by the kernel to find keys for subsystems that require them and one used by userspace programs to manage keys. The intent is to provide a fast mechanism for the kernel to access the keys that it needs and to push the add, modify and delete operations into userspace. 'Key' is the term used, but it may not be keys in the traditional, cryptographic sense that are stored. Any kind of authentication or access information can be stored as a key; it is essentially an opaque chunk of data that is only interpreted by the kernel subsystem that is interested in it. While filesystems are the main target of the API, any kernel subsystem that requires this kind of information could use it. At the core, keys are stored in the aptly named struct key which has the following kinds of fields:
The key types provide a way for a filesystem to configure its own set of key operations. The operations that a key type can specify are:
int register_key_type(struct key_type *type);
When the kernel needs to find a key, it calls:
struct key *request_key(const struct key_type *type,
const char *description,
const char *callout_string);
It passes the type and description and the match
function from the struct key_type is used to try and find a matching
key. If no key is found, and callout_string is not NULL,
the kernel will invoke /sbin/request-key, which
attempts to obtain the necessary key from userspace.
The payload field of a key can be accessed once the key has been found, but if it is more complex than a simple integer, some arrangement must be made to prevent simultaneous reads and writes. Support for semaphore locking or Read-Copy-Update (RCU) are present in the key structure and must be used unless the key type has no modification methods. Once the filesystem is done with the key, it should be released with:
void key_put(struct key *key);
Keyrings are, as the name implies, collections of related keys and there are various calls to manipulate them. Each process is associated with three keyrings: a thread-specific keyring, a process-specific keyring and a session-specific keyring. These are the keyrings searched when a request_key is issued. Each user on the system is associated with a user-specific keyring; a default user session keyring used to initialize the session-specific keyring when a process changes its real user id. Permissions for keys are stored in a bit field, much like Linux file permissions, but are more extensive. Each key has a user and group id and a permissions mask for each of four potential accessors: possessor, user, group, and other. The mask consists of six bits:
The userspace API consists of the three main system calls:
key_serial_t add_key(const char *type, const char *desc,
const void *payload, size_t plen,
key_serial_t keyring);
key_serial_t request_key(const char *type, const char *description,
const char *callout_info,
key_serial_t dest_keyring);
key_serial_t keyctl(int cmd, key_serial_t id, int create);
add_key() adds a key to the keyring specified. request_key(),
much like its kernel-side counterpart,
searches for the key based on the type and description, possibly calling
out to userspace if callout_info is non-NULL. It can also attach
the key to the specified destination keyring if it is found. keyctl()
is an ioctl-like interface that provides for the management of keys.
<linux/keyctl.h> contains 17 separate commands for
updating, changing permissions, searching, linking, reading and the like.
The /bin/keyctl command-line utility, part of the keyutils package, provides an easy interface to the userspace system calls to facilitate working with keys from userspace. Also, the /proc/keys and /proc/key-users entries in procfs enable a user to view the keys and key users currently managed by the kernel. The only filesystem in the current 2.6 tree that uses the key management API is eCryptfs, a stacked filesystem that encrypts its data using a password and optional salt. It uses the user key type rather than creating its own type and does not directly support userspace callbacks. Instead it uses the mount.ecryptfs command to prompt the user for the password and stores that as the key. According to slides from Dave Howells' talk at the 2006 Ottawa Linux Symposium (available here), several other filesystems (including CIFS, NFSv4 and AFS) are planning to use the API in the future. For more information, extensive documentation can be found in the kernel tree in Documentation/keys.txt and Documentation/keys-request-key.txt. Overall, this looks to be a useful interface for kernel subsystems that require keys and, in keeping with kernel tradition, most of the policy and management pieces are pushed out to userspace. It provides all of the capabilities that one would expect and hopefully more kernel subsystems will be using it in the future. (Log in to post comments)
Kernel key management Posted Nov 22, 2006 13:44 UTC (Wed) by NAR (subscriber, #1313) [Link] I was wondering - what's better (faster, safer, etc.) for local disks (e.g. for disks in laptops that could be easily stolen): encrypt a filesystem or encrypt the block device under the filesystem?
Kernel key management Posted Nov 22, 2006 19:21 UTC (Wed) by arjan (subscriber, #36785) [Link] technically it's "Safer" to encrypt the device as a whole, there can't then be leaked blocks from files that moved all over the disk..
HOwever encrypting files is more convenient for several things: for example if you need to legally remove all data from a certain person... all you need to do is destroy his key now, and that takes care automatically of all your backup tapes too ;)
Kernel key management Posted Nov 22, 2006 16:15 UTC (Wed) by kleptog (subscriber, #1183) [Link] Seems to me that this could pave the way for pervasive authentication. When a user logs in (say with a some token) that could be stored in the session keyring. This would then be available for any subprocess (it's preserved over fork, clone, execve, etc) to authenticate itself to something else. Sort of like ssh-agent on steriods.
Or am I missing something important?
ssh-agent Posted Nov 23, 2006 17:19 UTC (Thu) by ncm (subscriber, #165) [Link] Seems like ssh-agent itself would be a good choice for this role.
ssh-agent Posted Nov 23, 2006 18:07 UTC (Thu) by kleptog (subscriber, #1183) [Link] Hmm, the reason why I think ssh-agent isn't up to the job are two-fold:
- The link to the agent is via an environment variable, which isn't preserved in a variety of situations.
The stuff in this article can fix both since preservation is guarenteed and the keys can be protected even from root (barring direct memory reads ofcourse).
ssh-agent Posted Nov 24, 2006 18:44 UTC (Fri) by dlang (subscriber, #313) [Link] and the fact that root can su to any other user
|
Copyright © 2006, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds
Powered by Rackspace Managed Hosting.