xref: /linux/drivers/crypto/bcm/spu.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1cb849fc5SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29d12ba86SRob Rice /*
39d12ba86SRob Rice  * Copyright 2016 Broadcom
49d12ba86SRob Rice  */
59d12ba86SRob Rice 
69d12ba86SRob Rice #include <linux/kernel.h>
79d12ba86SRob Rice #include <linux/string.h>
89d12ba86SRob Rice 
99d12ba86SRob Rice #include "util.h"
109d12ba86SRob Rice #include "spu.h"
119d12ba86SRob Rice #include "spum.h"
129d12ba86SRob Rice #include "cipher.h"
139d12ba86SRob Rice 
149d12ba86SRob Rice char *hash_alg_name[] = { "None", "md5", "sha1", "sha224", "sha256", "aes",
159d12ba86SRob Rice 	"sha384", "sha512", "sha3_224", "sha3_256", "sha3_384", "sha3_512" };
169d12ba86SRob Rice 
179d12ba86SRob Rice char *aead_alg_name[] = { "ccm(aes)", "gcm(aes)", "authenc" };
189d12ba86SRob Rice 
199d12ba86SRob Rice /* Assumes SPU-M messages are in big endian */
spum_dump_msg_hdr(u8 * buf,unsigned int buf_len)209d12ba86SRob Rice void spum_dump_msg_hdr(u8 *buf, unsigned int buf_len)
219d12ba86SRob Rice {
229d12ba86SRob Rice 	u8 *ptr = buf;
239d12ba86SRob Rice 	struct SPUHEADER *spuh = (struct SPUHEADER *)buf;
249d12ba86SRob Rice 	unsigned int hash_key_len = 0;
259d12ba86SRob Rice 	unsigned int hash_state_len = 0;
269d12ba86SRob Rice 	unsigned int cipher_key_len = 0;
279d12ba86SRob Rice 	unsigned int iv_len;
289d12ba86SRob Rice 	u32 pflags;
299d12ba86SRob Rice 	u32 cflags;
309d12ba86SRob Rice 	u32 ecf;
319d12ba86SRob Rice 	u32 cipher_alg;
329d12ba86SRob Rice 	u32 cipher_mode;
339d12ba86SRob Rice 	u32 cipher_type;
349d12ba86SRob Rice 	u32 hash_alg;
359d12ba86SRob Rice 	u32 hash_mode;
369d12ba86SRob Rice 	u32 hash_type;
379d12ba86SRob Rice 	u32 sctx_size;   /* SCTX length in words */
389d12ba86SRob Rice 	u32 sctx_pl_len; /* SCTX payload length in bytes */
399d12ba86SRob Rice 
409d12ba86SRob Rice 	packet_log("\n");
419d12ba86SRob Rice 	packet_log("SPU Message header %p len: %u\n", buf, buf_len);
429d12ba86SRob Rice 
439d12ba86SRob Rice 	/* ========== Decode MH ========== */
445a17eae4SHerbert Xu 	packet_log("  MH 0x%08x\n", be32_to_cpup((__be32 *)ptr));
459d12ba86SRob Rice 	if (spuh->mh.flags & MH_SCTX_PRES)
469d12ba86SRob Rice 		packet_log("    SCTX  present\n");
479d12ba86SRob Rice 	if (spuh->mh.flags & MH_BDESC_PRES)
489d12ba86SRob Rice 		packet_log("    BDESC present\n");
499d12ba86SRob Rice 	if (spuh->mh.flags & MH_MFM_PRES)
509d12ba86SRob Rice 		packet_log("    MFM   present\n");
519d12ba86SRob Rice 	if (spuh->mh.flags & MH_BD_PRES)
529d12ba86SRob Rice 		packet_log("    BD    present\n");
539d12ba86SRob Rice 	if (spuh->mh.flags & MH_HASH_PRES)
549d12ba86SRob Rice 		packet_log("    HASH  present\n");
559d12ba86SRob Rice 	if (spuh->mh.flags & MH_SUPDT_PRES)
569d12ba86SRob Rice 		packet_log("    SUPDT present\n");
579d12ba86SRob Rice 	packet_log("    Opcode 0x%02x\n", spuh->mh.op_code);
589d12ba86SRob Rice 
599d12ba86SRob Rice 	ptr += sizeof(spuh->mh) + sizeof(spuh->emh);  /* skip emh. unused */
609d12ba86SRob Rice 
619d12ba86SRob Rice 	/* ========== Decode SCTX ========== */
629d12ba86SRob Rice 	if (spuh->mh.flags & MH_SCTX_PRES) {
639d12ba86SRob Rice 		pflags = be32_to_cpu(spuh->sa.proto_flags);
649d12ba86SRob Rice 		packet_log("  SCTX[0] 0x%08x\n", pflags);
659d12ba86SRob Rice 		sctx_size = pflags & SCTX_SIZE;
669d12ba86SRob Rice 		packet_log("    Size %u words\n", sctx_size);
679d12ba86SRob Rice 
689d12ba86SRob Rice 		cflags = be32_to_cpu(spuh->sa.cipher_flags);
699d12ba86SRob Rice 		packet_log("  SCTX[1] 0x%08x\n", cflags);
709d12ba86SRob Rice 		packet_log("    Inbound:%lu (1:decrypt/vrfy 0:encrypt/auth)\n",
719d12ba86SRob Rice 			   (cflags & CIPHER_INBOUND) >> CIPHER_INBOUND_SHIFT);
729d12ba86SRob Rice 		packet_log("    Order:%lu (1:AuthFirst 0:EncFirst)\n",
739d12ba86SRob Rice 			   (cflags & CIPHER_ORDER) >> CIPHER_ORDER_SHIFT);
749d12ba86SRob Rice 		packet_log("    ICV_IS_512:%lx\n",
759d12ba86SRob Rice 			   (cflags & ICV_IS_512) >> ICV_IS_512_SHIFT);
769d12ba86SRob Rice 		cipher_alg = (cflags & CIPHER_ALG) >> CIPHER_ALG_SHIFT;
779d12ba86SRob Rice 		cipher_mode = (cflags & CIPHER_MODE) >> CIPHER_MODE_SHIFT;
789d12ba86SRob Rice 		cipher_type = (cflags & CIPHER_TYPE) >> CIPHER_TYPE_SHIFT;
799d12ba86SRob Rice 		packet_log("    Crypto Alg:%u Mode:%u Type:%u\n",
809d12ba86SRob Rice 			   cipher_alg, cipher_mode, cipher_type);
819d12ba86SRob Rice 		hash_alg = (cflags & HASH_ALG) >> HASH_ALG_SHIFT;
829d12ba86SRob Rice 		hash_mode = (cflags & HASH_MODE) >> HASH_MODE_SHIFT;
839d12ba86SRob Rice 		hash_type = (cflags & HASH_TYPE) >> HASH_TYPE_SHIFT;
849d12ba86SRob Rice 		packet_log("    Hash   Alg:%x Mode:%x Type:%x\n",
859d12ba86SRob Rice 			   hash_alg, hash_mode, hash_type);
869d12ba86SRob Rice 		packet_log("    UPDT_Offset:%u\n", cflags & UPDT_OFST);
879d12ba86SRob Rice 
889d12ba86SRob Rice 		ecf = be32_to_cpu(spuh->sa.ecf);
899d12ba86SRob Rice 		packet_log("  SCTX[2] 0x%08x\n", ecf);
909d12ba86SRob Rice 		packet_log("    WriteICV:%lu CheckICV:%lu ICV_SIZE:%u ",
919d12ba86SRob Rice 			   (ecf & INSERT_ICV) >> INSERT_ICV_SHIFT,
929d12ba86SRob Rice 			   (ecf & CHECK_ICV) >> CHECK_ICV_SHIFT,
939d12ba86SRob Rice 			   (ecf & ICV_SIZE) >> ICV_SIZE_SHIFT);
949d12ba86SRob Rice 		packet_log("BD_SUPPRESS:%lu\n",
959d12ba86SRob Rice 			   (ecf & BD_SUPPRESS) >> BD_SUPPRESS_SHIFT);
969d12ba86SRob Rice 		packet_log("    SCTX_IV:%lu ExplicitIV:%lu GenIV:%lu ",
979d12ba86SRob Rice 			   (ecf & SCTX_IV) >> SCTX_IV_SHIFT,
989d12ba86SRob Rice 			   (ecf & EXPLICIT_IV) >> EXPLICIT_IV_SHIFT,
999d12ba86SRob Rice 			   (ecf & GEN_IV) >> GEN_IV_SHIFT);
1009d12ba86SRob Rice 		packet_log("IV_OV_OFST:%lu EXP_IV_SIZE:%u\n",
1019d12ba86SRob Rice 			   (ecf & IV_OFFSET) >> IV_OFFSET_SHIFT,
1029d12ba86SRob Rice 			   ecf & EXP_IV_SIZE);
1039d12ba86SRob Rice 
1049d12ba86SRob Rice 		ptr += sizeof(struct SCTX);
1059d12ba86SRob Rice 
1069d12ba86SRob Rice 		if (hash_alg && hash_mode) {
1079d12ba86SRob Rice 			char *name = "NONE";
1089d12ba86SRob Rice 
1099d12ba86SRob Rice 			switch (hash_alg) {
1109d12ba86SRob Rice 			case HASH_ALG_MD5:
1119d12ba86SRob Rice 				hash_key_len = 16;
1129d12ba86SRob Rice 				name = "MD5";
1139d12ba86SRob Rice 				break;
1149d12ba86SRob Rice 			case HASH_ALG_SHA1:
1159d12ba86SRob Rice 				hash_key_len = 20;
1169d12ba86SRob Rice 				name = "SHA1";
1179d12ba86SRob Rice 				break;
1189d12ba86SRob Rice 			case HASH_ALG_SHA224:
1199d12ba86SRob Rice 				hash_key_len = 28;
1209d12ba86SRob Rice 				name = "SHA224";
1219d12ba86SRob Rice 				break;
1229d12ba86SRob Rice 			case HASH_ALG_SHA256:
1239d12ba86SRob Rice 				hash_key_len = 32;
1249d12ba86SRob Rice 				name = "SHA256";
1259d12ba86SRob Rice 				break;
1269d12ba86SRob Rice 			case HASH_ALG_SHA384:
1279d12ba86SRob Rice 				hash_key_len = 48;
1289d12ba86SRob Rice 				name = "SHA384";
1299d12ba86SRob Rice 				break;
1309d12ba86SRob Rice 			case HASH_ALG_SHA512:
1319d12ba86SRob Rice 				hash_key_len = 64;
1329d12ba86SRob Rice 				name = "SHA512";
1339d12ba86SRob Rice 				break;
1349d12ba86SRob Rice 			case HASH_ALG_AES:
1359d12ba86SRob Rice 				hash_key_len = 0;
1369d12ba86SRob Rice 				name = "AES";
1379d12ba86SRob Rice 				break;
1389d12ba86SRob Rice 			case HASH_ALG_NONE:
1399d12ba86SRob Rice 				break;
1409d12ba86SRob Rice 			}
1419d12ba86SRob Rice 
1429d12ba86SRob Rice 			packet_log("    Auth Key Type:%s Length:%u Bytes\n",
1439d12ba86SRob Rice 				   name, hash_key_len);
1449d12ba86SRob Rice 			packet_dump("    KEY: ", ptr, hash_key_len);
1459d12ba86SRob Rice 			ptr += hash_key_len;
1469d12ba86SRob Rice 		} else if ((hash_alg == HASH_ALG_AES) &&
1479d12ba86SRob Rice 			   (hash_mode == HASH_MODE_XCBC)) {
1489d12ba86SRob Rice 			char *name = "NONE";
1499d12ba86SRob Rice 
1509d12ba86SRob Rice 			switch (cipher_type) {
1519d12ba86SRob Rice 			case CIPHER_TYPE_AES128:
1529d12ba86SRob Rice 				hash_key_len = 16;
1539d12ba86SRob Rice 				name = "AES128-XCBC";
1549d12ba86SRob Rice 				break;
1559d12ba86SRob Rice 			case CIPHER_TYPE_AES192:
1569d12ba86SRob Rice 				hash_key_len = 24;
1579d12ba86SRob Rice 				name = "AES192-XCBC";
1589d12ba86SRob Rice 				break;
1599d12ba86SRob Rice 			case CIPHER_TYPE_AES256:
1609d12ba86SRob Rice 				hash_key_len = 32;
1619d12ba86SRob Rice 				name = "AES256-XCBC";
1629d12ba86SRob Rice 				break;
1639d12ba86SRob Rice 			}
1649d12ba86SRob Rice 			packet_log("    Auth Key Type:%s Length:%u Bytes\n",
1659d12ba86SRob Rice 				   name, hash_key_len);
1669d12ba86SRob Rice 			packet_dump("    KEY: ", ptr, hash_key_len);
1679d12ba86SRob Rice 			ptr += hash_key_len;
1689d12ba86SRob Rice 		}
1699d12ba86SRob Rice 
1709d12ba86SRob Rice 		if (hash_alg && (hash_mode == HASH_MODE_NONE) &&
1719d12ba86SRob Rice 		    (hash_type == HASH_TYPE_UPDT)) {
1729d12ba86SRob Rice 			char *name = "NONE";
1739d12ba86SRob Rice 
1749d12ba86SRob Rice 			switch (hash_alg) {
1759d12ba86SRob Rice 			case HASH_ALG_MD5:
1769d12ba86SRob Rice 				hash_state_len = 16;
1779d12ba86SRob Rice 				name = "MD5";
1789d12ba86SRob Rice 				break;
1799d12ba86SRob Rice 			case HASH_ALG_SHA1:
1809d12ba86SRob Rice 				hash_state_len = 20;
1819d12ba86SRob Rice 				name = "SHA1";
1829d12ba86SRob Rice 				break;
1839d12ba86SRob Rice 			case HASH_ALG_SHA224:
1849d12ba86SRob Rice 				hash_state_len = 32;
1859d12ba86SRob Rice 				name = "SHA224";
1869d12ba86SRob Rice 				break;
1879d12ba86SRob Rice 			case HASH_ALG_SHA256:
1889d12ba86SRob Rice 				hash_state_len = 32;
1899d12ba86SRob Rice 				name = "SHA256";
1909d12ba86SRob Rice 				break;
1919d12ba86SRob Rice 			case HASH_ALG_SHA384:
1929d12ba86SRob Rice 				hash_state_len = 48;
1939d12ba86SRob Rice 				name = "SHA384";
1949d12ba86SRob Rice 				break;
1959d12ba86SRob Rice 			case HASH_ALG_SHA512:
1969d12ba86SRob Rice 				hash_state_len = 64;
1979d12ba86SRob Rice 				name = "SHA512";
1989d12ba86SRob Rice 				break;
1999d12ba86SRob Rice 			case HASH_ALG_AES:
2009d12ba86SRob Rice 				hash_state_len = 0;
2019d12ba86SRob Rice 				name = "AES";
2029d12ba86SRob Rice 				break;
2039d12ba86SRob Rice 			case HASH_ALG_NONE:
2049d12ba86SRob Rice 				break;
2059d12ba86SRob Rice 			}
2069d12ba86SRob Rice 
2079d12ba86SRob Rice 			packet_log("    Auth State Type:%s Length:%u Bytes\n",
2089d12ba86SRob Rice 				   name, hash_state_len);
2099d12ba86SRob Rice 			packet_dump("    State: ", ptr, hash_state_len);
2109d12ba86SRob Rice 			ptr += hash_state_len;
2119d12ba86SRob Rice 		}
2129d12ba86SRob Rice 
2139d12ba86SRob Rice 		if (cipher_alg) {
2149d12ba86SRob Rice 			char *name = "NONE";
2159d12ba86SRob Rice 
2169d12ba86SRob Rice 			switch (cipher_alg) {
2179d12ba86SRob Rice 			case CIPHER_ALG_DES:
2189d12ba86SRob Rice 				cipher_key_len = 8;
2199d12ba86SRob Rice 				name = "DES";
2209d12ba86SRob Rice 				break;
2219d12ba86SRob Rice 			case CIPHER_ALG_3DES:
2229d12ba86SRob Rice 				cipher_key_len = 24;
2239d12ba86SRob Rice 				name = "3DES";
2249d12ba86SRob Rice 				break;
2259d12ba86SRob Rice 			case CIPHER_ALG_AES:
2269d12ba86SRob Rice 				switch (cipher_type) {
2279d12ba86SRob Rice 				case CIPHER_TYPE_AES128:
2289d12ba86SRob Rice 					cipher_key_len = 16;
2299d12ba86SRob Rice 					name = "AES128";
2309d12ba86SRob Rice 					break;
2319d12ba86SRob Rice 				case CIPHER_TYPE_AES192:
2329d12ba86SRob Rice 					cipher_key_len = 24;
2339d12ba86SRob Rice 					name = "AES192";
2349d12ba86SRob Rice 					break;
2359d12ba86SRob Rice 				case CIPHER_TYPE_AES256:
2369d12ba86SRob Rice 					cipher_key_len = 32;
2379d12ba86SRob Rice 					name = "AES256";
2389d12ba86SRob Rice 					break;
2399d12ba86SRob Rice 				}
2409d12ba86SRob Rice 				break;
2419d12ba86SRob Rice 			case CIPHER_ALG_NONE:
2429d12ba86SRob Rice 				break;
2439d12ba86SRob Rice 			}
2449d12ba86SRob Rice 
2459d12ba86SRob Rice 			packet_log("    Cipher Key Type:%s Length:%u Bytes\n",
2469d12ba86SRob Rice 				   name, cipher_key_len);
2479d12ba86SRob Rice 
2489d12ba86SRob Rice 			/* XTS has two keys */
2499d12ba86SRob Rice 			if (cipher_mode == CIPHER_MODE_XTS) {
2509d12ba86SRob Rice 				packet_dump("    KEY2: ", ptr, cipher_key_len);
2519d12ba86SRob Rice 				ptr += cipher_key_len;
2529d12ba86SRob Rice 				packet_dump("    KEY1: ", ptr, cipher_key_len);
2539d12ba86SRob Rice 				ptr += cipher_key_len;
2549d12ba86SRob Rice 
2559d12ba86SRob Rice 				cipher_key_len *= 2;
2569d12ba86SRob Rice 			} else {
2579d12ba86SRob Rice 				packet_dump("    KEY: ", ptr, cipher_key_len);
2589d12ba86SRob Rice 				ptr += cipher_key_len;
2599d12ba86SRob Rice 			}
2609d12ba86SRob Rice 
2619d12ba86SRob Rice 			if (ecf & SCTX_IV) {
2629d12ba86SRob Rice 				sctx_pl_len = sctx_size * sizeof(u32) -
2639d12ba86SRob Rice 					sizeof(struct SCTX);
2649d12ba86SRob Rice 				iv_len = sctx_pl_len -
2659d12ba86SRob Rice 					(hash_key_len + hash_state_len +
2669d12ba86SRob Rice 					 cipher_key_len);
2679d12ba86SRob Rice 				packet_log("    IV Length:%u Bytes\n", iv_len);
2689d12ba86SRob Rice 				packet_dump("    IV: ", ptr, iv_len);
2699d12ba86SRob Rice 				ptr += iv_len;
2709d12ba86SRob Rice 			}
2719d12ba86SRob Rice 		}
2729d12ba86SRob Rice 	}
2739d12ba86SRob Rice 
2749d12ba86SRob Rice 	/* ========== Decode BDESC ========== */
2759d12ba86SRob Rice 	if (spuh->mh.flags & MH_BDESC_PRES) {
2769d12ba86SRob Rice 		struct BDESC_HEADER *bdesc = (struct BDESC_HEADER *)ptr;
2775a17eae4SHerbert Xu 
2785a17eae4SHerbert Xu 		packet_log("  BDESC[0] 0x%08x\n", be32_to_cpup((__be32 *)ptr));
2799d12ba86SRob Rice 		packet_log("    OffsetMAC:%u LengthMAC:%u\n",
2809d12ba86SRob Rice 			   be16_to_cpu(bdesc->offset_mac),
2819d12ba86SRob Rice 			   be16_to_cpu(bdesc->length_mac));
2829d12ba86SRob Rice 		ptr += sizeof(u32);
2839d12ba86SRob Rice 
2845a17eae4SHerbert Xu 		packet_log("  BDESC[1] 0x%08x\n", be32_to_cpup((__be32 *)ptr));
2859d12ba86SRob Rice 		packet_log("    OffsetCrypto:%u LengthCrypto:%u\n",
2869d12ba86SRob Rice 			   be16_to_cpu(bdesc->offset_crypto),
2879d12ba86SRob Rice 			   be16_to_cpu(bdesc->length_crypto));
2889d12ba86SRob Rice 		ptr += sizeof(u32);
2899d12ba86SRob Rice 
2905a17eae4SHerbert Xu 		packet_log("  BDESC[2] 0x%08x\n", be32_to_cpup((__be32 *)ptr));
2919d12ba86SRob Rice 		packet_log("    OffsetICV:%u OffsetIV:%u\n",
2929d12ba86SRob Rice 			   be16_to_cpu(bdesc->offset_icv),
2939d12ba86SRob Rice 			   be16_to_cpu(bdesc->offset_iv));
2949d12ba86SRob Rice 		ptr += sizeof(u32);
2959d12ba86SRob Rice 	}
2969d12ba86SRob Rice 
2979d12ba86SRob Rice 	/* ========== Decode BD ========== */
2989d12ba86SRob Rice 	if (spuh->mh.flags & MH_BD_PRES) {
2999d12ba86SRob Rice 		struct BD_HEADER *bd = (struct BD_HEADER *)ptr;
3005a17eae4SHerbert Xu 
3015a17eae4SHerbert Xu 		packet_log("  BD[0] 0x%08x\n", be32_to_cpup((__be32 *)ptr));
3029d12ba86SRob Rice 		packet_log("    Size:%ubytes PrevLength:%u\n",
3039d12ba86SRob Rice 			   be16_to_cpu(bd->size), be16_to_cpu(bd->prev_length));
3049d12ba86SRob Rice 		ptr += 4;
3059d12ba86SRob Rice 	}
3069d12ba86SRob Rice 
3079d12ba86SRob Rice 	/* Double check sanity */
3089d12ba86SRob Rice 	if (buf + buf_len != ptr) {
3099d12ba86SRob Rice 		packet_log(" Packet parsed incorrectly. ");
3109d12ba86SRob Rice 		packet_log("buf:%p buf_len:%u buf+buf_len:%p ptr:%p\n",
3119d12ba86SRob Rice 			   buf, buf_len, buf + buf_len, ptr);
3129d12ba86SRob Rice 	}
3139d12ba86SRob Rice 
3149d12ba86SRob Rice 	packet_log("\n");
3159d12ba86SRob Rice }
3169d12ba86SRob Rice 
3179d12ba86SRob Rice /**
3189d12ba86SRob Rice  * spum_ns2_ctx_max_payload() - Determine the max length of the payload for a
3199d12ba86SRob Rice  * SPU message for a given cipher and hash alg context.
3209d12ba86SRob Rice  * @cipher_alg:		The cipher algorithm
3219d12ba86SRob Rice  * @cipher_mode:	The cipher mode
3229d12ba86SRob Rice  * @blocksize:		The size of a block of data for this algo
3239d12ba86SRob Rice  *
3249d12ba86SRob Rice  * The max payload must be a multiple of the blocksize so that if a request is
3259d12ba86SRob Rice  * too large to fit in a single SPU message, the request can be broken into
3269d12ba86SRob Rice  * max_payload sized chunks. Each chunk must be a multiple of blocksize.
3279d12ba86SRob Rice  *
3289d12ba86SRob Rice  * Return: Max payload length in bytes
3299d12ba86SRob Rice  */
spum_ns2_ctx_max_payload(enum spu_cipher_alg cipher_alg,enum spu_cipher_mode cipher_mode,unsigned int blocksize)3309d12ba86SRob Rice u32 spum_ns2_ctx_max_payload(enum spu_cipher_alg cipher_alg,
3319d12ba86SRob Rice 			     enum spu_cipher_mode cipher_mode,
3329d12ba86SRob Rice 			     unsigned int blocksize)
3339d12ba86SRob Rice {
3349d12ba86SRob Rice 	u32 max_payload = SPUM_NS2_MAX_PAYLOAD;
3359d12ba86SRob Rice 	u32 excess;
3369d12ba86SRob Rice 
3379d12ba86SRob Rice 	/* In XTS on SPU-M, we'll need to insert tweak before input data */
3389d12ba86SRob Rice 	if (cipher_mode == CIPHER_MODE_XTS)
3399d12ba86SRob Rice 		max_payload -= SPU_XTS_TWEAK_SIZE;
3409d12ba86SRob Rice 
3419d12ba86SRob Rice 	excess = max_payload % blocksize;
3429d12ba86SRob Rice 
3439d12ba86SRob Rice 	return max_payload - excess;
3449d12ba86SRob Rice }
3459d12ba86SRob Rice 
3469d12ba86SRob Rice /**
3479d12ba86SRob Rice  * spum_nsp_ctx_max_payload() - Determine the max length of the payload for a
3489d12ba86SRob Rice  * SPU message for a given cipher and hash alg context.
3499d12ba86SRob Rice  * @cipher_alg:		The cipher algorithm
3509d12ba86SRob Rice  * @cipher_mode:	The cipher mode
3519d12ba86SRob Rice  * @blocksize:		The size of a block of data for this algo
3529d12ba86SRob Rice  *
3539d12ba86SRob Rice  * The max payload must be a multiple of the blocksize so that if a request is
3549d12ba86SRob Rice  * too large to fit in a single SPU message, the request can be broken into
3559d12ba86SRob Rice  * max_payload sized chunks. Each chunk must be a multiple of blocksize.
3569d12ba86SRob Rice  *
3579d12ba86SRob Rice  * Return: Max payload length in bytes
3589d12ba86SRob Rice  */
spum_nsp_ctx_max_payload(enum spu_cipher_alg cipher_alg,enum spu_cipher_mode cipher_mode,unsigned int blocksize)3599d12ba86SRob Rice u32 spum_nsp_ctx_max_payload(enum spu_cipher_alg cipher_alg,
3609d12ba86SRob Rice 			     enum spu_cipher_mode cipher_mode,
3619d12ba86SRob Rice 			     unsigned int blocksize)
3629d12ba86SRob Rice {
3639d12ba86SRob Rice 	u32 max_payload = SPUM_NSP_MAX_PAYLOAD;
3649d12ba86SRob Rice 	u32 excess;
3659d12ba86SRob Rice 
3669d12ba86SRob Rice 	/* In XTS on SPU-M, we'll need to insert tweak before input data */
3679d12ba86SRob Rice 	if (cipher_mode == CIPHER_MODE_XTS)
3689d12ba86SRob Rice 		max_payload -= SPU_XTS_TWEAK_SIZE;
3699d12ba86SRob Rice 
3709d12ba86SRob Rice 	excess = max_payload % blocksize;
3719d12ba86SRob Rice 
3729d12ba86SRob Rice 	return max_payload - excess;
3739d12ba86SRob Rice }
3749d12ba86SRob Rice 
3759d12ba86SRob Rice /** spum_payload_length() - Given a SPU-M message header, extract the payload
3769d12ba86SRob Rice  * length.
3779d12ba86SRob Rice  * @spu_hdr:	Start of SPU header
3789d12ba86SRob Rice  *
3799d12ba86SRob Rice  * Assumes just MH, EMH, BD (no SCTX, BDESC. Works for response frames.
3809d12ba86SRob Rice  *
3819d12ba86SRob Rice  * Return: payload length in bytes
3829d12ba86SRob Rice  */
spum_payload_length(u8 * spu_hdr)3839d12ba86SRob Rice u32 spum_payload_length(u8 *spu_hdr)
3849d12ba86SRob Rice {
3859d12ba86SRob Rice 	struct BD_HEADER *bd;
3869d12ba86SRob Rice 	u32 pl_len;
3879d12ba86SRob Rice 
3889d12ba86SRob Rice 	/* Find BD header.  skip MH, EMH */
3899d12ba86SRob Rice 	bd = (struct BD_HEADER *)(spu_hdr + 8);
3909d12ba86SRob Rice 	pl_len = be16_to_cpu(bd->size);
3919d12ba86SRob Rice 
3929d12ba86SRob Rice 	return pl_len;
3939d12ba86SRob Rice }
3949d12ba86SRob Rice 
3959d12ba86SRob Rice /**
3969d12ba86SRob Rice  * spum_response_hdr_len() - Given the length of the hash key and encryption
3979d12ba86SRob Rice  * key, determine the expected length of a SPU response header.
3989d12ba86SRob Rice  * @auth_key_len:	authentication key length (bytes)
3999d12ba86SRob Rice  * @enc_key_len:	encryption key length (bytes)
4009d12ba86SRob Rice  * @is_hash:		true if response message is for a hash operation
4019d12ba86SRob Rice  *
4029d12ba86SRob Rice  * Return: length of SPU response header (bytes)
4039d12ba86SRob Rice  */
spum_response_hdr_len(u16 auth_key_len,u16 enc_key_len,bool is_hash)4049d12ba86SRob Rice u16 spum_response_hdr_len(u16 auth_key_len, u16 enc_key_len, bool is_hash)
4059d12ba86SRob Rice {
4069d12ba86SRob Rice 	if (is_hash)
4079d12ba86SRob Rice 		return SPU_HASH_RESP_HDR_LEN;
4089d12ba86SRob Rice 	else
4099d12ba86SRob Rice 		return SPU_RESP_HDR_LEN;
4109d12ba86SRob Rice }
4119d12ba86SRob Rice 
4129d12ba86SRob Rice /**
4139d12ba86SRob Rice  * spum_hash_pad_len() - Calculate the length of hash padding required to extend
4149d12ba86SRob Rice  * data to a full block size.
4159d12ba86SRob Rice  * @hash_alg:   hash algorithm
4169d12ba86SRob Rice  * @hash_mode:       hash mode
4179d12ba86SRob Rice  * @chunksize:  length of data, in bytes
4189d12ba86SRob Rice  * @hash_block_size:  size of a block of data for hash algorithm
4199d12ba86SRob Rice  *
4209d12ba86SRob Rice  * Reserve space for 1 byte (0x80) start of pad and the total length as u64
4219d12ba86SRob Rice  *
4229d12ba86SRob Rice  * Return:  length of hash pad in bytes
4239d12ba86SRob Rice  */
spum_hash_pad_len(enum hash_alg hash_alg,enum hash_mode hash_mode,u32 chunksize,u16 hash_block_size)4249d12ba86SRob Rice u16 spum_hash_pad_len(enum hash_alg hash_alg, enum hash_mode hash_mode,
4259d12ba86SRob Rice 		      u32 chunksize, u16 hash_block_size)
4269d12ba86SRob Rice {
4279d12ba86SRob Rice 	unsigned int length_len;
4289d12ba86SRob Rice 	unsigned int used_space_last_block;
4299d12ba86SRob Rice 	int hash_pad_len;
4309d12ba86SRob Rice 
4319d12ba86SRob Rice 	/* AES-XCBC hash requires just padding to next block boundary */
4329d12ba86SRob Rice 	if ((hash_alg == HASH_ALG_AES) && (hash_mode == HASH_MODE_XCBC)) {
4339d12ba86SRob Rice 		used_space_last_block = chunksize % hash_block_size;
4349d12ba86SRob Rice 		hash_pad_len = hash_block_size - used_space_last_block;
4359d12ba86SRob Rice 		if (hash_pad_len >= hash_block_size)
4369d12ba86SRob Rice 			hash_pad_len -= hash_block_size;
4379d12ba86SRob Rice 		return hash_pad_len;
4389d12ba86SRob Rice 	}
4399d12ba86SRob Rice 
4409d12ba86SRob Rice 	used_space_last_block = chunksize % hash_block_size + 1;
4419d12ba86SRob Rice 	if ((hash_alg == HASH_ALG_SHA384) || (hash_alg == HASH_ALG_SHA512))
4429d12ba86SRob Rice 		length_len = 2 * sizeof(u64);
4439d12ba86SRob Rice 	else
4449d12ba86SRob Rice 		length_len = sizeof(u64);
4459d12ba86SRob Rice 
4469d12ba86SRob Rice 	used_space_last_block += length_len;
4479d12ba86SRob Rice 	hash_pad_len = hash_block_size - used_space_last_block;
4489d12ba86SRob Rice 	if (hash_pad_len < 0)
4499d12ba86SRob Rice 		hash_pad_len += hash_block_size;
4509d12ba86SRob Rice 
4519d12ba86SRob Rice 	hash_pad_len += 1 + length_len;
4529d12ba86SRob Rice 	return hash_pad_len;
4539d12ba86SRob Rice }
4549d12ba86SRob Rice 
4559d12ba86SRob Rice /**
4569d12ba86SRob Rice  * spum_gcm_ccm_pad_len() - Determine the required length of GCM or CCM padding.
4579d12ba86SRob Rice  * @cipher_mode:	Algo type
4589d12ba86SRob Rice  * @data_size:		Length of plaintext (bytes)
4599d12ba86SRob Rice  *
460*85a557cbSLee Jones  * Return: Length of padding, in bytes
4619d12ba86SRob Rice  */
spum_gcm_ccm_pad_len(enum spu_cipher_mode cipher_mode,unsigned int data_size)4629d12ba86SRob Rice u32 spum_gcm_ccm_pad_len(enum spu_cipher_mode cipher_mode,
4639d12ba86SRob Rice 			 unsigned int data_size)
4649d12ba86SRob Rice {
4659d12ba86SRob Rice 	u32 pad_len = 0;
4669d12ba86SRob Rice 	u32 m1 = SPU_GCM_CCM_ALIGN - 1;
4679d12ba86SRob Rice 
4689d12ba86SRob Rice 	if ((cipher_mode == CIPHER_MODE_GCM) ||
4699d12ba86SRob Rice 	    (cipher_mode == CIPHER_MODE_CCM))
4709d12ba86SRob Rice 		pad_len = ((data_size + m1) & ~m1) - data_size;
4719d12ba86SRob Rice 
4729d12ba86SRob Rice 	return pad_len;
4739d12ba86SRob Rice }
4749d12ba86SRob Rice 
4759d12ba86SRob Rice /**
4769d12ba86SRob Rice  * spum_assoc_resp_len() - Determine the size of the receive buffer required to
4779d12ba86SRob Rice  * catch associated data.
4789d12ba86SRob Rice  * @cipher_mode:	cipher mode
4799d12ba86SRob Rice  * @assoc_len:		length of associated data (bytes)
4809d12ba86SRob Rice  * @iv_len:		length of IV (bytes)
4819d12ba86SRob Rice  * @is_encrypt:		true if encrypting. false if decrypting.
4829d12ba86SRob Rice  *
4839d12ba86SRob Rice  * Return: length of associated data in response message (bytes)
4849d12ba86SRob Rice  */
spum_assoc_resp_len(enum spu_cipher_mode cipher_mode,unsigned int assoc_len,unsigned int iv_len,bool is_encrypt)4859d12ba86SRob Rice u32 spum_assoc_resp_len(enum spu_cipher_mode cipher_mode,
4869d12ba86SRob Rice 			unsigned int assoc_len, unsigned int iv_len,
4879d12ba86SRob Rice 			bool is_encrypt)
4889d12ba86SRob Rice {
4899d12ba86SRob Rice 	u32 buflen = 0;
4909d12ba86SRob Rice 	u32 pad;
4919d12ba86SRob Rice 
4929d12ba86SRob Rice 	if (assoc_len)
4939d12ba86SRob Rice 		buflen = assoc_len;
4949d12ba86SRob Rice 
4959d12ba86SRob Rice 	if (cipher_mode == CIPHER_MODE_GCM) {
4969d12ba86SRob Rice 		/* AAD needs to be padded in responses too */
4979d12ba86SRob Rice 		pad = spum_gcm_ccm_pad_len(cipher_mode, buflen);
4989d12ba86SRob Rice 		buflen += pad;
4999d12ba86SRob Rice 	}
5009d12ba86SRob Rice 	if (cipher_mode == CIPHER_MODE_CCM) {
5019d12ba86SRob Rice 		/*
5029d12ba86SRob Rice 		 * AAD needs to be padded in responses too
5039d12ba86SRob Rice 		 * for CCM, len + 2 needs to be 128-bit aligned.
5049d12ba86SRob Rice 		 */
5059d12ba86SRob Rice 		pad = spum_gcm_ccm_pad_len(cipher_mode, buflen + 2);
5069d12ba86SRob Rice 		buflen += pad;
5079d12ba86SRob Rice 	}
5089d12ba86SRob Rice 
5099d12ba86SRob Rice 	return buflen;
5109d12ba86SRob Rice }
5119d12ba86SRob Rice 
5129d12ba86SRob Rice /**
513*85a557cbSLee Jones  * spum_aead_ivlen() - Calculate the length of the AEAD IV to be included
5149d12ba86SRob Rice  * in a SPU request after the AAD and before the payload.
5159d12ba86SRob Rice  * @cipher_mode:  cipher mode
516*85a557cbSLee Jones  * @iv_len:   initialization vector length in bytes
5179d12ba86SRob Rice  *
5189d12ba86SRob Rice  * In Linux ~4.2 and later, the assoc_data sg includes the IV. So no need
5199d12ba86SRob Rice  * to include the IV as a separate field in the SPU request msg.
5209d12ba86SRob Rice  *
5219d12ba86SRob Rice  * Return: Length of AEAD IV in bytes
5229d12ba86SRob Rice  */
spum_aead_ivlen(enum spu_cipher_mode cipher_mode,u16 iv_len)5239d12ba86SRob Rice u8 spum_aead_ivlen(enum spu_cipher_mode cipher_mode, u16 iv_len)
5249d12ba86SRob Rice {
5259d12ba86SRob Rice 	return 0;
5269d12ba86SRob Rice }
5279d12ba86SRob Rice 
5289d12ba86SRob Rice /**
5299d12ba86SRob Rice  * spum_hash_type() - Determine the type of hash operation.
5309d12ba86SRob Rice  * @src_sent:  The number of bytes in the current request that have already
5319d12ba86SRob Rice  *             been sent to the SPU to be hashed.
5329d12ba86SRob Rice  *
5339d12ba86SRob Rice  * We do not use HASH_TYPE_FULL for requests that fit in a single SPU message.
5349d12ba86SRob Rice  * Using FULL causes failures (such as when the string to be hashed is empty).
5359d12ba86SRob Rice  * For similar reasons, we never use HASH_TYPE_FIN. Instead, submit messages
5369d12ba86SRob Rice  * as INIT or UPDT and do the hash padding in sw.
5379d12ba86SRob Rice  */
spum_hash_type(u32 src_sent)5389d12ba86SRob Rice enum hash_type spum_hash_type(u32 src_sent)
5399d12ba86SRob Rice {
5409d12ba86SRob Rice 	return src_sent ? HASH_TYPE_UPDT : HASH_TYPE_INIT;
5419d12ba86SRob Rice }
5429d12ba86SRob Rice 
5439d12ba86SRob Rice /**
5449d12ba86SRob Rice  * spum_digest_size() - Determine the size of a hash digest to expect the SPU to
5459d12ba86SRob Rice  * return.
546*85a557cbSLee Jones  * @alg_digest_size: Number of bytes in the final digest for the given algo
547*85a557cbSLee Jones  * @alg:             The hash algorithm
548*85a557cbSLee Jones  * @htype:           Type of hash operation (init, update, full, etc)
5499d12ba86SRob Rice  *
5509d12ba86SRob Rice  * When doing incremental hashing for an algorithm with a truncated hash
5519d12ba86SRob Rice  * (e.g., SHA224), the SPU returns the full digest so that it can be fed back as
5529d12ba86SRob Rice  * a partial result for the next chunk.
5539d12ba86SRob Rice  */
spum_digest_size(u32 alg_digest_size,enum hash_alg alg,enum hash_type htype)5549d12ba86SRob Rice u32 spum_digest_size(u32 alg_digest_size, enum hash_alg alg,
5559d12ba86SRob Rice 		     enum hash_type htype)
5569d12ba86SRob Rice {
5579d12ba86SRob Rice 	u32 digestsize = alg_digest_size;
5589d12ba86SRob Rice 
5599d12ba86SRob Rice 	/* SPU returns complete digest when doing incremental hash and truncated
5609d12ba86SRob Rice 	 * hash algo.
5619d12ba86SRob Rice 	 */
5629d12ba86SRob Rice 	if ((htype == HASH_TYPE_INIT) || (htype == HASH_TYPE_UPDT)) {
5639d12ba86SRob Rice 		if (alg == HASH_ALG_SHA224)
5649d12ba86SRob Rice 			digestsize = SHA256_DIGEST_SIZE;
5659d12ba86SRob Rice 		else if (alg == HASH_ALG_SHA384)
5669d12ba86SRob Rice 			digestsize = SHA512_DIGEST_SIZE;
5679d12ba86SRob Rice 	}
5689d12ba86SRob Rice 	return digestsize;
5699d12ba86SRob Rice }
5709d12ba86SRob Rice 
5719d12ba86SRob Rice /**
5729d12ba86SRob Rice  * spum_create_request() - Build a SPU request message header, up to and
5739d12ba86SRob Rice  * including the BD header. Construct the message starting at spu_hdr. Caller
5749d12ba86SRob Rice  * should allocate this buffer in DMA-able memory at least SPU_HEADER_ALLOC_LEN
5759d12ba86SRob Rice  * bytes long.
5769d12ba86SRob Rice  * @spu_hdr: Start of buffer where SPU request header is to be written
5779d12ba86SRob Rice  * @req_opts: SPU request message options
5789d12ba86SRob Rice  * @cipher_parms: Parameters related to cipher algorithm
5799d12ba86SRob Rice  * @hash_parms:   Parameters related to hash algorithm
5809d12ba86SRob Rice  * @aead_parms:   Parameters related to AEAD operation
5819d12ba86SRob Rice  * @data_size:    Length of data to be encrypted or authenticated. If AEAD, does
5829d12ba86SRob Rice  *		  not include length of AAD.
583*85a557cbSLee Jones  *
5849d12ba86SRob Rice  * Return: the length of the SPU header in bytes. 0 if an error occurs.
5859d12ba86SRob Rice  */
spum_create_request(u8 * spu_hdr,struct spu_request_opts * req_opts,struct spu_cipher_parms * cipher_parms,struct spu_hash_parms * hash_parms,struct spu_aead_parms * aead_parms,unsigned int data_size)5869d12ba86SRob Rice u32 spum_create_request(u8 *spu_hdr,
5879d12ba86SRob Rice 			struct spu_request_opts *req_opts,
5889d12ba86SRob Rice 			struct spu_cipher_parms *cipher_parms,
5899d12ba86SRob Rice 			struct spu_hash_parms *hash_parms,
5909d12ba86SRob Rice 			struct spu_aead_parms *aead_parms,
5919d12ba86SRob Rice 			unsigned int data_size)
5929d12ba86SRob Rice {
5939d12ba86SRob Rice 	struct SPUHEADER *spuh;
5949d12ba86SRob Rice 	struct BDESC_HEADER *bdesc;
5959d12ba86SRob Rice 	struct BD_HEADER *bd;
5969d12ba86SRob Rice 
5979d12ba86SRob Rice 	u8 *ptr;
5989d12ba86SRob Rice 	u32 protocol_bits = 0;
5999d12ba86SRob Rice 	u32 cipher_bits = 0;
6009d12ba86SRob Rice 	u32 ecf_bits = 0;
6019d12ba86SRob Rice 	u8 sctx_words = 0;
6029d12ba86SRob Rice 	unsigned int buf_len = 0;
6039d12ba86SRob Rice 
6049d12ba86SRob Rice 	/* size of the cipher payload */
6059d12ba86SRob Rice 	unsigned int cipher_len = hash_parms->prebuf_len + data_size +
6069d12ba86SRob Rice 				hash_parms->pad_len;
6079d12ba86SRob Rice 
6089d12ba86SRob Rice 	/* offset of prebuf or data from end of BD header */
6099d12ba86SRob Rice 	unsigned int cipher_offset = aead_parms->assoc_size +
6109d12ba86SRob Rice 		aead_parms->iv_len + aead_parms->aad_pad_len;
6119d12ba86SRob Rice 
6129d12ba86SRob Rice 	/* total size of the DB data (without STAT word padding) */
6139d12ba86SRob Rice 	unsigned int real_db_size = spu_real_db_size(aead_parms->assoc_size,
6149d12ba86SRob Rice 						 aead_parms->iv_len,
6159d12ba86SRob Rice 						 hash_parms->prebuf_len,
6169d12ba86SRob Rice 						 data_size,
6179d12ba86SRob Rice 						 aead_parms->aad_pad_len,
6189d12ba86SRob Rice 						 aead_parms->data_pad_len,
6199d12ba86SRob Rice 						 hash_parms->pad_len);
6209d12ba86SRob Rice 
6219d12ba86SRob Rice 	unsigned int auth_offset = 0;
6229d12ba86SRob Rice 	unsigned int offset_iv = 0;
6239d12ba86SRob Rice 
6249d12ba86SRob Rice 	/* size/offset of the auth payload */
6259d12ba86SRob Rice 	unsigned int auth_len;
6269d12ba86SRob Rice 
6279d12ba86SRob Rice 	auth_len = real_db_size;
6289d12ba86SRob Rice 
6299d12ba86SRob Rice 	if (req_opts->is_aead && req_opts->is_inbound)
6309d12ba86SRob Rice 		cipher_len -= hash_parms->digestsize;
6319d12ba86SRob Rice 
6329d12ba86SRob Rice 	if (req_opts->is_aead && req_opts->is_inbound)
6339d12ba86SRob Rice 		auth_len -= hash_parms->digestsize;
6349d12ba86SRob Rice 
6359d12ba86SRob Rice 	if ((hash_parms->alg == HASH_ALG_AES) &&
6369d12ba86SRob Rice 	    (hash_parms->mode == HASH_MODE_XCBC)) {
6379d12ba86SRob Rice 		auth_len -= hash_parms->pad_len;
6389d12ba86SRob Rice 		cipher_len -= hash_parms->pad_len;
6399d12ba86SRob Rice 	}
6409d12ba86SRob Rice 
6419d12ba86SRob Rice 	flow_log("%s()\n", __func__);
6429d12ba86SRob Rice 	flow_log("  in:%u authFirst:%u\n",
6439d12ba86SRob Rice 		 req_opts->is_inbound, req_opts->auth_first);
6449d12ba86SRob Rice 	flow_log("  %s. cipher alg:%u mode:%u type %u\n",
6459d12ba86SRob Rice 		 spu_alg_name(cipher_parms->alg, cipher_parms->mode),
6469d12ba86SRob Rice 		 cipher_parms->alg, cipher_parms->mode, cipher_parms->type);
6479d12ba86SRob Rice 	flow_log("    key: %d\n", cipher_parms->key_len);
6489d12ba86SRob Rice 	flow_dump("    key: ", cipher_parms->key_buf, cipher_parms->key_len);
6499d12ba86SRob Rice 	flow_log("    iv: %d\n", cipher_parms->iv_len);
6509d12ba86SRob Rice 	flow_dump("    iv: ", cipher_parms->iv_buf, cipher_parms->iv_len);
6519d12ba86SRob Rice 	flow_log("  auth alg:%u mode:%u type %u\n",
6529d12ba86SRob Rice 		 hash_parms->alg, hash_parms->mode, hash_parms->type);
6539d12ba86SRob Rice 	flow_log("  digestsize: %u\n", hash_parms->digestsize);
6549d12ba86SRob Rice 	flow_log("  authkey: %d\n", hash_parms->key_len);
6559d12ba86SRob Rice 	flow_dump("  authkey: ", hash_parms->key_buf, hash_parms->key_len);
6569d12ba86SRob Rice 	flow_log("  assoc_size:%u\n", aead_parms->assoc_size);
6579d12ba86SRob Rice 	flow_log("  prebuf_len:%u\n", hash_parms->prebuf_len);
6589d12ba86SRob Rice 	flow_log("  data_size:%u\n", data_size);
6599d12ba86SRob Rice 	flow_log("  hash_pad_len:%u\n", hash_parms->pad_len);
6609d12ba86SRob Rice 	flow_log("  real_db_size:%u\n", real_db_size);
6619d12ba86SRob Rice 	flow_log(" auth_offset:%u auth_len:%u cipher_offset:%u cipher_len:%u\n",
6629d12ba86SRob Rice 		 auth_offset, auth_len, cipher_offset, cipher_len);
6639d12ba86SRob Rice 	flow_log("  aead_iv: %u\n", aead_parms->iv_len);
6649d12ba86SRob Rice 
6659d12ba86SRob Rice 	/* starting out: zero the header (plus some) */
6669d12ba86SRob Rice 	ptr = spu_hdr;
6679d12ba86SRob Rice 	memset(ptr, 0, sizeof(struct SPUHEADER));
6689d12ba86SRob Rice 
6699d12ba86SRob Rice 	/* format master header word */
6709d12ba86SRob Rice 	/* Do not set the next bit even though the datasheet says to */
6719d12ba86SRob Rice 	spuh = (struct SPUHEADER *)ptr;
6729d12ba86SRob Rice 	ptr += sizeof(struct SPUHEADER);
6739d12ba86SRob Rice 	buf_len += sizeof(struct SPUHEADER);
6749d12ba86SRob Rice 
6759d12ba86SRob Rice 	spuh->mh.op_code = SPU_CRYPTO_OPERATION_GENERIC;
6769d12ba86SRob Rice 	spuh->mh.flags |= (MH_SCTX_PRES | MH_BDESC_PRES | MH_BD_PRES);
6779d12ba86SRob Rice 
6789d12ba86SRob Rice 	/* Format sctx word 0 (protocol_bits) */
6799d12ba86SRob Rice 	sctx_words = 3;		/* size in words */
6809d12ba86SRob Rice 
6819d12ba86SRob Rice 	/* Format sctx word 1 (cipher_bits) */
6829d12ba86SRob Rice 	if (req_opts->is_inbound)
6839d12ba86SRob Rice 		cipher_bits |= CIPHER_INBOUND;
6849d12ba86SRob Rice 	if (req_opts->auth_first)
6859d12ba86SRob Rice 		cipher_bits |= CIPHER_ORDER;
6869d12ba86SRob Rice 
6879d12ba86SRob Rice 	/* Set the crypto parameters in the cipher.flags */
6889d12ba86SRob Rice 	cipher_bits |= cipher_parms->alg << CIPHER_ALG_SHIFT;
6899d12ba86SRob Rice 	cipher_bits |= cipher_parms->mode << CIPHER_MODE_SHIFT;
6909d12ba86SRob Rice 	cipher_bits |= cipher_parms->type << CIPHER_TYPE_SHIFT;
6919d12ba86SRob Rice 
6929d12ba86SRob Rice 	/* Set the auth parameters in the cipher.flags */
6939d12ba86SRob Rice 	cipher_bits |= hash_parms->alg << HASH_ALG_SHIFT;
6949d12ba86SRob Rice 	cipher_bits |= hash_parms->mode << HASH_MODE_SHIFT;
6959d12ba86SRob Rice 	cipher_bits |= hash_parms->type << HASH_TYPE_SHIFT;
6969d12ba86SRob Rice 
6979d12ba86SRob Rice 	/*
6989d12ba86SRob Rice 	 * Format sctx extensions if required, and update main fields if
6999d12ba86SRob Rice 	 * required)
7009d12ba86SRob Rice 	 */
7019d12ba86SRob Rice 	if (hash_parms->alg) {
7029d12ba86SRob Rice 		/* Write the authentication key material if present */
7039d12ba86SRob Rice 		if (hash_parms->key_len) {
7049d12ba86SRob Rice 			memcpy(ptr, hash_parms->key_buf, hash_parms->key_len);
7059d12ba86SRob Rice 			ptr += hash_parms->key_len;
7069d12ba86SRob Rice 			buf_len += hash_parms->key_len;
7079d12ba86SRob Rice 			sctx_words += hash_parms->key_len / 4;
7089d12ba86SRob Rice 		}
7099d12ba86SRob Rice 
7109d12ba86SRob Rice 		if ((cipher_parms->mode == CIPHER_MODE_GCM) ||
7119d12ba86SRob Rice 		    (cipher_parms->mode == CIPHER_MODE_CCM))
7129d12ba86SRob Rice 			/* unpadded length */
7139d12ba86SRob Rice 			offset_iv = aead_parms->assoc_size;
7149d12ba86SRob Rice 
7159d12ba86SRob Rice 		/* if GCM/CCM we need to write ICV into the payload */
7169d12ba86SRob Rice 		if (!req_opts->is_inbound) {
7179d12ba86SRob Rice 			if ((cipher_parms->mode == CIPHER_MODE_GCM) ||
7189d12ba86SRob Rice 			    (cipher_parms->mode == CIPHER_MODE_CCM))
7199d12ba86SRob Rice 				ecf_bits |= 1 << INSERT_ICV_SHIFT;
7209d12ba86SRob Rice 		} else {
7219d12ba86SRob Rice 			ecf_bits |= CHECK_ICV;
7229d12ba86SRob Rice 		}
7239d12ba86SRob Rice 
7249d12ba86SRob Rice 		/* Inform the SPU of the ICV size (in words) */
7259d12ba86SRob Rice 		if (hash_parms->digestsize == 64)
7269d12ba86SRob Rice 			cipher_bits |= ICV_IS_512;
7279d12ba86SRob Rice 		else
7289d12ba86SRob Rice 			ecf_bits |=
7299d12ba86SRob Rice 			(hash_parms->digestsize / 4) << ICV_SIZE_SHIFT;
7309d12ba86SRob Rice 	}
7319d12ba86SRob Rice 
7329d12ba86SRob Rice 	if (req_opts->bd_suppress)
7339d12ba86SRob Rice 		ecf_bits |= BD_SUPPRESS;
7349d12ba86SRob Rice 
7359d12ba86SRob Rice 	/* copy the encryption keys in the SAD entry */
7369d12ba86SRob Rice 	if (cipher_parms->alg) {
7379d12ba86SRob Rice 		if (cipher_parms->key_len) {
7389d12ba86SRob Rice 			memcpy(ptr, cipher_parms->key_buf,
7399d12ba86SRob Rice 			       cipher_parms->key_len);
7409d12ba86SRob Rice 			ptr += cipher_parms->key_len;
7419d12ba86SRob Rice 			buf_len += cipher_parms->key_len;
7429d12ba86SRob Rice 			sctx_words += cipher_parms->key_len / 4;
7439d12ba86SRob Rice 		}
7449d12ba86SRob Rice 
7459d12ba86SRob Rice 		/*
7469d12ba86SRob Rice 		 * if encrypting then set IV size, use SCTX IV unless no IV
7479d12ba86SRob Rice 		 * given here
7489d12ba86SRob Rice 		 */
7499d12ba86SRob Rice 		if (cipher_parms->iv_buf && cipher_parms->iv_len) {
7509d12ba86SRob Rice 			/* Use SCTX IV */
7519d12ba86SRob Rice 			ecf_bits |= SCTX_IV;
7529d12ba86SRob Rice 
7539d12ba86SRob Rice 			/* cipher iv provided so put it in here */
7549d12ba86SRob Rice 			memcpy(ptr, cipher_parms->iv_buf, cipher_parms->iv_len);
7559d12ba86SRob Rice 
7569d12ba86SRob Rice 			ptr += cipher_parms->iv_len;
7579d12ba86SRob Rice 			buf_len += cipher_parms->iv_len;
7589d12ba86SRob Rice 			sctx_words += cipher_parms->iv_len / 4;
7599d12ba86SRob Rice 		}
7609d12ba86SRob Rice 	}
7619d12ba86SRob Rice 
7629d12ba86SRob Rice 	/*
7639d12ba86SRob Rice 	 * RFC4543 (GMAC/ESP) requires data to be sent as part of AAD
7649d12ba86SRob Rice 	 * so we need to override the BDESC parameters.
7659d12ba86SRob Rice 	 */
7669d12ba86SRob Rice 	if (req_opts->is_rfc4543) {
7679d12ba86SRob Rice 		if (req_opts->is_inbound)
7689d12ba86SRob Rice 			data_size -= hash_parms->digestsize;
7699d12ba86SRob Rice 		offset_iv = aead_parms->assoc_size + data_size;
7709d12ba86SRob Rice 		cipher_len = 0;
7719d12ba86SRob Rice 		cipher_offset = offset_iv;
7729d12ba86SRob Rice 		auth_len = cipher_offset + aead_parms->data_pad_len;
7739d12ba86SRob Rice 	}
7749d12ba86SRob Rice 
7759d12ba86SRob Rice 	/* write in the total sctx length now that we know it */
7769d12ba86SRob Rice 	protocol_bits |= sctx_words;
7779d12ba86SRob Rice 
7789d12ba86SRob Rice 	/* Endian adjust the SCTX */
7799d12ba86SRob Rice 	spuh->sa.proto_flags = cpu_to_be32(protocol_bits);
7809d12ba86SRob Rice 	spuh->sa.cipher_flags = cpu_to_be32(cipher_bits);
7819d12ba86SRob Rice 	spuh->sa.ecf = cpu_to_be32(ecf_bits);
7829d12ba86SRob Rice 
7839d12ba86SRob Rice 	/* === create the BDESC section === */
7849d12ba86SRob Rice 	bdesc = (struct BDESC_HEADER *)ptr;
7859d12ba86SRob Rice 
7869d12ba86SRob Rice 	bdesc->offset_mac = cpu_to_be16(auth_offset);
7879d12ba86SRob Rice 	bdesc->length_mac = cpu_to_be16(auth_len);
7889d12ba86SRob Rice 	bdesc->offset_crypto = cpu_to_be16(cipher_offset);
7899d12ba86SRob Rice 	bdesc->length_crypto = cpu_to_be16(cipher_len);
7909d12ba86SRob Rice 
7919d12ba86SRob Rice 	/*
7929d12ba86SRob Rice 	 * CCM in SPU-M requires that ICV not be in same 32-bit word as data or
7939d12ba86SRob Rice 	 * padding.  So account for padding as necessary.
7949d12ba86SRob Rice 	 */
7959d12ba86SRob Rice 	if (cipher_parms->mode == CIPHER_MODE_CCM)
7969d12ba86SRob Rice 		auth_len += spum_wordalign_padlen(auth_len);
7979d12ba86SRob Rice 
7989d12ba86SRob Rice 	bdesc->offset_icv = cpu_to_be16(auth_len);
7999d12ba86SRob Rice 	bdesc->offset_iv = cpu_to_be16(offset_iv);
8009d12ba86SRob Rice 
8019d12ba86SRob Rice 	ptr += sizeof(struct BDESC_HEADER);
8029d12ba86SRob Rice 	buf_len += sizeof(struct BDESC_HEADER);
8039d12ba86SRob Rice 
8049d12ba86SRob Rice 	/* === no MFM section === */
8059d12ba86SRob Rice 
8069d12ba86SRob Rice 	/* === create the BD section === */
8079d12ba86SRob Rice 
8089d12ba86SRob Rice 	/* add the BD header */
8099d12ba86SRob Rice 	bd = (struct BD_HEADER *)ptr;
8109d12ba86SRob Rice 	bd->size = cpu_to_be16(real_db_size);
8119d12ba86SRob Rice 	bd->prev_length = 0;
8129d12ba86SRob Rice 
8139d12ba86SRob Rice 	ptr += sizeof(struct BD_HEADER);
8149d12ba86SRob Rice 	buf_len += sizeof(struct BD_HEADER);
8159d12ba86SRob Rice 
8169d12ba86SRob Rice 	packet_dump("  SPU request header: ", spu_hdr, buf_len);
8179d12ba86SRob Rice 
8189d12ba86SRob Rice 	return buf_len;
8199d12ba86SRob Rice }
8209d12ba86SRob Rice 
8219d12ba86SRob Rice /**
8229d12ba86SRob Rice  * spum_cipher_req_init() - Build a SPU request message header, up to and
8239d12ba86SRob Rice  * including the BD header.
8249d12ba86SRob Rice  * @spu_hdr:      Start of SPU request header (MH)
8259d12ba86SRob Rice  * @cipher_parms: Parameters that describe the cipher request
8269d12ba86SRob Rice  *
8279d12ba86SRob Rice  * Construct the message starting at spu_hdr. Caller should allocate this buffer
8289d12ba86SRob Rice  * in DMA-able memory at least SPU_HEADER_ALLOC_LEN bytes long.
8299d12ba86SRob Rice  *
8309d12ba86SRob Rice  * Return: the length of the SPU header in bytes. 0 if an error occurs.
8319d12ba86SRob Rice  */
spum_cipher_req_init(u8 * spu_hdr,struct spu_cipher_parms * cipher_parms)8329d12ba86SRob Rice u16 spum_cipher_req_init(u8 *spu_hdr, struct spu_cipher_parms *cipher_parms)
8339d12ba86SRob Rice {
8349d12ba86SRob Rice 	struct SPUHEADER *spuh;
8359d12ba86SRob Rice 	u32 protocol_bits = 0;
8369d12ba86SRob Rice 	u32 cipher_bits = 0;
8379d12ba86SRob Rice 	u32 ecf_bits = 0;
8389d12ba86SRob Rice 	u8 sctx_words = 0;
8399d12ba86SRob Rice 	u8 *ptr = spu_hdr;
8409d12ba86SRob Rice 
8419d12ba86SRob Rice 	flow_log("%s()\n", __func__);
8429d12ba86SRob Rice 	flow_log("  cipher alg:%u mode:%u type %u\n", cipher_parms->alg,
8439d12ba86SRob Rice 		 cipher_parms->mode, cipher_parms->type);
8449d12ba86SRob Rice 	flow_log("  cipher_iv_len: %u\n", cipher_parms->iv_len);
8459d12ba86SRob Rice 	flow_log("    key: %d\n", cipher_parms->key_len);
8469d12ba86SRob Rice 	flow_dump("    key: ", cipher_parms->key_buf, cipher_parms->key_len);
8479d12ba86SRob Rice 
8489d12ba86SRob Rice 	/* starting out: zero the header (plus some) */
8499d12ba86SRob Rice 	memset(spu_hdr, 0, sizeof(struct SPUHEADER));
8509d12ba86SRob Rice 	ptr += sizeof(struct SPUHEADER);
8519d12ba86SRob Rice 
8529d12ba86SRob Rice 	/* format master header word */
8539d12ba86SRob Rice 	/* Do not set the next bit even though the datasheet says to */
8549d12ba86SRob Rice 	spuh = (struct SPUHEADER *)spu_hdr;
8559d12ba86SRob Rice 
8569d12ba86SRob Rice 	spuh->mh.op_code = SPU_CRYPTO_OPERATION_GENERIC;
8579d12ba86SRob Rice 	spuh->mh.flags |= (MH_SCTX_PRES | MH_BDESC_PRES | MH_BD_PRES);
8589d12ba86SRob Rice 
8599d12ba86SRob Rice 	/* Format sctx word 0 (protocol_bits) */
8609d12ba86SRob Rice 	sctx_words = 3;		/* size in words */
8619d12ba86SRob Rice 
8629d12ba86SRob Rice 	/* copy the encryption keys in the SAD entry */
8639d12ba86SRob Rice 	if (cipher_parms->alg) {
8649d12ba86SRob Rice 		if (cipher_parms->key_len) {
8659d12ba86SRob Rice 			ptr += cipher_parms->key_len;
8669d12ba86SRob Rice 			sctx_words += cipher_parms->key_len / 4;
8679d12ba86SRob Rice 		}
8689d12ba86SRob Rice 
8699d12ba86SRob Rice 		/*
8709d12ba86SRob Rice 		 * if encrypting then set IV size, use SCTX IV unless no IV
8719d12ba86SRob Rice 		 * given here
8729d12ba86SRob Rice 		 */
8739d12ba86SRob Rice 		if (cipher_parms->iv_len) {
8749d12ba86SRob Rice 			/* Use SCTX IV */
8759d12ba86SRob Rice 			ecf_bits |= SCTX_IV;
8769d12ba86SRob Rice 			ptr += cipher_parms->iv_len;
8779d12ba86SRob Rice 			sctx_words += cipher_parms->iv_len / 4;
8789d12ba86SRob Rice 		}
8799d12ba86SRob Rice 	}
8809d12ba86SRob Rice 
8819d12ba86SRob Rice 	/* Set the crypto parameters in the cipher.flags */
8829d12ba86SRob Rice 	cipher_bits |= cipher_parms->alg << CIPHER_ALG_SHIFT;
8839d12ba86SRob Rice 	cipher_bits |= cipher_parms->mode << CIPHER_MODE_SHIFT;
8849d12ba86SRob Rice 	cipher_bits |= cipher_parms->type << CIPHER_TYPE_SHIFT;
8859d12ba86SRob Rice 
8869d12ba86SRob Rice 	/* copy the encryption keys in the SAD entry */
8879d12ba86SRob Rice 	if (cipher_parms->alg && cipher_parms->key_len)
8889d12ba86SRob Rice 		memcpy(spuh + 1, cipher_parms->key_buf, cipher_parms->key_len);
8899d12ba86SRob Rice 
8909d12ba86SRob Rice 	/* write in the total sctx length now that we know it */
8919d12ba86SRob Rice 	protocol_bits |= sctx_words;
8929d12ba86SRob Rice 
8939d12ba86SRob Rice 	/* Endian adjust the SCTX */
8949d12ba86SRob Rice 	spuh->sa.proto_flags = cpu_to_be32(protocol_bits);
8959d12ba86SRob Rice 
8969d12ba86SRob Rice 	/* Endian adjust the SCTX */
8979d12ba86SRob Rice 	spuh->sa.cipher_flags = cpu_to_be32(cipher_bits);
8989d12ba86SRob Rice 	spuh->sa.ecf = cpu_to_be32(ecf_bits);
8999d12ba86SRob Rice 
9009d12ba86SRob Rice 	packet_dump("  SPU request header: ", spu_hdr,
9019d12ba86SRob Rice 		    sizeof(struct SPUHEADER));
9029d12ba86SRob Rice 
9039d12ba86SRob Rice 	return sizeof(struct SPUHEADER) + cipher_parms->key_len +
9049d12ba86SRob Rice 		cipher_parms->iv_len + sizeof(struct BDESC_HEADER) +
9059d12ba86SRob Rice 		sizeof(struct BD_HEADER);
9069d12ba86SRob Rice }
9079d12ba86SRob Rice 
9089d12ba86SRob Rice /**
9099d12ba86SRob Rice  * spum_cipher_req_finish() - Finish building a SPU request message header for a
9109d12ba86SRob Rice  * block cipher request. Assumes much of the header was already filled in at
9119d12ba86SRob Rice  * setkey() time in spu_cipher_req_init().
9129d12ba86SRob Rice  * @spu_hdr:         Start of the request message header (MH field)
9139d12ba86SRob Rice  * @spu_req_hdr_len: Length in bytes of the SPU request header
914*85a557cbSLee Jones  * @is_inbound:      0 encrypt, 1 decrypt
9159d12ba86SRob Rice  * @cipher_parms:    Parameters describing cipher operation to be performed
9169d12ba86SRob Rice  * @data_size:       Length of the data in the BD field
9179d12ba86SRob Rice  *
9189d12ba86SRob Rice  * Assumes much of the header was already filled in at setkey() time in
9199d12ba86SRob Rice  * spum_cipher_req_init().
9201dbab6b1SArd Biesheuvel  * spum_cipher_req_init() fills in the encryption key.
9219d12ba86SRob Rice  */
spum_cipher_req_finish(u8 * spu_hdr,u16 spu_req_hdr_len,unsigned int is_inbound,struct spu_cipher_parms * cipher_parms,unsigned int data_size)9229d12ba86SRob Rice void spum_cipher_req_finish(u8 *spu_hdr,
9239d12ba86SRob Rice 			    u16 spu_req_hdr_len,
9249d12ba86SRob Rice 			    unsigned int is_inbound,
9259d12ba86SRob Rice 			    struct spu_cipher_parms *cipher_parms,
9269d12ba86SRob Rice 			    unsigned int data_size)
9279d12ba86SRob Rice {
9289d12ba86SRob Rice 	struct SPUHEADER *spuh;
9299d12ba86SRob Rice 	struct BDESC_HEADER *bdesc;
9309d12ba86SRob Rice 	struct BD_HEADER *bd;
9319d12ba86SRob Rice 	u8 *bdesc_ptr = spu_hdr + spu_req_hdr_len -
9329d12ba86SRob Rice 	    (sizeof(struct BD_HEADER) + sizeof(struct BDESC_HEADER));
9339d12ba86SRob Rice 
9349d12ba86SRob Rice 	u32 cipher_bits;
9359d12ba86SRob Rice 
9369d12ba86SRob Rice 	flow_log("%s()\n", __func__);
9379d12ba86SRob Rice 	flow_log(" in: %u\n", is_inbound);
9389d12ba86SRob Rice 	flow_log(" cipher alg: %u, cipher_type: %u\n", cipher_parms->alg,
9399d12ba86SRob Rice 		 cipher_parms->type);
9409d12ba86SRob Rice 
9419d12ba86SRob Rice 	/*
9429d12ba86SRob Rice 	 * In XTS mode, API puts "i" parameter (block tweak) in IV.  For
9439d12ba86SRob Rice 	 * SPU-M, should be in start of the BD; tx_sg_create() copies it there.
9449d12ba86SRob Rice 	 * IV in SPU msg for SPU-M should be 0, since that's the "j" parameter
9459d12ba86SRob Rice 	 * (block ctr within larger data unit) - given we can send entire disk
9469d12ba86SRob Rice 	 * block (<= 4KB) in 1 SPU msg, don't need to use this parameter.
9479d12ba86SRob Rice 	 */
9489d12ba86SRob Rice 	if (cipher_parms->mode == CIPHER_MODE_XTS)
9499d12ba86SRob Rice 		memset(cipher_parms->iv_buf, 0, cipher_parms->iv_len);
9509d12ba86SRob Rice 
9519d12ba86SRob Rice 	flow_log(" iv len: %d\n", cipher_parms->iv_len);
9529d12ba86SRob Rice 	flow_dump("    iv: ", cipher_parms->iv_buf, cipher_parms->iv_len);
9539d12ba86SRob Rice 	flow_log(" data_size: %u\n", data_size);
9549d12ba86SRob Rice 
9559d12ba86SRob Rice 	/* format master header word */
9569d12ba86SRob Rice 	/* Do not set the next bit even though the datasheet says to */
9579d12ba86SRob Rice 	spuh = (struct SPUHEADER *)spu_hdr;
9589d12ba86SRob Rice 
9599d12ba86SRob Rice 	/* cipher_bits was initialized at setkey time */
9609d12ba86SRob Rice 	cipher_bits = be32_to_cpu(spuh->sa.cipher_flags);
9619d12ba86SRob Rice 
9629d12ba86SRob Rice 	/* Format sctx word 1 (cipher_bits) */
9639d12ba86SRob Rice 	if (is_inbound)
9649d12ba86SRob Rice 		cipher_bits |= CIPHER_INBOUND;
9659d12ba86SRob Rice 	else
9669d12ba86SRob Rice 		cipher_bits &= ~CIPHER_INBOUND;
9679d12ba86SRob Rice 
9689d12ba86SRob Rice 	if (cipher_parms->alg && cipher_parms->iv_buf && cipher_parms->iv_len)
9699d12ba86SRob Rice 		/* cipher iv provided so put it in here */
9709d12ba86SRob Rice 		memcpy(bdesc_ptr - cipher_parms->iv_len, cipher_parms->iv_buf,
9719d12ba86SRob Rice 		       cipher_parms->iv_len);
9729d12ba86SRob Rice 
9739d12ba86SRob Rice 	spuh->sa.cipher_flags = cpu_to_be32(cipher_bits);
9749d12ba86SRob Rice 
9759d12ba86SRob Rice 	/* === create the BDESC section === */
9769d12ba86SRob Rice 	bdesc = (struct BDESC_HEADER *)bdesc_ptr;
9779d12ba86SRob Rice 	bdesc->offset_mac = 0;
9789d12ba86SRob Rice 	bdesc->length_mac = 0;
9799d12ba86SRob Rice 	bdesc->offset_crypto = 0;
9809d12ba86SRob Rice 
9819d12ba86SRob Rice 	/* XTS mode, data_size needs to include tweak parameter */
9829d12ba86SRob Rice 	if (cipher_parms->mode == CIPHER_MODE_XTS)
9839d12ba86SRob Rice 		bdesc->length_crypto = cpu_to_be16(data_size +
9849d12ba86SRob Rice 						  SPU_XTS_TWEAK_SIZE);
9859d12ba86SRob Rice 	else
9869d12ba86SRob Rice 		bdesc->length_crypto = cpu_to_be16(data_size);
9879d12ba86SRob Rice 
9889d12ba86SRob Rice 	bdesc->offset_icv = 0;
9899d12ba86SRob Rice 	bdesc->offset_iv = 0;
9909d12ba86SRob Rice 
9919d12ba86SRob Rice 	/* === no MFM section === */
9929d12ba86SRob Rice 
9939d12ba86SRob Rice 	/* === create the BD section === */
9949d12ba86SRob Rice 	/* add the BD header */
9959d12ba86SRob Rice 	bd = (struct BD_HEADER *)(bdesc_ptr + sizeof(struct BDESC_HEADER));
9969d12ba86SRob Rice 	bd->size = cpu_to_be16(data_size);
9979d12ba86SRob Rice 
9989d12ba86SRob Rice 	/* XTS mode, data_size needs to include tweak parameter */
9999d12ba86SRob Rice 	if (cipher_parms->mode == CIPHER_MODE_XTS)
10009d12ba86SRob Rice 		bd->size = cpu_to_be16(data_size + SPU_XTS_TWEAK_SIZE);
10019d12ba86SRob Rice 	else
10029d12ba86SRob Rice 		bd->size = cpu_to_be16(data_size);
10039d12ba86SRob Rice 
10049d12ba86SRob Rice 	bd->prev_length = 0;
10059d12ba86SRob Rice 
10069d12ba86SRob Rice 	packet_dump("  SPU request header: ", spu_hdr, spu_req_hdr_len);
10079d12ba86SRob Rice }
10089d12ba86SRob Rice 
10099d12ba86SRob Rice /**
10109d12ba86SRob Rice  * spum_request_pad() - Create pad bytes at the end of the data.
10119d12ba86SRob Rice  * @pad_start:		Start of buffer where pad bytes are to be written
10129d12ba86SRob Rice  * @gcm_ccm_padding:	length of GCM/CCM padding, in bytes
10139d12ba86SRob Rice  * @hash_pad_len:	Number of bytes of padding extend data to full block
10149d12ba86SRob Rice  * @auth_alg:		authentication algorithm
10159d12ba86SRob Rice  * @auth_mode:		authentication mode
10169d12ba86SRob Rice  * @total_sent:		length inserted at end of hash pad
10179d12ba86SRob Rice  * @status_padding:	Number of bytes of padding to align STATUS word
10189d12ba86SRob Rice  *
10199d12ba86SRob Rice  * There may be three forms of pad:
10209d12ba86SRob Rice  *  1. GCM/CCM pad - for GCM/CCM mode ciphers, pad to 16-byte alignment
10219d12ba86SRob Rice  *  2. hash pad - pad to a block length, with 0x80 data terminator and
10229d12ba86SRob Rice  *                size at the end
10239d12ba86SRob Rice  *  3. STAT pad - to ensure the STAT field is 4-byte aligned
10249d12ba86SRob Rice  */
spum_request_pad(u8 * pad_start,u32 gcm_ccm_padding,u32 hash_pad_len,enum hash_alg auth_alg,enum hash_mode auth_mode,unsigned int total_sent,u32 status_padding)10259d12ba86SRob Rice void spum_request_pad(u8 *pad_start,
10269d12ba86SRob Rice 		      u32 gcm_ccm_padding,
10279d12ba86SRob Rice 		      u32 hash_pad_len,
10289d12ba86SRob Rice 		      enum hash_alg auth_alg,
10299d12ba86SRob Rice 		      enum hash_mode auth_mode,
10309d12ba86SRob Rice 		      unsigned int total_sent, u32 status_padding)
10319d12ba86SRob Rice {
10329d12ba86SRob Rice 	u8 *ptr = pad_start;
10339d12ba86SRob Rice 
10349d12ba86SRob Rice 	/* fix data alignent for GCM/CCM */
10359d12ba86SRob Rice 	if (gcm_ccm_padding > 0) {
10369d12ba86SRob Rice 		flow_log("  GCM: padding to 16 byte alignment: %u bytes\n",
10379d12ba86SRob Rice 			 gcm_ccm_padding);
10389d12ba86SRob Rice 		memset(ptr, 0, gcm_ccm_padding);
10399d12ba86SRob Rice 		ptr += gcm_ccm_padding;
10409d12ba86SRob Rice 	}
10419d12ba86SRob Rice 
10429d12ba86SRob Rice 	if (hash_pad_len > 0) {
10439d12ba86SRob Rice 		/* clear the padding section */
10449d12ba86SRob Rice 		memset(ptr, 0, hash_pad_len);
10459d12ba86SRob Rice 
10469d12ba86SRob Rice 		if ((auth_alg == HASH_ALG_AES) &&
10479d12ba86SRob Rice 		    (auth_mode == HASH_MODE_XCBC)) {
10489d12ba86SRob Rice 			/* AES/XCBC just requires padding to be 0s */
10499d12ba86SRob Rice 			ptr += hash_pad_len;
10509d12ba86SRob Rice 		} else {
10519d12ba86SRob Rice 			/* terminate the data */
10529d12ba86SRob Rice 			*ptr = 0x80;
10539d12ba86SRob Rice 			ptr += (hash_pad_len - sizeof(u64));
10549d12ba86SRob Rice 
10559d12ba86SRob Rice 			/* add the size at the end as required per alg */
10569d12ba86SRob Rice 			if (auth_alg == HASH_ALG_MD5)
10575a17eae4SHerbert Xu 				*(__le64 *)ptr = cpu_to_le64(total_sent * 8ull);
10589d12ba86SRob Rice 			else		/* SHA1, SHA2-224, SHA2-256 */
10595a17eae4SHerbert Xu 				*(__be64 *)ptr = cpu_to_be64(total_sent * 8ull);
10609d12ba86SRob Rice 			ptr += sizeof(u64);
10619d12ba86SRob Rice 		}
10629d12ba86SRob Rice 	}
10639d12ba86SRob Rice 
10649d12ba86SRob Rice 	/* pad to a 4byte alignment for STAT */
10659d12ba86SRob Rice 	if (status_padding > 0) {
10669d12ba86SRob Rice 		flow_log("  STAT: padding to 4 byte alignment: %u bytes\n",
10679d12ba86SRob Rice 			 status_padding);
10689d12ba86SRob Rice 
10699d12ba86SRob Rice 		memset(ptr, 0, status_padding);
10709d12ba86SRob Rice 		ptr += status_padding;
10719d12ba86SRob Rice 	}
10729d12ba86SRob Rice }
10739d12ba86SRob Rice 
10749d12ba86SRob Rice /**
10759d12ba86SRob Rice  * spum_xts_tweak_in_payload() - Indicate that SPUM DOES place the XTS tweak
10769d12ba86SRob Rice  * field in the packet payload (rather than using IV)
10779d12ba86SRob Rice  *
10789d12ba86SRob Rice  * Return: 1
10799d12ba86SRob Rice  */
spum_xts_tweak_in_payload(void)10809d12ba86SRob Rice u8 spum_xts_tweak_in_payload(void)
10819d12ba86SRob Rice {
10829d12ba86SRob Rice 	return 1;
10839d12ba86SRob Rice }
10849d12ba86SRob Rice 
10859d12ba86SRob Rice /**
10869d12ba86SRob Rice  * spum_tx_status_len() - Return the length of the STATUS field in a SPU
10879d12ba86SRob Rice  * response message.
10889d12ba86SRob Rice  *
10899d12ba86SRob Rice  * Return: Length of STATUS field in bytes.
10909d12ba86SRob Rice  */
spum_tx_status_len(void)10919d12ba86SRob Rice u8 spum_tx_status_len(void)
10929d12ba86SRob Rice {
10939d12ba86SRob Rice 	return SPU_TX_STATUS_LEN;
10949d12ba86SRob Rice }
10959d12ba86SRob Rice 
10969d12ba86SRob Rice /**
10979d12ba86SRob Rice  * spum_rx_status_len() - Return the length of the STATUS field in a SPU
10989d12ba86SRob Rice  * response message.
10999d12ba86SRob Rice  *
11009d12ba86SRob Rice  * Return: Length of STATUS field in bytes.
11019d12ba86SRob Rice  */
spum_rx_status_len(void)11029d12ba86SRob Rice u8 spum_rx_status_len(void)
11039d12ba86SRob Rice {
11049d12ba86SRob Rice 	return SPU_RX_STATUS_LEN;
11059d12ba86SRob Rice }
11069d12ba86SRob Rice 
11079d12ba86SRob Rice /**
11089d12ba86SRob Rice  * spum_status_process() - Process the status from a SPU response message.
11099d12ba86SRob Rice  * @statp:  start of STATUS word
11109d12ba86SRob Rice  * Return:
11119d12ba86SRob Rice  *   0 - if status is good and response should be processed
11129d12ba86SRob Rice  *   !0 - status indicates an error and response is invalid
11139d12ba86SRob Rice  */
spum_status_process(u8 * statp)11149d12ba86SRob Rice int spum_status_process(u8 *statp)
11159d12ba86SRob Rice {
11169d12ba86SRob Rice 	u32 status;
11179d12ba86SRob Rice 
11189d12ba86SRob Rice 	status = __be32_to_cpu(*(__be32 *)statp);
11199d12ba86SRob Rice 	flow_log("SPU response STATUS %#08x\n", status);
11209d12ba86SRob Rice 	if (status & SPU_STATUS_ERROR_FLAG) {
11219d12ba86SRob Rice 		pr_err("%s() Warning: Error result from SPU: %#08x\n",
11229d12ba86SRob Rice 		       __func__, status);
11239d12ba86SRob Rice 		if (status & SPU_STATUS_INVALID_ICV)
11249d12ba86SRob Rice 			return SPU_INVALID_ICV;
11259d12ba86SRob Rice 		return -EBADMSG;
11269d12ba86SRob Rice 	}
11279d12ba86SRob Rice 	return 0;
11289d12ba86SRob Rice }
11299d12ba86SRob Rice 
11309d12ba86SRob Rice /**
11319d12ba86SRob Rice  * spum_ccm_update_iv() - Update the IV as per the requirements for CCM mode.
11329d12ba86SRob Rice  *
11339d12ba86SRob Rice  * @digestsize:		Digest size of this request
11349d12ba86SRob Rice  * @cipher_parms:	(pointer to) cipher parmaeters, includes IV buf & IV len
11359d12ba86SRob Rice  * @assoclen:		Length of AAD data
11369d12ba86SRob Rice  * @chunksize:		length of input data to be sent in this req
11379d12ba86SRob Rice  * @is_encrypt:		true if this is an output/encrypt operation
11389d12ba86SRob Rice  * @is_esp:		true if this is an ESP / RFC4309 operation
11399d12ba86SRob Rice  *
11409d12ba86SRob Rice  */
spum_ccm_update_iv(unsigned int digestsize,struct spu_cipher_parms * cipher_parms,unsigned int assoclen,unsigned int chunksize,bool is_encrypt,bool is_esp)11419d12ba86SRob Rice void spum_ccm_update_iv(unsigned int digestsize,
11429d12ba86SRob Rice 			struct spu_cipher_parms *cipher_parms,
11439d12ba86SRob Rice 			unsigned int assoclen,
11449d12ba86SRob Rice 			unsigned int chunksize,
11459d12ba86SRob Rice 			bool is_encrypt,
11469d12ba86SRob Rice 			bool is_esp)
11479d12ba86SRob Rice {
11489d12ba86SRob Rice 	u8 L;		/* L from CCM algorithm, length of plaintext data */
11499d12ba86SRob Rice 	u8 mprime;	/* M' from CCM algo, (M - 2) / 2, where M=authsize */
11509d12ba86SRob Rice 	u8 adata;
11519d12ba86SRob Rice 
11529d12ba86SRob Rice 	if (cipher_parms->iv_len != CCM_AES_IV_SIZE) {
11539d12ba86SRob Rice 		pr_err("%s(): Invalid IV len %d for CCM mode, should be %d\n",
11549d12ba86SRob Rice 		       __func__, cipher_parms->iv_len, CCM_AES_IV_SIZE);
11559d12ba86SRob Rice 		return;
11569d12ba86SRob Rice 	}
11579d12ba86SRob Rice 
11589d12ba86SRob Rice 	/*
11599d12ba86SRob Rice 	 * IV needs to be formatted as follows:
11609d12ba86SRob Rice 	 *
11619d12ba86SRob Rice 	 * |          Byte 0               | Bytes 1 - N | Bytes (N+1) - 15 |
11629d12ba86SRob Rice 	 * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Bits 7 - 0  |    Bits 7 - 0    |
11639d12ba86SRob Rice 	 * | 0 |Ad?|(M - 2) / 2|   L - 1   |    Nonce    | Plaintext Length |
11649d12ba86SRob Rice 	 *
11659d12ba86SRob Rice 	 * Ad? = 1 if AAD present, 0 if not present
11669d12ba86SRob Rice 	 * M = size of auth field, 8, 12, or 16 bytes (SPU-M) -or-
11679d12ba86SRob Rice 	 *                         4, 6, 8, 10, 12, 14, 16 bytes (SPU2)
11689d12ba86SRob Rice 	 * L = Size of Plaintext Length field; Nonce size = 15 - L
11699d12ba86SRob Rice 	 *
11709d12ba86SRob Rice 	 * It appears that the crypto API already expects the L-1 portion
11719d12ba86SRob Rice 	 * to be set in the first byte of the IV, which implicitly determines
11729d12ba86SRob Rice 	 * the nonce size, and also fills in the nonce.  But the other bits
11739d12ba86SRob Rice 	 * in byte 0 as well as the plaintext length need to be filled in.
11749d12ba86SRob Rice 	 *
11759d12ba86SRob Rice 	 * In rfc4309/esp mode, L is not already in the supplied IV and
11769d12ba86SRob Rice 	 * we need to fill it in, as well as move the IV data to be after
11779d12ba86SRob Rice 	 * the salt
11789d12ba86SRob Rice 	 */
11799d12ba86SRob Rice 	if (is_esp) {
11809d12ba86SRob Rice 		L = CCM_ESP_L_VALUE;	/* RFC4309 has fixed L */
11819d12ba86SRob Rice 	} else {
11829d12ba86SRob Rice 		/* L' = plaintext length - 1 so Plaintext length is L' + 1 */
11839d12ba86SRob Rice 		L = ((cipher_parms->iv_buf[0] & CCM_B0_L_PRIME) >>
11849d12ba86SRob Rice 		      CCM_B0_L_PRIME_SHIFT) + 1;
11859d12ba86SRob Rice 	}
11869d12ba86SRob Rice 
11879d12ba86SRob Rice 	mprime = (digestsize - 2) >> 1;  /* M' = (M - 2) / 2 */
11889d12ba86SRob Rice 	adata = (assoclen > 0);  /* adata = 1 if any associated data */
11899d12ba86SRob Rice 
11909d12ba86SRob Rice 	cipher_parms->iv_buf[0] = (adata << CCM_B0_ADATA_SHIFT) |
11919d12ba86SRob Rice 				  (mprime << CCM_B0_M_PRIME_SHIFT) |
11929d12ba86SRob Rice 				  ((L - 1) << CCM_B0_L_PRIME_SHIFT);
11939d12ba86SRob Rice 
11949d12ba86SRob Rice 	/* Nonce is already filled in by crypto API, and is 15 - L bytes */
11959d12ba86SRob Rice 
11969d12ba86SRob Rice 	/* Don't include digest in plaintext size when decrypting */
11979d12ba86SRob Rice 	if (!is_encrypt)
11989d12ba86SRob Rice 		chunksize -= digestsize;
11999d12ba86SRob Rice 
12009d12ba86SRob Rice 	/* Fill in length of plaintext, formatted to be L bytes long */
12019d12ba86SRob Rice 	format_value_ccm(chunksize, &cipher_parms->iv_buf[15 - L + 1], L);
12029d12ba86SRob Rice }
12039d12ba86SRob Rice 
12049d12ba86SRob Rice /**
12059d12ba86SRob Rice  * spum_wordalign_padlen() - Given the length of a data field, determine the
12069d12ba86SRob Rice  * padding required to align the data following this field on a 4-byte boundary.
12079d12ba86SRob Rice  * @data_size: length of data field in bytes
12089d12ba86SRob Rice  *
12099d12ba86SRob Rice  * Return: length of status field padding, in bytes
12109d12ba86SRob Rice  */
spum_wordalign_padlen(u32 data_size)12119d12ba86SRob Rice u32 spum_wordalign_padlen(u32 data_size)
12129d12ba86SRob Rice {
12139d12ba86SRob Rice 	return ((data_size + 3) & ~3) - data_size;
12149d12ba86SRob Rice }
1215