KEYS: Document asymmetric key type
In-source documentation for the asymmetric key type. This will be located in: Documentation/crypto/asymmetric-keys.txt Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Родитель
aacf29bf1b
Коммит
9a83b46578
|
@ -0,0 +1,312 @@
|
|||
=============================================
|
||||
ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE
|
||||
=============================================
|
||||
|
||||
Contents:
|
||||
|
||||
- Overview.
|
||||
- Key identification.
|
||||
- Accessing asymmetric keys.
|
||||
- Signature verification.
|
||||
- Asymmetric key subtypes.
|
||||
- Instantiation data parsers.
|
||||
|
||||
|
||||
========
|
||||
OVERVIEW
|
||||
========
|
||||
|
||||
The "asymmetric" key type is designed to be a container for the keys used in
|
||||
public-key cryptography, without imposing any particular restrictions on the
|
||||
form or mechanism of the cryptography or form of the key.
|
||||
|
||||
The asymmetric key is given a subtype that defines what sort of data is
|
||||
associated with the key and provides operations to describe and destroy it.
|
||||
However, no requirement is made that the key data actually be stored in the
|
||||
key.
|
||||
|
||||
A completely in-kernel key retention and operation subtype can be defined, but
|
||||
it would also be possible to provide access to cryptographic hardware (such as
|
||||
a TPM) that might be used to both retain the relevant key and perform
|
||||
operations using that key. In such a case, the asymmetric key would then
|
||||
merely be an interface to the TPM driver.
|
||||
|
||||
Also provided is the concept of a data parser. Data parsers are responsible
|
||||
for extracting information from the blobs of data passed to the instantiation
|
||||
function. The first data parser that recognises the blob gets to set the
|
||||
subtype of the key and define the operations that can be done on that key.
|
||||
|
||||
A data parser may interpret the data blob as containing the bits representing a
|
||||
key, or it may interpret it as a reference to a key held somewhere else in the
|
||||
system (for example, a TPM).
|
||||
|
||||
|
||||
==================
|
||||
KEY IDENTIFICATION
|
||||
==================
|
||||
|
||||
If a key is added with an empty name, the instantiation data parsers are given
|
||||
the opportunity to pre-parse a key and to determine the description the key
|
||||
should be given from the content of the key.
|
||||
|
||||
This can then be used to refer to the key, either by complete match or by
|
||||
partial match. The key type may also use other criteria to refer to a key.
|
||||
|
||||
The asymmetric key type's match function can then perform a wider range of
|
||||
comparisons than just the straightforward comparison of the description with
|
||||
the criterion string:
|
||||
|
||||
(1) If the criterion string is of the form "id:<hexdigits>" then the match
|
||||
function will examine a key's fingerprint to see if the hex digits given
|
||||
after the "id:" match the tail. For instance:
|
||||
|
||||
keyctl search @s asymmetric id:5acc2142
|
||||
|
||||
will match a key with fingerprint:
|
||||
|
||||
1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142
|
||||
|
||||
(2) If the criterion string is of the form "<subtype>:<hexdigits>" then the
|
||||
match will match the ID as in (1), but with the added restriction that
|
||||
only keys of the specified subtype (e.g. tpm) will be matched. For
|
||||
instance:
|
||||
|
||||
keyctl search @s asymmetric tpm:5acc2142
|
||||
|
||||
Looking in /proc/keys, the last 8 hex digits of the key fingerprint are
|
||||
displayed, along with the subtype:
|
||||
|
||||
1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 []
|
||||
|
||||
|
||||
=========================
|
||||
ACCESSING ASYMMETRIC KEYS
|
||||
=========================
|
||||
|
||||
For general access to asymmetric keys from within the kernel, the following
|
||||
inclusion is required:
|
||||
|
||||
#include <crypto/public_key.h>
|
||||
|
||||
This gives access to functions for dealing with asymmetric / public keys.
|
||||
Three enums are defined there for representing public-key cryptography
|
||||
algorithms:
|
||||
|
||||
enum pkey_algo
|
||||
|
||||
digest algorithms used by those:
|
||||
|
||||
enum pkey_hash_algo
|
||||
|
||||
and key identifier representations:
|
||||
|
||||
enum pkey_id_type
|
||||
|
||||
Note that the key type representation types are required because key
|
||||
identifiers from different standards aren't necessarily compatible. For
|
||||
instance, PGP generates key identifiers by hashing the key data plus some
|
||||
PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers.
|
||||
|
||||
The operations defined upon a key are:
|
||||
|
||||
(1) Signature verification.
|
||||
|
||||
Other operations are possible (such as encryption) with the same key data
|
||||
required for verification, but not currently supported, and others
|
||||
(eg. decryption and signature generation) require extra key data.
|
||||
|
||||
|
||||
SIGNATURE VERIFICATION
|
||||
----------------------
|
||||
|
||||
An operation is provided to perform cryptographic signature verification, using
|
||||
an asymmetric key to provide or to provide access to the public key.
|
||||
|
||||
int verify_signature(const struct key *key,
|
||||
const struct public_key_signature *sig);
|
||||
|
||||
The caller must have already obtained the key from some source and can then use
|
||||
it to check the signature. The caller must have parsed the signature and
|
||||
transferred the relevant bits to the structure pointed to by sig.
|
||||
|
||||
struct public_key_signature {
|
||||
u8 *digest;
|
||||
u8 digest_size;
|
||||
enum pkey_hash_algo pkey_hash_algo : 8;
|
||||
u8 nr_mpi;
|
||||
union {
|
||||
MPI mpi[2];
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that
|
||||
make up the actual signature must be stored in sig->mpi[] and the count of MPIs
|
||||
placed in sig->nr_mpi.
|
||||
|
||||
In addition, the data must have been digested by the caller and the resulting
|
||||
hash must be pointed to by sig->digest and the size of the hash be placed in
|
||||
sig->digest_size.
|
||||
|
||||
The function will return 0 upon success or -EKEYREJECTED if the signature
|
||||
doesn't match.
|
||||
|
||||
The function may also return -ENOTSUPP if an unsupported public-key algorithm
|
||||
or public-key/hash algorithm combination is specified or the key doesn't
|
||||
support the operation; -EBADMSG or -ERANGE if some of the parameters have weird
|
||||
data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned
|
||||
if the key argument is the wrong type or is incompletely set up.
|
||||
|
||||
|
||||
=======================
|
||||
ASYMMETRIC KEY SUBTYPES
|
||||
=======================
|
||||
|
||||
Asymmetric keys have a subtype that defines the set of operations that can be
|
||||
performed on that key and that determines what data is attached as the key
|
||||
payload. The payload format is entirely at the whim of the subtype.
|
||||
|
||||
The subtype is selected by the key data parser and the parser must initialise
|
||||
the data required for it. The asymmetric key retains a reference on the
|
||||
subtype module.
|
||||
|
||||
The subtype definition structure can be found in:
|
||||
|
||||
#include <keys/asymmetric-subtype.h>
|
||||
|
||||
and looks like the following:
|
||||
|
||||
struct asymmetric_key_subtype {
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
|
||||
void (*describe)(const struct key *key, struct seq_file *m);
|
||||
void (*destroy)(void *payload);
|
||||
int (*verify_signature)(const struct key *key,
|
||||
const struct public_key_signature *sig);
|
||||
};
|
||||
|
||||
Asymmetric keys point to this with their type_data[0] member.
|
||||
|
||||
The owner and name fields should be set to the owning module and the name of
|
||||
the subtype. Currently, the name is only used for print statements.
|
||||
|
||||
There are a number of operations defined by the subtype:
|
||||
|
||||
(1) describe().
|
||||
|
||||
Mandatory. This allows the subtype to display something in /proc/keys
|
||||
against the key. For instance the name of the public key algorithm type
|
||||
could be displayed. The key type will display the tail of the key
|
||||
identity string after this.
|
||||
|
||||
(2) destroy().
|
||||
|
||||
Mandatory. This should free the memory associated with the key. The
|
||||
asymmetric key will look after freeing the fingerprint and releasing the
|
||||
reference on the subtype module.
|
||||
|
||||
(3) verify_signature().
|
||||
|
||||
Optional. These are the entry points for the key usage operations.
|
||||
Currently there is only the one defined. If not set, the caller will be
|
||||
given -ENOTSUPP. The subtype may do anything it likes to implement an
|
||||
operation, including offloading to hardware.
|
||||
|
||||
|
||||
==========================
|
||||
INSTANTIATION DATA PARSERS
|
||||
==========================
|
||||
|
||||
The asymmetric key type doesn't generally want to store or to deal with a raw
|
||||
blob of data that holds the key data. It would have to parse it and error
|
||||
check it each time it wanted to use it. Further, the contents of the blob may
|
||||
have various checks that can be performed on it (eg. self-signatures, validity
|
||||
dates) and may contain useful data about the key (identifiers, capabilities).
|
||||
|
||||
Also, the blob may represent a pointer to some hardware containing the key
|
||||
rather than the key itself.
|
||||
|
||||
Examples of blob formats for which parsers could be implemented include:
|
||||
|
||||
- OpenPGP packet stream [RFC 4880].
|
||||
- X.509 ASN.1 stream.
|
||||
- Pointer to TPM key.
|
||||
- Pointer to UEFI key.
|
||||
|
||||
During key instantiation each parser in the list is tried until one doesn't
|
||||
return -EBADMSG.
|
||||
|
||||
The parser definition structure can be found in:
|
||||
|
||||
#include <keys/asymmetric-parser.h>
|
||||
|
||||
and looks like the following:
|
||||
|
||||
struct asymmetric_key_parser {
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
|
||||
int (*parse)(struct key_preparsed_payload *prep);
|
||||
};
|
||||
|
||||
The owner and name fields should be set to the owning module and the name of
|
||||
the parser.
|
||||
|
||||
There is currently only a single operation defined by the parser, and it is
|
||||
mandatory:
|
||||
|
||||
(1) parse().
|
||||
|
||||
This is called to preparse the key from the key creation and update paths.
|
||||
In particular, it is called during the key creation _before_ a key is
|
||||
allocated, and as such, is permitted to provide the key's description in
|
||||
the case that the caller declines to do so.
|
||||
|
||||
The caller passes a pointer to the following struct with all of the fields
|
||||
cleared, except for data, datalen and quotalen [see
|
||||
Documentation/security/keys.txt].
|
||||
|
||||
struct key_preparsed_payload {
|
||||
char *description;
|
||||
void *type_data[2];
|
||||
void *payload;
|
||||
const void *data;
|
||||
size_t datalen;
|
||||
size_t quotalen;
|
||||
};
|
||||
|
||||
The instantiation data is in a blob pointed to by data and is datalen in
|
||||
size. The parse() function is not permitted to change these two values at
|
||||
all, and shouldn't change any of the other values _unless_ they are
|
||||
recognise the blob format and will not return -EBADMSG to indicate it is
|
||||
not theirs.
|
||||
|
||||
If the parser is happy with the blob, it should propose a description for
|
||||
the key and attach it to ->description, ->type_data[0] should be set to
|
||||
point to the subtype to be used, ->payload should be set to point to the
|
||||
initialised data for that subtype, ->type_data[1] should point to a hex
|
||||
fingerprint and quotalen should be updated to indicate how much quota this
|
||||
key should account for.
|
||||
|
||||
When clearing up, the data attached to ->type_data[1] and ->description
|
||||
will be kfree()'d and the data attached to ->payload will be passed to the
|
||||
subtype's ->destroy() method to be disposed of. A module reference for
|
||||
the subtype pointed to by ->type_data[0] will be put.
|
||||
|
||||
|
||||
If the data format is not recognised, -EBADMSG should be returned. If it
|
||||
is recognised, but the key cannot for some reason be set up, some other
|
||||
negative error code should be returned. On success, 0 should be returned.
|
||||
|
||||
The key's fingerprint string may be partially matched upon. For a
|
||||
public-key algorithm such as RSA and DSA this will likely be a printable
|
||||
hex version of the key's fingerprint.
|
||||
|
||||
Functions are provided to register and unregister parsers:
|
||||
|
||||
int register_asymmetric_key_parser(struct asymmetric_key_parser *parser);
|
||||
void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype);
|
||||
|
||||
Parsers may not have the same name. The names are otherwise only used for
|
||||
displaying in debugging messages.
|
Загрузка…
Ссылка в новой задаче