162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* RSA asymmetric public-key algorithm [RFC3447]
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2015, Intel Corporation
562306a36Sopenharmony_ci * Authors: Tadeusz Struk <tadeusz.struk@intel.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/fips.h>
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/mpi.h>
1162306a36Sopenharmony_ci#include <crypto/internal/rsa.h>
1262306a36Sopenharmony_ci#include <crypto/internal/akcipher.h>
1362306a36Sopenharmony_ci#include <crypto/akcipher.h>
1462306a36Sopenharmony_ci#include <crypto/algapi.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistruct rsa_mpi_key {
1762306a36Sopenharmony_ci	MPI n;
1862306a36Sopenharmony_ci	MPI e;
1962306a36Sopenharmony_ci	MPI d;
2062306a36Sopenharmony_ci	MPI p;
2162306a36Sopenharmony_ci	MPI q;
2262306a36Sopenharmony_ci	MPI dp;
2362306a36Sopenharmony_ci	MPI dq;
2462306a36Sopenharmony_ci	MPI qinv;
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/*
2862306a36Sopenharmony_ci * RSAEP function [RFC3447 sec 5.1.1]
2962306a36Sopenharmony_ci * c = m^e mod n;
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_cistatic int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	/* (1) Validate 0 <= m < n */
3462306a36Sopenharmony_ci	if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
3562306a36Sopenharmony_ci		return -EINVAL;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	/* (2) c = m^e mod n */
3862306a36Sopenharmony_ci	return mpi_powm(c, m, key->e, key->n);
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * RSADP function [RFC3447 sec 5.1.2]
4362306a36Sopenharmony_ci * m_1 = c^dP mod p;
4462306a36Sopenharmony_ci * m_2 = c^dQ mod q;
4562306a36Sopenharmony_ci * h = (m_1 - m_2) * qInv mod p;
4662306a36Sopenharmony_ci * m = m_2 + q * h;
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_cistatic int _rsa_dec_crt(const struct rsa_mpi_key *key, MPI m_or_m1_or_h, MPI c)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	MPI m2, m12_or_qh;
5162306a36Sopenharmony_ci	int ret = -ENOMEM;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	/* (1) Validate 0 <= c < n */
5462306a36Sopenharmony_ci	if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
5562306a36Sopenharmony_ci		return -EINVAL;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	m2 = mpi_alloc(0);
5862306a36Sopenharmony_ci	m12_or_qh = mpi_alloc(0);
5962306a36Sopenharmony_ci	if (!m2 || !m12_or_qh)
6062306a36Sopenharmony_ci		goto err_free_mpi;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	/* (2i) m_1 = c^dP mod p */
6362306a36Sopenharmony_ci	ret = mpi_powm(m_or_m1_or_h, c, key->dp, key->p);
6462306a36Sopenharmony_ci	if (ret)
6562306a36Sopenharmony_ci		goto err_free_mpi;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* (2i) m_2 = c^dQ mod q */
6862306a36Sopenharmony_ci	ret = mpi_powm(m2, c, key->dq, key->q);
6962306a36Sopenharmony_ci	if (ret)
7062306a36Sopenharmony_ci		goto err_free_mpi;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	/* (2iii) h = (m_1 - m_2) * qInv mod p */
7362306a36Sopenharmony_ci	mpi_sub(m12_or_qh, m_or_m1_or_h, m2);
7462306a36Sopenharmony_ci	mpi_mulm(m_or_m1_or_h, m12_or_qh, key->qinv, key->p);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	/* (2iv) m = m_2 + q * h */
7762306a36Sopenharmony_ci	mpi_mul(m12_or_qh, key->q, m_or_m1_or_h);
7862306a36Sopenharmony_ci	mpi_addm(m_or_m1_or_h, m2, m12_or_qh, key->n);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	ret = 0;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cierr_free_mpi:
8362306a36Sopenharmony_ci	mpi_free(m12_or_qh);
8462306a36Sopenharmony_ci	mpi_free(m2);
8562306a36Sopenharmony_ci	return ret;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	return akcipher_tfm_ctx(tfm);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic int rsa_enc(struct akcipher_request *req)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
9662306a36Sopenharmony_ci	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
9762306a36Sopenharmony_ci	MPI m, c = mpi_alloc(0);
9862306a36Sopenharmony_ci	int ret = 0;
9962306a36Sopenharmony_ci	int sign;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (!c)
10262306a36Sopenharmony_ci		return -ENOMEM;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (unlikely(!pkey->n || !pkey->e)) {
10562306a36Sopenharmony_ci		ret = -EINVAL;
10662306a36Sopenharmony_ci		goto err_free_c;
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	ret = -ENOMEM;
11062306a36Sopenharmony_ci	m = mpi_read_raw_from_sgl(req->src, req->src_len);
11162306a36Sopenharmony_ci	if (!m)
11262306a36Sopenharmony_ci		goto err_free_c;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	ret = _rsa_enc(pkey, c, m);
11562306a36Sopenharmony_ci	if (ret)
11662306a36Sopenharmony_ci		goto err_free_m;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign);
11962306a36Sopenharmony_ci	if (ret)
12062306a36Sopenharmony_ci		goto err_free_m;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (sign < 0)
12362306a36Sopenharmony_ci		ret = -EBADMSG;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cierr_free_m:
12662306a36Sopenharmony_ci	mpi_free(m);
12762306a36Sopenharmony_cierr_free_c:
12862306a36Sopenharmony_ci	mpi_free(c);
12962306a36Sopenharmony_ci	return ret;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic int rsa_dec(struct akcipher_request *req)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
13562306a36Sopenharmony_ci	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
13662306a36Sopenharmony_ci	MPI c, m = mpi_alloc(0);
13762306a36Sopenharmony_ci	int ret = 0;
13862306a36Sopenharmony_ci	int sign;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	if (!m)
14162306a36Sopenharmony_ci		return -ENOMEM;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (unlikely(!pkey->n || !pkey->d)) {
14462306a36Sopenharmony_ci		ret = -EINVAL;
14562306a36Sopenharmony_ci		goto err_free_m;
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	ret = -ENOMEM;
14962306a36Sopenharmony_ci	c = mpi_read_raw_from_sgl(req->src, req->src_len);
15062306a36Sopenharmony_ci	if (!c)
15162306a36Sopenharmony_ci		goto err_free_m;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	ret = _rsa_dec_crt(pkey, m, c);
15462306a36Sopenharmony_ci	if (ret)
15562306a36Sopenharmony_ci		goto err_free_c;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
15862306a36Sopenharmony_ci	if (ret)
15962306a36Sopenharmony_ci		goto err_free_c;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (sign < 0)
16262306a36Sopenharmony_ci		ret = -EBADMSG;
16362306a36Sopenharmony_cierr_free_c:
16462306a36Sopenharmony_ci	mpi_free(c);
16562306a36Sopenharmony_cierr_free_m:
16662306a36Sopenharmony_ci	mpi_free(m);
16762306a36Sopenharmony_ci	return ret;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic void rsa_free_mpi_key(struct rsa_mpi_key *key)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	mpi_free(key->d);
17362306a36Sopenharmony_ci	mpi_free(key->e);
17462306a36Sopenharmony_ci	mpi_free(key->n);
17562306a36Sopenharmony_ci	mpi_free(key->p);
17662306a36Sopenharmony_ci	mpi_free(key->q);
17762306a36Sopenharmony_ci	mpi_free(key->dp);
17862306a36Sopenharmony_ci	mpi_free(key->dq);
17962306a36Sopenharmony_ci	mpi_free(key->qinv);
18062306a36Sopenharmony_ci	key->d = NULL;
18162306a36Sopenharmony_ci	key->e = NULL;
18262306a36Sopenharmony_ci	key->n = NULL;
18362306a36Sopenharmony_ci	key->p = NULL;
18462306a36Sopenharmony_ci	key->q = NULL;
18562306a36Sopenharmony_ci	key->dp = NULL;
18662306a36Sopenharmony_ci	key->dq = NULL;
18762306a36Sopenharmony_ci	key->qinv = NULL;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int rsa_check_key_length(unsigned int len)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	switch (len) {
19362306a36Sopenharmony_ci	case 512:
19462306a36Sopenharmony_ci	case 1024:
19562306a36Sopenharmony_ci	case 1536:
19662306a36Sopenharmony_ci		if (fips_enabled)
19762306a36Sopenharmony_ci			return -EINVAL;
19862306a36Sopenharmony_ci		fallthrough;
19962306a36Sopenharmony_ci	case 2048:
20062306a36Sopenharmony_ci	case 3072:
20162306a36Sopenharmony_ci	case 4096:
20262306a36Sopenharmony_ci		return 0;
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	return -EINVAL;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic int rsa_check_exponent_fips(MPI e)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	MPI e_max = NULL;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/* check if odd */
21362306a36Sopenharmony_ci	if (!mpi_test_bit(e, 0)) {
21462306a36Sopenharmony_ci		return -EINVAL;
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	/* check if 2^16 < e < 2^256. */
21862306a36Sopenharmony_ci	if (mpi_cmp_ui(e, 65536) <= 0) {
21962306a36Sopenharmony_ci		return -EINVAL;
22062306a36Sopenharmony_ci	}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	e_max = mpi_alloc(0);
22362306a36Sopenharmony_ci	if (!e_max)
22462306a36Sopenharmony_ci		return -ENOMEM;
22562306a36Sopenharmony_ci	mpi_set_bit(e_max, 256);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (mpi_cmp(e, e_max) >= 0) {
22862306a36Sopenharmony_ci		mpi_free(e_max);
22962306a36Sopenharmony_ci		return -EINVAL;
23062306a36Sopenharmony_ci	}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	mpi_free(e_max);
23362306a36Sopenharmony_ci	return 0;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
23762306a36Sopenharmony_ci			   unsigned int keylen)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
24062306a36Sopenharmony_ci	struct rsa_key raw_key = {0};
24162306a36Sopenharmony_ci	int ret;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* Free the old MPI key if any */
24462306a36Sopenharmony_ci	rsa_free_mpi_key(mpi_key);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	ret = rsa_parse_pub_key(&raw_key, key, keylen);
24762306a36Sopenharmony_ci	if (ret)
24862306a36Sopenharmony_ci		return ret;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz);
25162306a36Sopenharmony_ci	if (!mpi_key->e)
25262306a36Sopenharmony_ci		goto err;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz);
25562306a36Sopenharmony_ci	if (!mpi_key->n)
25662306a36Sopenharmony_ci		goto err;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) {
25962306a36Sopenharmony_ci		rsa_free_mpi_key(mpi_key);
26062306a36Sopenharmony_ci		return -EINVAL;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	if (fips_enabled && rsa_check_exponent_fips(mpi_key->e)) {
26462306a36Sopenharmony_ci		rsa_free_mpi_key(mpi_key);
26562306a36Sopenharmony_ci		return -EINVAL;
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	return 0;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cierr:
27162306a36Sopenharmony_ci	rsa_free_mpi_key(mpi_key);
27262306a36Sopenharmony_ci	return -ENOMEM;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
27662306a36Sopenharmony_ci			    unsigned int keylen)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
27962306a36Sopenharmony_ci	struct rsa_key raw_key = {0};
28062306a36Sopenharmony_ci	int ret;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	/* Free the old MPI key if any */
28362306a36Sopenharmony_ci	rsa_free_mpi_key(mpi_key);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	ret = rsa_parse_priv_key(&raw_key, key, keylen);
28662306a36Sopenharmony_ci	if (ret)
28762306a36Sopenharmony_ci		return ret;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	mpi_key->d = mpi_read_raw_data(raw_key.d, raw_key.d_sz);
29062306a36Sopenharmony_ci	if (!mpi_key->d)
29162306a36Sopenharmony_ci		goto err;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz);
29462306a36Sopenharmony_ci	if (!mpi_key->e)
29562306a36Sopenharmony_ci		goto err;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz);
29862306a36Sopenharmony_ci	if (!mpi_key->n)
29962306a36Sopenharmony_ci		goto err;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	mpi_key->p = mpi_read_raw_data(raw_key.p, raw_key.p_sz);
30262306a36Sopenharmony_ci	if (!mpi_key->p)
30362306a36Sopenharmony_ci		goto err;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	mpi_key->q = mpi_read_raw_data(raw_key.q, raw_key.q_sz);
30662306a36Sopenharmony_ci	if (!mpi_key->q)
30762306a36Sopenharmony_ci		goto err;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	mpi_key->dp = mpi_read_raw_data(raw_key.dp, raw_key.dp_sz);
31062306a36Sopenharmony_ci	if (!mpi_key->dp)
31162306a36Sopenharmony_ci		goto err;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	mpi_key->dq = mpi_read_raw_data(raw_key.dq, raw_key.dq_sz);
31462306a36Sopenharmony_ci	if (!mpi_key->dq)
31562306a36Sopenharmony_ci		goto err;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	mpi_key->qinv = mpi_read_raw_data(raw_key.qinv, raw_key.qinv_sz);
31862306a36Sopenharmony_ci	if (!mpi_key->qinv)
31962306a36Sopenharmony_ci		goto err;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) {
32262306a36Sopenharmony_ci		rsa_free_mpi_key(mpi_key);
32362306a36Sopenharmony_ci		return -EINVAL;
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	if (fips_enabled && rsa_check_exponent_fips(mpi_key->e)) {
32762306a36Sopenharmony_ci		rsa_free_mpi_key(mpi_key);
32862306a36Sopenharmony_ci		return -EINVAL;
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	return 0;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cierr:
33462306a36Sopenharmony_ci	rsa_free_mpi_key(mpi_key);
33562306a36Sopenharmony_ci	return -ENOMEM;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic unsigned int rsa_max_size(struct crypto_akcipher *tfm)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	return mpi_get_size(pkey->n);
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic void rsa_exit_tfm(struct crypto_akcipher *tfm)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	rsa_free_mpi_key(pkey);
35062306a36Sopenharmony_ci}
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cistatic struct akcipher_alg rsa = {
35362306a36Sopenharmony_ci	.encrypt = rsa_enc,
35462306a36Sopenharmony_ci	.decrypt = rsa_dec,
35562306a36Sopenharmony_ci	.set_priv_key = rsa_set_priv_key,
35662306a36Sopenharmony_ci	.set_pub_key = rsa_set_pub_key,
35762306a36Sopenharmony_ci	.max_size = rsa_max_size,
35862306a36Sopenharmony_ci	.exit = rsa_exit_tfm,
35962306a36Sopenharmony_ci	.base = {
36062306a36Sopenharmony_ci		.cra_name = "rsa",
36162306a36Sopenharmony_ci		.cra_driver_name = "rsa-generic",
36262306a36Sopenharmony_ci		.cra_priority = 100,
36362306a36Sopenharmony_ci		.cra_module = THIS_MODULE,
36462306a36Sopenharmony_ci		.cra_ctxsize = sizeof(struct rsa_mpi_key),
36562306a36Sopenharmony_ci	},
36662306a36Sopenharmony_ci};
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic int __init rsa_init(void)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	int err;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	err = crypto_register_akcipher(&rsa);
37362306a36Sopenharmony_ci	if (err)
37462306a36Sopenharmony_ci		return err;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	err = crypto_register_template(&rsa_pkcs1pad_tmpl);
37762306a36Sopenharmony_ci	if (err) {
37862306a36Sopenharmony_ci		crypto_unregister_akcipher(&rsa);
37962306a36Sopenharmony_ci		return err;
38062306a36Sopenharmony_ci	}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	return 0;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic void __exit rsa_exit(void)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
38862306a36Sopenharmony_ci	crypto_unregister_akcipher(&rsa);
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cisubsys_initcall(rsa_init);
39262306a36Sopenharmony_cimodule_exit(rsa_exit);
39362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("rsa");
39462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
39562306a36Sopenharmony_ciMODULE_DESCRIPTION("RSA generic algorithm");
396