xref: /linux/crypto/rsa-pkcs1pad.c (revision c771600c6af14749609b49565ffb4cac2959710d)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23d5b1ecdSAndrzej Zaborowski /*
33d5b1ecdSAndrzej Zaborowski  * RSA padding templates.
43d5b1ecdSAndrzej Zaborowski  *
53d5b1ecdSAndrzej Zaborowski  * Copyright (c) 2015  Intel Corporation
63d5b1ecdSAndrzej Zaborowski  */
73d5b1ecdSAndrzej Zaborowski 
83d5b1ecdSAndrzej Zaborowski #include <crypto/algapi.h>
93d5b1ecdSAndrzej Zaborowski #include <crypto/akcipher.h>
103d5b1ecdSAndrzej Zaborowski #include <crypto/internal/akcipher.h>
11a1180cffSEric Biggers #include <crypto/internal/rsa.h>
123d5b1ecdSAndrzej Zaborowski #include <linux/err.h>
133d5b1ecdSAndrzej Zaborowski #include <linux/init.h>
143d5b1ecdSAndrzej Zaborowski #include <linux/kernel.h>
153d5b1ecdSAndrzej Zaborowski #include <linux/module.h>
163d5b1ecdSAndrzej Zaborowski #include <linux/random.h>
170c3dc787SHerbert Xu #include <linux/scatterlist.h>
183d5b1ecdSAndrzej Zaborowski 
193d5b1ecdSAndrzej Zaborowski struct pkcs1pad_ctx {
203d5b1ecdSAndrzej Zaborowski 	struct crypto_akcipher *child;
213d5b1ecdSAndrzej Zaborowski 	unsigned int key_size;
223d5b1ecdSAndrzej Zaborowski };
233d5b1ecdSAndrzej Zaborowski 
24a49de377STadeusz Struk struct pkcs1pad_inst_ctx {
25a49de377STadeusz Struk 	struct crypto_akcipher_spawn spawn;
26a49de377STadeusz Struk };
27a49de377STadeusz Struk 
283d5b1ecdSAndrzej Zaborowski struct pkcs1pad_request {
290f2c8319SHerbert Xu 	struct scatterlist in_sg[2], out_sg[1];
303d5b1ecdSAndrzej Zaborowski 	uint8_t *in_buf, *out_buf;
31a6d7bfd0STadeusz Struk 	struct akcipher_request child_req;
323d5b1ecdSAndrzej Zaborowski };
333d5b1ecdSAndrzej Zaborowski 
pkcs1pad_set_pub_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)343d5b1ecdSAndrzej Zaborowski static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
353d5b1ecdSAndrzej Zaborowski 		unsigned int keylen)
363d5b1ecdSAndrzej Zaborowski {
373d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
3873f79189SHerbert Xu 
397964b0d4SLukas Wunner 	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
403d5b1ecdSAndrzej Zaborowski }
413d5b1ecdSAndrzej Zaborowski 
pkcs1pad_set_priv_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)423d5b1ecdSAndrzej Zaborowski static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
433d5b1ecdSAndrzej Zaborowski 		unsigned int keylen)
443d5b1ecdSAndrzej Zaborowski {
453d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
4673f79189SHerbert Xu 
477964b0d4SLukas Wunner 	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
483d5b1ecdSAndrzej Zaborowski }
493d5b1ecdSAndrzej Zaborowski 
pkcs1pad_get_max_size(struct crypto_akcipher * tfm)50543de102STudor-Dan Ambarus static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
513d5b1ecdSAndrzej Zaborowski {
523d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
533d5b1ecdSAndrzej Zaborowski 
543d5b1ecdSAndrzej Zaborowski 	/*
55*1e562deaSLukas Wunner 	 * The maximum destination buffer size for the encrypt operation
563d5b1ecdSAndrzej Zaborowski 	 * will be the same as for RSA, even though it's smaller for
57*1e562deaSLukas Wunner 	 * decrypt.
583d5b1ecdSAndrzej Zaborowski 	 */
593d5b1ecdSAndrzej Zaborowski 
60543de102STudor-Dan Ambarus 	return ctx->key_size;
613d5b1ecdSAndrzej Zaborowski }
623d5b1ecdSAndrzej Zaborowski 
pkcs1pad_sg_set_buf(struct scatterlist * sg,void * buf,size_t len,struct scatterlist * next)633d5b1ecdSAndrzej Zaborowski static void pkcs1pad_sg_set_buf(struct scatterlist *sg, void *buf, size_t len,
643d5b1ecdSAndrzej Zaborowski 		struct scatterlist *next)
653d5b1ecdSAndrzej Zaborowski {
660f2c8319SHerbert Xu 	int nsegs = next ? 2 : 1;
673d5b1ecdSAndrzej Zaborowski 
683d5b1ecdSAndrzej Zaborowski 	sg_init_table(sg, nsegs);
693d5b1ecdSAndrzej Zaborowski 	sg_set_buf(sg, buf, len);
703d5b1ecdSAndrzej Zaborowski 
713d5b1ecdSAndrzej Zaborowski 	if (next)
723d5b1ecdSAndrzej Zaborowski 		sg_chain(sg, nsegs, next);
733d5b1ecdSAndrzej Zaborowski }
743d5b1ecdSAndrzej Zaborowski 
pkcs1pad_encrypt_complete(struct akcipher_request * req,int err)75*1e562deaSLukas Wunner static int pkcs1pad_encrypt_complete(struct akcipher_request *req, int err)
763d5b1ecdSAndrzej Zaborowski {
773d5b1ecdSAndrzej Zaborowski 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
783d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
793d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
80d858b071SHerbert Xu 	unsigned int pad_len;
81d858b071SHerbert Xu 	unsigned int len;
82d858b071SHerbert Xu 	u8 *out_buf;
833d5b1ecdSAndrzej Zaborowski 
84d858b071SHerbert Xu 	if (err)
85d858b071SHerbert Xu 		goto out;
865319216dSAndrzej Zaborowski 
87d858b071SHerbert Xu 	len = req_ctx->child_req.dst_len;
88d858b071SHerbert Xu 	pad_len = ctx->key_size - len;
895319216dSAndrzej Zaborowski 
90d858b071SHerbert Xu 	/* Four billion to one */
91d858b071SHerbert Xu 	if (likely(!pad_len))
92d858b071SHerbert Xu 		goto out;
935319216dSAndrzej Zaborowski 
94d52b0c78SHerbert Xu 	out_buf = kzalloc(ctx->key_size, GFP_ATOMIC);
95d858b071SHerbert Xu 	err = -ENOMEM;
96d858b071SHerbert Xu 	if (!out_buf)
97d858b071SHerbert Xu 		goto out;
983d5b1ecdSAndrzej Zaborowski 
99d858b071SHerbert Xu 	sg_copy_to_buffer(req->dst, sg_nents_for_len(req->dst, len),
100d858b071SHerbert Xu 			  out_buf + pad_len, len);
101d858b071SHerbert Xu 	sg_copy_from_buffer(req->dst,
1023d5b1ecdSAndrzej Zaborowski 			    sg_nents_for_len(req->dst, ctx->key_size),
103d858b071SHerbert Xu 			    out_buf, ctx->key_size);
104453431a5SWaiman Long 	kfree_sensitive(out_buf);
105d858b071SHerbert Xu 
106d858b071SHerbert Xu out:
1073d5b1ecdSAndrzej Zaborowski 	req->dst_len = ctx->key_size;
1083d5b1ecdSAndrzej Zaborowski 
1093d5b1ecdSAndrzej Zaborowski 	kfree(req_ctx->in_buf);
1103d5b1ecdSAndrzej Zaborowski 
1113d5b1ecdSAndrzej Zaborowski 	return err;
1123d5b1ecdSAndrzej Zaborowski }
1133d5b1ecdSAndrzej Zaborowski 
pkcs1pad_encrypt_complete_cb(void * data,int err)114*1e562deaSLukas Wunner static void pkcs1pad_encrypt_complete_cb(void *data, int err)
1153d5b1ecdSAndrzej Zaborowski {
116255e48ebSHerbert Xu 	struct akcipher_request *req = data;
1173d5b1ecdSAndrzej Zaborowski 
1183d5b1ecdSAndrzej Zaborowski 	if (err == -EINPROGRESS)
119564cabc0SHerbert Xu 		goto out;
1203d5b1ecdSAndrzej Zaborowski 
121*1e562deaSLukas Wunner 	err = pkcs1pad_encrypt_complete(req, err);
122564cabc0SHerbert Xu 
123564cabc0SHerbert Xu out:
124564cabc0SHerbert Xu 	akcipher_request_complete(req, err);
1253d5b1ecdSAndrzej Zaborowski }
1263d5b1ecdSAndrzej Zaborowski 
pkcs1pad_encrypt(struct akcipher_request * req)1273d5b1ecdSAndrzej Zaborowski static int pkcs1pad_encrypt(struct akcipher_request *req)
1283d5b1ecdSAndrzej Zaborowski {
1293d5b1ecdSAndrzej Zaborowski 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
1303d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
1313d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
1323d5b1ecdSAndrzej Zaborowski 	int err;
1333d5b1ecdSAndrzej Zaborowski 	unsigned int i, ps_end;
1343d5b1ecdSAndrzej Zaborowski 
1353d5b1ecdSAndrzej Zaborowski 	if (!ctx->key_size)
1363d5b1ecdSAndrzej Zaborowski 		return -EINVAL;
1373d5b1ecdSAndrzej Zaborowski 
1383d5b1ecdSAndrzej Zaborowski 	if (req->src_len > ctx->key_size - 11)
1393d5b1ecdSAndrzej Zaborowski 		return -EOVERFLOW;
1403d5b1ecdSAndrzej Zaborowski 
1413d5b1ecdSAndrzej Zaborowski 	if (req->dst_len < ctx->key_size) {
1423d5b1ecdSAndrzej Zaborowski 		req->dst_len = ctx->key_size;
1433d5b1ecdSAndrzej Zaborowski 		return -EOVERFLOW;
1443d5b1ecdSAndrzej Zaborowski 	}
1453d5b1ecdSAndrzej Zaborowski 
1463d5b1ecdSAndrzej Zaborowski 	req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
1473a32ce50SHerbert Xu 				  GFP_KERNEL);
1483d5b1ecdSAndrzej Zaborowski 	if (!req_ctx->in_buf)
1493d5b1ecdSAndrzej Zaborowski 		return -ENOMEM;
1503d5b1ecdSAndrzej Zaborowski 
1513d5b1ecdSAndrzej Zaborowski 	ps_end = ctx->key_size - req->src_len - 2;
1523d5b1ecdSAndrzej Zaborowski 	req_ctx->in_buf[0] = 0x02;
1533d5b1ecdSAndrzej Zaborowski 	for (i = 1; i < ps_end; i++)
154e8a533cbSJason A. Donenfeld 		req_ctx->in_buf[i] = get_random_u32_inclusive(1, 255);
1553d5b1ecdSAndrzej Zaborowski 	req_ctx->in_buf[ps_end] = 0x00;
1563d5b1ecdSAndrzej Zaborowski 
1573d5b1ecdSAndrzej Zaborowski 	pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
1583d5b1ecdSAndrzej Zaborowski 			ctx->key_size - 1 - req->src_len, req->src);
1593d5b1ecdSAndrzej Zaborowski 
1603d5b1ecdSAndrzej Zaborowski 	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
1613d5b1ecdSAndrzej Zaborowski 	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
162*1e562deaSLukas Wunner 			pkcs1pad_encrypt_complete_cb, req);
1633d5b1ecdSAndrzej Zaborowski 
164d858b071SHerbert Xu 	/* Reuse output buffer */
165d858b071SHerbert Xu 	akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
166d858b071SHerbert Xu 				   req->dst, ctx->key_size - 1, req->dst_len);
167d858b071SHerbert Xu 
1683d5b1ecdSAndrzej Zaborowski 	err = crypto_akcipher_encrypt(&req_ctx->child_req);
1694e5b0ad5SGilad Ben-Yossef 	if (err != -EINPROGRESS && err != -EBUSY)
170*1e562deaSLukas Wunner 		return pkcs1pad_encrypt_complete(req, err);
1713d5b1ecdSAndrzej Zaborowski 
1723d5b1ecdSAndrzej Zaborowski 	return err;
1733d5b1ecdSAndrzej Zaborowski }
1743d5b1ecdSAndrzej Zaborowski 
pkcs1pad_decrypt_complete(struct akcipher_request * req,int err)1753d5b1ecdSAndrzej Zaborowski static int pkcs1pad_decrypt_complete(struct akcipher_request *req, int err)
1763d5b1ecdSAndrzej Zaborowski {
1773d5b1ecdSAndrzej Zaborowski 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
1783d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
1793d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
1800cf43f50SHerbert Xu 	unsigned int dst_len;
1813d5b1ecdSAndrzej Zaborowski 	unsigned int pos;
1820cf43f50SHerbert Xu 	u8 *out_buf;
1833d5b1ecdSAndrzej Zaborowski 
1843d5b1ecdSAndrzej Zaborowski 	if (err)
1853d5b1ecdSAndrzej Zaborowski 		goto done;
1863d5b1ecdSAndrzej Zaborowski 
1873d5b1ecdSAndrzej Zaborowski 	err = -EINVAL;
1880cf43f50SHerbert Xu 	dst_len = req_ctx->child_req.dst_len;
1890cf43f50SHerbert Xu 	if (dst_len < ctx->key_size - 1)
1903d5b1ecdSAndrzej Zaborowski 		goto done;
1910cf43f50SHerbert Xu 
1920cf43f50SHerbert Xu 	out_buf = req_ctx->out_buf;
1930cf43f50SHerbert Xu 	if (dst_len == ctx->key_size) {
1940cf43f50SHerbert Xu 		if (out_buf[0] != 0x00)
1950cf43f50SHerbert Xu 			/* Decrypted value had no leading 0 byte */
1960cf43f50SHerbert Xu 			goto done;
1970cf43f50SHerbert Xu 
1980cf43f50SHerbert Xu 		dst_len--;
1990cf43f50SHerbert Xu 		out_buf++;
2003d5b1ecdSAndrzej Zaborowski 	}
2013d5b1ecdSAndrzej Zaborowski 
2020cf43f50SHerbert Xu 	if (out_buf[0] != 0x02)
2033d5b1ecdSAndrzej Zaborowski 		goto done;
2040cf43f50SHerbert Xu 
2050cf43f50SHerbert Xu 	for (pos = 1; pos < dst_len; pos++)
2060cf43f50SHerbert Xu 		if (out_buf[pos] == 0x00)
2073d5b1ecdSAndrzej Zaborowski 			break;
2080cf43f50SHerbert Xu 	if (pos < 9 || pos == dst_len)
2093d5b1ecdSAndrzej Zaborowski 		goto done;
2103d5b1ecdSAndrzej Zaborowski 	pos++;
2113d5b1ecdSAndrzej Zaborowski 
2120cf43f50SHerbert Xu 	err = 0;
2130cf43f50SHerbert Xu 
2140cf43f50SHerbert Xu 	if (req->dst_len < dst_len - pos)
2153d5b1ecdSAndrzej Zaborowski 		err = -EOVERFLOW;
2160cf43f50SHerbert Xu 	req->dst_len = dst_len - pos;
2173d5b1ecdSAndrzej Zaborowski 
2183d5b1ecdSAndrzej Zaborowski 	if (!err)
2193d5b1ecdSAndrzej Zaborowski 		sg_copy_from_buffer(req->dst,
2203d5b1ecdSAndrzej Zaborowski 				sg_nents_for_len(req->dst, req->dst_len),
2210cf43f50SHerbert Xu 				out_buf + pos, req->dst_len);
2223d5b1ecdSAndrzej Zaborowski 
2233d5b1ecdSAndrzej Zaborowski done:
224453431a5SWaiman Long 	kfree_sensitive(req_ctx->out_buf);
2253d5b1ecdSAndrzej Zaborowski 
2263d5b1ecdSAndrzej Zaborowski 	return err;
2273d5b1ecdSAndrzej Zaborowski }
2283d5b1ecdSAndrzej Zaborowski 
pkcs1pad_decrypt_complete_cb(void * data,int err)229255e48ebSHerbert Xu static void pkcs1pad_decrypt_complete_cb(void *data, int err)
2303d5b1ecdSAndrzej Zaborowski {
231255e48ebSHerbert Xu 	struct akcipher_request *req = data;
2323d5b1ecdSAndrzej Zaborowski 
2333d5b1ecdSAndrzej Zaborowski 	if (err == -EINPROGRESS)
234564cabc0SHerbert Xu 		goto out;
2353d5b1ecdSAndrzej Zaborowski 
236564cabc0SHerbert Xu 	err = pkcs1pad_decrypt_complete(req, err);
237564cabc0SHerbert Xu 
238564cabc0SHerbert Xu out:
239564cabc0SHerbert Xu 	akcipher_request_complete(req, err);
2403d5b1ecdSAndrzej Zaborowski }
2413d5b1ecdSAndrzej Zaborowski 
pkcs1pad_decrypt(struct akcipher_request * req)2423d5b1ecdSAndrzej Zaborowski static int pkcs1pad_decrypt(struct akcipher_request *req)
2433d5b1ecdSAndrzej Zaborowski {
2443d5b1ecdSAndrzej Zaborowski 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
2453d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
2463d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
2473d5b1ecdSAndrzej Zaborowski 	int err;
2483d5b1ecdSAndrzej Zaborowski 
2493d5b1ecdSAndrzej Zaborowski 	if (!ctx->key_size || req->src_len != ctx->key_size)
2503d5b1ecdSAndrzej Zaborowski 		return -EINVAL;
2513d5b1ecdSAndrzej Zaborowski 
2523a32ce50SHerbert Xu 	req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
2533d5b1ecdSAndrzej Zaborowski 	if (!req_ctx->out_buf)
2543d5b1ecdSAndrzej Zaborowski 		return -ENOMEM;
2553d5b1ecdSAndrzej Zaborowski 
2563d5b1ecdSAndrzej Zaborowski 	pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
2576f0904adSTadeusz Struk 			    ctx->key_size, NULL);
2583d5b1ecdSAndrzej Zaborowski 
2593d5b1ecdSAndrzej Zaborowski 	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
2603d5b1ecdSAndrzej Zaborowski 	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
2613d5b1ecdSAndrzej Zaborowski 			pkcs1pad_decrypt_complete_cb, req);
2623d5b1ecdSAndrzej Zaborowski 
263d858b071SHerbert Xu 	/* Reuse input buffer, output to a new buffer */
264d858b071SHerbert Xu 	akcipher_request_set_crypt(&req_ctx->child_req, req->src,
265d858b071SHerbert Xu 				   req_ctx->out_sg, req->src_len,
266d858b071SHerbert Xu 				   ctx->key_size);
267d858b071SHerbert Xu 
2683d5b1ecdSAndrzej Zaborowski 	err = crypto_akcipher_decrypt(&req_ctx->child_req);
2694e5b0ad5SGilad Ben-Yossef 	if (err != -EINPROGRESS && err != -EBUSY)
2703d5b1ecdSAndrzej Zaborowski 		return pkcs1pad_decrypt_complete(req, err);
2713d5b1ecdSAndrzej Zaborowski 
2723d5b1ecdSAndrzej Zaborowski 	return err;
2733d5b1ecdSAndrzej Zaborowski }
2743d5b1ecdSAndrzej Zaborowski 
pkcs1pad_init_tfm(struct crypto_akcipher * tfm)2753d5b1ecdSAndrzej Zaborowski static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
2763d5b1ecdSAndrzej Zaborowski {
2773d5b1ecdSAndrzej Zaborowski 	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
278a49de377STadeusz Struk 	struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
2793d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
2803d5b1ecdSAndrzej Zaborowski 	struct crypto_akcipher *child_tfm;
2813d5b1ecdSAndrzej Zaborowski 
282c0d20d22SHerbert Xu 	child_tfm = crypto_spawn_akcipher(&ictx->spawn);
2833d5b1ecdSAndrzej Zaborowski 	if (IS_ERR(child_tfm))
2843d5b1ecdSAndrzej Zaborowski 		return PTR_ERR(child_tfm);
2853d5b1ecdSAndrzej Zaborowski 
2863d5b1ecdSAndrzej Zaborowski 	ctx->child = child_tfm;
2875b11d1a3SHerbert Xu 
2885b11d1a3SHerbert Xu 	akcipher_set_reqsize(tfm, sizeof(struct pkcs1pad_request) +
2895b11d1a3SHerbert Xu 				  crypto_akcipher_reqsize(child_tfm));
2905b11d1a3SHerbert Xu 
2913d5b1ecdSAndrzej Zaborowski 	return 0;
2923d5b1ecdSAndrzej Zaborowski }
2933d5b1ecdSAndrzej Zaborowski 
pkcs1pad_exit_tfm(struct crypto_akcipher * tfm)2943d5b1ecdSAndrzej Zaborowski static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
2953d5b1ecdSAndrzej Zaborowski {
2963d5b1ecdSAndrzej Zaborowski 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
2973d5b1ecdSAndrzej Zaborowski 
2983d5b1ecdSAndrzej Zaborowski 	crypto_free_akcipher(ctx->child);
2993d5b1ecdSAndrzej Zaborowski }
3003d5b1ecdSAndrzej Zaborowski 
pkcs1pad_free(struct akcipher_instance * inst)3013d5b1ecdSAndrzej Zaborowski static void pkcs1pad_free(struct akcipher_instance *inst)
3023d5b1ecdSAndrzej Zaborowski {
303a49de377STadeusz Struk 	struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst);
304a49de377STadeusz Struk 	struct crypto_akcipher_spawn *spawn = &ctx->spawn;
3053d5b1ecdSAndrzej Zaborowski 
3063d5b1ecdSAndrzej Zaborowski 	crypto_drop_akcipher(spawn);
3073d5b1ecdSAndrzej Zaborowski 	kfree(inst);
3083d5b1ecdSAndrzej Zaborowski }
3093d5b1ecdSAndrzej Zaborowski 
pkcs1pad_create(struct crypto_template * tmpl,struct rtattr ** tb)3103d5b1ecdSAndrzej Zaborowski static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
3113d5b1ecdSAndrzej Zaborowski {
31273bed26fSEric Biggers 	u32 mask;
3133d5b1ecdSAndrzej Zaborowski 	struct akcipher_instance *inst;
314a49de377STadeusz Struk 	struct pkcs1pad_inst_ctx *ctx;
3153d5b1ecdSAndrzej Zaborowski 	struct akcipher_alg *rsa_alg;
3163d5b1ecdSAndrzej Zaborowski 	int err;
3173d5b1ecdSAndrzej Zaborowski 
3187bcb2c99SEric Biggers 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AKCIPHER, &mask);
3197bcb2c99SEric Biggers 	if (err)
3207bcb2c99SEric Biggers 		return err;
32173bed26fSEric Biggers 
322a49de377STadeusz Struk 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
3233d5b1ecdSAndrzej Zaborowski 	if (!inst)
3243d5b1ecdSAndrzej Zaborowski 		return -ENOMEM;
3253d5b1ecdSAndrzej Zaborowski 
326a49de377STadeusz Struk 	ctx = akcipher_instance_ctx(inst);
327a49de377STadeusz Struk 
3280708bb43SEric Biggers 	err = crypto_grab_akcipher(&ctx->spawn, akcipher_crypto_instance(inst),
3290708bb43SEric Biggers 				   crypto_attr_alg_name(tb[1]), 0, mask);
3303d5b1ecdSAndrzej Zaborowski 	if (err)
3310708bb43SEric Biggers 		goto err_free_inst;
3323d5b1ecdSAndrzej Zaborowski 
3330708bb43SEric Biggers 	rsa_alg = crypto_spawn_akcipher_alg(&ctx->spawn);
3343d5b1ecdSAndrzej Zaborowski 
3359b30430eSEric Biggers 	if (strcmp(rsa_alg->base.cra_name, "rsa") != 0) {
3369b30430eSEric Biggers 		err = -EINVAL;
3379b30430eSEric Biggers 		goto err_free_inst;
3389b30430eSEric Biggers 	}
3399b30430eSEric Biggers 
3403d5b1ecdSAndrzej Zaborowski 	err = -ENAMETOOLONG;
341b3a8c8a5SDenis Kenzior 	if (snprintf(inst->alg.base.cra_name,
342b3a8c8a5SDenis Kenzior 		     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
343b3a8c8a5SDenis Kenzior 		     rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
3440708bb43SEric Biggers 		goto err_free_inst;
345b3a8c8a5SDenis Kenzior 
346b3a8c8a5SDenis Kenzior 	if (snprintf(inst->alg.base.cra_driver_name,
347b3a8c8a5SDenis Kenzior 		     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
348*1e562deaSLukas Wunner 		     rsa_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
3490708bb43SEric Biggers 		goto err_free_inst;
3503d5b1ecdSAndrzej Zaborowski 
3513d5b1ecdSAndrzej Zaborowski 	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
3523d5b1ecdSAndrzej Zaborowski 	inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);
3533d5b1ecdSAndrzej Zaborowski 
3543d5b1ecdSAndrzej Zaborowski 	inst->alg.init = pkcs1pad_init_tfm;
3553d5b1ecdSAndrzej Zaborowski 	inst->alg.exit = pkcs1pad_exit_tfm;
3563d5b1ecdSAndrzej Zaborowski 
3573d5b1ecdSAndrzej Zaborowski 	inst->alg.encrypt = pkcs1pad_encrypt;
3583d5b1ecdSAndrzej Zaborowski 	inst->alg.decrypt = pkcs1pad_decrypt;
3593d5b1ecdSAndrzej Zaborowski 	inst->alg.set_pub_key = pkcs1pad_set_pub_key;
3603d5b1ecdSAndrzej Zaborowski 	inst->alg.set_priv_key = pkcs1pad_set_priv_key;
3613d5b1ecdSAndrzej Zaborowski 	inst->alg.max_size = pkcs1pad_get_max_size;
3623d5b1ecdSAndrzej Zaborowski 
3633d5b1ecdSAndrzej Zaborowski 	inst->free = pkcs1pad_free;
3643d5b1ecdSAndrzej Zaborowski 
3653d5b1ecdSAndrzej Zaborowski 	err = akcipher_register_instance(tmpl, inst);
3660708bb43SEric Biggers 	if (err) {
3670708bb43SEric Biggers err_free_inst:
3680708bb43SEric Biggers 		pkcs1pad_free(inst);
3690708bb43SEric Biggers 	}
3703d5b1ecdSAndrzej Zaborowski 	return err;
3713d5b1ecdSAndrzej Zaborowski }
3723d5b1ecdSAndrzej Zaborowski 
3733d5b1ecdSAndrzej Zaborowski struct crypto_template rsa_pkcs1pad_tmpl = {
3743d5b1ecdSAndrzej Zaborowski 	.name = "pkcs1pad",
3753d5b1ecdSAndrzej Zaborowski 	.create = pkcs1pad_create,
3763d5b1ecdSAndrzej Zaborowski 	.module = THIS_MODULE,
3773d5b1ecdSAndrzej Zaborowski };
378f5fb88e5SHerbert Xu 
379f5fb88e5SHerbert Xu MODULE_ALIAS_CRYPTO("pkcs1pad");
380