18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * RSA padding templates. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2015 Intel Corporation 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 98c2ecf20Sopenharmony_ci#include <crypto/akcipher.h> 108c2ecf20Sopenharmony_ci#include <crypto/internal/akcipher.h> 118c2ecf20Sopenharmony_ci#include <crypto/internal/rsa.h> 128c2ecf20Sopenharmony_ci#include <linux/err.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/random.h> 178c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_md5[] = { 238c2ecf20Sopenharmony_ci 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 248c2ecf20Sopenharmony_ci 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */ 258c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x10 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_sha1[] = { 298c2ecf20Sopenharmony_ci 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 308c2ecf20Sopenharmony_ci 0x2b, 0x0e, 0x03, 0x02, 0x1a, 318c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x14 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_rmd160[] = { 358c2ecf20Sopenharmony_ci 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 368c2ecf20Sopenharmony_ci 0x2b, 0x24, 0x03, 0x02, 0x01, 378c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x14 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_sha224[] = { 418c2ecf20Sopenharmony_ci 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 428c2ecf20Sopenharmony_ci 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 438c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x1c 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_sha256[] = { 478c2ecf20Sopenharmony_ci 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 488c2ecf20Sopenharmony_ci 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 498c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x20 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_sha384[] = { 538c2ecf20Sopenharmony_ci 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 548c2ecf20Sopenharmony_ci 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 558c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x30 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic const u8 rsa_digest_info_sha512[] = { 598c2ecf20Sopenharmony_ci 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 608c2ecf20Sopenharmony_ci 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 618c2ecf20Sopenharmony_ci 0x05, 0x00, 0x04, 0x40 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic const struct rsa_asn1_template { 658c2ecf20Sopenharmony_ci const char *name; 668c2ecf20Sopenharmony_ci const u8 *data; 678c2ecf20Sopenharmony_ci size_t size; 688c2ecf20Sopenharmony_ci} rsa_asn1_templates[] = { 698c2ecf20Sopenharmony_ci#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) } 708c2ecf20Sopenharmony_ci _(md5), 718c2ecf20Sopenharmony_ci _(sha1), 728c2ecf20Sopenharmony_ci _(rmd160), 738c2ecf20Sopenharmony_ci _(sha256), 748c2ecf20Sopenharmony_ci _(sha384), 758c2ecf20Sopenharmony_ci _(sha512), 768c2ecf20Sopenharmony_ci _(sha224), 778c2ecf20Sopenharmony_ci { NULL } 788c2ecf20Sopenharmony_ci#undef _ 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic const struct rsa_asn1_template *rsa_lookup_asn1(const char *name) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci const struct rsa_asn1_template *p; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci for (p = rsa_asn1_templates; p->name; p++) 868c2ecf20Sopenharmony_ci if (strcmp(name, p->name) == 0) 878c2ecf20Sopenharmony_ci return p; 888c2ecf20Sopenharmony_ci return NULL; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct pkcs1pad_ctx { 928c2ecf20Sopenharmony_ci struct crypto_akcipher *child; 938c2ecf20Sopenharmony_ci unsigned int key_size; 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistruct pkcs1pad_inst_ctx { 978c2ecf20Sopenharmony_ci struct crypto_akcipher_spawn spawn; 988c2ecf20Sopenharmony_ci const struct rsa_asn1_template *digest_info; 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistruct pkcs1pad_request { 1028c2ecf20Sopenharmony_ci struct scatterlist in_sg[2], out_sg[1]; 1038c2ecf20Sopenharmony_ci uint8_t *in_buf, *out_buf; 1048c2ecf20Sopenharmony_ci struct akcipher_request child_req; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key, 1088c2ecf20Sopenharmony_ci unsigned int keylen) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 1118c2ecf20Sopenharmony_ci int err; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci ctx->key_size = 0; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci err = crypto_akcipher_set_pub_key(ctx->child, key, keylen); 1168c2ecf20Sopenharmony_ci if (err) 1178c2ecf20Sopenharmony_ci return err; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* Find out new modulus size from rsa implementation */ 1208c2ecf20Sopenharmony_ci err = crypto_akcipher_maxsize(ctx->child); 1218c2ecf20Sopenharmony_ci if (err > PAGE_SIZE) 1228c2ecf20Sopenharmony_ci return -ENOTSUPP; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci ctx->key_size = err; 1258c2ecf20Sopenharmony_ci return 0; 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key, 1298c2ecf20Sopenharmony_ci unsigned int keylen) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 1328c2ecf20Sopenharmony_ci int err; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ctx->key_size = 0; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci err = crypto_akcipher_set_priv_key(ctx->child, key, keylen); 1378c2ecf20Sopenharmony_ci if (err) 1388c2ecf20Sopenharmony_ci return err; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Find out new modulus size from rsa implementation */ 1418c2ecf20Sopenharmony_ci err = crypto_akcipher_maxsize(ctx->child); 1428c2ecf20Sopenharmony_ci if (err > PAGE_SIZE) 1438c2ecf20Sopenharmony_ci return -ENOTSUPP; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci ctx->key_size = err; 1468c2ecf20Sopenharmony_ci return 0; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* 1548c2ecf20Sopenharmony_ci * The maximum destination buffer size for the encrypt/sign operations 1558c2ecf20Sopenharmony_ci * will be the same as for RSA, even though it's smaller for 1568c2ecf20Sopenharmony_ci * decrypt/verify. 1578c2ecf20Sopenharmony_ci */ 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return ctx->key_size; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic void pkcs1pad_sg_set_buf(struct scatterlist *sg, void *buf, size_t len, 1638c2ecf20Sopenharmony_ci struct scatterlist *next) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci int nsegs = next ? 2 : 1; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci sg_init_table(sg, nsegs); 1688c2ecf20Sopenharmony_ci sg_set_buf(sg, buf, len); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (next) 1718c2ecf20Sopenharmony_ci sg_chain(sg, nsegs, next); 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 1778c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 1788c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 1798c2ecf20Sopenharmony_ci unsigned int pad_len; 1808c2ecf20Sopenharmony_ci unsigned int len; 1818c2ecf20Sopenharmony_ci u8 *out_buf; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (err) 1848c2ecf20Sopenharmony_ci goto out; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci len = req_ctx->child_req.dst_len; 1878c2ecf20Sopenharmony_ci pad_len = ctx->key_size - len; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* Four billion to one */ 1908c2ecf20Sopenharmony_ci if (likely(!pad_len)) 1918c2ecf20Sopenharmony_ci goto out; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci out_buf = kzalloc(ctx->key_size, GFP_KERNEL); 1948c2ecf20Sopenharmony_ci err = -ENOMEM; 1958c2ecf20Sopenharmony_ci if (!out_buf) 1968c2ecf20Sopenharmony_ci goto out; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci sg_copy_to_buffer(req->dst, sg_nents_for_len(req->dst, len), 1998c2ecf20Sopenharmony_ci out_buf + pad_len, len); 2008c2ecf20Sopenharmony_ci sg_copy_from_buffer(req->dst, 2018c2ecf20Sopenharmony_ci sg_nents_for_len(req->dst, ctx->key_size), 2028c2ecf20Sopenharmony_ci out_buf, ctx->key_size); 2038c2ecf20Sopenharmony_ci kfree_sensitive(out_buf); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ciout: 2068c2ecf20Sopenharmony_ci req->dst_len = ctx->key_size; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci kfree(req_ctx->in_buf); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci return err; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic void pkcs1pad_encrypt_sign_complete_cb( 2148c2ecf20Sopenharmony_ci struct crypto_async_request *child_async_req, int err) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct akcipher_request *req = child_async_req->data; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 2198c2ecf20Sopenharmony_ci goto out; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci err = pkcs1pad_encrypt_sign_complete(req, err); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciout: 2248c2ecf20Sopenharmony_ci akcipher_request_complete(req, err); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int pkcs1pad_encrypt(struct akcipher_request *req) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 2308c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 2318c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 2328c2ecf20Sopenharmony_ci int err; 2338c2ecf20Sopenharmony_ci unsigned int i, ps_end; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (!ctx->key_size) 2368c2ecf20Sopenharmony_ci return -EINVAL; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (req->src_len > ctx->key_size - 11) 2398c2ecf20Sopenharmony_ci return -EOVERFLOW; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (req->dst_len < ctx->key_size) { 2428c2ecf20Sopenharmony_ci req->dst_len = ctx->key_size; 2438c2ecf20Sopenharmony_ci return -EOVERFLOW; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len, 2478c2ecf20Sopenharmony_ci GFP_KERNEL); 2488c2ecf20Sopenharmony_ci if (!req_ctx->in_buf) 2498c2ecf20Sopenharmony_ci return -ENOMEM; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci ps_end = ctx->key_size - req->src_len - 2; 2528c2ecf20Sopenharmony_ci req_ctx->in_buf[0] = 0x02; 2538c2ecf20Sopenharmony_ci for (i = 1; i < ps_end; i++) 2548c2ecf20Sopenharmony_ci req_ctx->in_buf[i] = 1 + prandom_u32_max(255); 2558c2ecf20Sopenharmony_ci req_ctx->in_buf[ps_end] = 0x00; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf, 2588c2ecf20Sopenharmony_ci ctx->key_size - 1 - req->src_len, req->src); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); 2618c2ecf20Sopenharmony_ci akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 2628c2ecf20Sopenharmony_ci pkcs1pad_encrypt_sign_complete_cb, req); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* Reuse output buffer */ 2658c2ecf20Sopenharmony_ci akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg, 2668c2ecf20Sopenharmony_ci req->dst, ctx->key_size - 1, req->dst_len); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci err = crypto_akcipher_encrypt(&req_ctx->child_req); 2698c2ecf20Sopenharmony_ci if (err != -EINPROGRESS && err != -EBUSY) 2708c2ecf20Sopenharmony_ci return pkcs1pad_encrypt_sign_complete(req, err); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return err; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int pkcs1pad_decrypt_complete(struct akcipher_request *req, int err) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 2788c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 2798c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 2808c2ecf20Sopenharmony_ci unsigned int dst_len; 2818c2ecf20Sopenharmony_ci unsigned int pos; 2828c2ecf20Sopenharmony_ci u8 *out_buf; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (err) 2858c2ecf20Sopenharmony_ci goto done; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci err = -EINVAL; 2888c2ecf20Sopenharmony_ci dst_len = req_ctx->child_req.dst_len; 2898c2ecf20Sopenharmony_ci if (dst_len < ctx->key_size - 1) 2908c2ecf20Sopenharmony_ci goto done; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci out_buf = req_ctx->out_buf; 2938c2ecf20Sopenharmony_ci if (dst_len == ctx->key_size) { 2948c2ecf20Sopenharmony_ci if (out_buf[0] != 0x00) 2958c2ecf20Sopenharmony_ci /* Decrypted value had no leading 0 byte */ 2968c2ecf20Sopenharmony_ci goto done; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci dst_len--; 2998c2ecf20Sopenharmony_ci out_buf++; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (out_buf[0] != 0x02) 3038c2ecf20Sopenharmony_ci goto done; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci for (pos = 1; pos < dst_len; pos++) 3068c2ecf20Sopenharmony_ci if (out_buf[pos] == 0x00) 3078c2ecf20Sopenharmony_ci break; 3088c2ecf20Sopenharmony_ci if (pos < 9 || pos == dst_len) 3098c2ecf20Sopenharmony_ci goto done; 3108c2ecf20Sopenharmony_ci pos++; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci err = 0; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (req->dst_len < dst_len - pos) 3158c2ecf20Sopenharmony_ci err = -EOVERFLOW; 3168c2ecf20Sopenharmony_ci req->dst_len = dst_len - pos; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (!err) 3198c2ecf20Sopenharmony_ci sg_copy_from_buffer(req->dst, 3208c2ecf20Sopenharmony_ci sg_nents_for_len(req->dst, req->dst_len), 3218c2ecf20Sopenharmony_ci out_buf + pos, req->dst_len); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cidone: 3248c2ecf20Sopenharmony_ci kfree_sensitive(req_ctx->out_buf); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return err; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic void pkcs1pad_decrypt_complete_cb( 3308c2ecf20Sopenharmony_ci struct crypto_async_request *child_async_req, int err) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct akcipher_request *req = child_async_req->data; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 3358c2ecf20Sopenharmony_ci goto out; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci err = pkcs1pad_decrypt_complete(req, err); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ciout: 3408c2ecf20Sopenharmony_ci akcipher_request_complete(req, err); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic int pkcs1pad_decrypt(struct akcipher_request *req) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 3468c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 3478c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 3488c2ecf20Sopenharmony_ci int err; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (!ctx->key_size || req->src_len != ctx->key_size) 3518c2ecf20Sopenharmony_ci return -EINVAL; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL); 3548c2ecf20Sopenharmony_ci if (!req_ctx->out_buf) 3558c2ecf20Sopenharmony_ci return -ENOMEM; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf, 3588c2ecf20Sopenharmony_ci ctx->key_size, NULL); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); 3618c2ecf20Sopenharmony_ci akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 3628c2ecf20Sopenharmony_ci pkcs1pad_decrypt_complete_cb, req); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* Reuse input buffer, output to a new buffer */ 3658c2ecf20Sopenharmony_ci akcipher_request_set_crypt(&req_ctx->child_req, req->src, 3668c2ecf20Sopenharmony_ci req_ctx->out_sg, req->src_len, 3678c2ecf20Sopenharmony_ci ctx->key_size); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci err = crypto_akcipher_decrypt(&req_ctx->child_req); 3708c2ecf20Sopenharmony_ci if (err != -EINPROGRESS && err != -EBUSY) 3718c2ecf20Sopenharmony_ci return pkcs1pad_decrypt_complete(req, err); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci return err; 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic int pkcs1pad_sign(struct akcipher_request *req) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 3798c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 3808c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 3818c2ecf20Sopenharmony_ci struct akcipher_instance *inst = akcipher_alg_instance(tfm); 3828c2ecf20Sopenharmony_ci struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst); 3838c2ecf20Sopenharmony_ci const struct rsa_asn1_template *digest_info = ictx->digest_info; 3848c2ecf20Sopenharmony_ci int err; 3858c2ecf20Sopenharmony_ci unsigned int ps_end, digest_size = 0; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (!ctx->key_size) 3888c2ecf20Sopenharmony_ci return -EINVAL; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (digest_info) 3918c2ecf20Sopenharmony_ci digest_size = digest_info->size; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci if (req->src_len + digest_size > ctx->key_size - 11) 3948c2ecf20Sopenharmony_ci return -EOVERFLOW; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci if (req->dst_len < ctx->key_size) { 3978c2ecf20Sopenharmony_ci req->dst_len = ctx->key_size; 3988c2ecf20Sopenharmony_ci return -EOVERFLOW; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len, 4028c2ecf20Sopenharmony_ci GFP_KERNEL); 4038c2ecf20Sopenharmony_ci if (!req_ctx->in_buf) 4048c2ecf20Sopenharmony_ci return -ENOMEM; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci ps_end = ctx->key_size - digest_size - req->src_len - 2; 4078c2ecf20Sopenharmony_ci req_ctx->in_buf[0] = 0x01; 4088c2ecf20Sopenharmony_ci memset(req_ctx->in_buf + 1, 0xff, ps_end - 1); 4098c2ecf20Sopenharmony_ci req_ctx->in_buf[ps_end] = 0x00; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (digest_info) 4128c2ecf20Sopenharmony_ci memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data, 4138c2ecf20Sopenharmony_ci digest_info->size); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf, 4168c2ecf20Sopenharmony_ci ctx->key_size - 1 - req->src_len, req->src); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); 4198c2ecf20Sopenharmony_ci akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 4208c2ecf20Sopenharmony_ci pkcs1pad_encrypt_sign_complete_cb, req); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* Reuse output buffer */ 4238c2ecf20Sopenharmony_ci akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg, 4248c2ecf20Sopenharmony_ci req->dst, ctx->key_size - 1, req->dst_len); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci err = crypto_akcipher_decrypt(&req_ctx->child_req); 4278c2ecf20Sopenharmony_ci if (err != -EINPROGRESS && err != -EBUSY) 4288c2ecf20Sopenharmony_ci return pkcs1pad_encrypt_sign_complete(req, err); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci return err; 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic int pkcs1pad_verify_complete(struct akcipher_request *req, int err) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 4368c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 4378c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 4388c2ecf20Sopenharmony_ci struct akcipher_instance *inst = akcipher_alg_instance(tfm); 4398c2ecf20Sopenharmony_ci struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst); 4408c2ecf20Sopenharmony_ci const struct rsa_asn1_template *digest_info = ictx->digest_info; 4418c2ecf20Sopenharmony_ci unsigned int dst_len; 4428c2ecf20Sopenharmony_ci unsigned int pos; 4438c2ecf20Sopenharmony_ci u8 *out_buf; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (err) 4468c2ecf20Sopenharmony_ci goto done; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci err = -EINVAL; 4498c2ecf20Sopenharmony_ci dst_len = req_ctx->child_req.dst_len; 4508c2ecf20Sopenharmony_ci if (dst_len < ctx->key_size - 1) 4518c2ecf20Sopenharmony_ci goto done; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci out_buf = req_ctx->out_buf; 4548c2ecf20Sopenharmony_ci if (dst_len == ctx->key_size) { 4558c2ecf20Sopenharmony_ci if (out_buf[0] != 0x00) 4568c2ecf20Sopenharmony_ci /* Decrypted value had no leading 0 byte */ 4578c2ecf20Sopenharmony_ci goto done; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci dst_len--; 4608c2ecf20Sopenharmony_ci out_buf++; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci err = -EBADMSG; 4648c2ecf20Sopenharmony_ci if (out_buf[0] != 0x01) 4658c2ecf20Sopenharmony_ci goto done; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci for (pos = 1; pos < dst_len; pos++) 4688c2ecf20Sopenharmony_ci if (out_buf[pos] != 0xff) 4698c2ecf20Sopenharmony_ci break; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00) 4728c2ecf20Sopenharmony_ci goto done; 4738c2ecf20Sopenharmony_ci pos++; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (digest_info) { 4768c2ecf20Sopenharmony_ci if (digest_info->size > dst_len - pos) 4778c2ecf20Sopenharmony_ci goto done; 4788c2ecf20Sopenharmony_ci if (crypto_memneq(out_buf + pos, digest_info->data, 4798c2ecf20Sopenharmony_ci digest_info->size)) 4808c2ecf20Sopenharmony_ci goto done; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci pos += digest_info->size; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci err = 0; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (req->dst_len != dst_len - pos) { 4888c2ecf20Sopenharmony_ci err = -EKEYREJECTED; 4898c2ecf20Sopenharmony_ci req->dst_len = dst_len - pos; 4908c2ecf20Sopenharmony_ci goto done; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci /* Extract appended digest. */ 4938c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(req->src, 4948c2ecf20Sopenharmony_ci sg_nents_for_len(req->src, 4958c2ecf20Sopenharmony_ci req->src_len + req->dst_len), 4968c2ecf20Sopenharmony_ci req_ctx->out_buf + ctx->key_size, 4978c2ecf20Sopenharmony_ci req->dst_len, req->src_len); 4988c2ecf20Sopenharmony_ci /* Do the actual verification step. */ 4998c2ecf20Sopenharmony_ci if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos, 5008c2ecf20Sopenharmony_ci req->dst_len) != 0) 5018c2ecf20Sopenharmony_ci err = -EKEYREJECTED; 5028c2ecf20Sopenharmony_cidone: 5038c2ecf20Sopenharmony_ci kfree_sensitive(req_ctx->out_buf); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci return err; 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_cistatic void pkcs1pad_verify_complete_cb( 5098c2ecf20Sopenharmony_ci struct crypto_async_request *child_async_req, int err) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci struct akcipher_request *req = child_async_req->data; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci if (err == -EINPROGRESS) 5148c2ecf20Sopenharmony_ci goto out; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci err = pkcs1pad_verify_complete(req, err); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ciout: 5198c2ecf20Sopenharmony_ci akcipher_request_complete(req, err); 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci/* 5238c2ecf20Sopenharmony_ci * The verify operation is here for completeness similar to the verification 5248c2ecf20Sopenharmony_ci * defined in RFC2313 section 10.2 except that block type 0 is not accepted, 5258c2ecf20Sopenharmony_ci * as in RFC2437. RFC2437 section 9.2 doesn't define any operation to 5268c2ecf20Sopenharmony_ci * retrieve the DigestInfo from a signature, instead the user is expected 5278c2ecf20Sopenharmony_ci * to call the sign operation to generate the expected signature and compare 5288c2ecf20Sopenharmony_ci * signatures instead of the message-digests. 5298c2ecf20Sopenharmony_ci */ 5308c2ecf20Sopenharmony_cistatic int pkcs1pad_verify(struct akcipher_request *req) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 5338c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 5348c2ecf20Sopenharmony_ci struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 5358c2ecf20Sopenharmony_ci int err; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (WARN_ON(req->dst) || 5388c2ecf20Sopenharmony_ci WARN_ON(!req->dst_len) || 5398c2ecf20Sopenharmony_ci !ctx->key_size || req->src_len != ctx->key_size) 5408c2ecf20Sopenharmony_ci return -EINVAL; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci req_ctx->out_buf = kmalloc(ctx->key_size + req->dst_len, GFP_KERNEL); 5438c2ecf20Sopenharmony_ci if (!req_ctx->out_buf) 5448c2ecf20Sopenharmony_ci return -ENOMEM; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf, 5478c2ecf20Sopenharmony_ci ctx->key_size, NULL); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); 5508c2ecf20Sopenharmony_ci akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 5518c2ecf20Sopenharmony_ci pkcs1pad_verify_complete_cb, req); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* Reuse input buffer, output to a new buffer */ 5548c2ecf20Sopenharmony_ci akcipher_request_set_crypt(&req_ctx->child_req, req->src, 5558c2ecf20Sopenharmony_ci req_ctx->out_sg, req->src_len, 5568c2ecf20Sopenharmony_ci ctx->key_size); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci err = crypto_akcipher_encrypt(&req_ctx->child_req); 5598c2ecf20Sopenharmony_ci if (err != -EINPROGRESS && err != -EBUSY) 5608c2ecf20Sopenharmony_ci return pkcs1pad_verify_complete(req, err); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci return err; 5638c2ecf20Sopenharmony_ci} 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_cistatic int pkcs1pad_init_tfm(struct crypto_akcipher *tfm) 5668c2ecf20Sopenharmony_ci{ 5678c2ecf20Sopenharmony_ci struct akcipher_instance *inst = akcipher_alg_instance(tfm); 5688c2ecf20Sopenharmony_ci struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst); 5698c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 5708c2ecf20Sopenharmony_ci struct crypto_akcipher *child_tfm; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci child_tfm = crypto_spawn_akcipher(&ictx->spawn); 5738c2ecf20Sopenharmony_ci if (IS_ERR(child_tfm)) 5748c2ecf20Sopenharmony_ci return PTR_ERR(child_tfm); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci ctx->child = child_tfm; 5778c2ecf20Sopenharmony_ci return 0; 5788c2ecf20Sopenharmony_ci} 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cistatic void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci crypto_free_akcipher(ctx->child); 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic void pkcs1pad_free(struct akcipher_instance *inst) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst); 5908c2ecf20Sopenharmony_ci struct crypto_akcipher_spawn *spawn = &ctx->spawn; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci crypto_drop_akcipher(spawn); 5938c2ecf20Sopenharmony_ci kfree(inst); 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_cistatic int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci u32 mask; 5998c2ecf20Sopenharmony_ci struct akcipher_instance *inst; 6008c2ecf20Sopenharmony_ci struct pkcs1pad_inst_ctx *ctx; 6018c2ecf20Sopenharmony_ci struct akcipher_alg *rsa_alg; 6028c2ecf20Sopenharmony_ci const char *hash_name; 6038c2ecf20Sopenharmony_ci int err; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AKCIPHER, &mask); 6068c2ecf20Sopenharmony_ci if (err) 6078c2ecf20Sopenharmony_ci return err; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 6108c2ecf20Sopenharmony_ci if (!inst) 6118c2ecf20Sopenharmony_ci return -ENOMEM; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci ctx = akcipher_instance_ctx(inst); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci err = crypto_grab_akcipher(&ctx->spawn, akcipher_crypto_instance(inst), 6168c2ecf20Sopenharmony_ci crypto_attr_alg_name(tb[1]), 0, mask); 6178c2ecf20Sopenharmony_ci if (err) 6188c2ecf20Sopenharmony_ci goto err_free_inst; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci rsa_alg = crypto_spawn_akcipher_alg(&ctx->spawn); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (strcmp(rsa_alg->base.cra_name, "rsa") != 0) { 6238c2ecf20Sopenharmony_ci err = -EINVAL; 6248c2ecf20Sopenharmony_ci goto err_free_inst; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci err = -ENAMETOOLONG; 6288c2ecf20Sopenharmony_ci hash_name = crypto_attr_alg_name(tb[2]); 6298c2ecf20Sopenharmony_ci if (IS_ERR(hash_name)) { 6308c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_name, 6318c2ecf20Sopenharmony_ci CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", 6328c2ecf20Sopenharmony_ci rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME) 6338c2ecf20Sopenharmony_ci goto err_free_inst; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_driver_name, 6368c2ecf20Sopenharmony_ci CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", 6378c2ecf20Sopenharmony_ci rsa_alg->base.cra_driver_name) >= 6388c2ecf20Sopenharmony_ci CRYPTO_MAX_ALG_NAME) 6398c2ecf20Sopenharmony_ci goto err_free_inst; 6408c2ecf20Sopenharmony_ci } else { 6418c2ecf20Sopenharmony_ci ctx->digest_info = rsa_lookup_asn1(hash_name); 6428c2ecf20Sopenharmony_ci if (!ctx->digest_info) { 6438c2ecf20Sopenharmony_ci err = -EINVAL; 6448c2ecf20Sopenharmony_ci goto err_free_inst; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 6488c2ecf20Sopenharmony_ci "pkcs1pad(%s,%s)", rsa_alg->base.cra_name, 6498c2ecf20Sopenharmony_ci hash_name) >= CRYPTO_MAX_ALG_NAME) 6508c2ecf20Sopenharmony_ci goto err_free_inst; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_driver_name, 6538c2ecf20Sopenharmony_ci CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)", 6548c2ecf20Sopenharmony_ci rsa_alg->base.cra_driver_name, 6558c2ecf20Sopenharmony_ci hash_name) >= CRYPTO_MAX_ALG_NAME) 6568c2ecf20Sopenharmony_ci goto err_free_inst; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci inst->alg.base.cra_priority = rsa_alg->base.cra_priority; 6608c2ecf20Sopenharmony_ci inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci inst->alg.init = pkcs1pad_init_tfm; 6638c2ecf20Sopenharmony_ci inst->alg.exit = pkcs1pad_exit_tfm; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci inst->alg.encrypt = pkcs1pad_encrypt; 6668c2ecf20Sopenharmony_ci inst->alg.decrypt = pkcs1pad_decrypt; 6678c2ecf20Sopenharmony_ci inst->alg.sign = pkcs1pad_sign; 6688c2ecf20Sopenharmony_ci inst->alg.verify = pkcs1pad_verify; 6698c2ecf20Sopenharmony_ci inst->alg.set_pub_key = pkcs1pad_set_pub_key; 6708c2ecf20Sopenharmony_ci inst->alg.set_priv_key = pkcs1pad_set_priv_key; 6718c2ecf20Sopenharmony_ci inst->alg.max_size = pkcs1pad_get_max_size; 6728c2ecf20Sopenharmony_ci inst->alg.reqsize = sizeof(struct pkcs1pad_request) + rsa_alg->reqsize; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci inst->free = pkcs1pad_free; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci err = akcipher_register_instance(tmpl, inst); 6778c2ecf20Sopenharmony_ci if (err) { 6788c2ecf20Sopenharmony_cierr_free_inst: 6798c2ecf20Sopenharmony_ci pkcs1pad_free(inst); 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci return err; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistruct crypto_template rsa_pkcs1pad_tmpl = { 6858c2ecf20Sopenharmony_ci .name = "pkcs1pad", 6868c2ecf20Sopenharmony_ci .create = pkcs1pad_create, 6878c2ecf20Sopenharmony_ci .module = THIS_MODULE, 6888c2ecf20Sopenharmony_ci}; 689