/**
 * 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
 *
 * OpenSSLCryptoX509:= OpenSSL based class for handling X509 (V3) certificates
 *
 * Author(s): Berin Lautenbach
 *
 * $Id$
 *
 */

#include <xsec/framework/XSECDefs.hpp>

#if defined (XSEC_HAVE_OPENSSL)

#include <xsec/dsig/DSIGConstants.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyEC.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
#include <xsec/enc/OpenSSL/OpenSSLSupport.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/enc/XSCrypt/XSCryptCryptoBase64.hpp>

#include <xercesc/util/Janitor.hpp>

XSEC_USING_XERCES(ArrayJanitor);
XSEC_USING_XERCES(Janitor);

#include <openssl/evp.h>

OpenSSLCryptoX509::OpenSSLCryptoX509() :
m_DERX509("") { 

    mp_X509 = NULL;

}

OpenSSLCryptoX509::~OpenSSLCryptoX509() {

    if (mp_X509 != NULL)
        X509_free(mp_X509);

}

OpenSSLCryptoX509::OpenSSLCryptoX509(X509 * x) {

    // Build this from an existing X509 structure

    mp_X509 = X509_dup(x);
    
    // Now need to create the DER encoding

    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 X509 to Base64

    i2d_X509_bio(b64, x);

    BIO_flush(b64);

    char buf[1024];
    unsigned int l;
    
    m_DERX509.sbStrcpyIn("");

    while ((l = BIO_read(bmem, buf, 1023)) > 0) {
        buf[l] = '\0';
        m_DERX509.sbStrcatIn(buf);
    }

    BIO_free_all(b64);

}

// load functions

void OpenSSLCryptoX509::loadX509Base64Bin(const char * buf, unsigned int len) {

    // Free anything currently held.
    
    if (mp_X509 != NULL)
        X509_free(mp_X509);
    
    // Have to implement using EVP_Decode routines due to a bug in older
    // versions of OpenSSL BIO_f_base64

    int bufLen = len;
    unsigned char * outBuf;
    XSECnew(outBuf, unsigned char[len + 1]);
    ArrayJanitor<unsigned char> j_outBuf(outBuf);

    /* Had to move to our own Base64 decoder because it handles non-wrapped b64
       better.  Grrr. */

    XSCryptCryptoBase64 *b64;
    XSECnew(b64, XSCryptCryptoBase64);
    Janitor<XSCryptCryptoBase64> j_b64(b64);

    b64->decodeInit();
    bufLen = b64->decode((unsigned char *) buf, len, outBuf, len);
    bufLen += b64->decodeFinish(&outBuf[bufLen], len-bufLen);

    /*

    EVP_ENCODE_CTX m_dctx;
    EVP_DecodeInit(&m_dctx);

    int rc = EVP_DecodeUpdate(&m_dctx, 
                          outBuf, 
                          &bufLen, 
                          (unsigned char *) buf, 
                          len);

    if (rc < 0) {

        throw XSECCryptoException(XSECCryptoException::Base64Error,
            "OpenSSL:Base64 - Error during Base64 Decode of X509 Certificate");
    }
    
    int finalLen;
    EVP_DecodeFinal(&m_dctx, &outBuf[bufLen], &finalLen); 

    bufLen += finalLen;
    */
    if (bufLen > 0) {
#if defined(XSEC_OPENSSL_D2IX509_CONST_BUFFER)
        mp_X509=  d2i_X509(NULL, (const unsigned char **) (&outBuf), bufLen);
#else
        mp_X509=  d2i_X509(NULL, &outBuf, bufLen);
#endif
    }

    // Check to see if we have a certificate....
    if (mp_X509 == NULL) {

        throw XSECCryptoException(XSECCryptoException::X509Error,
        "OpenSSL:X509 - Error translating Base64 DER encoding into OpenSSL X509 structure");

    }

    m_DERX509.sbMemcpyIn(buf, len);
    m_DERX509[len] = '\0';
}

// Info functions

const XMLCh * OpenSSLCryptoX509::getProviderName() const {

    return DSIGConstants::s_unicodeStrPROVOpenSSL;

}

XSECCryptoKey::KeyType OpenSSLCryptoX509::getPublicKeyType() const {

    if (mp_X509 == NULL) {
        throw XSECCryptoException(XSECCryptoException::X509Error,
            "OpenSSL:X509 - getPublicKeyType called before X509 loaded");
    }

    EVP_PKEY *pkey;

    pkey = X509_get_pubkey(mp_X509);

    if (pkey == NULL) {
        throw XSECCryptoException(XSECCryptoException::X509Error,
            "OpenSSL:X509 - cannot retrieve public key from cert");
    }

    XSECCryptoKey::KeyType ret;

    switch (EVP_PKEY_id(pkey)) {

    case EVP_PKEY_DSA :

        ret = XSECCryptoKey::KEY_DSA_PUBLIC;
        break;

    case EVP_PKEY_RSA :

        ret = XSECCryptoKey::KEY_RSA_PUBLIC;
        break;

#if defined(XSEC_OPENSSL_HAVE_EC)
    case EVP_PKEY_EC :

        ret = XSECCryptoKey::KEY_EC_PUBLIC;
        break;
#endif

    default :

        ret = XSECCryptoKey::KEY_NONE;

    }

    EVP_PKEY_free (pkey);

    return ret;

}
        

// Get functions
XSECCryptoKey * OpenSSLCryptoX509::clonePublicKey() const {

    if (mp_X509 == NULL) {
        throw XSECCryptoException(XSECCryptoException::X509Error,
            "OpenSSL:X509 - clonePublicKey called before X509 loaded");
    }

    EVP_PKEY *pkey;
    XSECCryptoKey * ret;

    pkey = X509_get_pubkey(mp_X509);

    if (pkey == NULL) {
        throw XSECCryptoException(XSECCryptoException::X509Error,
            "OpenSSL:X509 - cannot retrieve public key from cert");
    }

    switch (EVP_PKEY_id(pkey)) {

    case EVP_PKEY_DSA :

        ret = new OpenSSLCryptoKeyDSA(pkey);
        break;

    case EVP_PKEY_RSA :

        ret = new OpenSSLCryptoKeyRSA(pkey);
        break;

#if defined(XSEC_OPENSSL_HAVE_EC)
    case EVP_PKEY_EC :

        ret = new OpenSSLCryptoKeyEC(pkey);
        break;
#endif

    default :

        ret = NULL;

    }

    EVP_PKEY_free (pkey);

    return ret;

}

#endif /* XSEC_HAVE_OPENSSL */
