xref: /openbmc/linux/crypto/akcipher.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23c339ab8STadeusz Struk /*
33c339ab8STadeusz Struk  * Public Key Encryption
43c339ab8STadeusz Struk  *
53c339ab8STadeusz Struk  * Copyright (c) 2015, Intel Corporation
63c339ab8STadeusz Struk  * Authors: Tadeusz Struk <tadeusz.struk@intel.com>
73c339ab8STadeusz Struk  */
8035d78a1SHerbert Xu #include <crypto/internal/akcipher.h>
9035d78a1SHerbert Xu #include <linux/cryptouser.h>
103c339ab8STadeusz Struk #include <linux/errno.h>
113c339ab8STadeusz Struk #include <linux/kernel.h>
123c339ab8STadeusz Struk #include <linux/module.h>
133c339ab8STadeusz Struk #include <linux/scatterlist.h>
143c339ab8STadeusz Struk #include <linux/seq_file.h>
153c339ab8STadeusz Struk #include <linux/slab.h>
163c339ab8STadeusz Struk #include <linux/string.h>
17035d78a1SHerbert Xu #include <net/netlink.h>
183c339ab8STadeusz Struk 
193c339ab8STadeusz Struk #include "internal.h"
20c0f9e01dSHerbert Xu 
21c0f9e01dSHerbert Xu #define CRYPTO_ALG_TYPE_AHASH_MASK	0x0000000e
223c339ab8STadeusz Struk 
crypto_akcipher_report(struct sk_buff * skb,struct crypto_alg * alg)233c339ab8STadeusz Struk static int __maybe_unused crypto_akcipher_report(
243c339ab8STadeusz Struk 	struct sk_buff *skb, struct crypto_alg *alg)
2537db69e0SEric Biggers {
263c339ab8STadeusz Struk 	struct crypto_report_akcipher rakcipher;
2737db69e0SEric Biggers 
283c339ab8STadeusz Struk 	memset(&rakcipher, 0, sizeof(rakcipher));
2937db69e0SEric Biggers 
3037db69e0SEric Biggers 	strscpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
313c339ab8STadeusz Struk 
323c339ab8STadeusz Struk 	return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
333c339ab8STadeusz Struk 		       sizeof(rakcipher), &rakcipher);
34d8c34b94SGideon Israel Dsouza }
353c339ab8STadeusz Struk 
363c339ab8STadeusz Struk static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg)
373c339ab8STadeusz Struk 	__maybe_unused;
383c339ab8STadeusz Struk 
crypto_akcipher_show(struct seq_file * m,struct crypto_alg * alg)393c339ab8STadeusz Struk static void crypto_akcipher_show(struct seq_file *m, struct crypto_alg *alg)
403c339ab8STadeusz Struk {
413c339ab8STadeusz Struk 	seq_puts(m, "type         : akcipher\n");
423c339ab8STadeusz Struk }
433c339ab8STadeusz Struk 
crypto_akcipher_exit_tfm(struct crypto_tfm * tfm)443c339ab8STadeusz Struk static void crypto_akcipher_exit_tfm(struct crypto_tfm *tfm)
453c339ab8STadeusz Struk {
463c339ab8STadeusz Struk 	struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm);
473c339ab8STadeusz Struk 	struct akcipher_alg *alg = crypto_akcipher_alg(akcipher);
483c339ab8STadeusz Struk 
493c339ab8STadeusz Struk 	alg->exit(akcipher);
503c339ab8STadeusz Struk }
513c339ab8STadeusz Struk 
crypto_akcipher_init_tfm(struct crypto_tfm * tfm)523c339ab8STadeusz Struk static int crypto_akcipher_init_tfm(struct crypto_tfm *tfm)
533c339ab8STadeusz Struk {
543c339ab8STadeusz Struk 	struct crypto_akcipher *akcipher = __crypto_akcipher_tfm(tfm);
553c339ab8STadeusz Struk 	struct akcipher_alg *alg = crypto_akcipher_alg(akcipher);
563c339ab8STadeusz Struk 
573c339ab8STadeusz Struk 	if (alg->exit)
583c339ab8STadeusz Struk 		akcipher->base.exit = crypto_akcipher_exit_tfm;
593c339ab8STadeusz Struk 
603c339ab8STadeusz Struk 	if (alg->init)
613c339ab8STadeusz Struk 		return alg->init(akcipher);
623c339ab8STadeusz Struk 
6328a4618aSAndrzej Zaborowski 	return 0;
6428a4618aSAndrzej Zaborowski }
6528a4618aSAndrzej Zaborowski 
crypto_akcipher_free_instance(struct crypto_instance * inst)6628a4618aSAndrzej Zaborowski static void crypto_akcipher_free_instance(struct crypto_instance *inst)
6728a4618aSAndrzej Zaborowski {
6828a4618aSAndrzej Zaborowski 	struct akcipher_instance *akcipher = akcipher_instance(inst);
6928a4618aSAndrzej Zaborowski 
70035d78a1SHerbert Xu 	akcipher->free(akcipher);
71035d78a1SHerbert Xu }
72035d78a1SHerbert Xu 
crypto_akcipher_report_stat(struct sk_buff * skb,struct crypto_alg * alg)73035d78a1SHerbert Xu static int __maybe_unused crypto_akcipher_report_stat(
74035d78a1SHerbert Xu 	struct sk_buff *skb, struct crypto_alg *alg)
75035d78a1SHerbert Xu {
76035d78a1SHerbert Xu 	struct akcipher_alg *akcipher = __crypto_akcipher_alg(alg);
77035d78a1SHerbert Xu 	struct crypto_istat_akcipher *istat;
78035d78a1SHerbert Xu 	struct crypto_stat_akcipher rakcipher;
79035d78a1SHerbert Xu 
80035d78a1SHerbert Xu 	istat = akcipher_get_stat(akcipher);
81035d78a1SHerbert Xu 
82035d78a1SHerbert Xu 	memset(&rakcipher, 0, sizeof(rakcipher));
83035d78a1SHerbert Xu 
84035d78a1SHerbert Xu 	strscpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
85035d78a1SHerbert Xu 	rakcipher.stat_encrypt_cnt = atomic64_read(&istat->encrypt_cnt);
86035d78a1SHerbert Xu 	rakcipher.stat_encrypt_tlen = atomic64_read(&istat->encrypt_tlen);
87035d78a1SHerbert Xu 	rakcipher.stat_decrypt_cnt = atomic64_read(&istat->decrypt_cnt);
88035d78a1SHerbert Xu 	rakcipher.stat_decrypt_tlen = atomic64_read(&istat->decrypt_tlen);
89035d78a1SHerbert Xu 	rakcipher.stat_sign_cnt = atomic64_read(&istat->sign_cnt);
90035d78a1SHerbert Xu 	rakcipher.stat_verify_cnt = atomic64_read(&istat->verify_cnt);
91035d78a1SHerbert Xu 	rakcipher.stat_err_cnt = atomic64_read(&istat->err_cnt);
92035d78a1SHerbert Xu 
93035d78a1SHerbert Xu 	return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER,
943c339ab8STadeusz Struk 		       sizeof(rakcipher), &rakcipher);
953c339ab8STadeusz Struk }
963c339ab8STadeusz Struk 
9728a4618aSAndrzej Zaborowski static const struct crypto_type crypto_akcipher_type = {
983c339ab8STadeusz Struk 	.extsize = crypto_alg_extsize,
993c339ab8STadeusz Struk 	.init_tfm = crypto_akcipher_init_tfm,
1003c339ab8STadeusz Struk 	.free = crypto_akcipher_free_instance,
101*b8969a1bSOndrej Mosnacek #ifdef CONFIG_PROC_FS
1023c339ab8STadeusz Struk 	.show = crypto_akcipher_show,
103c0f9e01dSHerbert Xu #endif
104035d78a1SHerbert Xu #if IS_ENABLED(CONFIG_CRYPTO_USER)
105035d78a1SHerbert Xu 	.report = crypto_akcipher_report,
106035d78a1SHerbert Xu #endif
1073c339ab8STadeusz Struk #ifdef CONFIG_CRYPTO_STATS
1083c339ab8STadeusz Struk 	.report_stat = crypto_akcipher_report_stat,
1093c339ab8STadeusz Struk #endif
1103c339ab8STadeusz Struk 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
1113c339ab8STadeusz Struk 	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
1123c339ab8STadeusz Struk 	.type = CRYPTO_ALG_TYPE_AKCIPHER,
11373bed26fSEric Biggers 	.tfmsize = offsetof(struct crypto_akcipher, base),
11473bed26fSEric Biggers };
11573bed26fSEric Biggers 
crypto_grab_akcipher(struct crypto_akcipher_spawn * spawn,struct crypto_instance * inst,const char * name,u32 type,u32 mask)11628a4618aSAndrzej Zaborowski int crypto_grab_akcipher(struct crypto_akcipher_spawn *spawn,
11728a4618aSAndrzej Zaborowski 			 struct crypto_instance *inst,
118de95c957SEric Biggers 			 const char *name, u32 type, u32 mask)
11928a4618aSAndrzej Zaborowski {
12028a4618aSAndrzej Zaborowski 	spawn->base.frontend = &crypto_akcipher_type;
12128a4618aSAndrzej Zaborowski 	return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
1223c339ab8STadeusz Struk }
1233c339ab8STadeusz Struk EXPORT_SYMBOL_GPL(crypto_grab_akcipher);
1243c339ab8STadeusz Struk 
crypto_alloc_akcipher(const char * alg_name,u32 type,u32 mask)1253c339ab8STadeusz Struk struct crypto_akcipher *crypto_alloc_akcipher(const char *alg_name, u32 type,
1263c339ab8STadeusz Struk 					      u32 mask)
1273c339ab8STadeusz Struk {
1283c339ab8STadeusz Struk 	return crypto_alloc_tfm(alg_name, &crypto_akcipher_type, type, mask);
12928a4618aSAndrzej Zaborowski }
1303c339ab8STadeusz Struk EXPORT_SYMBOL_GPL(crypto_alloc_akcipher);
131035d78a1SHerbert Xu 
akcipher_prepare_alg(struct akcipher_alg * alg)1323c339ab8STadeusz Struk static void akcipher_prepare_alg(struct akcipher_alg *alg)
1333c339ab8STadeusz Struk {
1343c339ab8STadeusz Struk 	struct crypto_istat_akcipher *istat = akcipher_get_stat(alg);
1353c339ab8STadeusz Struk 	struct crypto_alg *base = &alg->base;
1363c339ab8STadeusz Struk 
137035d78a1SHerbert Xu 	base->cra_type = &crypto_akcipher_type;
138035d78a1SHerbert Xu 	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
139035d78a1SHerbert Xu 	base->cra_flags |= CRYPTO_ALG_TYPE_AKCIPHER;
14028a4618aSAndrzej Zaborowski 
14128a4618aSAndrzej Zaborowski 	if (IS_ENABLED(CONFIG_CRYPTO_STATS))
14278a0324fSVitaly Chikunov 		memset(istat, 0, sizeof(*istat));
14378a0324fSVitaly Chikunov }
14478a0324fSVitaly Chikunov 
akcipher_default_op(struct akcipher_request * req)14578a0324fSVitaly Chikunov static int akcipher_default_op(struct akcipher_request *req)
14678a0324fSVitaly Chikunov {
147bc155c6cSIgnat Korchagin 	return -ENOSYS;
148bc155c6cSIgnat Korchagin }
149bc155c6cSIgnat Korchagin 
akcipher_default_set_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)150bc155c6cSIgnat Korchagin static int akcipher_default_set_key(struct crypto_akcipher *tfm,
151bc155c6cSIgnat Korchagin 				     const void *key, unsigned int keylen)
152bc155c6cSIgnat Korchagin {
15328a4618aSAndrzej Zaborowski 	return -ENOSYS;
15428a4618aSAndrzej Zaborowski }
15528a4618aSAndrzej Zaborowski 
crypto_register_akcipher(struct akcipher_alg * alg)15628a4618aSAndrzej Zaborowski int crypto_register_akcipher(struct akcipher_alg *alg)
15778a0324fSVitaly Chikunov {
15878a0324fSVitaly Chikunov 	struct crypto_alg *base = &alg->base;
15978a0324fSVitaly Chikunov 
16078a0324fSVitaly Chikunov 	if (!alg->sign)
16178a0324fSVitaly Chikunov 		alg->sign = akcipher_default_op;
16278a0324fSVitaly Chikunov 	if (!alg->verify)
16378a0324fSVitaly Chikunov 		alg->verify = akcipher_default_op;
16478a0324fSVitaly Chikunov 	if (!alg->encrypt)
165bc155c6cSIgnat Korchagin 		alg->encrypt = akcipher_default_op;
166bc155c6cSIgnat Korchagin 	if (!alg->decrypt)
16778a0324fSVitaly Chikunov 		alg->decrypt = akcipher_default_op;
16828a4618aSAndrzej Zaborowski 	if (!alg->set_priv_key)
1693c339ab8STadeusz Struk 		alg->set_priv_key = akcipher_default_set_key;
1703c339ab8STadeusz Struk 
1713c339ab8STadeusz Struk 	akcipher_prepare_alg(alg);
1723c339ab8STadeusz Struk 	return crypto_register_alg(base);
1733c339ab8STadeusz Struk }
1743c339ab8STadeusz Struk EXPORT_SYMBOL_GPL(crypto_register_akcipher);
1753c339ab8STadeusz Struk 
crypto_unregister_akcipher(struct akcipher_alg * alg)1763c339ab8STadeusz Struk void crypto_unregister_akcipher(struct akcipher_alg *alg)
1773c339ab8STadeusz Struk {
1783c339ab8STadeusz Struk 	crypto_unregister_alg(&alg->base);
17928a4618aSAndrzej Zaborowski }
18028a4618aSAndrzej Zaborowski EXPORT_SYMBOL_GPL(crypto_unregister_akcipher);
18128a4618aSAndrzej Zaborowski 
akcipher_register_instance(struct crypto_template * tmpl,struct akcipher_instance * inst)182d4fdc2dfSEric Biggers int akcipher_register_instance(struct crypto_template *tmpl,
183d4fdc2dfSEric Biggers 			       struct akcipher_instance *inst)
18428a4618aSAndrzej Zaborowski {
18528a4618aSAndrzej Zaborowski 	if (WARN_ON(!inst->free))
18628a4618aSAndrzej Zaborowski 		return -EINVAL;
18728a4618aSAndrzej Zaborowski 	akcipher_prepare_alg(&inst->alg);
18828a4618aSAndrzej Zaborowski 	return crypto_register_instance(tmpl, akcipher_crypto_instance(inst));
1893c339ab8STadeusz Struk }
190338a9de0STadeusz Struk EXPORT_SYMBOL_GPL(akcipher_register_instance);
191 
crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data * data)192 int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
193 {
194 	unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
195 	struct akcipher_request *req;
196 	struct scatterlist *sg;
197 	unsigned int mlen;
198 	unsigned int len;
199 	u8 *buf;
200 
201 	if (data->dst)
202 		mlen = max(data->slen, data->dlen);
203 	else
204 		mlen = data->slen + data->dlen;
205 
206 	len = sizeof(*req) + reqsize + mlen;
207 	if (len < mlen)
208 		return -EOVERFLOW;
209 
210 	req = kzalloc(len, GFP_KERNEL);
211 	if (!req)
212 		return -ENOMEM;
213 
214 	data->req = req;
215 	akcipher_request_set_tfm(req, data->tfm);
216 
217 	buf = (u8 *)(req + 1) + reqsize;
218 	data->buf = buf;
219 	memcpy(buf, data->src, data->slen);
220 
221 	sg = &data->sg;
222 	sg_init_one(sg, buf, mlen);
223 	akcipher_request_set_crypt(req, sg, data->dst ? sg : NULL,
224 				   data->slen, data->dlen);
225 
226 	crypto_init_wait(&data->cwait);
227 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
228 				      crypto_req_done, &data->cwait);
229 
230 	return 0;
231 }
232 EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep);
233 
crypto_akcipher_sync_post(struct crypto_akcipher_sync_data * data,int err)234 int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err)
235 {
236 	err = crypto_wait_req(err, &data->cwait);
237 	if (data->dst)
238 		memcpy(data->dst, data->buf, data->dlen);
239 	data->dlen = data->req->dst_len;
240 	kfree_sensitive(data->req);
241 	return err;
242 }
243 EXPORT_SYMBOL_GPL(crypto_akcipher_sync_post);
244 
crypto_akcipher_sync_encrypt(struct crypto_akcipher * tfm,const void * src,unsigned int slen,void * dst,unsigned int dlen)245 int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
246 				 const void *src, unsigned int slen,
247 				 void *dst, unsigned int dlen)
248 {
249 	struct crypto_akcipher_sync_data data = {
250 		.tfm = tfm,
251 		.src = src,
252 		.dst = dst,
253 		.slen = slen,
254 		.dlen = dlen,
255 	};
256 
257 	return crypto_akcipher_sync_prep(&data) ?:
258 	       crypto_akcipher_sync_post(&data,
259 					 crypto_akcipher_encrypt(data.req));
260 }
261 EXPORT_SYMBOL_GPL(crypto_akcipher_sync_encrypt);
262 
crypto_akcipher_sync_decrypt(struct crypto_akcipher * tfm,const void * src,unsigned int slen,void * dst,unsigned int dlen)263 int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
264 				 const void *src, unsigned int slen,
265 				 void *dst, unsigned int dlen)
266 {
267 	struct crypto_akcipher_sync_data data = {
268 		.tfm = tfm,
269 		.src = src,
270 		.dst = dst,
271 		.slen = slen,
272 		.dlen = dlen,
273 	};
274 
275 	return crypto_akcipher_sync_prep(&data) ?:
276 	       crypto_akcipher_sync_post(&data,
277 					 crypto_akcipher_decrypt(data.req)) ?:
278 	       data.dlen;
279 }
280 EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
281 
crypto_exit_akcipher_ops_sig(struct crypto_tfm * tfm)282 static void crypto_exit_akcipher_ops_sig(struct crypto_tfm *tfm)
283 {
284 	struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
285 
286 	crypto_free_akcipher(*ctx);
287 }
288 
crypto_init_akcipher_ops_sig(struct crypto_tfm * tfm)289 int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm)
290 {
291 	struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
292 	struct crypto_alg *calg = tfm->__crt_alg;
293 	struct crypto_akcipher *akcipher;
294 
295 	if (!crypto_mod_get(calg))
296 		return -EAGAIN;
297 
298 	akcipher = crypto_create_tfm(calg, &crypto_akcipher_type);
299 	if (IS_ERR(akcipher)) {
300 		crypto_mod_put(calg);
301 		return PTR_ERR(akcipher);
302 	}
303 
304 	*ctx = akcipher;
305 	tfm->exit = crypto_exit_akcipher_ops_sig;
306 
307 	return 0;
308 }
309 EXPORT_SYMBOL_GPL(crypto_init_akcipher_ops_sig);
310 
311 MODULE_LICENSE("GPL");
312 MODULE_DESCRIPTION("Generic public key cipher type");
313