aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys/x509_public_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/asymmetric_keys/x509_public_key.c')
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c157
1 files changed, 68 insertions, 89 deletions
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 06007f0e880c..382ef0d2ff2e 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -23,82 +23,84 @@
23#include "public_key.h" 23#include "public_key.h"
24#include "x509_parser.h" 24#include "x509_parser.h"
25 25
26static const
27struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = {
28 [PKEY_ALGO_DSA] = NULL,
29#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
30 defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
31 [PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
32#endif
33};
34
35/* 26/*
36 * Check the signature on a certificate using the provided public key 27 * Set up the signature parameters in an X.509 certificate. This involves
28 * digesting the signed data and extracting the signature.
37 */ 29 */
38static int x509_check_signature(const struct public_key *pub, 30int x509_get_sig_params(struct x509_certificate *cert)
39 const struct x509_certificate *cert)
40{ 31{
41 struct public_key_signature *sig;
42 struct crypto_shash *tfm; 32 struct crypto_shash *tfm;
43 struct shash_desc *desc; 33 struct shash_desc *desc;
44 size_t digest_size, desc_size; 34 size_t digest_size, desc_size;
35 void *digest;
45 int ret; 36 int ret;
46 37
47 pr_devel("==>%s()\n", __func__); 38 pr_devel("==>%s()\n", __func__);
48 39
40 if (cert->sig.rsa.s)
41 return 0;
42
43 cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
44 if (!cert->sig.rsa.s)
45 return -ENOMEM;
46 cert->sig.nr_mpi = 1;
47
49 /* Allocate the hashing algorithm we're going to need and find out how 48 /* Allocate the hashing algorithm we're going to need and find out how
50 * big the hash operational data will be. 49 * big the hash operational data will be.
51 */ 50 */
52 tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); 51 tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
53 if (IS_ERR(tfm)) 52 if (IS_ERR(tfm))
54 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 53 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
55 54
56 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 55 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
57 digest_size = crypto_shash_digestsize(tfm); 56 digest_size = crypto_shash_digestsize(tfm);
58 57
59 /* We allocate the hash operational data storage on the end of our 58 /* We allocate the hash operational data storage on the end of the
60 * context data. 59 * digest storage space.
61 */ 60 */
62 ret = -ENOMEM; 61 ret = -ENOMEM;
63 sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); 62 digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
64 if (!sig) 63 if (!digest)
65 goto error_no_sig; 64 goto error;
66 65
67 sig->pkey_hash_algo = cert->sig_hash_algo; 66 cert->sig.digest = digest;
68 sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; 67 cert->sig.digest_size = digest_size;
69 sig->digest_size = digest_size;
70 68
71 desc = (void *)sig + sizeof(*sig); 69 desc = digest + digest_size;
72 desc->tfm = tfm; 70 desc->tfm = tfm;
73 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 71 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
74 72
75 ret = crypto_shash_init(desc); 73 ret = crypto_shash_init(desc);
76 if (ret < 0) 74 if (ret < 0)
77 goto error; 75 goto error;
76 might_sleep();
77 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest);
78error:
79 crypto_free_shash(tfm);
80 pr_devel("<==%s() = %d\n", __func__, ret);
81 return ret;
82}
83EXPORT_SYMBOL_GPL(x509_get_sig_params);
78 84
79 ret = -ENOMEM; 85/*
80 sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); 86 * Check the signature on a certificate using the provided public key
81 if (!sig->rsa.s) 87 */
82 goto error; 88int x509_check_signature(const struct public_key *pub,
89 struct x509_certificate *cert)
90{
91 int ret;
83 92
84 ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); 93 pr_devel("==>%s()\n", __func__);
85 if (ret < 0)
86 goto error_mpi;
87 94
88 ret = pub->algo->verify_signature(pub, sig); 95 ret = x509_get_sig_params(cert);
96 if (ret < 0)
97 return ret;
89 98
99 ret = public_key_verify_signature(pub, &cert->sig);
90 pr_debug("Cert Verification: %d\n", ret); 100 pr_debug("Cert Verification: %d\n", ret);
91
92error_mpi:
93 mpi_free(sig->rsa.s);
94error:
95 kfree(sig);
96error_no_sig:
97 crypto_free_shash(tfm);
98
99 pr_devel("<==%s() = %d\n", __func__, ret);
100 return ret; 101 return ret;
101} 102}
103EXPORT_SYMBOL_GPL(x509_check_signature);
102 104
103/* 105/*
104 * Attempt to parse a data blob for a key as an X509 certificate. 106 * Attempt to parse a data blob for a key as an X509 certificate.
@@ -106,7 +108,6 @@ error_no_sig:
106static int x509_key_preparse(struct key_preparsed_payload *prep) 108static int x509_key_preparse(struct key_preparsed_payload *prep)
107{ 109{
108 struct x509_certificate *cert; 110 struct x509_certificate *cert;
109 struct tm now;
110 size_t srlen, sulen; 111 size_t srlen, sulen;
111 char *desc = NULL; 112 char *desc = NULL;
112 int ret; 113 int ret;
@@ -117,7 +118,18 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
117 118
118 pr_devel("Cert Issuer: %s\n", cert->issuer); 119 pr_devel("Cert Issuer: %s\n", cert->issuer);
119 pr_devel("Cert Subject: %s\n", cert->subject); 120 pr_devel("Cert Subject: %s\n", cert->subject);
120 pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); 121
122 if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
123 cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
124 cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
125 !pkey_algo[cert->pub->pkey_algo] ||
126 !pkey_algo[cert->sig.pkey_algo] ||
127 !hash_algo_name[cert->sig.pkey_hash_algo]) {
128 ret = -ENOPKG;
129 goto error_free_cert;
130 }
131
132 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", 133 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, 134 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
123 cert->valid_from.tm_mday, cert->valid_from.tm_hour, 135 cert->valid_from.tm_mday, cert->valid_from.tm_hour,
@@ -127,58 +139,22 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
127 cert->valid_to.tm_mday, cert->valid_to.tm_hour, 139 cert->valid_to.tm_mday, cert->valid_to.tm_hour,
128 cert->valid_to.tm_min, cert->valid_to.tm_sec); 140 cert->valid_to.tm_min, cert->valid_to.tm_sec);
129 pr_devel("Cert Signature: %s + %s\n", 141 pr_devel("Cert Signature: %s + %s\n",
130 pkey_algo[cert->sig_pkey_algo], 142 pkey_algo_name[cert->sig.pkey_algo],
131 pkey_hash_algo[cert->sig_hash_algo]); 143 hash_algo_name[cert->sig.pkey_hash_algo]);
132 144
133 if (!cert->fingerprint || !cert->authority) { 145 if (!cert->fingerprint) {
134 pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", 146 pr_warn("Cert for '%s' must have a SubjKeyId extension\n",
135 cert->subject); 147 cert->subject);
136 ret = -EKEYREJECTED; 148 ret = -EKEYREJECTED;
137 goto error_free_cert; 149 goto error_free_cert;
138 } 150 }
139 151
140 time_to_tm(CURRENT_TIME.tv_sec, 0, &now); 152 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; 153 cert->pub->id_type = PKEY_ID_X509;
179 154
180 /* Check the signature on the key */ 155 /* Check the signature on the key if it appears to be self-signed */
181 if (strcmp(cert->fingerprint, cert->authority) == 0) { 156 if (!cert->authority ||
157 strcmp(cert->fingerprint, cert->authority) == 0) {
182 ret = x509_check_signature(cert->pub, cert); 158 ret = x509_check_signature(cert->pub, cert);
183 if (ret < 0) 159 if (ret < 0)
184 goto error_free_cert; 160 goto error_free_cert;
@@ -237,3 +213,6 @@ static void __exit x509_key_exit(void)
237 213
238module_init(x509_key_init); 214module_init(x509_key_init);
239module_exit(x509_key_exit); 215module_exit(x509_key_exit);
216
217MODULE_DESCRIPTION("X.509 certificate parser");
218MODULE_LICENSE("GPL");