18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2016 Broadcom
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci/*
78c2ecf20Sopenharmony_ci * This file contains the definition of SPU messages. There are currently two
88c2ecf20Sopenharmony_ci * SPU message formats: SPU-M and SPU2. The hardware uses different values to
98c2ecf20Sopenharmony_ci * identify the same things in SPU-M vs SPU2. So this file defines values that
108c2ecf20Sopenharmony_ci * are hardware independent. Software can use these values for any version of
118c2ecf20Sopenharmony_ci * SPU hardware. These values are used in APIs in spu.c. Functions internal to
128c2ecf20Sopenharmony_ci * spu.c and spu2.c convert these to hardware-specific values.
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#ifndef _SPU_H
168c2ecf20Sopenharmony_ci#define _SPU_H
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/types.h>
198c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
208c2ecf20Sopenharmony_ci#include <crypto/sha.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cienum spu_cipher_alg {
238c2ecf20Sopenharmony_ci	CIPHER_ALG_NONE = 0x0,
248c2ecf20Sopenharmony_ci	CIPHER_ALG_RC4 = 0x1,
258c2ecf20Sopenharmony_ci	CIPHER_ALG_DES = 0x2,
268c2ecf20Sopenharmony_ci	CIPHER_ALG_3DES = 0x3,
278c2ecf20Sopenharmony_ci	CIPHER_ALG_AES = 0x4,
288c2ecf20Sopenharmony_ci	CIPHER_ALG_LAST = 0x5
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cienum spu_cipher_mode {
328c2ecf20Sopenharmony_ci	CIPHER_MODE_NONE = 0x0,
338c2ecf20Sopenharmony_ci	CIPHER_MODE_ECB = 0x0,
348c2ecf20Sopenharmony_ci	CIPHER_MODE_CBC = 0x1,
358c2ecf20Sopenharmony_ci	CIPHER_MODE_OFB = 0x2,
368c2ecf20Sopenharmony_ci	CIPHER_MODE_CFB = 0x3,
378c2ecf20Sopenharmony_ci	CIPHER_MODE_CTR = 0x4,
388c2ecf20Sopenharmony_ci	CIPHER_MODE_CCM = 0x5,
398c2ecf20Sopenharmony_ci	CIPHER_MODE_GCM = 0x6,
408c2ecf20Sopenharmony_ci	CIPHER_MODE_XTS = 0x7,
418c2ecf20Sopenharmony_ci	CIPHER_MODE_LAST = 0x8
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cienum spu_cipher_type {
458c2ecf20Sopenharmony_ci	CIPHER_TYPE_NONE = 0x0,
468c2ecf20Sopenharmony_ci	CIPHER_TYPE_DES = 0x0,
478c2ecf20Sopenharmony_ci	CIPHER_TYPE_3DES = 0x0,
488c2ecf20Sopenharmony_ci	CIPHER_TYPE_INIT = 0x0,	/* used for ARC4 */
498c2ecf20Sopenharmony_ci	CIPHER_TYPE_AES128 = 0x0,
508c2ecf20Sopenharmony_ci	CIPHER_TYPE_AES192 = 0x1,
518c2ecf20Sopenharmony_ci	CIPHER_TYPE_UPDT = 0x1,	/* used for ARC4 */
528c2ecf20Sopenharmony_ci	CIPHER_TYPE_AES256 = 0x2,
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cienum hash_alg {
568c2ecf20Sopenharmony_ci	HASH_ALG_NONE = 0x0,
578c2ecf20Sopenharmony_ci	HASH_ALG_MD5 = 0x1,
588c2ecf20Sopenharmony_ci	HASH_ALG_SHA1 = 0x2,
598c2ecf20Sopenharmony_ci	HASH_ALG_SHA224 = 0x3,
608c2ecf20Sopenharmony_ci	HASH_ALG_SHA256 = 0x4,
618c2ecf20Sopenharmony_ci	HASH_ALG_AES = 0x5,
628c2ecf20Sopenharmony_ci	HASH_ALG_SHA384 = 0x6,
638c2ecf20Sopenharmony_ci	HASH_ALG_SHA512 = 0x7,
648c2ecf20Sopenharmony_ci	/* Keep SHA3 algorithms at the end always */
658c2ecf20Sopenharmony_ci	HASH_ALG_SHA3_224 = 0x8,
668c2ecf20Sopenharmony_ci	HASH_ALG_SHA3_256 = 0x9,
678c2ecf20Sopenharmony_ci	HASH_ALG_SHA3_384 = 0xa,
688c2ecf20Sopenharmony_ci	HASH_ALG_SHA3_512 = 0xb,
698c2ecf20Sopenharmony_ci	HASH_ALG_LAST
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cienum hash_mode {
738c2ecf20Sopenharmony_ci	HASH_MODE_NONE = 0x0,
748c2ecf20Sopenharmony_ci	HASH_MODE_HASH = 0x0,
758c2ecf20Sopenharmony_ci	HASH_MODE_XCBC = 0x0,
768c2ecf20Sopenharmony_ci	HASH_MODE_CMAC = 0x1,
778c2ecf20Sopenharmony_ci	HASH_MODE_CTXT = 0x1,
788c2ecf20Sopenharmony_ci	HASH_MODE_HMAC = 0x2,
798c2ecf20Sopenharmony_ci	HASH_MODE_RABIN = 0x4,
808c2ecf20Sopenharmony_ci	HASH_MODE_FHMAC = 0x6,
818c2ecf20Sopenharmony_ci	HASH_MODE_CCM = 0x5,
828c2ecf20Sopenharmony_ci	HASH_MODE_GCM = 0x6,
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cienum hash_type {
868c2ecf20Sopenharmony_ci	HASH_TYPE_NONE = 0x0,
878c2ecf20Sopenharmony_ci	HASH_TYPE_FULL = 0x0,
888c2ecf20Sopenharmony_ci	HASH_TYPE_INIT = 0x1,
898c2ecf20Sopenharmony_ci	HASH_TYPE_UPDT = 0x2,
908c2ecf20Sopenharmony_ci	HASH_TYPE_FIN = 0x3,
918c2ecf20Sopenharmony_ci	HASH_TYPE_AES128 = 0x0,
928c2ecf20Sopenharmony_ci	HASH_TYPE_AES192 = 0x1,
938c2ecf20Sopenharmony_ci	HASH_TYPE_AES256 = 0x2
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cienum aead_type {
978c2ecf20Sopenharmony_ci	AES_CCM,
988c2ecf20Sopenharmony_ci	AES_GCM,
998c2ecf20Sopenharmony_ci	AUTHENC,
1008c2ecf20Sopenharmony_ci	AEAD_TYPE_LAST
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciextern char *hash_alg_name[HASH_ALG_LAST];
1048c2ecf20Sopenharmony_ciextern char *aead_alg_name[AEAD_TYPE_LAST];
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistruct spu_request_opts {
1078c2ecf20Sopenharmony_ci	bool is_inbound;
1088c2ecf20Sopenharmony_ci	bool auth_first;
1098c2ecf20Sopenharmony_ci	bool is_aead;
1108c2ecf20Sopenharmony_ci	bool is_esp;
1118c2ecf20Sopenharmony_ci	bool bd_suppress;
1128c2ecf20Sopenharmony_ci	bool is_rfc4543;
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistruct spu_cipher_parms {
1168c2ecf20Sopenharmony_ci	enum spu_cipher_alg  alg;
1178c2ecf20Sopenharmony_ci	enum spu_cipher_mode mode;
1188c2ecf20Sopenharmony_ci	enum spu_cipher_type type;
1198c2ecf20Sopenharmony_ci	u8                  *key_buf;
1208c2ecf20Sopenharmony_ci	u16                  key_len;
1218c2ecf20Sopenharmony_ci	/* iv_buf and iv_len include salt, if applicable */
1228c2ecf20Sopenharmony_ci	u8                  *iv_buf;
1238c2ecf20Sopenharmony_ci	u16                  iv_len;
1248c2ecf20Sopenharmony_ci};
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistruct spu_hash_parms {
1278c2ecf20Sopenharmony_ci	enum hash_alg  alg;
1288c2ecf20Sopenharmony_ci	enum hash_mode mode;
1298c2ecf20Sopenharmony_ci	enum hash_type type;
1308c2ecf20Sopenharmony_ci	u8             digestsize;
1318c2ecf20Sopenharmony_ci	u8            *key_buf;
1328c2ecf20Sopenharmony_ci	u16            key_len;
1338c2ecf20Sopenharmony_ci	u16            prebuf_len;
1348c2ecf20Sopenharmony_ci	/* length of hash pad. signed, needs to handle roll-overs */
1358c2ecf20Sopenharmony_ci	int            pad_len;
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct spu_aead_parms {
1398c2ecf20Sopenharmony_ci	u32 assoc_size;
1408c2ecf20Sopenharmony_ci	u16 iv_len;      /* length of IV field between assoc data and data */
1418c2ecf20Sopenharmony_ci	u8  aad_pad_len; /* For AES GCM/CCM, length of padding after AAD */
1428c2ecf20Sopenharmony_ci	u8  data_pad_len;/* For AES GCM/CCM, length of padding after data */
1438c2ecf20Sopenharmony_ci	bool return_iv;  /* True if SPU should return an IV */
1448c2ecf20Sopenharmony_ci	u32 ret_iv_len;  /* Length in bytes of returned IV */
1458c2ecf20Sopenharmony_ci	u32 ret_iv_off;  /* Offset into full IV if partial IV returned */
1468c2ecf20Sopenharmony_ci};
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/************** SPU sizes ***************/
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#define SPU_RX_STATUS_LEN  4
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/* Max length of padding for 4-byte alignment of STATUS field */
1538c2ecf20Sopenharmony_ci#define SPU_STAT_PAD_MAX  4
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* Max length of pad fragment. 4 is for 4-byte alignment of STATUS field */
1568c2ecf20Sopenharmony_ci#define SPU_PAD_LEN_MAX (SPU_GCM_CCM_ALIGN + MAX_HASH_BLOCK_SIZE + \
1578c2ecf20Sopenharmony_ci			 SPU_STAT_PAD_MAX)
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/* GCM and CCM require 16-byte alignment */
1608c2ecf20Sopenharmony_ci#define SPU_GCM_CCM_ALIGN 16
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/* Length up SUPDT field in SPU response message for RC4 */
1638c2ecf20Sopenharmony_ci#define SPU_SUPDT_LEN 260
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/* SPU status error codes. These used as common error codes across all
1668c2ecf20Sopenharmony_ci * SPU variants.
1678c2ecf20Sopenharmony_ci */
1688c2ecf20Sopenharmony_ci#define SPU_INVALID_ICV  1
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/* Indicates no limit to the length of the payload in a SPU message */
1718c2ecf20Sopenharmony_ci#define SPU_MAX_PAYLOAD_INF  0xFFFFFFFF
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/* Size of XTS tweak ("i" parameter), in bytes */
1748c2ecf20Sopenharmony_ci#define SPU_XTS_TWEAK_SIZE 16
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/* CCM B_0 field definitions, common for SPU-M and SPU2 */
1778c2ecf20Sopenharmony_ci#define CCM_B0_ADATA		0x40
1788c2ecf20Sopenharmony_ci#define CCM_B0_ADATA_SHIFT	   6
1798c2ecf20Sopenharmony_ci#define CCM_B0_M_PRIME		0x38
1808c2ecf20Sopenharmony_ci#define CCM_B0_M_PRIME_SHIFT	   3
1818c2ecf20Sopenharmony_ci#define CCM_B0_L_PRIME		0x07
1828c2ecf20Sopenharmony_ci#define CCM_B0_L_PRIME_SHIFT	   0
1838c2ecf20Sopenharmony_ci#define CCM_ESP_L_VALUE		   4
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci/**
1868c2ecf20Sopenharmony_ci * spu_req_incl_icv() - Return true if SPU request message should include the
1878c2ecf20Sopenharmony_ci * ICV as a separate buffer.
1888c2ecf20Sopenharmony_ci * @cipher_mode:  the cipher mode being requested
1898c2ecf20Sopenharmony_ci * @is_encrypt:   true if encrypting. false if decrypting.
1908c2ecf20Sopenharmony_ci *
1918c2ecf20Sopenharmony_ci * Return:  true if ICV to be included as separate buffer
1928c2ecf20Sopenharmony_ci */
1938c2ecf20Sopenharmony_cistatic __always_inline  bool spu_req_incl_icv(enum spu_cipher_mode cipher_mode,
1948c2ecf20Sopenharmony_ci					      bool is_encrypt)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	if ((cipher_mode == CIPHER_MODE_GCM) && !is_encrypt)
1978c2ecf20Sopenharmony_ci		return true;
1988c2ecf20Sopenharmony_ci	if ((cipher_mode == CIPHER_MODE_CCM) && !is_encrypt)
1998c2ecf20Sopenharmony_ci		return true;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	return false;
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic __always_inline u32 spu_real_db_size(u32 assoc_size,
2058c2ecf20Sopenharmony_ci					    u32 aead_iv_buf_len,
2068c2ecf20Sopenharmony_ci					    u32 prebuf_len,
2078c2ecf20Sopenharmony_ci					    u32 data_size,
2088c2ecf20Sopenharmony_ci					    u32 aad_pad_len,
2098c2ecf20Sopenharmony_ci					    u32 gcm_pad_len,
2108c2ecf20Sopenharmony_ci					    u32 hash_pad_len)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	return assoc_size + aead_iv_buf_len + prebuf_len + data_size +
2138c2ecf20Sopenharmony_ci	    aad_pad_len + gcm_pad_len + hash_pad_len;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci/************** SPU Functions Prototypes **************/
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_civoid spum_dump_msg_hdr(u8 *buf, unsigned int buf_len);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ciu32 spum_ns2_ctx_max_payload(enum spu_cipher_alg cipher_alg,
2218c2ecf20Sopenharmony_ci			     enum spu_cipher_mode cipher_mode,
2228c2ecf20Sopenharmony_ci			     unsigned int blocksize);
2238c2ecf20Sopenharmony_ciu32 spum_nsp_ctx_max_payload(enum spu_cipher_alg cipher_alg,
2248c2ecf20Sopenharmony_ci			     enum spu_cipher_mode cipher_mode,
2258c2ecf20Sopenharmony_ci			     unsigned int blocksize);
2268c2ecf20Sopenharmony_ciu32 spum_payload_length(u8 *spu_hdr);
2278c2ecf20Sopenharmony_ciu16 spum_response_hdr_len(u16 auth_key_len, u16 enc_key_len, bool is_hash);
2288c2ecf20Sopenharmony_ciu16 spum_hash_pad_len(enum hash_alg hash_alg, enum hash_mode hash_mode,
2298c2ecf20Sopenharmony_ci		      u32 chunksize, u16 hash_block_size);
2308c2ecf20Sopenharmony_ciu32 spum_gcm_ccm_pad_len(enum spu_cipher_mode cipher_mode,
2318c2ecf20Sopenharmony_ci			 unsigned int data_size);
2328c2ecf20Sopenharmony_ciu32 spum_assoc_resp_len(enum spu_cipher_mode cipher_mode,
2338c2ecf20Sopenharmony_ci			unsigned int assoc_len, unsigned int iv_len,
2348c2ecf20Sopenharmony_ci			bool is_encrypt);
2358c2ecf20Sopenharmony_ciu8 spum_aead_ivlen(enum spu_cipher_mode cipher_mode, u16 iv_len);
2368c2ecf20Sopenharmony_cibool spu_req_incl_icv(enum spu_cipher_mode cipher_mode, bool is_encrypt);
2378c2ecf20Sopenharmony_cienum hash_type spum_hash_type(u32 src_sent);
2388c2ecf20Sopenharmony_ciu32 spum_digest_size(u32 alg_digest_size, enum hash_alg alg,
2398c2ecf20Sopenharmony_ci		     enum hash_type htype);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ciu32 spum_create_request(u8 *spu_hdr,
2428c2ecf20Sopenharmony_ci			struct spu_request_opts *req_opts,
2438c2ecf20Sopenharmony_ci			struct spu_cipher_parms *cipher_parms,
2448c2ecf20Sopenharmony_ci			struct spu_hash_parms *hash_parms,
2458c2ecf20Sopenharmony_ci			struct spu_aead_parms *aead_parms,
2468c2ecf20Sopenharmony_ci			unsigned int data_size);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ciu16 spum_cipher_req_init(u8 *spu_hdr, struct spu_cipher_parms *cipher_parms);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_civoid spum_cipher_req_finish(u8 *spu_hdr,
2518c2ecf20Sopenharmony_ci			    u16 spu_req_hdr_len,
2528c2ecf20Sopenharmony_ci			    unsigned int is_inbound,
2538c2ecf20Sopenharmony_ci			    struct spu_cipher_parms *cipher_parms,
2548c2ecf20Sopenharmony_ci			    unsigned int data_size);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_civoid spum_request_pad(u8 *pad_start,
2578c2ecf20Sopenharmony_ci		      u32 gcm_padding,
2588c2ecf20Sopenharmony_ci		      u32 hash_pad_len,
2598c2ecf20Sopenharmony_ci		      enum hash_alg auth_alg,
2608c2ecf20Sopenharmony_ci		      enum hash_mode auth_mode,
2618c2ecf20Sopenharmony_ci		      unsigned int total_sent, u32 status_padding);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ciu8 spum_xts_tweak_in_payload(void);
2648c2ecf20Sopenharmony_ciu8 spum_tx_status_len(void);
2658c2ecf20Sopenharmony_ciu8 spum_rx_status_len(void);
2668c2ecf20Sopenharmony_ciint spum_status_process(u8 *statp);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_civoid spum_ccm_update_iv(unsigned int digestsize,
2698c2ecf20Sopenharmony_ci			struct spu_cipher_parms *cipher_parms,
2708c2ecf20Sopenharmony_ci			unsigned int assoclen,
2718c2ecf20Sopenharmony_ci			unsigned int chunksize,
2728c2ecf20Sopenharmony_ci			bool is_encrypt,
2738c2ecf20Sopenharmony_ci			bool is_esp);
2748c2ecf20Sopenharmony_ciu32 spum_wordalign_padlen(u32 data_size);
2758c2ecf20Sopenharmony_ci#endif
276