aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-21 22:46:00 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-21 22:46:00 -0500
commit78dc53c422172a317adb0776dfb687057ffa28b7 (patch)
tree7c5d15da75d769d01f6a992c24c3490b3867d5b2 /crypto
parent3eaded86ac3e7f00fb3eeb8162d89e9a34e42fb0 (diff)
parent62fe318256befbd1b4a6765e71d9c997f768fe79 (diff)
Merge branch 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "In this patchset, we finally get an SELinux update, with Paul Moore taking over as maintainer of that code. Also a significant update for the Keys subsystem, as well as maintenance updates to Smack, IMA, TPM, and Apparmor" and since I wanted to know more about the updates to key handling, here's the explanation from David Howells on that: "Okay. There are a number of separate bits. I'll go over the big bits and the odd important other bit, most of the smaller bits are just fixes and cleanups. If you want the small bits accounting for, I can do that too. (1) Keyring capacity expansion. KEYS: Consolidate the concept of an 'index key' for key access KEYS: Introduce a search context structure KEYS: Search for auth-key by name rather than target key ID Add a generic associative array implementation. KEYS: Expand the capacity of a keyring Several of the patches are providing an expansion of the capacity of a keyring. Currently, the maximum size of a keyring payload is one page. Subtract a small header and then divide up into pointers, that only gives you ~500 pointers on an x86_64 box. However, since the NFS idmapper uses a keyring to store ID mapping data, that has proven to be insufficient to the cause. Whatever data structure I use to handle the keyring payload, it can only store pointers to keys, not the keys themselves because several keyrings may point to a single key. This precludes inserting, say, and rb_node struct into the key struct for this purpose. I could make an rbtree of records such that each record has an rb_node and a key pointer, but that would use four words of space per key stored in the keyring. It would, however, be able to use much existing code. I selected instead a non-rebalancing radix-tree type approach as that could have a better space-used/key-pointer ratio. I could have used the radix tree implementation that we already have and insert keys into it by their serial numbers, but that means any sort of search must iterate over the whole radix tree. Further, its nodes are a bit on the capacious side for what I want - especially given that key serial numbers are randomly allocated, thus leaving a lot of empty space in the tree. So what I have is an associative array that internally is a radix-tree with 16 pointers per node where the index key is constructed from the key type pointer and the key description. This means that an exact lookup by type+description is very fast as this tells us how to navigate directly to the target key. I made the data structure general in lib/assoc_array.c as far as it is concerned, its index key is just a sequence of bits that leads to a pointer. It's possible that someone else will be able to make use of it also. FS-Cache might, for example. (2) Mark keys as 'trusted' and keyrings as 'trusted only'. KEYS: verify a certificate is signed by a 'trusted' key KEYS: Make the system 'trusted' keyring viewable by userspace KEYS: Add a 'trusted' flag and a 'trusted only' flag KEYS: Separate the kernel signature checking keyring from module signing These patches allow keys carrying asymmetric public keys to be marked as being 'trusted' and allow keyrings to be marked as only permitting the addition or linkage of trusted keys. Keys loaded from hardware during kernel boot or compiled into the kernel during build are marked as being trusted automatically. New keys can be loaded at runtime with add_key(). They are checked against the system keyring contents and if their signatures can be validated with keys that are already marked trusted, then they are marked trusted also and can thus be added into the master keyring. Patches from Mimi Zohar make this usable with the IMA keyrings also. (3) Remove the date checks on the key used to validate a module signature. X.509: Remove certificate date checks It's not reasonable to reject a signature just because the key that it was generated with is no longer valid datewise - especially if the kernel hasn't yet managed to set the system clock when the first module is loaded - so just remove those checks. (4) Make it simpler to deal with additional X.509 being loaded into the kernel. KEYS: Load *.x509 files into kernel keyring KEYS: Have make canonicalise the paths of the X.509 certs better to deduplicate The builder of the kernel now just places files with the extension ".x509" into the kernel source or build trees and they're concatenated by the kernel build and stuffed into the appropriate section. (5) Add support for userspace kerberos to use keyrings. KEYS: Add per-user_namespace registers for persistent per-UID kerberos caches KEYS: Implement a big key type that can save to tmpfs Fedora went to, by default, storing kerberos tickets and tokens in tmpfs. We looked at storing it in keyrings instead as that confers certain advantages such as tickets being automatically deleted after a certain amount of time and the ability for the kernel to get at these tokens more easily. To make this work, two things were needed: (a) A way for the tickets to persist beyond the lifetime of all a user's sessions so that cron-driven processes can still use them. The problem is that a user's session keyrings are deleted when the session that spawned them logs out and the user's user keyring is deleted when the UID is deleted (typically when the last log out happens), so neither of these places is suitable. I've added a system keyring into which a 'persistent' keyring is created for each UID on request. Each time a user requests their persistent keyring, the expiry time on it is set anew. If the user doesn't ask for it for, say, three days, the keyring is automatically expired and garbage collected using the existing gc. All the kerberos tokens it held are then also gc'd. (b) A key type that can hold really big tickets (up to 1MB in size). The problem is that Active Directory can return huge tickets with lots of auxiliary data attached. We don't, however, want to eat up huge tracts of unswappable kernel space for this, so if the ticket is greater than a certain size, we create a swappable shmem file and dump the contents in there and just live with the fact we then have an inode and a dentry overhead. If the ticket is smaller than that, we slap it in a kmalloc()'d buffer" * 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (121 commits) KEYS: Fix keyring content gc scanner KEYS: Fix error handling in big_key instantiation KEYS: Fix UID check in keyctl_get_persistent() KEYS: The RSA public key algorithm needs to select MPILIB ima: define '_ima' as a builtin 'trusted' keyring ima: extend the measurement list to include the file signature kernel/system_certificate.S: use real contents instead of macro GLOBAL() KEYS: fix error return code in big_key_instantiate() KEYS: Fix keyring quota misaccounting on key replacement and unlink KEYS: Fix a race between negating a key and reading the error set KEYS: Make BIG_KEYS boolean apparmor: remove the "task" arg from may_change_ptraced_domain() apparmor: remove parent task info from audit logging apparmor: remove tsk field from the apparmor_audit_struct apparmor: fix capability to not use the current task, during reporting Smack: Ptrace access check mode ima: provide hash algo info in the xattr ima: enable support for larger default filedata hash algorithms ima: define kernel parameter 'ima_template=' to change configured default ima: add Kconfig default measurement list template ...
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Kconfig3
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/asymmetric_keys/Kconfig4
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c1
-rw-r--r--crypto/asymmetric_keys/public_key.c66
-rw-r--r--crypto/asymmetric_keys/public_key.h6
-rw-r--r--crypto/asymmetric_keys/rsa.c14
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c35
-rw-r--r--crypto/asymmetric_keys/x509_parser.h18
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c232
-rw-r--r--crypto/hash_info.c56
11 files changed, 296 insertions, 140 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 71f337aefa39..4ae5734fb473 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1402,6 +1402,9 @@ config CRYPTO_USER_API_SKCIPHER
1402 This option enables the user-spaces interface for symmetric 1402 This option enables the user-spaces interface for symmetric
1403 key cipher algorithms. 1403 key cipher algorithms.
1404 1404
1405config CRYPTO_HASH_INFO
1406 bool
1407
1405source "drivers/crypto/Kconfig" 1408source "drivers/crypto/Kconfig"
1406source crypto/asymmetric_keys/Kconfig 1409source crypto/asymmetric_keys/Kconfig
1407 1410
diff --git a/crypto/Makefile b/crypto/Makefile
index 80019ba8da3a..b3a7e807e08b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -104,3 +104,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
104obj-$(CONFIG_XOR_BLOCKS) += xor.o 104obj-$(CONFIG_XOR_BLOCKS) += xor.o
105obj-$(CONFIG_ASYNC_CORE) += async_tx/ 105obj-$(CONFIG_ASYNC_CORE) += async_tx/
106obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ 106obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
107obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 6d2c2ea12559..03a6eb95ab50 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -12,6 +12,8 @@ if ASYMMETRIC_KEY_TYPE
12config ASYMMETRIC_PUBLIC_KEY_SUBTYPE 12config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
13 tristate "Asymmetric public-key crypto algorithm subtype" 13 tristate "Asymmetric public-key crypto algorithm subtype"
14 select MPILIB 14 select MPILIB
15 select PUBLIC_KEY_ALGO_RSA
16 select CRYPTO_HASH_INFO
15 help 17 help
16 This option provides support for asymmetric public key type handling. 18 This option provides support for asymmetric public key type handling.
17 If signature generation and/or verification are to be used, 19 If signature generation and/or verification are to be used,
@@ -20,8 +22,8 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
20 22
21config PUBLIC_KEY_ALGO_RSA 23config PUBLIC_KEY_ALGO_RSA
22 tristate "RSA public-key algorithm" 24 tristate "RSA public-key algorithm"
23 depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
24 select MPILIB_EXTRA 25 select MPILIB_EXTRA
26 select MPILIB
25 help 27 help
26 This option enables support for the RSA algorithm (PKCS#1, RFC3447). 28 This option enables support for the RSA algorithm (PKCS#1, RFC3447).
27 29
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index cf807654d221..b77eb5304788 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -209,6 +209,7 @@ struct key_type key_type_asymmetric = {
209 .match = asymmetric_key_match, 209 .match = asymmetric_key_match,
210 .destroy = asymmetric_key_destroy, 210 .destroy = asymmetric_key_destroy,
211 .describe = asymmetric_key_describe, 211 .describe = asymmetric_key_describe,
212 .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE,
212}; 213};
213EXPORT_SYMBOL_GPL(key_type_asymmetric); 214EXPORT_SYMBOL_GPL(key_type_asymmetric);
214 215
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index cb2e29180a87..97eb001960b9 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -22,29 +22,25 @@
22 22
23MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
24 24
25const char *const pkey_algo[PKEY_ALGO__LAST] = { 25const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
26 [PKEY_ALGO_DSA] = "DSA", 26 [PKEY_ALGO_DSA] = "DSA",
27 [PKEY_ALGO_RSA] = "RSA", 27 [PKEY_ALGO_RSA] = "RSA",
28}; 28};
29EXPORT_SYMBOL_GPL(pkey_algo); 29EXPORT_SYMBOL_GPL(pkey_algo_name);
30 30
31const char *const pkey_hash_algo[PKEY_HASH__LAST] = { 31const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
32 [PKEY_HASH_MD4] = "md4", 32#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
33 [PKEY_HASH_MD5] = "md5", 33 defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
34 [PKEY_HASH_SHA1] = "sha1", 34 [PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
35 [PKEY_HASH_RIPE_MD_160] = "rmd160", 35#endif
36 [PKEY_HASH_SHA256] = "sha256",
37 [PKEY_HASH_SHA384] = "sha384",
38 [PKEY_HASH_SHA512] = "sha512",
39 [PKEY_HASH_SHA224] = "sha224",
40}; 36};
41EXPORT_SYMBOL_GPL(pkey_hash_algo); 37EXPORT_SYMBOL_GPL(pkey_algo);
42 38
43const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { 39const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
44 [PKEY_ID_PGP] = "PGP", 40 [PKEY_ID_PGP] = "PGP",
45 [PKEY_ID_X509] = "X509", 41 [PKEY_ID_X509] = "X509",
46}; 42};
47EXPORT_SYMBOL_GPL(pkey_id_type); 43EXPORT_SYMBOL_GPL(pkey_id_type_name);
48 44
49/* 45/*
50 * Provide a part of a description of the key for /proc/keys. 46 * Provide a part of a description of the key for /proc/keys.
@@ -56,7 +52,7 @@ static void public_key_describe(const struct key *asymmetric_key,
56 52
57 if (key) 53 if (key)
58 seq_printf(m, "%s.%s", 54 seq_printf(m, "%s.%s",
59 pkey_id_type[key->id_type], key->algo->name); 55 pkey_id_type_name[key->id_type], key->algo->name);
60} 56}
61 57
62/* 58/*
@@ -78,21 +74,45 @@ EXPORT_SYMBOL_GPL(public_key_destroy);
78/* 74/*
79 * Verify a signature using a public key. 75 * Verify a signature using a public key.
80 */ 76 */
81static int public_key_verify_signature(const struct key *key, 77int public_key_verify_signature(const struct public_key *pk,
82 const struct public_key_signature *sig) 78 const struct public_key_signature *sig)
83{ 79{
84 const struct public_key *pk = key->payload.data; 80 const struct public_key_algorithm *algo;
81
82 BUG_ON(!pk);
83 BUG_ON(!pk->mpi[0]);
84 BUG_ON(!pk->mpi[1]);
85 BUG_ON(!sig);
86 BUG_ON(!sig->digest);
87 BUG_ON(!sig->mpi[0]);
88
89 algo = pk->algo;
90 if (!algo) {
91 if (pk->pkey_algo >= PKEY_ALGO__LAST)
92 return -ENOPKG;
93 algo = pkey_algo[pk->pkey_algo];
94 if (!algo)
95 return -ENOPKG;
96 }
85 97
86 if (!pk->algo->verify_signature) 98 if (!algo->verify_signature)
87 return -ENOTSUPP; 99 return -ENOTSUPP;
88 100
89 if (sig->nr_mpi != pk->algo->n_sig_mpi) { 101 if (sig->nr_mpi != algo->n_sig_mpi) {
90 pr_debug("Signature has %u MPI not %u\n", 102 pr_debug("Signature has %u MPI not %u\n",
91 sig->nr_mpi, pk->algo->n_sig_mpi); 103 sig->nr_mpi, algo->n_sig_mpi);
92 return -EINVAL; 104 return -EINVAL;
93 } 105 }
94 106
95 return pk->algo->verify_signature(pk, sig); 107 return algo->verify_signature(pk, sig);
108}
109EXPORT_SYMBOL_GPL(public_key_verify_signature);
110
111static int public_key_verify_signature_2(const struct key *key,
112 const struct public_key_signature *sig)
113{
114 const struct public_key *pk = key->payload.data;
115 return public_key_verify_signature(pk, sig);
96} 116}
97 117
98/* 118/*
@@ -103,6 +123,6 @@ struct asymmetric_key_subtype public_key_subtype = {
103 .name = "public_key", 123 .name = "public_key",
104 .describe = public_key_describe, 124 .describe = public_key_describe,
105 .destroy = public_key_destroy, 125 .destroy = public_key_destroy,
106 .verify_signature = public_key_verify_signature, 126 .verify_signature = public_key_verify_signature_2,
107}; 127};
108EXPORT_SYMBOL_GPL(public_key_subtype); 128EXPORT_SYMBOL_GPL(public_key_subtype);
diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h
index 5e5e35626899..5c37a22a0637 100644
--- a/crypto/asymmetric_keys/public_key.h
+++ b/crypto/asymmetric_keys/public_key.h
@@ -28,3 +28,9 @@ struct public_key_algorithm {
28}; 28};
29 29
30extern const struct public_key_algorithm RSA_public_key_algorithm; 30extern const struct public_key_algorithm RSA_public_key_algorithm;
31
32/*
33 * public_key.c
34 */
35extern int public_key_verify_signature(const struct public_key *pk,
36 const struct public_key_signature *sig);
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
index 4a6a0696f8a3..90a17f59ba28 100644
--- a/crypto/asymmetric_keys/rsa.c
+++ b/crypto/asymmetric_keys/rsa.c
@@ -73,13 +73,13 @@ static const struct {
73 size_t size; 73 size_t size;
74} RSA_ASN1_templates[PKEY_HASH__LAST] = { 74} RSA_ASN1_templates[PKEY_HASH__LAST] = {
75#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } 75#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
76 [PKEY_HASH_MD5] = _(MD5), 76 [HASH_ALGO_MD5] = _(MD5),
77 [PKEY_HASH_SHA1] = _(SHA1), 77 [HASH_ALGO_SHA1] = _(SHA1),
78 [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), 78 [HASH_ALGO_RIPE_MD_160] = _(RIPE_MD_160),
79 [PKEY_HASH_SHA256] = _(SHA256), 79 [HASH_ALGO_SHA256] = _(SHA256),
80 [PKEY_HASH_SHA384] = _(SHA384), 80 [HASH_ALGO_SHA384] = _(SHA384),
81 [PKEY_HASH_SHA512] = _(SHA512), 81 [HASH_ALGO_SHA512] = _(SHA512),
82 [PKEY_HASH_SHA224] = _(SHA224), 82 [HASH_ALGO_SHA224] = _(SHA224),
83#undef _ 83#undef _
84}; 84};
85 85
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index facbf26bc6bb..29893162497c 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert)
47 kfree(cert->subject); 47 kfree(cert->subject);
48 kfree(cert->fingerprint); 48 kfree(cert->fingerprint);
49 kfree(cert->authority); 49 kfree(cert->authority);
50 kfree(cert->sig.digest);
51 mpi_free(cert->sig.rsa.s);
50 kfree(cert); 52 kfree(cert);
51 } 53 }
52} 54}
@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
152 return -ENOPKG; /* Unsupported combination */ 154 return -ENOPKG; /* Unsupported combination */
153 155
154 case OID_md4WithRSAEncryption: 156 case OID_md4WithRSAEncryption:
155 ctx->cert->sig_hash_algo = PKEY_HASH_MD5; 157 ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5;
156 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 158 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
157 break; 159 break;
158 160
159 case OID_sha1WithRSAEncryption: 161 case OID_sha1WithRSAEncryption:
160 ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; 162 ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1;
161 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 163 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
162 break; 164 break;
163 165
164 case OID_sha256WithRSAEncryption: 166 case OID_sha256WithRSAEncryption:
165 ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; 167 ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256;
166 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 168 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
167 break; 169 break;
168 170
169 case OID_sha384WithRSAEncryption: 171 case OID_sha384WithRSAEncryption:
170 ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; 172 ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384;
171 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 173 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
172 break; 174 break;
173 175
174 case OID_sha512WithRSAEncryption: 176 case OID_sha512WithRSAEncryption:
175 ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; 177 ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512;
176 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 178 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
177 break; 179 break;
178 180
179 case OID_sha224WithRSAEncryption: 181 case OID_sha224WithRSAEncryption:
180 ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; 182 ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224;
181 ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; 183 ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
182 break; 184 break;
183 } 185 }
184 186
@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen,
203 return -EINVAL; 205 return -EINVAL;
204 } 206 }
205 207
206 ctx->cert->sig = value; 208 ctx->cert->raw_sig = value;
207 ctx->cert->sig_size = vlen; 209 ctx->cert->raw_sig_size = vlen;
208 return 0; 210 return 0;
209} 211}
210 212
@@ -343,8 +345,9 @@ int x509_extract_key_data(void *context, size_t hdrlen,
343 if (ctx->last_oid != OID_rsaEncryption) 345 if (ctx->last_oid != OID_rsaEncryption)
344 return -ENOPKG; 346 return -ENOPKG;
345 347
346 /* There seems to be an extraneous 0 byte on the front of the data */ 348 ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA;
347 ctx->cert->pkey_algo = PKEY_ALGO_RSA; 349
350 /* Discard the BIT STRING metadata */
348 ctx->key = value + 1; 351 ctx->key = value + 1;
349 ctx->key_size = vlen - 1; 352 ctx->key_size = vlen - 1;
350 return 0; 353 return 0;
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index f86dc5fcc4ad..87d9cc26f630 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -9,6 +9,7 @@
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12#include <linux/time.h>
12#include <crypto/public_key.h> 13#include <crypto/public_key.h>
13 14
14struct x509_certificate { 15struct x509_certificate {
@@ -20,13 +21,11 @@ struct x509_certificate {
20 char *authority; /* Authority key fingerprint as hex */ 21 char *authority; /* Authority key fingerprint as hex */
21 struct tm valid_from; 22 struct tm valid_from;
22 struct tm valid_to; 23 struct tm valid_to;
23 enum pkey_algo pkey_algo : 8; /* Public key algorithm */
24 enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */
25 enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */
26 const void *tbs; /* Signed data */ 24 const void *tbs; /* Signed data */
27 size_t tbs_size; /* Size of signed data */ 25 unsigned tbs_size; /* Size of signed data */
28 const void *sig; /* Signature data */ 26 unsigned raw_sig_size; /* Size of sigature */
29 size_t sig_size; /* Size of sigature */ 27 const void *raw_sig; /* Signature data */
28 struct public_key_signature sig; /* Signature parameters */
30}; 29};
31 30
32/* 31/*
@@ -34,3 +33,10 @@ struct x509_certificate {
34 */ 33 */
35extern void x509_free_certificate(struct x509_certificate *cert); 34extern void x509_free_certificate(struct x509_certificate *cert);
36extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); 35extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
36
37/*
38 * x509_public_key.c
39 */
40extern int x509_get_sig_params(struct x509_certificate *cert);
41extern int x509_check_signature(const struct public_key *pub,
42 struct x509_certificate *cert);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 06007f0e880c..f83300b6e8c1 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -18,85 +18,162 @@
18#include <linux/asn1_decoder.h> 18#include <linux/asn1_decoder.h>
19#include <keys/asymmetric-subtype.h> 19#include <keys/asymmetric-subtype.h>
20#include <keys/asymmetric-parser.h> 20#include <keys/asymmetric-parser.h>
21#include <keys/system_keyring.h>
21#include <crypto/hash.h> 22#include <crypto/hash.h>
22#include "asymmetric_keys.h" 23#include "asymmetric_keys.h"
23#include "public_key.h" 24#include "public_key.h"
24#include "x509_parser.h" 25#include "x509_parser.h"
25 26
26static const 27/*
27struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { 28 * Find a key in the given keyring by issuer and authority.
28 [PKEY_ALGO_DSA] = NULL, 29 */
29#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ 30static struct key *x509_request_asymmetric_key(
30 defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) 31 struct key *keyring,
31 [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, 32 const char *signer, size_t signer_len,
32#endif 33 const char *authority, size_t auth_len)
33}; 34{
35 key_ref_t key;
36 char *id;
37
38 /* Construct an identifier. */
39 id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
40 if (!id)
41 return ERR_PTR(-ENOMEM);
42
43 memcpy(id, signer, signer_len);
44 id[signer_len + 0] = ':';
45 id[signer_len + 1] = ' ';
46 memcpy(id + signer_len + 2, authority, auth_len);
47 id[signer_len + 2 + auth_len] = 0;
48
49 pr_debug("Look up: \"%s\"\n", id);
50
51 key = keyring_search(make_key_ref(keyring, 1),
52 &key_type_asymmetric, id);
53 if (IS_ERR(key))
54 pr_debug("Request for module key '%s' err %ld\n",
55 id, PTR_ERR(key));
56 kfree(id);
57
58 if (IS_ERR(key)) {
59 switch (PTR_ERR(key)) {
60 /* Hide some search errors */
61 case -EACCES:
62 case -ENOTDIR:
63 case -EAGAIN:
64 return ERR_PTR(-ENOKEY);
65 default:
66 return ERR_CAST(key);
67 }
68 }
69
70 pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
71 return key_ref_to_ptr(key);
72}
34 73
35/* 74/*
36 * Check the signature on a certificate using the provided public key 75 * Set up the signature parameters in an X.509 certificate. This involves
76 * digesting the signed data and extracting the signature.
37 */ 77 */
38static int x509_check_signature(const struct public_key *pub, 78int x509_get_sig_params(struct x509_certificate *cert)
39 const struct x509_certificate *cert)
40{ 79{
41 struct public_key_signature *sig;
42 struct crypto_shash *tfm; 80 struct crypto_shash *tfm;
43 struct shash_desc *desc; 81 struct shash_desc *desc;
44 size_t digest_size, desc_size; 82 size_t digest_size, desc_size;
83 void *digest;
45 int ret; 84 int ret;
46 85
47 pr_devel("==>%s()\n", __func__); 86 pr_devel("==>%s()\n", __func__);
48 87
88 if (cert->sig.rsa.s)
89 return 0;
90
91 cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
92 if (!cert->sig.rsa.s)
93 return -ENOMEM;
94 cert->sig.nr_mpi = 1;
95
49 /* Allocate the hashing algorithm we're going to need and find out how 96 /* Allocate the hashing algorithm we're going to need and find out how
50 * big the hash operational data will be. 97 * big the hash operational data will be.
51 */ 98 */
52 tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); 99 tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
53 if (IS_ERR(tfm)) 100 if (IS_ERR(tfm))
54 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 101 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
55 102
56 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 103 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
57 digest_size = crypto_shash_digestsize(tfm); 104 digest_size = crypto_shash_digestsize(tfm);
58 105
59 /* We allocate the hash operational data storage on the end of our 106 /* We allocate the hash operational data storage on the end of the
60 * context data. 107 * digest storage space.
61 */ 108 */
62 ret = -ENOMEM; 109 ret = -ENOMEM;
63 sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); 110 digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
64 if (!sig) 111 if (!digest)
65 goto error_no_sig; 112 goto error;
66 113
67 sig->pkey_hash_algo = cert->sig_hash_algo; 114 cert->sig.digest = digest;
68 sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; 115 cert->sig.digest_size = digest_size;
69 sig->digest_size = digest_size;
70 116
71 desc = (void *)sig + sizeof(*sig); 117 desc = digest + digest_size;
72 desc->tfm = tfm; 118 desc->tfm = tfm;
73 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 119 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
74 120
75 ret = crypto_shash_init(desc); 121 ret = crypto_shash_init(desc);
76 if (ret < 0) 122 if (ret < 0)
77 goto error; 123 goto error;
124 might_sleep();
125 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest);
126error:
127 crypto_free_shash(tfm);
128 pr_devel("<==%s() = %d\n", __func__, ret);
129 return ret;
130}
131EXPORT_SYMBOL_GPL(x509_get_sig_params);
78 132
79 ret = -ENOMEM; 133/*
80 sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); 134 * Check the signature on a certificate using the provided public key
81 if (!sig->rsa.s) 135 */
82 goto error; 136int x509_check_signature(const struct public_key *pub,
137 struct x509_certificate *cert)
138{
139 int ret;
83 140
84 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); 141 pr_devel("==>%s()\n", __func__);
85 if (ret < 0)
86 goto error_mpi;
87 142
88 ret = pub->algo->verify_signature(pub, sig); 143 ret = x509_get_sig_params(cert);
144 if (ret < 0)
145 return ret;
89 146
147 ret = public_key_verify_signature(pub, &cert->sig);
90 pr_debug("Cert Verification: %d\n", ret); 148 pr_debug("Cert Verification: %d\n", ret);
149 return ret;
150}
151EXPORT_SYMBOL_GPL(x509_check_signature);
91 152
92error_mpi: 153/*
93 mpi_free(sig->rsa.s); 154 * Check the new certificate against the ones in the trust keyring. If one of
94error: 155 * those is the signing key and validates the new certificate, then mark the
95 kfree(sig); 156 * new certificate as being trusted.
96error_no_sig: 157 *
97 crypto_free_shash(tfm); 158 * Return 0 if the new certificate was successfully validated, 1 if we couldn't
159 * find a matching parent certificate in the trusted list and an error if there
160 * is a matching certificate but the signature check fails.
161 */
162static int x509_validate_trust(struct x509_certificate *cert,
163 struct key *trust_keyring)
164{
165 const struct public_key *pk;
166 struct key *key;
167 int ret = 1;
98 168
99 pr_devel("<==%s() = %d\n", __func__, ret); 169 key = x509_request_asymmetric_key(trust_keyring,
170 cert->issuer, strlen(cert->issuer),
171 cert->authority,
172 strlen(cert->authority));
173 if (!IS_ERR(key)) {
174 pk = key->payload.data;
175 ret = x509_check_signature(pk, cert);
176 }
100 return ret; 177 return ret;
101} 178}
102 179
@@ -106,7 +183,6 @@ error_no_sig:
106static int x509_key_preparse(struct key_preparsed_payload *prep) 183static int x509_key_preparse(struct key_preparsed_payload *prep)
107{ 184{
108 struct x509_certificate *cert; 185 struct x509_certificate *cert;
109 struct tm now;
110 size_t srlen, sulen; 186 size_t srlen, sulen;
111 char *desc = NULL; 187 char *desc = NULL;
112 int ret; 188 int ret;
@@ -117,7 +193,18 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
117 193
118 pr_devel("Cert Issuer: %s\n", cert->issuer); 194 pr_devel("Cert Issuer: %s\n", cert->issuer);
119 pr_devel("Cert Subject: %s\n", cert->subject); 195 pr_devel("Cert Subject: %s\n", cert->subject);
120 pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); 196
197 if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
198 cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
199 cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
200 !pkey_algo[cert->pub->pkey_algo] ||
201 !pkey_algo[cert->sig.pkey_algo] ||
202 !hash_algo_name[cert->sig.pkey_hash_algo]) {
203 ret = -ENOPKG;
204 goto error_free_cert;
205 }
206
207 pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
121 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", 208 pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
122 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, 209 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
123 cert->valid_from.tm_mday, cert->valid_from.tm_hour, 210 cert->valid_from.tm_mday, cert->valid_from.tm_hour,
@@ -127,61 +214,29 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
127 cert->valid_to.tm_mday, cert->valid_to.tm_hour, 214 cert->valid_to.tm_mday, cert->valid_to.tm_hour,
128 cert->valid_to.tm_min, cert->valid_to.tm_sec); 215 cert->valid_to.tm_min, cert->valid_to.tm_sec);
129 pr_devel("Cert Signature: %s + %s\n", 216 pr_devel("Cert Signature: %s + %s\n",
130 pkey_algo[cert->sig_pkey_algo], 217 pkey_algo_name[cert->sig.pkey_algo],
131 pkey_hash_algo[cert->sig_hash_algo]); 218 hash_algo_name[cert->sig.pkey_hash_algo]);
132 219
133 if (!cert->fingerprint || !cert->authority) { 220 if (!cert->fingerprint) {
134 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", 221 pr_warn("Cert for '%s' must have a SubjKeyId extension\n",
135 cert->subject); 222 cert->subject);
136 ret = -EKEYREJECTED; 223 ret = -EKEYREJECTED;
137 goto error_free_cert; 224 goto error_free_cert;
138 } 225 }
139 226
140 time_to_tm(CURRENT_TIME.tv_sec, 0, &now); 227 cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
141 pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n",
142 now.tm_year + 1900, now.tm_mon + 1, now.tm_mday,
143 now.tm_hour, now.tm_min, now.tm_sec);
144 if (now.tm_year < cert->valid_from.tm_year ||
145 (now.tm_year == cert->valid_from.tm_year &&
146 (now.tm_mon < cert->valid_from.tm_mon ||
147 (now.tm_mon == cert->valid_from.tm_mon &&
148 (now.tm_mday < cert->valid_from.tm_mday ||
149 (now.tm_mday == cert->valid_from.tm_mday &&
150 (now.tm_hour < cert->valid_from.tm_hour ||
151 (now.tm_hour == cert->valid_from.tm_hour &&
152 (now.tm_min < cert->valid_from.tm_min ||
153 (now.tm_min == cert->valid_from.tm_min &&
154 (now.tm_sec < cert->valid_from.tm_sec
155 ))))))))))) {
156 pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
157 ret = -EKEYREJECTED;
158 goto error_free_cert;
159 }
160 if (now.tm_year > cert->valid_to.tm_year ||
161 (now.tm_year == cert->valid_to.tm_year &&
162 (now.tm_mon > cert->valid_to.tm_mon ||
163 (now.tm_mon == cert->valid_to.tm_mon &&
164 (now.tm_mday > cert->valid_to.tm_mday ||
165 (now.tm_mday == cert->valid_to.tm_mday &&
166 (now.tm_hour > cert->valid_to.tm_hour ||
167 (now.tm_hour == cert->valid_to.tm_hour &&
168 (now.tm_min > cert->valid_to.tm_min ||
169 (now.tm_min == cert->valid_to.tm_min &&
170 (now.tm_sec > cert->valid_to.tm_sec
171 ))))))))))) {
172 pr_warn("Cert %s has expired\n", cert->fingerprint);
173 ret = -EKEYEXPIRED;
174 goto error_free_cert;
175 }
176
177 cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
178 cert->pub->id_type = PKEY_ID_X509; 228 cert->pub->id_type = PKEY_ID_X509;
179 229
180 /* Check the signature on the key */ 230 /* Check the signature on the key if it appears to be self-signed */
181 if (strcmp(cert->fingerprint, cert->authority) == 0) { 231 if (!cert->authority ||
182 ret = x509_check_signature(cert->pub, cert); 232 strcmp(cert->fingerprint, cert->authority) == 0) {
233 ret = x509_check_signature(cert->pub, cert); /* self-signed */
183 if (ret < 0) 234 if (ret < 0)
184 goto error_free_cert; 235 goto error_free_cert;
236 } else {
237 ret = x509_validate_trust(cert, system_trusted_keyring);
238 if (!ret)
239 prep->trusted = 1;
185 } 240 }
186 241
187 /* Propose a description */ 242 /* Propose a description */
@@ -237,3 +292,6 @@ static void __exit x509_key_exit(void)
237 292
238module_init(x509_key_init); 293module_init(x509_key_init);
239module_exit(x509_key_exit); 294module_exit(x509_key_exit);
295
296MODULE_DESCRIPTION("X.509 certificate parser");
297MODULE_LICENSE("GPL");
diff --git a/crypto/hash_info.c b/crypto/hash_info.c
new file mode 100644
index 000000000000..3e7ff46f26e8
--- /dev/null
+++ b/crypto/hash_info.c
@@ -0,0 +1,56 @@
1/*
2 * Hash Info: Hash algorithms information
3 *
4 * Copyright (c) 2013 Dmitry Kasatkin <d.kasatkin@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 */
12
13#include <linux/export.h>
14#include <crypto/hash_info.h>
15
16const char *const hash_algo_name[HASH_ALGO__LAST] = {
17 [HASH_ALGO_MD4] = "md4",
18 [HASH_ALGO_MD5] = "md5",
19 [HASH_ALGO_SHA1] = "sha1",
20 [HASH_ALGO_RIPE_MD_160] = "rmd160",
21 [HASH_ALGO_SHA256] = "sha256",
22 [HASH_ALGO_SHA384] = "sha384",
23 [HASH_ALGO_SHA512] = "sha512",
24 [HASH_ALGO_SHA224] = "sha224",
25 [HASH_ALGO_RIPE_MD_128] = "rmd128",
26 [HASH_ALGO_RIPE_MD_256] = "rmd256",
27 [HASH_ALGO_RIPE_MD_320] = "rmd320",
28 [HASH_ALGO_WP_256] = "wp256",
29 [HASH_ALGO_WP_384] = "wp384",
30 [HASH_ALGO_WP_512] = "wp512",
31 [HASH_ALGO_TGR_128] = "tgr128",
32 [HASH_ALGO_TGR_160] = "tgr160",
33 [HASH_ALGO_TGR_192] = "tgr192",
34};
35EXPORT_SYMBOL_GPL(hash_algo_name);
36
37const int hash_digest_size[HASH_ALGO__LAST] = {
38 [HASH_ALGO_MD4] = MD5_DIGEST_SIZE,
39 [HASH_ALGO_MD5] = MD5_DIGEST_SIZE,
40 [HASH_ALGO_SHA1] = SHA1_DIGEST_SIZE,
41 [HASH_ALGO_RIPE_MD_160] = RMD160_DIGEST_SIZE,
42 [HASH_ALGO_SHA256] = SHA256_DIGEST_SIZE,
43 [HASH_ALGO_SHA384] = SHA384_DIGEST_SIZE,
44 [HASH_ALGO_SHA512] = SHA512_DIGEST_SIZE,
45 [HASH_ALGO_SHA224] = SHA224_DIGEST_SIZE,
46 [HASH_ALGO_RIPE_MD_128] = RMD128_DIGEST_SIZE,
47 [HASH_ALGO_RIPE_MD_256] = RMD256_DIGEST_SIZE,
48 [HASH_ALGO_RIPE_MD_320] = RMD320_DIGEST_SIZE,
49 [HASH_ALGO_WP_256] = WP256_DIGEST_SIZE,
50 [HASH_ALGO_WP_384] = WP384_DIGEST_SIZE,
51 [HASH_ALGO_WP_512] = WP512_DIGEST_SIZE,
52 [HASH_ALGO_TGR_128] = TGR128_DIGEST_SIZE,
53 [HASH_ALGO_TGR_160] = TGR160_DIGEST_SIZE,
54 [HASH_ALGO_TGR_192] = TGR192_DIGEST_SIZE,
55};
56EXPORT_SYMBOL_GPL(hash_digest_size);