Commit 9d12ba86 authored by Rob Rice's avatar Rob Rice Committed by Herbert Xu

crypto: brcm - Add Broadcom SPU driver

Add Broadcom Secure Processing Unit (SPU) crypto driver for SPU
hardware crypto offload. The driver supports ablkcipher, ahash,
and aead symmetric crypto operations.
Signed-off-by: default avatarSteve Lin <steven.lin1@broadcom.com>
Signed-off-by: default avatarRob Rice <rob.rice@broadcom.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 206dc4fc
......@@ -587,4 +587,19 @@ source "drivers/crypto/chelsio/Kconfig"
source "drivers/crypto/virtio/Kconfig"
config CRYPTO_DEV_BCM_SPU
tristate "Broadcom symmetric crypto/hash acceleration support"
depends on ARCH_BCM_IPROC
depends on BCM_PDC_MBOX
default m
select CRYPTO_DES
select CRYPTO_MD5
select CRYPTO_SHA1
select CRYPTO_SHA256
select CRYPTO_SHA512
help
This driver provides support for Broadcom crypto acceleration using the
Secure Processing Unit (SPU). The SPU driver registers ablkcipher,
ahash, and aead algorithms with the kernel cryptographic API.
endif # CRYPTO_HW
......@@ -35,3 +35,4 @@ obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/
obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) += bcm/
# File: drivers/crypto/bcm/Makefile
#
# Makefile for crypto acceleration files for Broadcom SPU driver
#
# Uncomment to enable debug tracing in the SPU driver.
# CFLAGS_util.o := -DDEBUG
# CFLAGS_cipher.o := -DDEBUG
# CFLAGS_spu.o := -DDEBUG
# CFLAGS_spu2.o := -DDEBUG
obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) := bcm_crypto_spu.o
bcm_crypto_spu-objs := util.o spu.o spu2.o cipher.o
ccflags-y += -I. -DBCMDRIVER
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2016 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation (the "GPL").
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 (GPLv2) for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 (GPLv2) along with this source code.
*/
/*
* This file contains the definition of SPU messages. There are currently two
* SPU message formats: SPU-M and SPU2. The hardware uses different values to
* identify the same things in SPU-M vs SPU2. So this file defines values that
* are hardware independent. Software can use these values for any version of
* SPU hardware. These values are used in APIs in spu.c. Functions internal to
* spu.c and spu2.c convert these to hardware-specific values.
*/
#ifndef _SPU_H
#define _SPU_H
#include <linux/types.h>
#include <linux/scatterlist.h>
#include <crypto/sha.h>
enum spu_cipher_alg {
CIPHER_ALG_NONE = 0x0,
CIPHER_ALG_RC4 = 0x1,
CIPHER_ALG_DES = 0x2,
CIPHER_ALG_3DES = 0x3,
CIPHER_ALG_AES = 0x4,
CIPHER_ALG_LAST = 0x5
};
enum spu_cipher_mode {
CIPHER_MODE_NONE = 0x0,
CIPHER_MODE_ECB = 0x0,
CIPHER_MODE_CBC = 0x1,
CIPHER_MODE_OFB = 0x2,
CIPHER_MODE_CFB = 0x3,
CIPHER_MODE_CTR = 0x4,
CIPHER_MODE_CCM = 0x5,
CIPHER_MODE_GCM = 0x6,
CIPHER_MODE_XTS = 0x7,
CIPHER_MODE_LAST = 0x8
};
enum spu_cipher_type {
CIPHER_TYPE_NONE = 0x0,
CIPHER_TYPE_DES = 0x0,
CIPHER_TYPE_3DES = 0x0,
CIPHER_TYPE_INIT = 0x0, /* used for ARC4 */
CIPHER_TYPE_AES128 = 0x0,
CIPHER_TYPE_AES192 = 0x1,
CIPHER_TYPE_UPDT = 0x1, /* used for ARC4 */
CIPHER_TYPE_AES256 = 0x2,
};
enum hash_alg {
HASH_ALG_NONE = 0x0,
HASH_ALG_MD5 = 0x1,
HASH_ALG_SHA1 = 0x2,
HASH_ALG_SHA224 = 0x3,
HASH_ALG_SHA256 = 0x4,
HASH_ALG_AES = 0x5,
HASH_ALG_SHA384 = 0x6,
HASH_ALG_SHA512 = 0x7,
/* Keep SHA3 algorithms at the end always */
HASH_ALG_SHA3_224 = 0x8,
HASH_ALG_SHA3_256 = 0x9,
HASH_ALG_SHA3_384 = 0xa,
HASH_ALG_SHA3_512 = 0xb,
HASH_ALG_LAST
};
enum hash_mode {
HASH_MODE_NONE = 0x0,
HASH_MODE_HASH = 0x0,
HASH_MODE_XCBC = 0x0,
HASH_MODE_CMAC = 0x1,
HASH_MODE_CTXT = 0x1,
HASH_MODE_HMAC = 0x2,
HASH_MODE_RABIN = 0x4,
HASH_MODE_FHMAC = 0x6,
HASH_MODE_CCM = 0x5,
HASH_MODE_GCM = 0x6,
};
enum hash_type {
HASH_TYPE_NONE = 0x0,
HASH_TYPE_FULL = 0x0,
HASH_TYPE_INIT = 0x1,
HASH_TYPE_UPDT = 0x2,
HASH_TYPE_FIN = 0x3,
HASH_TYPE_AES128 = 0x0,
HASH_TYPE_AES192 = 0x1,
HASH_TYPE_AES256 = 0x2
};
enum aead_type {
AES_CCM,
AES_GCM,
AUTHENC,
AEAD_TYPE_LAST
};
extern char *hash_alg_name[HASH_ALG_LAST];
extern char *aead_alg_name[AEAD_TYPE_LAST];
struct spu_request_opts {
bool is_inbound;
bool auth_first;
bool is_aead;
bool is_esp;
bool bd_suppress;
bool is_rfc4543;
};
struct spu_cipher_parms {
enum spu_cipher_alg alg;
enum spu_cipher_mode mode;
enum spu_cipher_type type;
u8 *key_buf;
u16 key_len;
/* iv_buf and iv_len include salt, if applicable */
u8 *iv_buf;
u16 iv_len;
};
struct spu_hash_parms {
enum hash_alg alg;
enum hash_mode mode;
enum hash_type type;
u8 digestsize;
u8 *key_buf;
u16 key_len;
u16 prebuf_len;
/* length of hash pad. signed, needs to handle roll-overs */
int pad_len;
};
struct spu_aead_parms {
u32 assoc_size;
u16 iv_len; /* length of IV field between assoc data and data */
u8 aad_pad_len; /* For AES GCM/CCM, length of padding after AAD */
u8 data_pad_len;/* For AES GCM/CCM, length of padding after data */
bool return_iv; /* True if SPU should return an IV */
u32 ret_iv_len; /* Length in bytes of returned IV */
u32 ret_iv_off; /* Offset into full IV if partial IV returned */
};
/************** SPU sizes ***************/
#define SPU_RX_STATUS_LEN 4
/* Max length of padding for 4-byte alignment of STATUS field */
#define SPU_STAT_PAD_MAX 4
/* Max length of pad fragment. 4 is for 4-byte alignment of STATUS field */
#define SPU_PAD_LEN_MAX (SPU_GCM_CCM_ALIGN + MAX_HASH_BLOCK_SIZE + \
SPU_STAT_PAD_MAX)
/* GCM and CCM require 16-byte alignment */
#define SPU_GCM_CCM_ALIGN 16
/* Length up SUPDT field in SPU response message for RC4 */
#define SPU_SUPDT_LEN 260
/* SPU status error codes. These used as common error codes across all
* SPU variants.
*/
#define SPU_INVALID_ICV 1
/* Indicates no limit to the length of the payload in a SPU message */
#define SPU_MAX_PAYLOAD_INF 0xFFFFFFFF
/* Size of XTS tweak ("i" parameter), in bytes */
#define SPU_XTS_TWEAK_SIZE 16
/* CCM B_0 field definitions, common for SPU-M and SPU2 */
#define CCM_B0_ADATA 0x40
#define CCM_B0_ADATA_SHIFT 6
#define CCM_B0_M_PRIME 0x38
#define CCM_B0_M_PRIME_SHIFT 3
#define CCM_B0_L_PRIME 0x07
#define CCM_B0_L_PRIME_SHIFT 0
#define CCM_ESP_L_VALUE 4
/**
* spu_req_incl_icv() - Return true if SPU request message should include the
* ICV as a separate buffer.
* @cipher_mode: the cipher mode being requested
* @is_encrypt: true if encrypting. false if decrypting.
*
* Return: true if ICV to be included as separate buffer
*/
static __always_inline bool spu_req_incl_icv(enum spu_cipher_mode cipher_mode,
bool is_encrypt)
{
if ((cipher_mode == CIPHER_MODE_GCM) && !is_encrypt)
return true;
if ((cipher_mode == CIPHER_MODE_CCM) && !is_encrypt)
return true;
return false;
}
static __always_inline u32 spu_real_db_size(u32 assoc_size,
u32 aead_iv_buf_len,
u32 prebuf_len,
u32 data_size,
u32 aad_pad_len,
u32 gcm_pad_len,
u32 hash_pad_len)
{
return assoc_size + aead_iv_buf_len + prebuf_len + data_size +
aad_pad_len + gcm_pad_len + hash_pad_len;
}
/************** SPU Functions Prototypes **************/
void spum_dump_msg_hdr(u8 *buf, unsigned int buf_len);
u32 spum_ns2_ctx_max_payload(enum spu_cipher_alg cipher_alg,
enum spu_cipher_mode cipher_mode,
unsigned int blocksize);
u32 spum_nsp_ctx_max_payload(enum spu_cipher_alg cipher_alg,
enum spu_cipher_mode cipher_mode,
unsigned int blocksize);
u32 spum_payload_length(u8 *spu_hdr);
u16 spum_response_hdr_len(u16 auth_key_len, u16 enc_key_len, bool is_hash);
u16 spum_hash_pad_len(enum hash_alg hash_alg, enum hash_mode hash_mode,
u32 chunksize, u16 hash_block_size);
u32 spum_gcm_ccm_pad_len(enum spu_cipher_mode cipher_mode,
unsigned int data_size);
u32 spum_assoc_resp_len(enum spu_cipher_mode cipher_mode,
unsigned int assoc_len, unsigned int iv_len,
bool is_encrypt);
u8 spum_aead_ivlen(enum spu_cipher_mode cipher_mode, u16 iv_len);
bool spu_req_incl_icv(enum spu_cipher_mode cipher_mode, bool is_encrypt);
enum hash_type spum_hash_type(u32 src_sent);
u32 spum_digest_size(u32 alg_digest_size, enum hash_alg alg,
enum hash_type htype);
u32 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);
u16 spum_cipher_req_init(u8 *spu_hdr, struct spu_cipher_parms *cipher_parms);
void spum_cipher_req_finish(u8 *spu_hdr,
u16 spu_req_hdr_len,
unsigned int is_inbound,
struct spu_cipher_parms *cipher_parms,
bool update_key,
unsigned int data_size);
void spum_request_pad(u8 *pad_start,
u32 gcm_padding,
u32 hash_pad_len,
enum hash_alg auth_alg,
enum hash_mode auth_mode,
unsigned int total_sent, u32 status_padding);
u8 spum_xts_tweak_in_payload(void);
u8 spum_tx_status_len(void);
u8 spum_rx_status_len(void);
int spum_status_process(u8 *statp);
void 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);
u32 spum_wordalign_padlen(u32 data_size);
#endif
This diff is collapsed.
/*
* Copyright 2016 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation (the "GPL").
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 (GPLv2) for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 (GPLv2) along with this source code.
*/
/*
* This file contains SPU message definitions specific to SPU2.
*/
#ifndef _SPU2_H
#define _SPU2_H
enum spu2_cipher_type {
SPU2_CIPHER_TYPE_NONE = 0x0,
SPU2_CIPHER_TYPE_AES128 = 0x1,
SPU2_CIPHER_TYPE_AES192 = 0x2,
SPU2_CIPHER_TYPE_AES256 = 0x3,
SPU2_CIPHER_TYPE_DES = 0x4,
SPU2_CIPHER_TYPE_3DES = 0x5,
SPU2_CIPHER_TYPE_LAST
};
enum spu2_cipher_mode {
SPU2_CIPHER_MODE_ECB = 0x0,
SPU2_CIPHER_MODE_CBC = 0x1,
SPU2_CIPHER_MODE_CTR = 0x2,
SPU2_CIPHER_MODE_CFB = 0x3,
SPU2_CIPHER_MODE_OFB = 0x4,
SPU2_CIPHER_MODE_XTS = 0x5,
SPU2_CIPHER_MODE_CCM = 0x6,
SPU2_CIPHER_MODE_GCM = 0x7,
SPU2_CIPHER_MODE_LAST
};
enum spu2_hash_type {
SPU2_HASH_TYPE_NONE = 0x0,
SPU2_HASH_TYPE_AES128 = 0x1,
SPU2_HASH_TYPE_AES192 = 0x2,
SPU2_HASH_TYPE_AES256 = 0x3,
SPU2_HASH_TYPE_MD5 = 0x6,
SPU2_HASH_TYPE_SHA1 = 0x7,
SPU2_HASH_TYPE_SHA224 = 0x8,
SPU2_HASH_TYPE_SHA256 = 0x9,
SPU2_HASH_TYPE_SHA384 = 0xa,
SPU2_HASH_TYPE_SHA512 = 0xb,
SPU2_HASH_TYPE_SHA512_224 = 0xc,
SPU2_HASH_TYPE_SHA512_256 = 0xd,
SPU2_HASH_TYPE_SHA3_224 = 0xe,
SPU2_HASH_TYPE_SHA3_256 = 0xf,
SPU2_HASH_TYPE_SHA3_384 = 0x10,
SPU2_HASH_TYPE_SHA3_512 = 0x11,
SPU2_HASH_TYPE_LAST
};
enum spu2_hash_mode {
SPU2_HASH_MODE_CMAC = 0x0,
SPU2_HASH_MODE_CBC_MAC = 0x1,
SPU2_HASH_MODE_XCBC_MAC = 0x2,
SPU2_HASH_MODE_HMAC = 0x3,
SPU2_HASH_MODE_RABIN = 0x4,
SPU2_HASH_MODE_CCM = 0x5,
SPU2_HASH_MODE_GCM = 0x6,
SPU2_HASH_MODE_RESERVED = 0x7,
SPU2_HASH_MODE_LAST
};
enum spu2_ret_md_opts {
SPU2_RET_NO_MD = 0, /* return no metadata */
SPU2_RET_FMD_OMD = 1, /* return both FMD and OMD */
SPU2_RET_FMD_ONLY = 2, /* return only FMD */
SPU2_RET_FMD_OMD_IV = 3, /* return FMD and OMD with just IVs */
};
/* Fixed Metadata format */
struct SPU2_FMD {
u64 ctrl0;
u64 ctrl1;
u64 ctrl2;
u64 ctrl3;
};
#define FMD_SIZE sizeof(struct SPU2_FMD)
/* Fixed part of request message header length in bytes. Just FMD. */
#define SPU2_REQ_FIXED_LEN FMD_SIZE
#define SPU2_HEADER_ALLOC_LEN (SPU_REQ_FIXED_LEN + \
2 * MAX_KEY_SIZE + 2 * MAX_IV_SIZE)
/* FMD ctrl0 field masks */
#define SPU2_CIPH_ENCRYPT_EN 0x1 /* 0: decrypt, 1: encrypt */
#define SPU2_CIPH_TYPE 0xF0 /* one of spu2_cipher_type */
#define SPU2_CIPH_TYPE_SHIFT 4
#define SPU2_CIPH_MODE 0xF00 /* one of spu2_cipher_mode */
#define SPU2_CIPH_MODE_SHIFT 8
#define SPU2_CFB_MASK 0x7000 /* cipher feedback mask */
#define SPU2_CFB_MASK_SHIFT 12
#define SPU2_PROTO_SEL 0xF00000 /* MACsec, IPsec, TLS... */
#define SPU2_PROTO_SEL_SHIFT 20
#define SPU2_HASH_FIRST 0x1000000 /* 1: hash input is input pkt
* data
*/
#define SPU2_CHK_TAG 0x2000000 /* 1: check digest provided */
#define SPU2_HASH_TYPE 0x1F0000000 /* one of spu2_hash_type */
#define SPU2_HASH_TYPE_SHIFT 28
#define SPU2_HASH_MODE 0xF000000000 /* one of spu2_hash_mode */
#define SPU2_HASH_MODE_SHIFT 36
#define SPU2_CIPH_PAD_EN 0x100000000000 /* 1: Add pad to end of payload for
* enc
*/
#define SPU2_CIPH_PAD 0xFF000000000000 /* cipher pad value */
#define SPU2_CIPH_PAD_SHIFT 48
/* FMD ctrl1 field masks */
#define SPU2_TAG_LOC 0x1 /* 1: end of payload, 0: undef */
#define SPU2_HAS_FR_DATA 0x2 /* 1: msg has frame data */
#define SPU2_HAS_AAD1 0x4 /* 1: msg has AAD1 field */
#define SPU2_HAS_NAAD 0x8 /* 1: msg has NAAD field */
#define SPU2_HAS_AAD2 0x10 /* 1: msg has AAD2 field */
#define SPU2_HAS_ESN 0x20 /* 1: msg has ESN field */
#define SPU2_HASH_KEY_LEN 0xFF00 /* len of hash key in bytes.
* HMAC only.
*/
#define SPU2_HASH_KEY_LEN_SHIFT 8
#define SPU2_CIPH_KEY_LEN 0xFF00000 /* len of cipher key in bytes */
#define SPU2_CIPH_KEY_LEN_SHIFT 20
#define SPU2_GENIV 0x10000000 /* 1: hw generates IV */
#define SPU2_HASH_IV 0x20000000 /* 1: IV incl in hash */
#define SPU2_RET_IV 0x40000000 /* 1: return IV in output msg
* b4 payload
*/
#define SPU2_RET_IV_LEN 0xF00000000 /* length in bytes of IV returned.
* 0 = 16 bytes
*/
#define SPU2_RET_IV_LEN_SHIFT 32
#define SPU2_IV_OFFSET 0xF000000000 /* gen IV offset */
#define SPU2_IV_OFFSET_SHIFT 36
#define SPU2_IV_LEN 0x1F0000000000 /* length of input IV in bytes */
#define SPU2_IV_LEN_SHIFT 40
#define SPU2_HASH_TAG_LEN 0x7F000000000000 /* hash tag length in bytes */
#define SPU2_HASH_TAG_LEN_SHIFT 48
#define SPU2_RETURN_MD 0x300000000000000 /* return metadata */
#define SPU2_RETURN_MD_SHIFT 56
#define SPU2_RETURN_FD 0x400000000000000
#define SPU2_RETURN_AAD1 0x800000000000000
#define SPU2_RETURN_NAAD 0x1000000000000000
#define SPU2_RETURN_AAD2 0x2000000000000000
#define SPU2_RETURN_PAY 0x4000000000000000 /* return payload */
/* FMD ctrl2 field masks */
#define SPU2_AAD1_OFFSET 0xFFF /* byte offset of AAD1 field */
#define SPU2_AAD1_LEN 0xFF000 /* length of AAD1 in bytes */
#define SPU2_AAD1_LEN_SHIFT 12
#define SPU2_AAD2_OFFSET 0xFFF00000 /* byte offset of AAD2 field */
#define SPU2_AAD2_OFFSET_SHIFT 20
#define SPU2_PL_OFFSET 0xFFFFFFFF00000000 /* payload offset from AAD2 */
#define SPU2_PL_OFFSET_SHIFT 32
/* FMD ctrl3 field masks */
#define SPU2_PL_LEN 0xFFFFFFFF /* payload length in bytes */
#define SPU2_TLS_LEN 0xFFFF00000000 /* TLS encrypt: cipher len
* TLS decrypt: compressed len
*/
#define SPU2_TLS_LEN_SHIFT 32
/*
* Max value that can be represented in the Payload Length field of the
* ctrl3 word of FMD.
*/
#define SPU2_MAX_PAYLOAD SPU2_PL_LEN
/* Error values returned in STATUS field of response messages */
#define SPU2_INVALID_ICV 1
void spu2_dump_msg_hdr(u8 *buf, unsigned int buf_len);
u32 spu2_ctx_max_payload(enum spu_cipher_alg cipher_alg,
enum spu_cipher_mode cipher_mode,
unsigned int blocksize);
u32 spu2_payload_length(u8 *spu_hdr);
u16 spu2_response_hdr_len(u16 auth_key_len, u16 enc_key_len, bool is_hash);
u16 spu2_hash_pad_len(enum hash_alg hash_alg, enum hash_mode hash_mode,
u32 chunksize, u16 hash_block_size);
u32 spu2_gcm_ccm_pad_len(enum spu_cipher_mode cipher_mode,
unsigned int data_size);
u32 spu2_assoc_resp_len(enum spu_cipher_mode cipher_mode,
unsigned int assoc_len, unsigned int iv_len,
bool is_encrypt);
u8 spu2_aead_ivlen(enum spu_cipher_mode cipher_mode,
u16 iv_len);
enum hash_type spu2_hash_type(u32 src_sent);
u32 spu2_digest_size(u32 alg_digest_size, enum hash_alg alg,
enum hash_type htype);
u32 spu2_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);
u16 spu2_cipher_req_init(u8 *spu_hdr, struct spu_cipher_parms *cipher_parms);
void spu2_cipher_req_finish(u8 *spu_hdr,
u16 spu_req_hdr_len,
unsigned int is_inbound,
struct spu_cipher_parms *cipher_parms,
bool update_key,
unsigned int data_size);
void spu2_request_pad(u8 *pad_start, u32 gcm_padding, u32 hash_pad_len,
enum hash_alg auth_alg, enum hash_mode auth_mode,
unsigned int total_sent, u32 status_padding);
u8 spu2_xts_tweak_in_payload(void);
u8 spu2_tx_status_len(void);
u8 spu2_rx_status_len(void);
int spu2_status_process(u8 *statp);
void spu2_ccm_update_iv(unsigned int digestsize,
struct spu_cipher_parms *cipher_parms,
unsigned int assoclen, unsigned int chunksize,
bool is_encrypt, bool is_esp);
u32 spu2_wordalign_padlen(u32 data_size);
#endif
/*
* Copyright 2016 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation (the "GPL").
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 (GPLv2) for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 (GPLv2) along with this source code.
*/
/*
* This file contains SPU message definitions specific to SPU-M.
*/
#ifndef _SPUM_H_
#define _SPUM_H_
#define SPU_CRYPTO_OPERATION_GENERIC 0x1
/* Length of STATUS field in tx and rx packets */
#define SPU_TX_STATUS_LEN 4
/* SPU-M error codes */
#define SPU_STATUS_MASK 0x0000FF00
#define SPU_STATUS_SUCCESS 0x00000000
#define SPU_STATUS_INVALID_ICV 0x00000100
#define SPU_STATUS_ERROR_FLAG 0x00020000
/* Request message. MH + EMH + BDESC + BD header */
#define SPU_REQ_FIXED_LEN 24
/*
* Max length of a SPU message header. Used to allocate a buffer where
* the SPU message header is constructed. Can be used for either a SPU-M
* header or a SPU2 header.
* For SPU-M, sum of the following:
* MH - 4 bytes
* EMH - 4
* SCTX - 3 +
* max auth key len - 64
* max cipher key len - 264 (RC4)
* max IV len - 16
* BDESC - 12
* BD header - 4
* Total: 371
*
* For SPU2, FMD_SIZE (32) plus lengths of hash and cipher keys,
* hash and cipher IVs. If SPU2 does not support RC4, then
*/
#define SPU_HEADER_ALLOC_LEN (SPU_REQ_FIXED_LEN + MAX_KEY_SIZE + \
MAX_KEY_SIZE + MAX_IV_SIZE)
/*
* Response message header length. Normally MH, EMH, BD header, but when
* BD_SUPPRESS is used for hash requests, there is no BD header.
*/
#define SPU_RESP_HDR_LEN 12
#define SPU_HASH_RESP_HDR_LEN 8
/*
* Max value that can be represented in the Payload Length field of the BD
* header. This is a 16-bit field.
*/
#define SPUM_NS2_MAX_PAYLOAD (BIT(16) - 1)
/*
* NSP SPU is limited to ~9KB because of FA2 FIFO size limitations;
* Set MAX_PAYLOAD to 8k to allow for addition of header, digest, etc.
* and stay within limitation.
*/
#define SPUM_NSP_MAX_PAYLOAD 8192
/* Buffer Descriptor Header [BDESC]. SPU in big-endian mode. */
struct BDESC_HEADER {
u16 offset_mac; /* word 0 [31-16] */
u16 length_mac; /* word 0 [15-0] */
u16 offset_crypto; /* word 1 [31-16] */
u16 length_crypto; /* word 1 [15-0] */
u16 offset_icv; /* word 2 [31-16] */
u16 offset_iv; /* word 2 [15-0] */
};
/* Buffer Data Header [BD]. SPU in big-endian mode. */
struct BD_HEADER {
u16 size;
u16 prev_length;
};
/* Command Context Header. SPU-M in big endian mode. */
struct MHEADER {
u8 flags; /* [31:24] */
u8 op_code; /* [23:16] */
u16 reserved; /* [15:0] */
};
/* MH header flags bits */
#define MH_SUPDT_PRES BIT(0)
#define MH_HASH_PRES BIT(2)
#define MH_BD_PRES BIT(3)
#define MH_MFM_PRES BIT(4)
#define MH_BDESC_PRES BIT(5)
#define MH_SCTX_PRES BIT(7)
/* SCTX word 0 bit offsets and fields masks */
#define SCTX_SIZE 0x000000FF
/* SCTX word 1 bit shifts and field masks */
#define UPDT_OFST 0x000000FF /* offset of SCTX updateable fld */
#define HASH_TYPE 0x00000300 /* hash alg operation type */
#define HASH_TYPE_SHIFT 8
#define HASH_MODE 0x00001C00 /* one of spu2_hash_mode */
#define HASH_MODE_SHIFT 10
#define HASH_ALG 0x0000E000 /* hash algorithm */
#define HASH_ALG_SHIFT 13
#define CIPHER_TYPE 0x00030000 /* encryption operation type */
#define CIPHER_TYPE_SHIFT 16
#define CIPHER_MODE 0x001C0000 /* encryption mode */
#define CIPHER_MODE_SHIFT 18
#define CIPHER_ALG 0x00E00000 /* encryption algo */
#define CIPHER_ALG_SHIFT 21
#define ICV_IS_512 BIT(27)
#define ICV_IS_512_SHIFT 27
#define CIPHER_ORDER BIT(30)
#define CIPHER_ORDER_SHIFT 30
#define CIPHER_INBOUND BIT(31)
#define CIPHER_INBOUND_SHIFT 31
/* SCTX word 2 bit shifts and field masks */
#define EXP_IV_SIZE 0x7
#define IV_OFFSET BIT(3)
#define IV_OFFSET_SHIFT 3
#define GEN_IV BIT(5)
#define GEN_IV_SHIFT 5
#define EXPLICIT_IV BIT(6)
#define EXPLICIT_IV_SHIFT 6
#define SCTX_IV BIT(7)
#define SCTX_IV_SHIFT 7
#define ICV_SIZE 0x0F00
#define ICV_SIZE_SHIFT 8
#define CHECK_ICV BIT(12)
#define CHECK_ICV_SHIFT 12
#define INSERT_ICV BIT(13)
#define INSERT_ICV_SHIFT 13
#define BD_SUPPRESS BIT(19)
#define BD_SUPPRESS_SHIFT 19
/* Generic Mode Security Context Structure [SCTX] */
struct SCTX {
/* word 0: protocol flags */
u32 proto_flags;
/* word 1: cipher flags */
u32 cipher_flags;
/* word 2: Extended cipher flags */
u32 ecf;
};
struct SPUHEADER {
struct MHEADER mh;
u32 emh;
struct SCTX sa;
};
#endif /* _SPUM_H_ */
This diff is collapsed.
/*
* Copyright 2016 Broadcom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation (the "GPL").
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 (GPLv2) for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 (GPLv2) along with this source code.
*/
#ifndef _UTIL_H
#define _UTIL_H
#include <linux/kernel.h>
#include <linux/delay.h>
#include "spu.h"
extern int flow_debug_logging;
extern int packet_debug_logging;
extern int debug_logging_sleep;
#ifdef DEBUG
#define flow_log(...) \
do { \
if (flow_debug_logging) { \
printk(__VA_ARGS__); \
if (debug_logging_sleep) \
msleep(debug_logging_sleep); \
} \
} while (0)
#define flow_dump(msg, var, var_len) \
do { \
if (flow_debug_logging) { \
print_hex_dump(KERN_ALERT, msg, DUMP_PREFIX_NONE, \
16, 1, var, var_len, false); \
if (debug_logging_sleep) \
msleep(debug_logging_sleep); \
} \
} while (0)
#define packet_log(...) \
do { \
if (packet_debug_logging) { \
printk(__VA_ARGS__); \
if (debug_logging_sleep) \
msleep(debug_logging_sleep); \
} \
} while (0)
#define packet_dump(msg, var, var_len) \
do { \
if (packet_debug_logging) { \
print_hex_dump(KERN_ALERT, msg, DUMP_PREFIX_NONE, \
16, 1, var, var_len, false); \
if (debug_logging_sleep) \
msleep(debug_logging_sleep); \
} \
} while (0)
void __dump_sg(struct scatterlist *sg, unsigned int skip, unsigned int len);
#define dump_sg(sg, skip, len) __dump_sg(sg, skip, len)
#else /* !DEBUG_ON */
#define flow_log(...) do {} while (0)
#define flow_dump(msg, var, var_len) do {} while (0)
#define packet_log(...) do {} while (0)
#define packet_dump(msg, var, var_len) do {} while (0)
#define dump_sg(sg, skip, len) do {} while (0)
#endif /* DEBUG_ON */
int spu_sg_at_offset(struct scatterlist *sg, unsigned int skip,
struct scatterlist **sge, unsigned int *sge_offset);
/* Copy sg data, from skip, length len, to dest */
void sg_copy_part_to_buf(struct scatterlist *src, u8 *dest,
unsigned int len, unsigned int skip);
/* Copy src into scatterlist from offset, length len */
void sg_copy_part_from_buf(struct scatterlist *dest, u8 *src,
unsigned int len, unsigned int skip);
int spu_sg_count(struct scatterlist *sg_list, unsigned int skip, int nbytes);
u32 spu_msg_sg_add(struct scatterlist **to_sg,
struct scatterlist **from_sg, u32 *skip,
u8 from_nents, u32 tot_len);
void add_to_ctr(u8 *ctr_pos, unsigned int increment);
/* do a synchronous decrypt operation */
int do_decrypt(char *alg_name,
void *key_ptr, unsigned int key_len,
void *iv_ptr, void *src_ptr, void *dst_ptr,
unsigned int block_len);
/* produce a message digest from data of length n bytes */
int do_shash(unsigned char *name, unsigned char *result,
const u8 *data1, unsigned int data1_len,
const u8 *data2, unsigned int data2_len,
const u8 *key, unsigned int key_len);
char *spu_alg_name(enum spu_cipher_alg alg, enum spu_cipher_mode mode);
void spu_setup_debugfs(void);
void spu_free_debugfs(void);
void format_value_ccm(unsigned int val, u8 *buf, u8 len);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment