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