aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
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);