blob: 6efe951c057c8834921306243fa579784c91cc94 [file] [log] [blame]
AKASHI Takahirocbb10072019-11-13 09:44:58 +09001// SPDX-License-Identifier: GPL-2.0-or-later
2/* In-software asymmetric public-key crypto subtype
3 *
4 * See Documentation/crypto/asymmetric-keys.txt
5 *
6 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
7 * Written by David Howells (dhowells@redhat.com)
8 */
9
10#define pr_fmt(fmt) "PKEY: "fmt
11#ifdef __UBOOT__
Simon Glassd66c5f72020-02-03 07:36:15 -070012#include <dm/devres.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060013#include <linux/bug.h>
AKASHI Takahirocbb10072019-11-13 09:44:58 +090014#include <linux/compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070015#include <linux/err.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060016#include <linux/printk.h>
AKASHI Takahirocbb10072019-11-13 09:44:58 +090017#else
18#include <linux/module.h>
19#include <linux/export.h>
20#endif
21#include <linux/kernel.h>
22#ifndef __UBOOT__
23#include <linux/slab.h>
24#include <linux/seq_file.h>
25#include <linux/scatterlist.h>
26#include <keys/asymmetric-subtype.h>
27#endif
28#include <crypto/public_key.h>
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +090029#ifdef __UBOOT__
30#include <image.h>
31#include <u-boot/rsa.h>
32#else
AKASHI Takahirocbb10072019-11-13 09:44:58 +090033#include <crypto/akcipher.h>
34#endif
35
36MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
37MODULE_AUTHOR("Red Hat, Inc.");
38MODULE_LICENSE("GPL");
39
40#ifndef __UBOOT__
41/*
42 * Provide a part of a description of the key for /proc/keys.
43 */
44static void public_key_describe(const struct key *asymmetric_key,
45 struct seq_file *m)
46{
47 struct public_key *key = asymmetric_key->payload.data[asym_crypto];
48
49 if (key)
50 seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
51}
52#endif
53
54/*
55 * Destroy a public key algorithm key.
56 */
57void public_key_free(struct public_key *key)
58{
59 if (key) {
60 kfree(key->key);
61 kfree(key->params);
62 kfree(key);
63 }
64}
65EXPORT_SYMBOL_GPL(public_key_free);
66
67#ifdef __UBOOT__
68/*
69 * from <linux>/crypto/asymmetric_keys/signature.c
70 *
71 * Destroy a public key signature.
72 */
73void public_key_signature_free(struct public_key_signature *sig)
74{
75 int i;
76
77 if (sig) {
78 for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++)
79 free(sig->auth_ids[i]);
80 free(sig->s);
81 free(sig->digest);
82 free(sig);
83 }
84}
85EXPORT_SYMBOL_GPL(public_key_signature_free);
86
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +090087/**
88 * public_key_verify_signature - Verify a signature using a public key.
89 *
90 * @pkey: Public key
91 * @sig: Signature
92 *
93 * Verify a signature, @sig, using a RSA public key, @pkey.
94 *
95 * Return: 0 - verified, non-zero error code - otherwise
96 */
97int public_key_verify_signature(const struct public_key *pkey,
98 const struct public_key_signature *sig)
99{
100 struct image_sign_info info;
Ilias Apalodimascde8bae2022-01-19 13:54:41 +0200101 char algo[256];
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900102 int ret;
103
104 pr_devel("==>%s()\n", __func__);
105
106 if (!pkey || !sig)
107 return -EINVAL;
108
109 if (pkey->key_is_private)
110 return -EINVAL;
111
112 memset(&info, '\0', sizeof(info));
Ilias Apalodimascde8bae2022-01-19 13:54:41 +0200113 memset(algo, 0, sizeof(algo));
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900114 info.padding = image_get_padding_algo("pkcs-1.5");
Ilias Apalodimascde8bae2022-01-19 13:54:41 +0200115 if (strcmp(sig->pkey_algo, "rsa")) {
116 pr_err("Encryption is not RSA: %s\n", sig->pkey_algo);
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900117 return -ENOPKG;
118 }
Ilias Apalodimascde8bae2022-01-19 13:54:41 +0200119 ret = snprintf(algo, sizeof(algo), "%s,%s%d", sig->hash_algo,
120 sig->pkey_algo, sig->s_size * 8);
121
122 if (ret >= sizeof(algo))
123 return -EINVAL;
124
125 info.checksum = image_get_checksum_algo((const char *)algo);
126 info.name = (const char *)algo;
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900127 info.crypto = image_get_crypto_algo(info.name);
Ilias Apalodimascde8bae2022-01-19 13:54:41 +0200128 if (!info.checksum || !info.crypto) {
129 pr_err("<%s> not supported on image_get_(checksum|crypto)_algo()\n",
130 algo);
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900131 return -ENOPKG;
Ilias Apalodimascde8bae2022-01-19 13:54:41 +0200132 }
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900133
134 info.key = pkey->key;
135 info.keylen = pkey->keylen;
136
AKASHI Takahiro697b4cc2020-07-21 19:35:17 +0900137 if (rsa_verify_with_pkey(&info, sig->digest, sig->s, sig->s_size))
138 ret = -EKEYREJECTED;
139 else
140 ret = 0;
141
142 pr_devel("<==%s() = %d\n", __func__, ret);
143 return ret;
144}
AKASHI Takahirocbb10072019-11-13 09:44:58 +0900145#else
146/*
147 * Destroy a public key algorithm key.
148 */
149static void public_key_destroy(void *payload0, void *payload3)
150{
151 public_key_free(payload0);
152 public_key_signature_free(payload3);
153}
154
155/*
156 * Determine the crypto algorithm name.
157 */
158static
159int software_key_determine_akcipher(const char *encoding,
160 const char *hash_algo,
161 const struct public_key *pkey,
162 char alg_name[CRYPTO_MAX_ALG_NAME])
163{
164 int n;
165
166 if (strcmp(encoding, "pkcs1") == 0) {
167 /* The data wangled by the RSA algorithm is typically padded
168 * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
169 * sec 8.2].
170 */
171 if (!hash_algo)
172 n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
173 "pkcs1pad(%s)",
174 pkey->pkey_algo);
175 else
176 n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
177 "pkcs1pad(%s,%s)",
178 pkey->pkey_algo, hash_algo);
179 return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
180 }
181
182 if (strcmp(encoding, "raw") == 0) {
183 strcpy(alg_name, pkey->pkey_algo);
184 return 0;
185 }
186
187 return -ENOPKG;
188}
189
190static u8 *pkey_pack_u32(u8 *dst, u32 val)
191{
192 memcpy(dst, &val, sizeof(val));
193 return dst + sizeof(val);
194}
195
196/*
197 * Query information about a key.
198 */
199static int software_key_query(const struct kernel_pkey_params *params,
200 struct kernel_pkey_query *info)
201{
202 struct crypto_akcipher *tfm;
203 struct public_key *pkey = params->key->payload.data[asym_crypto];
204 char alg_name[CRYPTO_MAX_ALG_NAME];
205 u8 *key, *ptr;
206 int ret, len;
207
208 ret = software_key_determine_akcipher(params->encoding,
209 params->hash_algo,
210 pkey, alg_name);
211 if (ret < 0)
212 return ret;
213
214 tfm = crypto_alloc_akcipher(alg_name, 0, 0);
215 if (IS_ERR(tfm))
216 return PTR_ERR(tfm);
217
218 key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
219 GFP_KERNEL);
220 if (!key)
221 goto error_free_tfm;
222 memcpy(key, pkey->key, pkey->keylen);
223 ptr = key + pkey->keylen;
224 ptr = pkey_pack_u32(ptr, pkey->algo);
225 ptr = pkey_pack_u32(ptr, pkey->paramlen);
226 memcpy(ptr, pkey->params, pkey->paramlen);
227
228 if (pkey->key_is_private)
229 ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
230 else
231 ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
232 if (ret < 0)
233 goto error_free_key;
234
235 len = crypto_akcipher_maxsize(tfm);
236 info->key_size = len * 8;
237 info->max_data_size = len;
238 info->max_sig_size = len;
239 info->max_enc_size = len;
240 info->max_dec_size = len;
241 info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |
242 KEYCTL_SUPPORTS_VERIFY);
243 if (pkey->key_is_private)
244 info->supported_ops |= (KEYCTL_SUPPORTS_DECRYPT |
245 KEYCTL_SUPPORTS_SIGN);
246 ret = 0;
247
248error_free_key:
249 kfree(key);
250error_free_tfm:
251 crypto_free_akcipher(tfm);
252 pr_devel("<==%s() = %d\n", __func__, ret);
253 return ret;
254}
255
256/*
257 * Do encryption, decryption and signing ops.
258 */
259static int software_key_eds_op(struct kernel_pkey_params *params,
260 const void *in, void *out)
261{
262 const struct public_key *pkey = params->key->payload.data[asym_crypto];
263 struct akcipher_request *req;
264 struct crypto_akcipher *tfm;
265 struct crypto_wait cwait;
266 struct scatterlist in_sg, out_sg;
267 char alg_name[CRYPTO_MAX_ALG_NAME];
268 char *key, *ptr;
269 int ret;
270
271 pr_devel("==>%s()\n", __func__);
272
273 ret = software_key_determine_akcipher(params->encoding,
274 params->hash_algo,
275 pkey, alg_name);
276 if (ret < 0)
277 return ret;
278
279 tfm = crypto_alloc_akcipher(alg_name, 0, 0);
280 if (IS_ERR(tfm))
281 return PTR_ERR(tfm);
282
283 req = akcipher_request_alloc(tfm, GFP_KERNEL);
284 if (!req)
285 goto error_free_tfm;
286
287 key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
288 GFP_KERNEL);
289 if (!key)
290 goto error_free_req;
291
292 memcpy(key, pkey->key, pkey->keylen);
293 ptr = key + pkey->keylen;
294 ptr = pkey_pack_u32(ptr, pkey->algo);
295 ptr = pkey_pack_u32(ptr, pkey->paramlen);
296 memcpy(ptr, pkey->params, pkey->paramlen);
297
298 if (pkey->key_is_private)
299 ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
300 else
301 ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
302 if (ret)
303 goto error_free_key;
304
305 sg_init_one(&in_sg, in, params->in_len);
306 sg_init_one(&out_sg, out, params->out_len);
307 akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
308 params->out_len);
309 crypto_init_wait(&cwait);
310 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
311 CRYPTO_TFM_REQ_MAY_SLEEP,
312 crypto_req_done, &cwait);
313
314 /* Perform the encryption calculation. */
315 switch (params->op) {
316 case kernel_pkey_encrypt:
317 ret = crypto_akcipher_encrypt(req);
318 break;
319 case kernel_pkey_decrypt:
320 ret = crypto_akcipher_decrypt(req);
321 break;
322 case kernel_pkey_sign:
323 ret = crypto_akcipher_sign(req);
324 break;
325 default:
326 BUG();
327 }
328
329 ret = crypto_wait_req(ret, &cwait);
330 if (ret == 0)
331 ret = req->dst_len;
332
333error_free_key:
334 kfree(key);
335error_free_req:
336 akcipher_request_free(req);
337error_free_tfm:
338 crypto_free_akcipher(tfm);
339 pr_devel("<==%s() = %d\n", __func__, ret);
340 return ret;
341}
342
343/*
344 * Verify a signature using a public key.
345 */
346int public_key_verify_signature(const struct public_key *pkey,
347 const struct public_key_signature *sig)
348{
349 struct crypto_wait cwait;
350 struct crypto_akcipher *tfm;
351 struct akcipher_request *req;
352 struct scatterlist src_sg[2];
353 char alg_name[CRYPTO_MAX_ALG_NAME];
354 char *key, *ptr;
355 int ret;
356
357 pr_devel("==>%s()\n", __func__);
358
359 BUG_ON(!pkey);
360 BUG_ON(!sig);
361 BUG_ON(!sig->s);
362
363 ret = software_key_determine_akcipher(sig->encoding,
364 sig->hash_algo,
365 pkey, alg_name);
366 if (ret < 0)
367 return ret;
368
369 tfm = crypto_alloc_akcipher(alg_name, 0, 0);
370 if (IS_ERR(tfm))
371 return PTR_ERR(tfm);
372
373 ret = -ENOMEM;
374 req = akcipher_request_alloc(tfm, GFP_KERNEL);
375 if (!req)
376 goto error_free_tfm;
377
378 key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
379 GFP_KERNEL);
380 if (!key)
381 goto error_free_req;
382
383 memcpy(key, pkey->key, pkey->keylen);
384 ptr = key + pkey->keylen;
385 ptr = pkey_pack_u32(ptr, pkey->algo);
386 ptr = pkey_pack_u32(ptr, pkey->paramlen);
387 memcpy(ptr, pkey->params, pkey->paramlen);
388
389 if (pkey->key_is_private)
390 ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
391 else
392 ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
393 if (ret)
394 goto error_free_key;
395
396 sg_init_table(src_sg, 2);
397 sg_set_buf(&src_sg[0], sig->s, sig->s_size);
398 sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
399 akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
400 sig->digest_size);
401 crypto_init_wait(&cwait);
402 akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
403 CRYPTO_TFM_REQ_MAY_SLEEP,
404 crypto_req_done, &cwait);
405 ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
406
407error_free_key:
408 kfree(key);
409error_free_req:
410 akcipher_request_free(req);
411error_free_tfm:
412 crypto_free_akcipher(tfm);
413 pr_devel("<==%s() = %d\n", __func__, ret);
414 if (WARN_ON_ONCE(ret > 0))
415 ret = -EINVAL;
416 return ret;
417}
418EXPORT_SYMBOL_GPL(public_key_verify_signature);
419
420static int public_key_verify_signature_2(const struct key *key,
421 const struct public_key_signature *sig)
422{
423 const struct public_key *pk = key->payload.data[asym_crypto];
424 return public_key_verify_signature(pk, sig);
425}
426
427/*
428 * Public key algorithm asymmetric key subtype
429 */
430struct asymmetric_key_subtype public_key_subtype = {
431 .owner = THIS_MODULE,
432 .name = "public_key",
433 .name_len = sizeof("public_key") - 1,
434 .describe = public_key_describe,
435 .destroy = public_key_destroy,
436 .query = software_key_query,
437 .eds_op = software_key_eds_op,
438 .verify_signature = public_key_verify_signature_2,
439};
440EXPORT_SYMBOL_GPL(public_key_subtype);
441#endif /* !__UBOOT__ */