diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Kconfig | 3 | ||||
-rw-r--r-- | crypto/Makefile | 1 | ||||
-rw-r--r-- | crypto/asymmetric_keys/Kconfig | 4 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 1 | ||||
-rw-r--r-- | crypto/asymmetric_keys/public_key.c | 66 | ||||
-rw-r--r-- | crypto/asymmetric_keys/public_key.h | 6 | ||||
-rw-r--r-- | crypto/asymmetric_keys/rsa.c | 14 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 35 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 18 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 232 | ||||
-rw-r--r-- | crypto/hash_info.c | 56 |
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 | ||
1405 | config CRYPTO_HASH_INFO | ||
1406 | bool | ||
1407 | |||
1405 | source "drivers/crypto/Kconfig" | 1408 | source "drivers/crypto/Kconfig" |
1406 | source crypto/asymmetric_keys/Kconfig | 1409 | source 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 | |||
104 | obj-$(CONFIG_XOR_BLOCKS) += xor.o | 104 | obj-$(CONFIG_XOR_BLOCKS) += xor.o |
105 | obj-$(CONFIG_ASYNC_CORE) += async_tx/ | 105 | obj-$(CONFIG_ASYNC_CORE) += async_tx/ |
106 | obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ | 106 | obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ |
107 | obj-$(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 | |||
12 | config ASYMMETRIC_PUBLIC_KEY_SUBTYPE | 12 | config 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 | ||
21 | config PUBLIC_KEY_ALGO_RSA | 23 | config 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 | }; |
213 | EXPORT_SYMBOL_GPL(key_type_asymmetric); | 214 | EXPORT_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 | ||
23 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
24 | 24 | ||
25 | const char *const pkey_algo[PKEY_ALGO__LAST] = { | 25 | const 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 | }; |
29 | EXPORT_SYMBOL_GPL(pkey_algo); | 29 | EXPORT_SYMBOL_GPL(pkey_algo_name); |
30 | 30 | ||
31 | const char *const pkey_hash_algo[PKEY_HASH__LAST] = { | 31 | const 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 | }; |
41 | EXPORT_SYMBOL_GPL(pkey_hash_algo); | 37 | EXPORT_SYMBOL_GPL(pkey_algo); |
42 | 38 | ||
43 | const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { | 39 | const 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 | }; |
47 | EXPORT_SYMBOL_GPL(pkey_id_type); | 43 | EXPORT_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 | */ |
81 | static int public_key_verify_signature(const struct key *key, | 77 | int 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 | } | ||
109 | EXPORT_SYMBOL_GPL(public_key_verify_signature); | ||
110 | |||
111 | static 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 | }; |
108 | EXPORT_SYMBOL_GPL(public_key_subtype); | 128 | EXPORT_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 | ||
30 | extern const struct public_key_algorithm RSA_public_key_algorithm; | 30 | extern const struct public_key_algorithm RSA_public_key_algorithm; |
31 | |||
32 | /* | ||
33 | * public_key.c | ||
34 | */ | ||
35 | extern 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 | ||
14 | struct x509_certificate { | 15 | struct 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 | */ |
35 | extern void x509_free_certificate(struct x509_certificate *cert); | 34 | extern void x509_free_certificate(struct x509_certificate *cert); |
36 | extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); | 35 | extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); |
36 | |||
37 | /* | ||
38 | * x509_public_key.c | ||
39 | */ | ||
40 | extern int x509_get_sig_params(struct x509_certificate *cert); | ||
41 | extern 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 | ||
26 | static const | 27 | /* |
27 | struct 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) || \ | 30 | static 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 | */ |
38 | static int x509_check_signature(const struct public_key *pub, | 78 | int 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); | ||
126 | error: | ||
127 | crypto_free_shash(tfm); | ||
128 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
129 | return ret; | ||
130 | } | ||
131 | EXPORT_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; | 136 | int 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 | } | ||
151 | EXPORT_SYMBOL_GPL(x509_check_signature); | ||
91 | 152 | ||
92 | error_mpi: | 153 | /* |
93 | mpi_free(sig->rsa.s); | 154 | * Check the new certificate against the ones in the trust keyring. If one of |
94 | error: | 155 | * those is the signing key and validates the new certificate, then mark the |
95 | kfree(sig); | 156 | * new certificate as being trusted. |
96 | error_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 | */ | ||
162 | static 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: | |||
106 | static int x509_key_preparse(struct key_preparsed_payload *prep) | 183 | static 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 | ||
238 | module_init(x509_key_init); | 293 | module_init(x509_key_init); |
239 | module_exit(x509_key_exit); | 294 | module_exit(x509_key_exit); |
295 | |||
296 | MODULE_DESCRIPTION("X.509 certificate parser"); | ||
297 | MODULE_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 | |||
16 | const 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 | }; | ||
35 | EXPORT_SYMBOL_GPL(hash_algo_name); | ||
36 | |||
37 | const 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 | }; | ||
56 | EXPORT_SYMBOL_GPL(hash_digest_size); | ||