Commit | Line | Data |
---|---|---|
a9681bf3 DH |
1 | /* In-software asymmetric public-key crypto subtype |
2 | * | |
3 | * See Documentation/crypto/asymmetric-keys.txt | |
4 | * | |
5 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | |
6 | * Written by David Howells (dhowells@redhat.com) | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public Licence | |
10 | * as published by the Free Software Foundation; either version | |
11 | * 2 of the Licence, or (at your option) any later version. | |
12 | */ | |
13 | ||
14 | #define pr_fmt(fmt) "PKEY: "fmt | |
15 | #include <linux/module.h> | |
16 | #include <linux/export.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/slab.h> | |
19 | #include <linux/seq_file.h> | |
d43de6c7 | 20 | #include <linux/scatterlist.h> |
a9681bf3 | 21 | #include <keys/asymmetric-subtype.h> |
db6c43bd | 22 | #include <crypto/public_key.h> |
d43de6c7 | 23 | #include <crypto/akcipher.h> |
a9681bf3 DH |
24 | |
25 | MODULE_LICENSE("GPL"); | |
26 | ||
a9681bf3 DH |
27 | /* |
28 | * Provide a part of a description of the key for /proc/keys. | |
29 | */ | |
30 | static void public_key_describe(const struct key *asymmetric_key, | |
31 | struct seq_file *m) | |
32 | { | |
146aa8b1 | 33 | struct public_key *key = asymmetric_key->payload.data[asym_crypto]; |
a9681bf3 DH |
34 | |
35 | if (key) | |
4e8ae72a | 36 | seq_printf(m, "%s.%s", key->id_type, key->pkey_algo); |
a9681bf3 DH |
37 | } |
38 | ||
39 | /* | |
40 | * Destroy a public key algorithm key. | |
41 | */ | |
3b764563 | 42 | void public_key_free(struct public_key *key) |
a9681bf3 | 43 | { |
3b764563 | 44 | if (key) { |
db6c43bd | 45 | kfree(key->key); |
3b764563 DH |
46 | kfree(key); |
47 | } | |
48 | } | |
49 | EXPORT_SYMBOL_GPL(public_key_free); | |
50 | ||
51 | /* | |
52 | * Destroy a public key algorithm key. | |
53 | */ | |
54 | static void public_key_destroy(void *payload0, void *payload3) | |
55 | { | |
56 | public_key_free(payload0); | |
57 | public_key_signature_free(payload3); | |
a9681bf3 | 58 | } |
a9681bf3 | 59 | |
3aa4e80d DH |
60 | /* |
61 | * Determine the crypto algorithm name. | |
62 | */ | |
63 | static | |
64 | int software_key_determine_akcipher(const char *encoding, | |
65 | const char *hash_algo, | |
66 | const struct public_key *pkey, | |
67 | char alg_name[CRYPTO_MAX_ALG_NAME]) | |
68 | { | |
69 | int n; | |
70 | ||
71 | if (strcmp(encoding, "pkcs1") == 0) { | |
72 | /* The data wangled by the RSA algorithm is typically padded | |
73 | * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 | |
74 | * sec 8.2]. | |
75 | */ | |
76 | if (!hash_algo) | |
77 | n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, | |
78 | "pkcs1pad(%s)", | |
79 | pkey->pkey_algo); | |
80 | else | |
81 | n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, | |
82 | "pkcs1pad(%s,%s)", | |
83 | pkey->pkey_algo, hash_algo); | |
84 | return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0; | |
85 | } | |
86 | ||
87 | if (strcmp(encoding, "raw") == 0) { | |
88 | strcpy(alg_name, pkey->pkey_algo); | |
89 | return 0; | |
90 | } | |
91 | ||
92 | return -ENOPKG; | |
93 | } | |
94 | ||
95 | /* | |
96 | * Query information about a key. | |
97 | */ | |
98 | static int software_key_query(const struct kernel_pkey_params *params, | |
99 | struct kernel_pkey_query *info) | |
100 | { | |
101 | struct crypto_akcipher *tfm; | |
102 | struct public_key *pkey = params->key->payload.data[asym_crypto]; | |
103 | char alg_name[CRYPTO_MAX_ALG_NAME]; | |
104 | int ret, len; | |
105 | ||
106 | ret = software_key_determine_akcipher(params->encoding, | |
107 | params->hash_algo, | |
108 | pkey, alg_name); | |
109 | if (ret < 0) | |
110 | return ret; | |
111 | ||
112 | tfm = crypto_alloc_akcipher(alg_name, 0, 0); | |
113 | if (IS_ERR(tfm)) | |
114 | return PTR_ERR(tfm); | |
115 | ||
b19b107b DH |
116 | if (pkey->key_is_private) |
117 | ret = crypto_akcipher_set_priv_key(tfm, | |
118 | pkey->key, pkey->keylen); | |
119 | else | |
120 | ret = crypto_akcipher_set_pub_key(tfm, | |
121 | pkey->key, pkey->keylen); | |
3aa4e80d DH |
122 | if (ret < 0) |
123 | goto error_free_tfm; | |
124 | ||
125 | len = crypto_akcipher_maxsize(tfm); | |
126 | info->key_size = len * 8; | |
127 | info->max_data_size = len; | |
128 | info->max_sig_size = len; | |
129 | info->max_enc_size = len; | |
130 | info->max_dec_size = len; | |
3a8b45d6 DH |
131 | info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT | |
132 | KEYCTL_SUPPORTS_VERIFY); | |
133 | if (pkey->key_is_private) | |
134 | info->supported_ops |= (KEYCTL_SUPPORTS_DECRYPT | | |
135 | KEYCTL_SUPPORTS_SIGN); | |
3aa4e80d DH |
136 | ret = 0; |
137 | ||
138 | error_free_tfm: | |
139 | crypto_free_akcipher(tfm); | |
140 | pr_devel("<==%s() = %d\n", __func__, ret); | |
141 | return ret; | |
142 | } | |
143 | ||
d43de6c7 DH |
144 | struct public_key_completion { |
145 | struct completion completion; | |
146 | int err; | |
147 | }; | |
148 | ||
3a8b45d6 | 149 | static void public_key_crypto_done(struct crypto_async_request *req, int err) |
d43de6c7 DH |
150 | { |
151 | struct public_key_completion *compl = req->data; | |
152 | ||
153 | if (err == -EINPROGRESS) | |
154 | return; | |
155 | ||
156 | compl->err = err; | |
157 | complete(&compl->completion); | |
158 | } | |
159 | ||
3a8b45d6 DH |
160 | /* |
161 | * Do encryption, decryption and signing ops. | |
162 | */ | |
163 | static int software_key_eds_op(struct kernel_pkey_params *params, | |
164 | const void *in, void *out) | |
165 | { | |
166 | struct public_key_completion compl; | |
167 | const struct public_key *pkey = params->key->payload.data[asym_crypto]; | |
168 | struct akcipher_request *req; | |
169 | struct crypto_akcipher *tfm; | |
170 | struct scatterlist in_sg, out_sg; | |
171 | char alg_name[CRYPTO_MAX_ALG_NAME]; | |
172 | int ret; | |
173 | ||
174 | pr_devel("==>%s()\n", __func__); | |
175 | ||
176 | ret = software_key_determine_akcipher(params->encoding, | |
177 | params->hash_algo, | |
178 | pkey, alg_name); | |
179 | if (ret < 0) | |
180 | return ret; | |
181 | ||
182 | tfm = crypto_alloc_akcipher(alg_name, 0, 0); | |
183 | if (IS_ERR(tfm)) | |
184 | return PTR_ERR(tfm); | |
185 | ||
186 | req = akcipher_request_alloc(tfm, GFP_KERNEL); | |
187 | if (!req) | |
188 | goto error_free_tfm; | |
189 | ||
190 | if (pkey->key_is_private) | |
191 | ret = crypto_akcipher_set_priv_key(tfm, | |
192 | pkey->key, pkey->keylen); | |
193 | else | |
194 | ret = crypto_akcipher_set_pub_key(tfm, | |
195 | pkey->key, pkey->keylen); | |
196 | if (ret) | |
197 | goto error_free_req; | |
198 | ||
199 | sg_init_one(&in_sg, in, params->in_len); | |
200 | sg_init_one(&out_sg, out, params->out_len); | |
201 | akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len, | |
202 | params->out_len); | |
203 | init_completion(&compl.completion); | |
204 | akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | | |
205 | CRYPTO_TFM_REQ_MAY_SLEEP, | |
206 | public_key_crypto_done, &compl); | |
207 | ||
208 | /* Perform the encryption calculation. */ | |
209 | switch (params->op) { | |
210 | case kernel_pkey_encrypt: | |
211 | ret = crypto_akcipher_encrypt(req); | |
212 | break; | |
213 | case kernel_pkey_decrypt: | |
214 | ret = crypto_akcipher_decrypt(req); | |
215 | break; | |
216 | case kernel_pkey_sign: | |
217 | ret = crypto_akcipher_sign(req); | |
218 | break; | |
219 | default: | |
220 | BUG(); | |
221 | } | |
222 | if (ret == -EINPROGRESS) { | |
223 | wait_for_completion(&compl.completion); | |
224 | ret = compl.err; | |
225 | } | |
226 | ||
227 | if (ret == 0) | |
228 | ret = req->dst_len; | |
229 | ||
230 | error_free_req: | |
231 | akcipher_request_free(req); | |
232 | error_free_tfm: | |
233 | crypto_free_akcipher(tfm); | |
234 | pr_devel("<==%s() = %d\n", __func__, ret); | |
235 | return ret; | |
236 | } | |
237 | ||
a9681bf3 DH |
238 | /* |
239 | * Verify a signature using a public key. | |
240 | */ | |
db6c43bd | 241 | int public_key_verify_signature(const struct public_key *pkey, |
3d167d68 | 242 | const struct public_key_signature *sig) |
a9681bf3 | 243 | { |
d43de6c7 DH |
244 | struct public_key_completion compl; |
245 | struct crypto_akcipher *tfm; | |
246 | struct akcipher_request *req; | |
247 | struct scatterlist sig_sg, digest_sg; | |
3aa4e80d | 248 | char alg_name[CRYPTO_MAX_ALG_NAME]; |
d43de6c7 DH |
249 | void *output; |
250 | unsigned int outlen; | |
251 | int ret = -ENOMEM; | |
252 | ||
253 | pr_devel("==>%s()\n", __func__); | |
254 | ||
db6c43bd | 255 | BUG_ON(!pkey); |
3d167d68 DH |
256 | BUG_ON(!sig); |
257 | BUG_ON(!sig->digest); | |
db6c43bd | 258 | BUG_ON(!sig->s); |
a9681bf3 | 259 | |
3aa4e80d DH |
260 | ret = software_key_determine_akcipher(sig->encoding, |
261 | sig->hash_algo, | |
262 | pkey, alg_name); | |
263 | if (ret < 0) | |
264 | return ret; | |
d43de6c7 DH |
265 | |
266 | tfm = crypto_alloc_akcipher(alg_name, 0, 0); | |
267 | if (IS_ERR(tfm)) | |
268 | return PTR_ERR(tfm); | |
269 | ||
270 | req = akcipher_request_alloc(tfm, GFP_KERNEL); | |
271 | if (!req) | |
272 | goto error_free_tfm; | |
273 | ||
b19b107b DH |
274 | if (pkey->key_is_private) |
275 | ret = crypto_akcipher_set_priv_key(tfm, | |
276 | pkey->key, pkey->keylen); | |
277 | else | |
278 | ret = crypto_akcipher_set_pub_key(tfm, | |
279 | pkey->key, pkey->keylen); | |
d43de6c7 DH |
280 | if (ret) |
281 | goto error_free_req; | |
282 | ||
283 | outlen = crypto_akcipher_maxsize(tfm); | |
284 | output = kmalloc(outlen, GFP_KERNEL); | |
285 | if (!output) | |
286 | goto error_free_req; | |
287 | ||
288 | sg_init_one(&sig_sg, sig->s, sig->s_size); | |
289 | sg_init_one(&digest_sg, output, outlen); | |
290 | akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, | |
291 | outlen); | |
292 | init_completion(&compl.completion); | |
293 | akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | | |
294 | CRYPTO_TFM_REQ_MAY_SLEEP, | |
3a8b45d6 | 295 | public_key_crypto_done, &compl); |
d43de6c7 DH |
296 | |
297 | /* Perform the verification calculation. This doesn't actually do the | |
298 | * verification, but rather calculates the hash expected by the | |
299 | * signature and returns that to us. | |
300 | */ | |
301 | ret = crypto_akcipher_verify(req); | |
302 | if (ret == -EINPROGRESS) { | |
303 | wait_for_completion(&compl.completion); | |
304 | ret = compl.err; | |
305 | } | |
306 | if (ret < 0) | |
307 | goto out_free_output; | |
a9681bf3 | 308 | |
d43de6c7 DH |
309 | /* Do the actual verification step. */ |
310 | if (req->dst_len != sig->digest_size || | |
311 | memcmp(sig->digest, output, sig->digest_size) != 0) | |
312 | ret = -EKEYREJECTED; | |
a9681bf3 | 313 | |
d43de6c7 DH |
314 | out_free_output: |
315 | kfree(output); | |
316 | error_free_req: | |
317 | akcipher_request_free(req); | |
318 | error_free_tfm: | |
319 | crypto_free_akcipher(tfm); | |
320 | pr_devel("<==%s() = %d\n", __func__, ret); | |
321 | return ret; | |
3d167d68 DH |
322 | } |
323 | EXPORT_SYMBOL_GPL(public_key_verify_signature); | |
324 | ||
325 | static int public_key_verify_signature_2(const struct key *key, | |
326 | const struct public_key_signature *sig) | |
327 | { | |
146aa8b1 | 328 | const struct public_key *pk = key->payload.data[asym_crypto]; |
3d167d68 | 329 | return public_key_verify_signature(pk, sig); |
a9681bf3 DH |
330 | } |
331 | ||
332 | /* | |
333 | * Public key algorithm asymmetric key subtype | |
334 | */ | |
335 | struct asymmetric_key_subtype public_key_subtype = { | |
336 | .owner = THIS_MODULE, | |
337 | .name = "public_key", | |
876c6e3e | 338 | .name_len = sizeof("public_key") - 1, |
a9681bf3 DH |
339 | .describe = public_key_describe, |
340 | .destroy = public_key_destroy, | |
3aa4e80d | 341 | .query = software_key_query, |
3a8b45d6 | 342 | .eds_op = software_key_eds_op, |
3d167d68 | 343 | .verify_signature = public_key_verify_signature_2, |
a9681bf3 DH |
344 | }; |
345 | EXPORT_SYMBOL_GPL(public_key_subtype); |