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

nitrox_aead.c (14266B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/kernel.h>
      3#include <linux/printk.h>
      4#include <linux/crypto.h>
      5#include <linux/rtnetlink.h>
      6
      7#include <crypto/aead.h>
      8#include <crypto/authenc.h>
      9#include <crypto/des.h>
     10#include <crypto/internal/aead.h>
     11#include <crypto/scatterwalk.h>
     12#include <crypto/gcm.h>
     13
     14#include "nitrox_dev.h"
     15#include "nitrox_common.h"
     16#include "nitrox_req.h"
     17
     18#define GCM_AES_SALT_SIZE	4
     19
     20union gph_p3 {
     21	struct {
     22#ifdef __BIG_ENDIAN_BITFIELD
     23		u16 iv_offset : 8;
     24		u16 auth_offset	: 8;
     25#else
     26		u16 auth_offset	: 8;
     27		u16 iv_offset : 8;
     28#endif
     29	};
     30	u16 param;
     31};
     32
     33static int nitrox_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key,
     34				 unsigned int keylen)
     35{
     36	int aes_keylen;
     37	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
     38	struct flexi_crypto_context *fctx;
     39	union fc_ctx_flags flags;
     40
     41	aes_keylen = flexi_aes_keylen(keylen);
     42	if (aes_keylen < 0)
     43		return -EINVAL;
     44
     45	/* fill crypto context */
     46	fctx = nctx->u.fctx;
     47	flags.fu = be64_to_cpu(fctx->flags.f);
     48	flags.w0.aes_keylen = aes_keylen;
     49	fctx->flags.f = cpu_to_be64(flags.fu);
     50
     51	/* copy enc key to context */
     52	memset(&fctx->crypto, 0, sizeof(fctx->crypto));
     53	memcpy(fctx->crypto.u.key, key, keylen);
     54
     55	return 0;
     56}
     57
     58static int nitrox_aead_setauthsize(struct crypto_aead *aead,
     59				   unsigned int authsize)
     60{
     61	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
     62	struct flexi_crypto_context *fctx = nctx->u.fctx;
     63	union fc_ctx_flags flags;
     64
     65	flags.fu = be64_to_cpu(fctx->flags.f);
     66	flags.w0.mac_len = authsize;
     67	fctx->flags.f = cpu_to_be64(flags.fu);
     68
     69	aead->authsize = authsize;
     70
     71	return 0;
     72}
     73
     74static int nitrox_aes_gcm_setauthsize(struct crypto_aead *aead,
     75				      unsigned int authsize)
     76{
     77	switch (authsize) {
     78	case 4:
     79	case 8:
     80	case 12:
     81	case 13:
     82	case 14:
     83	case 15:
     84	case 16:
     85		break;
     86	default:
     87		return -EINVAL;
     88	}
     89
     90	return nitrox_aead_setauthsize(aead, authsize);
     91}
     92
     93static int alloc_src_sglist(struct nitrox_kcrypt_request *nkreq,
     94			    struct scatterlist *src, char *iv, int ivsize,
     95			    int buflen)
     96{
     97	int nents = sg_nents_for_len(src, buflen);
     98	int ret;
     99
    100	if (nents < 0)
    101		return nents;
    102
    103	/* IV entry */
    104	nents += 1;
    105	/* Allocate buffer to hold IV and input scatterlist array */
    106	ret = alloc_src_req_buf(nkreq, nents, ivsize);
    107	if (ret)
    108		return ret;
    109
    110	nitrox_creq_copy_iv(nkreq->src, iv, ivsize);
    111	nitrox_creq_set_src_sg(nkreq, nents, ivsize, src, buflen);
    112
    113	return 0;
    114}
    115
    116static int alloc_dst_sglist(struct nitrox_kcrypt_request *nkreq,
    117			    struct scatterlist *dst, int ivsize, int buflen)
    118{
    119	int nents = sg_nents_for_len(dst, buflen);
    120	int ret;
    121
    122	if (nents < 0)
    123		return nents;
    124
    125	/* IV, ORH, COMPLETION entries */
    126	nents += 3;
    127	/* Allocate buffer to hold ORH, COMPLETION and output scatterlist
    128	 * array
    129	 */
    130	ret = alloc_dst_req_buf(nkreq, nents);
    131	if (ret)
    132		return ret;
    133
    134	nitrox_creq_set_orh(nkreq);
    135	nitrox_creq_set_comp(nkreq);
    136	nitrox_creq_set_dst_sg(nkreq, nents, ivsize, dst, buflen);
    137
    138	return 0;
    139}
    140
    141static void free_src_sglist(struct nitrox_kcrypt_request *nkreq)
    142{
    143	kfree(nkreq->src);
    144}
    145
    146static void free_dst_sglist(struct nitrox_kcrypt_request *nkreq)
    147{
    148	kfree(nkreq->dst);
    149}
    150
    151static int nitrox_set_creq(struct nitrox_aead_rctx *rctx)
    152{
    153	struct se_crypto_request *creq = &rctx->nkreq.creq;
    154	union gph_p3 param3;
    155	int ret;
    156
    157	creq->flags = rctx->flags;
    158	creq->gfp = (rctx->flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL :
    159							       GFP_ATOMIC;
    160
    161	creq->ctrl.value = 0;
    162	creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC;
    163	creq->ctrl.s.arg = rctx->ctrl_arg;
    164
    165	creq->gph.param0 = cpu_to_be16(rctx->cryptlen);
    166	creq->gph.param1 = cpu_to_be16(rctx->cryptlen + rctx->assoclen);
    167	creq->gph.param2 = cpu_to_be16(rctx->ivsize + rctx->assoclen);
    168	param3.iv_offset = 0;
    169	param3.auth_offset = rctx->ivsize;
    170	creq->gph.param3 = cpu_to_be16(param3.param);
    171
    172	creq->ctx_handle = rctx->ctx_handle;
    173	creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context);
    174
    175	ret = alloc_src_sglist(&rctx->nkreq, rctx->src, rctx->iv, rctx->ivsize,
    176			       rctx->srclen);
    177	if (ret)
    178		return ret;
    179
    180	ret = alloc_dst_sglist(&rctx->nkreq, rctx->dst, rctx->ivsize,
    181			       rctx->dstlen);
    182	if (ret) {
    183		free_src_sglist(&rctx->nkreq);
    184		return ret;
    185	}
    186
    187	return 0;
    188}
    189
    190static void nitrox_aead_callback(void *arg, int err)
    191{
    192	struct aead_request *areq = arg;
    193	struct nitrox_aead_rctx *rctx = aead_request_ctx(areq);
    194
    195	free_src_sglist(&rctx->nkreq);
    196	free_dst_sglist(&rctx->nkreq);
    197	if (err) {
    198		pr_err_ratelimited("request failed status 0x%0x\n", err);
    199		err = -EINVAL;
    200	}
    201
    202	areq->base.complete(&areq->base, err);
    203}
    204
    205static inline bool nitrox_aes_gcm_assoclen_supported(unsigned int assoclen)
    206{
    207	if (assoclen <= 512)
    208		return true;
    209
    210	return false;
    211}
    212
    213static int nitrox_aes_gcm_enc(struct aead_request *areq)
    214{
    215	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
    216	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    217	struct nitrox_aead_rctx *rctx = aead_request_ctx(areq);
    218	struct se_crypto_request *creq = &rctx->nkreq.creq;
    219	struct flexi_crypto_context *fctx = nctx->u.fctx;
    220	int ret;
    221
    222	if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen))
    223		return -EINVAL;
    224
    225	memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE);
    226
    227	rctx->cryptlen = areq->cryptlen;
    228	rctx->assoclen = areq->assoclen;
    229	rctx->srclen = areq->assoclen + areq->cryptlen;
    230	rctx->dstlen = rctx->srclen + aead->authsize;
    231	rctx->iv = &areq->iv[GCM_AES_SALT_SIZE];
    232	rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE;
    233	rctx->flags = areq->base.flags;
    234	rctx->ctx_handle = nctx->u.ctx_handle;
    235	rctx->src = areq->src;
    236	rctx->dst = areq->dst;
    237	rctx->ctrl_arg = ENCRYPT;
    238	ret = nitrox_set_creq(rctx);
    239	if (ret)
    240		return ret;
    241
    242	/* send the crypto request */
    243	return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback,
    244					 areq);
    245}
    246
    247static int nitrox_aes_gcm_dec(struct aead_request *areq)
    248{
    249	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
    250	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    251	struct nitrox_aead_rctx *rctx = aead_request_ctx(areq);
    252	struct se_crypto_request *creq = &rctx->nkreq.creq;
    253	struct flexi_crypto_context *fctx = nctx->u.fctx;
    254	int ret;
    255
    256	if (!nitrox_aes_gcm_assoclen_supported(areq->assoclen))
    257		return -EINVAL;
    258
    259	memcpy(fctx->crypto.iv, areq->iv, GCM_AES_SALT_SIZE);
    260
    261	rctx->cryptlen = areq->cryptlen - aead->authsize;
    262	rctx->assoclen = areq->assoclen;
    263	rctx->srclen = areq->cryptlen + areq->assoclen;
    264	rctx->dstlen = rctx->srclen - aead->authsize;
    265	rctx->iv = &areq->iv[GCM_AES_SALT_SIZE];
    266	rctx->ivsize = GCM_AES_IV_SIZE - GCM_AES_SALT_SIZE;
    267	rctx->flags = areq->base.flags;
    268	rctx->ctx_handle = nctx->u.ctx_handle;
    269	rctx->src = areq->src;
    270	rctx->dst = areq->dst;
    271	rctx->ctrl_arg = DECRYPT;
    272	ret = nitrox_set_creq(rctx);
    273	if (ret)
    274		return ret;
    275
    276	/* send the crypto request */
    277	return nitrox_process_se_request(nctx->ndev, creq, nitrox_aead_callback,
    278					 areq);
    279}
    280
    281static int nitrox_aead_init(struct crypto_aead *aead)
    282{
    283	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    284	struct crypto_ctx_hdr *chdr;
    285
    286	/* get the first device */
    287	nctx->ndev = nitrox_get_first_device();
    288	if (!nctx->ndev)
    289		return -ENODEV;
    290
    291	/* allocate nitrox crypto context */
    292	chdr = crypto_alloc_context(nctx->ndev);
    293	if (!chdr) {
    294		nitrox_put_device(nctx->ndev);
    295		return -ENOMEM;
    296	}
    297	nctx->chdr = chdr;
    298	nctx->u.ctx_handle = (uintptr_t)((u8 *)chdr->vaddr +
    299					 sizeof(struct ctx_hdr));
    300	nctx->u.fctx->flags.f = 0;
    301
    302	return 0;
    303}
    304
    305static int nitrox_gcm_common_init(struct crypto_aead *aead)
    306{
    307	int ret;
    308	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    309	union fc_ctx_flags *flags;
    310
    311	ret = nitrox_aead_init(aead);
    312	if (ret)
    313		return ret;
    314
    315	flags = &nctx->u.fctx->flags;
    316	flags->w0.cipher_type = CIPHER_AES_GCM;
    317	flags->w0.hash_type = AUTH_NULL;
    318	flags->w0.iv_source = IV_FROM_DPTR;
    319	/* ask microcode to calculate ipad/opad */
    320	flags->w0.auth_input_type = 1;
    321	flags->f = cpu_to_be64(flags->fu);
    322
    323	return 0;
    324}
    325
    326static int nitrox_aes_gcm_init(struct crypto_aead *aead)
    327{
    328	int ret;
    329
    330	ret = nitrox_gcm_common_init(aead);
    331	if (ret)
    332		return ret;
    333
    334	crypto_aead_set_reqsize(aead,
    335				sizeof(struct aead_request) +
    336					sizeof(struct nitrox_aead_rctx));
    337
    338	return 0;
    339}
    340
    341static void nitrox_aead_exit(struct crypto_aead *aead)
    342{
    343	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    344
    345	/* free the nitrox crypto context */
    346	if (nctx->u.ctx_handle) {
    347		struct flexi_crypto_context *fctx = nctx->u.fctx;
    348
    349		memzero_explicit(&fctx->crypto, sizeof(struct crypto_keys));
    350		memzero_explicit(&fctx->auth, sizeof(struct auth_keys));
    351		crypto_free_context((void *)nctx->chdr);
    352	}
    353	nitrox_put_device(nctx->ndev);
    354
    355	nctx->u.ctx_handle = 0;
    356	nctx->ndev = NULL;
    357}
    358
    359static int nitrox_rfc4106_setkey(struct crypto_aead *aead, const u8 *key,
    360				 unsigned int keylen)
    361{
    362	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    363	struct flexi_crypto_context *fctx = nctx->u.fctx;
    364	int ret;
    365
    366	if (keylen < GCM_AES_SALT_SIZE)
    367		return -EINVAL;
    368
    369	keylen -= GCM_AES_SALT_SIZE;
    370	ret = nitrox_aes_gcm_setkey(aead, key, keylen);
    371	if (ret)
    372		return ret;
    373
    374	memcpy(fctx->crypto.iv, key + keylen, GCM_AES_SALT_SIZE);
    375	return 0;
    376}
    377
    378static int nitrox_rfc4106_setauthsize(struct crypto_aead *aead,
    379				      unsigned int authsize)
    380{
    381	switch (authsize) {
    382	case 8:
    383	case 12:
    384	case 16:
    385		break;
    386	default:
    387		return -EINVAL;
    388	}
    389
    390	return nitrox_aead_setauthsize(aead, authsize);
    391}
    392
    393static int nitrox_rfc4106_set_aead_rctx_sglist(struct aead_request *areq)
    394{
    395	struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq);
    396	struct nitrox_aead_rctx *aead_rctx = &rctx->base;
    397	unsigned int assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE;
    398	struct scatterlist *sg;
    399
    400	if (areq->assoclen != 16 && areq->assoclen != 20)
    401		return -EINVAL;
    402
    403	scatterwalk_map_and_copy(rctx->assoc, areq->src, 0, assoclen, 0);
    404	sg_init_table(rctx->src, 3);
    405	sg_set_buf(rctx->src, rctx->assoc, assoclen);
    406	sg = scatterwalk_ffwd(rctx->src + 1, areq->src, areq->assoclen);
    407	if (sg != rctx->src + 1)
    408		sg_chain(rctx->src, 2, sg);
    409
    410	if (areq->src != areq->dst) {
    411		sg_init_table(rctx->dst, 3);
    412		sg_set_buf(rctx->dst, rctx->assoc, assoclen);
    413		sg = scatterwalk_ffwd(rctx->dst + 1, areq->dst, areq->assoclen);
    414		if (sg != rctx->dst + 1)
    415			sg_chain(rctx->dst, 2, sg);
    416	}
    417
    418	aead_rctx->src = rctx->src;
    419	aead_rctx->dst = (areq->src == areq->dst) ? rctx->src : rctx->dst;
    420
    421	return 0;
    422}
    423
    424static void nitrox_rfc4106_callback(void *arg, int err)
    425{
    426	struct aead_request *areq = arg;
    427	struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq);
    428	struct nitrox_kcrypt_request *nkreq = &rctx->base.nkreq;
    429
    430	free_src_sglist(nkreq);
    431	free_dst_sglist(nkreq);
    432	if (err) {
    433		pr_err_ratelimited("request failed status 0x%0x\n", err);
    434		err = -EINVAL;
    435	}
    436
    437	areq->base.complete(&areq->base, err);
    438}
    439
    440static int nitrox_rfc4106_enc(struct aead_request *areq)
    441{
    442	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
    443	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    444	struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq);
    445	struct nitrox_aead_rctx *aead_rctx = &rctx->base;
    446	struct se_crypto_request *creq = &aead_rctx->nkreq.creq;
    447	int ret;
    448
    449	aead_rctx->cryptlen = areq->cryptlen;
    450	aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE;
    451	aead_rctx->srclen = aead_rctx->assoclen + aead_rctx->cryptlen;
    452	aead_rctx->dstlen = aead_rctx->srclen + aead->authsize;
    453	aead_rctx->iv = areq->iv;
    454	aead_rctx->ivsize = GCM_RFC4106_IV_SIZE;
    455	aead_rctx->flags = areq->base.flags;
    456	aead_rctx->ctx_handle = nctx->u.ctx_handle;
    457	aead_rctx->ctrl_arg = ENCRYPT;
    458
    459	ret = nitrox_rfc4106_set_aead_rctx_sglist(areq);
    460	if (ret)
    461		return ret;
    462
    463	ret = nitrox_set_creq(aead_rctx);
    464	if (ret)
    465		return ret;
    466
    467	/* send the crypto request */
    468	return nitrox_process_se_request(nctx->ndev, creq,
    469					 nitrox_rfc4106_callback, areq);
    470}
    471
    472static int nitrox_rfc4106_dec(struct aead_request *areq)
    473{
    474	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
    475	struct nitrox_crypto_ctx *nctx = crypto_aead_ctx(aead);
    476	struct nitrox_rfc4106_rctx *rctx = aead_request_ctx(areq);
    477	struct nitrox_aead_rctx *aead_rctx = &rctx->base;
    478	struct se_crypto_request *creq = &aead_rctx->nkreq.creq;
    479	int ret;
    480
    481	aead_rctx->cryptlen = areq->cryptlen - aead->authsize;
    482	aead_rctx->assoclen = areq->assoclen - GCM_RFC4106_IV_SIZE;
    483	aead_rctx->srclen =
    484		areq->cryptlen - GCM_RFC4106_IV_SIZE + areq->assoclen;
    485	aead_rctx->dstlen = aead_rctx->srclen - aead->authsize;
    486	aead_rctx->iv = areq->iv;
    487	aead_rctx->ivsize = GCM_RFC4106_IV_SIZE;
    488	aead_rctx->flags = areq->base.flags;
    489	aead_rctx->ctx_handle = nctx->u.ctx_handle;
    490	aead_rctx->ctrl_arg = DECRYPT;
    491
    492	ret = nitrox_rfc4106_set_aead_rctx_sglist(areq);
    493	if (ret)
    494		return ret;
    495
    496	ret = nitrox_set_creq(aead_rctx);
    497	if (ret)
    498		return ret;
    499
    500	/* send the crypto request */
    501	return nitrox_process_se_request(nctx->ndev, creq,
    502					 nitrox_rfc4106_callback, areq);
    503}
    504
    505static int nitrox_rfc4106_init(struct crypto_aead *aead)
    506{
    507	int ret;
    508
    509	ret = nitrox_gcm_common_init(aead);
    510	if (ret)
    511		return ret;
    512
    513	crypto_aead_set_reqsize(aead, sizeof(struct aead_request) +
    514				sizeof(struct nitrox_rfc4106_rctx));
    515
    516	return 0;
    517}
    518
    519static struct aead_alg nitrox_aeads[] = { {
    520	.base = {
    521		.cra_name = "gcm(aes)",
    522		.cra_driver_name = "n5_aes_gcm",
    523		.cra_priority = PRIO,
    524		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
    525		.cra_blocksize = 1,
    526		.cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
    527		.cra_alignmask = 0,
    528		.cra_module = THIS_MODULE,
    529	},
    530	.setkey = nitrox_aes_gcm_setkey,
    531	.setauthsize = nitrox_aes_gcm_setauthsize,
    532	.encrypt = nitrox_aes_gcm_enc,
    533	.decrypt = nitrox_aes_gcm_dec,
    534	.init = nitrox_aes_gcm_init,
    535	.exit = nitrox_aead_exit,
    536	.ivsize = GCM_AES_IV_SIZE,
    537	.maxauthsize = AES_BLOCK_SIZE,
    538}, {
    539	.base = {
    540		.cra_name = "rfc4106(gcm(aes))",
    541		.cra_driver_name = "n5_rfc4106",
    542		.cra_priority = PRIO,
    543		.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,
    544		.cra_blocksize = 1,
    545		.cra_ctxsize = sizeof(struct nitrox_crypto_ctx),
    546		.cra_alignmask = 0,
    547		.cra_module = THIS_MODULE,
    548	},
    549	.setkey = nitrox_rfc4106_setkey,
    550	.setauthsize = nitrox_rfc4106_setauthsize,
    551	.encrypt = nitrox_rfc4106_enc,
    552	.decrypt = nitrox_rfc4106_dec,
    553	.init = nitrox_rfc4106_init,
    554	.exit = nitrox_aead_exit,
    555	.ivsize = GCM_RFC4106_IV_SIZE,
    556	.maxauthsize = AES_BLOCK_SIZE,
    557} };
    558
    559int nitrox_register_aeads(void)
    560{
    561	return crypto_register_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads));
    562}
    563
    564void nitrox_unregister_aeads(void)
    565{
    566	crypto_unregister_aeads(nitrox_aeads, ARRAY_SIZE(nitrox_aeads));
    567}