/*
 * Copyright 2003-2005 The Apache Software Foundation.
 *
 * Licensed 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
 *
 * XSECAlgorithmHandlerDefault := Interface class to define handling of
 *								  default encryption algorithms
 *
 * $Id$
 *
 */

// XSEC Includes

#include <xsec/framework/XSECDefs.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMCipher.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/xenc/XENCEncryptionMethod.hpp>
#include <xsec/enc/XSECCryptoKey.hpp>
#include <xsec/enc/XSECCryptoSymmetricKey.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>

#include "XENCAlgorithmHandlerDefault.hpp"

#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/Janitor.hpp>

XERCES_CPP_NAMESPACE_USE

#define _MY_MAX_KEY_SIZE 2048

unsigned char s_3DES_CMS_IV [] = {
	0x4a,
	0xdd,
	0xa2,
	0x2c,
	0x79,
	0xe8,
	0x21,
	0x05
};

unsigned char s_AES_IV [] = {

	0xA6,
	0xA6,
	0xA6,
	0xA6,
	0xA6,
	0xA6,
	0xA6,
	0xA6

};

// --------------------------------------------------------------------------------
//			Compare URI to key type
// --------------------------------------------------------------------------------

void XENCAlgorithmHandlerDefault::mapURIToKey(const XMLCh * uri, 
											  XSECCryptoKey * key,
											  XSECCryptoKey::KeyType &kt,
											  XSECCryptoSymmetricKey::SymmetricKeyType &skt,
											  bool &isSymmetricKeyWrap) {

	if (key == NULL) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::mapURIToKey - trying to process a NULL key");
	}

	XSECCryptoSymmetricKey * keySymmetric;
	bool keyOK = false;

	kt = key->getKeyType();
	skt = XSECCryptoSymmetricKey::KEY_NONE;
	isSymmetricKeyWrap = false;
	
	switch (kt) {

	case XSECCryptoKey::KEY_RSA_PUBLIC :
	case XSECCryptoKey::KEY_RSA_PAIR :
	case XSECCryptoKey::KEY_RSA_PRIVATE :

		keyOK = strEquals(uri, DSIGConstants::s_unicodeStrURIRSA_1_5) ||
			strEquals(uri, DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1);
		break;

	case XSECCryptoKey::KEY_SYMMETRIC :

		keySymmetric = (XSECCryptoSymmetricKey *) key;
		if (keySymmetric != NULL) {
			skt = keySymmetric->getSymmetricKeyType();

			switch (skt) {

			case XSECCryptoSymmetricKey::KEY_3DES_192 :
				isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_3DES);
				keyOK = isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURI3DES_CBC);
				break;
			case XSECCryptoSymmetricKey::KEY_AES_128 :
				isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES128);
				keyOK =  isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_CBC);
				break;
			case XSECCryptoSymmetricKey::KEY_AES_192 :
				isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES192);
				keyOK =  isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_CBC);
				break;
			case XSECCryptoSymmetricKey::KEY_AES_256 :
				isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES256);
				keyOK =  isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_CBC);
				break;
			default:
				break;
			}
		}
		break;

	default:
		 break;
	}

	if (keyOK == false) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::mapURIToKey - key inappropriate for URI");
	}

}

// --------------------------------------------------------------------------------
//			AES Key wrap/unwrap
// --------------------------------------------------------------------------------

unsigned int XENCAlgorithmHandlerDefault::unwrapKeyAES(
   		TXFMChain * cipherText,
		XSECCryptoKey * key,
		safeBuffer & result) {

	// Cat the encrypted key
	XMLByte buf[_MY_MAX_KEY_SIZE];
	XMLByte aesBuf[16];
	XMLByte aesOutBuf[16];
	TXFMBase * b = cipherText->getLastTxfm();
	int sz = b->readBytes(buf, _MY_MAX_KEY_SIZE);

	if (sz <= 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - AES Wrapped Key not found");
	}

	if (sz == _MY_MAX_KEY_SIZE) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - Key to decrypt too big!");
	}

	// Find number of blocks, and ensure we are a multiple of 64 bits
	if (sz % 8 != 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - AES wrapped key not a multiple of 64");
	}

	// Do the decrypt - this cast will throw if wrong, but we should
	// not have been able to get through algorithm checks otherwise
	XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key;

	int blocks = sz / 8;
	int n = blocks - 1;
	for (int j = 5; j >= 0; j--) {
		for (int i = n ; i > 0 ; --i) {

			// Gather blocks to decrypt
			// A
			memcpy(aesBuf, buf, 8);
			// Ri
			memcpy(&aesBuf[8], &buf[8 * i], 8);
			// A mod t
			aesBuf[7] ^= ((n * j) + i);

			// do decrypt
			sk->decryptInit(false, XSECCryptoSymmetricKey::MODE_ECB);		// No padding
			int sz = sk->decrypt(aesBuf, aesOutBuf, 16, 16);
			sz += sk->decryptFinish(&aesOutBuf[sz], 16 - sz);

			if (sz != 16) {
				throw XSECException(XSECException::CipherError, 
					"XENCAlgorithmHandlerDefault - Error performing decrypt in AES Unwrap");
			}

			// Copy back to where we are
			// A
			memcpy(buf, aesOutBuf, 8);
			// Ri
			memcpy(&buf[8 * i], &aesOutBuf[8], 8);

		}
	}

	// Check is valid
	if (memcmp(buf, s_AES_IV, 8) != 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - decrypt failed - AES IV is not correct");
	}

	// Copy to safebuffer
	result.sbMemcpyIn(&buf[8], n * 8);

	return n * 8;
}

bool XENCAlgorithmHandlerDefault::wrapKeyAES(
   		TXFMChain * cipherText,
		XSECCryptoKey * key,
		safeBuffer & result) {

	// get the raw key
	XMLByte buf[_MY_MAX_KEY_SIZE + 8];
	memcpy(buf, s_AES_IV, 8);
	XMLByte aesBuf[16];
	XMLByte aesOutBuf[32];  // Give this an extra block for WinCAPI
	TXFMBase * b = cipherText->getLastTxfm();
	int sz = b->readBytes(&buf[8], _MY_MAX_KEY_SIZE);

	if (sz <= 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - Key not found");
	}

	if (sz == _MY_MAX_KEY_SIZE) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - Key to encrypt too big!");
	}

	// Find number of blocks, and ensure we are a multiple of 64 bits
	if (sz % 8 != 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - AES wrapped key not a multiple of 64");
	}

	// Do the decrypt - this cast will throw if wrong, but we should
	// not have been able to get through algorithm checks otherwise
	XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key;

	int n = sz / 8;

	for (int j = 0; j <= 5; ++j) {
		for (int i = 1 ; i <= n ; ++i) {

			// Gather blocks to decrypt
			// A
			memcpy(aesBuf, buf, 8);
			// Ri
			memcpy(&aesBuf[8], &buf[8 * i], 8);

			// do encrypt
			sk->encryptInit(false, XSECCryptoSymmetricKey::MODE_ECB);
			int sz = sk->encrypt(aesBuf, aesOutBuf, 16, 32);
			sz += sk->encryptFinish(&aesOutBuf[sz], 32 - sz);

			if (sz != 16) {
				throw XSECException(XSECException::CipherError, 
					"XENCAlgorithmHandlerDefault - Error performing encrypt in AES wrap");
			}

			// Copy back to where we are
			// A
			memcpy(buf, aesOutBuf, 8);
			// A mod t
			buf[7] ^= ((n * j) + i);
			// Ri
			memcpy(&buf[8 * i], &aesOutBuf[8], 8);

		}
	}

	// Now we have to base64 encode
	XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64();

	if (!b64) {

		throw XSECException(XSECException::CryptoProviderError, 
				"XENCAlgorithmHandlerDefault - Error getting base64 encoder in AES wrap");

	}

	Janitor<XSECCryptoBase64> j_b64(b64);
	unsigned char * b64Buffer;
	int bufLen = ((n + 1) * 8) * 3;
	XSECnew(b64Buffer, unsigned char[bufLen + 1]);// Overkill
	ArrayJanitor<unsigned char> j_b64Buffer(b64Buffer);

	b64->encodeInit();
	int outputLen = b64->encode (buf, (n+1) * 8, b64Buffer, bufLen);
	outputLen += b64->encodeFinish(&b64Buffer[outputLen], bufLen - outputLen);
	b64Buffer[outputLen] = '\0';

	// Copy to safebuffer
	result.sbStrcpyIn((const char *) b64Buffer);

	return true;
}

// --------------------------------------------------------------------------------
//			DES CMS Key wrap/unwrap
// --------------------------------------------------------------------------------

unsigned int XENCAlgorithmHandlerDefault::unwrapKey3DES(
   		TXFMChain * cipherText,
		XSECCryptoKey * key,
		safeBuffer & result) {

	// Perform an unwrap on the key
	safeBuffer cipherSB;

	// Cat the encrypted key
	XMLByte buf[_MY_MAX_KEY_SIZE];
	TXFMBase * b = cipherText->getLastTxfm();
	int offset = 0;
	int sz = b->readBytes(buf, _MY_MAX_KEY_SIZE);

	while (sz > 0) {
		cipherSB.sbMemcpyIn(offset, buf, sz);
		offset += sz;
		sz = b->readBytes(buf, _MY_MAX_KEY_SIZE);
	}

	if (offset > _MY_MAX_KEY_SIZE) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - Key to decrypt too big!");
	}

	// Do the decrypt - this cast will throw if wrong, but we should
	// not have been able to get through algorithm checks otherwise
	XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key;

	sk->decryptInit(false, XSECCryptoSymmetricKey::MODE_CBC, s_3DES_CMS_IV);
	// If key is bigger than this, then we have a problem
	sz = sk->decrypt(cipherSB.rawBuffer(), buf, offset, _MY_MAX_KEY_SIZE);

	sz += sk->decryptFinish(&buf[sz], _MY_MAX_KEY_SIZE - sz);

	if (sz <= 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - Error decrypting key!");
	}

	// We now have the first cut, reverse the cipher text
	XMLByte buf2[_MY_MAX_KEY_SIZE];
	for (int i = 0; i < sz; ++ i) {
		buf2[sz - i - 1] = buf[i];
	}

	// decrypt again
	sk->decryptInit(false);
	offset = sk->decrypt(buf2, buf, sz, _MY_MAX_KEY_SIZE);
	offset += sk->decryptFinish(&buf[offset], _MY_MAX_KEY_SIZE - offset);

	// Calculate the CMS Key Checksum
	XSECCryptoHash * sha1 = XSECPlatformUtils::g_cryptoProvider->hashSHA1();
	if (!sha1) {

		throw XSECException(XSECException::CryptoProviderError, 
				"XENCAlgorithmHandlerDefault - Error getting SHA-1 object in 3DES unwrap");

	}
	Janitor<XSECCryptoHash> j_sha1(sha1);
	sha1->reset();
	sha1->hash(buf, offset - 8);
	sha1->finish(buf2, _MY_MAX_KEY_SIZE);

	// Compare
	for (int j = 0; j < 8; ++j) {

		if (buf[offset - 8 + j] != buf2[j]) {
			throw XSECException(XSECException::CipherError, 
				"XENCAlgorithmHandlerDefault::unwrapKey3DES - CMS Key Checksum does not match");
		}
	}

	result.sbMemcpyIn(buf, offset - 8);

	return offset - 8;

}

bool XENCAlgorithmHandlerDefault::wrapKey3DES(
   		TXFMChain * cipherText,
		XSECCryptoKey * key,
		safeBuffer & result) {

	// Cat the plaintext key
	XMLByte buf[_MY_MAX_KEY_SIZE + 16];
	TXFMBase * b = cipherText->getLastTxfm();
	int offset = 0;
	int sz = b->readBytes(buf, _MY_MAX_KEY_SIZE);

	if (sz <= 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::wrapKey3DES - Unable to read key");
	}

	if (sz >= _MY_MAX_KEY_SIZE) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::wrapKey3DES - Key to decrypt too big!");
	}

	if (sz % 8 != 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::wrapKey3DES - Key to encrypt not a multiple of 8 bytes");
	}

	// Calculate the CMS Key Checksum

	// Do the first encrypt
	XMLByte buf2[_MY_MAX_KEY_SIZE + 16];

	XSECCryptoHash * sha1 = XSECPlatformUtils::g_cryptoProvider->hashSHA1();
	if (!sha1) {

		throw XSECException(XSECException::CryptoProviderError, 
				"XENCAlgorithmHandlerDefault - Error getting SHA-1 object in 3DES wrap");

	}
	Janitor<XSECCryptoHash> j_sha1(sha1);
	sha1->reset();
	sha1->hash(buf, sz);
	sha1->finish(buf2, _MY_MAX_KEY_SIZE);

	for (int j = 0; j < 8 ; ++j)
		buf[sz++] = buf2[j];

	// Do the first encrypt - this cast will throw if wrong, but we should
	// not have been able to get through algorithm checks otherwise
	XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key;

	sk->encryptInit(false);
	// If key is bigger than this, then we have a problem
	sz = sk->encrypt(buf, buf2, sz, _MY_MAX_KEY_SIZE);
	sz += sk->encryptFinish(&buf2[sz], _MY_MAX_KEY_SIZE - sz);

	if (sz <= 0) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::wrapKey3DES - Error encrypting key!");
	}

	// We now have the first cut, reverse the cipher text
	for (int i = 0; i < sz; ++ i) {
		buf[sz - i - 1] = buf2[i];
	}

	// encrypt again
	sk->encryptInit(false, XSECCryptoSymmetricKey::MODE_CBC, s_3DES_CMS_IV);
	offset = sk->encrypt(buf, buf2, sz, _MY_MAX_KEY_SIZE);
	offset += sk->encryptFinish(&buf2[offset], _MY_MAX_KEY_SIZE - offset);

	// Base64 encode
	XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64();

	if (!b64) {

		throw XSECException(XSECException::CryptoProviderError, 
				"XENCAlgorithmHandlerDefault - Error getting base64 encoder in 3DES wrap");

	}

	Janitor<XSECCryptoBase64> j_b64(b64);
	unsigned char * b64Buffer;
	int bufLen = (offset + 9) * 3;
	XSECnew(b64Buffer, unsigned char[bufLen + 1]);// Overkill
	ArrayJanitor<unsigned char> j_b64Buffer(b64Buffer);

	b64->encodeInit();
	int outputLen = b64->encode (&buf2[8], offset-8, b64Buffer, bufLen);
	outputLen += b64->encodeFinish(&b64Buffer[outputLen], bufLen - outputLen);
	b64Buffer[outputLen] = '\0';

	// Copy to safebuffer
	result.sbStrcpyIn((const char *) b64Buffer);

	return true;

}

// --------------------------------------------------------------------------------
//			InputStream decryption
// --------------------------------------------------------------------------------
	
bool XENCAlgorithmHandlerDefault::appendDecryptCipherTXFM(
		TXFMChain * cipherText,
		XENCEncryptionMethod * encryptionMethod,
		XSECCryptoKey * key,
		XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc
		) {

	// We only support this for bulk Symmetric key algorithms

	XSECCryptoKey::KeyType kt;
	XSECCryptoSymmetricKey::SymmetricKeyType skt;
	bool isKeyWrap = false;

	mapURIToKey(encryptionMethod->getAlgorithm(), key, kt, skt, isKeyWrap);
	if (kt != XSECCryptoKey::KEY_SYMMETRIC || isKeyWrap == true) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::appendDecryptCipherTXFM - only supports bulk symmetric algorithms");
	}

	// Add the decryption TXFM

	TXFMCipher * tcipher;
	XSECnew(tcipher, TXFMCipher(doc, key, false));

	cipherText->appendTxfm(tcipher);

	return true;
}


// --------------------------------------------------------------------------------
//			RSA SafeBuffer decryption
// --------------------------------------------------------------------------------

unsigned int XENCAlgorithmHandlerDefault::doRSADecryptToSafeBuffer(
		TXFMChain * cipherText,
		XENCEncryptionMethod * encryptionMethod,
		XSECCryptoKey * key,
		DOMDocument * doc,
		safeBuffer & result) {

	// Only works with RSA_PRIVATE or PAIR
	if (key->getKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - RSA Decrypt must use private key");
	}

	// Know this is an RSA key, so just cast

	XSECCryptoKeyRSA * rsa = (XSECCryptoKeyRSA *) key;

	// Allocate an output buffer
	unsigned char * decBuf;
	XSECnew(decBuf, unsigned char[rsa->getLength()]);
	ArrayJanitor<unsigned char> j_decBuf(decBuf);

	// Input
	TXFMBase * b = cipherText->getLastTxfm();
	safeBuffer cipherSB;
	XMLByte buf[1024];
	unsigned int offset = 0;

	int bytesRead = b->readBytes(buf, 1024);
	while (bytesRead > 0) {
		cipherSB.sbMemcpyIn(offset, buf, bytesRead);
		offset += bytesRead;
		bytesRead = b->readBytes(buf, 1024);
	}

	unsigned int decryptLen;

	// Now we find out what kind of padding
	if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_1_5)) {

		// Do decrypt
		decryptLen = rsa->privateDecrypt(cipherSB.rawBuffer(), 
												  decBuf, 
												  offset, 
												  rsa->getLength(), 
												  XSECCryptoKeyRSA::PAD_PKCS_1_5, 
												  HASH_NONE);
	}
	else if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1)) {

		if (!strEquals(encryptionMethod->getDigestMethod(), DSIGConstants::s_unicodeStrURISHA1)) {
			throw XSECException(XSECException::CipherError, 
				"XENCAlgorithmHandlerDefault::doRSADecryptToSafeBuffer - Currently only SHA-1 is supported for OAEP");
		}

		// Read out any OAEP params
		unsigned char * oaepParamsBuf = NULL;
		const XMLCh * oaepParams = encryptionMethod->getOAEPparams();
		unsigned int sz = 0;
		if (oaepParams != NULL) {

			char * oaepParamsStr = XMLString::transcode(oaepParams);
			ArrayJanitor<char> j_oaepParamsStr(oaepParamsStr);

			unsigned int bufLen = (unsigned int) strlen(oaepParamsStr);
			oaepParamsBuf = new unsigned char[bufLen];
			ArrayJanitor<unsigned char> j_oaepParamsBuf(oaepParamsBuf);

			XSECCryptoBase64 * b64 = 
				XSECPlatformUtils::g_cryptoProvider->base64();
			Janitor<XSECCryptoBase64> j_b64(b64);

			b64->decodeInit();
			sz = b64->decode((unsigned char *) oaepParamsStr, bufLen, oaepParamsBuf, bufLen);
			sz += b64->decodeFinish(&oaepParamsBuf[sz], bufLen - sz);

			rsa->setOAEPparams(oaepParamsBuf, sz);

		}
		else
			rsa->setOAEPparams(NULL, 0);

		decryptLen = rsa->privateDecrypt(cipherSB.rawBuffer(), 
												  decBuf, 
												  offset, 
												  rsa->getLength(), 
												  XSECCryptoKeyRSA::PAD_OAEP_MGFP1, 
												  HASH_SHA1);

	}

	else {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::doRSADecryptToSafeBuffer - Unknown padding type");
	}
	// Copy to output
	result.sbMemcpyIn(decBuf, decryptLen);
	
	memset(decBuf, 0, decryptLen);

	return decryptLen;

}

// --------------------------------------------------------------------------------
//			SafeBuffer decryption
// --------------------------------------------------------------------------------

unsigned int XENCAlgorithmHandlerDefault::decryptToSafeBuffer(
		TXFMChain * cipherText,
		XENCEncryptionMethod * encryptionMethod,
		XSECCryptoKey * key,
		DOMDocument * doc,
		safeBuffer & result
		) {

	XSECCryptoKey::KeyType kt;
	XSECCryptoSymmetricKey::SymmetricKeyType skt;
	bool isKeyWrap = false;

	if (encryptionMethod == NULL) {
		throw XSECException(XSECException::CipherError,
			"XENCAlgorithmHandlerDefault::decryptToSafeBuffer - Cannot operate with NULL encryption Method");
	}


	// Check the uri against the key type
	mapURIToKey(encryptionMethod->getAlgorithm(), key, kt, skt, isKeyWrap);

	// RSA?
	if (kt == XSECCryptoKey::KEY_RSA_PAIR || 
		kt == XSECCryptoKey::KEY_RSA_PUBLIC || 
		kt == XSECCryptoKey::KEY_RSA_PRIVATE) {

		return doRSADecryptToSafeBuffer(cipherText, encryptionMethod, key, doc, result);

	}

	// Ensure is symmetric before we continue
	if (kt != XSECCryptoKey::KEY_SYMMETRIC) {
		throw XSECException(XSECException::CipherError,
			"XENCAlgorithmHandlerDefault::decryptToSafeBuffer - Not an RSA key, but not symmetric");
	}

	// Key wrap?

	if (isKeyWrap == true) {

		if (skt == XSECCryptoSymmetricKey::KEY_AES_128 ||
			skt == XSECCryptoSymmetricKey::KEY_AES_192 ||
			skt == XSECCryptoSymmetricKey::KEY_AES_256) {

			return unwrapKeyAES(cipherText, key, result);

		}

		else if (skt == XSECCryptoSymmetricKey::KEY_3DES_192) {
			return unwrapKey3DES(cipherText, key, result);
		}

		else {
			throw XSECException(XSECException::CipherError,
				"XENCAlgorithmHandlerDefault::decryptToSafeBuffer - don't know how to do key wrap for algorithm");
		}

	}

	// It's symmetric and it's not a key wrap, so just treat as a block algorithm

	TXFMCipher * tcipher;
	XSECnew(tcipher, TXFMCipher(doc, key, false));

	cipherText->appendTxfm(tcipher);

	// Do the decrypt to the safeBuffer

	result.sbStrcpyIn("");
	unsigned int offset = 0;
	XMLByte buf[1024];
	TXFMBase * b = cipherText->getLastTxfm();

	int bytesRead = b->readBytes(buf, 1024);
	while (bytesRead > 0) {
		result.sbMemcpyIn(offset, buf, bytesRead);
		offset += bytesRead;
		bytesRead = b->readBytes(buf, 1024);
	}

	result[offset] = '\0'; 

	return offset;

}

// --------------------------------------------------------------------------------
//			RSA SafeBuffer encryption
// --------------------------------------------------------------------------------

bool XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer(
		TXFMChain * plainText,
		XENCEncryptionMethod * encryptionMethod,
		XSECCryptoKey * key,
		XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc,
		safeBuffer & result
		) {

	// Only works with RSA_PRIVATE or PAIR
	if (key->getKeyType() == XSECCryptoKey::KEY_RSA_PRIVATE) {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault - RSA Encrypt must use public key");
	}

	XSECCryptoKeyRSA * rsa = (XSECCryptoKeyRSA *) key;
	
	// Allocate an output buffer
	unsigned char * encBuf;
	XSECnew(encBuf, unsigned char[rsa->getLength()]);
	ArrayJanitor<unsigned char> j_encBuf(encBuf);

	// Input
	TXFMBase * b = plainText->getLastTxfm();
	safeBuffer plainSB;
	plainSB.isSensitive();

	XMLByte buf[1024];
	unsigned int offset = 0;

	int bytesRead = b->readBytes(buf, 1024);
	while (bytesRead > 0) {
		plainSB.sbMemcpyIn(offset, buf, bytesRead);
		offset += bytesRead;
		bytesRead = b->readBytes(buf, 1024);
	}

	unsigned int encryptLen;

	// Do decrypt
	if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_1_5)) {
		encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(), 
												  encBuf, 
												  offset, 
												  rsa->getLength(), 
												  XSECCryptoKeyRSA::PAD_PKCS_1_5, 
												  HASH_NONE);
	}

	else if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1)) {

		encryptionMethod->setDigestMethod(DSIGConstants::s_unicodeStrURISHA1);

		// Check for OAEP params
		int oaepParamsLen = rsa->getOAEPparamsLen();
		if (oaepParamsLen > 0) {
			unsigned char * oaepParamsB64;
			XSECnew(oaepParamsB64, unsigned char[oaepParamsLen * 2]);
			ArrayJanitor<unsigned char> j_oaepParamsB64(oaepParamsB64);

			XSECCryptoBase64 * b64 = 
				XSECPlatformUtils::g_cryptoProvider->base64();
			Janitor<XSECCryptoBase64> j_b64(b64);

			b64->encodeInit();
			int sz = b64->encode(rsa->getOAEPparams(), oaepParamsLen, oaepParamsB64, oaepParamsLen *2);
			sz += b64->encodeFinish(&oaepParamsB64[sz], (oaepParamsLen * 2)  - sz);
			oaepParamsB64[sz] = '\0';

			XMLCh * xBuf = XMLString::transcode((char *) oaepParamsB64);
			ArrayJanitor<XMLCh> j_xBuf(xBuf);

			encryptionMethod->setOAEPparams(xBuf);

		}

		encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(), 
										  encBuf, 
										  offset, 
										  rsa->getLength(), 
										  XSECCryptoKeyRSA::PAD_OAEP_MGFP1, 
										  HASH_SHA1);

	}
	else {
		throw XSECException(XSECException::CipherError, 
			"XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer - Unknown padding type");
	}

	// Now need to base64 encode
	XSECCryptoBase64 * b64 = 
		XSECPlatformUtils::g_cryptoProvider->base64();
	Janitor<XSECCryptoBase64> j_b64(b64);

	b64->encodeInit();
	encryptLen = b64->encode(encBuf, encryptLen, buf, 1024);
	result.sbMemcpyIn(buf, encryptLen);
	unsigned int finalLen = b64->encodeFinish(buf, 1024);
	result.sbMemcpyIn(encryptLen, buf, finalLen);
	result[encryptLen + finalLen] = '\0';

	// This is a string, so set the buffer correctly
	result.setBufferType(safeBuffer::BUFFER_CHAR);

	return true;

}


// --------------------------------------------------------------------------------
//			SafeBuffer encryption
// --------------------------------------------------------------------------------

bool XENCAlgorithmHandlerDefault::encryptToSafeBuffer(
		TXFMChain * plainText,
		XENCEncryptionMethod * encryptionMethod,
		XSECCryptoKey * key,
		XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc,
		safeBuffer & result
		) {

	XSECCryptoKey::KeyType kt;
	XSECCryptoSymmetricKey::SymmetricKeyType skt;
	bool isKeyWrap = false;

	if (encryptionMethod == NULL) {
		throw XSECException(XSECException::CipherError,
			"XENCAlgorithmHandlerDefault::encryptToSafeBuffer - Cannot operate with NULL encryption Method");
	}


	// Check the uri against the key type
	mapURIToKey(encryptionMethod->getAlgorithm(), key, kt, skt, isKeyWrap);

	// RSA?
	if (kt == XSECCryptoKey::KEY_RSA_PRIVATE || 
		kt == XSECCryptoKey::KEY_RSA_PUBLIC || 
		kt == XSECCryptoKey::KEY_RSA_PAIR) {

		return doRSAEncryptToSafeBuffer(plainText, encryptionMethod, key, doc, result);

	}

	// Ensure is symmetric before we continue
	if (kt != XSECCryptoKey::KEY_SYMMETRIC) {
		throw XSECException(XSECException::CipherError,
			"XENCAlgorithmHandlerDefault::encryptToSafeBuffer - Not an RSA key, but not symmetric");
	}

	if (isKeyWrap == true) {

		if (skt == XSECCryptoSymmetricKey::KEY_AES_128 ||
			skt == XSECCryptoSymmetricKey::KEY_AES_192 ||
			skt == XSECCryptoSymmetricKey::KEY_AES_256) {

			return wrapKeyAES(plainText, key, result);

		}

		if (skt == XSECCryptoSymmetricKey::KEY_3DES_192) {
			return wrapKey3DES(plainText, key, result);
		}

		else {
			throw XSECException(XSECException::CipherError,
				"XENCAlgorithmHandlerDefault::decryptToSafeBuffer - don't know how to do key wrap for algorithm");
		}

	}
	
	// Must be bulk symmetric - do the encryption

	TXFMCipher *tcipher;
	XSECnew(tcipher, TXFMCipher(doc, key, true));
	plainText->appendTxfm(tcipher);

	// Transform to Base64
	TXFMBase64 * tb64;
	XSECnew(tb64, TXFMBase64(doc, false));
	plainText->appendTxfm(tb64);

	// Read into the safeBuffer
	result = "";

	result << plainText->getLastTxfm();

	return true;

}
// --------------------------------------------------------------------------------
//			Key Creation
// --------------------------------------------------------------------------------

XSECCryptoKey * XENCAlgorithmHandlerDefault::createKeyForURI(
		const XMLCh * uri,
		const unsigned char * keyBuffer,
		unsigned int keyLen
		) {

	XSECCryptoSymmetricKey * sk = NULL;

	if (strEquals(uri, DSIGConstants::s_unicodeStrURI3DES_CBC)) {
		sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192);
	}
	else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_CBC)) {
		sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128);
	}
	else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_CBC)) {
		sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192);
	}
	else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_CBC)) {
		sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256);
	}

	if (sk != NULL) {
		sk->setKey(keyBuffer, keyLen);
		return sk;
	}

	throw XSECException(XSECException::CipherError, 
		"XENCAlgorithmHandlerDefault - URI Provided, but cannot create associated key");

}


// --------------------------------------------------------------------------------
//			Clone
// --------------------------------------------------------------------------------

XSECAlgorithmHandler * XENCAlgorithmHandlerDefault::clone(void) const {

	XENCAlgorithmHandlerDefault * ret;
	XSECnew(ret, XENCAlgorithmHandlerDefault);

	return ret;

}

// --------------------------------------------------------------------------------
//			Unsupported operations
// --------------------------------------------------------------------------------

unsigned int XENCAlgorithmHandlerDefault::signToSafeBuffer(
		TXFMChain * inputBytes,
		const XMLCh * URI,
		XSECCryptoKey * key,
		unsigned int outputLength,
		safeBuffer & result) {

	throw XSECException(XSECException::AlgorithmMapperError, 
			"XENCAlgorithmHandlerDefault - Signature operations not supported");

}


bool XENCAlgorithmHandlerDefault::appendSignatureHashTxfm(
		TXFMChain * inputBytes,
		const XMLCh * URI,
		XSECCryptoKey * key) {

	throw XSECException(XSECException::AlgorithmMapperError, 
			"XENCAlgorithmHandlerDefault - Signature operations not supported");

}

bool XENCAlgorithmHandlerDefault::verifyBase64Signature(
		TXFMChain * inputBytes,
		const XMLCh * URI,
		const char * sig,
		unsigned int outputLength,
		XSECCryptoKey * key) {

	throw XSECException(XSECException::AlgorithmMapperError, 
			"XENCAlgorithmHandlerDefault - Signature operations not supported");

}

bool XENCAlgorithmHandlerDefault::appendHashTxfm(
		TXFMChain * inputBytes,
		const XMLCh * URI) {

	throw XSECException(XSECException::AlgorithmMapperError, 
			"XENCAlgorithmHandlerDefault - Hash operations not supported");

}

