/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss or reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#ifndef _CIPHER_H
#define _CIPHER_H

/*
*	Cipher core and mode function structures
*/

extern const struct bc_cipher	_bc_cipher_aes;
extern const struct bc_cipher	_bc_cipher_des;
extern const struct bc_cipher	_bc_cipher_tea;
extern const struct bc_cblock	_bc_block_ecb;
extern const struct bc_cblock	_bc_block_cbf;
extern const struct bc_cblock	_bc_block_cbc;
extern const struct bc_cblock	_bc_block_ofb;

/** @addtogroup cipher */
/** @{ */

/**
*	State descriptor for the ARC4 cypher
*/

typedef unsigned char BC_ARC4[ 258 ];

/**
*	Size of the AES key schedule buffer, in words.
*/

enum {

	BC_AES_128_KSINTS =	45,	//!< Number of words for 128 bit keys
	BC_AES_192_KSINTS =	53,	//!< Number of words for 192 bit keys
	BC_AES_256_KSINTS =	61	//!< Number of words for 256 bit keys
};

/**
*	Number of bytes per encrypt/decrypt block for AES
*/

#define	BC_AES_BLOCK	16

/**
*	Size of the DES/TDEA key schedule buffer, in words
*/

enum {

	BC_TDEA3_KSINTS = 25,	//!< Number of words for TDEA3 (DES)
	BC_TDEA2_KSINTS = 49,	//!< Number of words for TDEA2
	BC_TDEA1_KSINTS = 73	//!< Number of words for TDEA1
};

/**
*	Number of bytes per encrypt/decrypt block for TDEA (DES)
*/

#define	BC_DES_BLOCK	8

/** @} */

void BC_Arc4Start( BC_ARC4 crypt, const char *key, int klen );
void BC_Arc4Crypt( BC_ARC4 crypt, const char *in, char *out, int dlen );
void BC_AesKeySched( int *ksc, const void *key, int len );
void BC_DesKeySched( int *ksc, const void *k1, const void *k2, const void *k3 );
void BC_TeaKeySched( int *ksc, const void *key );

/*
*	Block ciphers
*/

#define	BC_CIPHER_AES	(&_bc_cipher_aes)	// Select AES cipher function
#define	BC_CIPHER_DES	(&_bc_cipher_des)	// Select DES/TDEA cipher function
#define	BC_CIPHER_TEA	(&_bc_cipher_tea)	// Select BTEA32 cipher function

/*
*	Block cipher modes
*/

#define	BC_BCMODE_ECB	(&_bc_block_ecb)	// Electronic codebook mode
#define	BC_BCMODE_CBF	(&_bc_block_cbf)	// Cipher feedback mode
#define	BC_BCMODE_CBC	(&_bc_block_cbc)	// Cipher block chaining mode
#define	BC_BCMODE_OFB	(&_bc_block_ofb)	// Output feedback mode
#define	BC_BCMODE_CTR	(&_bc_block_ctr)	// Counter mode

/**
*	A block cipher descriptor.
*/

typedef struct bc_bcipher {

	void					*vector;		// Pointer to the vector
	const int				*ksched;		// Pointer to the key schedule
	const struct bc_cipher	*cipher;		// Pointer to the cipher
	const struct bc_cblock	*method;		// Pointer to the block funct
	unsigned				length;			// Number of bytes processed

} BC_CIPHER;

/** @} */

void	BC_CipherPrepare( BC_CIPHER *cipher,
						  const struct bc_cipher *cfunc,
						  const struct bc_cblock *cmode,
						  const int *sched, int *nonce );
void	BC_CipherEncrypt( BC_CIPHER *state, const void *clear, void *cipher );
void	BC_CipherDecrypt( BC_CIPHER *state, const void *cipher, void *clear );
unsigned	BC_CipherLength( const BC_CIPHER *state );

#endif

