| ====================== |
| CRYPTOGRAPHIC KEY TYPE |
| ====================== |
| |
| Contents: |
| |
| - Overview. |
| - Key identification. |
| - Accessing crypto keys. |
| - Signature verification. |
| - Implementing crypto parsers. |
| - Implementing crypto subtypes. |
| - Initial PGP key preloading. |
| |
| |
| ======== |
| OVERVIEW |
| ======== |
| |
| The "crypto" key type is designed to be a container for cryptographic keys, |
| without imposing any particular restrictions on the form of the cryptography or |
| the key. |
| |
| The crypto 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 loaded into the key. |
| |
| The crypto key also has a number of data parsers registered with it. The data |
| parsers are responsible for extracing information the blobs of data passed to |
| the instantiator 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. |
| |
| Completely in-kernel key retention and operation subtypes and parsers 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 crypto key would then |
| merely be an interface to the TPM driver. |
| |
| |
| ================== |
| KEY IDENTIFICATION |
| ================== |
| |
| Because the identity of a key is not necessarily known and may not be easily |
| calculated when a crypto key is allocated, it may not be a simple matter to set |
| a key description to something that's useful for determining whether this is |
| the key you're looking for. Furthermore, it may be necessary to perform a |
| partial match upon the key identity. |
| |
| To help with this, when a key is loaded, the parser calculates the key |
| fingerprint and stores a copy in the key structure. |
| |
| The crypto key type's key matching function then performs more checks 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 crypto 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. dsa or rsa) will be matched. For |
| instance: |
| |
| keyctl search @s crypto dsa: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 crypto modsign.0: DSA 5acc2142 [] |
| |
| |
| ===================== |
| ACCESSING CRYPTO KEYS |
| ===================== |
| |
| To access crypto keys from within the kernel, the following inclusion is |
| required: |
| |
| #include <keys/crypto-type.h> |
| |
| This gives access to the key type: |
| |
| struct key_type key_type_crypto; |
| |
| |
| SIGNATURE VERIFICATION |
| ---------------------- |
| |
| The four operations that can perform cryptographic signature verification, |
| using one of a set of keys to provide the public key: |
| |
| (1) Begin verification procedure. |
| |
| struct crypto_key_verify_context * |
| verify_sig_begin(struct key *keyring, const void *sig, size_t siglen); |
| |
| This function sets up a verification context from the information in the |
| signature and looks for a suitable key in the keyring. The signature blob |
| must be presented again at the end of the procedure. The keys will be |
| checked against parameters in the signature, and if the matching one is |
| not found then -ENOKEY will be returned. |
| |
| The hashing algorithm, if such a thing applies, will be determined from |
| information in the signature and the appropriate crypto module will be |
| used. -ENOPKG will be returned if the hash algorithm is unavailable. |
| |
| The return value is an opaque pointer to be passed to the other functions, |
| or a negative error code. |
| |
| (2) Indicate data to be verified. |
| |
| int verify_sig_add_data(struct crypto_key_verify_context *ctx, |
| const void *data, size_t datalen); |
| |
| This function is used to shovel data to the verification procedure so that |
| it can load it into the hash, pass it to hardware or whatever is |
| appropriate for the algorithm being employed. |
| |
| The data is not canonicalised for the document type specified in the |
| signature. The caller must do that. |
| |
| It will return 0 if successful and a negative error code if not. |
| |
| (3) Complete the verification process. |
| |
| int verify_sig_end(struct crypto_key_verify_context *ctx, |
| const void *sig, size_t siglen); |
| |
| This function performs the actual signature verification step and cleans |
| up the resources allocated at the beginning. The signature must be |
| presented again as some of the data therein may need to be added to the |
| internal hash. |
| |
| It will return -EKEYREJECTED if the signature didn't match, 0 if |
| successful and may return other errors as appropriate. |
| |
| (4) Cancel the verification process. |
| |
| void verify_sig_cancel(struct crypto_key_verify_context *ctx); |
| |
| This function cleans up the resources allocated at the beginning. This is |
| not necessary if verify_sig_end() was called. |
| |
| |
| =========================== |
| IMPLEMENTING CRYPTO PARSERS |
| =========================== |
| |
| The crypto key type keeps a list of registered data parsers. An example of |
| such a parser is one that parses OpenPGP packet formatted data [RFC 4880]. |
| |
| During key instantiation each parser in the list is tried until one doesn't |
| return -EBADMSG. |
| |
| The parser definition structure looks like the following: |
| |
| struct crypto_key_parser { |
| struct module *owner; |
| const char *name; |
| |
| int (*instantiate)(struct key *key, |
| const void *data, size_t datalen); |
| struct crypto_key_verify_context *(*verify_sig_begin)( |
| struct key *keyring, const u8 *sig, size_t siglen); |
| }; |
| |
| The owner and name fields should be set to the owning module and the name of |
| the parser. |
| |
| There are a number of operations defined by the parser. They are all optional, |
| but it is expected that at least one will be defined. |
| |
| (1) instantiate(). |
| |
| The arguments are the same as for the instantiate function in the key |
| type. 'key' is the crypto key being instantiated; data and datalen are |
| the instantiation data, presumably containing cryptographic key data, and |
| the length of that data. |
| |
| 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. |
| |
| If the key can be successfully set up, then key->payload should be set to |
| point to the retained data, key->type_data.p[0] should be set to point to |
| the subtype chosen and key->type_data.p[1] should be set to point to a |
| copy of the key's identity string and 0 should be returned. |
| |
| The key's identity 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. |
| |
| (2) verify_sig_begin(). |
| |
| This is similar in concept to the instantiate() function, except that it |
| is given a signature blob to parse rather than a key data blob. |
| |
| If the data format is not recognised, -EBADMSG should be returned. If it |
| is recognised, but the signature verification process cannot for some |
| reason be set up, some other negative error code should be returned. |
| -ENOKEY should be used to indicate that no matching key is available and |
| -ENOPKG should be returned if the hash algorithm or the verification |
| algorithm are unavailable. |
| |
| If successful, the parser should allocate a verification context and embed |
| the following struct in it: |
| |
| struct crypto_key_verify_context { |
| struct key *key; |
| int (*add_data)(struct crypto_key_verify_context *ctx, |
| const void *data, size_t datalen); |
| int (*end)(struct crypto_key_verify_context *ctx, |
| const u8 *sig, size_t siglen); |
| void (*cancel)(struct crypto_key_verify_context *ctx); |
| }; |
| |
| and return a pointer to this to the caller, who will then pass it to the |
| verification operation wrappers described in the "Signature Verification" |
| section. The three operation pointers here correspond exactly to those |
| wrappers and are all mandatory. container_of() should be used to retrieve |
| the actual context. |
| |
| Note that the crypto key type retains a reference on the parser module for |
| the lifetime of this context, though the operation pointers need not point |
| into this module. |
| |
| The parser should also record a pointer to the key selected and take a |
| reference on that key with key_get(). |
| |
| |
| Functions are provided to register and unregister parsers: |
| |
| int register_crypto_key_parser(struct crypto_key_parser *parser); |
| void unregister_crypto_key_parser(struct crypto_key_parser *subtype); |
| |
| Parsers may not have the same name. The names are only used for displaying in |
| debugging messages. |
| |
| |
| ============================ |
| IMPLEMENTING CRYPTO SUBTYPES |
| ============================ |
| |
| The parser selects the appropriate subtype directly and sets it on the key; the |
| crypto key then retains a reference on the subtype module (which means the |
| parser can be removed thereafter). |
| |
| The subtype definition structure looks like the following: |
| |
| struct crypto_key_subtype { |
| struct module *owner; |
| const char *name; |
| |
| void (*describe)(const struct key *key, struct seq_file *m); |
| void (*destroy)(void *payload); |
| }; |
| |
| The owner and name fields should be set to the owning module and the name of |
| the subtype. |
| |
| 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 |
| crypto key will look after freeing the fingerprint and releasing the |
| reference on the subtype module. |
| |
| |
| ======================= |
| INITIAL PGP KEY LOADING |
| ======================= |
| |
| A function is provided to perform an initial load of a set of public keys bound |
| into a PGP packet format blob: |
| |
| int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen, |
| struct key *keyring); |
| |
| This takes the blob of data defined by pgpdata and pgpdatalen, extracts keys |
| from them and adds them to the specified keyring. The keys are labelled with a |
| description generated from the fingerprint and last user ID of each key. The |
| description is required to prevent all but the last key being discarded when |
| the keys are linked into the keyring. |
| |
| This function is only available during initial kernel set up. |