313 lines
		
	
	
	
		
			11 KiB
			
		
	
	
	
		
			Text
		
	
	
	
	
	
		
		
			
		
	
	
			313 lines
		
	
	
	
		
			11 KiB
			
		
	
	
	
		
			Text
		
	
	
	
	
	
| 
								 | 
							
										=============================================
							 | 
						||
| 
								 | 
							
										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.
							 |