/**
 * 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
 *
 * OpenSSLCryptoKeyDSA := DSA Keys
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */
#include <xsec/framework/XSECDefs.hpp>
#if defined (XSEC_HAVE_OPENSSL)

#include <xsec/enc/OpenSSL/OpenSSLSupport.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoBase64.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/enc/XSECCryptoUtils.hpp>
#include <xsec/framework/XSECError.hpp>

#include <xercesc/util/Janitor.hpp>

XSEC_USING_XERCES(ArrayJanitor);

#include <openssl/dsa.h>


OpenSSLCryptoKeyDSA::OpenSSLCryptoKeyDSA() : mp_dsaKey(NULL), mp_accumP(NULL), mp_accumQ(NULL), mp_accumG(NULL) {
};

OpenSSLCryptoKeyDSA::~OpenSSLCryptoKeyDSA() {


    // If we have a DSA, delete it
    // OpenSSL will ensure the memory holding any private key is freed.

    if (mp_dsaKey)
        DSA_free(mp_dsaKey);

    if (mp_accumG)
        BN_free(mp_accumG);

    if (mp_accumP)
        BN_free(mp_accumP);

    if (mp_accumQ)
        BN_free(mp_accumQ);
};

const XMLCh* OpenSSLCryptoKeyDSA::getProviderName() const {
	return DSIGConstants::s_unicodeStrPROVOpenSSL;
}

// Generic key functions

XSECCryptoKey::KeyType OpenSSLCryptoKeyDSA::getKeyType() const {

    // Find out what we have
    if (mp_dsaKey == NULL)
        return KEY_NONE;

    if (DSA_get0_privkey(mp_dsaKey) != NULL && DSA_get0_pubkey(mp_dsaKey) != NULL)
        return KEY_DSA_PAIR;

    if (DSA_get0_privkey(mp_dsaKey) != NULL)
        return KEY_DSA_PRIVATE;

    if (DSA_get0_pubkey(mp_dsaKey) != NULL)
        return KEY_DSA_PUBLIC;

    return KEY_NONE;

}

void OpenSSLCryptoKeyDSA::loadPBase64BigNums(const char * b64, unsigned int len)  {

    setPBase(OpenSSLCryptoBase64::b642BN((char *) b64, len));

}

void OpenSSLCryptoKeyDSA::setPBase(BIGNUM  * p) {

    if (mp_dsaKey == NULL)
        mp_dsaKey = DSA_new();

#if (OPENSSL_VERSION_NUMBER < 0x10100000L)

    // Do it immediately
    mp_dsaKey->p = p;

#else
    // Save it for later
    if (mp_accumP != NULL)
        BN_free(mp_accumP);

    mp_accumP = p;

    commitPQG();

#endif

}

void OpenSSLCryptoKeyDSA::loadQBase64BigNums(const char * b64, unsigned int len) {

    setQBase(OpenSSLCryptoBase64::b642BN((char *) b64, len));

}

void OpenSSLCryptoKeyDSA::setQBase(BIGNUM  * q) {

    if (mp_dsaKey == NULL)
        mp_dsaKey = DSA_new();

#if (OPENSSL_VERSION_NUMBER <   0x10100000L)

    mp_dsaKey->q = q;

#else
    if (mp_accumQ != NULL)
        BN_free(mp_accumQ);

    mp_accumQ = q;
    commitPQG();

#endif

}


void OpenSSLCryptoKeyDSA::loadGBase64BigNums(const char * b64, unsigned int len) {

    setGBase(OpenSSLCryptoBase64::b642BN((char *) b64, len));

}

void OpenSSLCryptoKeyDSA::setGBase(BIGNUM  * g) {

    if (mp_dsaKey == NULL)
        mp_dsaKey = DSA_new();

#if (OPENSSL_VERSION_NUMBER <   0x10100000L)

    mp_dsaKey->g = g;

#else
    if (mp_accumG != NULL)
        BN_free(mp_accumG);

    mp_accumG = g;
    commitPQG();

#endif

}

#if (OPENSSL_VERSION_NUMBER >=  0x10100000L)
void OpenSSLCryptoKeyDSA::commitPQG() {


    if (mp_accumP != NULL && mp_accumQ != NULL && mp_accumG != NULL) {

        DSA_set0_pqg(mp_dsaKey, mp_accumP, mp_accumQ, mp_accumG);
        mp_accumP = NULL;
        mp_accumQ = NULL;
        mp_accumG = NULL;

    }
}
#endif

void OpenSSLCryptoKeyDSA::loadYBase64BigNums(const char * b64, unsigned int len) {

    if (mp_dsaKey == NULL)
        mp_dsaKey = DSA_new();

    BIGNUM *newPub = OpenSSLCryptoBase64::b642BN((char *) b64, len);
    const BIGNUM *oldPriv;
    DSA_get0_key(mp_dsaKey, NULL, &oldPriv);

    DSA_set0_key(mp_dsaKey, newPub, (oldPriv?BN_dup(oldPriv):NULL));
}

void OpenSSLCryptoKeyDSA::loadJBase64BigNums(const char * b64, unsigned int len) {

    if (mp_dsaKey == NULL)
        mp_dsaKey = DSA_new();

    // Do nothing
}


// "Hidden" OpenSSL functions

OpenSSLCryptoKeyDSA::OpenSSLCryptoKeyDSA(EVP_PKEY *k) : mp_accumP(NULL), mp_accumQ(NULL), mp_accumG(NULL) {

    // Create a new key to be loaded as we go

    mp_dsaKey = DSA_new();
    mp_accumG = NULL;
    mp_accumP = NULL;
    mp_accumQ = NULL;

    if (k == NULL || EVP_PKEY_id(k) != EVP_PKEY_DSA)
        return; // Nothing to do with us

    const BIGNUM *otherP = NULL, *otherQ = NULL, *otherG = NULL;
    DSA_get0_pqg(EVP_PKEY_get0_DSA(k), &otherP, &otherQ, &otherG);

    if (otherP != NULL && otherQ != NULL && otherG != NULL) {
        DSA_set0_pqg(mp_dsaKey, BN_dup(otherP), BN_dup(otherQ), BN_dup(otherG));
    }

    const BIGNUM *otherPriv = NULL, *otherPub = NULL;
    DSA_get0_key(EVP_PKEY_get0_DSA(k), &otherPub, &otherPriv);

    if (otherPub != NULL) {

        BIGNUM *newPriv = NULL;

        if (otherPriv != NULL)
            newPriv = BN_dup(otherPriv);

        DSA_set0_key(mp_dsaKey, BN_dup(otherPub), newPriv);

    }
}

// --------------------------------------------------------------------------------
//           Verify a signature encoded as a Base64 string
// --------------------------------------------------------------------------------

bool OpenSSLCryptoKeyDSA::verifyBase64Signature(unsigned char * hashBuf,
                                 unsigned int hashLen,
                                 char * base64Signature,
                                 unsigned int sigLen) const {

    // Use the currently loaded key to validate the Base64 encoded signature

    if (mp_dsaKey == NULL) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Attempt to validate signature with empty key");
    }

    XSECCryptoKey::KeyType keyType = getKeyType();
    if (keyType != KEY_DSA_PAIR && keyType != KEY_DSA_PUBLIC) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Attempt to validate signature without public key");
    }

    char* cleanedBase64Signature;
    unsigned int cleanedBase64SignatureLen = 0;

    cleanedBase64Signature =
        XSECCryptoBase64::cleanBuffer(base64Signature, sigLen, cleanedBase64SignatureLen);
    ArrayJanitor<char> j_cleanedBase64Signature(cleanedBase64Signature);

    int sigValLen;
    unsigned char* sigVal = new unsigned char[sigLen + 1];
    ArrayJanitor<unsigned char> j_sigVal(sigVal);

    EvpEncodeCtxRAII dctx;

    if (!dctx.of()) {
        throw XSECCryptoException(XSECCryptoException::ECError,
            "OpenSSL:DSA - allocation fail during Context Creation");
    }

    EVP_DecodeInit(dctx.of());

    int rc = EVP_DecodeUpdate(dctx.of(),
                          sigVal,
                          &sigValLen,
                          (unsigned char *) cleanedBase64Signature,
                          cleanedBase64SignatureLen);

    if (rc < 0) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Error during Base64 Decode");
    }

    int t = 0;

    EVP_DecodeFinal(dctx.of(), &sigVal[sigValLen], &t);

    sigValLen += t;

    // Translate to BNs and thence to DSA_SIG
    BIGNUM * R;
    BIGNUM * S;

    if (sigValLen == 40) {

        R = BN_bin2bn(sigVal, 20, NULL);
        S = BN_bin2bn(&sigVal[20], 20, NULL);
    }
    else {

        unsigned char rb[20];
        unsigned char sb[20];

        if (sigValLen == 46 && ASN2DSASig(sigVal, rb, sb) == true) {

            R = BN_bin2bn(rb, 20, NULL);
            S = BN_bin2bn(sb, 20, NULL);

        }

        else {

            throw XSECCryptoException(XSECCryptoException::DSAError,
                "OpenSSL:DSA - Signature Length incorrect");
        }
    }

    DSA_SIG * dsa_sig = DSA_SIG_new();

    DSA_SIG_set0(dsa_sig, BN_dup(R), BN_dup(S));

    BN_free(R);
    BN_free(S);

    // Now we have a signature and a key - lets check

    int err = DSA_do_verify(hashBuf, hashLen, dsa_sig, mp_dsaKey);

    DSA_SIG_free(dsa_sig);

    if (err < 0) {

        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Error validating signature");
    }

    return (err == 1);

}

// --------------------------------------------------------------------------------
//           Sign and encode result as a Base64 string
// --------------------------------------------------------------------------------


unsigned int OpenSSLCryptoKeyDSA::signBase64Signature(unsigned char * hashBuf,
        unsigned int hashLen,
        char * base64SignatureBuf,
        unsigned int base64SignatureBufLen) const {

    // Sign a pre-calculated hash using this key

    if (mp_dsaKey == NULL) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Attempt to sign data with empty key");
    }

    KeyType keyType = getKeyType();
    if (keyType != KEY_DSA_PAIR && keyType != KEY_DSA_PRIVATE) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Attempt to sign data without private key");
    }


    DSA_SIG* dsa_sig = DSA_do_sign(hashBuf, hashLen, mp_dsaKey);

    if (dsa_sig == NULL) {

        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Error signing data");

    }

    // Now turn the signature into a base64 string
    
    const BIGNUM *dsaSigR;
    const BIGNUM *dsaSigS;

    DSA_SIG_get0(dsa_sig, &dsaSigR, &dsaSigS);

    unsigned char* rawSigBuf = new unsigned char[(BN_num_bits(dsaSigR) + BN_num_bits(dsaSigS) + 7) / 8];
    ArrayJanitor<unsigned char> j_sigbuf(rawSigBuf);
    
    unsigned int rawLen = BN_bn2bin(dsaSigR, rawSigBuf);

    if (rawLen <= 0) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Error converting signature to raw buffer");
    }

    unsigned int rawLenS = BN_bn2bin(dsaSigS, (unsigned char *) &rawSigBuf[rawLen]);

    if (rawLenS <= 0) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Error converting signature to raw buffer");
    }

    rawLen += rawLenS;

    // Now convert to Base 64

    BIO * b64 = BIO_new(BIO_f_base64());
    BIO * bmem = BIO_new(BIO_s_mem());

    BIO_set_mem_eof_return(bmem, 0);
    b64 = BIO_push(b64, bmem);

    // Translate signature from Base64

    BIO_write(b64, rawSigBuf, rawLen);
    BIO_flush(b64);

    unsigned int sigValLen = BIO_read(bmem, base64SignatureBuf, base64SignatureBufLen);

    BIO_free_all(b64);

    if (sigValLen <= 0) {
        throw XSECCryptoException(XSECCryptoException::DSAError,
            "OpenSSL:DSA - Error base64 encoding signature");
    }

    return sigValLen;

}



XSECCryptoKey * OpenSSLCryptoKeyDSA::clone() const {

    OpenSSLCryptoKeyDSA * ret;

    XSECnew(ret, OpenSSLCryptoKeyDSA);

    ret->mp_dsaKey = DSA_new();

    // Duplicate parameters

    const BIGNUM *p=NULL, *q=NULL, *g=NULL;
    DSA_get0_pqg(mp_dsaKey, &p, &q, &g);

    if (p && q && g) // DSA_set0_pqg only works if all three params are non zero
        DSA_set0_pqg(ret->mp_dsaKey, BN_dup(p), BN_dup(q), BN_dup(g));

    const BIGNUM *oldPub= NULL, *oldPriv=NULL;
    DSA_get0_key(mp_dsaKey, &oldPub, &oldPriv);

    if (oldPub) {

        // DSA_setKey requires non-null Public

        DSA_set0_key(ret->mp_dsaKey, BN_dup(oldPub), (oldPriv?BN_dup(oldPriv):NULL));

    }
    return ret;
}

#endif /* XSEC_HAVE_OPENSSL */
