MPILIB: Export some more symbols
Subsystems (14)
David Howells
maintainerPATCH 1/14 MPILIB: Export some more symbols
Export some more symbols for use by the DSA key subtype.
---
lib/mpi/mpi-cmp.c | 2 ++ lib/mpi/mpi-div.c | 1 + lib/mpi/mpi-inv.c | 1 + lib/mpi/mpi-mpow.c | 1 + lib/mpi/mpi-mul.c | 1 + 5 files changed, 6 insertions(+), 0 deletions(-)
lib/mpi/mpi-cmp.c +2 -0
@@ -39,6 +39,7 @@ int mpi_cmp_ui(MPI u, unsigned long v)else return -1 ; } +EXPORT_SYMBOL_GPL (mpi_cmp_ui);int mpi_cmp (MPI u,MPI v) {
@@ -66,3 +67,4 @@ int mpi_cmp(MPI u, MPI v)return 1 ;return -1 ; } +EXPORT_SYMBOL_GPL (mpi_cmp);
lib/mpi/mpi-div.c +1 -0
@@ -59,6 +59,7 @@ nomem:mpi_free (temp_divisor);return rc; } +EXPORT_SYMBOL_GPL (mpi_fdiv_r);/**************** * Division rounding the quotient towards -infinity.
lib/mpi/mpi-inv.c +1 -0
@@ -185,3 +185,4 @@ cleanup:mpi_free (v);return rc; } +EXPORT_SYMBOL_GPL (mpi_invm);
lib/mpi/mpi-mpow.c +1 -0
@@ -131,3 +131,4 @@ nomem:kfree (G );return rc; } +EXPORT_SYMBOL_GPL (mpi_mulpowm);
lib/mpi/mpi-mul.c +1 -0
@@ -192,3 +192,4 @@ int mpi_mulm(MPI w, MPI u, MPI v, MPI m)return -ENOMEM ;return mpi_fdiv_r (w, w, m); } +EXPORT_SYMBOL_GPL (mpi_mulm);
David Howells
maintainerPATCH 2/14 KEYS: Permit key_serial() to be called with a const key pointer
Permit key_serial() to be called with a const key pointer.
---
include/linux/key.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/key.h +1 -1
@@ -271,7 +271,7 @@ extern int keyring_add_key(struct key *keyring,extern struct key *key_lookup (key_serial_t id); -static inline key_serial_t key_serial (struct key *key) +static inline key_serial_t key_serial (const struct key *key) {return key ? key->serial :0 ; }
David Howells
maintainerPATCH 3/14 PGP: Add definitions (RFC 4880) and packet parser
In reply to David HowellsAdd some useful PGP definitions from RFC 4880. These describe details of public key crypto as used by crypto keys for things like signature verification.
Also add a simple parser that extracts the packets from a PGP blob and passes the desirous ones to the given processor function:
struct pgp_parse_context {
u64 types_of_interest;
int (*process_packet)(struct pgp_parse_context *context,
enum pgp_packet_tag type,
u8 headerlen,
const u8 *data,
size_t datalen);
};
int pgp_parse_packets(const u8 *data, size_t datalen,
struct pgp_parse_context *ctx);---
include/linux/pgp.h | 230 +++++++++++++++++++++++++++++++++++++++++ security/keys/pgp_parse.c | 254 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 484 insertions(+), 0 deletions(-) create mode 100644 include/linux/pgp.h create mode 100644 security/keys/pgp_parse.c
include/linux/pgp.h new file +230 -0
@@ -0,0 +1,230 @@ +/* PGP definitions (RFC 4880) +* +* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +*/ + +#ifndef _LINUX_PGP_H +#define _LINUX_PGP_H + +#include <linux/types.h> + +struct pgp_key_ID { +u8 id[8 ]; +}; + +struct pgp_time { +u8 time[4 ]; +}; + +/* +* PGP public-key algorithm identifiers [RFC4880: 9.1] +*/ +enum pgp_pubkey_algo { +PGP_PUBKEY_RSA_ENC_OR_SIG =1 , +PGP_PUBKEY_RSA_ENC_ONLY =2 , +PGP_PUBKEY_RSA_SIG_ONLY =3 , +PGP_PUBKEY_ELGAMAL =16 , +PGP_PUBKEY_DSA =17 , +}; + +/* +* PGP symmetric-key algorithm identifiers [RFC4880: 9.2] +*/ +enum pgp_symkey_algo { +PGP_SYMKEY_PLAINTEXT =0 , +PGP_SYMKEY_IDEA =1 , +PGP_SYMKEY_3DES =2 , +PGP_SYMKEY_CAST5 =3 , +PGP_SYMKEY_BLOWFISH =4 , +PGP_SYMKEY_AES_128KEY =7 , +PGP_SYMKEY_AES_192KEY =8 , +PGP_SYMKEY_AES_256KEY =9 , +PGP_SYMKEY_TWOFISH_256KEY =10 , +}; + +/* +* PGP compression algorithm identifiers [RFC4880: 9.3] +*/ +enum pgp_compr_algo { +PGP_COMPR_UNCOMPRESSED =0 , +PGP_COMPR_ZIP =1 , +PGP_COMPR_ZLIB =2 , +PGP_COMPR_BZIP2 =3 , +}; + +/* +* PGP hash algorithm identifiers [RFC4880: 9.4] +*/ +enum pgp_hash_algo { +PGP_HASH_MD5 =1 , +PGP_HASH_SHA1 =2 , +PGP_HASH_RIPE_MD_160 =3 , +PGP_HASH_SHA256 =8 , +PGP_HASH_SHA384 =9 , +PGP_HASH_SHA512 =10 , +PGP_HASH_SHA224 =11 , +PGP_HASH__LAST +}; + +extern const char *const pgp_hash_algorithms[PGP_HASH__LAST ]; + +/* +* PGP packet type tags [RFC4880: 4.3]. +*/ +enum pgp_packet_tag { +PGP_PKT_RESERVED =0 , +PGP_PKT_PUBKEY_ENC_SESSION_KEY =1 , +PGP_PKT_SIGNATURE =2 , +PGP_PKT_SYMKEY_ENC_SESSION_KEY =3 , +PGP_PKT_ONEPASS_SIGNATURE =4 , +PGP_PKT_SECRET_KEY =5 , +PGP_PKT_PUBLIC_KEY =6 , +PGP_PKT_SECRET_SUBKEY =7 , +PGP_PKT_COMPRESSED_DATA =8 , +PGP_PKT_SYM_ENC_DATA =9 , +PGP_PKT_MARKER =10 , +PGP_PKT_LITERAL_DATA =11 , +PGP_PKT_TRUST =12 , +PGP_PKT_USER_ID =13 , +PGP_PKT_PUBLIC_SUBKEY =14 , +PGP_PKT_USER_ATTRIBUTE =17 , +PGP_PKT_SYM_ENC_AND_INTEG_DATA =18 , +PGP_PKT_MODIFY_DETECT_CODE =19 , +PGP_PKT_PRIVATE_0 =60 , +PGP_PKT_PRIVATE_3 =63 , +PGP_PKT__HIGHEST =63 +}; + +/* +* Signature (tag 2) packet [RFC4880: 5.2]. +*/ +enum pgp_signature_version { +PGP_SIG_VERSION_3 =3 , +PGP_SIG_VERSION_4 =4 , +}; + +enum pgp_signature_type { +PGP_SIG_BINARY_DOCUMENT_SIG =0x00 , +PGP_SIG_CANONICAL_TEXT_DOCUMENT_SIG =0x01 , +PGP_SIG_STANDALONE_SIG =0x02 , +PGP_SIG_GENERAL_CERT_OF_UID_PUBKEY =0x10 , +PGP_SIG_PERSONAL_CERT_OF_UID_PUBKEY =0x11 , +PGP_SIG_CASUAL_CERT_OF_UID_PUBKEY =0x12 , +PGP_SIG_POSTITIVE_CERT_OF_UID_PUBKEY =0x13 , +PGP_SIG_SUBKEY_BINDING_SIG =0x18 , +PGP_SIG_PRIMARY_KEY_BINDING_SIG =0x19 , +PGP_SIG_DIRECTLY_ON_KEY =0x1F , +PGP_SIG_KEY_REVOCATION_SIG =0x20 , +PGP_SIG_SUBKEY_REVOCATION_SIG =0x28 , +PGP_SIG_CERT_REVOCATION_SIG =0x30 , +PGP_SIG_TIMESTAMP_SIG =0x40 , +PGP_SIG_THIRD_PARTY_CONFIRM_SIG =0x50 , +}; + +struct pgp_signature_v3_packet { +enum pgp_signature_version version :8 ;/* == PGP_SIG_VERSION_3 */ +u8 length_of_hashed;/* == 5 */ +struct { +enum pgp_signature_type signature_type :8 ; +struct pgp_time creation_time; + } hashed; +struct pgp_key_ID issuer; +enum pgp_pubkey_algo pubkey_algo :8 ; +enum pgp_hash_algo hash_algo :8 ; +}; + +struct pgp_signature_v4_packet { +enum pgp_signature_version version :8 ;/* == PGP_SIG_VERSION_4 */ +enum pgp_signature_type signature_type :8 ; +enum pgp_pubkey_algo pubkey_algo :8 ; +enum pgp_hash_algo hash_algo :8 ; +}; + +/* +* V4 signature subpacket types [RFC4880: 5.2.3.1]. +*/ +enum pgp_sig_subpkt_type { +PGP_SIG_CREATION_TIME =2 , +PGP_SIG_EXPIRATION_TIME =3 , +PGP_SIG_EXPORTABLE_CERT =4 , +PGP_SIG_TRUST_SIG =5 , +PGP_SIG_REGEXP =6 , +PGP_SIG_REVOCABLE =7 , +PGP_SIG_KEY_EXPIRATION_TIME =9 , +PGP_SIG_PREF_SYM_ALGO =11 , +PGP_SIG_REVOCATION_KEY =12 , +PGP_SIG_ISSUER =16 , +PGP_SIG_NOTATION_DATA =20 , +PGP_SIG_PREF_HASH_ALGO =21 , +PGP_SIG_PREF_COMPR_ALGO =22 , +PGP_SIG_KEY_SERVER_PREFS =23 , +PGP_SIG_PREF_KEY_SERVER =24 , +PGP_SIG_PRIMARY_USER_ID =25 , +PGP_SIG_POLICY_URI =26 , +PGP_SIG_KEY_FLAGS =27 , +PGP_SIG_SIGNERS_USER_ID =28 , +PGP_SIG_REASON_FOR_REVOCATION =29 , +PGP_SIG_FEATURES =30 , +PGP_SIG_TARGET =31 , +PGP_SIG_EMBEDDED_SIG =32 , +PGP_SIG__LAST +}; + +#define PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK 0x80 + +/* +* Key (tag 5, 6, 7 and 14) packet +*/ +enum pgp_key_version { +PGP_KEY_VERSION_2 =2 , +PGP_KEY_VERSION_3 =3 , +PGP_KEY_VERSION_4 =4 , +}; + +struct pgp_key_v3_packet { +enum pgp_key_version version :8 ; +struct pgp_time creation_time; +u8 expiry[2 ];/* 0 or time in days till expiry */ +enum pgp_pubkey_algo pubkey_algo :8 ; +u8 key_material[0 ]; +}; + +struct pgp_key_v4_packet { +enum pgp_key_version version :8 ; +struct pgp_time creation_time; +enum pgp_pubkey_algo pubkey_algo :8 ; +u8 key_material[0 ]; +}; + +/* +* PGP packet parser +*/ +struct pgp_parse_context { +u64 types_of_interest; +int (*process_packet)(struct pgp_parse_context *context, +enum pgp_packet_tag type, +u8 headerlen, +const u8 *data, +size_t datalen); +}; + +extern int pgp_parse_packets (const u8 *data,size_t datalen, +struct pgp_parse_context *ctx); + +struct pgp_parse_pubkey { +enum pgp_key_version version :8 ; +enum pgp_pubkey_algo pubkey_algo :8 ; +time_t creation_time; +time_t expires_at; +}; + +extern int pgp_parse_public_key (const u8 **_data,size_t *_datalen, +struct pgp_parse_pubkey *pk); + +#endif /* _LINUX_PGP_H */
security/keys/pgp_parse.c new file +254 -0
254 lines not on this page · raw message
David Howells
maintainerPATCH 4/14 KEYS: Create a key type that can be used for general cryptographic operations
In reply to David HowellsCreate a key type that can be used for general cryptographic operations, such as encryption, decryption, signature generation and signature verification.
The key type is "crypto" and can provide access to a variety of cryptographic algorithms.
---
Documentation/security/keys-crypto.txt | 170 +++++++++++++++++ include/keys/crypto-subtype.h | 46 +++++ include/keys/crypto-type.h | 25 ++ security/Kconfig | 8 + security/keys/Makefile | 3 security/keys/crypto_keys.h | 21 ++ security/keys/crypto_type.c | 322 ++++++++++++++++++++++++++++++++ 7 files changed, 595 insertions(+), 0 deletions(-) create mode 100644 Documentation/security/keys-crypto.txt create mode 100644 include/keys/crypto-subtype.h create mode 100644 include/keys/crypto-type.h create mode 100644 security/keys/crypto_keys.h create mode 100644 security/keys/crypto_type.c
Documentation/security/keys-crypto.txt new file +170 -0
@@ -0,0 +1,170 @@ + ====================== + CRYPTOGRAPHIC KEY TYPE + ====================== + +Contents: + + - Overview. + - Key identification. + - Crypto subtypes. + - Accessing crypto keys. + - Implementing crypto subtypes. + + +======== +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 what operations might be performed with it. However, no +requirement is made that the key data actually be loaded into the key or that +the operations are done by the kernel. + +For instance, cryptographic hardware (such as a TPM) might be used to both +retain the relevant key and provide 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 or is not 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 key subtype's instantiation +routine calculates the key fingerprint and stores a copy in the key struct. + +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 [] + + +=============== +CRYPTO SUBTYPES +=============== + +The crypto key is just a simple container. It contains no data of its own and +does very little except provide a place to hang a function pointer table. The +key subtype does the actual work. + +When a crypto key is instantiated, it looks through its list of registered +subtypes to try and find one that can handle the data blob it is given. If the +data blob begins with a byte with the top bit set, it is assumed to be a PGP +packet format blob [RFC 4880] and is treated so. The blob is parsed to find a +PGP key, and then a subtype is looked for that says it can handle the +appropriate algorithm type. + + +===================== +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; + + +============================ +IMPLEMENTING CRYPTO SUBTYPES +============================ + +If a suitable subtype is found, then key->type_data.p[0] is set to point to the +subtype definition and the module usage count is incremented. + +The subtype definition structure looks like the following: + + struct crypto_key_subtype { + struct module *owner; + const char *name; + enum pgp_pubkey_algo pubkey_algo : 8; + unsigned short info; + + int (*instantiate)(struct key *key, + const void *data, size_t datalen); + + void (*revoke)(struct key *key); + void (*destroy)(struct key *key); + }; + +The owner and name fields should be set to the owning module and the name of +the subtype. + +If the subtype represents a PGP public key algorithm the info field should have +CRYPTO_KEY_IS_PUBKEY_ALGO OR'd into it and pubkey_algo should be set to the +appropriate PGP_PUBKEY_ constant from the enumeration in <linux/pgp.h>. + + +There are a number of operations defined by the subtype. The first few are for +management of the key itself: + + (1) instantiate(). + + Mandatory. When the subtype is selected, the instantiate() method will be + given the key being instantiated and the data blob. If the first byte of + the data blob has bit 7 set, then it's a PGP packet blob and can be parsed + with the routines declared in <linux/pgp.h>. + + If the key has a fingerprint or other auxiliary identifier, this should be + determined or calculated and a copy attached to key->type_data.p[1]. + + If successful, the subtype must set key->type_data.p[0] to point to its + definition. + + The subtype may use key->payload in anyway it sees fit. + + (2) revoke(). + + Optional. Notification that the key has been revoked. This provides the + subtype the opportunity to discard some memory, but care should be taken + as the key may be in use when this is called. + + (3) destroy(). + + Mandatory. key->type_data.p[0] is cleared by the caller and the module + usage will be decremented upon return. The memory pointed to by + key->type_data.[1] will be freed after this method returns. This method + must free whatever key->payload refers to. + + +Functions are provided to register and unregister key subtypes: + + int register_crypto_key_subtype(struct crypto_key_subtype *subtype); + void unregister_crypto_key_subtype(struct crypto_key_subtype *subtype); + +Key subtypes may have the same name, provided they differ in some other +criterion, such as the public key algorithm ID. This makes it possible to +handle algorithms such as RSA that have multiple algorithm IDs.
include/keys/crypto-subtype.h new file +46 -0
46 lines not on this page · raw message
include/keys/crypto-type.h new file +25 -0
@@ -0,0 +1,25 @@ +/* Cryptographic key type interface +* +* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +* +* See Documentation/security/keys-crypto.txt +*/ + +#ifndef _KEYS_CRYPTO_TYPE_H +#define _KEYS_CRYPTO_TYPE_H + +#include <linux/key-type.h> + +extern struct key_type key_type_crypto; + +/* +* The payload is at the discretion of the subtype. +*/ + +#endif /* _KEYS_CRYPTO_TYPE_H */
security/Kconfig +8 -0
@@ -54,6 +54,14 @@ config ENCRYPTED_KEYS If you are unsure as to whether this is required, answer N. +config CRYPTO_KEY_TYPE + tristate "Cryptographic key type" + depends on KEYS + help + This option provides support for a type of key that holds the keys + required for cryptographic operations such as encryption, decryption, + signature generation and signature verification. + config KEYS_DEBUG_PROC_KEYS bool "Enable the /proc/keys file by which keys may be viewed" depends on KEYS
security/keys/Makefile +3 -0
@@ -15,6 +15,9 @@ obj-y := \ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ +obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o + +crypto_keys-y := crypto_type.o pgp_parse.o
security/keys/crypto_keys.h new file +21 -0
@@ -0,0 +1,21 @@ +/* Internal crypto type stuff +* +* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +*/ + +static inline +struct crypto_key_subtype *crypto_key_subtype (const struct key *key) +{ +return key->type_data.p[0 ]; +} + +static inline char *crypto_key_id (const struct key *key) +{ +return key->type_data.p[1 ]; +}
security/keys/crypto_type.c new file +322 -0
322 lines not on this page · raw message
David Howells
maintainerPATCH 5/14 KEYS: Add a DSA crypto key subtype
In reply to David HowellsAdd a key subtype for handling DSA crypto keys. For the moment it only provides a signature verification facility.
---
security/Kconfig | 10 + security/keys/Makefile | 2 security/keys/crypto_dsa.h | 36 ++++ security/keys/crypto_dsa_subtype.c | 338 ++++++++++++++++++++++++++++++++++++ 4 files changed, 386 insertions(+), 0 deletions(-) create mode 100644 security/keys/crypto_dsa.h create mode 100644 security/keys/crypto_dsa_subtype.c
security/Kconfig +10 -0
@@ -62,6 +62,16 @@ config CRYPTO_KEY_TYPE required for cryptographic operations such as encryption, decryption, signature generation and signature verification. +config CRYPTO_KEY_DSA + tristate "DSA key type" + depends on CRYPTO_KEY_TYPE + select CRYPTO + select MPILIB + select MPILIB_EXTRA + help + This option makes DSA cryptographic keys available. They can be used + for signature verification. + config KEYS_DEBUG_PROC_KEYS bool "Enable the /proc/keys file by which keys may be viewed" depends on KEYS
security/keys/Makefile +2 -0
@@ -16,8 +16,10 @@ obj-y := \ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o +obj-$(CONFIG_CRYPTO_KEY_DSA) += crypto_dsa.o obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o crypto_keys-y := crypto_type.o pgp_parse.o +crypto_dsa-y := crypto_dsa_subtype.o
security/keys/crypto_dsa.h new file +36 -0
@@ -0,0 +1,36 @@ +/* DSA internal definitions +* +* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +*/ + +#define DSA_NPKEY 4/* number of MPI's in DSA public key */ + +extern struct crypto_key_subtype DSA_crypto_key_subtype; + +/* +* public key record +*/ +struct DSA_public_key { +struct pgp_parse_pubkey pgp; +union { +MPI pkey[DSA_NPKEY ]; +struct { +MPI p;/* DSA prime */ +MPI q;/* DSA group order */ +MPI g;/* DSA group generator */ +MPI y;/* DSA public-key value = g^x mod p */ + }; + }; +}; + +struct DSA_payload { +u8 key_id[8 ];/* ID of this key pair */ +u8 key_id_size;/* Number of bytes in key_id */ +struct DSA_public_key *public_key; +};
security/keys/crypto_dsa_subtype.c new file +338 -0
338 lines not on this page · raw message
David Howells
maintainerPATCH 6/14 KEYS: Add a RSA crypto key subtype
In reply to David HowellsAdd a key subtype for handling RSA crypto keys. For the moment it only provides a signature verification facility.
---
security/Kconfig | 9 + security/keys/Makefile | 1 security/keys/crypto_rsa.c | 394 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 404 insertions(+), 0 deletions(-) create mode 100644 security/keys/crypto_rsa.c
security/Kconfig +9 -0
@@ -72,6 +72,15 @@ config CRYPTO_KEY_DSA This option makes DSA cryptographic keys available. They can be used for signature verification. +config CRYPTO_KEY_RSA + tristate "RSA key type" + depends on CRYPTO_KEY_TYPE + select CRYPTO + select MPILIB + help + This option makes RSA cryptographic keys available. They can be used + for signature verification. + config KEYS_DEBUG_PROC_KEYS bool "Enable the /proc/keys file by which keys may be viewed" depends on KEYS
security/keys/Makefile +1 -0
@@ -17,6 +17,7 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o obj-$(CONFIG_CRYPTO_KEY_DSA) += crypto_dsa.o +obj-$(CONFIG_CRYPTO_KEY_RSA) += crypto_rsa.o obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o
security/keys/crypto_rsa.c new file +394 -0
394 lines not on this page · raw message
David Howells
maintainerPATCH 7/14 PGP: Add signature parser
In reply to David HowellsAdd some PGP signature parsing helpers:
(1) A function to parse V4 signature subpackets and pass the desired ones to a processor function:
int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
struct pgp_parse_sig_context *ctx);
(2) A function to parse out basic signature parameters from any PGP signature such that the algorithms and public key can be selected:
int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
struct pgp_sig_parameters *p);
---
include/linux/pgp.h | 24 ++++ security/keys/pgp_parse.c | 274 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+), 0 deletions(-)
include/linux/pgp.h +24 -0
@@ -227,4 +227,28 @@ struct pgp_parse_pubkey {extern int pgp_parse_public_key (const u8 **_data,size_t *_datalen,struct pgp_parse_pubkey *pk); +struct pgp_parse_sig_context { +unsigned long types_of_interest[128 /BITS_PER_LONG ]; +int (*process_packet)(struct pgp_parse_sig_context *context, +enum pgp_sig_subpkt_type type, +const u8 *data, +size_t datalen); +}; + +extern int pgp_parse_sig_packets (const u8 *data,size_t datalen, +struct pgp_parse_sig_context *ctx); + +struct pgp_sig_parameters { +enum pgp_signature_type signature_type :8 ; +union { +struct pgp_key_ID issuer; +__be32 issuer32[2 ]; + }; +enum pgp_pubkey_algo pubkey_algo :8 ; +enum pgp_hash_algo hash_algo :8 ; +}; + +extern int pgp_parse_sig_params (const u8 **_data,size_t *_datalen, +struct pgp_sig_parameters *p); +#endif /* _LINUX_PGP_H */
security/keys/pgp_parse.c +274 -0
277 lines not on this page · raw message
David Howells
maintainerPATCH 8/14 KEYS: Add signature verification facility
In reply to David HowellsAdd a facility whereby a key subtype may be asked to verify a signature against the data it is purported to have signed.
---
Documentation/security/keys-crypto.txt | 106 +++++++++++++++++++++++++++++++- include/keys/crypto-subtype.h | 15 +++++ include/keys/crypto-type.h | 9 +++ security/keys/Makefile | 2 - security/keys/crypto_verify.c | 87 ++++++++++++++++++++++++++ 5 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 security/keys/crypto_verify.c
Documentation/security/keys-crypto.txt +102 -4
@@ -8,7 +8,9 @@ Contents: - Key identification. - Crypto subtypes. - Accessing crypto keys. + - Signature verification. - Implementing crypto subtypes. + - Registration. ========
@@ -98,14 +100,69 @@ 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 a key to provide the public key: + + (1) Begin verification procedure. + + struct crypto_key_verify_context * + verify_sig_begin(struct key *key, const void *sig, size_t siglen); + + This function sets up a verification context from the specified key and + the signature blob. The signature blob must be presented again at the end + of the procedure. The key is checked against parameters in the signature, + and if it's not the right key then an error will be given. + + If such a thing applies, the hashing algorithm, will be extracted from 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 SUBTYPES ============================ -If a suitable subtype is found, then key->type_data.p[0] is set to point to the -subtype definition and the module usage count is incremented. - -The subtype definition structure looks like the following: +Each subtype is specified through a definition structure: struct crypto_key_subtype { struct module *owner;
@@ -118,6 +175,14 @@ The subtype definition structure looks like the following: void (*revoke)(struct key *key); void (*destroy)(struct key *key); + + struct crypto_key_verify_context *(*verify_sig_begin)( + struct key *key, const u8 *sig, size_t siglen); + int (*verify_sig_add_data)(struct crypto_key_verify_context *ctx, + const void *data, size_t datalen); + int (*verify_sig_end)(struct crypto_key_verify_context *ctx, + const u8 *sig, size_t siglen); + void (*verify_sig_cancel)(struct crypto_key_verify_context *ctx); }; The owner and name fields should be set to the owning module and the name of
@@ -160,6 +225,39 @@ management of the key itself: must free whatever key->payload refers to. +There are then sets of method pointers to actually use the key for things: + + (*) Signature verification + + Then there are functions to verify a signature using the public key stored in + this key: + + (1) verify_sig_begin(). + (2) verify_sig_add_data(). + (3) verify_sig_end(). + (4) verify_sig_cancel(). + + These correspond to the accessor functions mentioned in the previous + section. The first function is optional - if it is not provided, then + verification is not a service available with this key. The other three + are mandatory if the first is supplied and unnecessary otherwise. + + The subtype should allocate a context in ->verify_sig_begin() and embed + the following struct in it: + + struct crypto_key_verify_context { + struct key *key; + }; + + A pointer to this struct is then returned to the caller. This is used by + the master routines to route the operations to the right place. This is + passed to the _add_data, _end and _cancel routines - which should use + container_of() on it to get the full context. + + +REGISTRATION +------------ + Functions are provided to register and unregister key subtypes: int register_crypto_key_subtype(struct crypto_key_subtype *subtype);
include/keys/crypto-subtype.h +15 -0
@@ -20,6 +20,14 @@extern struct key_type key_type_crypto;/* +* Context base for signature verification methods. Allocated by the subtype +* and presumably embedded in something appropriate. +*/ +struct crypto_key_verify_context { +struct key *key; +}; + +/* * Keys of this type declare a subtype that indicates the handlers and * capabilities. */
@@ -38,6 +46,13 @@ struct crypto_key_subtype {void (*revoke)(struct key *key);void (*destroy)(struct key *key); +struct crypto_key_verify_context *(*verify_sig_begin)( +struct key *key,const u8 *sig,size_t siglen); +int (*verify_sig_add_data)(struct crypto_key_verify_context *ctx, +const void *data,size_t datalen); +int (*verify_sig_end)(struct crypto_key_verify_context *ctx, +const u8 *sig,size_t siglen); +void (*verify_sig_cancel)(struct crypto_key_verify_context *ctx); };extern int register_crypto_key_subtype (struct crypto_key_subtype *);
include/keys/crypto-type.h +9 -0
@@ -18,6 +18,15 @@extern struct key_type key_type_crypto; +struct crypto_key_verify_context ; +extern struct crypto_key_verify_context *verify_sig_begin ( +struct key *key,const void *sig,size_t siglen); +extern int verify_sig_add_data (struct crypto_key_verify_context *ctx, +const void *data,size_t datalen); +extern int verify_sig_end (struct crypto_key_verify_context *ctx, +const void *sig,size_t siglen); +extern void verify_sig_cancel (struct crypto_key_verify_context *ctx); +/* * The payload is at the discretion of the subtype. */
security/keys/Makefile +1 -1
@@ -22,5 +22,5 @@ obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o -crypto_keys-y := crypto_type.o pgp_parse.o +crypto_keys-y := crypto_type.o pgp_parse.o crypto_verify.o crypto_dsa-y := crypto_dsa_subtype.o
security/keys/crypto_verify.c new file +87 -0
87 lines not on this page · raw message
David Howells
maintainerPATCH 9/14 KEYS: DSA key signature verification
In reply to David HowellsSignature verification routines for DSA crypto key subtype.
---
security/keys/Makefile | 2 security/keys/crypto_dsa.h | 11 + security/keys/crypto_dsa_verify.c | 375 +++++++++++++++++++++++++++++++++++++ 3 files changed, 387 insertions(+), 1 deletions(-) create mode 100644 security/keys/crypto_dsa_verify.c
security/keys/Makefile +1 -1
@@ -23,4 +23,4 @@ obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o crypto_keys-y := crypto_type.o pgp_parse.o crypto_verify.o -crypto_dsa-y := crypto_dsa_subtype.o +crypto_dsa-y := crypto_dsa_subtype.o crypto_dsa_verify.o
security/keys/crypto_dsa.h +11 -0
@@ -34,3 +34,14 @@ struct DSA_payload {u8 key_id_size;/* Number of bytes in key_id */ struct DSA_public_key *public_key; }; + +/* +* crypto_dsa_verify.c +*/ +extern struct crypto_key_verify_context *DSA_verify_sig_begin ( +struct key *key,const u8 *sig,size_t siglen); +extern int DSA_verify_sig_add_data (struct crypto_key_verify_context *ctx, +const void *data,size_t datalen); +extern int DSA_verify_sig_end (struct crypto_key_verify_context *ctx, +const u8 *sig,size_t siglen); +extern void DSA_verify_sig_cancel (struct crypto_key_verify_context *ctx);
security/keys/crypto_dsa_verify.c new file +375 -0
375 lines not on this page · raw message
David Howells
maintainerPATCH 10/14 KEYS: Add a crypto key request function
In reply to David HowellsAdd a function by which crypto keys can be requested. A keyring is supplied for the function to search (which can be, say, a system keyring containing keys for kernel module signature checking). The function also provides a point at which hardware key caches, such as a TPM, can be consulted.
---
Documentation/security/keys-crypto.txt | 12 ++++ include/keys/crypto-type.h | 3 + security/keys/Makefile | 2 - security/keys/crypto_request.c | 94 ++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletions(-) create mode 100644 security/keys/crypto_request.c
Documentation/security/keys-crypto.txt +12 -0
@@ -158,6 +158,18 @@ using a key to provide the public key: not necessary if verify_sig_end() was called. +To find a key to use for signature verification, the following function may be +called: + + struct key *request_crypto_key_for_PGP_sig(struct key *keyring, + const u8 *sig, size_t siglen); + +This parses the specified signature blob to find the signing key identity and +then searches the given keyring for a matching key. It may also examine a +hardware keystore (such as a TPM) for a usable signature matching service and +generate a key to provide an access method to that service. + + ============================ IMPLEMENTING CRYPTO SUBTYPES ============================
include/keys/crypto-type.h +3 -0
@@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_key_verify_context *ctx);* The payload is at the discretion of the subtype. */ +extern struct key *request_crypto_key_for_PGP_sig (struct key *keyring, +const u8 *sig,size_t siglen); +#endif /* _KEYS_CRYPTO_TYPE_H */
security/keys/Makefile +1 -1
@@ -22,5 +22,5 @@ obj-$(CONFIG_KEYS_COMPAT) += compat.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSCTL) += sysctl.o -crypto_keys-y := crypto_type.o pgp_parse.o crypto_verify.o +crypto_keys-y := crypto_type.o pgp_parse.o crypto_verify.o crypto_request.o crypto_dsa-y := crypto_dsa_subtype.o crypto_dsa_verify.o
security/keys/crypto_request.c new file +94 -0
94 lines not on this page · raw message
David Howells
maintainerPATCH 11/14 KEYS: Provide a function to load keys from a PGP keyring blob
In reply to David HowellsProvide a function to load keys from a PGP keyring blob for use in initialising the module signing key keyring:
int load_PGP_keys(const u8 *pgpdata, size_t pgpdatalen, struct key *keyring, const char *descprefix);
The keys are labelled with descprefix plus a number to uniquify them. The keys will actually be identified by the ID calculated from the PGP data rather than by the description, so this shouldn't be a problem.
The keys are attached to the keyring supplied.
Looking as root in /proc/keys after the module signing keyring has been loaded:
24460d1c I----- 1 perm 3f010000 0 0 crypto modsign.0: dsa 5acc2142 [] 3ca85723 I----- 1 perm 1f010000 0 0 keyring .module_sign: 1/4
---
Documentation/security/keys-crypto.txt | 19 ++++++++ include/keys/crypto-type.h | 3 + security/keys/crypto_request.c | 73 ++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 0 deletions(-)
Documentation/security/keys-crypto.txt +19 -0
@@ -9,6 +9,7 @@ Contents: - Crypto subtypes. - Accessing crypto keys. - Signature verification. + - Initial pgp key loading. - Implementing crypto subtypes. - Registration.
@@ -170,6 +171,24 @@ hardware keystore (such as a TPM) for a usable signature matching service and generate a key to provide an access method to that service. +INITIAL PGP KEY LOADING +----------------------- + +A function is provided to perform an initial load of a set of public keys bound +into a PGP keyring blob: + + int load_PGP_keys(const u8 *pgpdata, size_t pgpdatalen, + struct key *keyring, const char *descprefix); + +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 +descprefix plus a simple uniquifier - it is not expected that the description +will be used to identify the 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. + + ============================ IMPLEMENTING CRYPTO SUBTYPES ============================
include/keys/crypto-type.h +3 -0
@@ -34,4 +34,7 @@ extern void verify_sig_cancel(struct crypto_key_verify_context *ctx);extern struct key *request_crypto_key_for_PGP_sig (struct key *keyring,const u8 *sig,size_t siglen); +extern __init int load_PGP_keys (const u8 *pgpdata,size_t pgpdatalen, +struct key *keyring,const char *descprefix); +#endif /* _KEYS_CRYPTO_TYPE_H */
security/keys/crypto_request.c +73 -0
76 lines not on this page · raw message
David Howells
maintainerPATCH 12/14 MODSIGN: Add indications of module ELF types
In reply to David HowellsAdd per-arch indications of module ELF types and relocation table entry types.
---
arch/alpha/include/asm/module.h | 3 +++ arch/arm/include/asm/module.h | 5 +++++ arch/cris/include/asm/module.h | 5 +++++ arch/h8300/include/asm/module.h | 5 +++++ arch/ia64/include/asm/module.h | 5 +++++ arch/m32r/include/asm/module.h | 5 +++++ arch/m68k/include/asm/module.h | 5 +++++ arch/mips/include/asm/module.h | 12 ++++++++++-- arch/parisc/include/asm/module.h | 8 ++++++++ arch/powerpc/include/asm/module.h | 10 ++++++++++ arch/s390/include/asm/module.h | 3 +++ include/asm-generic/module.h | 10 ++++++++++ 12 files changed, 74 insertions(+), 2 deletions(-)
arch/alpha/include/asm/module.h +3 -0
@@ -6,6 +6,7 @@ struct mod_arch_specificunsigned int gotsecindex; }; +#define MODULES_ARE_ELF64 #define Elf_Sym Elf64_Sym#define Elf_Shdr Elf64_Shdr#define Elf_Ehdr Elf64_Ehdr
@@ -13,6 +14,8 @@ struct mod_arch_specific#define Elf_Dyn Elf64_Dyn#define Elf_Rel Elf64_Rel#define Elf_Rela Elf64_Rela +#define ELF_R_TYPE (X ) ELF64_R_TYPE(X) +#define ELF_R_SYM (X ) ELF64_R_SYM(X)#define ARCH_SHF_SMALL SHF_ALPHA_GPREL
arch/arm/include/asm/module.h +5 -0
@@ -1,9 +1,14 @@#ifndef _ASM_ARM_MODULE_H#define _ASM_ARM_MODULE_H +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)struct unwind_table ;
arch/cris/include/asm/module.h +5 -0
@@ -3,7 +3,12 @@/* cris is simple */ struct mod_arch_specific { }; +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#endif /* _ASM_CRIS_MODULE_H */
arch/h8300/include/asm/module.h +5 -0
@@ -4,8 +4,13 @@* This file contains the H8/300 architecture specific module code. */ struct mod_arch_specific { }; +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#endif /* _ASM_H8/300_MODULE_H */
arch/ia64/include/asm/module.h +5 -0
@@ -29,9 +29,14 @@ struct mod_arch_specific {unsigned int next_got_entry;/* index of next available got entry */ }; +#define MODULES_ARE_ELF64 #define Elf_Shdr Elf64_Shdr#define Elf_Sym Elf64_Sym#define Elf_Ehdr Elf64_Ehdr +#define Elf_Rel Elf64_Rel +#define Elf_Rela Elf64_Rela +#define ELF_R_TYPE (X ) ELF64_R_TYPE(X) +#define ELF_R_SYM (X ) ELF64_R_SYM(X)#define MODULE_PROC_FAMILY "ia64"#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY \
arch/m32r/include/asm/module.h +5 -0
@@ -3,8 +3,13 @@struct mod_arch_specific { }; +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#endif /* _ASM_M32R_MODULE_H */
arch/m68k/include/asm/module.h +5 -0
@@ -36,8 +36,13 @@ struct module;extern void module_fixup (struct module *mod,struct m68k_fixup_info *start,struct m68k_fixup_info *end); +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#endif /* _ASM_M68K_MODULE_H */
arch/mips/include/asm/module.h +10 -2
@@ -33,11 +33,15 @@ typedef struct { } Elf64_Mips_Rela;#ifdef CONFIG_32BIT - +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr#define Elf_Addr Elf32_Addr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#define Elf_Mips_Rel Elf32_Rel#define Elf_Mips_Rela Elf32_Rela
@@ -48,11 +52,15 @@ typedef struct {#endif #ifdef CONFIG_64BIT - +#define MODULES_ARE_ELF64 #define Elf_Shdr Elf64_Shdr#define Elf_Sym Elf64_Sym#define Elf_Ehdr Elf64_Ehdr#define Elf_Addr Elf64_Addr +#define Elf_Rel Elf64_Rel +#define Elf_Rela Elf64_Rela +#define ELF_R_TYPE (X ) ELF64_R_TYPE(X) +#define ELF_R_SYM (X ) ELF64_R_SYM(X)#define Elf_Mips_Rel Elf64_Mips_Rel#define Elf_Mips_Rela Elf64_Mips_Rela
arch/parisc/include/asm/module.h +8 -0
@@ -4,17 +4,25 @@* This file contains the parisc architecture specific module code. */ #ifdef CONFIG_64BIT +#define MODULES_ARE_ELF64 #define Elf_Shdr Elf64_Shdr#define Elf_Sym Elf64_Sym#define Elf_Ehdr Elf64_Ehdr#define Elf_Addr Elf64_Addr +#define Elf_Rel Elf64_Rel#define Elf_Rela Elf64_Rela +#define ELF_R_TYPE (X ) ELF64_R_TYPE(X) +#define ELF_R_SYM (X ) ELF64_R_SYM(X)#else +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr#define Elf_Addr Elf32_Addr +#define Elf_Rel Elf32_Rel#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#endif struct unwind_table ;
arch/powerpc/include/asm/module.h +10 -0
@@ -60,16 +60,26 @@ struct mod_arch_specific {*/ #ifdef __powerpc64__ +# define MODULES_ARE_ELF64 # define Elf_Shdr Elf64_Shdr# define Elf_Sym Elf64_Sym# define Elf_Ehdr Elf64_Ehdr +# define Elf_Rel Elf64_Rel +# define Elf_Rela Elf64_Rela +# define ELF_R_TYPE (X ) ELF64_R_TYPE(X) +# define ELF_R_SYM (X ) ELF64_R_SYM(X)# ifdef MODULE asm(".section .stubs,\"ax\",@nobits; .align 3; .previous" );# endif #else +# define MODULES_ARE_ELF32 # define Elf_Shdr Elf32_Shdr# define Elf_Sym Elf32_Sym# define Elf_Ehdr Elf32_Ehdr +# define Elf_Rel Elf32_Rel +# define Elf_Rela Elf32_Rela +# define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +# define ELF_R_SYM (X ) ELF32_R_SYM(X)# ifdef MODULE asm(".section .plt,\"ax\",@nobits; .align 3; .previous" ); asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous" );
arch/s390/include/asm/module.h +3 -0
@@ -29,14 +29,17 @@ struct mod_arch_specific };#ifdef __s390x__ +#define MODULES_ARE_ELF64 #define ElfW (x) Elf64_ ## x#define ELFW (x) ELF64_ ## x#else +#define MODULES_ARE_ELF32 #define ElfW (x) Elf32_ ## x#define ELFW (x) ELF32_ ## x#endif #define Elf_Addr ElfW(Addr) +#define Elf_Rel ElfW(Rel)#define Elf_Rela ElfW(Rela)#define Elf_Shdr ElfW(Shdr)#define Elf_Sym ElfW(Sym)
include/asm-generic/module.h +10 -0
@@ -10,13 +10,23 @@ struct mod_arch_specific };#ifdef CONFIG_64BIT +#define MODULES_ARE_ELF64 #define Elf_Shdr Elf64_Shdr#define Elf_Sym Elf64_Sym#define Elf_Ehdr Elf64_Ehdr +#define Elf_Rel Elf64_Rel +#define Elf_Rela Elf64_Rela +#define ELF_R_TYPE (X ) ELF64_R_TYPE(X) +#define ELF_R_SYM (X ) ELF64_R_SYM(X)#else +#define MODULES_ARE_ELF32 #define Elf_Shdr Elf32_Shdr#define Elf_Sym Elf32_Sym#define Elf_Ehdr Elf32_Ehdr +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_TYPE (X ) ELF32_R_TYPE(X) +#define ELF_R_SYM (X ) ELF32_R_SYM(X)#endif #endif /* __ASM_GENERIC_MODULE_H */
David Howells
maintainerPATCH 13/14 MODSIGN: Module ELF verifier
In reply to David HowellsDo preliminary verification of the ELF structure of a module. This is used to make sure that the ELF structure can then be used to check the module signature and access the module data without breaking the module loader.
If the module's ELF metadata is determined to be bad, then ELIBBAD will be returned and a message will be logged to the kernel log.
---
init/Kconfig | 11 + kernel/Makefile | 2 kernel/module-verify-elf.c | 344 ++++++++++++++++++++++++++++++++++++++++++++ kernel/module-verify.c | 41 +++++ kernel/module-verify.h | 53 +++++++ kernel/module.c | 6 + 6 files changed, 457 insertions(+), 0 deletions(-) create mode 100644 kernel/module-verify-elf.c create mode 100644 kernel/module-verify.c create mode 100644 kernel/module-verify.h
init/Kconfig +11 -0
@@ -1383,6 +1383,17 @@ config MODULE_SRCVERSION_ALL the version). With this option, such a "srcversion" field will be created for all modules. If unsure, say N. +config MODULE_VERIFY_ELF + bool "Module ELF structure verification" + depends on MODULES + help + Check ELF structure of modules upon load + +config MODULE_VERIFY + bool + depends on MODULES + default y if MODULE_VERIFY_ELF + endif # MODULES config INIT_ALL_POSSIBLE
kernel/Makefile +2 -0
@@ -51,6 +51,8 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_MODULE_VERIFY) += module-verify.o +obj-$(CONFIG_MODULE_VERIFY_ELF) += module-verify-elf.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_FREEZER) += power/
kernel/module-verify-elf.c new file +344 -0
344 lines not on this page · raw message
kernel/module-verify.c new file +41 -0
41 lines not on this page · raw message
kernel/module-verify.h new file +53 -0
53 lines not on this page · raw message
kernel/module.c +6 -0
@@ -58,6 +58,7 @@#include <linux/jump_label.h> #include <linux/pfn.h> #include <linux/bsearch.h> +#include "module-verify.h" #define CREATE_TRACE_POINTS #include <trace/events/module.h>
@@ -2365,6 +2366,11 @@ static int copy_and_check(struct load_info *info, goto free_hdr; } +/* Verify the module's contents */ + err =module_verify (hdr, len); +if (err <0 ) + goto free_hdr; + info->hdr = hdr; info->len = len;return 0 ;
David Howells
maintainerPATCH 14/14 MODSIGN: Apply signature checking to modules on module load
In reply to David HowellsApply signature checking to modules on module load, checking the signature against the ring of public keys compiled into the kernel (if enabled by CONFIG_MODULE_SIG). Turning on signature checking will also force the module's ELF metadata to be verified first.
These patches have been in use by RHEL and Fedora kernels for years, and so have been thoroughly tested. The signed modules survive both the debuginfo separation performed by rpmbuild and the strip performed when modules are being reduced as much as possible before being included in an initial ramdisk composition. Signed modules have been tested to work with LE and BE, 32- and 64-bit arch kernels, including i386, x86_64, ppc64, ia64, s390 and s390x.
There are several reasons why these patches are useful, amongst which are:
(1) to protect against accidentally-corrupted modules causing damage;
(2) to protect against maliciously modified modules causing damage;
(3) to allow a sysadmin (or more likely an IT department) to enforce a policy that only known and approved modules shall be loaded onto machines which they're expected to support;
(4) to allow other support providers to do likewise, or at least to _detect_
the fact that unsupported modules are loaded;
(5) to allow the detection of modules replaced by a second-order distro or a preloaded Linux purveyor.
These patches have two main appeals: (a) preventing malicious modules from being loaded, and (b) reducing support workload by pointing out modules on a crashing box that aren't what they're expected to be.
Now, this is not a complete solution by any means: the core kernel is not protected, and nor are /dev/mem or /dev/kmem, but it denies (or at least controls) one relatively simple attack vector.
This facility is optional: the builder of a kernel is by no means under any requirement to actually enable it, let alone force the set of loadable modules to be restricted to just those that the builder provides (there are degrees of restriction available).
Use of the module signing facility is documentated in:
Documentation/module-signing.txt
which I've included here for reference:
============================== KERNEL MODULE SIGNING FACILITY ==============================
The module signing facilitiy applies cryptographic signature checking to modules on module load, checking the signature against a ring of public keys compiled into the kernel. GPG is used to do the cryptographic work and determines the format of the signature and key data. The facility uses GPG's MPI library to handle the huge numbers involved.
This facility is enabled through CONFIG_MODULE_SIG. Turning on signature checking will also force the module's ELF metadata to be verified before the signature is checked.
=====================
SUPPLYING PUBLIC KEYS
=====================
A set of public keys must be supplied at main kernel compile time. This is done by taking a GPG public key file, running it through the kernel's bin2c program and writing the result over crypto/signature/key.h. To automate this process, something like this could be done:
cat >genkey <<EOF
%pubring kernel.pub
%secring kernel.sec
Key-Type: DSA
Key-Length: 512
Name-Real: A. N. Other
Name-Comment: Kernel Module GPG key
%commit
EOF
make scripts/bin2c
gpg --homedir . --batch --gen-key genkey
The above generates fresh keys using /dev/random. If there's insufficient data in /dev/random, more can be provided more by running:
rngd -r /dev/urandom
in the background.
Note:
(1) That "keyname" is the name of the key in the keyring. This differentiates it from any other keys that may be added to the keyring.
(2) That no GPG password is used in the above scriptlet.
(3) It may be desirable to shred and delete the private key file after signing the modules.
==============
MODULE SIGNING
==============
Modules will then be signed automatically. The kernel make command line can include the following options:
(*) MODSECKEY=<secret-key-ring-path>
This indicates the whereabouts of the GPG keyring that is the source of the secret key to be used. The default is "./kernel.sec".
(*) MODPUBKEY=<public-key-ring-path>
This indicates the whereabouts of the GPG keyring that is the source of the public key to be used. The default is "./kernel.pub".
(*) MODKEYNAME=<key-name>
The name of the key pair to be used from the aforementioned keyrings. This defaults to being unset, thus leaving the choice of default key to gpg.
(*) KEYFLAGS="gpg-options"
Override the complete gpg command line, including the preceding three
options. The default options supplied to gpg are:
--no-default-keyring
--secret-keyring $(MODSECKEY)
--keyring $(MODPUBKEY)
--no-default-keyring
--homedir .
--no-options
--no-auto-check-trustdb
--no-permission-warning
with:
--default-key $(MODKEYNAME)
being added if requested.The resulting module.ko file will be the signed module.
========================
STRIPPING SIGNED MODULES
========================
Signed modules may be safely stripped as the signature only covers those parts of the module the kernel actually uses and any ELF metadata required to deal with them. Any necessary ELF metadata that is affected by stripping is canonicalised by the sig generator and the sig checker to hide strip effects.
This permits the debuginfo to be detached from the module and placed in another spot so that gdb can find it when referring to that module without the need for multiple signed versions of the module. Such is done by rpmbuild when producing RPMs.
It also permits the module to be stripped as far as possible for when modules are being reduced prior to being included in an initial ramdisk composition.
======================
LOADING SIGNED MODULES
======================
Modules are loaded with insmod, exactly as for unsigned modules. The signature is inserted into the module object file as an ELF section called ".module_sig". The signature checker will spot it and apply signature checking.
=========================================
NON-VALID SIGNATURES AND UNSIGNED MODULES
=========================================
If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on the kernel command line, the kernel will _only_ load validly signed modules for which it has a public key. Otherwise, it will also load modules that are unsigned. Any module for which the kernel has a key, but which proves to have a signature mismatch will not be permitted to load (returning EKEYREJECTED).
This table indicates the behaviours of the various situations:
MODULE STATE PERMISSIVE MODE ENFORCING MODE
=============================== =============== ===============
Unsigned Ok EKEYREJECTED
Signed, no public key ENOKEY ENOKEY
Validly signed, public key Ok Ok
Invalidly signed, public key EKEYREJECTED EKEYREJECTED
Validly signed, expired key EKEYEXPIRED EKEYEXPIRED
Corrupt signature ELIBBAD ELIBBAD
Corrupt ELF ELIBBAD ELIBBAD
---
.gitignore | 15 + Documentation/module-signing.txt | 143 ++++++ Makefile | 1 include/linux/elfnote.h | 4 include/linux/modsign.h | 27 + include/linux/module.h | 3 init/Kconfig | 22 + kernel/Makefile | 1 kernel/modsign-pubkey.c | 38 ++ kernel/module-verify-sig.c | 535 ++++++++++++++++++++++ kernel/module-verify.c | 5 kernel/module-verify.h | 19 + kernel/module.c | 21 + scripts/Makefile.modpost | 63 +++ scripts/mod/.gitignore | 1 scripts/mod/Makefile | 2 scripts/mod/mod-extract.c | 913 ++++++++++++++++++++++++++++++++++++++ scripts/mod/modsign-note.sh | 16 + 18 files changed, 1817 insertions(+), 12 deletions(-) create mode 100644 Documentation/module-signing.txt create mode 100644 include/linux/modsign.h create mode 100644 kernel/modsign-pubkey.c create mode 100644 kernel/module-verify-sig.c create mode 100644 scripts/mod/mod-extract.c create mode 100644 scripts/mod/modsign-note.sh
.gitignore +15 -0
@@ -14,6 +14,9 @@ *.o.* *.a *.s +*.ko.unsigned +*.ko.digest +*.ko.digest.sig *.ko *.so *.so.dbg
@@ -84,3 +87,15 @@ GTAGS *.orig *~ \#*# + +# +# GPG leavings from module signing +# +trustdb.gpg +random_seed +kernel.pub +kernel.sec +extract.pub +secring.gpg +pubring.gpg +crypto/signature/key.h
Documentation/module-signing.txt new file +143 -0
143 lines not on this page · raw message
Makefile +1 -0
@@ -1404,6 +1404,7 @@ clean: $(clean-dirs) $(call cmd,rmfiles) @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ + -o -name '*.ko.*' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ -o -name '*.symtypes' -o -name 'modules.order' \ -o -name modules.builtin -o -name '.tmp_*.o.*' \
include/linux/elfnote.h +4 -0
@@ -58,6 +58,7 @@ ELFNOTE_END#else /* !__ASSEMBLER__ */ +#include <linux/stringify.h> #include <linux/elf.h> /* * Use an anonymous structure which matches the shape of
@@ -93,6 +94,9 @@#define ELFNOTE32 (name, type, desc) ELFNOTE(32, name, type, desc)#define ELFNOTE64 (name, type, desc) ELFNOTE(64, name, type, desc) + +#define ELFNOTE_NAME (name) __stringify(name) +#define ELFNOTE_SECTION (name) ".note."ELFNOTE_NAME(name)#endif /* __ASSEMBLER__ */ #endif /* _LINUX_ELFNOTE_H */
include/linux/modsign.h new file +27 -0
@@ -0,0 +1,27 @@ +/* Module signing definitions +* +* Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +*/ + +#ifndef _LINUX_MODSIGN_H +#define _LINUX_MODSIGN_H + +#ifdef CONFIG_MODULE_SIG + +#include <linux/elfnote.h> + +/* +* The parameters of the ELF note used to carry the signature +*/ +#define MODSIGN_NOTE_NAME module.sig +#define MODSIGN_NOTE_TYPE 100 + +#endif + +#endif /* _LINUX_MODSIGN_H */
include/linux/module.h +3 -0
@@ -280,6 +280,9 @@ struct moduleunsigned int taints;/* same bits as kernel:tainted */ +/* Is this module GPG signed */ +int gpgsig_ok; +#ifdef CONFIG_GENERIC_BUG /* Support for BUG */ unsigned num_bugs;
init/Kconfig +21 -1
@@ -1389,10 +1389,30 @@ config MODULE_VERIFY_ELF help Check ELF structure of modules upon load +config MODULE_SIG + bool "Module signature verification (EXPERIMENTAL)" + depends on MODULES && EXPERIMENTAL + select CRYPTO_KEY_TYPE + select CRYPTO_KEY_DSA + select CRYPTO_SHA1 + select MODULE_VERIFY_ELF + help + Check modules for valid signatures upon load. For more information + see: + + Documentation/module-signing.txt + +config MODULE_SIG_FORCE + bool "Required modules to be validly signed (EXPERIMENTAL)" + depends on MODULE_SIG + help + Reject unsigned modules or signed modules for which we don't have a + key. + config MODULE_VERIFY bool depends on MODULES - default y if MODULE_VERIFY_ELF + default y if MODULE_VERIFY_ELF || MODULE_SIG endif # MODULES
kernel/Makefile +1 -0
@@ -53,6 +53,7 @@ obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_VERIFY) += module-verify.o obj-$(CONFIG_MODULE_VERIFY_ELF) += module-verify-elf.o +obj-$(CONFIG_MODULE_SIG) += module-verify-sig.o modsign-pubkey.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_FREEZER) += power/
kernel/modsign-pubkey.c new file +38 -0
@@ -0,0 +1,38 @@ +/* Public keys for module signature verification +* +* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. +* Written by David Howells ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public Licence +* as published by the Free Software Foundation; either version +* 2 of the Licence, or (at your option) any later version. +*/ + +#include <linux/kernel.h> +#include <keys/keyring-type.h> +#include "module-verify.h" + +extern __initdata const u8 modsign_public_keys[]; +extern __initdata const u8 modsign_public_keys_end[]; +asm(".section .init.data,\"aw\"\n" +"modsign_public_keys:\n" +".incbin \"kernel.pub\"\n" +"modsign_public_keys_end:" + ); + +/* +* Load the compiled-in keys +*/ +static __init int modsign_pubkey_init (void ) +{ +pr_notice ("Load module verification keys\n" ); + +if (load_PGP_keys (modsign_public_keys, + modsign_public_keys_end - modsign_public_keys, + modsign_keyring,"modsign." ) <0 ) +panic ("Can't load module signing keys\n" ); + +return 0 ; +} +late_initcall (modsign_pubkey_init);
kernel/module-verify-sig.c new file +535 -0
535 lines not on this page · raw message
kernel/module-verify.c +4 -1
@@ -16,8 +16,9 @@/* * verify a module's integrity * - check the ELF is viable +* - check the module's signature */ -int module_verify (const Elf_Ehdr *hdr,size_t size) +int module_verify (const Elf_Ehdr *hdr,size_t size,int *_gpgsig_ok) {struct module_verify_data mvdata;int ret;
@@ -34,6 +35,8 @@ int module_verify(const Elf_Ehdr *hdr, size_t size) goto error; } + ret =module_verify_signature (&mvdata, _gpgsig_ok); + error:kfree (mvdata.secsizes);kfree (mvdata.canonlist);
kernel/module-verify.h +17 -2
@@ -10,10 +10,13 @@*/ #include <linux/types.h> +#include <linux/elf.h> +#include <keys/crypto-type.h> #include <asm/module.h> #ifdef CONFIG_MODULE_VERIFY struct module_verify_data { + struct crypto_key_verify_context *mod_sig; /* Module signing context */ const void *buffer; /* module buffer */ const Elf_Ehdr *hdr; /* ELF header */ const Elf_Shdr *sections; /* ELF section table */
@@ -37,7 +40,7 @@ struct module_verify_data {/* * module-verify.c */ -extern int module_verify (const Elf_Ehdr *hdr,size_t size); +extern int module_verify (const Elf_Ehdr *hdr,size_t size,int *_gpgsig_ok);/* * module-verify-elf.c
@@ -48,6 +51,18 @@ extern int module_verify_elf(struct module_verify_data *mvdata);#define module_verify_elf (m) (0)#endif +/* +* module-verify-sig.c +*/ +#ifdef CONFIG_MODULE_SIG +extern struct key *modsign_keyring; + +extern int module_verify_signature (struct module_verify_data *mvdata, +int *_gpgsig_ok); +#else +#define module_verify_signature (m, g) (0) +#endif +#else -#define module_verify (h, s) (0) +#define module_verify (h, s, g) (0)#endif
kernel/module.c +15 -6
@@ -2333,7 +2333,8 @@ static inline void kmemleak_load_module(const struct module *mod,/* Sets info->hdr and info->len. */ static int copy_and_check (struct load_info *info,const void __user *umod,unsigned long len, -const char __user *uargs) +const char __user *uargs, +int *_gpgsig_ok) {int err;Elf_Ehdr *hdr;
@@ -2367,7 +2368,7 @@ static int copy_and_check(struct load_info *info, }/* Verify the module's contents */ - err =module_verify (hdr, len); + err =module_verify (hdr, len, _gpgsig_ok);if (err <0 ) goto free_hdr;
@@ -2713,7 +2714,8 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,return 0 ; } -static struct module *layout_and_allocate (struct load_info *info) +static struct module *layout_and_allocate (struct load_info *info, +int gpgsig_ok) {/* Module within temporary copy. */ struct module *mod;
@@ -2723,6 +2725,7 @@ static struct module *layout_and_allocate(struct load_info *info) mod =setup_load_info (info);if (IS_ERR (mod))return mod; + mod->gpgsig_ok = gpgsig_ok; err =check_modinfo (mod, info);if (err)
@@ -2816,17 +2819,18 @@ static struct module *load_module(void __user *umod,struct load_info info = {NULL , };struct module *mod;long err; +int gpgsig_ok;DEBUGP ("load_module: umod=%p, len=%lu, uargs=%p\n" , umod, len, uargs);/* Copy in the blobs from userspace, check they are vaguely sane. */ - err =copy_and_check (&info, umod, len, uargs); + err =copy_and_check (&info, umod, len, uargs, &gpgsig_ok);if (err)return ERR_PTR (err);/* Figure out module layout, and allocate all the memory. */ - mod =layout_and_allocate (&info); + mod =layout_and_allocate (&info, gpgsig_ok);if (IS_ERR (mod)) { err =PTR_ERR (mod); goto free_copy;
@@ -3476,8 +3480,13 @@ void print_modules(void)printk (KERN_DEFAULT "Modules linked in:" );/* Most callers should already have preempt disabled, but make sure */ preempt_disable (); -list_for_each_entry_rcu (mod, &modules, list) +list_for_each_entry_rcu (mod, &modules, list) {printk (" %s%s" , mod->name,module_flags (mod, buf)); +#ifdef CONFIG_MODULE_SIG +if (!mod->gpgsig_ok) +printk ("(U)" ); +#endif + }preempt_enable ();if (last_unloaded_module[0 ])printk (" [last unloaded: %s]" , last_unloaded_module);
scripts/Makefile.modpost +62 -1
88 lines not on this page · raw message
scripts/mod/.gitignore +1 -0
@@ -1,4 +1,5 @@ elfconfig.h mk_elfconfig modpost +mod-extract
scripts/mod/Makefile +1 -1
@@ -1,4 +1,4 @@ -hostprogs-y := modpost mk_elfconfig +hostprogs-y := modpost mk_elfconfig mod-extract always := $(hostprogs-y) empty.o modpost-objs := modpost.o file2alias.o sumversion.o
scripts/mod/mod-extract.c new file +913 -0
913 lines not on this page · raw message
scripts/mod/modsign-note.sh new file +16 -0
@@ -0,0 +1,16 @@ +#!/bin/sh +# +# Generate a module signature note source file +# +# mod-sign.sh <sig-file> ><note-src-file> +# + +SIG=$1 + +cat <<EOF +#include <linux/modsign.h> + +ELFNOTE(MODSIGN_NOTE_NAME, MODSIGN_NOTE_TYPE, .incbin "$SIG") +EOF + +exit 0
David Howells
maintainercover Crypto keys and module signing
In reply to David HowellsHere are a set of patches that create a framework for using cryptographic keys within the kernel. The basic crypto key has no requirements as to how the key is implemented; it's basically a jump table for the operations and an anchor for any relevant data.
I have provided a couple of subtypes: DSA and RSA. The DSA type has signature verification facilities available within the kernel, and is used for module signature verification.
These two subtypes store their public key data attached to the key and implement the algorithms within the kernel. However, it would be possible to merely refer to keys held in a hardware keystore (such as a TPM) and have the accessor methods offload the actual work to that keystore to be done in hardware.
The patches break down into a number of areas:
(0) Dmitry Kasatkin's MPI library patches - which I have not included here but that can be obtained from the security GIT tree.
(1) Utility: MPI function exports and make key_serial() handle a const pointer.
(2) PGP defs and PGP packet parser; basic crypto key infrastructure.
(3) DSA key and RSA key basic implementations.
(4) PGP signature parser; signature verification operations.
(5) DSA verification algorithm.
(6) Module ELF verification and module signature verification.
I have included the documentation for the crypto key type below.
David
---
====================== CRYPTOGRAPHIC KEY TYPE ======================
Contents:
- Overview.
- Key identification.
- Crypto subtypes.
- Accessing crypto keys.
- Signature verification.
- Initial pgp key loading.
- Implementing crypto subtypes.
- Registration.
========
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 what operations might be performed with it. However, no requirement is made that the key data actually be loaded into the key or that the operations are done by the kernel.
For instance, cryptographic hardware (such as a TPM) might be used to both retain the relevant key and provide 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 or is not 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 key subtype's instantiation routine calculates the key fingerprint and stores a copy in the key struct.
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 []
===============
CRYPTO SUBTYPES
===============
The crypto key is just a simple container. It contains no data of its own and does very little except provide a place to hang a function pointer table. The key subtype does the actual work.
When a crypto key is instantiated, it looks through its list of registered subtypes to try and find one that can handle the data blob it is given. If the data blob begins with a byte with the top bit set, it is assumed to be a PGP packet format blob [RFC 4880] and is treated so. The blob is parsed to find a PGP key, and then a subtype is looked for that says it can handle the appropriate algorithm type.
=====================
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 a key to provide the public key:
(1) Begin verification procedure.
struct crypto_key_verify_context * verify_sig_begin(struct key *key, const void *sig, size_t siglen);
This function sets up a verification context from the specified key and the signature blob. The signature blob must be presented again at the end of the procedure. The key is checked against parameters in the signature, and if it's not the right key then an error will be given.
If such a thing applies, the hashing algorithm, will be extracted from 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.
To find a key to use for signature verification, the following function may be called:
struct key *request_crypto_key_for_PGP_sig(struct key *keyring, const u8 *sig, size_t siglen);
This parses the specified signature blob to find the signing key identity and then searches the given keyring for a matching key. It may also examine a hardware keystore (such as a TPM) for a usable signature matching service and generate a key to provide an access method to that service.
INITIAL PGP KEY LOADING
-----------------------
A function is provided to perform an initial load of a set of public keys bound into a PGP keyring blob:
int load_PGP_keys(const u8 *pgpdata, size_t pgpdatalen, struct key *keyring, const char *descprefix);
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 descprefix plus a simple uniquifier - it is not expected that the description will be used to identify the 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.
============================
IMPLEMENTING CRYPTO SUBTYPES
============================
Each subtype is specified through a definition structure:
struct crypto_key_subtype {
struct module *owner;
const char *name;
enum pgp_pubkey_algo pubkey_algo : 8;
unsigned short info;
int (*instantiate)(struct key *key,
const void *data, size_t datalen);
void (*revoke)(struct key *key);
void (*destroy)(struct key *key);
struct crypto_key_verify_context *(*verify_sig_begin)(
struct key *key, const u8 *sig, size_t siglen);
int (*verify_sig_add_data)(struct crypto_key_verify_context *ctx,
const void *data, size_t datalen);
int (*verify_sig_end)(struct crypto_key_verify_context *ctx,
const u8 *sig, size_t siglen);
void (*verify_sig_cancel)(struct crypto_key_verify_context *ctx);
};The owner and name fields should be set to the owning module and the name of the subtype.
If the subtype represents a PGP public key algorithm the info field should have CRYPTO_KEY_IS_PUBKEY_ALGO OR'd into it and pubkey_algo should be set to the appropriate PGP_PUBKEY_ constant from the enumeration in <linux/pgp.h>.
There are a number of operations defined by the subtype. The first few are for management of the key itself:
(1) instantiate().
Mandatory. When the subtype is selected, the instantiate() method will be given the key being instantiated and the data blob. If the first byte of the data blob has bit 7 set, then it's a PGP packet blob and can be parsed with the routines declared in <linux/pgp.h>.
If the key has a fingerprint or other auxiliary identifier, this should be determined or calculated and a copy attached to key->type_data.p[1].
If successful, the subtype must set key->type_data.p[0] to point to its definition.
The subtype may use key->payload in anyway it sees fit.
(2) revoke().
Optional. Notification that the key has been revoked. This provides the subtype the opportunity to discard some memory, but care should be taken as the key may be in use when this is called.
(3) destroy().
Mandatory. key->type_data.p[0] is cleared by the caller and the module
usage will be decremented upon return. The memory pointed to by
key->type_data.[1] will be freed after this method returns. This method
must free whatever key->payload refers to.There are then sets of method pointers to actually use the key for things:
(*) Signature verification
Then there are functions to verify a signature using the public key stored in this key:
(1) verify_sig_begin().
(2) verify_sig_add_data().
(3) verify_sig_end().
(4) verify_sig_cancel().
These correspond to the accessor functions mentioned in the previous section. The first function is optional - if it is not provided, then verification is not a service available with this key. The other three are mandatory if the first is supplied and unnecessary otherwise.
The subtype should allocate a context in ->verify_sig_begin() and embed the following struct in it:
struct crypto_key_verify_context {
struct key *key;
};
A pointer to this struct is then returned to the caller. This is used by the master routines to route the operations to the right place. This is passed to the _add_data, _end and _cancel routines - which should use container_of() on it to get the full context.
REGISTRATION
------------
Functions are provided to register and unregister key subtypes:
int register_crypto_key_subtype(struct crypto_key_subtype *subtype); void unregister_crypto_key_subtype(struct crypto_key_subtype *subtype);
Key subtypes may have the same name, provided they differ in some other criterion, such as the public key algorithm ID. This makes it possible to handle algorithms such as RSA that have multiple algorithm IDs.