Logo Search packages:      
Sourcecode: beid version File versions  Download package

cryptoFramework.cpp

/* ****************************************************************************

 * eID Middleware Project.
 * Copyright (C) 2008-2009 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see
 * http://www.gnu.org/licenses/.

**************************************************************************** */
#include "cryptoFramework.h"

#include "MWException.h"
#include "eidErrors.h"
#include "Util.h"
#include "Log.h"
#include "ByteArray.h"
#include "APLConfig.h"
#include "MiscUtil.h"
#include "Thread.h"

#include "openssl/evp.h"
#include "openssl/x509.h"
#include "openssl/x509v3.h"
#include "xercesc/util/Base64.hpp"
#include "xercesc/util/XMLString.hpp"

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#define CRL_MEMORY_CACHE_SIZE 10

namespace eIDMW
{
/* **********************************
*** Internal class CrlMemoryCache ***
********************************** */
class CrlMemoryCache
{

private:

      class CrlMemoryElement
      {
      public:
            CrlMemoryElement()
            {
                  m_baHash=NULL;
                  m_crl=NULL;
                  m_timeStamp.clear();
            }

            ~CrlMemoryElement()
            {
                  clear();
            }

            void clear()
            {
                  if(m_baHash) 
                  {     
                        delete m_baHash;
                        m_baHash=NULL;
                  }
                  if(m_crl) 
                  {
                        X509_CRL_free(m_crl);
                        m_crl=NULL;
                  }
                  m_timeStamp.clear();
            }

            bool getOlderTS(std::string &timeStamp)
            {
                  if((timeStamp.empty() && !m_timeStamp.empty()) || m_timeStamp.compare(timeStamp)<0)
                  {
                        timeStamp=m_timeStamp;
                        return true;
                  }

                  return false;
            }

            bool checkHash(const CByteArray &hash, std::string &timeStamp,bool &bTSChanged)
            {
                  bTSChanged=getOlderTS(timeStamp);
                  if(m_baHash)
                        return m_baHash->Equals(hash);
                  else
                        return false;
            }

            X509_CRL *getCrl()
            {
                  CTimestampUtil::getTimestamp(m_timeStamp,0,"%Y%m%dT%H%M%S"/*YYYYMMDDThhmmss*/);
                  return m_crl;
            }

            void setCrl(X509_CRL *crl,const CByteArray &hash)
            {
                  clear();

                  m_baHash=new CByteArray(hash);
                  m_crl=crl;
                  CTimestampUtil::getTimestamp(m_timeStamp,0,"%Y%m%dT%H%M%S"/*YYYYMMDDThhmmss*/);
            }

      private:
            CByteArray *m_baHash;
            X509_CRL *m_crl;
            std::string m_timeStamp;
      }; 

public:
      CrlMemoryCache()
      {
            MWLOG(LEV_INFO, MOD_SSL, L"Create CrlMemoryCache");
            m_CrlMemoryArray=new CrlMemoryElement[CRL_MEMORY_CACHE_SIZE];
      }

      ~CrlMemoryCache()
      {
            MWLOG(LEV_INFO, MOD_SSL, L"Delete CrlMemoryCache");
            delete[] m_CrlMemoryArray;
            MWLOG(LEV_INFO, MOD_SSL, L" ---> CrlMemoryCache deleted");
      }

      X509_CRL *getX509CRL(const CByteArray &crl, const CByteArray &hash)
      {
            int i;
            bool bTSChanged=false;
            int iOlder=0;
            std::string timeStamp;
            X509_CRL *pX509CRL=NULL;

            //Check if already in the array
            MWLOG(LEV_DEBUG, MOD_SSL, L"Check for element in CrlMemoryCache hash=%ls",hash.ToWString().c_str());
            for(i=0;i<CRL_MEMORY_CACHE_SIZE;i++)
            {
                  if(m_CrlMemoryArray[i].checkHash(hash,timeStamp,bTSChanged))
                  {
                        MWLOG(LEV_DEBUG, MOD_SSL, L" ---> Element found index= %ld",i);
                        return m_CrlMemoryArray[i].getCrl();
                  }

                  if(bTSChanged)
                        iOlder=i;
            }

            MWLOG(LEV_DEBUG, MOD_SSL, L"Add element in CrlMemoryCach");
            //find the index to replace
            for(;i<CRL_MEMORY_CACHE_SIZE;i++)
            {
                  if(m_CrlMemoryArray[i].getOlderTS(timeStamp))
                        iOlder=i;
            }
            MWLOG(LEV_DEBUG, MOD_SSL, L" ---> Index found = %ld",iOlder);

            const unsigned char *pTempBuffer = crl.GetBytes();

            #if (OPENSSL_VERSION_NUMBER > 0x009070ffL)
              pX509CRL = d2i_X509_CRL(&pX509CRL,&pTempBuffer,crl.Size()); 
            #else   
              unsigned char* pTempBuffer_nonconst = const_cast<unsigned char*> (pTempBuffer);
              pX509CRL = d2i_X509_CRL(&pX509CRL,&pTempBuffer_nonconst,crl.Size()); 
            #endif

            MWLOG(LEV_DEBUG, MOD_SSL, L" ---> OpenSSL structure created");

            m_CrlMemoryArray[iOlder].setCrl(pX509CRL,hash);
            MWLOG(LEV_DEBUG, MOD_SSL, L" ---> Element added");

            return pX509CRL;
      }

private:
      CrlMemoryElement *m_CrlMemoryArray;
};

/* *********************************
*** Internal class ThreadConnect ***
********************************* */
class ThreadConnect : public CThread
{
public:
      ThreadConnect(char *pszHost, int iPort, int iSSL, SSL_CTX **ppSSLCtx)
      {
            m_pszHost=pszHost; 
            m_iPort=iPort; 
            m_iSSL=iSSL; 
            m_ppSSLCtx=ppSSLCtx;
            m_pConnect = NULL;
      }

      void Run()
      {
            BIO *pConnect = NULL;

            if (m_iSSL) 
            {
                  OpenSSL_add_all_algorithms();
                  *m_ppSSLCtx = SSL_CTX_new(SSLv23_client_method());
          
                  if (!(pConnect = BIO_new_ssl_connect(*m_ppSSLCtx))) 
                        return;

                  BIO_set_conn_hostname(pConnect, m_pszHost);   
            }
            else
            {
                  if (!(pConnect = BIO_new_connect(m_pszHost)))
                        return;
            }

            BIO_set_conn_int_port(pConnect, &m_iPort);

            if ( BIO_do_connect(pConnect) <= 0 )
                  return;

            m_pConnect=pConnect;

            return;
      }

      BIO *getConnect()
      {
            return m_pConnect;
      }

private:
      char *m_pszHost;
      int m_iPort;
      int m_iSSL;
      SSL_CTX **m_ppSSLCtx;
      BIO *m_pConnect;
};

/* ***************
*** APL_CryptoFwk ***
***************** */
00251 APL_CryptoFwk::APL_CryptoFwk()
{
      m_proxy_host.clear();
      m_proxy_port.clear();
      m_proxy_pac.clear();

      resetProxy();

      m_CrlMemoryCache=NULL;
      m_CrlMemoryCache=new CrlMemoryCache();
}

00263 APL_CryptoFwk::~APL_CryptoFwk(void)
{
      if(m_CrlMemoryCache) delete m_CrlMemoryCache;
}

bool d2i_X509_Wrapper(X509** pX509,const unsigned char* pucContent, int iContentSize){
#if (OPENSSL_VERSION_NUMBER > 0x009070ffL)
  *pX509 = d2i_X509(pX509, &pucContent, iContentSize);
#else
  unsigned char* pucContent_nonconst = const_cast<unsigned char*> (pucContent);
  *pX509 = d2i_X509(pX509, &pucContent_nonconst, iContentSize);
#endif
  if(*pX509 == NULL) return false;

  return true;
}

00280 unsigned long APL_CryptoFwk::GetCertUniqueID(const CByteArray &cert)
{
      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;

      //Convert cert into pX509
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //The unique ID is made with a hash of issuer and serial

      unsigned long ret;
      ret=X509_issuer_and_serial_hash(pX509);

      //Free openSSL object
      X509_free(pX509);

      return ret;
}

00301 bool APL_CryptoFwk::VerifyDateValidity(const CByteArray &cert)
{
      bool bOk=false;

      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;

      //Convert cert into pX509
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bOk=VerifyDateValidity(pX509);

      //Free openSSL object
      if(pX509) X509_free(pX509);

      return bOk;
}
00320 bool APL_CryptoFwk::VerifyDateValidity(const X509 *pX509)
{
      bool bOk=false;

      if (pX509==NULL)
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //The current time must be between notBefore and notAfter
      if(X509_cmp_current_time(X509_get_notBefore(pX509))<=0
            && X509_cmp_current_time(X509_get_notAfter(pX509))>=0)

            bOk=true;

      return bOk;
}

00336 bool APL_CryptoFwk::VerifyCrlDateValidity(const CByteArray &crl)
{
      bool bOk=false;

      X509_CRL *pX509_Crl = NULL;

      //Convert cert into pX509
      if ( NULL == (pX509_Crl=getX509CRL(crl)) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bOk=VerifyCrlDateValidity(pX509_Crl);

      return bOk;
}

00351 bool APL_CryptoFwk::VerifyCrlDateValidity(const X509_CRL *pX509_Crl)
{
      bool bOk=false;

      if (pX509_Crl==NULL)
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //The current time must be between notBefore and notAfter
      if(X509_cmp_current_time(X509_CRL_get_lastUpdate(pX509_Crl))<=0
            && X509_cmp_current_time(X509_CRL_get_nextUpdate(pX509_Crl))>=0)

            bOk=true;

      return bOk;
}
00366 bool APL_CryptoFwk::isSelfIssuer(const CByteArray &cert)
{
      bool bOk = false;
      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;

      //Convert cert into pX509
      pucCert=cert.GetBytes();
      
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      
      //FIRST CHECK IF THE ISUER NAME IS THE SAME AS THE OWNER (SUBJECT)
      if(X509_name_cmp(X509_get_issuer_name(pX509),X509_get_subject_name(pX509))==0)
      {
            //THEN CHECK IF THE CERTIFICATE IS SELF-SIGNED
            bOk=VerifyCertSignature(pX509,pX509);
      }

      //Free openSSL object
    X509_free(pX509);

      return bOk;
}

00392 bool APL_CryptoFwk::isCrlValid(const CByteArray &crl,const CByteArray &issuer)
{
      bool bOk = false;
      const unsigned char *pucIssuer=NULL;
      X509_CRL *pX509_Crl = NULL;
      X509 *pX509_Issuer = NULL;

      //Convert crl into pX509_Crl
      if ( NULL == (pX509_Crl=getX509CRL(crl)) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
        
      //Convert issuer into pX509_Issuer
      pucIssuer=issuer.GetBytes();
      
      if ( ! d2i_X509_Wrapper(&pX509_Issuer, pucIssuer,issuer.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bOk=isCrlIssuer(pX509_Crl,pX509_Issuer);

      if(bOk)
            bOk=VerifyCrlDateValidity(pX509_Crl);

      //Free openSSL object
      if(pX509_Issuer)  X509_free(pX509_Issuer);

      return bOk;
}

00420 bool APL_CryptoFwk::isCrlIssuer(const CByteArray &crl,const CByteArray &issuer)
{
      bool bOk = false;
      const unsigned char *pucIssuer=NULL;
      X509_CRL *pX509_Crl = NULL;
      X509 *pX509_Issuer = NULL;

      //Convert crl into pX509_Crl
      if ( NULL == (pX509_Crl=getX509CRL(crl)) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
        
      //Convert issuer into pX509_Issuer
      pucIssuer=issuer.GetBytes();
      
      if ( ! d2i_X509_Wrapper(&pX509_Issuer, pucIssuer,issuer.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bOk=isCrlIssuer(pX509_Crl,pX509_Issuer);

      //Free openSSL object
      if(pX509_Issuer)  X509_free(pX509_Issuer);

      return bOk;
}

00445 bool APL_CryptoFwk::isCrlIssuer(X509_CRL *pX509_Crl,X509 *pX509_Issuer)
{
      bool bOk = false;

      //Convert crl into pX509_Crl
      if ( pX509_Crl==NULL || pX509_Issuer==NULL )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
        
      //FIRST CHECK IF THE ISUER NAME IS THE SAME AS THE OWNER (SUBJECT)
      if(X509_name_cmp(X509_CRL_get_issuer(pX509_Crl),X509_get_subject_name(pX509_Issuer))==0)
      {
            //THEN CHECK IF CERT IS SIGNED BY ISSUER
            bOk=VerifyCrlSignature(pX509_Crl,pX509_Issuer);
      }

      return bOk;
}

00463 bool APL_CryptoFwk::isIssuer(const CByteArray &cert,const CByteArray &issuer)
{
      bool bOk = false;
      const unsigned char *pucCert=NULL;
      const unsigned char *pucIssuer=NULL;
      X509 *pX509_Cert = NULL;
      X509 *pX509_Issuer = NULL;

      //Convert cert into pX509_Cert
      pucCert=cert.GetBytes();

      if ( ! d2i_X509_Wrapper(&pX509_Cert, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
        
      //Convert issuer into pX509_Issuer
      pucIssuer=issuer.GetBytes();
      
      if ( ! d2i_X509_Wrapper(&pX509_Issuer, pucIssuer,issuer.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);


      //FIRST CHECK IF THE ISUER NAME IS THE SAME AS THE OWNER (SUBJECT)
      if(X509_name_cmp(X509_get_issuer_name(pX509_Cert),X509_get_subject_name(pX509_Issuer))==0)
      {
            //THEN CHECK IF CERT IS SIGNED BY ISSUER
            bOk=VerifyCertSignature(pX509_Cert,pX509_Issuer);
      }

      //Free openSSL object
      X509_free(pX509_Cert);
    X509_free(pX509_Issuer);

      return bOk;
}

00498 bool APL_CryptoFwk::VerifyCertSignature(X509 *pX509_Cert,X509 *pX509_Issuer)
{
      if(pX509_Cert==NULL || pX509_Issuer==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bool bOk = false;

      //Convert pX509_Cert->cert_info into unsigned char * and then into CByteArray
      unsigned char *pucInfo,*pucInfoNext;
      long lLen=i2d_X509_CINF(pX509_Cert->cert_info,NULL); //Get the length for the buffer
      if(lLen > 0)
      {
            //Convert the signature into CByteArray
            CByteArray signature(pX509_Cert->signature->data,pX509_Cert->signature->length);

            pucInfo = pucInfoNext = (unsigned char *)malloc(lLen);      //Allocate the buffer
            i2d_X509_CINF(pX509_Cert->cert_info,&pucInfoNext);          //Fill the buffer
            CByteArray certinfo(pucInfo,lLen);                                //Fill the CByteArray
            free(pucInfo);                                                                //Free buffer

            //Verify if the signature of the certinfo is correct (regarding the issuer certificate)
            bOk=VerifySignature(certinfo,signature,pX509_Issuer,EVP_sha1());
      }

      return bOk;
}

00525 bool APL_CryptoFwk::VerifyCrlSignature(X509_CRL *pX509_Crl,X509 *pX509_Issuer)
{
      if(pX509_Crl==NULL || pX509_Issuer==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bool bOk = false;

      //Convert pX509_Crl into unsigned char * and then into CByteArray
      unsigned char *pucCrl,*pucCrlNext;
      long lLen=i2d_X509_CRL_INFO(pX509_Crl->crl,NULL); //Get the length for the buffer
      if(lLen > 0)
      {
            //Convert the signature into CByteArray
            CByteArray signature(pX509_Crl->signature->data,pX509_Crl->signature->length);

            pucCrl = pucCrlNext = (unsigned char *)malloc(lLen);  //Allocate the buffer
            i2d_X509_CRL_INFO(pX509_Crl->crl,&pucCrlNext);        //Fill the buffer
            CByteArray crl(pucCrl,lLen);                                //Fill the CByteArray
            free(pucCrl);                                                           //Free buffer

            //Verify if the signature of the certinfo is correct (regarding the issuer certificate)
            bOk=VerifySignature(crl,signature,pX509_Issuer,EVP_sha1());
      }

      return bOk;
}

00552 const EVP_MD *APL_CryptoFwk::ConvertAlgorithm(FWK_HashAlgo algo)
{
      switch(algo)
      {
      case FWK_ALGO_MD5:
            return EVP_md5();
      case FWK_ALGO_SHA1:
            return EVP_sha1();
      default:
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);
      }
}

00565 bool APL_CryptoFwk::VerifyHash(const CByteArray &data, const CByteArray &hash, FWK_HashAlgo algo)
{
      //Check the hash with sha1 algorithm
      return VerifyHash(data,hash,ConvertAlgorithm(algo));
}

00571 bool APL_CryptoFwk::VerifyHashMd5(const CByteArray &data, const CByteArray &hash)
{
      //Check the hash with sha1 algorithm
      return VerifyHash(data,hash,EVP_md5());
}

00577 bool APL_CryptoFwk::VerifyHashSha1(const CByteArray &data, const CByteArray &hash)
{
      //Check the hash with sha1 algorithm
      return VerifyHash(data,hash,EVP_sha1());
}

00583 bool APL_CryptoFwk::VerifyHash(const CByteArray &data, const CByteArray &hash, const EVP_MD *algorithm)
{
      CByteArray baCalculatedHash;

      if(!GetHash(data,algorithm,&baCalculatedHash))
            return false;

      //If the hash calculate is the same as the given hash, it's ok
      return (memcmp(baCalculatedHash.GetBytes(), hash.GetBytes(), hash.Size()) == 0);
}

00594 bool APL_CryptoFwk::GetHash(const CByteArray &data, FWK_HashAlgo algo, CByteArray *hash)
{
      return GetHash(data,ConvertAlgorithm(algo),hash);
}

00599 bool APL_CryptoFwk::GetHashSha1(const CByteArray &data, CByteArray *hash)
{
      //Get the hash with sha1 algorithm
      return GetHash(data,EVP_sha1(),hash);
}

00605 bool APL_CryptoFwk::GetHashMd5(const CByteArray &data, CByteArray *hash)
{
      //Get the hash with md5 algorithm
      return GetHash(data,EVP_md5(),hash);
}

00611 bool APL_CryptoFwk::GetHash(const CByteArray &data, const EVP_MD *algorithm, CByteArray *hash)
{
      if(hash==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      EVP_MD_CTX cmd_ctx;
      unsigned char md_value[EVP_MAX_MD_SIZE] = {0};
      unsigned int md_len = 0;

      //Calculate the hash from the data
      EVP_DigestInit(&cmd_ctx, algorithm);
    EVP_DigestUpdate(&cmd_ctx, data.GetBytes(), data.Size());
    EVP_DigestFinal(&cmd_ctx, md_value, &md_len);

      //Copy the hash in the ByteArray
      hash->ClearContents();
      hash->Append(md_value,md_len);

      return true;

}
00632 bool APL_CryptoFwk::VerifySignatureSha1(const CByteArray &data, const CByteArray &signature, const CByteArray &cert)
{
      bool bOk=false;

      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;

      //Convert cert into pX509_Cert
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //Verify if the signature of the data is correct (regarding the certificate pX509)
      bOk=VerifySignature(data,signature,pX509,EVP_sha1());

      //Free openSSL object
    X509_free(pX509);

      return bOk;
}

00653 bool APL_CryptoFwk::VerifySignature(const CByteArray &data, const CByteArray &signature, X509 *pX509, const EVP_MD *algorithm)
{
      if(pX509==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

    EVP_MD_CTX cmd_ctx;
    EVP_PKEY *pKey = NULL;
      const unsigned char *pucSign=NULL;
      long ret;

      //Get the public key
    if (NULL == (pKey = X509_get_pubkey(pX509)))
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //VERIFY THE DATA-SIGNATURE with public key
      EVP_VerifyInit(&cmd_ctx, algorithm);
    EVP_VerifyUpdate(&cmd_ctx, data.GetBytes(), data.Size());

      pucSign=signature.GetBytes();
#if (OPENSSL_VERSION_NUMBER > 0x009070ffL)
      ret=EVP_VerifyFinal(&cmd_ctx, pucSign, signature.Size(), pKey);
#else
    unsigned char* signatureBytes = const_cast<unsigned char*> (pucSign);
      ret=EVP_VerifyFinal(&cmd_ctx, signatureBytes, signature.Size(), pKey);
#endif
      

      EVP_MD_CTX_cleanup(&cmd_ctx);
      //Free openSSL object
    EVP_PKEY_free(pKey);

      return (ret==1);
}

00687 bool APL_CryptoFwk::VerifyRoot(const CByteArray &cert, const unsigned char *const *roots)
{
      const unsigned char *const *proot;
      for(proot=roots;*proot!=NULL;proot++)
      {
            if(memcmp(cert.GetBytes(),*proot,cert.Size())==0)
                  return true;
      }

      return false;
}

00699 bool APL_CryptoFwk::VerifyOid(const CByteArray &cert, const char *const *oids)
{
      const char *const *poid;

      //Convert CByteArray in X509
      X509 *pX509 = NULL;
      const unsigned char *pucCert=NULL;
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
        
      //Get the satck of policy info
      STACK_OF(POLICYINFO) *pol = NULL;
      if(NULL == (pol = (struct stack_st *) X509_get_ext_d2i(pX509, NID_certificate_policies, NULL, NULL)))
            return false;

      POLICYINFO *pinfo = NULL;
      bool bFound = false;

      //Loop through the policy info's 
      for(int j = 0; j < sk_POLICYINFO_num(pol); j++) 
      {
            pinfo = sk_POLICYINFO_value(pol, j);
            if(pinfo != NULL)
            {
                  //Get the policyid value
                  char szBuffer[64] = {0};
                  OBJ_obj2txt(szBuffer, 64, pinfo->policyid, 0);
                  //Compare to value to each value of oids array
                  for(poid=oids;*poid!=NULL;poid++)
                  {
                        //if value match we will return true
                        if (0 == strcmp(szBuffer, *poid))
                        {
                              bFound = true;
                              break;
                        }
                  }
                  if(bFound)
                        break;
            }
      }

      //Free resources
      sk_POLICYINFO_free(pol);
    X509_free(pX509);

      return bFound;
}

00749 FWK_CertifStatus APL_CryptoFwk::CRLValidation(const CByteArray &cert,const CByteArray &crl)
{
      X509_CRL *pX509Crl = NULL;
      X509 *pX509 = NULL;
      STACK_OF(X509_REVOKED) *pRevokeds = NULL;
      const unsigned char *pucCert=NULL;
      pucCert=cert.GetBytes();
      bool bFound=false;
      FWK_CertifStatus eStatus=FWK_CERTIF_STATUS_UNCHECK;

      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        goto cleanup;
      
      //Convert bytearray into X509_CRL
      if (NULL == (pX509Crl=getX509CRL(crl)))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

    pRevokeds = X509_CRL_get_REVOKED(pX509Crl);
    if(pRevokeds)
      {
            for(int i = 0; i < sk_X509_REVOKED_num(pRevokeds); i++) 
            {
                  X509_REVOKED *pRevoked = sk_X509_REVOKED_value(pRevokeds, i);
                  if(M_ASN1_INTEGER_cmp(X509_get_serialNumber(pX509),pRevoked->serialNumber)==0)
                  {
                        bFound=true;
                        break;
                  }
            }
      }

      if(bFound)
            eStatus = FWK_CERTIF_STATUS_REVOKED;
      else
            eStatus = FWK_CERTIF_STATUS_VALID;

cleanup:
      //Free openSSL object
    if(pX509) X509_free(pX509);

      return eStatus; 
}

00795 FWK_CertifStatus APL_CryptoFwk::OCSPValidation(const CByteArray &cert, const CByteArray &issuer, CByteArray *pResponse)
{
      return GetOCSPResponse(cert,issuer,pResponse);
}

00800 FWK_CertifStatus APL_CryptoFwk::GetOCSPResponse(const CByteArray &cert, const CByteArray &issuer, CByteArray *pResponse)
{
      bool bResponseOk = false;
      const unsigned char *pucCert=NULL;
      const unsigned char *pucIssuer=NULL;
      X509 *pX509_Cert = NULL;
      X509 *pX509_Issuer = NULL;
      OCSP_RESPONSE *pOcspResponse=NULL;
      FWK_CertifStatus eStatus=FWK_CERTIF_STATUS_UNCHECK;

      //Convert cert into pX509_Cert
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509_Cert, pucCert,cert.Size() ) )
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      //Convert issuer into pX509_Issuer
      pucIssuer=issuer.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509_Issuer, pucIssuer,issuer.Size() ) )
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }
        
      try
      {
            eStatus=GetOCSPResponse(pX509_Cert,pX509_Issuer,&pOcspResponse);
            if(eStatus!=FWK_CERTIF_STATUS_CONNECT && eStatus!=FWK_CERTIF_STATUS_ERROR)
                  bResponseOk=true;
      }
      catch(CMWException e)
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
      }

      if(bResponseOk && pResponse)
      {
            unsigned char *pBuffer=NULL;
            unsigned char *pBufferNext=NULL;

            long lLen = i2d_OCSP_RESPONSE(pOcspResponse, NULL);
            if(lLen > 0)
            {
                  pBuffer = pBufferNext = (unsigned char *)malloc(lLen);
                  i2d_OCSP_RESPONSE(pOcspResponse, &pBufferNext);
                  pResponse->Append(pBuffer,lLen);
                  free(pBuffer);
            }
            else
            {
                  eStatus=FWK_CERTIF_STATUS_ERROR;
            }     
      }

      //Free openSSL object
cleanup:
      if (pOcspResponse) OCSP_RESPONSE_free(pOcspResponse);
      if (pX509_Cert) X509_free(pX509_Cert);
    if (pX509_Issuer) X509_free(pX509_Issuer);

      return eStatus;
}

00865 FWK_CertifStatus APL_CryptoFwk::GetOCSPResponse(const char *pUrlResponder,const tOcspCertID &certid, CByteArray *pResponse,const CByteArray *issuer)
{
      if(certid.issuerNameHash==NULL || certid.issuerKeyHash==NULL || certid.serialNumber==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      bool bResponseOk = false;
      X509 *pX509_Issuer = NULL;
      OCSP_CERTID *pCertID=NULL;
      ASN1_TYPE *astype;
      X509_ALGOR *hashAlgorithm=NULL;
      ASN1_OCTET_STRING *issuerNameHash=NULL;
      ASN1_OCTET_STRING *issuerKeyHash=NULL;
      ASN1_INTEGER *serialNumber=NULL;
      FWK_CertifStatus eStatus=FWK_CERTIF_STATUS_UNCHECK;
      OCSP_RESPONSE *pOcspResponse=NULL;
      int nid = 0;

      if(issuer)
      {
            const unsigned char *pucIssuer=NULL;

            //Convert issuer into pX509_Issuer
            pucIssuer=issuer->GetBytes();
            if ( ! d2i_X509_Wrapper(&pX509_Issuer, pucIssuer,issuer->Size() ) )
            {
                  eStatus=FWK_CERTIF_STATUS_ERROR;
                  goto cleanup;
            }
      }

      //Convert tOcspCertID into OCSP_CERTID

      switch(certid.hashAlgorithm)
      {
      case FWK_ALGO_MD5:
            nid = EVP_MD_type(EVP_md5());
            break;
    case FWK_ALGO_SHA1:
            nid = EVP_MD_type(EVP_sha1());
            break;
      }     

      if (!(astype = ASN1_TYPE_new()))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      astype->type=V_ASN1_NULL; 

      if (!(hashAlgorithm = X509_ALGOR_new()))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      hashAlgorithm->algorithm=OBJ_nid2obj(nid);
      hashAlgorithm->parameter=astype;

      if(!(issuerNameHash=ASN1_OCTET_STRING_new()))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      // Mac's ASN1_OCTET_STRING_set() needs a 'const unsigned char *' instead of an 'unsigned char *'
      unsigned char tucTmp[200];

      memset(tucTmp, 0, sizeof(tucTmp));
      if (certid.issuerNameHash->Size() <= sizeof(tucTmp))
            memcpy(tucTmp, certid.issuerNameHash->GetBytes(), certid.issuerNameHash->Size());
      ASN1_OCTET_STRING_set(issuerNameHash, tucTmp,certid.issuerNameHash->Size());

      if(!(issuerKeyHash=ASN1_OCTET_STRING_new()))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      memset(tucTmp, 0, sizeof(tucTmp));
      if (certid. issuerKeyHash->Size() <= sizeof(tucTmp))
            memcpy(tucTmp, certid. issuerKeyHash->GetBytes(), certid. issuerKeyHash->Size());
      ASN1_OCTET_STRING_set(issuerKeyHash,tucTmp,certid.issuerKeyHash->Size());

      if(!(serialNumber=ASN1_INTEGER_new()))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      memset(tucTmp, 0, sizeof(tucTmp));
      if (certid. serialNumber->Size() <= sizeof(tucTmp))
            memcpy(tucTmp, certid. serialNumber->GetBytes(), certid. serialNumber->Size());
      ASN1_OCTET_STRING_set(serialNumber,tucTmp,certid.serialNumber->Size());
      
      if (!(pCertID = OCSP_CERTID_new()))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      pCertID->hashAlgorithm=hashAlgorithm;
      pCertID->issuerNameHash=issuerNameHash;
      pCertID->issuerKeyHash=issuerKeyHash;
      pCertID->serialNumber=serialNumber;

      try
      {
            eStatus=GetOCSPResponse(pUrlResponder,pCertID,&pOcspResponse,pX509_Issuer); 
            if(eStatus!=FWK_CERTIF_STATUS_CONNECT && eStatus!=FWK_CERTIF_STATUS_ERROR)
                  bResponseOk=true;
      }
      catch(CMWException e)
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
      }

      if(bResponseOk && pResponse)
      {
            unsigned char *pBuffer=NULL;
            unsigned char *pBufferNext=NULL;

            long lLen = i2d_OCSP_RESPONSE(pOcspResponse, NULL);
            if(lLen > 0)
            {
                  pBuffer = pBufferNext = (unsigned char *)malloc(lLen);
                  i2d_OCSP_RESPONSE(pOcspResponse, &pBufferNext);
                  pResponse->Append(pBuffer,lLen);
                  free(pBuffer);
            }
            else
            {
                  eStatus=FWK_CERTIF_STATUS_ERROR;
            }     
      }

cleanup:
      //Free openSSL object
      if (pOcspResponse) OCSP_RESPONSE_free(pOcspResponse);
      //if (pCertID) OCSP_CERTID_free(pCertID);
      //if (hashAlgorithm) X509_ALGOR_free(hashAlgorithm);
      //if (astype) ASN1_TYPE_free(astype);
      //if (issuerNameHash) ASN1_OCTET_STRING_free(issuerNameHash);
      //if (issuerKeyHash) ASN1_OCTET_STRING_free(issuerKeyHash);
      //if (serialNumber) ASN1_INTEGER_free(serialNumber);

      return eStatus;
}

01014 FWK_CertifStatus APL_CryptoFwk::GetOCSPResponse(X509 *pX509_Cert,X509 *pX509_Issuer, OCSP_RESPONSE **pResponse) 
{
      if(pX509_Cert==NULL || pX509_Issuer==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

    OCSP_CERTID *pCertID=NULL;
      char *pUrlResponder=NULL;
      FWK_CertifStatus eStatus=FWK_CERTIF_STATUS_UNCHECK;

      //Get the URL of the OCSP responder
      pUrlResponder = GetOCSPUrl(pX509_Cert);

      //If there is no OCSP responder, the certificate is unknown for OCSP
      if(pUrlResponder == NULL || strlen(pUrlResponder)==0)
      {
            eStatus = FWK_CERTIF_STATUS_UNKNOWN;
            goto cleanup;
      }

    pCertID = OCSP_cert_to_id(0, pX509_Cert, pX509_Issuer);
    if (!pCertID)
      {
            eStatus = FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      eStatus=GetOCSPResponse(pUrlResponder,pCertID,pResponse,pX509_Issuer);

cleanup:
      if (pUrlResponder) free(pUrlResponder);

    return eStatus;
}

01048 FWK_CertifStatus APL_CryptoFwk::GetOCSPResponse(const char *pUrlResponder,OCSP_CERTID *pCertID, OCSP_RESPONSE **pResponse,X509 *pX509_Issuer) 
{
      //The pointer should not be NULL
    if(pUrlResponder == NULL)
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //We must have a responder
      if(strlen(pUrlResponder)==0)
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

    if (!pCertID)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      BIO *pBio = 0;
      int iSSL=0;
    char *pszHost = 0;
    char *pszPath = 0;
    char *pszPort = 0;
    SSL_CTX  *pSSLCtx = 0;
    OCSP_REQUEST  *pRequest = 0;
    OCSP_BASICRESP *pBasic = NULL;
    bool  bConnect = false;
    ASN1_GENERALIZEDTIME  *producedAt, *thisUpdate, *nextUpdate;
      int iStatus=-1;
      FWK_CertifStatus eStatus=FWK_CERTIF_STATUS_UNCHECK;
      int iReason;

      //We parse the URL
      char *uri=new char[strlen(pUrlResponder)+1];
#ifdef WIN32
      strcpy_s(uri,strlen(pUrlResponder)+1,pUrlResponder);
#else
      strcpy(uri,pUrlResponder);
#endif
      if (!ParseUrl(uri, &pszHost, &pszPort, &pszPath, &iSSL)) 
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

      if(uri) delete[] uri;

      //We create the request
    if (!(pRequest = OCSP_REQUEST_new())) 
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }
   
      //We add the CertID
    if (!OCSP_request_add0_id(pRequest, pCertID))
      {
            eStatus=FWK_CERTIF_STATUS_ERROR;
            goto cleanup;
      }

    OCSP_request_add1_nonce(pRequest, 0, -1);

    try
      {
            /* establish a connection to the OCSP responder */
            pBio = Connect(pszHost, atoi(pszPort),iSSL,&pSSLCtx);
            bConnect = true;
      }
      catch(CMWException e)
      {
            eStatus=FWK_CERTIF_STATUS_CONNECT;
      }

      if(bConnect)
      {
            /* send the request and get a response */
            if( NULL == (*pResponse = OCSP_sendreq_bio(pBio, pszPath, pRequest)))
            {
                  eStatus=FWK_CERTIF_STATUS_ERROR;
                  goto cleanup;
            }

            int ResponseStatus = OCSP_response_status(*pResponse);
            if (ResponseStatus != OCSP_RESPONSE_STATUS_SUCCESSFUL) 
            {
                  eStatus=FWK_CERTIF_STATUS_ERROR;
                  goto cleanup;
            }
        
          if (!(pBasic = OCSP_response_get1_basic(*pResponse)))
            {
                  eStatus=FWK_CERTIF_STATUS_ERROR;
                  goto cleanup;
            }

            if(pX509_Issuer)
            {
                  //Get the algorithm
                  const EVP_MD *algorithm; 
                  int i=OBJ_obj2nid(pBasic->signatureAlgorithm->algorithm);
                  const char *algoName=OBJ_nid2sn(i);
                  algorithm=EVP_get_digestbyname(algoName); 
                  if(algorithm==NULL)
                        algorithm=EVP_sha1();

                  //Get the Data of the response
                  long lLen=i2d_OCSP_RESPDATA(pBasic->tbsResponseData,NULL); //Get the length for the buffer
                  if(lLen <= 0)
                  {
                        eStatus=FWK_CERTIF_STATUS_ERROR;
                        goto cleanup;
                  }

                  unsigned char *pucBuffer=NULL;
                  unsigned char *pucBufferNext=NULL;
                  pucBuffer = pucBufferNext = (unsigned char *)malloc(lLen);        //Allocate the buffer
                  i2d_OCSP_RESPDATA(pBasic->tbsResponseData,&pucBufferNext);        //Fill the buffer
                  CByteArray baData(pucBuffer,lLen);                                            //Fill the CByteArray
                  free(pucBuffer);                                                                    //Free buffer

                  //Get the signature
                  CByteArray baSignature(pBasic->signature->data,pBasic->signature->length);

                  //Verify if the signature of the hash is correct
                  if(!VerifySignature(baData,baSignature,pX509_Issuer,algorithm))
                  {
                        //if no we check the certificate in the response to see if has correctly signed the response
                        //and for this certificate we check if the issuer was the one we have
                        STACK_OF(X509) *pX509s = pBasic->certs;
                        X509 *pX509 = NULL;
                        bool bFound = false;

                        //Loop through the X509's 
                        for(int i = 0; i < sk_X509_num(pX509s); i++) 
                        {
                              pX509 = sk_X509_value(pX509s, i);
                              if(pX509 != NULL)
                              {
                                    if(VerifySignature(baData,baSignature,pX509,algorithm))
                                    {
                                          bFound = true;
                                          break;
                                    }
                              }
                        }
                        if(bFound)
                        {
                              if(!VerifyCertSignature(pX509,pX509_Issuer))
                                    eStatus=FWK_CERTIF_STATUS_ERROR;
                        }
                        else
                        {
                              eStatus=FWK_CERTIF_STATUS_ERROR;
                        }
                  }
            }

            if(eStatus!=FWK_CERTIF_STATUS_ERROR)
            {
                  if (!OCSP_resp_find_status(pBasic, pCertID, &iStatus, &iReason, &producedAt,&thisUpdate, &nextUpdate))
                  {
                        eStatus=FWK_CERTIF_STATUS_ERROR;
                  }
                  else
                  {
                        switch(iStatus)
                        {
                        case V_OCSP_CERTSTATUS_GOOD:
                              eStatus=FWK_CERTIF_STATUS_VALID;
                              break;
                        case V_OCSP_CERTSTATUS_REVOKED:
                              eStatus=FWK_CERTIF_STATUS_REVOKED;
                              break;
                        default:
                              eStatus=FWK_CERTIF_STATUS_UNKNOWN;
                              break;
                        }
                  }
            }
      }

cleanup:
    if (pBio) BIO_free_all(pBio);
    if (pszHost) OPENSSL_free(pszHost);
    if (pszPort) OPENSSL_free(pszPort);
    if (pszPath) OPENSSL_free(pszPath);
    if (pRequest) OCSP_REQUEST_free(pRequest);
    if (pSSLCtx) SSL_CTX_free(pSSLCtx);
    if (pBasic) OCSP_BASICRESP_free(pBasic);

    return eStatus;
}

01237 bool APL_CryptoFwk::GetOCSPUrl(const CByteArray &cert, std::string &url)
{
      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;
      char *pUrl=NULL;
      bool bOk=false;

      //Convert cert into pX509_Cert
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //Get the URL of the OCSP responder
      pUrl = GetOCSPUrl(pX509);

      url.clear();

      if(pUrl && strlen(pUrl)>0)
      {
            bOk=true;
            url+=pUrl;
      }

      if(pUrl) free(pUrl);
      if(pX509) X509_free(pX509);

      return bOk;
}

01266 char *APL_CryptoFwk::GetOCSPUrl(X509 *pX509_Cert) 
{
    struct stack_st *pStack = NULL;
    const char *pData = NULL;
    bool bFound = false;

      pStack = (struct stack_st *) X509_get_ext_d2i(pX509_Cert, NID_info_access, NULL, NULL);

    if(pStack == NULL)
#ifdef WIN32
        return _strdup("");
#else
        return strdup("");
#endif
      
      for(int j = 0; j < sk_ACCESS_DESCRIPTION_num(pStack); j++) 
    {
        ACCESS_DESCRIPTION *pAccess = sk_ACCESS_DESCRIPTION_value(pStack, j);
        if(pAccess != NULL && pAccess->method != NULL && OBJ_obj2nid(pAccess->method) == NID_ad_OCSP)
        {
            GENERAL_NAME *pName = pAccess->location;
            if(pName != NULL && pName->type == GEN_URI)
            {
                pData = (const char *)ASN1_STRING_data(pName->d.uniformResourceIdentifier); 
                bFound = true;
                        break;
            }
        }
    }
    sk_ACCESS_DESCRIPTION_free(pStack);

      if(!bFound)
            return NULL;

      //This path correspond to specific url for test card
      if(strcmp(pData,"http://ocsp.ZetesCards.be/dummy")==0)
#ifdef WIN32
        return _strdup("");
#else
        return strdup("");
#endif

#ifdef WIN32
        return _strdup(pData);
#else
        return strdup(pData);
#endif
}

01315 bool APL_CryptoFwk::GetCDPUrl(const CByteArray &cert, std::string &url)
{
      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;
      char *pUrl=NULL;
      bool bOk = false;

      //Convert cert into pX509_Cert
      pucCert=cert.GetBytes();
      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      //Get the URL of the OCSP responder
      pUrl = GetCDPUrl(pX509);

      url.clear();

      if(pUrl && strlen(pUrl)>0)
      {
            bOk=true;
            url+=pUrl;
      }

      if(pUrl) free(pUrl);
      if(pX509) X509_free(pX509);

      return bOk;
}

01344 char *APL_CryptoFwk::GetCDPUrl(X509 *pX509_Cert) 
{
    struct stack_st *pStack = NULL;
    const char *pData = NULL;
    bool bFound = false;

      pStack = (struct stack_st *) X509_get_ext_d2i(pX509_Cert, NID_crl_distribution_points, NULL, NULL);

    if(pStack == NULL)
#ifdef WIN32
        return _strdup("");
#else
        return strdup("");
#endif
      
    for(int j = 0; j < sk_DIST_POINT_num(pStack); j++) 
    {
        DIST_POINT *pRes = (DIST_POINT *)sk_DIST_POINT_value(pStack, j);
        if(pRes != NULL)
        {
            STACK_OF(GENERAL_NAME) *pNames = pRes->distpoint->name.fullname;
            if(pNames)
            {
                for(int i = 0; i < sk_GENERAL_NAME_num(pNames); i++) 
                {
                    GENERAL_NAME *pName = sk_GENERAL_NAME_value(pNames, i);
                    if(pName != NULL && pName->type == GEN_URI )
                    {
                        pData = (const char *)ASN1_STRING_data(pName->d.uniformResourceIdentifier); 
                        bFound = true;
                                    break;
                    }
                 }
                sk_GENERAL_NAME_free(pNames);
                        if(bFound) break;
            }
        }
    } 
    sk_DIST_POINT_free(pStack);

      if(!bFound)
            return NULL;

      //This path correspond to specific url for test card
      if(strcmp(pData,"http://crl.eid.zetes.be/belgium/belgium.crl")==0)
#ifdef WIN32
        return _strdup("");
#else
        return strdup("");
#endif

#ifdef WIN32
        return _strdup(pData);
#else
        return strdup(pData);
#endif
}

01402 bool APL_CryptoFwk::getCertInfo(const CByteArray &cert, tCertifInfo &info, const char *dateFormat)
{
      const unsigned char *pucCert=NULL;
      X509 *pX509 = NULL;

      //Convert cert into pX509_Cert
      pucCert=cert.GetBytes();

      if ( ! d2i_X509_Wrapper(&pX509, pucCert,cert.Size() ) )
        throw CMWEXCEPTION(EIDMW_ERR_CHECK);
        
    char szTemp[128] = {0};

      CByteArray baTemp;

      baTemp.ClearContents();
      baTemp.Append(X509_get_serialNumber(pX509)->data,X509_get_serialNumber(pX509)->length);
      info.serialNumber=baTemp.ToString(false);

    memset(szTemp, 0, sizeof(szTemp));
      X509_NAME_get_text_by_NID(X509_get_subject_name(pX509), NID_commonName, szTemp, sizeof(szTemp));
      info.ownerName=szTemp;

    memset(szTemp, 0, sizeof(szTemp));
      X509_NAME_get_text_by_NID(X509_get_issuer_name(pX509), NID_commonName, szTemp, sizeof(szTemp));
      info.issuerName=szTemp;

      TimeToString(X509_get_notBefore(pX509),info.validityNotBefore,dateFormat);
      TimeToString(X509_get_notAfter(pX509),info.validityNotAfter,dateFormat);

    EVP_PKEY *pKey = X509_get_pubkey(pX509);
    if(pKey) info.keyLength=EVP_PKEY_bits(pKey);

      //Free openSSL object
      if(pX509) X509_free(pX509);
    if(pKey) EVP_PKEY_free(pKey);

      return true;
}

01442 bool APL_CryptoFwk::getCrlInfo(const CByteArray &crl,tCrlInfo &info, const char *dateFormat)
{
      bool bDownload=true;

      X509_CRL *pX509CRL = getX509CRL(crl);
      if(!pX509CRL)
            throw CMWEXCEPTION(EIDMW_ERR_CHECK);

      int iCheck = 0;

      iCheck = X509_cmp_time(X509_CRL_get_lastUpdate(pX509CRL), NULL);
      if (iCheck >= 0)
      {
            // X509_V_ERR_CRL_NOT_YET_VALID or X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD error
            bDownload = false;
      }

      iCheck = X509_cmp_time(X509_CRL_get_nextUpdate(pX509CRL), NULL);
      if (iCheck <= 0)
      {
            // X509_V_ERR_CRL_HAS_EXPIRED or X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD error
            bDownload = false;
       }

    char szTemp[128] = {0};

      memset(szTemp, 0, sizeof(szTemp));
      X509_NAME_get_text_by_NID(X509_CRL_get_issuer(pX509CRL), NID_commonName, szTemp, sizeof(szTemp));
      info.issuerName=szTemp;
      //info.issuerName=X509_CRL_get_issuer(pX509CRL);

      TimeToString(X509_CRL_get_lastUpdate(pX509CRL),info.validityLastUpdate,dateFormat);
      TimeToString(X509_CRL_get_nextUpdate(pX509CRL),info.validityNextUpdate,dateFormat);

      return bDownload;
}

01479 X509_CRL *APL_CryptoFwk::getX509CRL(const CByteArray &crl)
{
      CByteArray baHash;
      GetHash(crl,EVP_sha1(),&baHash);

      return m_CrlMemoryCache->getX509CRL(crl,baHash);
}

01487 BIO *APL_CryptoFwk::Connect(char *pszHost, int iPort, int iSSL, SSL_CTX **ppSSLCtx) 
{
      ThreadConnect thread_connect(pszHost,iPort,iSSL,ppSSLCtx);
      thread_connect.Start();

      APL_Config conf_timeout(CConfig::EIDMW_CONFIG_PARAM_PROXY_CONNECT_TIMEOUT);
      long timeout=conf_timeout.getLong();

      if(!thread_connect.WaitTimeout(timeout,1))
            throw CMWEXCEPTION(EIDMW_ERR_SOCKET_CONNECT);

      BIO *pConnect = thread_connect.getConnect();
      if(pConnect==NULL)
            throw CMWEXCEPTION(EIDMW_ERR_SOCKET_CONNECT);

    return pConnect;
}

01505 void APL_CryptoFwk::resetProxy()
{
      APL_Config conf_pac(CConfig::EIDMW_CONFIG_PARAM_PROXY_PACFILE);     
      m_proxy_pac = conf_pac.getString();

      APL_Config conf_host(CConfig::EIDMW_CONFIG_PARAM_PROXY_HOST);     
      m_proxy_host = conf_host.getString();

      APL_Config conf_port(CConfig::EIDMW_CONFIG_PARAM_PROXY_PORT); 
      char buffer[10];
      sprintf_s(buffer,sizeof(buffer),"%ld",conf_port.getLong());
      m_proxy_port = buffer;

      MWLOG(LEV_INFO, MOD_SSL, L"Proxy settings: pac='%ls', host='%ls' and port=%ls",utilStringWiden(m_proxy_pac).c_str(),utilStringWiden(m_proxy_host).c_str(),utilStringWiden(m_proxy_port).c_str());
}

01521 int APL_CryptoFwk::ParseUrl(char *pszUri, char **pszHost, char **pszPort, char **pszPath, int *iSSL)
{
      std::string proxy_host;
      std::string proxy_port;

      //If there is a pac file we check for the host and port for this uri
      if(!m_proxy_pac.empty())
    {
            if(!GetProxyFromPac(m_proxy_pac.c_str(),pszUri,&proxy_host,&proxy_port))
            {
                  proxy_host.clear();
                  proxy_port.clear();
            }
      }
      else
      {
            proxy_host=m_proxy_host;
            proxy_port=m_proxy_port;
      }

      if(!proxy_host.empty())
    {
        *pszHost = (char *)OPENSSL_malloc(proxy_host.size() + 1);
        strcpy_s(*pszHost,proxy_host.size() + 1, proxy_host.c_str()); 
    }
    if(!proxy_port.empty() && strcmp(proxy_port.c_str(),"0")!=0)
    {
        *pszPort = (char *)OPENSSL_malloc(proxy_port.size() + 1);
        strcpy_s(*pszPort,proxy_port.size() + 1, proxy_port.c_str()); 
    }

     if(*pszHost == NULL || *pszPort == NULL)
    {
        return OCSP_parse_url(pszUri, pszHost, pszPort, pszPath, iSSL);
     }
     else
     {
        *pszPath = (char *)OPENSSL_malloc(strlen(pszUri) + 1);
        strcpy_s(*pszPath,strlen(pszUri) + 1, pszUri); 
            return 1;
     }

       return 0;
}

01566 bool APL_CryptoFwk::downloadFile(const char *pszUri, CByteArray &baData,bool &bStopping) 
{
    long lBytes = 0;
    unsigned long ulContentLength = 0;
    unsigned long ulHeaderLen = 0;
    int iSd = 0;
    int iSSL = 0;
    int iSel = 0;
    BIO *pBio = 0;
    SSL *pSSL = 0;
    SSL_CTX *pSSLCtx = 0;
    char szBuffer[1024] = {0};
    char *pszHeaders = NULL;
    char *pszHost = NULL;
    char *pszPath = NULL;
    char *pszPort = NULL;
    char *pszTmp = NULL;
    fd_set  rmask, wmask;
    struct timeval tTimeOut;
    tTimeOut.tv_sec = 5;
    tTimeOut.tv_usec = 0;
    void  *pvData = NULL;
      bool bConnect=false;
      bool bDownloadOk=false;

      unsigned long ulLen=0;
      baData.ClearContents();

    if (!ParseUrl((char *)pszUri, &pszHost, &pszPort, &pszPath, &iSSL)) 
            goto end_error;

      try
      {
            /* establish a connection to the OCSP responder */
            pBio = Connect(pszHost, atoi(pszPort),iSSL,&pSSLCtx);
            bConnect = true;
      }
      catch(CMWException e)
      {
            //If connection failed, we return the CONNECT status
            if(e.GetError()!=(long)EIDMW_ERR_SOCKET_CONNECT)
                  throw e;

            return bDownloadOk;
      }
   
      if(bConnect)
      {
            // Send the request for the data
            BIO_printf(pBio, "GET %s HTTP/1.0\r\nConnection: close\r\n\r\n", pszPath);
         
            // Put the socket into non-blocking mode
            BIO_get_fd(pBio, &iSd);
            BIO_socket_nbio(iSd, 1);
            if (iSSL) 
            {
                  BIO_get_ssl(pBio, &pSSL);
                  SSL_set_mode(pSSL, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
            }
         
            // Loop reading data from the socket until we've got all of the headers
            for (;;) 
            {
                  FD_ZERO(&rmask);
                  FD_SET(iSd, &rmask);
                  FD_ZERO(&wmask);
                  if (BIO_should_write(pBio)) 
                        FD_SET(iSd, &wmask);
                  iSel = select(FD_SETSIZE, &rmask, &wmask, 0, &tTimeOut);
                  if(iSel < 0) goto end_error;
                  if(iSel ==  0) continue;
                  if (FD_ISSET(iSd, &wmask)) BIO_write(pBio, szBuffer, 0);
                  if (FD_ISSET(iSd, &rmask)) 
                  {
                        if ((lBytes = BIO_read(pBio, szBuffer, sizeof(szBuffer))) <= 0) 
                        {
                              if (BIO_should_retry(pBio)) continue;
                              goto end_error;
                        }
                        if (!(pszHeaders = (char *)realloc((pszTmp = pszHeaders), ulHeaderLen + lBytes))) 
                        {
                              pszHeaders = pszTmp;
                              goto end_error;
                        }
                        memcpy(pszHeaders + ulHeaderLen, szBuffer, lBytes);
                        ulHeaderLen += lBytes;
                        if ((pszTmp = strstr(pszHeaders, "\r\n\r\n")) != 0) 
                        {
                              *(pszTmp + 2) = '\0';
                              ulLen = ulHeaderLen - ((pszTmp + 4) - pszHeaders);
                              ulHeaderLen -= (ulLen + 2);
                              if (ulLen > 0) 
                              {
                                    if (!(pvData = (char *)malloc(ulLen))) goto end_error;
                                    memcpy(pvData, pszTmp + 4, ulLen);
                              }
                              break;
                        }
                  }
            }
        
            /* Examine the headers to determine whether or not to continue.  If we are to
            * continue, look for a content-length header to find out how much data we're
            * going to get.  If there is no content-length header, we'll have to read
            * until the remote server closes the connection.
            */
#ifdef WIN32
            if (0 == _strnicmp(pszHeaders, "HTTP/1.", 7)) 
#else
            if (0 == strncasecmp(pszHeaders, "HTTP/1.", 7)) 
#endif
            {
                  if (!(pszTmp = strchr(pszHeaders, ' '))) goto end_error;
                  if (strncmp(pszTmp + 1, "200 ", 4) && strncmp(pszTmp + 1, "200\r\n", 5))
                        goto end_error;
                  for (pszTmp = strstr(pszHeaders, "\r\n");  pszTmp;  pszTmp = strstr(pszTmp + 2, "\r\n")) 
                  {
#ifdef WIN32
                        if (_strnicmp(pszTmp + 2, "content-length: ", 16)) continue;
#else
                        if ( strncasecmp(pszTmp + 2, "content-length: ", 16)) continue;
#endif
                        ulContentLength = atol(pszTmp + 18);
                        break;
                  }
            } 
            else 
                  goto end_error;
         
            /* Continuously read and accumulate data from the remote server.  Finish when
            * we've read up to the content-length that we received.  If we didn't receive
            * a content-length, read until the remote server closes the connection.
            */
            if(ulContentLength > 0)
            {
                  char *pvTemp = (char *)malloc(ulLen);
                  memcpy(pvTemp, pvData, ulLen);
                  free(pvData);
                  pvData = (char *)malloc(ulContentLength);
                  if(!pvData)
                        goto end_error;

                  memcpy(pvData, pvTemp, ulLen);
                  free(pvTemp);
            }
            while ((!ulContentLength || ulLen < ulContentLength) && !bStopping) 
            {
                  FD_ZERO(&rmask);
                  FD_SET(iSd, &rmask);
                  FD_ZERO(&wmask);
                  if (BIO_should_write(pBio)) FD_SET(iSd, &wmask);
                  iSel = select(FD_SETSIZE, &rmask, &wmask, 0, &tTimeOut);
                  if(iSel < 0) 
                        goto end_error;
                  if(iSel ==  0) 
                        continue;
                  if (FD_ISSET(iSd, &wmask)) BIO_write(pBio, szBuffer, 0);
                  if (FD_ISSET(iSd, &rmask))
                  if ((lBytes = BIO_read(pBio, szBuffer, sizeof(szBuffer))) <= 0) 
                  {
                        if (BIO_should_retry(pBio)) continue;
                        break;
                  }
                  memcpy((char *)pvData + ulLen, szBuffer, lBytes);
                  ulLen += lBytes;
            }

            if ((ulContentLength && ulLen != ulContentLength) || bStopping) 
                  goto end_error;

            baData.Append((unsigned char *)pvData,ulLen);
      }

      bDownloadOk=true;

    goto end;
   
end_error:
      if (pvData) 
      { 
            free(pvData);  
      }

end:
      if (pszHeaders) free(pszHeaders);
      if (pBio) BIO_free_all(pBio);
      if (pszHost) OPENSSL_free(pszHost);
      if (pszPort) OPENSSL_free(pszPort);
      if (pszPath) OPENSSL_free(pszPath);
      if (pSSLCtx) SSL_CTX_free(pSSLCtx);

      return bDownloadOk;
}

01760 bool APL_CryptoFwk::b64Encode(const CByteArray &baIn, CByteArray &baOut,bool bWithLineFeed)
{
      unsigned int iLenOut=0;
      XMLByte *pOut=NULL;

      //Encode the baIn
      pOut=XERCES_CPP_NAMESPACE::Base64::encode((XMLByte *)baIn.GetBytes(),baIn.Size(),&iLenOut);
      if(!pOut)
            return false;

      //Put the result in baOut
      baOut.ClearContents();
      baOut.Append(pOut,iLenOut);

      XERCES_CPP_NAMESPACE::XMLString::release(&pOut);

      //If we don't want linefeed, we have to replace them by space
      if(!bWithLineFeed)
            baOut.Replace(0x0a,' ');

      return true;
}

01783 bool APL_CryptoFwk::b64Decode(const CByteArray &baIn, CByteArray &baOut)
{
      unsigned char *pIn=NULL;
      unsigned int iLenOut=0;
      XMLByte *pOut=NULL;

      //The byte array must be zero terminated
      pIn=new unsigned char[baIn.Size()+1];
      memcpy(pIn,baIn.GetBytes(),baIn.Size());
      pIn[baIn.Size()]=0;

      //Decode the pIn
      pOut=XERCES_CPP_NAMESPACE::Base64::decode((XMLByte *)pIn,&iLenOut);
      if(!pOut)
      {
            delete[] pIn;
            return false;
      }

      //Put the result in baOut
      baOut.ClearContents();
      baOut.Append(pOut,iLenOut);
      XERCES_CPP_NAMESPACE::XMLString::release(&pOut);
      delete[] pIn;

      return true;
}

01811 void APL_CryptoFwk::TimeToString(ASN1_TIME *asn1Time, std::string &strTime, const char *dateFormat)
{
    struct tm timeinfo;
      char buffer [50];

      if(asn1Time->type == V_ASN1_UTCTIME)
        UtcTimeToString(asn1Time, timeinfo);

      if(asn1Time->type == V_ASN1_GENERALIZEDTIME)
            GeneralTimeToString(asn1Time, timeinfo);
      try
      {
            strftime (buffer,sizeof(buffer),dateFormat,&timeinfo);
            strTime.assign(buffer);
      }
      catch(...)
      {
            strTime.clear();
      }
} 

01832 void APL_CryptoFwk::GeneralTimeToString(ASN1_GENERALIZEDTIME *asn1Time, struct tm &timeinfo)
{
      char *v;
      int gmt=0;
      int i;

      i=asn1Time->length;
      v=(char *)asn1Time->data;

      if (i < 12) 
            return;

      if (v[i-1] == 'Z') 
            gmt=1;

      for (i=0; i<12; i++)
      {
            if ((v[i] > '9') || (v[i] < '0')) 
                  return;
      }

      timeinfo.tm_year= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
      timeinfo.tm_mon= (v[4]-'0')*10+(v[5]-'0')-1;

      if ((timeinfo.tm_mon > 11) || (timeinfo.tm_mon < 0)) 
            return;

      timeinfo.tm_mday= (v[6]-'0')*10+(v[7]-'0');
      timeinfo.tm_hour= (v[8]-'0')*10+(v[9]-'0');
      timeinfo.tm_min=  (v[10]-'0')*10+(v[11]-'0');

      if ((v[12] >= '0') && (v[12] <= '9') && (v[13] >= '0') && (v[13] <= '9'))
            timeinfo.tm_sec=  (v[12]-'0')*10+(v[13]-'0');
}

01867 void APL_CryptoFwk::UtcTimeToString(ASN1_UTCTIME *asn1Time, struct tm &timeinfo)
{
      char *v;
      int gmt=0;
      int i;

      i=asn1Time->length;
      v=(char *)asn1Time->data;

      if (i < 10) 
            return;

      if (v[i-1] == 'Z') 
            gmt=1;

      for (i=0; i<10; i++)
      {
            if ((v[i] > '9') || (v[i] < '0')) 
                  return;
      }

      timeinfo.tm_year= (v[0]-'0')*10+(v[1]-'0');

      if (timeinfo.tm_year < 50) 
            timeinfo.tm_year+=100;

      timeinfo.tm_mon= (v[2]-'0')*10+(v[3]-'0')-1;

      if ((timeinfo.tm_mon > 11) || (timeinfo.tm_mon < 0)) 
            return;

      timeinfo.tm_mday= (v[4]-'0')*10+(v[5]-'0');
      timeinfo.tm_hour= (v[6]-'0')*10+(v[7]-'0');
      timeinfo.tm_min=  (v[8]-'0')*10+(v[9]-'0');

      if ((v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9'))
            timeinfo.tm_sec=  (v[10]-'0')*10+(v[11]-'0');
}

}

Generated by  Doxygen 1.6.0   Back to index