/*
 *
 *			   IPSEC for Linux
 *		         Preliminary Release
 * 
 *	 Copyright (C) 1996, 1997, John Ioannidis <ji@hol.gr>
 * 
 * Changes by Angelos D. Keromytis and Niels Provos
 * ported from OpenBSD 2.2 by Petr Novak, <pn@i.cz>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 */

/*
 * $Id: ipsec_ah.h,v 0.4 1997/01/15 01:28:15 ji Rel $
 *
 * $Log: ipsec_ah.h,v $
 * Revision 0.4  1997/01/15 01:28:15  ji
 * Added definitions for new AH transforms.
 *
 * Revision 0.3  1996/11/20 14:35:48  ji
 * Minor Cleanup.
 * Rationalized debugging code.
 *
 * Revision 0.2  1996/11/02 00:18:33  ji
 * First limited release.
 *
 *
 */

#ifndef	IPPROTO_AH
#define	IPPROTO_AH	51
#endif

#include "hashes/ipsec_md5h.h"
#include "hashes/ipsec_sha1.h"
#include "hashes/ipsec_rmd160.h"

/*
 * Authentication Header declarations
 */

struct ah_hash {
    int type;
    char *name;
    __u16 hashsize;
    __u16 authsize;
    __u16 ctxsize;
    void (*Init)(void *);
    void (*Update)(void *, __u8 *, __u16);
    void (*Final)(__u8 *, void *);
};

typedef union {
	MD5_CTX md5ctx;
	SHA1_CTX sha1ctx;
	RMD160_CTX rmd160ctx;
} HASH_CTX;

#define AHMD5_KMAX	64		/* max 512 bits key */
#define AHSHA1_KMAX	64		/* max 512 bits key */
#define AHMD5_AMAX	8+64		/* optional 64-bit replay counter, and
					   up to 512 bits of authenticator */
struct ah_old				/* Generic AH header */
{
	__u8	ah_nh;			/* Next header (protocol) */
	__u8	ah_hl;			/* AH length, in 32-bit words */
	__u16	ah_rv;			/* reserved, must be 0 */
	__u32	ah_spi;			/* Security Parameters Index */
	__u8	ah_data[1];		/* More, really */
};

#define AH_OLD_FLENGTH	8		/* size of fixed part */

/* Authenticator lengths */
#define AH_MD5_ALEN             16
#define AH_SHA1_ALEN            20
#define AH_RMD160_ALEN          20

#define AH_ALEN_MAX             AH_SHA1_ALEN    /* Keep this updated */

#define AH_HMAC_HASHLEN         12      /* 96 bits of authenticator */
#define AH_HMAC_RPLENGTH        4       /* 32 bits of replay counter */
#define AH_HMAC_INITIAL_RPL     1       /* Replay counter initial value */

#define HMAC_IPAD_VAL           0x36
#define HMAC_OPAD_VAL           0x5C
#define HMAC_BLOCK_LEN          64

struct ah_new
{
    __u8        ah_nh;                  /* Next header (protocol) */
    __u8        ah_hl;                  /* AH length, in 32-bit words */
    __u16       ah_rv;                  /* reserved, must be 0 */
    __u32       ah_spi;                 /* Security Parameters Index */
    __u32       ah_rpl;                 /* Replay prevention */
    __u8        ah_data[AH_HMAC_HASHLEN];/* Authenticator */
};

#define AH_NEW_FLENGTH		8	/* The fixed part only! */

struct ah_new_xencap
{
    __u32       amx_hash_algorithm;
    __s32       amx_wnd;
    __u32       amx_keylen;
    __u8        amx_key[1];
};

#define AH_NEW_XENCAP_LEN       (3 * sizeof(__u32))

struct ah_new_xdata
{
    __u32       amx_hash_algorithm;
    __s32       amx_wnd;
    __u32       amx_rpl;                /* Replay counter */
    __u32       amx_bitmap;
    struct ah_hash  *amx_hash;
    union
    {
        MD5_CTX         amx_MD5_ictx;       /* Internal key+padding */
        SHA1_CTX        amx_SHA1_ictx;
        RMD160_CTX      amx_RMD160_ictx;
    } amx_ictx;
    union
    {
        MD5_CTX         amx_MD5_octx;       /* External key+padding */
        SHA1_CTX        amx_SHA1_octx;
        RMD160_CTX      amx_RMD160_octx;
    } amx_octx;
};

#define amx_md5_ictx    amx_ictx.amx_MD5_ictx
#define amx_md5_octx    amx_octx.amx_MD5_octx
#define amx_sha1_ictx   amx_ictx.amx_SHA1_ictx
#define amx_sha1_octx   amx_octx.amx_SHA1_octx
#define amx_rmd160_ictx amx_ictx.amx_RMD160_ictx
#define amx_rmd160_octx amx_octx.amx_RMD160_octx

struct ah_old_xdata
{
    __u32       amx_hash_algorithm;
    __u32       amx_keylen;             /* Key material length */
    struct ah_hash  *amx_hash;
    union
    {
        MD5_CTX     amx_MD5_ctx;
        SHA1_CTX    amx_SHA1_ctx;
    } amx_ctx;
    __u8        amx_key[1];             /* Key material */
};

#define amx_md5_ctx     amx_ctx.amx_MD5_ctx
#define amx_sha1_ctx    amx_ctx.amx_SHA1_ctx

struct ah_old_xencap
{
    __u32       amx_hash_algorithm;
    __u32       amx_keylen;
    __u8        amx_key[1];
};

#define AH_OLD_XENCAP_LEN       (2 * sizeof(__u32))

#define AH_HMAC_IPAD_VAL        0x36
#define AH_HMAC_OPAD_VAL        0x5C

extern struct inet_protocol ah_protocol;

#if 0
#if defined(__LITTLE_ENDIAN)
static inline unsigned long long
htonq(unsigned long long q)
{
	register unsigned long u, l;
	u = q >> 32;
	l = (unsigned long)q;
	
	return htonl(u) | ((unsigned long long)htonl(l) << 32);
}

#define ntohq(_x) htonq(_x)

#elif defined(__BIG_ENDIAN)

#define htonq(_x) (_x)
#define ntohq(_x) htonq(_x)

#else
#error  "Please fix <asm/byteorder.h>"
#endif                                          
#endif

#ifdef DEBUG_IPSEC_AH

extern int debug_ah;

#define DB_AH_PKTRX	0x0001
#define DB_AH_PKTRX2	0x0002
#define DB_AH_DMP	0x0004
#define DB_AH_TDB	0x0010
#define DB_AH_XF	0x0020
#define DB_AH_INAU	0x0040
#define DB_AH_REPLAY	0x0100
#endif
