xref: /openbmc/linux/drivers/crypto/nx/nx-aes-xcbc.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
164d85cc9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*10cb823bSAditya Srivastava /*
36148c1adSKent Yoder  * AES XCBC routines supporting the Power 7+ Nest Accelerators driver
46148c1adSKent Yoder  *
56148c1adSKent Yoder  * Copyright (C) 2011-2012 International Business Machines Inc.
66148c1adSKent Yoder  *
76148c1adSKent Yoder  * Author: Kent Yoder <yoder1@us.ibm.com>
86148c1adSKent Yoder  */
96148c1adSKent Yoder 
106148c1adSKent Yoder #include <crypto/internal/hash.h>
116148c1adSKent Yoder #include <crypto/aes.h>
126148c1adSKent Yoder #include <crypto/algapi.h>
136148c1adSKent Yoder #include <linux/module.h>
146148c1adSKent Yoder #include <linux/types.h>
156148c1adSKent Yoder #include <linux/crypto.h>
166148c1adSKent Yoder #include <asm/vio.h>
176148c1adSKent Yoder 
186148c1adSKent Yoder #include "nx_csbcpb.h"
196148c1adSKent Yoder #include "nx.h"
206148c1adSKent Yoder 
216148c1adSKent Yoder 
226148c1adSKent Yoder struct xcbc_state {
236148c1adSKent Yoder 	u8 state[AES_BLOCK_SIZE];
246148c1adSKent Yoder 	unsigned int count;
256148c1adSKent Yoder 	u8 buffer[AES_BLOCK_SIZE];
266148c1adSKent Yoder };
276148c1adSKent Yoder 
nx_xcbc_set_key(struct crypto_shash * desc,const u8 * in_key,unsigned int key_len)286148c1adSKent Yoder static int nx_xcbc_set_key(struct crypto_shash *desc,
296148c1adSKent Yoder 			   const u8            *in_key,
306148c1adSKent Yoder 			   unsigned int         key_len)
316148c1adSKent Yoder {
326148c1adSKent Yoder 	struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc);
33030f4e96SHerbert Xu 	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
346148c1adSKent Yoder 
356148c1adSKent Yoder 	switch (key_len) {
366148c1adSKent Yoder 	case AES_KEYSIZE_128:
376148c1adSKent Yoder 		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
386148c1adSKent Yoder 		break;
396148c1adSKent Yoder 	default:
406148c1adSKent Yoder 		return -EINVAL;
416148c1adSKent Yoder 	}
426148c1adSKent Yoder 
43030f4e96SHerbert Xu 	memcpy(csbcpb->cpb.aes_xcbc.key, in_key, key_len);
446148c1adSKent Yoder 
456148c1adSKent Yoder 	return 0;
466148c1adSKent Yoder }
476148c1adSKent Yoder 
4841e3173dSMarcelo Cerri /*
4941e3173dSMarcelo Cerri  * Based on RFC 3566, for a zero-length message:
5041e3173dSMarcelo Cerri  *
5141e3173dSMarcelo Cerri  * n = 1
5241e3173dSMarcelo Cerri  * K1 = E(K, 0x01010101010101010101010101010101)
5341e3173dSMarcelo Cerri  * K3 = E(K, 0x03030303030303030303030303030303)
5441e3173dSMarcelo Cerri  * E[0] = 0x00000000000000000000000000000000
5541e3173dSMarcelo Cerri  * M[1] = 0x80000000000000000000000000000000 (0 length message with padding)
5641e3173dSMarcelo Cerri  * E[1] = (K1, M[1] ^ E[0] ^ K3)
5741e3173dSMarcelo Cerri  * Tag = M[1]
5841e3173dSMarcelo Cerri  */
nx_xcbc_empty(struct shash_desc * desc,u8 * out)5941e3173dSMarcelo Cerri static int nx_xcbc_empty(struct shash_desc *desc, u8 *out)
6041e3173dSMarcelo Cerri {
6141e3173dSMarcelo Cerri 	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
6241e3173dSMarcelo Cerri 	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
6341e3173dSMarcelo Cerri 	struct nx_sg *in_sg, *out_sg;
6441e3173dSMarcelo Cerri 	u8 keys[2][AES_BLOCK_SIZE];
6541e3173dSMarcelo Cerri 	u8 key[32];
6641e3173dSMarcelo Cerri 	int rc = 0;
675313231aSLeonidas S. Barbosa 	int len;
6841e3173dSMarcelo Cerri 
6941e3173dSMarcelo Cerri 	/* Change to ECB mode */
7041e3173dSMarcelo Cerri 	csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB;
7141e3173dSMarcelo Cerri 	memcpy(key, csbcpb->cpb.aes_xcbc.key, AES_BLOCK_SIZE);
7241e3173dSMarcelo Cerri 	memcpy(csbcpb->cpb.aes_ecb.key, key, AES_BLOCK_SIZE);
7341e3173dSMarcelo Cerri 	NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
7441e3173dSMarcelo Cerri 
7541e3173dSMarcelo Cerri 	/* K1 and K3 base patterns */
7641e3173dSMarcelo Cerri 	memset(keys[0], 0x01, sizeof(keys[0]));
7741e3173dSMarcelo Cerri 	memset(keys[1], 0x03, sizeof(keys[1]));
7841e3173dSMarcelo Cerri 
795313231aSLeonidas S. Barbosa 	len = sizeof(keys);
8041e3173dSMarcelo Cerri 	/* Generate K1 and K3 encrypting the patterns */
815313231aSLeonidas S. Barbosa 	in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) keys, &len,
8241e3173dSMarcelo Cerri 				 nx_ctx->ap->sglen);
835313231aSLeonidas S. Barbosa 
845313231aSLeonidas S. Barbosa 	if (len != sizeof(keys))
855313231aSLeonidas S. Barbosa 		return -EINVAL;
865313231aSLeonidas S. Barbosa 
875313231aSLeonidas S. Barbosa 	out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *) keys, &len,
8841e3173dSMarcelo Cerri 				  nx_ctx->ap->sglen);
895313231aSLeonidas S. Barbosa 
905313231aSLeonidas S. Barbosa 	if (len != sizeof(keys))
915313231aSLeonidas S. Barbosa 		return -EINVAL;
925313231aSLeonidas S. Barbosa 
9341e3173dSMarcelo Cerri 	nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
9441e3173dSMarcelo Cerri 	nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
9541e3173dSMarcelo Cerri 
9675f22228SEric Biggers 	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0);
9741e3173dSMarcelo Cerri 	if (rc)
9841e3173dSMarcelo Cerri 		goto out;
9941e3173dSMarcelo Cerri 	atomic_inc(&(nx_ctx->stats->aes_ops));
10041e3173dSMarcelo Cerri 
10141e3173dSMarcelo Cerri 	/* XOr K3 with the padding for a 0 length message */
10241e3173dSMarcelo Cerri 	keys[1][0] ^= 0x80;
10341e3173dSMarcelo Cerri 
1045313231aSLeonidas S. Barbosa 	len = sizeof(keys[1]);
1055313231aSLeonidas S. Barbosa 
10641e3173dSMarcelo Cerri 	/* Encrypt the final result */
10741e3173dSMarcelo Cerri 	memcpy(csbcpb->cpb.aes_ecb.key, keys[0], AES_BLOCK_SIZE);
1085313231aSLeonidas S. Barbosa 	in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) keys[1], &len,
10941e3173dSMarcelo Cerri 				 nx_ctx->ap->sglen);
1105313231aSLeonidas S. Barbosa 
1115313231aSLeonidas S. Barbosa 	if (len != sizeof(keys[1]))
1125313231aSLeonidas S. Barbosa 		return -EINVAL;
1135313231aSLeonidas S. Barbosa 
1145313231aSLeonidas S. Barbosa 	len = AES_BLOCK_SIZE;
1155313231aSLeonidas S. Barbosa 	out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len,
11641e3173dSMarcelo Cerri 				  nx_ctx->ap->sglen);
1175313231aSLeonidas S. Barbosa 
1185313231aSLeonidas S. Barbosa 	if (len != AES_BLOCK_SIZE)
1195313231aSLeonidas S. Barbosa 		return -EINVAL;
1205313231aSLeonidas S. Barbosa 
12141e3173dSMarcelo Cerri 	nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
12241e3173dSMarcelo Cerri 	nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
12341e3173dSMarcelo Cerri 
12475f22228SEric Biggers 	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0);
12541e3173dSMarcelo Cerri 	if (rc)
12641e3173dSMarcelo Cerri 		goto out;
12741e3173dSMarcelo Cerri 	atomic_inc(&(nx_ctx->stats->aes_ops));
12841e3173dSMarcelo Cerri 
12941e3173dSMarcelo Cerri out:
13041e3173dSMarcelo Cerri 	/* Restore XCBC mode */
13141e3173dSMarcelo Cerri 	csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC;
13241e3173dSMarcelo Cerri 	memcpy(csbcpb->cpb.aes_xcbc.key, key, AES_BLOCK_SIZE);
13341e3173dSMarcelo Cerri 	NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
13441e3173dSMarcelo Cerri 
13541e3173dSMarcelo Cerri 	return rc;
13641e3173dSMarcelo Cerri }
13741e3173dSMarcelo Cerri 
nx_crypto_ctx_aes_xcbc_init2(struct crypto_tfm * tfm)138030f4e96SHerbert Xu static int nx_crypto_ctx_aes_xcbc_init2(struct crypto_tfm *tfm)
1396148c1adSKent Yoder {
140030f4e96SHerbert Xu 	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
1416148c1adSKent Yoder 	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
142030f4e96SHerbert Xu 	int err;
143030f4e96SHerbert Xu 
144030f4e96SHerbert Xu 	err = nx_crypto_ctx_aes_xcbc_init(tfm);
145030f4e96SHerbert Xu 	if (err)
146030f4e96SHerbert Xu 		return err;
1476148c1adSKent Yoder 
1486148c1adSKent Yoder 	nx_ctx_init(nx_ctx, HCOP_FC_AES);
1496148c1adSKent Yoder 
1506148c1adSKent Yoder 	NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
1516148c1adSKent Yoder 	csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC;
1526148c1adSKent Yoder 
153030f4e96SHerbert Xu 	return 0;
154030f4e96SHerbert Xu }
1556148c1adSKent Yoder 
nx_xcbc_init(struct shash_desc * desc)156030f4e96SHerbert Xu static int nx_xcbc_init(struct shash_desc *desc)
157030f4e96SHerbert Xu {
158030f4e96SHerbert Xu 	struct xcbc_state *sctx = shash_desc_ctx(desc);
1595313231aSLeonidas S. Barbosa 
160030f4e96SHerbert Xu 	memset(sctx, 0, sizeof *sctx);
1616148c1adSKent Yoder 
1626148c1adSKent Yoder 	return 0;
1636148c1adSKent Yoder }
1646148c1adSKent Yoder 
nx_xcbc_update(struct shash_desc * desc,const u8 * data,unsigned int len)1656148c1adSKent Yoder static int nx_xcbc_update(struct shash_desc *desc,
1666148c1adSKent Yoder 			  const u8          *data,
1676148c1adSKent Yoder 			  unsigned int       len)
1686148c1adSKent Yoder {
1696148c1adSKent Yoder 	struct xcbc_state *sctx = shash_desc_ctx(desc);
1706148c1adSKent Yoder 	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
1716148c1adSKent Yoder 	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
1726148c1adSKent Yoder 	struct nx_sg *in_sg;
173030f4e96SHerbert Xu 	struct nx_sg *out_sg;
1745313231aSLeonidas S. Barbosa 	u32 to_process = 0, leftover, total;
1755313231aSLeonidas S. Barbosa 	unsigned int max_sg_len;
176c849163bSMarcelo Cerri 	unsigned long irq_flags;
1776148c1adSKent Yoder 	int rc = 0;
1785313231aSLeonidas S. Barbosa 	int data_len;
1796148c1adSKent Yoder 
180c849163bSMarcelo Cerri 	spin_lock_irqsave(&nx_ctx->lock, irq_flags);
181c849163bSMarcelo Cerri 
1829d6f1a82SFionnuala Gunter 
1839d6f1a82SFionnuala Gunter 	total = sctx->count + len;
1846148c1adSKent Yoder 
1856148c1adSKent Yoder 	/* 2 cases for total data len:
1866148c1adSKent Yoder 	 *  1: <= AES_BLOCK_SIZE: copy into state, return 0
1876148c1adSKent Yoder 	 *  2: > AES_BLOCK_SIZE: process X blocks, copy in leftover
1886148c1adSKent Yoder 	 */
1899d6f1a82SFionnuala Gunter 	if (total <= AES_BLOCK_SIZE) {
1906148c1adSKent Yoder 		memcpy(sctx->buffer + sctx->count, data, len);
1916148c1adSKent Yoder 		sctx->count += len;
1926148c1adSKent Yoder 		goto out;
1936148c1adSKent Yoder 	}
1946148c1adSKent Yoder 
1959d6f1a82SFionnuala Gunter 	in_sg = nx_ctx->in_sg;
1965313231aSLeonidas S. Barbosa 	max_sg_len = min_t(u64, nx_driver.of.max_sg_len/sizeof(struct nx_sg),
1979d6f1a82SFionnuala Gunter 				nx_ctx->ap->sglen);
1985313231aSLeonidas S. Barbosa 	max_sg_len = min_t(u64, max_sg_len,
1995313231aSLeonidas S. Barbosa 				nx_ctx->ap->databytelen/NX_PAGE_SIZE);
2009d6f1a82SFionnuala Gunter 
201030f4e96SHerbert Xu 	data_len = AES_BLOCK_SIZE;
202030f4e96SHerbert Xu 	out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
203030f4e96SHerbert Xu 				  &len, nx_ctx->ap->sglen);
204030f4e96SHerbert Xu 
205030f4e96SHerbert Xu 	if (data_len != AES_BLOCK_SIZE) {
206030f4e96SHerbert Xu 		rc = -EINVAL;
207030f4e96SHerbert Xu 		goto out;
208030f4e96SHerbert Xu 	}
209030f4e96SHerbert Xu 
210030f4e96SHerbert Xu 	nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
211030f4e96SHerbert Xu 
2129d6f1a82SFionnuala Gunter 	do {
2135313231aSLeonidas S. Barbosa 		to_process = total - to_process;
2149d6f1a82SFionnuala Gunter 		to_process = to_process & ~(AES_BLOCK_SIZE - 1);
2155313231aSLeonidas S. Barbosa 
2169d6f1a82SFionnuala Gunter 		leftover = total - to_process;
2176148c1adSKent Yoder 
2189d6f1a82SFionnuala Gunter 		/* the hardware will not accept a 0 byte operation for this
2199d6f1a82SFionnuala Gunter 		 * algorithm and the operation MUST be finalized to be correct.
2209d6f1a82SFionnuala Gunter 		 * So if we happen to get an update that falls on a block sized
2219d6f1a82SFionnuala Gunter 		 * boundary, we must save off the last block to finalize with
2229d6f1a82SFionnuala Gunter 		 * later. */
2236148c1adSKent Yoder 		if (!leftover) {
2246148c1adSKent Yoder 			to_process -= AES_BLOCK_SIZE;
2256148c1adSKent Yoder 			leftover = AES_BLOCK_SIZE;
2266148c1adSKent Yoder 		}
2276148c1adSKent Yoder 
2286148c1adSKent Yoder 		if (sctx->count) {
2295313231aSLeonidas S. Barbosa 			data_len = sctx->count;
2309d6f1a82SFionnuala Gunter 			in_sg = nx_build_sg_list(nx_ctx->in_sg,
2319d6f1a82SFionnuala Gunter 						(u8 *) sctx->buffer,
2325313231aSLeonidas S. Barbosa 						&data_len,
2339d6f1a82SFionnuala Gunter 						max_sg_len);
234030f4e96SHerbert Xu 			if (data_len != sctx->count) {
235030f4e96SHerbert Xu 				rc = -EINVAL;
236030f4e96SHerbert Xu 				goto out;
237030f4e96SHerbert Xu 			}
2389d6f1a82SFionnuala Gunter 		}
2395313231aSLeonidas S. Barbosa 
2405313231aSLeonidas S. Barbosa 		data_len = to_process - sctx->count;
2419d6f1a82SFionnuala Gunter 		in_sg = nx_build_sg_list(in_sg,
2429d6f1a82SFionnuala Gunter 					(u8 *) data,
2435313231aSLeonidas S. Barbosa 					&data_len,
2449d6f1a82SFionnuala Gunter 					max_sg_len);
2455313231aSLeonidas S. Barbosa 
246030f4e96SHerbert Xu 		if (data_len != to_process - sctx->count) {
247030f4e96SHerbert Xu 			rc = -EINVAL;
248030f4e96SHerbert Xu 			goto out;
249030f4e96SHerbert Xu 		}
2505313231aSLeonidas S. Barbosa 
2516148c1adSKent Yoder 		nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
2526148c1adSKent Yoder 					sizeof(struct nx_sg);
2539d6f1a82SFionnuala Gunter 
2549d6f1a82SFionnuala Gunter 		/* we've hit the nx chip previously and we're updating again,
2559d6f1a82SFionnuala Gunter 		 * so copy over the partial digest */
2569d6f1a82SFionnuala Gunter 		if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
2579d6f1a82SFionnuala Gunter 			memcpy(csbcpb->cpb.aes_xcbc.cv,
2589d6f1a82SFionnuala Gunter 				csbcpb->cpb.aes_xcbc.out_cv_mac,
2599d6f1a82SFionnuala Gunter 				AES_BLOCK_SIZE);
2606148c1adSKent Yoder 		}
2616148c1adSKent Yoder 
2626148c1adSKent Yoder 		NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
2636148c1adSKent Yoder 		if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
2646148c1adSKent Yoder 			rc = -EINVAL;
2656148c1adSKent Yoder 			goto out;
2666148c1adSKent Yoder 		}
2676148c1adSKent Yoder 
26875f22228SEric Biggers 		rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0);
2696148c1adSKent Yoder 		if (rc)
2706148c1adSKent Yoder 			goto out;
2716148c1adSKent Yoder 
2726148c1adSKent Yoder 		atomic_inc(&(nx_ctx->stats->aes_ops));
2736148c1adSKent Yoder 
2746148c1adSKent Yoder 		/* everything after the first update is continuation */
2756148c1adSKent Yoder 		NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
2769d6f1a82SFionnuala Gunter 
2779d6f1a82SFionnuala Gunter 		total -= to_process;
2789d6f1a82SFionnuala Gunter 		data += to_process - sctx->count;
2799d6f1a82SFionnuala Gunter 		sctx->count = 0;
2809d6f1a82SFionnuala Gunter 		in_sg = nx_ctx->in_sg;
2819d6f1a82SFionnuala Gunter 	} while (leftover > AES_BLOCK_SIZE);
2829d6f1a82SFionnuala Gunter 
2839d6f1a82SFionnuala Gunter 	/* copy the leftover back into the state struct */
2849d6f1a82SFionnuala Gunter 	memcpy(sctx->buffer, data, leftover);
2859d6f1a82SFionnuala Gunter 	sctx->count = leftover;
2869d6f1a82SFionnuala Gunter 
2876148c1adSKent Yoder out:
288c849163bSMarcelo Cerri 	spin_unlock_irqrestore(&nx_ctx->lock, irq_flags);
2896148c1adSKent Yoder 	return rc;
2906148c1adSKent Yoder }
2916148c1adSKent Yoder 
nx_xcbc_final(struct shash_desc * desc,u8 * out)2926148c1adSKent Yoder static int nx_xcbc_final(struct shash_desc *desc, u8 *out)
2936148c1adSKent Yoder {
2946148c1adSKent Yoder 	struct xcbc_state *sctx = shash_desc_ctx(desc);
2956148c1adSKent Yoder 	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
2966148c1adSKent Yoder 	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
2976148c1adSKent Yoder 	struct nx_sg *in_sg, *out_sg;
298c849163bSMarcelo Cerri 	unsigned long irq_flags;
2996148c1adSKent Yoder 	int rc = 0;
3005313231aSLeonidas S. Barbosa 	int len;
3016148c1adSKent Yoder 
302c849163bSMarcelo Cerri 	spin_lock_irqsave(&nx_ctx->lock, irq_flags);
303c849163bSMarcelo Cerri 
3046148c1adSKent Yoder 	if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
3056148c1adSKent Yoder 		/* we've hit the nx chip previously, now we're finalizing,
3066148c1adSKent Yoder 		 * so copy over the partial digest */
3076148c1adSKent Yoder 		memcpy(csbcpb->cpb.aes_xcbc.cv,
3086148c1adSKent Yoder 		       csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
3096148c1adSKent Yoder 	} else if (sctx->count == 0) {
31041e3173dSMarcelo Cerri 		/*
31141e3173dSMarcelo Cerri 		 * we've never seen an update, so this is a 0 byte op. The
31241e3173dSMarcelo Cerri 		 * hardware cannot handle a 0 byte op, so just ECB to
31341e3173dSMarcelo Cerri 		 * generate the hash.
31441e3173dSMarcelo Cerri 		 */
31541e3173dSMarcelo Cerri 		rc = nx_xcbc_empty(desc, out);
3166148c1adSKent Yoder 		goto out;
3176148c1adSKent Yoder 	}
3186148c1adSKent Yoder 
3196148c1adSKent Yoder 	/* final is represented by continuing the operation and indicating that
3206148c1adSKent Yoder 	 * this is not an intermediate operation */
3216148c1adSKent Yoder 	NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
3226148c1adSKent Yoder 
3235313231aSLeonidas S. Barbosa 	len = sctx->count;
3246148c1adSKent Yoder 	in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer,
3255313231aSLeonidas S. Barbosa 				 &len, nx_ctx->ap->sglen);
3265313231aSLeonidas S. Barbosa 
327030f4e96SHerbert Xu 	if (len != sctx->count) {
328030f4e96SHerbert Xu 		rc = -EINVAL;
329030f4e96SHerbert Xu 		goto out;
330030f4e96SHerbert Xu 	}
3315313231aSLeonidas S. Barbosa 
3325313231aSLeonidas S. Barbosa 	len = AES_BLOCK_SIZE;
3335313231aSLeonidas S. Barbosa 	out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len,
3346148c1adSKent Yoder 				  nx_ctx->ap->sglen);
3356148c1adSKent Yoder 
336030f4e96SHerbert Xu 	if (len != AES_BLOCK_SIZE) {
337030f4e96SHerbert Xu 		rc = -EINVAL;
338030f4e96SHerbert Xu 		goto out;
339030f4e96SHerbert Xu 	}
3405313231aSLeonidas S. Barbosa 
3416148c1adSKent Yoder 	nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
3426148c1adSKent Yoder 	nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
3436148c1adSKent Yoder 
3446148c1adSKent Yoder 	if (!nx_ctx->op.outlen) {
3456148c1adSKent Yoder 		rc = -EINVAL;
3466148c1adSKent Yoder 		goto out;
3476148c1adSKent Yoder 	}
3486148c1adSKent Yoder 
34975f22228SEric Biggers 	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0);
3506148c1adSKent Yoder 	if (rc)
3516148c1adSKent Yoder 		goto out;
3526148c1adSKent Yoder 
3536148c1adSKent Yoder 	atomic_inc(&(nx_ctx->stats->aes_ops));
3546148c1adSKent Yoder 
3556148c1adSKent Yoder 	memcpy(out, csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
3566148c1adSKent Yoder out:
357c849163bSMarcelo Cerri 	spin_unlock_irqrestore(&nx_ctx->lock, irq_flags);
3586148c1adSKent Yoder 	return rc;
3596148c1adSKent Yoder }
3606148c1adSKent Yoder 
3616148c1adSKent Yoder struct shash_alg nx_shash_aes_xcbc_alg = {
3626148c1adSKent Yoder 	.digestsize = AES_BLOCK_SIZE,
3636148c1adSKent Yoder 	.init       = nx_xcbc_init,
3646148c1adSKent Yoder 	.update     = nx_xcbc_update,
3656148c1adSKent Yoder 	.final      = nx_xcbc_final,
3666148c1adSKent Yoder 	.setkey     = nx_xcbc_set_key,
3676148c1adSKent Yoder 	.descsize   = sizeof(struct xcbc_state),
3686148c1adSKent Yoder 	.statesize  = sizeof(struct xcbc_state),
3696148c1adSKent Yoder 	.base       = {
3706148c1adSKent Yoder 		.cra_name        = "xcbc(aes)",
3716148c1adSKent Yoder 		.cra_driver_name = "xcbc-aes-nx",
3726148c1adSKent Yoder 		.cra_priority    = 300,
3736148c1adSKent Yoder 		.cra_blocksize   = AES_BLOCK_SIZE,
3746148c1adSKent Yoder 		.cra_module      = THIS_MODULE,
3756148c1adSKent Yoder 		.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
376030f4e96SHerbert Xu 		.cra_init        = nx_crypto_ctx_aes_xcbc_init2,
3776148c1adSKent Yoder 		.cra_exit        = nx_crypto_ctx_exit,
3786148c1adSKent Yoder 	}
3796148c1adSKent Yoder };
380