/*
 *			GPAC - MPEG-4 Systems C Development Kit
 *
 *			Copyright (c) Jean Le Feuvre 2000-2005
 *					All rights reserved
 *
 *  This file is part of GPAC / Crypto Tools sub-project
 *
 *  GPAC 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, or (at your option)
 *  any later version.
 *   
 *  GPAC 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 GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

/*
	The GPAC crypto lib is a simplified version of libmcrypt - not all algos are included.
	Doc here is man mcrypt
	Original libmcrypt license
*/

/*
 * Copyright (C) 1998,1999,2000 Nikos Mavroyanopoulos
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Library General Public License as published 
 * by the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef __M4_CRYPT_H_
#define __M4_CRYPT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <gpac/m4_tools.h>

/*max number of possible key sizes for all supported modes*/
#define MAX_KEY_SIZES	4

/*crypto lib handler*/
typedef struct _m4_crypt_stream *M4CRYPT;

/*supported modes (case insensitive): "CBC", "CFB", "CTR", "ECB", "nCFB", "nOFB", "OFB", "STREAM"*/
/*supported algos (case insensitive): 
	"AES-128" == "Rijndael-128"
	"AES-192" == "Rijndael-192"
	"AES-256" == "Rijndael-256"
	"DES", "3DES"
*/


/*opens crypto context - algo and mode SHALL NOT be NULL*/
M4CRYPT m4crypt_open(const char *algorithm, const char *mode);
/*close crypto context*/
void m4crypt_close(M4CRYPT m4c);

/* sets the state of the algorithm. Can be used only with block algorithms and certain modes like CBC, CFB etc. 
It is usefully if you want to restart or start a different encryption quickly. 
*/
M4Err m4crypt_set_state(M4CRYPT m4c, const void *iv, int size);
/*gets the state of the algorithm. Can be used only certain modes and algorithms. 
The size will hold the size of the state and the state must have enough bytes to hold it.
*/
M4Err m4crypt_get_state(M4CRYPT m4c, void *iv, int *size);
/*Returns 1 if the algorithm is a block algorithm or 0 if it is a stream algorithm.*/
Bool m4crypt_is_block_algorithm(M4CRYPT m4c);
/*Returns 1 if the mode is for use with block algorithms, otherwise it returns 0.*/
Bool m4crypt_is_block_algorithm_mode(M4CRYPT m4c);
/*Returns 1 if the mode outputs blocks of bytes or 0 if it outputs bytes. (eg. 1 for cbc and ecb, and 0 for cfb and stream)*/
Bool m4crypt_is_block_mode(M4CRYPT m4c);
/*Returns the block size of the algorithm specified by the encryption descriptor in bytes.*/
u32 m4crypt_get_block_size(M4CRYPT m4c);
/*Returns the maximum supported key size of the algorithm specified by the encryption descriptor in bytes.*/
u32 m4crypt_get_key_size(M4CRYPT m4c);
/*Returns the number of supported key sizes.
@keys: array of at least MAX_KEY_SIZES size - will hold the supported sizes*/
u32 m4crypt_get_supported_key_sizes(M4CRYPT m4c, u32 *key_sizes);
/*Returns size (in bytes) of the IV of the algorithm specified for the context. 
If it is '0' then the IV is ignored in that algorithm. 
IV is used in CBC, CFB, OFB modes, and in some algorithms in STREAM mode.
*/
u32 m4crypt_get_iv_size(M4CRYPT m4c);
/*Returns 1 if the mode needs an IV, 0 otherwise. 
Some 'stream' algorithms may need an IV even if the mode itself does not need an IV.
*/
Bool m4crypt_mode_has_iv(M4CRYPT m4c);

/*guess what these do...*/
const char *m4crypt_get_algorithm_name(M4CRYPT m4c);
u32 m4crypt_get_algorithm_version(M4CRYPT m4c);
const char *m4crypt_get_mode_name(M4CRYPT m4c);
u32 m4crypt_get_mode_version(M4CRYPT m4c);


/*
This function initializes all buffers for the specified context
@Lenofkey: key size in BYTES - maximum value of lenofkey should be the one obtained by 
calling m4crypt_get_key_size() and every value smaller than this is legal.
@IV: usually size of the algorithms block size - get it by calling m4crypt_get_iv_size().
	IV is ignored in ECB. IV MUST exist in CFB, CBC, STREAM, nOFB and OFB modes.
	It needs to be random and unique (but not secret). The same IV must be used
	for encryption/decryption. 
After calling this function you can use the descriptor for encryption or decryption (not both). 
*/
M4Err m4crypt_init(const M4CRYPT m4c, void *key, u32 lenofkey, const void *IV);
/*releases context buffers - you may call m4crypt_init after that, or m4crypt_close*/
void m4crypt_deinit(M4CRYPT m4c);
/*changes key and IV*/
M4Err m4crypt_set_key(M4CRYPT m4c, void *key, u32 keysize, const void *iv);

/*
main encryption function. 
@Plaintext, @len: plaintext to encrypt - len should be  k*algorithms_block_size if used in a mode
which operated in blocks (cbc, ecb, nofb), or whatever when used in cfb or ofb which operate in streams.
The plaintext is replaced by the ciphertext. 
*/
M4Err m4crypt_encrypt(M4CRYPT m4c, void *plaintext, int len);
/*decryption function. It is almost the same with m4crypt_generic.*/
M4Err m4crypt_decrypt(M4CRYPT m4c, void *ciphertext, int len);

/*various queries on both modes and algo*/
u32 m4crypt_str_get_algorithm_version(const char *algorithm);
u32 m4crypt_str_get_mode_version(const char *mode);
Bool m4crypt_str_is_block_algorithm(const char *algorithm);
Bool m4crypt_str_is_block_algorithm_mode(const char *algorithm);
Bool m4crypt_str_is_block_mode(const char *mode);
u32 m4crypt_str_module_get_algo_block_size(const char *algorithm);
u32 m4crypt_str_module_get_algo_key_size(const char *algorithm);
u32 m4crypt_str_get_algo_supported_key_sizes(const char *algorithm, int *keys);

#ifdef __cplusplus
}
#endif

#endif

