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