cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ccp-crypto-rsa.c (6892B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AMD Cryptographic Coprocessor (CCP) RSA crypto API support
      4 *
      5 * Copyright (C) 2017 Advanced Micro Devices, Inc.
      6 *
      7 * Author: Gary R Hook <gary.hook@amd.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/sched.h>
     12#include <linux/scatterlist.h>
     13#include <linux/crypto.h>
     14#include <crypto/algapi.h>
     15#include <crypto/internal/rsa.h>
     16#include <crypto/internal/akcipher.h>
     17#include <crypto/akcipher.h>
     18#include <crypto/scatterwalk.h>
     19
     20#include "ccp-crypto.h"
     21
     22static inline struct akcipher_request *akcipher_request_cast(
     23	struct crypto_async_request *req)
     24{
     25	return container_of(req, struct akcipher_request, base);
     26}
     27
     28static inline int ccp_copy_and_save_keypart(u8 **kpbuf, unsigned int *kplen,
     29					    const u8 *buf, size_t sz)
     30{
     31	int nskip;
     32
     33	for (nskip = 0; nskip < sz; nskip++)
     34		if (buf[nskip])
     35			break;
     36	*kplen = sz - nskip;
     37	*kpbuf = kmemdup(buf + nskip, *kplen, GFP_KERNEL);
     38	if (!*kpbuf)
     39		return -ENOMEM;
     40
     41	return 0;
     42}
     43
     44static int ccp_rsa_complete(struct crypto_async_request *async_req, int ret)
     45{
     46	struct akcipher_request *req = akcipher_request_cast(async_req);
     47	struct ccp_rsa_req_ctx *rctx = akcipher_request_ctx(req);
     48
     49	if (ret)
     50		return ret;
     51
     52	req->dst_len = rctx->cmd.u.rsa.key_size >> 3;
     53
     54	return 0;
     55}
     56
     57static unsigned int ccp_rsa_maxsize(struct crypto_akcipher *tfm)
     58{
     59	struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);
     60
     61	return ctx->u.rsa.n_len;
     62}
     63
     64static int ccp_rsa_crypt(struct akcipher_request *req, bool encrypt)
     65{
     66	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
     67	struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);
     68	struct ccp_rsa_req_ctx *rctx = akcipher_request_ctx(req);
     69	int ret = 0;
     70
     71	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
     72	INIT_LIST_HEAD(&rctx->cmd.entry);
     73	rctx->cmd.engine = CCP_ENGINE_RSA;
     74
     75	rctx->cmd.u.rsa.key_size = ctx->u.rsa.key_len; /* in bits */
     76	if (encrypt) {
     77		rctx->cmd.u.rsa.exp = &ctx->u.rsa.e_sg;
     78		rctx->cmd.u.rsa.exp_len = ctx->u.rsa.e_len;
     79	} else {
     80		rctx->cmd.u.rsa.exp = &ctx->u.rsa.d_sg;
     81		rctx->cmd.u.rsa.exp_len = ctx->u.rsa.d_len;
     82	}
     83	rctx->cmd.u.rsa.mod = &ctx->u.rsa.n_sg;
     84	rctx->cmd.u.rsa.mod_len = ctx->u.rsa.n_len;
     85	rctx->cmd.u.rsa.src = req->src;
     86	rctx->cmd.u.rsa.src_len = req->src_len;
     87	rctx->cmd.u.rsa.dst = req->dst;
     88
     89	ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
     90
     91	return ret;
     92}
     93
     94static int ccp_rsa_encrypt(struct akcipher_request *req)
     95{
     96	return ccp_rsa_crypt(req, true);
     97}
     98
     99static int ccp_rsa_decrypt(struct akcipher_request *req)
    100{
    101	return ccp_rsa_crypt(req, false);
    102}
    103
    104static int ccp_check_key_length(unsigned int len)
    105{
    106	/* In bits */
    107	if (len < 8 || len > 4096)
    108		return -EINVAL;
    109	return 0;
    110}
    111
    112static void ccp_rsa_free_key_bufs(struct ccp_ctx *ctx)
    113{
    114	/* Clean up old key data */
    115	kfree_sensitive(ctx->u.rsa.e_buf);
    116	ctx->u.rsa.e_buf = NULL;
    117	ctx->u.rsa.e_len = 0;
    118	kfree_sensitive(ctx->u.rsa.n_buf);
    119	ctx->u.rsa.n_buf = NULL;
    120	ctx->u.rsa.n_len = 0;
    121	kfree_sensitive(ctx->u.rsa.d_buf);
    122	ctx->u.rsa.d_buf = NULL;
    123	ctx->u.rsa.d_len = 0;
    124}
    125
    126static int ccp_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
    127			  unsigned int keylen, bool private)
    128{
    129	struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);
    130	struct rsa_key raw_key;
    131	int ret;
    132
    133	ccp_rsa_free_key_bufs(ctx);
    134	memset(&raw_key, 0, sizeof(raw_key));
    135
    136	/* Code borrowed from crypto/rsa.c */
    137	if (private)
    138		ret = rsa_parse_priv_key(&raw_key, key, keylen);
    139	else
    140		ret = rsa_parse_pub_key(&raw_key, key, keylen);
    141	if (ret)
    142		goto n_key;
    143
    144	ret = ccp_copy_and_save_keypart(&ctx->u.rsa.n_buf, &ctx->u.rsa.n_len,
    145					raw_key.n, raw_key.n_sz);
    146	if (ret)
    147		goto key_err;
    148	sg_init_one(&ctx->u.rsa.n_sg, ctx->u.rsa.n_buf, ctx->u.rsa.n_len);
    149
    150	ctx->u.rsa.key_len = ctx->u.rsa.n_len << 3; /* convert to bits */
    151	if (ccp_check_key_length(ctx->u.rsa.key_len)) {
    152		ret = -EINVAL;
    153		goto key_err;
    154	}
    155
    156	ret = ccp_copy_and_save_keypart(&ctx->u.rsa.e_buf, &ctx->u.rsa.e_len,
    157					raw_key.e, raw_key.e_sz);
    158	if (ret)
    159		goto key_err;
    160	sg_init_one(&ctx->u.rsa.e_sg, ctx->u.rsa.e_buf, ctx->u.rsa.e_len);
    161
    162	if (private) {
    163		ret = ccp_copy_and_save_keypart(&ctx->u.rsa.d_buf,
    164						&ctx->u.rsa.d_len,
    165						raw_key.d, raw_key.d_sz);
    166		if (ret)
    167			goto key_err;
    168		sg_init_one(&ctx->u.rsa.d_sg,
    169			    ctx->u.rsa.d_buf, ctx->u.rsa.d_len);
    170	}
    171
    172	return 0;
    173
    174key_err:
    175	ccp_rsa_free_key_bufs(ctx);
    176
    177n_key:
    178	return ret;
    179}
    180
    181static int ccp_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,
    182			      unsigned int keylen)
    183{
    184	return ccp_rsa_setkey(tfm, key, keylen, true);
    185}
    186
    187static int ccp_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
    188			     unsigned int keylen)
    189{
    190	return ccp_rsa_setkey(tfm, key, keylen, false);
    191}
    192
    193static int ccp_rsa_init_tfm(struct crypto_akcipher *tfm)
    194{
    195	struct ccp_ctx *ctx = akcipher_tfm_ctx(tfm);
    196
    197	akcipher_set_reqsize(tfm, sizeof(struct ccp_rsa_req_ctx));
    198	ctx->complete = ccp_rsa_complete;
    199
    200	return 0;
    201}
    202
    203static void ccp_rsa_exit_tfm(struct crypto_akcipher *tfm)
    204{
    205	struct ccp_ctx *ctx = crypto_tfm_ctx(&tfm->base);
    206
    207	ccp_rsa_free_key_bufs(ctx);
    208}
    209
    210static struct akcipher_alg ccp_rsa_defaults = {
    211	.encrypt = ccp_rsa_encrypt,
    212	.decrypt = ccp_rsa_decrypt,
    213	.set_pub_key = ccp_rsa_setpubkey,
    214	.set_priv_key = ccp_rsa_setprivkey,
    215	.max_size = ccp_rsa_maxsize,
    216	.init = ccp_rsa_init_tfm,
    217	.exit = ccp_rsa_exit_tfm,
    218	.base = {
    219		.cra_name = "rsa",
    220		.cra_driver_name = "rsa-ccp",
    221		.cra_priority = CCP_CRA_PRIORITY,
    222		.cra_module = THIS_MODULE,
    223		.cra_ctxsize = 2 * sizeof(struct ccp_ctx),
    224	},
    225};
    226
    227struct ccp_rsa_def {
    228	unsigned int version;
    229	const char *name;
    230	const char *driver_name;
    231	unsigned int reqsize;
    232	struct akcipher_alg *alg_defaults;
    233};
    234
    235static struct ccp_rsa_def rsa_algs[] = {
    236	{
    237		.version	= CCP_VERSION(3, 0),
    238		.name		= "rsa",
    239		.driver_name	= "rsa-ccp",
    240		.reqsize	= sizeof(struct ccp_rsa_req_ctx),
    241		.alg_defaults	= &ccp_rsa_defaults,
    242	}
    243};
    244
    245static int ccp_register_rsa_alg(struct list_head *head,
    246			        const struct ccp_rsa_def *def)
    247{
    248	struct ccp_crypto_akcipher_alg *ccp_alg;
    249	struct akcipher_alg *alg;
    250	int ret;
    251
    252	ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
    253	if (!ccp_alg)
    254		return -ENOMEM;
    255
    256	INIT_LIST_HEAD(&ccp_alg->entry);
    257
    258	alg = &ccp_alg->alg;
    259	*alg = *def->alg_defaults;
    260	snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
    261	snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
    262		 def->driver_name);
    263	ret = crypto_register_akcipher(alg);
    264	if (ret) {
    265		pr_err("%s akcipher algorithm registration error (%d)\n",
    266		       alg->base.cra_name, ret);
    267		kfree(ccp_alg);
    268		return ret;
    269	}
    270
    271	list_add(&ccp_alg->entry, head);
    272
    273	return 0;
    274}
    275
    276int ccp_register_rsa_algs(struct list_head *head)
    277{
    278	int i, ret;
    279	unsigned int ccpversion = ccp_version();
    280
    281	/* Register the RSA algorithm in standard mode
    282	 * This works for CCP v3 and later
    283	 */
    284	for (i = 0; i < ARRAY_SIZE(rsa_algs); i++) {
    285		if (rsa_algs[i].version > ccpversion)
    286			continue;
    287		ret = ccp_register_rsa_alg(head, &rsa_algs[i]);
    288		if (ret)
    289			return ret;
    290	}
    291
    292	return 0;
    293}