/*
 * The Cryptonit security software suite is developped by IDEALX
 * Cryptonit Team (http://IDEALX.org/ and http://cryptonit.org).
 *
 * Copyright 2003-2006 IDEALX
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 as published by the Free Software Foundation.
 * 
 * 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 St, Fifth Floor, Boston, MA
 * 02110-1301, USA. 
 *
 * In addition, as two special exceptions:
 *
 * 1) IDEALX S.A.S gives permission to:
 *  * link the code of portions of his program with the OpenSSL library under
 *    certain conditions described in each source file
 *  * distribute linked combinations including the two, with respect to the
 *    OpenSSL license and with the GPL
 *
 * You must obey the GNU General Public License in all respects for all of the
 * code used other than OpenSSL. If you modify file(s) with this exception,
 * you may extend this exception to your version of the file(s), but you are
 * not obligated to do so. If you do not wish to do so, delete this exception
 * statement from your version, in all files (this very one along with all
 * source files).

 * 2) IDEALX S.A.S acknowledges that portions of his sourcecode uses (by the
 * way of headers inclusion) some work published by 'RSA Security Inc.'. Those
 * portions are "derived from the RSA Security Inc. PKCS #11Cryptographic
 * Token Interface (Cryptoki)" as described in each individual source file.
 */

#ifndef _PKCS8_HH_
#define _PKCS8_HH_

#include "Key.hh"
#include "Certificate.hh"

#include <openssl/evp.h>
#include <openssl/bio.h>

namespace Cryptonit {
    
    /** This class represents an OpenSSL key.
     * 
     */
    class pkcs8 : public Key
    {
	
    private :
	/* This variable contains an OpenSSL key */
	EVP_PKEY *key;
	
    public :
	/** Construct an empty OpenSSL key
	 *
	 */
	pkcs8();

	/** Construct an OpenSSL key with the specified key
	 *
	 * @param privateKey : The private key
	 */
	pkcs8(EVP_PKEY *privateKey);

	/**
	 * The copy constructor  
	 */
	pkcs8( pkcs8 &src);
	
	/** Destruct this OpenSSL key
	 *
	 */
	virtual ~pkcs8();
	
	/**
	 *  Free the EVP_PKEY
	 */
	void free();
	
	/**
	 *  Load a key from a file. Several formats are accepted.
	 * @param fin : the file 
	 * @param format : the format of the file (see env.h)
	 */
	bool load(FILE *file, FileFormat format , const char *passwd=NULL);
	
	bool load(const char* _filename, FileFormat _format, const char *passwd=NULL );
	
	/** load a key from a BIO 
	 * @param bin : the source BIO
	 * @param format : the key format
	 */
	int load(BIO *bin , FileFormat format = der_format);
	
	/** save a key into a BIO 
	 * @param bin : the destination BIO
	 * @param format : the key format
	 */
	int save(BIO *bout, const FileFormat format = der_format);
	
	/** Write the private key on disk encrypted or unencrypted, in PEM format.
	 *  If only the filename is specified, then the private key will be written unencrypted.
	 *
	 *  @param filename : destination filename
	 *  @param cipher : cipher that will be used for encrypting private key, you can
	 *                  use the getCipher() function in Utls.hh to get the correct cipher 
	 *                  with a firendly name.
	 *  @param password : password used for the encryption.
	 *  @param klen : password length, if the value is 0 then the password must be NULL terminated.
	 *
	 *  @return  0 on success
	 *          -1 if there is no filename specified
	 *          -2 if the file cannot be opened in writting
	 *          -3 if the write process fail
	 */
	int save( const char* filename, const EVP_CIPHER* cipher = NULL, const char* password = NULL, int klen = 0 );
	
	
	/** Write the private key on disk encrypted or unencrypted, in PEM format.
	 *  If only the file pointer is specified, then the private key will be written unencrypted.
	 *
	 *  @param fp : destination file pointer
	 *  @param cipher : cipher that will be used for encrypting private key, you can
	 *                  use the getCipher() function in Utls.hh to get the correct cipher 
	 *                  with a firendly name.
	 *  @param password : password used for the encryption.
	 *  @param klen : password length, if the value is 0 then the password must be NULL terminated.
	 *
	 *  @return  0 on success
	 *          -1 if there is the file pointer is invalid
	 *          -2 if the file cannot be opened in writting
	 *          -3 if the write process fail
	 */
	int save( FILE* fp, const EVP_CIPHER* cipher = NULL, const char* password = NULL, int klen  = 0 );
	
	
	/** Return the OpenSSL private key.
	 * 
	 */
	EVP_PKEY* getKey();
	
	/** Set the private key with the specified key.
	 *
	 * @param privateKey : The key that will be replace the current key
	 */
	void setKey(EVP_PKEY* privateKey);
	
	
	/** Generate a RSA key pair.
	 *
	 *  @param bits : the number of bits in the public modulus 
	 *                (2048 is the minimum recommended)
	 *  @param callback : this function while be called during the prime generation
	 *                    process to report the status of the prime generation.
	 *  @param cb_arg : user argument that will be passed to the  callback function
	 *
	 *  @return 0 the genrated key is ready for use
	 *         -1 cannot correctly seed the PRNG
	 *         -2 the generated key is invalid and must be regenerated
	 *         -3 an error occured while performing test on the generated key
	 *         -4 cannot assign the generated key to the current key 'key'.
	 */
	int generateKeyPair( int bits = 2048, void (*callback)(int, int, void*) = NULL, void* cb_arg = NULL );
	
	
	EVP_PKEY* getPublicKey();
	EVP_PKEY* getPrivateKey();
    };
}
#endif
