/**
 * 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
 *
 * XSECAlgorithmHandlerDefault := Interface class to define handling of
 *                                  default encryption algorithms
 *
 * $Id$
 *
 */

// XSEC Includes

#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/enc/XSECCryptoKey.hpp>
#include <xsec/enc/XSECCryptoSymmetricKey.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMCipher.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMSB.hpp>
#include <xsec/xenc/XENCEncryptionMethod.hpp>

#include "../../utils/XSECAutoPtr.hpp"
#include "../../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,
                                              const XSECCryptoKey* key,
                                              XSECCryptoKey::KeyType& kt,
                                              XSECCryptoSymmetricKey::SymmetricKeyType& skt,
                                              bool& isSymmetricKeyWrap,
                                              XSECCryptoSymmetricKey::SymmetricKeyMode& skm,
                                              unsigned int& taglen) const {

    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;
    skm = XSECCryptoSymmetricKey::MODE_NONE;
    taglen = 0;

    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) ||
            strEquals(uri, DSIGConstants::s_unicodeStrURIRSA_OAEP);
        break;

    case XSECCryptoKey::KEY_SYMMETRIC :

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

            switch (skt) {

            case XSECCryptoSymmetricKey::KEY_3DES_192 :
                if (strEquals(uri, DSIGConstants::s_unicodeStrURIKW_3DES)) {
                    keyOK = true;
                    isSymmetricKeyWrap = true;
                    skm = XSECCryptoSymmetricKey::MODE_CBC;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURI3DES_CBC)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_CBC;
                }
                break;

            case XSECCryptoSymmetricKey::KEY_AES_128 :
                if (strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES128) || strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES128_PAD)) {
                    keyOK = true;
                    isSymmetricKeyWrap = true;
                    skm = XSECCryptoSymmetricKey::MODE_ECB;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_CBC)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_CBC;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_GCM)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_GCM;
                    taglen = 16;
                }
                break;

            case XSECCryptoSymmetricKey::KEY_AES_192 :
                if (strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES192) || strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES192_PAD)) {
                    keyOK = true;
                    isSymmetricKeyWrap = true;
                    skm = XSECCryptoSymmetricKey::MODE_ECB;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_CBC)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_CBC;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_GCM)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_GCM;
                    taglen = 16;
                }
                break;

            case XSECCryptoSymmetricKey::KEY_AES_256 :
                if (strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES256) || strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES256_PAD)) {
                    keyOK = true;
                    isSymmetricKeyWrap = true;
                    skm = XSECCryptoSymmetricKey::MODE_ECB;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_CBC)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_CBC;
                }
                else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_GCM)) {
                    keyOK = true;
                    skm = XSECCryptoSymmetricKey::MODE_GCM;
                    taglen = 16;
                }
                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,
        const XSECCryptoKey* key,
        safeBuffer& result) const {

    // Cat the encrypted key
    XMLByte buf[_MY_MAX_KEY_SIZE];
    XMLByte aesBuf[16];
    XMLByte aesOutBuf[16];
    TXFMBase* b = cipherText->getLastTxfm();
    unsigned int sz = (unsigned int) 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,
        const XSECCryptoKey* key,
        safeBuffer& result) const {

    // 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();
    unsigned int sz = (unsigned int) 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,
        const XSECCryptoKey* key,
        safeBuffer& result) const {

    // Perform an unwrap on the key
    safeBuffer cipherSB;

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

    while (sz > 0) {
        cipherSB.sbMemcpyIn(offset, buf, sz);
        offset += sz;
        sz = (unsigned int) 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 (unsigned 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->hash(XSECCryptoHash::HASH_SHA1);
    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 (unsigned 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,
        const XSECCryptoKey* key,
        safeBuffer& result) const {

    // Cat the plaintext key
    XMLByte buf[_MY_MAX_KEY_SIZE + 16];
    TXFMBase* b = cipherText->getLastTxfm();
    int offset = 0;
    unsigned int sz = (unsigned int) 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->hash(XSECCryptoHash::HASH_SHA1);
    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 (unsigned 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,
        const XSECCryptoKey* key,
        XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc
        ) const {

    // We only support this for bulk Symmetric key algorithms

    XSECCryptoKey::KeyType kt;
    XSECCryptoSymmetricKey::SymmetricKeyType skt;
    bool isKeyWrap = false;
    XSECCryptoSymmetricKey::SymmetricKeyMode skm;
    unsigned int taglen;

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

    if (skm == XSECCryptoSymmetricKey::MODE_GCM) {

        // GCM doesn't fit the pipelined model of the existing code, so we have a custom
        // routine that decrypts to a safeBuffer directly.
        safeBuffer result;
        unsigned int sz = doGCMDecryptToSafeBuffer(cipherText, key, taglen, result);

        // Now we hijack the original tansform chain with a safeBuffer-sourced link.
        TXFMSB* tsb;
        XSECnew(tsb, TXFMSB(doc));
        tsb->setInput(result, sz);
        cipherText->appendTxfm(tsb);
        result.cleanseBuffer();
        return true;
    }


    // Add the decryption TXFM
    TXFMCipher* tcipher;
    XSECnew(tcipher, TXFMCipher(doc, key, false));
    cipherText->appendTxfm(tcipher);

    return true;
}


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

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

    // Only works with symmetric key
    if (key->getKeyType() != XSECCryptoKey::KEY_SYMMETRIC) {
        throw XSECException(XSECException::CipherError,
            "XENCAlgorithmHandlerDefault - GCM Decrypt must use symmetric key");
    }

    // First read in all the data so we can get to the tag.
    safeBuffer cipherBuf("");
    XMLByte inbuf[3072];
    unsigned int szTotal = 0, sz = cipherText->getLastTxfm()->readBytes(inbuf, 3072);
    while (sz > 0) {
        cipherBuf.sbMemcpyIn(szTotal, inbuf, sz);
        szTotal += sz;
        sz = cipherText->getLastTxfm()->readBytes(inbuf, 3072);
    }

    if (szTotal <= taglen) {
        throw XSECException(XSECException::CipherError,
            "XENCAlgorithmHandlerDefault - GCM ciphertext size not large enough to include authentication tag");
    }

    const unsigned char* cipherPtr = cipherBuf.rawBuffer();

    // Init the cipher with the tag at the end of the cipher text and omit it from later decryption.
    szTotal -= taglen;
    ((XSECCryptoSymmetricKey*) key)->decryptInit(false, XSECCryptoSymmetricKey::MODE_GCM, NULL, cipherPtr + szTotal, taglen);

    unsigned int plainOffset = 0;
    do {
        // Feed the data in at most 2048-byte chunks.
        sz = ((XSECCryptoSymmetricKey*) key)->decrypt(cipherPtr, inbuf, (szTotal > 2048 ? 2048 : szTotal), 3072);
        cipherPtr += (szTotal > 2048 ? 2048 : szTotal);
        szTotal -= (szTotal > 2048 ? 2048 : szTotal);
        if (sz > 0) {
            result.sbMemcpyIn(plainOffset, inbuf, sz);
            plainOffset += sz;
        }
    } while (szTotal > 0);

    // Wrap it up.
    sz = ((XSECCryptoSymmetricKey*) key)->decryptFinish(inbuf, 3072);
    if (sz > 0) {
        result.sbMemcpyIn(plainOffset, inbuf, sz);
        plainOffset += sz;
    }

    // In case any plaintext is left lying around.
    memset(inbuf, 0, 3072);
    return plainOffset;
}

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

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

    // 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;

    unsigned int bytesRead = (unsigned int) b->readBytes(buf, 1024);
    while (bytesRead > 0) {
        cipherSB.sbMemcpyIn(offset, buf, bytesRead);
        offset += bytesRead;
        bytesRead = (unsigned int) 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);
    }
    else if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1) ||
             strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP)) {

        const XMLCh* digmeth = encryptionMethod->getDigestMethod();
        if (!digmeth|| !*digmeth) {
            digmeth = DSIGConstants::s_unicodeStrURISHA1;
        }

        const XMLCh* mgfalg = encryptionMethod->getMGF();
        if (!mgfalg || !*mgfalg) {
            mgfalg = DSIGConstants::s_unicodeStrURIMGF1_SHA1;
        }

        // Read out any OAEP params
        unsigned char* oaepParamsBuf = NULL;
        unsigned int oaepParamsLen = 0;

        const XMLCh* oaepParams = encryptionMethod->getOAEPparams();
        if (oaepParams != NULL) {
            XSECAutoPtrChar oaepParamsStr(oaepParams);

            unsigned int bufLen = (unsigned int) strlen(oaepParamsStr.get());
            oaepParamsBuf = new unsigned char[bufLen];

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

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

        ArrayJanitor<unsigned char> j_oaepParamsBuf(oaepParamsBuf);

        decryptLen = rsa->privateDecrypt(cipherSB.rawBuffer(),
                                                  decBuf,
                                                  offset,
                                                  rsa->getLength(),
                                                  XSECCryptoKeyRSA::PAD_OAEP,
                                                  digmeth,
                                                  mgfalg,
                                                  oaepParamsBuf,
                                                  oaepParamsLen);

    }

    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,
        const XSECCryptoKey* key,
        DOMDocument* doc,
        safeBuffer& result
        ) const {

    XSECCryptoKey::KeyType kt;
    XSECCryptoSymmetricKey::SymmetricKeyType skt;
    bool isKeyWrap = false;
    XSECCryptoSymmetricKey::SymmetricKeyMode skm;
    unsigned int taglen;

    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, skm, taglen);

    // 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");
        }
    }

    if (skm == XSECCryptoSymmetricKey::MODE_GCM) {
        // GCM doesn't fit the pipelined model of the existing code, so we have a custom
        // routine that decrypts to a safeBuffer directly.
        return doGCMDecryptToSafeBuffer(cipherText, key, taglen, result);
    }

    // It's symmetric and it's not a key wrap or GCM, 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();

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

    result[offset] = '\0';

    return offset;
}

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

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

    // 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;

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

    unsigned int encryptLen;

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

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

        const XMLCh* digmeth = encryptionMethod->getDigestMethod();
        if (!digmeth || !*digmeth) {
            digmeth = DSIGConstants::s_unicodeStrURISHA1;
        }

        const XMLCh* mgfalg = encryptionMethod->getMGF();
        if (!mgfalg || !*mgfalg) {
            mgfalg = DSIGConstants::s_unicodeStrURIMGF1_SHA1;
        }

        // Read out any OAEP params
        unsigned char* oaepParamsBuf = NULL;
        unsigned int oaepParamsLen = 0;

        const XMLCh* oaepParams = encryptionMethod->getOAEPparams();
        if (oaepParams != NULL) {
            XSECAutoPtrChar oaepParamsStr(oaepParams);

            unsigned int bufLen = (unsigned int) strlen(oaepParamsStr.get());
            oaepParamsBuf = new unsigned char[bufLen];

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

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

        ArrayJanitor<unsigned char> j_oaepParamsBuf(oaepParamsBuf);

        encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(),
                                          encBuf,
                                          offset,
                                          rsa->getLength(),
                                          XSECCryptoKeyRSA::PAD_OAEP,
                                          digmeth,
                                          mgfalg,
                                          oaepParamsBuf,
                                          oaepParamsLen);
    }
    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,
        const XSECCryptoKey* key,
        XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc,
        safeBuffer& result
        ) const {

    XSECCryptoKey::KeyType kt;
    XSECCryptoSymmetricKey::SymmetricKeyType skt;
    bool isKeyWrap = false;
    XSECCryptoSymmetricKey::SymmetricKeyMode skm;
    unsigned int taglen;

    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, skm, taglen);

    // 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, skm, taglen));
    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
        ) const {

    XSECCryptoSymmetricKey* sk = NULL;

    if (strEquals(uri, DSIGConstants::s_unicodeStrURI3DES_CBC)) {
        if (keyLen < 192 / 8)
            throw XSECException(XSECException::CipherError, 
                "XENCAlgorithmHandlerDefault - key size was invalid");
        sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192);
    }
    else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_CBC) || strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_GCM)) {
        if (keyLen < 128 / 8)
            throw XSECException(XSECException::CipherError, 
                "XENCAlgorithmHandlerDefault - key size was invalid");
        sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128);
    }
    else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_CBC) || strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_GCM)) {
        if (keyLen < 192 / 8)
            throw XSECException(XSECException::CipherError, 
                "XENCAlgorithmHandlerDefault - key size was invalid");
        sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192);
    }
    else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_CBC) || strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_GCM)) {
        if (keyLen < 256 / 8)
            throw XSECException(XSECException::CipherError, 
                "XENCAlgorithmHandlerDefault - key size was invalid");
        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,
        const XSECCryptoKey* key,
        unsigned int outputLength,
        safeBuffer& result) const {

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


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

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

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

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

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

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