blob: d248ea1f9b49974fa29738db177b0c4d745a036f [file] [log] [blame]
/*
* Copyright (c) 2009 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef _MODULE_IPSEC_H_
#define _MODULE_IPSEC_H_
#include "fe.h"
#include "common_hdrs.h" /* For ipv4 header structure */
/*
* * IPSEC_DEBUG - if not defined or defined to 0 disables debug instrumentation such as drop counters
* * */
#if !defined(IPSEC_DEBUG)
#define IPSEC_DEBUG 0
#endif
/* Codes for proto_family:
It copies from linux and equal to AF_INET/AF_INET6
*/
#define PROTO_FAMILY_IPV4 2
#define PROTO_FAMILY_IPV6 10
#define IPSEC_MAX_KEY_SIZE (256 /8)
#define IPSEC_MAX_NUM_KEYS 2
/******************************
* * IPSec API Command strutures
* *
* ******************************/
/* Authentication algorithms */
#define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 2
#define SADB_AALG_SHA1HMAC 3
#define SADB_X_AALG_SHA2_256HMAC 5
#define SADB_X_AALG_SHA2_384HMAC 6
#define SADB_X_AALG_SHA2_512HMAC 7
#define SADB_X_AALG_RIPEMD160HMAC 8
#define SADB_X_AALG_AES_XCBC_MAC 9
#define SADB_X_AALG_NULL 251 /* kame */
#define SADB_AALG_MAX 251
/* Encryption algorithms */
#define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 2
#define SADB_EALG_3DESCBC 3
#define SADB_X_EALG_CASTCBC 6
#define SADB_X_EALG_BLOWFISHCBC 7
#define SADB_EALG_NULL 11
#define SADB_X_EALG_AESCBC 12
#define SADB_X_EALG_AESCTR 13
#define SADB_X_EALG_AES_CCM_ICV8 14
#define SADB_X_EALG_AES_CCM_ICV12 15
#define SADB_X_EALG_AES_CCM_ICV16 16
#define SADB_X_EALG_AES_GCM_ICV8 18
#define SADB_X_EALG_AES_GCM_ICV12 19
#define SADB_X_EALG_AES_GCM_ICV16 20
/* AESGCM - 18/19/20 */
#define SADB_X_EALG_CAMELLIACBC 22
#define SADB_EALG_MAX 253 /* last EALG */
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
#define SADB_X_EALG_TWOFISHCBC 253 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
typedef struct _tIPSec_said {
unsigned int spi;
unsigned char sa_type;
unsigned char proto_family;
unsigned char replay_window;
#define NLKEY_SAFLAGS_ESN 0x1
unsigned char flags;
unsigned int dst_ip[4];
unsigned int src_ip[4]; // added for NAT-T transport mode
unsigned short mtu;
unsigned short dev_mtu;
}IPSec_said, *PIPSec_said;
typedef struct _tIPSec_key_desc {
unsigned short key_bits;
unsigned char key_alg;
unsigned char key_type;
unsigned char key[IPSEC_MAX_KEY_SIZE];
}IPSec_key_desc, *PIPSec_key_desc;
typedef struct _tIPSec_lifetime {
unsigned int allocations;
unsigned int bytes[2];
}IPSec_lifetime, *PIPSec_lifetime;
typedef struct _tCommandIPSecCreateSA {
unsigned short sagd;
unsigned short rsvd;
IPSec_said said;
}CommandIPSecCreateSA, *PCommandIPSecCreateSA;
typedef struct _tCommandIPSecDeleteSA {
unsigned short sagd;
unsigned short rsvd;
}CommandIPSecDeleteSA, *PCommandIPSecDeleteSA;
typedef struct _tCommandIPSecSetKey {
unsigned short sagd;
unsigned short rsvd;
unsigned short num_keys;
unsigned short rsvd2;
IPSec_key_desc keys[IPSEC_MAX_NUM_KEYS];
}CommandIPSecSetKey, *PCommandIPSecSetKey;
typedef struct _tCommandIPSecSetNatt {
unsigned short sagd;
unsigned short sport;
unsigned short dport;
unsigned short rsvd;
}CommandIPSecSetNatt, *PCommandIPSecSetNatt;
typedef struct _tCommandIPSecSetState {
unsigned short sagd;
unsigned short rsvd;
unsigned short state;
unsigned short rsvd2;
}CommandIPSecSetState, *PCommandIPSecSetState;
typedef struct _tCommandIPSecSetTunnel {
unsigned short sagd;
unsigned char rsvd;
unsigned char proto_family;
union {
ipv4_hdr_t ipv4h;
ipv6_hdr_t ipv6h;
} h;
}CommandIPSecSetTunnel, *PCommandIPSecSetTunnel;
typedef struct _tCommandIPSecSetLifetime{
unsigned short sagd;
unsigned short rsvd;
IPSec_lifetime hard_time;
IPSec_lifetime soft_time;
IPSec_lifetime current_time;
}CommandIPSecSetLifetime, *PCommandIPSecSetLifetime;
typedef struct _tCommandIPSecExpireNotify{
unsigned short sagd;
unsigned short rsvd;
unsigned int action;
}CommandIPSecExpireNotify, *PCommandIPSecExpireNotify;
typedef struct _tCommandIPSecSetPreFrag {
unsigned short pre_frag_en;
unsigned short reserved;
} CommandIPSecSetPreFrag, *PCommandIPSecSetPreFrag;
typedef struct _tSAQueryCommand {
unsigned short action;
unsigned short handle; /* handle */
/*SPI information */
unsigned short mtu; /* mtu configured */
unsigned short rsvd1;
unsigned int spi; /* spi */
unsigned char sa_type; /* SA TYPE Prtocol ESP/AH */
unsigned char family; /* Protocol Family */
unsigned char mode; /* Tunnel/Transport mode */
unsigned char replay_window; /* Replay Window */
unsigned int dst_ip[4];
unsigned int src_ip[4];
/* Key information */
unsigned char key_alg;
unsigned char state; /* SA VALID /EXPIRED / DEAD/ DYING */
unsigned short flags; /* ESP AH enabled /disabled */
unsigned char cipher_key[32];
unsigned char auth_key[20];
unsigned char ext_auth_key[12];
/* Tunnel Information */
unsigned char tunnel_proto_family;
unsigned char rsvd[3];
union {
ipv4_hdr_t ipv4;
ipv6_hdr_t ipv6;
} __attribute__((packed)) tnl;
U64 soft_byte_limit;
U64 hard_byte_limit;
U64 soft_packet_limit;
U64 hard_packet_limit;
} __attribute__((packed)) SAQueryCommand, *PSAQueryCommand;
#if !defined(COMCERTO_2000)
U16 M_ipsec_cmdproc(U16 cmd_code, U16 cmd_len, U16 *pcmd);
static int IPsec_handle_CREATE_SA(U16 *p, U16 Length);
static int IPsec_handle_DELETE_SA(U16 *p, U16 Length);
static int IPsec_handle_FLUSH_SA(U16 *p, U16 Length);
static int IPsec_handle_SA_SET_KEYS(U16 *p, U16 Length);
static int IPsec_handle_SA_SET_TUNNEL(U16 *p, U16 Length);
static int IPsec_handle_SA_SET_NATT(U16 *p, U16 Length);
static int IPsec_handle_SA_SET_STATE(U16 *p, U16 Length);
static int IPsec_handle_SA_SET_LIFETIME(U16 *p, U16 Length);
static int IPsec_handle_FRAG_CFG(U16 *p, U16 Length);
#endif
/* Debugging */
/*
Display memory command
*/
typedef struct _tDMCommand {
unsigned short pad_in_rc_out; /* Padding - retcode */
unsigned short length; /* Lenght of memory to display < 224 bytes
** returns length being displayed in response */
unsigned int address; /* msp address of memory to display
** returns address being displayed in response */
} DMCommand, *PDMCommand;
U16 M_ipsec_debug(U16 cmd_code, U16 cmd_len, U16 *pcmd);
__inline void read_random(unsigned char *p_result, unsigned int rlen);
#if defined(IPSEC_DEBUG) && (IPSEC_DEBUG)
# define IPSEC_DBG(x) do { x} while(0)
#else
# define IPSEC_DBG(x)
#endif
/****** IPSEC related common structures *****/
static __inline U16 HASH_SA(U32 *Daddr, U32 spi, U16 Proto, U8 family)
{
U16 sum;
U32 tmp32;
tmp32 = ntohl(Daddr[0]) ^ ntohl(Daddr[1]) ^ ntohl(spi);
sum = (tmp32 >> 16) + (tmp32 & 0xffff) + Proto;
return ((sum ^ (sum >> 8)) & (NUM_SA_ENTRIES - 1));
}
#define SA_MAX_OP 2 // maximum of stackable SA (ESP+AH)
typedef struct AH_HDR_STRUCT
{
U8 nexthdr;
U8 hdrlen; /* This one is measured in 32 bit units! */
U16 reserved;
U32 spi;
U32 seq_no; /* Sequence number */
U8 auth_data[4]; /* Variable len but >=4. Mind the 64 bit alignment! */
} ip_ah_hdr ;
typedef struct ESP_HDR_STRUCT
{
U32 spi;
U32 seq_no;
U32 enc_data[1];
} ip_esp_hdr;
/* from Linux XFRM stack... (should we use PF_KEY value instead ?) */
enum {
XFRM_STATE_VOID,
XFRM_STATE_ACQ,
XFRM_STATE_VALID,
XFRM_STATE_ERROR,
XFRM_STATE_EXPIRED,
XFRM_STATE_DEAD
};
#define SA_MODE_TUNNEL 0x1
#define SA_MODE_TRANSPORT 0x0
typedef struct _tSA_lft_conf {
U64 soft_byte_limit;
U64 hard_byte_limit;
U64 soft_packet_limit;
U64 hard_packet_limit;
} SA_lft_conf, *PSA_lft_conf;
/*
* Scatter/Gather data descriptor table.
*/
struct elp_ddtdesc {
/* volatile */U32 frag_addr;
/* volatile */U32 frag_size;
};
#if defined(COMCERTO_100)
#include "module_ipsec_c100.h"
#elif defined(COMCERTO_1000)
#include "module_ipsec_c1000.h"
#elif defined(COMCERTO_2000)
#include "module_ipsec_c2000.h"
#endif
#if defined(COMCERTO_2000_CONTROL)
void* M_ipsec_sa_cache_lookup_by_spi(U32 *daddr, U32 spi, U8 proto, U8 family);
void* M_ipsec_sa_cache_lookup_by_h(U16 handle);
extern struct slist_head sa_cache_by_spi[];
extern struct slist_head sa_cache_by_h[];
#elif defined(COMCERTO_2000_CLASS)
PSAEntry M_ipsec_sa_cache_lookup_by_spi(U32 *daddr, U32 spi, U8 proto, U8 family);
PSAEntry M_ipsec_sa_cache_lookup_by_h(U16 handle, PSAEntry);
extern PSAEntry sa_cache_by_spi[];
extern PSAEntry sa_cache_by_h[];
#elif defined(COMCERTO_2000_UTIL)
PSAEntry M_ipsec_sa_cache_lookup_by_h(U16 handle, PSAEntry);
extern PSAEntry sa_cache_by_h[];
#else
void* M_ipsec_sa_cache_lookup_by_spi(U32 *daddr, U32 spi, U8 proto, U8 family);
void* M_ipsec_sa_cache_lookup_by_h(U16 handle);
extern struct slist_head sa_cache_by_spi[];
extern struct slist_head sa_cache_by_h[];
#endif
/* NAT-T implementation */
extern PNatt_Socket_v6 gNatt_Sock_v6_cache[];
extern PNatt_Socket_v4 gNatt_Sock_v4_cache[];
/****** IPSEC related common structures *****/
/*
* * Codes
* */
#define ELP_HMAC_NULL 0
#define ELP_HMAC_MD5 1
#define ELP_HMAC_SHA1 2
#define ELP_HMAC_SHA2 3
#define ELP_GCM64 4
#define ELP_GCM96 5
#define ELP_GCM128 6
#define ELP_CIPHER_NULL 0
#define ELP_CIPHER_DES 1
#define ELP_CIPHER_3DES 2
#define ELP_CIPHER_AES128 3
#define ELP_CIPHER_AES192 4
#define ELP_CIPHER_AES256 5
#define ELP_CIPHER_AES128_GCM 6
#define ELP_CIPHER_AES192_GCM 7
#define ELP_CIPHER_AES256_GCM 8
#define ELP_CIPHER_AES128_CTR 9
#define ELP_CIPHER_AES192_CTR 10
#define ELP_CIPHER_AES256_CTR 11
/* Fixed mapping between source and destination ddts */
#define DST_DDTE(src_ddte) (&(src_ddte[ELP_MAX_DDT_PER_PKT]))
/* SA flags (oxffest 0x7e) bits */
#define ESPAH_ENABLED 0x0001
#define ESPAH_SEQ_ROLL_ALLOWED 0x0002
#define ESPAH_TTL_ENABLE 0x0004
#define ESPAH_TTL_TYPE 0x0008 /* 0:byte 1:time */
#define ESPAH_AH_MODE 0x0010 /* 0:ESP 1:AH */
#define ESPAH_ANTI_REPLAY_ENABLE 0x0080
#define ESPAH_COFF_EN 0x0400 /* 1:Crypto offload enable */
#define ESPAH_COFF_MODE 0x0800 /* Crypto offload mode: 0: ECB cypher or raw hash, 1 CBC cypher or HMAC hash */
#define ESPAH_IPV6_ENABLE 0x1000 /* 1:IPv6 SA */
#define ESPAH_DST_OP_MODE 0x2000 /* IPv6 dest opt treatment EDN-0277 page 16 */
#define ESPAH_EXTENDED_SEQNUM 0x4000
/* STAT codes that go into the STAT_RET_CODE of a register */
#define ESPAH_STAT_OK 0
#define ESPAH_STAT_BUSY 1
#define ESPAH_STAT_SOFT_TTL 2
#define ESPAH_STAT_HARD_TTL 3
#define ESPAH_STAT_SA_INACTIVE 4
#define ESPAH_STAT_REPLAY 5
#define ESPAH_STAT_ICV_FAIL 6
#define ESPAH_STAT_SEQ_ROLL 7
#define ESPAH_STAT_MEM_ERROR 8
#define ESPAH_STAT_VERS_ERROR 9
#define ESPAH_STAT_PROT_ERROR 10
#define ESPAH_STAT_PYLD_ERROR 11
#define ESPAH_STAT_PAD_ERROR 12
#define ESPAH_DUMMY_PKT 13
/****** IPSEC HW related common structures *****/
// Dummy ip headers are presently non-cachable hence flushing them is not needed
// // If they become cachable change flush definition below.
#define IPSEC_flush_ipv4h(start,end)
//#define IPSEC_flush_if_cachable(start,end) L1_dc_flush(start,end)
/* SA notifications */
#define IPSEC_SOFT_EXPIRE 0
#define IPSEC_HARD_EXPIRE 1
static __inline void consistent_elpctl(PElliptic_SA elp_sa_ptr, int sa_cache_flush)
{
#if !defined (COMCERTO_2000)
U8 *end_ptr = ((U8*) (elp_sa_ptr + 1)) - 1;
/* Make sure memory is settled*/
L1_dc_clean(elp_sa_ptr, end_ptr);
#elif defined(COMCERTO_2000_CONTROL)
wmb();
#endif
/* DSB(); - done as a part of cleaning */
/* sa_cache_flush should be always 0 for C100 */
hw_sa_cache_flush(elp_sa_ptr , sa_cache_flush);
}
int M_ipsec_ttl_check_time(void);
extern struct tIPSec_hw_context gIpSecHWCtx;
extern int gIpsec_available;
BOOL M_ipsec_pre_inbound_init(PModuleDesc pModule);
BOOL M_ipsec_post_inbound_init(PModuleDesc pModule);
BOOL M_ipsec_pre_outbound_init(PModuleDesc pModule);
BOOL M_ipsec_post_outbound_init(PModuleDesc pModule);
void M_ipsec_outbound_entry(void);
void M_ipsec_outbound_callback(void);
void M_ipsec_inbound_entry(void);
void M_ipsec_inbound_callback(void);
PNatt_Socket_v6 IPsec_Find_Natt_socket_v6(U32 /* __attribute__((packed)) */ *src_ip, U32 /* __attribute__((packed)) */ *dst_ip, unsigned short sport, unsigned short dport);
PNatt_Socket_v4 IPsec_Find_Natt_socket_v4(U32 src_ip, U32 dst_ip, unsigned short sport, unsigned short dport);
#if !defined(COMCERTO_2000_UTIL)
int M_ipsec_is_fragmentation_required(PMetadata mtd, void *l3_hdr, u32 encap_len) __attribute__ ((noinline));
void M_ipsec_prefragment_outbound(PMetadata mtd, U32 mtu, U32 L2_hlen, U32 if_type) __attribute__ ((noinline));
#endif
void ipsec_common_hard_init(IPSec_hw_context *sc);
#if !defined (COMCERTO_2000)
static int M_ipsec_lft_check_data(PSAEntry sa);
PNatt_Socket_v6 IPsec_create_Natt_socket_v6(PSAEntry sa);
static int IPsec_Free_Natt_socket_v6(PSAEntry sa);
PNatt_Socket_v4 IPsec_create_Natt_socket_v4(PSAEntry sa);
static int IPsec_Free_Natt_socket_v4(PSAEntry sa);
int hw_sa_set_lifetime(CommandIPSecSetLifetime *cmd, PSAEntry sa);
int hw_sa_set_cipher_key(PSAEntry sa, U8* key);
int hw_sa_set_cipher_ALG_AESCTR(PSAEntry sa, U16 key_bits, U8* key , U8* algo);
int hw_sa_set_digest_key(PSAEntry sa, U16 key_bits, U8* key);
#endif
//#define CONTROL_IPSEC_DEBUG
#if defined (COMCERTO_2000_CONTROL)
BOOL ipsec_init(void);
void ipsec_exit(void);
void ipsec_standalone_init(void);
#endif
#endif