/*      IPSec Authentication Header, RFC 2402        
 *	
 *      Authors: 
 *      Henrik Petander         <lpetande@tml.hut.fi>
 * 
 *      $Id: ah.h,v 1.19 2001/07/10 11:58:56 henkku Exp $
 *
 *      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.
 *
 *
 */

#ifndef _AH_H
#define _AH_H

#include <linux/autoconf.h>
#ifndef CONFIG_IPV6_MOBILITY_AH
#define NO_AH 
#endif

#ifndef NO_AH

#include <linux/skbuff.h>

#define AHHMAC_HASHLEN 12 

/* AH specific debug levels */
#define AH_PARSE 6
#define AH_DUMP 7 /* Dumps packets */

struct mipv6_ah				/* 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 */
        __u32   ah_rpl;                 /* Replay prevention */
	__u8	ah_data[AHHMAC_HASHLEN];/* Authentication hash */
};

int mipv6_process_ah(struct sk_buff **skb, struct in6_addr *coa, int noff); 
int mipv6_handle_auth(struct sk_buff *skb, int optoff);
void mipv6_initialize_ah(void);
void mipv6_shutdown_ah(void);
#endif /* __KERNEL__*/

#define HAVE_LITTLE_ENDIAN
#define SA_INITIALIZED 1 
#define SA_SOFT_EXPIRE 2 

#define ALG_AUTH_NONE           0
#define ALG_AUTH_KEYED_MD5      1
#define ALG_AUTH_KEYED_SHA1     2
#define ALG_AUTH_HMAC_MD5       3
#define ALG_AUTH_HMAC_SHA1      4
#define ALG_AUTH_NULL           5

#define ALG_ENC_NONE            0
#define ALG_ENC_DES_CBC         1
#define ALG_ENC_NULL            2

#define	IPSEC_MODE_ANY		0	/* i.e. wildcard. */
#define	IPSEC_MODE_TRANSPORT	1
#define	IPSEC_MODE_TUNNEL	2

#define REPLAY_WIN_SIZE         32
#define BYTE_COUNT              0
#define TIME_COUNT              1
#define BOTH_COUNT              2


struct lifetime {
	u_int8_t count_used; /* byte_count, time_count or both */
	u_int32_t byte_count_soft; /* After how many bytes ... */
	u_int32_t byte_count_hard; 
	u_int32_t time_count_soft;
	u_int32_t time_count_hard;
	u_int32_t use_time; 
	u_int32_t use_byte;
	u_int32_t add_time; /* when SA was added */
};


struct ah_processing {
  void* context;
  struct sec_as* sas;
};

struct antireplay {
	u_int32_t count;
	u_int32_t bitmap; 
};


struct sec_as {
	u_int8_t auth_alg; 
	u_int8_t direction;
	u_int8_t key_auth[64];
	u_int32_t lifetime; 
	u_int32_t soft_lifetime; /* In seconds */
	u_int32_t key_auth_len;
	u_int32_t spi; 
	struct in6_addr addr;	/* address of peer */
	/* Entries above this are same as in sa_ioctl */
	atomic_t use; /* reference count */
	u_int32_t seq_nb; /* Sequence number counter */
	u_int32_t flags;
	u_int32_t expires; /* In jiffies */
	u_int32_t soft_expires; 
	u_int32_t pmtu; /* Path MTU */
	u_int32_t replay_count;
	struct {
		u_int8_t sumsiz;
		int (*init)(struct ah_processing*, struct sec_as*);
		void (*loop)(struct ah_processing*, void*, u_int32_t);
		void (*result)(struct ah_processing*, char*);
	} alg_auth;		
};

struct sa_bundle {
	struct in6_addr addr; /* address of the other side, 
			       * only selector for now
			       */	
	struct sec_as *sa_i; /* Outgoing SA */
	struct sec_as *sa_o; /* Incoming SA */
};
#ifdef __KERNEL__ 
typedef struct {
  u_int32_t A, B, C, D;
  u_int32_t bitlen[2];
  u_int8_t* buf_cur;
  u_int8_t buf[64];
} MD5_CTX;

typedef struct {
  u_int32_t A, B, C, D, E;
  u_int32_t bitlen[2];
  u_int8_t* buf_cur;
  u_int8_t buf[64];
} SHA1_CTX;

void ah_keyed_md5_init(struct ah_processing*, struct sec_as*);
void ah_keyed_md5_loop(struct ah_processing*, void*, u_int32_t);
void ah_keyed_md5_result(struct ah_processing*, char*);
void ah_keyed_sha1_init(struct ah_processing*, struct sec_as*);
void ah_keyed_sha1_loop(struct ah_processing*, void*, u_int32_t);
void ah_keyed_sha1_result(struct ah_processing*, char*);
int
ah_hmac_md5_init (struct ah_processing* ahp, struct sec_as* sas);
void ah_hmac_md5_loop(struct ah_processing*, void*, u_int32_t);
void ah_hmac_md5_result(struct ah_processing*, char*);
int ah_hmac_sha1_init(struct ah_processing*, struct sec_as*);
void ah_hmac_sha1_loop(struct ah_processing*, void*, u_int32_t);
void ah_hmac_sha1_result(struct ah_processing*, char*);


#define AH_HDR_LEN 12   /* # of bytes for Next Header, Payload Length,
                           RESERVED, Security Parameters Index and

                           Sequence Number Field */

void md5_init(MD5_CTX *ctx);
void md5_over_block(MD5_CTX *ctx, u_int8_t* data);
void create_M_blocks(u_int32_t* M, u_int8_t* data);
void md5_compute(MD5_CTX *ctx, u_int8_t* data, u_int32_t len);
void md5_final(MD5_CTX *ctx, u_int8_t* digest);

void sha1_init(SHA1_CTX *ctx);
void sha1_over_block(SHA1_CTX *ctx, u_int8_t* data);
void create_W_blocks(u_int32_t* W, u_int8_t* data);
void sha1_compute(SHA1_CTX *ctx, u_int8_t* data, u_int32_t len);
void sha1_final(SHA1_CTX *ctx, u_int8_t* digest);

struct mipv6_acq {
	struct in6_addr coa;
	struct in6_addr haddr;
	struct in6_addr peer;
	u_int32_t spi;
};

#define KEYED_MD5_HASH_LEN  16
#define KEYED_SHA1_HASH_LEN 20
#define HMAC_MD5_HASH_LEN   16
#define HMAC_SHA1_HASH_LEN  20

#define KEYED_MD5_ICV_LEN  12
#define KEYED_SHA1_ICV_LEN 12
#define HMAC_MD5_ICV_LEN   12 /* RFC 2403 */
#define HMAC_SHA1_ICV_LEN  12 /* RFC 2404 */



#endif /*NO_AH */
#endif /*AH_H*/ 






