/**
 * 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
 *
 * WinCAPICryptoProvider := Provider to support Windows Crypto API
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

#include <xsec/framework/XSECError.hpp>


#include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoX509.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoKeyDSA.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoKeyRSA.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoHash.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoHashHMAC.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp>
#include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>
#include <xsec/enc/XSECCryptoException.hpp>

#if defined (XSEC_HAVE_WINCAPI)

#include <xercesc/util/Janitor.hpp>

XSEC_USING_XERCES(ArrayJanitor);

static char s_xsecKeyStoreName[] = "ApacheXML-SecurityKeyStore";

WinCAPICryptoProvider::WinCAPICryptoProvider(
                        LPCSTR provDSSName,
                        LPCSTR provRSAName,
                        DWORD dwFlags) {

    if (!CryptAcquireContext(&m_provDSS,
        NULL,
        provDSSName,
        PROV_DSS,
        CRYPT_VERIFYCONTEXT))
    {
        throw XSECException(XSECException::InternalError,
            "WinCAPICryptoProvider() - Error obtaining default PROV_DSS");
    }

    if (!CryptAcquireContext(&m_provRSA,
        NULL,
        provRSAName,
        PROV_RSA_AES,
        CRYPT_VERIFYCONTEXT))
    {
        // Check if we maybe don't understand AES

        DWORD error = GetLastError();
        if (error == NTE_PROV_TYPE_NOT_DEF || error == 0) {

            // This system does not have AES!
            m_haveAES = false;
            m_provRSAType = PROV_RSA_FULL;

            if (!CryptAcquireContext(&m_provRSA,
                NULL,
                provRSAName,
                PROV_RSA_FULL,
                CRYPT_VERIFYCONTEXT))
            {

                throw XSECException(XSECException::InternalError,
                    "WinCAPICryptoProvider() - Error obtaining default PROV_RSA_FULL");
            }

        }

        else {

            throw XSECException(XSECException::InternalError,
                "WinCAPICryptoProvider() - Error obtaining default PROV_RSA_AES");
        }
    }

    else {
        m_haveAES = true;
        m_provRSAType = PROV_RSA_AES;
    }

    // Now obtain our internal (library) key store

    if (!CryptAcquireContext(&m_provApacheKeyStore,
        s_xsecKeyStoreName,
        provRSAName,
        m_provRSAType,
        dwFlags))
    {
        CryptAcquireContext(&m_provApacheKeyStore,
                                s_xsecKeyStoreName,
                                provRSAName,
                                m_provRSAType,
                                CRYPT_DELETEKEYSET);

        // Try to create
        if (!CryptAcquireContext(&m_provApacheKeyStore,
            s_xsecKeyStoreName,
            provRSAName,
            m_provRSAType,
            dwFlags | CRYPT_NEWKEYSET)) {

            // Prevents failure on mandatory profiles, see SANTUARIO-378.
            if (GetLastError() != NTE_TEMPORARY_PROFILE) {
                throw XSECException(XSECException::InternalError,
                    "WinCAPICryptoProvider() - Error obtaining generating internal key store for PROV_RSA_FULL");
            } else {
                m_provApacheKeyStore = NULL;
            }
        }
        else {
            HCRYPTKEY k;
            if (!CryptGenKey(m_provApacheKeyStore, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &k)) {
                throw XSECException(XSECException::InternalError,
                    "WinCAPICryptoProvider() - Error generating internal key set for PROV_RSA_FULL");
            }
            CryptDestroyKey(k);
        }
    }

    // Copy parameters for later use

    if (provDSSName != NULL)
        m_provDSSName = strdup(provDSSName);
    else
        m_provDSSName = NULL;

    if (provRSAName != NULL)
        m_provRSAName = strdup(provRSAName);
    else
        m_provRSAName = NULL;
}

WinCAPICryptoProvider::~WinCAPICryptoProvider() {
    CryptReleaseContext(m_provRSA, 0);
    CryptReleaseContext(m_provDSS, 0);
    if (m_provApacheKeyStore) {
        CryptReleaseContext(m_provApacheKeyStore, 0);
    }
}

const XMLCh* WinCAPICryptoProvider::getProviderName() const {

    return DSIGConstants::s_unicodeStrPROVWinCAPI;

}


// Hashing classes

unsigned int WinCAPICryptoProvider::getMaxHashSize() const {
    return WINCAPI_MAX_HASH_SIZE;
}


XSECCryptoHash* WinCAPICryptoProvider::hash(XSECCryptoHash::HashType type) const {

    WinCAPICryptoHash* ret = NULL;

    switch(type) {
    case XSECCryptoHash::HASH_SHA1:
    case XSECCryptoHash::HASH_MD5:
        XSECnew(ret, WinCAPICryptoHash(m_provDSS, type));
        break;
    }

    return ret;
}

XSECCryptoHash* WinCAPICryptoProvider::HMAC(XSECCryptoHash::HashType type) const {

    WinCAPICryptoHashHMAC* ret = NULL;

    switch(type) {
    case XSECCryptoHash::HASH_SHA1:
    case XSECCryptoHash::HASH_MD5:
        XSECnew(ret, WinCAPICryptoHashHMAC(m_provDSS, type));
        break;
    }

    return ret;
}

XSECCryptoKeyHMAC* WinCAPICryptoProvider::keyHMAC(void) const {
    WinCAPICryptoKeyHMAC * ret;

    XSECnew(ret, WinCAPICryptoKeyHMAC(m_provDSS));

    return ret;
}

XSECCryptoKeyDSA* WinCAPICryptoProvider::keyDSA() const {
    WinCAPICryptoKeyDSA * ret;

    XSECnew(ret, WinCAPICryptoKeyDSA(m_provDSS));

    return ret;
}

XSECCryptoKeyRSA* WinCAPICryptoProvider::keyRSA() const {
    WinCAPICryptoKeyRSA * ret;

    XSECnew(ret, WinCAPICryptoKeyRSA(m_provRSA));

    return ret;
}

XSECCryptoKeyEC* WinCAPICryptoProvider::keyEC() const {

    throw XSECCryptoException(XSECCryptoException::UnsupportedError,
        "WinCAPICryptoProvider::keyEC - EC support not available");
}

XSECCryptoKey* WinCAPICryptoProvider::keyDER(const char* buf, unsigned long len, bool base64) const {

    throw XSECCryptoException(XSECCryptoException::UnsupportedError,
        "WinCAPICryptoProvider::keyDER - DER decoding support not available");
}

XSECCryptoX509* WinCAPICryptoProvider::X509() const {
    WinCAPICryptoX509 * ret;

    XSECnew(ret, WinCAPICryptoX509(m_provRSA, m_provDSS));

    return ret;
}

XSECCryptoBase64* WinCAPICryptoProvider::base64() const {

    // The Windows CAPI does not provide a Base64 decoder/encoder.
    // Use the internal implementation.

    XSCryptCryptoBase64 * ret;

    XSECnew(ret, XSCryptCryptoBase64());

    return ret;
}

bool WinCAPICryptoProvider::algorithmSupported(XSECCryptoSymmetricKey::SymmetricKeyType alg) const {

    switch (alg) {

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

        return m_haveAES;

    case (XSECCryptoSymmetricKey::KEY_3DES_192) :

        return true;

    default:

        return false;

    }

    return false;
}

bool WinCAPICryptoProvider::algorithmSupported(XSECCryptoHash::HashType alg) const {
    switch (alg) {

    case (XSECCryptoHash::HASH_SHA1) :
    case (XSECCryptoHash::HASH_MD5) :

        return true;

    case (XSECCryptoHash::HASH_SHA224) :
    case (XSECCryptoHash::HASH_SHA256) :
    case (XSECCryptoHash::HASH_SHA384) :
    case (XSECCryptoHash::HASH_SHA512) :

        return false;

    default:
        return false;
    }

    return false;
}

XSECCryptoSymmetricKey* WinCAPICryptoProvider::keySymmetric(XSECCryptoSymmetricKey::SymmetricKeyType alg) const {
    // Only temporary

    WinCAPICryptoSymmetricKey * ret;

    XSECnew(ret, WinCAPICryptoSymmetricKey(m_provApacheKeyStore, alg));

    return ret;
}

unsigned int WinCAPICryptoProvider::getRandom(unsigned char* buffer, unsigned int numOctets) const {

    if (!CryptGenRandom(m_provApacheKeyStore, numOctets, buffer)) {
        throw XSECException(XSECException::InternalError,
            "WinCAPICryptoProvider() - Error generating Random data");
    }

    return numOctets;
}



// --------------------------------------------------------------------------------
//     Translate a Base64 number to a Windows (little endian) integer
// --------------------------------------------------------------------------------

BYTE* WinCAPICryptoProvider::b642WinBN(const char* b64, unsigned int b64Len, unsigned int& retLen) {

    BYTE * os;
    XSECnew(os, BYTE[b64Len]);
    ArrayJanitor<BYTE> j_os(os);

    // Decode
    XSCryptCryptoBase64 b;

    b.decodeInit();
    retLen = b.decode((unsigned char *) b64, b64Len, os, b64Len);
    retLen += b.decodeFinish(&os[retLen], b64Len - retLen);

    BYTE * ret;
    XSECnew(ret, BYTE[retLen]);

    BYTE * j = os;
    BYTE * k = ret + retLen - 1;

    for (unsigned int i = 0; i < retLen ; ++i)
        *k-- = *j++;

    return ret;
}

// --------------------------------------------------------------------------------
//     Translate a Windows integer to a Base64 I2OSP number 
// --------------------------------------------------------------------------------

unsigned char * WinCAPICryptoProvider::WinBN2b64(BYTE * n, DWORD nLen, unsigned int &retLen) {


    // First reverse
    BYTE * rev;;
    XSECnew(rev, BYTE[nLen]);
    ArrayJanitor<BYTE> j_rev(rev);

    BYTE * j = n;
    BYTE * k = rev + nLen - 1;

    for (unsigned int i = 0; i < nLen ; ++i)
        *k-- = *j++;


    unsigned char * b64;
    // Naieve length calculation
    unsigned int bufLen = nLen * 2 + 4;

    XSECnew(b64, unsigned char[bufLen]);
    ArrayJanitor<unsigned char> j_b64(b64);

    XSCryptCryptoBase64 b;

    b.encodeInit();
    retLen = b.encode(rev, (unsigned int) nLen, b64, bufLen);
    retLen += b.encodeFinish(&b64[retLen], bufLen - retLen);

    j_b64.release();
    return b64;
}

#endif /* XSEC_HAVE_WINCAPI */

