/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * XSEC
 *
 * XSECCryptoSymmetricKey := Bulk encryption algorithms should all be
 *							implemented via this interface
 *
 * $Id$
 *
 */

#include <xsec/framework/XSECDefs.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/enc/XSECCryptoException.hpp>

#include <xercesc/util/Janitor.hpp>

XERCES_CPP_NAMESPACE_USE

#if defined (XSEC_HAVE_WINCAPI)

// --------------------------------------------------------------------------------
//           Constructors and Destructors
// --------------------------------------------------------------------------------

WinCAPICryptoSymmetricKey::WinCAPICryptoSymmetricKey(
						HCRYPTPROV prov,
						XSECCryptoSymmetricKey::SymmetricKeyType type) :
m_keyType(type),
m_keyMode(MODE_NONE),
m_initialised(false),
m_doPad(true),
m_p(prov),
m_k(0) {


}

WinCAPICryptoSymmetricKey::~WinCAPICryptoSymmetricKey() {

	if (m_k != 0)
		CryptDestroyKey(m_k);

}

// --------------------------------------------------------------------------------
//           Basic Key interface methods
// --------------------------------------------------------------------------------

XSECCryptoKey * WinCAPICryptoSymmetricKey::clone() const {

	WinCAPICryptoSymmetricKey * ret;

	XSECnew(ret, WinCAPICryptoSymmetricKey(m_p, m_keyType));
	ret->m_keyLen = m_keyLen;
	ret->m_keyBuf = m_keyBuf;

	if (m_k != 0) {

#if (_WIN32_WINNT > 0x0400)

		// Only supported in Win2K and above

		if (CryptDuplicateKey(m_k,
			 				  0,
							  0,
							  &(ret->m_k)) == 0 ) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey Error attempting to clone key parameters");

		}
#else

		ret->setKey(m_keyBuf.rawBuffer(), m_keyLen);

#endif
	}
	else
		ret->m_k = 0;

	return ret;

}

// --------------------------------------------------------------------------------
//           Store the key value
// --------------------------------------------------------------------------------

void WinCAPICryptoSymmetricKey::setKey(const unsigned char * key, unsigned int keyLen) {

	m_keyBuf.sbMemcpyIn(key, keyLen);
	m_keyLen = keyLen;

	if (m_k != 0)
		CryptDestroyKey(m_k);
	
	m_p = 0;
	m_k = createWindowsKey(key, keyLen, m_keyType, &m_p);
}

// --------------------------------------------------------------------------------
//           Decrypt
// --------------------------------------------------------------------------------

int WinCAPICryptoSymmetricKey::decryptCtxInit(const unsigned char * iv) {

	// Returns amount of IV data used (in bytes)
	// Sets m_initialised iff the key is OK and the IV is OK.

	if (m_initialised)
		return 0;

	if (m_k == 0) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Cannot initialise without key"); 
	}
    else if (m_keyMode == MODE_NONE) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Cannot initialise without mode"); 
    }

	DWORD cryptMode;
	if (m_keyMode == MODE_CBC) {

		if (iv == NULL) {

			return 0;	// Cannot initialise without an IV

		}
		
		cryptMode = CRYPT_MODE_CBC;

		if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey - Error setting cipher mode"); 

		}
		
		if (!CryptSetKeyParam(m_k, KP_IV, (unsigned char *) iv, 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error setting IV"); 

		}

	}
	else if (m_keyMode == MODE_ECB) {
		cryptMode = CRYPT_MODE_ECB;

		if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey - Error setting cipher mode"); 

		}
	}
    else {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unknown cipher mode"); 
    }

	// Set up the context according to the required cipher type
	switch (m_keyType) {

	case (XSECCryptoSymmetricKey::KEY_3DES_192) :

		// A 3DES CBC key

		m_blockSize = 8;
		m_bytesInLastBlock = 0;
		m_initialised = true;
		
		break;

	case (XSECCryptoSymmetricKey::KEY_AES_128) :
	case (XSECCryptoSymmetricKey::KEY_AES_192) :
	case (XSECCryptoSymmetricKey::KEY_AES_256) :

		// An AES key

		m_blockSize = 16;
		m_bytesInLastBlock = 0;
		m_initialised = true;
		
		break;

	default :

		// Cannot do this without an IV
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unknown key type"); 

	}

	// Setup ivSize
    switch (m_keyMode) {
        case MODE_CBC:
            m_ivSize = m_blockSize;
            break;

        case MODE_GCM:
            m_ivSize = 12;
            break;

        default:
            m_ivSize = 0;
    }

    return m_ivSize;
}


bool WinCAPICryptoSymmetricKey::decryptInit(bool doPad, 
											SymmetricKeyMode mode, 
											const unsigned char* iv,
                                            const unsigned char* tag,
                                            unsigned int taglen) {

	m_initialised = false;
	m_doPad = doPad;
	m_keyMode = mode;
	decryptCtxInit(iv);
	return true;

}

unsigned int WinCAPICryptoSymmetricKey::decrypt(const unsigned char * inBuf, 
								 unsigned char * plainBuf, 
								 unsigned int inLength,
								 unsigned int maxOutLength) {



	// NOTE: This won't actually stop WinCAPI blowing the buffer, so the onus is
	// on the caller.

	unsigned int offset = 0;
	if (!m_initialised) {
		offset = decryptCtxInit(inBuf);
		if (offset > inLength) {
			throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Not enough data passed in to get IV");
		}
	}

	/* As per bug #38365 - we need to ensure there are enough characters to decrypt.
	   Otherwise we get some nasty errors due to rounding calculations when inputs
	   are too small */

	else if (m_bytesInLastBlock + inLength < m_blockSize) {
		// Not enough input data
		memcpy(&m_lastBlock[m_bytesInLastBlock], inBuf, inLength);
		m_bytesInLastBlock += inLength;
		return 0;
	}

	DWORD outl = inLength - offset;

	// Copy in last block
	if (m_bytesInLastBlock > 0)
		memcpy(plainBuf, m_lastBlock, m_bytesInLastBlock);

	// Copy out the tail, as we _MUST_ know when we come to the end for decryptFinal
	unsigned int rounding = (outl % m_blockSize) + m_blockSize;
	memcpy(&plainBuf[m_bytesInLastBlock], &inBuf[offset], outl - rounding);

	// Copy the tail to m_lastBlock
	memcpy(m_lastBlock, &inBuf[offset + outl - rounding], rounding);
	outl = outl - rounding + m_bytesInLastBlock;
	m_bytesInLastBlock = rounding;
	
	if (!CryptDecrypt(m_k,
				 0,
				 FALSE,
				 0,
				 plainBuf,
				 &outl)) {

		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error during WinCAPI decrypt"); 

	}

	return outl;

}

unsigned int WinCAPICryptoSymmetricKey::decryptFinish(unsigned char * plainBuf,
													  unsigned int maxOutLength) {

	DWORD outl = m_bytesInLastBlock;

	memcpy(plainBuf, m_lastBlock, outl);

	if (!CryptDecrypt(m_k, 
					  0, 
					  FALSE,
					  0,
					  plainBuf,
					  &outl)) {

		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error during WinCAPI decrypt finalisation"); 

	}

	if (m_doPad) {

		// Need to do this ourselves, as WinCAPI appears broken
		if (plainBuf[outl - 1] > m_blockSize) {
			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey - Bad padding"); 
		}

		outl -= plainBuf[outl - 1];

	}

	// This is just to reset the key, and does nothing else useful.
	DWORD tmpout = maxOutLength - outl;
	CryptDecrypt(m_k, 0, TRUE, 0, &plainBuf[outl], &tmpout);

	return outl;
}

// --------------------------------------------------------------------------------
//           Encrypt
// --------------------------------------------------------------------------------

void WinCAPICryptoSymmetricKey::encryptCtxInit(const unsigned char * iv) {



	if (m_initialised == true)
		return;
	
	if (m_keyLen == 0) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Cannot initialise without key"); 
	}
    else if (m_keyMode == MODE_NONE) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Cannot initialise without mode"); 
    }

	m_initialised = true;

	// Set up the context according to the required cipher type

	const unsigned char * usedIV = NULL;
	unsigned char genIV[256];
	DWORD cryptMode;

	// Tell the library that the IV still has to be sent

	if (m_keyMode == MODE_CBC) {

		if (iv == NULL) {
			
			BOOL res = CryptGenRandom(m_p, 256, genIV);
			if (res == FALSE) {
				throw XSECCryptoException(XSECCryptoException::SymmetricError,
					"WinCAPI:SymmetricKey - Error generating random IV");
			}

			usedIV = genIV;
			//return 0;	// Cannot initialise without an IV

		}
		else
			usedIV = iv;

		cryptMode = CRYPT_MODE_CBC;

		if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey - Error setting cipher mode"); 

		}

		// Set the IV parameter
		if (!CryptSetKeyParam(m_k, KP_IV, (unsigned char *) usedIV, 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error setting IV"); 

		}

	}
	else if (m_keyMode == MODE_ECB) {

		cryptMode = CRYPT_MODE_ECB;

		if (!CryptSetKeyParam(m_k, KP_MODE, (BYTE *) (&cryptMode), 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey - Error setting cipher mode"); 

		}
	}
    else {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"OpenSSL:SymmetricKey - Unsupported cipher mode");
    }

	switch (m_keyType) {

	case (XSECCryptoSymmetricKey::KEY_3DES_192) :

		// A 3DES key

		m_blockSize = 8;
		if (m_keyMode == MODE_CBC)
			m_ivSize = 8;
		else 
			m_ivSize = 0;
		m_bytesInLastBlock = 0;

		break;

	case (XSECCryptoSymmetricKey::KEY_AES_128) :
	case (XSECCryptoSymmetricKey::KEY_AES_192) :
	case (XSECCryptoSymmetricKey::KEY_AES_256) :

		// An AES key

		m_blockSize = 16;
		if (m_keyMode == MODE_CBC)
			m_ivSize = 16;
        else if (m_keyMode == MODE_GCM)
            m_ivSize = 12;
		else 
			m_ivSize = 0;
		m_bytesInLastBlock = 0;

		break;
	
	default :

		// Cannot do this without an IV
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unknown key type"); 

	}

	if (usedIV != NULL && m_ivSize > 0)
		memcpy(m_lastBlock, usedIV, m_ivSize);


}
bool WinCAPICryptoSymmetricKey::encryptInit(bool doPad, 
											SymmetricKeyMode mode, 
											const unsigned char * iv) {

	m_doPad = doPad;
	m_keyMode = mode;
	m_initialised = false;
	encryptCtxInit(iv);
	return true;

}

unsigned int WinCAPICryptoSymmetricKey::encrypt(const unsigned char * inBuf, 
								 unsigned char * cipherBuf, 
								 unsigned int inLength,
								 unsigned int maxOutLength) {

	if (m_initialised == false) {

		encryptInit();

	}

	// NOTE: This won't actually stop WinCAPI blowing the buffer, so the onus is
	// on the caller.

	unsigned int offset = 0;
	unsigned char * bufPtr;
	unsigned char * encPtr;	// Ptr to start of block to encrypt

	DWORD outl = 0;
	
	if (m_ivSize > 0) {

		DWORD len = m_ivSize;
		if (!CryptGetKeyParam(m_k, KP_IV, (unsigned char *) m_lastBlock, &len, 0)) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error setting IV"); 

		}
		memcpy(cipherBuf, m_lastBlock, m_ivSize);
		offset = m_ivSize;
		outl += m_ivSize;
		m_ivSize = 0;

	}

	/* As per bug #38365 - we need to ensure there are enough characters to encrypt.
	   Otherwise we get some nasty errors due to rounding calculations when inputs
	   are too small */

	if (m_bytesInLastBlock + inLength < m_blockSize) {
		// Not enough input data
		memcpy(&m_lastBlock[m_bytesInLastBlock], inBuf, inLength);
		m_bytesInLastBlock += inLength;

		// Just in case we have returned an IV
		return outl;
	}

	bufPtr = &cipherBuf[offset];
	encPtr = bufPtr;

	if (m_bytesInLastBlock > 0) {
		memcpy(bufPtr, m_lastBlock, m_bytesInLastBlock);
		bufPtr = &bufPtr[m_bytesInLastBlock];
		outl += m_bytesInLastBlock;
	}

	unsigned int rounding = (m_bytesInLastBlock + inLength) % m_blockSize;
	rounding += m_blockSize;

	outl += inLength - rounding;
	if (outl > maxOutLength) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Not enough space in output buffer for encrypt"); 
	}

	outl -= offset;

	// Now copy back one block + rounding
	memcpy(m_lastBlock, &inBuf[inLength - rounding], rounding);
	m_bytesInLastBlock = rounding;

	// Finally, copy in last of buffer to encrypt
	memcpy(bufPtr, inBuf, inLength - rounding);

	// Do the enrypt
	if (!CryptEncrypt(m_k, 0, FALSE, 0, encPtr, &outl, maxOutLength)) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error during WinCAPI encrypt"); 
	}
	
	return outl + offset;

}

unsigned int WinCAPICryptoSymmetricKey::encryptFinish(unsigned char * cipherBuf,
													  unsigned int maxOutLength,
                                                      unsigned int taglen) {

	DWORD outl = m_bytesInLastBlock + m_blockSize;

	if (outl > maxOutLength) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Not enough space in output buffer for encrypt - NOTE WinCAPI requires an extra block to complete encryption"); 
	}

	outl = 0;

	if (m_bytesInLastBlock != 0) {

		memcpy(cipherBuf, m_lastBlock, m_bytesInLastBlock);
		outl = m_bytesInLastBlock;

	}

	if (!CryptEncrypt(m_k, 0, TRUE, 0, cipherBuf, &outl, maxOutLength)) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Error during WinCAPI encrypt"); 
	}

	if (!m_doPad) {

		// It is the responsibility of the caller to ensure they have 
		// passed in block size num bytes

		if (outl >= m_blockSize)
			outl -= m_blockSize;

	}

	return outl;

}


// --------------------------------------------------------------------------------
//           Create a windows key
// --------------------------------------------------------------------------------

HCRYPTKEY WinCAPICryptoSymmetricKey::createWindowsKey(
								const unsigned char * key, 
								unsigned int keyLen, 
								XSECCryptoSymmetricKey::SymmetricKeyType type,
								HCRYPTPROV * prov) {

	// First get the correct Provider handle to load the key into
	
	HCRYPTPROV p;
	
	if (prov == NULL || *prov == 0) {
		if (!strEquals(XSECPlatformUtils::g_cryptoProvider->getProviderName(), DSIGConstants::s_unicodeStrPROVWinCAPI)) {
			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey - Main provider is not Windows provider"); 
		}

		WinCAPICryptoProvider * cp = 
			(WinCAPICryptoProvider*) XSECPlatformUtils::g_cryptoProvider;

		p = cp->getApacheKeyStore();

		if (p == 0) {

			throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unable to retrieve internal key store"); 

		}

		if (prov != NULL)
			*prov = p;
	}

	else if (prov != NULL)
		p = *prov;

	// Get the key wrapping key
	HCRYPTKEY k;
	if (!CryptGetUserKey(p, AT_KEYEXCHANGE, &k)) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unable to retrieve internal key pair"); 
	}

	// Find out how long the output will be
	DWORD outl = 0;
	if (!CryptEncrypt(k, 0, TRUE, 0, 0, &outl, keyLen)) {
		DWORD error = GetLastError();
		if (error == NTE_BAD_KEY) {
			// We throw either way, but this is *likely* to be an unsupported OS issue
			throw XSECCryptoException(XSECCryptoException::SymmetricError,
				"WinCAPI:SymmetricKey::createWindowsKey - Error encrypting a key - is this >= Windows 2000?");
		}

		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unable to determine space required to encrypt key");
	}

	// Create the necessary buffer
	unsigned char * encryptBuf;
	unsigned int encryptBufSize = outl;
	XSECnew(encryptBuf, unsigned char[outl]);
	ArrayJanitor<unsigned char> j_encryptBuf(encryptBuf);

	memcpy(encryptBuf, key, keyLen);
	outl = keyLen;

	// Do the encrypt

	if (!CryptEncrypt(k, 0, TRUE, 0, encryptBuf, &outl, encryptBufSize)) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unable to encrypt key");
	}

	// Now we have the encrypted buffer, create a SIMPLEBLOB structure

	unsigned char * simpleBlob;
	XSECnew(simpleBlob, unsigned char [sizeof (BLOBHEADER) + sizeof (DWORD) +  outl]);
	ArrayJanitor<unsigned char> j_simpleBlob(simpleBlob);

	BLOBHEADER * blobHeader = (BLOBHEADER *) simpleBlob;
	blobHeader->bType = SIMPLEBLOB;
	blobHeader->bVersion = CUR_BLOB_VERSION;
	blobHeader->reserved = 0;

	unsigned int expectedLength;

	switch (type) {

	case (XSECCryptoSymmetricKey::KEY_3DES_192) :
					blobHeader->aiKeyAlg = CALG_3DES;
					expectedLength = 24;
					break;
	case (XSECCryptoSymmetricKey::KEY_AES_128) :
					blobHeader->aiKeyAlg = CALG_AES_128;
					expectedLength = 16;
					break;
	case (XSECCryptoSymmetricKey::KEY_AES_192) :
					blobHeader->aiKeyAlg = CALG_AES_192;
					expectedLength = 24;
					break;
	case (XSECCryptoSymmetricKey::KEY_AES_256) :
					blobHeader->aiKeyAlg = CALG_AES_256;
					expectedLength = 32;
					break;
	default :

		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey::createWindowsKey - Unknown Symmetric key type");

	}

	// Check key length - otherwise the user could get some very cryptic error messages
	if (keyLen != expectedLength) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey::createWindowsKey - Key length incorrect for algorithm");
	}

	DWORD * algId = (DWORD *) (simpleBlob + sizeof(BLOBHEADER));
	*algId = CALG_RSA_KEYX;

	// Copy in the encrypted data
	memcpy(&simpleBlob[sizeof(BLOBHEADER) + sizeof(DWORD)], encryptBuf, outl);

	// Now do the import

	HCRYPTKEY k2;

	if (!CryptImportKey(p, simpleBlob, sizeof(BLOBHEADER) + sizeof(DWORD) + outl, k, CRYPT_EXPORTABLE, &k2)) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"WinCAPI:SymmetricKey - Unable to import key");
	}

	return k2;

}


#endif /* XSEC_HAVE_WINCAPI */
