|  | ============================================= | 
|  | 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. |