/**
 * 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
 *
 * XENCCipherImpl := Implementation of the main encryption worker class
 *
 * $Id$
 *
 */

// XSEC Includes

#include <xsec/enc/XSECKeyInfoResolver.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/framework/XSECAlgorithmMapper.hpp>
#include <xsec/framework/XSECAlgorithmHandler.hpp>
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/enc/XSECCryptoKey.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMBase.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/transformers/TXFMSB.hpp>
#include <xsec/transformers/TXFMURL.hpp>
#include <xsec/transformers/TXFMDocObject.hpp>
#include <xsec/transformers/TXFMConcatChains.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>
#include <xsec/utils/XSECBinTXFMInputStream.hpp>

#include "XENCCipherImpl.hpp"
#include "XENCEncryptedDataImpl.hpp"
#include "XENCEncryptedKeyImpl.hpp"
#include "XENCEncryptionMethodImpl.hpp"
#include "XENCAlgorithmHandlerDefault.hpp"
#include "../../utils/XSECAutoPtr.hpp"
#include "../../utils/XSECDOMUtils.hpp"

#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/util/Janitor.hpp>

// With all the characters - just uplift entire thing

XERCES_CPP_NAMESPACE_USE

#include <iostream>
using std::cout;

// --------------------------------------------------------------------------------
//			Constant Strings
// --------------------------------------------------------------------------------


const XMLCh s_tagname[] = {

chLatin_f, chLatin_r, chLatin_a, chLatin_g, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull };

const XMLCh s_noData[] = { chLatin_n, chLatin_o, chLatin_D, chLatin_a, chLatin_t, chLatin_a, chNull };

const XMLCh s_ds[] = { chLatin_d, chLatin_s, chNull };

// --------------------------------------------------------------------------------
//			Constructors
// --------------------------------------------------------------------------------

XENCCipherImpl::XENCCipherImpl(DOMDocument * doc) :
    mp_doc(doc), mp_encryptedData(NULL), mp_key(NULL), mp_kek(NULL), mp_keyInfoResolver(NULL) {

    XSECnew(mp_env, XSECEnv(doc));
    mp_env->setDSIGNSPrefix(s_ds);
    m_keyDerived = false;
    m_kekDerived = false;
    m_useExcC14nSerialisation = true;

}

XENCCipherImpl::~XENCCipherImpl() {

    if (mp_encryptedData != NULL)
        delete mp_encryptedData;

    if (mp_key != NULL)
        delete mp_key;

    if (mp_kek != NULL)
        delete mp_kek;

    if (mp_env != NULL)
        delete mp_env;

    if (mp_keyInfoResolver != NULL)
        delete mp_keyInfoResolver;

}

// --------------------------------------------------------------------------------
//			Initialiser
// --------------------------------------------------------------------------------

void XENCCipherImpl::Initialise(void) {

    XENCAlgorithmHandlerDefault def;

    // Register default encryption algorithm handlers

    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURI3DES_CBC, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIAES128_CBC, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIAES192_CBC, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIAES256_CBC, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIAES128_GCM, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIAES192_GCM, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIAES256_GCM, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_3DES, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_AES128, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_AES192, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_AES256, def);
    //XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_AES128_PAD, def);
    //XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_AES192_PAD, def);
    //XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIKW_AES256_PAD, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_1_5, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, def);
    XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_OAEP, def);

}

// --------------------------------------------------------------------------------
//			Set/get the namespace prefix to be used when creating nodes
// --------------------------------------------------------------------------------

void XENCCipherImpl::setXENCNSPrefix(const XMLCh * prefix) {

    mp_env->setXENCNSPrefix(prefix);

}

const XMLCh * XENCCipherImpl::getXENCNSPrefix(void) const {

    return mp_env->getXENCNSPrefix();

}
// --------------------------------------------------------------------------------
//			Key Info resolvers
// --------------------------------------------------------------------------------

void XENCCipherImpl::setKeyInfoResolver(const XSECKeyInfoResolver * resolver) {

    if (mp_keyInfoResolver != NULL)
        delete mp_keyInfoResolver;

    mp_keyInfoResolver = resolver->clone();

}

// --------------------------------------------------------------------------------
//			Key Info resolvers
// --------------------------------------------------------------------------------

XENCEncryptedData * XENCCipherImpl::getEncryptedData() const {

    return mp_encryptedData;

}
// --------------------------------------------------------------------------------
//			Keys
// --------------------------------------------------------------------------------

void XENCCipherImpl::setKey(XSECCryptoKey * key) {

    if (mp_key != NULL)
        delete mp_key;

    mp_key = key;
    m_keyDerived = false;

}

void XENCCipherImpl::setKEK(XSECCryptoKey * key) {

    if (mp_kek != NULL)
        delete mp_kek;

    mp_kek = key;
    m_kekDerived = false;

}

// --------------------------------------------------------------------------------
//			Serialise/Deserialise an element
// --------------------------------------------------------------------------------

DOMDocumentFragment * XENCCipherImpl::deSerialise(safeBuffer &content, DOMNode * ctx) {

    DOMDocumentFragment * result;

    // Create the context to parse the document against
    safeBuffer sb, sbt;
    sb.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty);
    //sb.sbXMLChAppendCh(chUnicodeMarker);
    //sb.sbXMLChCat8("<?xml version=\"1.0\" encoding=\"UTF-16\"?><");
    sb.sbXMLChAppendCh(chOpenAngle);
    sb.sbXMLChCat(s_tagname);

    // Run through each node up to the document node and find any
    // xmlns: nodes that may be needed during the parse of the decrypted content

    DOMNode * ctxParent = ctx->getParentNode();
    DOMNode * wk = ctxParent;

    while (wk != NULL) {

        DOMNamedNodeMap * atts = wk->getAttributes();
        XMLSize_t length;
        if (atts != NULL)
            length = atts->getLength();
        else
            length = 0;

        for (XMLSize_t i = 0; i < length; ++i) {
            DOMNode * att = atts->item(i);
            if (strEquals(att->getNodeName(), DSIGConstants::s_unicodeStrXmlns) ||
                    (XMLString::compareNString(att->getNodeName(), DSIGConstants::s_unicodeStrXmlns, 5) == 0 &&
                            att->getNodeName()[5] == chColon)) {

                // Check to see if this node has already been found
                DOMNode * p = ctxParent;
                bool found = false;
                while (p != wk) {
                    DOMNamedNodeMap * tstAtts = p->getAttributes();
                    if (tstAtts != NULL && tstAtts->getNamedItem(att->getNodeName()) != NULL) {
                        found = true;
                        break;
                    }
                    p = p->getParentNode();
                }
                if (found == false) {

                    // This is an attribute node that needs to be added
                    sb.sbXMLChAppendCh(chSpace);
                    sb.sbXMLChCat(att->getNodeName());
                    sb.sbXMLChAppendCh(chEqual);
                    sb.sbXMLChAppendCh(chDoubleQuote);
                    sb.sbXMLChCat(att->getNodeValue());
                    sb.sbXMLChAppendCh(chDoubleQuote);
                }
            }
        }
        wk = wk->getParentNode();
    }
    sb.sbXMLChAppendCh(chCloseAngle);

    char* prefix = transcodeToUTF8(sb.rawXMLChBuffer());
    sbt = prefix;
    XSEC_RELEASE_XMLCH(prefix);

    const char * crcb = content.rawCharBuffer();
    int offset = 0;
    if (crcb[0] == '<' && crcb[1] == '?') {
        // Have a PI prefix - get rid of it
        int i = 2;
        while (crcb[i] != '\0' && crcb[i] != '>')
            ++i;

        if (crcb[i] == '>')
            offset = i + 1;
    }

    sbt.sbStrcatIn(&crcb[offset]);

    // Terminate the string
    sb.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty);
    sb.sbXMLChAppendCh(chOpenAngle);
    sb.sbXMLChAppendCh(chForwardSlash);
    sb.sbXMLChCat(s_tagname);
    sb.sbXMLChAppendCh(chCloseAngle);

    char* trailer = transcodeToUTF8(sb.rawXMLChBuffer());
    sbt.sbStrcatIn(trailer);
    XSEC_RELEASE_XMLCH(trailer);

    // Create an input source
    XMLSize_t bytes = XMLString::stringLen(sbt.rawCharBuffer());
    MemBufInputSource memIS((const XMLByte*) sbt.rawBuffer(), bytes, "XSECMem");

    XercesDOMParser parser;
    parser.setDoNamespaces(true);
    parser.setLoadExternalDTD(false);

    SecurityManager securityManager;
    securityManager.setEntityExpansionLimit(XSEC_ENTITY_EXPANSION_LIMIT);
    parser.setSecurityManager(&securityManager);

    parser.parse(memIS);
    XMLSize_t errorCount = parser.getErrorCount();
    if (errorCount > 0)
        throw XSECException(XSECException::CipherError, "Errors occurred during de-serialisation of decrypted element content");

    DOMDocument * doc = parser.getDocument();

    // Create a DocumentFragment to hold the children of the parsed doc element
    DOMDocument *ctxDocument = ctx->getOwnerDocument();
    result = ctxDocument->createDocumentFragment();
    Janitor<DOMDocumentFragment> j_result(result);

    // Now get the children of the document into a DOC fragment
    DOMNode * fragElt = doc->getDocumentElement();
    DOMNode * child;

    if (fragElt != NULL) {
        child = fragElt->getFirstChild();
    } else {

        throw XSECException(XSECException::CipherError, "XENCCipher::deSerialse - re-parsed document unexpectedly empty");
    }

    while (child != NULL) {
        result->appendChild(ctxDocument->importNode(child, true));
        child = child->getNextSibling();
    }

    // Done!

    j_result.release();
    return result;
}

// --------------------------------------------------------------------------------
//			Decrypt an Element and replace in original document
// --------------------------------------------------------------------------------

XSECCryptoKey * XENCCipherImpl::decryptKeyFromKeyInfoList(DSIGKeyInfoList * kil) {

    XSECCryptoKey * ret = NULL;
    const XSECAlgorithmHandler *handler;

    int kLen = (int) kil->getSize();

    for (int i = 0; ret == NULL && i < kLen; ++i) {

        if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_ENCRYPTEDKEY) {

            XENCEncryptedKey * ek = (XENCEncryptedKey*) (kil->item(i));
            volatile XMLByte buffer[1024];
            try {
                // Have to cast off volatile
                int keySize = decryptKey(ek, (XMLByte *) buffer, 1024);

                if (keySize > 0) {
                    // Try to map the key

                    XENCEncryptionMethod * encryptionMethod = mp_encryptedData->getEncryptionMethod();

                    if (encryptionMethod != NULL) {

                        handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
                            mp_encryptedData->getEncryptionMethod()->getAlgorithm());

                        if (handler != NULL)
                            ret = handler->createKeyForURI(mp_encryptedData->getEncryptionMethod()->getAlgorithm(),
                                (XMLByte *) buffer, keySize);
                    }
                }
            }

            catch (const XSECCryptoException&) {
                /* Do nothing - this is likely to be a bad decrypt on a public key */
            } catch (...) {
                memset((void *) buffer, 0, 1024);
                throw;
            }

            // Clear out the key buffer
            memset((void *) buffer, 0, 1024);
        }
    }

    return ret;
}

XENCEncryptedData * XENCCipherImpl::loadEncryptedData(DOMElement * element) {

    // First of all load the element
    if (mp_encryptedData != NULL)
        delete mp_encryptedData;

    XSECnew(mp_encryptedData, XENCEncryptedDataImpl(mp_env, element));

    // Load
    mp_encryptedData->load();

    return mp_encryptedData;

}

DOMDocument * XENCCipherImpl::decryptElement(DOMElement * element) {

    // First of all load the element
    if (mp_encryptedData != NULL)
        delete mp_encryptedData;

    XSECnew(mp_encryptedData, XENCEncryptedDataImpl(mp_env, element));

    // Load
    mp_encryptedData->load();

    return decryptElement();

}

DOMNode * XENCCipherImpl::decryptElementDetached(DOMElement * element) {

    // First of all load the element
    if (mp_encryptedData != NULL)
        delete mp_encryptedData;

    XSECnew(mp_encryptedData, XENCEncryptedDataImpl(mp_env, element));

    // Load
    mp_encryptedData->load();

    return decryptElementDetached();

}

DOMNode * XENCCipherImpl::decryptElementDetached() {

    const XSECAlgorithmHandler *handler;

    if (mp_encryptedData == NULL) {

        throw XSECException(XSECException::CipherError, "XENCCipherImpl::decryptElement - no element loaded for decryption");

    }

    // Check that this is a valid type
    const XMLCh * typeURI = mp_encryptedData->getType();

    if (typeURI != NULL && !strEquals(typeURI, DSIGConstants::s_unicodeStrURIXENC_ELEMENT) && !strEquals(typeURI,
        DSIGConstants::s_unicodeStrURIXENC_CONTENT)) {

        throw XSECException(XSECException::CipherError, "XENCCipherImpl::decryptElement - Type not Element or Content");

    }

    if (m_keyDerived && mp_key) {
        delete mp_key;
        mp_key = NULL;
    }

    // Make sure we have a key before we do anything else too drastic
    if (mp_key == NULL) {

        if (mp_keyInfoResolver != NULL)
            mp_key = mp_keyInfoResolver->resolveKey(mp_encryptedData->getKeyInfoList());

        if (mp_key == NULL) {

            mp_key = decryptKeyFromKeyInfoList(mp_encryptedData->getKeyInfoList());

        }

        if (mp_key == NULL) {

            throw XSECException(XSECException::CipherError, "XENCCipherImpl::decryptElement - No key set and cannot resolve");
        }

        m_keyDerived = true;
    }

    // Get the raw encrypted data
    TXFMChain * c = mp_encryptedData->createCipherTXFMChain();
    Janitor<TXFMChain> j_c(c);

    // Get the Algorithm handler for the algorithm
    XENCEncryptionMethod * encryptionMethod = mp_encryptedData->getEncryptionMethod();

    if (encryptionMethod != NULL) {

        handler
            = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(mp_encryptedData->getEncryptionMethod()->getAlgorithm());

    }

    else {

        handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(XSECAlgorithmMapper::s_defaultEncryptionMapping);

    }

    safeBuffer sb("");
    unsigned int decryptLen;

    if (handler != NULL) {

        decryptLen = handler->decryptToSafeBuffer(c, mp_encryptedData->getEncryptionMethod(), mp_key,
            mp_env->getParentDocument(), sb);
    } else {

        // Very strange if we get here - any problems should throw an
        // exception in the AlgorithmMapper.

        throw XSECException(XSECException::CipherError,
            "XENCCipherImpl::decryptElement - Error retrieving a handler for algorithm");

    }

    sb[decryptLen] = '\0';

    // Now de-serialise
    DOMElement * element = mp_encryptedData->getElement();
    DOMDocumentFragment * frag = deSerialise(sb, element);

    return frag;

}

DOMDocument * XENCCipherImpl::decryptElement() {

    // Call the worker
    DOMElement * element = mp_encryptedData->getElement();
    DOMDocumentFragment * frag = (DOMDocumentFragment *) decryptElementDetached();

    if (frag != NULL) {

        // Have something to replace current element with
        DOMNode * p = element->getParentNode();

        // By inserting the DocumentFragment, we effectively insert the children
        p->replaceChild(frag, element);

        // Delete the frag and the old element
        frag->release();
        element->release();

    }

    return mp_env->getParentDocument();

}

// --------------------------------------------------------------------------------
//			Decrypt data to an input stream
// --------------------------------------------------------------------------------

XSECBinTXFMInputStream * XENCCipherImpl::decryptToBinInputStream(
    XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * element
) {

    const XSECAlgorithmHandler *handler;

    // First of all load the element
    if (mp_encryptedData != NULL)
    	delete mp_encryptedData;

    XSECnew(mp_encryptedData,
        XENCEncryptedDataImpl(mp_env, element));

    // Load
    mp_encryptedData->load();

    // Check key is valid
    if (m_keyDerived && mp_key) {
        delete mp_key;
        mp_key = NULL;
    }

    // Make sure we have a key before we do anything else too drastic
    if (mp_key == NULL) {

        if (mp_keyInfoResolver != NULL)
        mp_key = mp_keyInfoResolver->resolveKey(mp_encryptedData->getKeyInfoList());

        if (mp_key == NULL) {

            mp_key = decryptKeyFromKeyInfoList(mp_encryptedData->getKeyInfoList());

        }

        if (mp_key == NULL) {

            throw XSECException(XSECException::CipherError,
                "XENCCipherImpl::decryptToBinInputStream - No key set and cannot resolve");
        }

        m_keyDerived = true;
    }

    // Get the raw encrypted data
    TXFMChain * c = mp_encryptedData->createCipherTXFMChain();
    Janitor<TXFMChain> j_c(c);

    // Get the Algorithm handler for the algorithm
    XENCEncryptionMethod * encryptionMethod = mp_encryptedData->getEncryptionMethod();

    if (encryptionMethod != NULL) {

        handler =
        XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
            mp_encryptedData->getEncryptionMethod()->getAlgorithm());

    }

    else {

        handler =
        XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
            XSECAlgorithmMapper::s_defaultEncryptionMapping);

    }

    if (handler != NULL) {

        if (handler->appendDecryptCipherTXFM(c,
                mp_encryptedData->getEncryptionMethod(),
                mp_key,
                mp_env->getParentDocument()) != true) {
            throw XSECException(XSECException::CipherError,
                "XENCCipherImpl::decryptToBinInputStream - error appending final transform");
        }

    }
    else {

        // Very strange if we get here - any problems should throw an
        // exception in the AlgorithmMapper.

        throw XSECException(XSECException::CipherError,
            "XENCCipherImpl::decryptElement - Error retrieving a handler for algorithm");

    }

    // Wrap in a Bin input stream
    XSECBinTXFMInputStream * ret;
    ret = new XSECBinTXFMInputStream(c); // Probs with MSVC++ mean no XSECnew
    j_c.release(); // Now owned by "ret"

    return ret;

}

// --------------------------------------------------------------------------------
//			Decrypt a key in an XENCEncryptedKey element
// --------------------------------------------------------------------------------

int XENCCipherImpl::decryptKey(XENCEncryptedKey * encryptedKey, XMLByte * rawKey, int maxKeySize) {

    // Check KEK is valid
    if (m_kekDerived && mp_kek) {
        delete mp_kek;
        mp_kek = NULL;
    }

    // Make sure we have a key before we do anything else too drastic
    if (mp_kek == NULL) {

        if (mp_keyInfoResolver != NULL)
            mp_kek = mp_keyInfoResolver->resolveKey(encryptedKey->getKeyInfoList());

        if (mp_kek == NULL) {

            throw XSECException(XSECException::CipherError, "XENCCipherImpl::decryptKey - No KEK set and cannot resolve");
        }
        m_kekDerived = true;
    }

    // Get the raw encrypted data
    TXFMChain * c = ((XENCEncryptedKeyImpl *) encryptedKey)->createCipherTXFMChain();
    Janitor<TXFMChain> j_c(c);

    // Get the Algorithm handler for the algorithm
    XENCEncryptionMethod * encryptionMethod = encryptedKey->getEncryptionMethod();
    const XSECAlgorithmHandler *handler;

    if (encryptionMethod != NULL) {

        handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(encryptedKey->getEncryptionMethod()->getAlgorithm());

    }

    else {

        handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(XSECAlgorithmMapper::s_defaultEncryptionMapping);

    }

    safeBuffer sb("");
    unsigned int keySize;

    if (handler != NULL) {

        keySize = handler->decryptToSafeBuffer(c, encryptedKey->getEncryptionMethod(), mp_kek, mp_env->getParentDocument(), sb);
    } else {

        // Very strange if we get here - any problems should throw an
        // exception in the AlgorithmMapper.

        throw XSECException(XSECException::CipherError,
            "XENCCipherImpl::decryptElement - Error retrieving a handler for algorithm");

    }

    keySize = (keySize < (unsigned int) maxKeySize ? keySize : (unsigned int) maxKeySize);
    memcpy(rawKey, sb.rawBuffer(), keySize);

    return keySize;
}
// --------------------------------------------------------------------------------
//			Decrypt a key from a DOM structure
// --------------------------------------------------------------------------------

int XENCCipherImpl::decryptKey(DOMElement * keyNode, XMLByte * rawKey, int maxKeySize) {

    XENCEncryptedKey * encryptedKey = loadEncryptedKey(keyNode);
    Janitor<XENCEncryptedKey> j_encryptedKey(encryptedKey);

    // Now decrypt!
    return decryptKey(encryptedKey, rawKey, maxKeySize);

}

XENCEncryptedKey * XENCCipherImpl::loadEncryptedKey(DOMElement * keyNode) {

    XENCEncryptedKeyImpl * encryptedKey;
    XSECnew(encryptedKey, XENCEncryptedKeyImpl(mp_env, keyNode));
    Janitor<XENCEncryptedKeyImpl> j_encryptedKey(encryptedKey);

    // Load
    encryptedKey->load();

    j_encryptedKey.release();
    return encryptedKey;

}
// --------------------------------------------------------------------------------
//			Encrypt a BinInputStream
// --------------------------------------------------------------------------------

XENCEncryptedData * XENCCipherImpl::encryptBinInputStream(
    XERCES_CPP_NAMESPACE_QUALIFIER BinInputStream * plainText,
    const XMLCh * algorithmURI) {

    TXFMURL * uri;
    XSECnew(uri, TXFMURL(mp_doc, NULL));

    uri->setInput(plainText);
    TXFMChain c(uri);

    return encryptTXFMChain(&c, algorithmURI);

}

// --------------------------------------------------------------------------------
//			Encrypt a TXFMChain
// --------------------------------------------------------------------------------

XENCEncryptedData * XENCCipherImpl::encryptTXFMChain(TXFMChain * plainText, const XMLCh * algorithmURI) {

    // Make sure we have a key before we do anything too drastic
    if (mp_key == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptTXFMChain - No key set");
    }
    else if (algorithmURI == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptTXFMChain - No algorithm set");
    }

    // Create the element with a dummy encrypted value

    if (mp_encryptedData != NULL) {
        delete mp_encryptedData;
        mp_encryptedData = NULL;
    }

    XSECnew(mp_encryptedData, XENCEncryptedDataImpl(mp_env));
    mp_encryptedData->createBlankEncryptedData(XENCCipherData::VALUE_TYPE, algorithmURI, s_noData);

    // Perform the encryption
    const XSECAlgorithmHandler *handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithmURI);
    if (!handler) {
        // Very strange if we get here - any problems should throw an
        // exception in the AlgorithmMapper.

        throw XSECException(XSECException::CipherError,
            "XENCCipherImpl::encryptTXFMChain - Error retrieving a handler for algorithm");
    }

    safeBuffer sb;
    handler->encryptToSafeBuffer(plainText, mp_encryptedData->getEncryptionMethod(), mp_key, mp_env->getParentDocument(), sb);

    // Set the value
    XENCCipherValue * val = mp_encryptedData->getCipherData()->getCipherValue();

    val->setCipherString(sb.sbStrToXMLCh());

    return mp_encryptedData;

}

// --------------------------------------------------------------------------------
//			Encrypt a key
// --------------------------------------------------------------------------------

XENCEncryptedKey * XENCCipherImpl::encryptKey(
        const unsigned char* keyBuffer,
        unsigned int keyLen,
        const XMLCh* algorithmURI,
        const XMLCh* mgfURI,
        unsigned char* oaepParams,
        unsigned int oaepParamsLen) {

    if (mp_kek == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptKey - No KEK set");
    }
    else if (algorithmURI == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptKey - No algorithm set");
    }

    // Create the element with a dummy encrypted value

    XENCEncryptedKeyImpl * encryptedKey;

    XSECnew(encryptedKey, XENCEncryptedKeyImpl(mp_env));
    Janitor<XENCEncryptedKeyImpl> j_encryptedKey(encryptedKey);

    encryptedKey->createBlankEncryptedKey(XENCCipherData::VALUE_TYPE, algorithmURI, s_noData);

    if (mgfURI)
        encryptedKey->getEncryptionMethod()->setMGF(mgfURI);

    if (oaepParams != NULL && 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(oaepParams, oaepParamsLen, oaepParamsB64, oaepParamsLen *2);
        sz += b64->encodeFinish(&oaepParamsB64[sz], (oaepParamsLen * 2)  - sz);
        oaepParamsB64[sz] = '\0';

        XSECAutoPtrXMLCh xBuf((char*) oaepParamsB64);

        encryptedKey->getEncryptionMethod()->setOAEPparams(xBuf.get());
    }

    // Create a transform chain to do pass the key to the encryption.

    safeBuffer rawKey;
    rawKey.isSensitive();
    rawKey.sbMemcpyIn(keyBuffer, keyLen);

    TXFMSB * tsb;
    XSECnew(tsb, TXFMSB(mp_doc));

    TXFMChain * c;
    XSECnew(c, TXFMChain(tsb));
    Janitor<TXFMChain> j_c(c);

    tsb->setInput(rawKey, keyLen);

    // Perform the encryption
    const XSECAlgorithmHandler *handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithmURI);
    if (!handler) {
        // Very strange if we get here - any problems should throw an
        // exception in the AlgorithmMapper.

        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptKey - Error retrieving a handler for algorithm");
    }

    safeBuffer sb;
    handler->encryptToSafeBuffer(c, encryptedKey->getEncryptionMethod(), mp_kek, mp_env->getParentDocument(), sb);

    // Set the value
    XENCCipherValue * val = encryptedKey->getCipherData()->getCipherValue();

    val->setCipherString(sb.sbStrToXMLCh());

    j_encryptedKey.release();
    return encryptedKey;
}

// --------------------------------------------------------------------------------
//			Create an EncryptedData element
// --------------------------------------------------------------------------------

XENCEncryptedData * XENCCipherImpl::createEncryptedData(XENCCipherData::XENCCipherDataType type, const XMLCh * algorithm,
    const XMLCh * value) {

    // Clean out anything currently being used
    if (mp_encryptedData != NULL) {
        delete mp_encryptedData;
        mp_encryptedData = NULL;
    }
    // Create a new EncryptedData element

    XSECnew(mp_encryptedData, XENCEncryptedDataImpl(mp_env));
    mp_encryptedData->createBlankEncryptedData(type, algorithm, value);

    return mp_encryptedData;
}

// --------------------------------------------------------------------------------
//			Encrypt an element
// --------------------------------------------------------------------------------

DOMNode * XENCCipherImpl::encryptElementDetached(DOMElement * element, const XMLCh * algorithmURI) {

    // Make sure we have a key before we do anything too drastic
    if (mp_key == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptElement - No key set");
    }
    else if (algorithmURI == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptElement - No algorithm set");
    }

    // Create a transform chain to do the encryption
    TXFMDocObject * tdocObj;
    XSECnew(tdocObj, TXFMDocObject(mp_doc));
    TXFMChain * c;
    XSECnew(c, TXFMChain(tdocObj));

    Janitor<TXFMChain> j_c(c);

    tdocObj->setInput(mp_doc, element);

    // Now need to serialise the element - easiest to just use a canonicalizer
    TXFMC14n *tc14n;
    XSECnew(tc14n, TXFMC14n(mp_doc));
    c->appendTxfm(tc14n);

    tc14n->activateComments();
    if (m_useExcC14nSerialisation)
        tc14n->setExclusive();

    // Do the hard work

    encryptTXFMChain(c, algorithmURI);

    mp_encryptedData->setType(DSIGConstants::s_unicodeStrURIXENC_ELEMENT);
    return mp_encryptedData->getElement();

}

DOMDocument * XENCCipherImpl::encryptElement(DOMElement * element, const XMLCh * algorithmURI) {

    // Do the actual encryption work
    encryptElementDetached(element, algorithmURI);

    // Replace original element
    DOMNode * p = element->getParentNode();

    if (p == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptElement - Passed in element has no parent");
    }

    p->replaceChild(mp_encryptedData->getElement(), element);

    // Clear up the old child
    element->release();

    return mp_doc;

}

// --------------------------------------------------------------------------------
//			Encrypt an element's children
// --------------------------------------------------------------------------------

DOMDocument * XENCCipherImpl::encryptElementContent(
    XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * element,
    const XMLCh * algorithmURI) {

    // Do the work
    encryptElementContentDetached(element, algorithmURI);

    // Delete current children
    DOMNode * n = element->getFirstChild();
    while (n != NULL) {

        element->removeChild(n);
        n->release();

        n = element->getFirstChild();

    }

    // Now add the EncryptedData
    element->appendChild(mp_encryptedData->getElement());

    return mp_doc;

}

DOMNode * XENCCipherImpl::encryptElementContentDetached(
    XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * element,
    const XMLCh * algorithmURI) {

    // Make sure we have a key before we do anything too drastic
    if (mp_key == NULL) {
        throw XSECException(XSECException::CipherError,
            "XENCCipherImpl::encryptElementContentDetached - No key set");
    }
    else if (algorithmURI == NULL) {
        throw XSECException(XSECException::CipherError, "XENCCipherImpl::encryptElementContentDetached - No algorithm set");
    }

    // Create a transform chain to do the encryption
    // We use a concat transformer so we can concatinate the bytestreams
    // from the serialisation of each child in turn

    TXFMConcatChains * tcat;
    XSECnew(tcat, TXFMConcatChains(mp_doc));
    TXFMChain * c;
    XSECnew(c, TXFMChain(tcat));
    Janitor<TXFMChain> j_c(c);

    DOMNode *n = element->getFirstChild();

    while (n != NULL) {

        TXFMDocObject * tdocObj;
        XSECnew(tdocObj, TXFMDocObject(mp_doc));
        TXFMChain * tc;
        XSECnew(tc, TXFMChain(tdocObj));

        // Add to the concat object, which will own it, so if anything throws
        // the memory will be released.

        tcat->setInput(tc);
        tdocObj->setInput(mp_doc, n);

        // Now need to serialise the element - easiest to just use a canonicaliser
        TXFMC14n *tc14n;
        XSECnew(tc14n, TXFMC14n(mp_doc));
        tc->appendTxfm(tc14n);

        tc14n->activateComments();
        if (m_useExcC14nSerialisation)
        tc14n->setExclusive();

        n = n->getNextSibling();

    }

    encryptTXFMChain(c, algorithmURI);

    mp_encryptedData->setType(DSIGConstants::s_unicodeStrURIXENC_CONTENT);

    return mp_encryptedData->getElement();

}

// --------------------------------------------------------------------------------
//			Pretty Print functions
// --------------------------------------------------------------------------------

void XENCCipherImpl::setExclusiveC14nSerialisation(bool flag) {

    m_useExcC14nSerialisation = flag;
}

bool XENCCipherImpl::getExclusiveC14nSerialisation() const {

    return m_useExcC14nSerialisation;

}

// --------------------------------------------------------------------------------
//			Exclusive C14n serialisation setting
// --------------------------------------------------------------------------------

void XENCCipherImpl::setPrettyPrint(bool flag) {

    mp_env->setPrettyPrintFlag(flag);

}

bool XENCCipherImpl::getPrettyPrint(void) const {

    return mp_env->getPrettyPrintFlag();

}
