A kernel key of asymmetric type acts as a handle to an asymmetric key as used for public-key cryptography. The key material itself may be held inside the kernel or it may be held in hardware with operations being offloaded. This prevents direct user access to the cryptographic material.
Keys may be any asymmetric type (RSA, ECDSA, ...) and may have both private and public components present or just the public component.
Asymmetric keys can be made use of by both the kernel and userspace. The kernel can make use of them for module signature verification and kexec image verification for example. Userspace is provided with a set of keyctl(KEYCTL_PKEY_*) calls for querying and using the key. These are wrapped by libkeyutils as functions named keyctl_pkey_*().
An asymmetric-type key can be loaded by the keyctl utility using a command line like:
openssl x509 -in key.x509 -outform DER | keyctl padd asymmetric foo @s
The asymmetric-type key can be viewed as a container that comprises of a number of components:
Note that expiry times from the payload are ignored as these patches may be used during boot before the system clock is set.
The asymmetric key parsers can handle keys in a number of forms:
In addition to the standard keyutils library functions, such as keyctl_update(), there are five calls specific to the asymmetric key type (though they are open to being used by other key types also):
The query function can be used to retrieve information about an asymmetric key, such as the key size, the amount of space required by buffers for the other operations and which operations are actually supported.
The other operations form two pairs: encrypt/decrypt and create/verify signature. Not all of these operations will necessarily be available; typically, encrypt and verify only require the public key to be available whereas decrypt and sign require the private key as well.
All of these operations take an information string parameter that supplies additional information such as encoding type/form and the password(s) needed to unlock/unwrap the key. This takes the form of a comma-separated list of "key[=value]" pairs, the exact set of which depends on the subtype driver used by a particular key.
Available parameters include:
Note that not all parameters are used by all subtypes.
An additional keyutils function, keyctl_restrict_keyring(), can be used to gate a keyring so that a new key can only be added to the affected keyring if (a) it's an asymmetric key, (b) it's validly signed by a key in some appropriate keyring and (c) it's not blacklisted.
keyctl_restrict_keyring(keyring, "asymmetric",
"key_or_keyring:<signing-key>[:chain]");
Where <signing-key> is the ID of a key or a ring of keys that act as the authority to permit a new key to be added to the keyring. The chain flag indicates that keys that have been added to the keyring may also be used to verify new keys. Authorising keys must themselves be asymmetric-type keys that can be used to do a signature verification on the key being added.
Note that there are various system keyrings visible to the root user that may permit additional keys to be added. These are typically gated by keys that already exist, preventing unauthorised keys from being used for such things as module verification.
When the attempt is made to add a key to the kernel, a hash of the public key is checked against the blacklist. This is a system keyring named .blacklist and contains keys of type blacklist. If the blacklist contains a key whose description matches the hash of the new key, that new key will be rejected with error EKEYREJECTED.
The blacklist keyring may be loaded from multiple sources, including a list compiled into the kernel and the UEFI dbx variable. Further hashes may also be blacklisted by the administrator. Note that blacklisting is not retroactive, so an asymmetric key that is already on the system cannot be blacklisted by adding a matching blacklist entry later.