00001 
00009 #include "PKIFCAPIRaw.h"
00010 #include "PKIFCAPICryptContext2.h"
00011 #include "PKIFCAPIHashContext.h"
00012 #include "CAPIUtils.h"
00013 
00014 #include "PKIFCryptoException.h"
00015 #include "PKIFKeyMaterial.h"
00016 #include "PKIFCryptoErrors.h"
00017 #include "PKIFCAPIErrors.h"
00018 #include "CAPIRawCryptContext.h"
00019 #include "PKIFAlgorithm.h"
00020 
00021 #include "AlgorithmIdentifier.h"
00022 #include "Buffer.h"
00023 #include "Certificate.h"
00024 #include "ToolkitUtils.h"
00025 #include "components.h"
00026 #include "PKIFException.h"
00027 
00028 #include "SubjectPublicKeyInfo.h"
00029 
00030 #include "ASN1Helper.h"
00031 #include "PKIX1Algorithms88.h"
00032 
00033 #include <iostream>
00034 #include <sstream>
00035 using namespace std;
00036 
00037 #if !defined(ALG_SID_SHA_256)
00038 #define ALG_SID_SHA_256 12 
00039 #define ALG_SID_SHA_384 13 
00040 #define ALG_SID_SHA_512 14 
00041  
00042 #define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) 
00043 #define CALG_SHA_384 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384) 
00044 #define CALG_SHA_512 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512) 
00045 #endif 
00046 
00047 CAC_API char g_defCACCAPITrustStore[] = "Root";
00048 
00050 struct CPKIFCAPIRawImpl
00051 {
00052 
00053     CPKIFCAPIRaw* m_parent;
00054     char * m_provName;
00055     int m_provType;
00063     CPKIFCAPIRawImpl ()
00064     {
00065         m_parent = NULL;
00066     }
00074     CPKIFCAPIRawImpl (CPKIFCAPIRaw  *p) 
00075     {
00076         m_parent = p;
00077     }
00079     HCRYPTPROV m_hProv;
00081     HCRYPTKEY m_hPubPrivKey;
00082 
00083     template<bool _CryptDirection>
00084     void Crypt(const CPKIFKeyMaterial& key, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool pad = true);
00085 
00086     template <bool _CryptDirection>
00087     void CryptFunc(IPKIFRawCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final);
00088 
00089 };
00091 
00100 CPKIFCAPIRaw::CPKIFCAPIRaw(void)
00101     :m_impl (new CPKIFCAPIRawImpl)
00102 {
00103     LOG_STRING_DEBUG("CPKIFCAPIRaw::CPKIFCAPIRaw(void)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00104     InitImpl();
00105 }
00106 
00115 CPKIFCAPIRaw::CPKIFCAPIRaw(
00117              const char* provider,
00119              int provType)
00120      :m_impl (new CPKIFCAPIRawImpl)
00121 {
00122     LOG_STRING_DEBUG("CPKIFCAPIRaw::CPKIFCAPIRaw(provider,provType)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00123     InitImpl(provider,provType);
00124 }
00132 CPKIFCAPIRaw::~CPKIFCAPIRaw(void)
00133 {
00134     LOG_STRING_DEBUG("CPKIFCAPIRaw::~CPKIFCAPIRaw(void)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00135 
00136     if(NULL != m_impl->m_hPubPrivKey)
00137     {
00138         BOOL succ = CryptDestroyKey(m_impl->m_hPubPrivKey);
00139         m_impl->m_hPubPrivKey = NULL;
00140     }
00141     if(NULL != m_impl->m_hProv)
00142     {
00143         BOOL succ = CryptReleaseContext(m_impl->m_hProv, 0);
00144         m_impl->m_hProv = NULL;
00145     }
00146     if(NULL != m_impl->m_provName) {
00147         free(m_impl->m_provName);
00148     }
00149     delete m_impl;
00150     m_impl = NULL;
00151 }
00159 void CPKIFCAPIRaw::Initialize()
00160 {
00161     LOG_STRING_DEBUG("CPKIFCAPIRaw::Initialize()", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00162 }
00163 
00164 
00172 void CPKIFCAPIRaw::InitImpl(const char * provider, int provType)
00173 {
00174     m_impl->m_parent = this;
00175     m_impl->m_hProv = NULL;
00176     m_impl->m_hPubPrivKey = NULL;
00177     if(provider) {
00178         m_impl->m_provName = _strdup(provider);
00179     } else {
00180         m_impl->m_provName = NULL;
00181     }
00182     m_impl->m_provType = provType;
00183 }
00184 
00194 ALG_ID GetSymAlgorithm(
00196     const CPKIFKeyMaterial& key)
00197 {
00198     switch(key.GetSymmetricKeyAlgorithm())
00199     {
00200     case PKIFCRYPTO::DES:
00201         return CALG_DES;
00202     case PKIFCRYPTO::TDES:
00203         return CALG_3DES;
00204     
00205     
00206     
00207     
00208     
00209     
00210     
00211     
00212     default:
00213         RAISE_CRYPTO_EXCEPTION("", TOOLKIT_CRYPTO, CRYPTO_ALG_NOT_SUPPORTED, NULL)
00214     }
00215 }
00225 DWORD GetProvType(
00227     PCCERT_CONTEXT cert)
00228 {
00229     
00230     if(0 == strcmp(szOID_X957_DSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00231         0 == strcmp(szOID_X957_SHA1DSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId))
00232         return PROV_DSS;
00233     else if(0 == strcmp(szOID_RSA_RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00234         0 == strcmp(szOID_RSA_MD5RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00235         0 == strcmp(szOID_RSA_SHA1RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId)) 
00236         return PROV_RSA_FULL;
00237     else
00238         RAISE_CRYPTO_EXCEPTION(cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, TOOLKIT_CRYPTO_CAPIRAW, CRYPTO_ALG_NOT_SUPPORTED, NULL)
00239 }
00249 DWORD GetProvType(
00251     const char* oidString)
00252 {
00253     
00254     if(0 == strcmp(szOID_X957_DSA, oidString) ||
00255         0 == strcmp(szOID_X957_SHA1DSA, oidString))
00256         return PROV_DSS;
00257     else if(0 == strcmp(szOID_RSA_RSA, oidString) ||
00258         0 == strcmp(szOID_RSA_MD5RSA, oidString) ||
00259         0 == strcmp(szOID_RSA_SHA1RSA, oidString)) 
00260         return PROV_RSA_FULL;
00261     else
00262         RAISE_CRYPTO_EXCEPTION(oidString, TOOLKIT_CRYPTO_CAPIRAW, CRYPTO_ALG_NOT_SUPPORTED, NULL)
00263 }
00279 bool CPKIFCAPIRaw::SupportsAlgorithm(
00281     const CPKIFKeyMaterial& key)
00282 {
00283     LOG_STRING_DEBUG("CPKIFCAPIRaw::SupportsAlgorithm(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00284 
00285     if(key.ContainsSymmetricKeyMaterial())
00286     {   
00287         try
00288         {
00289             GetSymAlgorithm(key);
00290             return true;
00291         }
00292         catch(CPKIFCryptoException& e)
00293         {
00294             if(CRYPTO_ALG_NOT_SUPPORTED == e.GetErrorCode())
00295             {
00296                 
00297                 
00298                 
00299                 
00300                 return false;
00301             }
00302             else
00303                 throw e; 
00304         }
00305     }
00306     else if(key.ContainsCertificate())
00307     {
00308         PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
00309             key.GetCertificate(), key.GetCertificateLength());
00310         if(NULL == cert)
00311         {
00312             std::ostringstream os;
00313             os << "CertCreateCertificateContext failed: " << GetLastError();
00314             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_CREATE_CERT_FAILED, this)
00315         }
00316 
00317         try
00318         {
00319             GetProvType(cert);
00320             if (NULL != cert)  
00321             {   CertFreeCertificateContext(cert); cert = NULL; }  
00322             return true;
00323         }
00324         catch(CPKIFException& e)
00325         {
00326             if (NULL != cert)  
00327             {   CertFreeCertificateContext(cert); cert = NULL; }  
00328 
00329             if(CRYPTO_ALG_NOT_SUPPORTED == e.GetErrorCode())
00330             {
00331                 
00332                 
00333                 
00334                 
00335                 return false;
00336             }
00337             else
00338                 throw e; 
00339         }
00340     }
00341     else
00342     {
00343         RAISE_CRYPTO_EXCEPTION("key parameter contents not recognized.", thisComponent, COMMON_INVALID_INPUT, this);
00344     }
00345 }
00356 void CPKIFCAPIRaw::Sign(
00358     const CPKIFKeyMaterial& key,
00360     unsigned char* pHashData,
00362     int nHashDataLen,
00364     unsigned char* pSignature,
00366     int* nSignatureLen,
00368     PKIFCRYPTO::HASH_ALG hashAlg
00369     )
00370 {
00371     LOG_STRING_DEBUG("CPKIFCAPIRaw::Sign(const CPKIFKeyMaterial& key,...)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00372 
00373     
00374     RAISE_CRYPTO_EXCEPTION("Signing operations are not implemented for raw key material.", thisComponent, COMMON_NOT_IMPLEMENTED, this);
00375 }
00376 
00377 
00399 template <bool _CryptDirection>
00400 void CPKIFCAPIRawImpl::Crypt(
00402     const CPKIFKeyMaterial& key,
00404     unsigned char* pData, 
00406     int nDataLen, 
00408     unsigned char* pResult, 
00411     int* pnResultLen, 
00415     bool pad)
00416 {
00417 #undef CLEANUP
00418 #define CLEANUP \
00419 { \
00420     if (NULL != hSessionKey)  \
00421     {   BOOL succ = CryptDestroyKey(hSessionKey); hSessionKey = NULL;}  \
00422     if (NULL != hTmpProv)  \
00423     {   CryptReleaseContext(hTmpProv, 0); hTmpProv = NULL; }  \
00424     if (NULL != cert)  \
00425     {   CertFreeCertificateContext(cert); cert = NULL; }  \
00426 } 
00427 
00428     LOG_STRING_DEBUG("CPKIFCAPIRaw::Crypt(const CPKIFKeyMaterial& key, ...)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
00429 
00430     HCRYPTKEY hSessionKey = 0;
00431     BOOL succ = FALSE;
00432     HCRYPTPROV hTmpProv = NULL;
00433     PCCERT_CONTEXT cert = NULL;
00434 
00435     if(key.ContainsSymmetricKeyMaterial())
00436     {
00437         if(NULL == m_hProv)
00438         {
00439             
00440             succ = CreatePrivateExponentOneKey(MS_ENHANCED_PROV, PROV_RSA_FULL,
00441                                                 "__PKIFTEMPCONTAINER", AT_KEYEXCHANGE, &m_hProv, &m_hPubPrivKey);
00442             if (!succ)
00443             {
00444                 if(NULL != m_hPubPrivKey)
00445                 {
00446                     CryptDestroyKey(m_hPubPrivKey); m_hPubPrivKey = NULL;
00447                 }
00448                 if(NULL != m_hProv)
00449                 {
00450                     CryptReleaseContext(m_hProv, 0); m_hProv = NULL;
00451                 }
00452                 std::ostringstream os;
00453                 os << "CreatePrivateExponentOneKey failed: " << GetLastError();;
00454                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_SESSION_KEY_ENCRYPT_FAILED, this);
00455             }
00456         }
00457 
00458         ALG_ID tmpAlgID = GetSymAlgorithm(key);
00459         if (!ImportPlainSessionBlob(m_hProv, m_hPubPrivKey, tmpAlgID, (unsigned char*)key.GetSymmetricKey(), key.GetSymmetricKeyLength(), &hSessionKey))
00460         {
00461             CLEANUP;
00462             std::ostringstream os;
00463             os << "ImportPlainSessionBlob failed: " << GetLastError();;
00464             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_KEY_IMPORT_FAILED, this);
00465         }
00466 
00467         DWORD tmpMode = 0;
00468         switch(key.GetMode())
00469         {
00470         case PKIFCRYPTO::ECB:
00471             tmpMode = CRYPT_MODE_ECB;
00472             break;
00473         case PKIFCRYPTO::CBC:
00474             tmpMode = CRYPT_MODE_CBC;
00475             if(NULL == key.GetIV())
00476                 throw CPKIFCryptoException(m_parent->thisComponent, CRYPTO_MISSING_IV);
00477             break;
00478         default:
00479             throw CPKIFCryptoException(m_parent->thisComponent, CRYPTO_MODE_NOT_SUPPORTED);
00480         }
00481 
00482         DWORD paddingType = PKCS5_PADDING;
00483         if(pad) 
00484         {
00485             if(!CryptSetKeyParam(hSessionKey, KP_PADDING, (BYTE*)&paddingType, 0))
00486             {
00487                 CLEANUP;
00488                 std::ostringstream os;
00489                 os << "CryptSetKeyParam failed: " << GetLastError();;
00490                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_SET_MODE_FAILED, this);
00491             }
00492         }
00493 
00494         if(!CryptSetKeyParam(hSessionKey, KP_MODE, (BYTE*)&tmpMode, 0))
00495         {
00496             CLEANUP;
00497             std::ostringstream os;
00498             os << "CryptSetKeyParam failed: " << GetLastError();;
00499             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_SET_MODE_FAILED, this);
00500         }
00501 
00502         if(NULL != key.GetIV() && PKIFCRYPTO::CBC == key.GetMode())
00503         {
00504             if(!CryptSetKeyParam(hSessionKey, KP_IV, (BYTE*)key.GetIV(), 0))
00505             {
00506                 CLEANUP;
00507                 std::ostringstream os;
00508                 os << "CryptSetKeyParam failed: " << GetLastError();;
00509                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_SET_IV_FAILED, this);
00510             }
00511         }
00512     }
00513     else if(key.ContainsCertificate())
00514     {
00515         
00516         cert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
00517             key.GetCertificate(), key.GetCertificateLength());
00518         if(NULL == cert)
00519         {
00520             CLEANUP;
00521             std::ostringstream os;
00522             os << "CertCreateCertificateContext failed: " << GetLastError();;
00523             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_CREATE_CERT_FAILED, this);
00524         }
00525 
00526         DWORD provType = 0;
00527         
00528         if(0 == strcmp(szOID_RSA_RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00529             0 == strcmp(szOID_RSA_MD5RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00530             0 == strcmp(szOID_RSA_SHA1RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId)) 
00531             provType = PROV_RSA_FULL;
00532         else
00533         {
00534             CLEANUP;
00535             throw CPKIFCryptoException(m_parent->thisComponent, CRYPTO_ALG_NOT_SUPPORTED, "Unsupported encryption algorithm identified in certificate.");
00536         }
00537 
00538         
00539         succ = CryptAcquireContext(&hTmpProv, NULL, NULL, provType, CRYPT_VERIFYCONTEXT);
00540         if(!succ)
00541         {
00542             CLEANUP;
00543             std::ostringstream os;
00544             os << "CryptAcquireContext failed: " << GetLastError();;
00545             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, this);
00546         }
00547 
00548         
00549         succ = CryptImportPublicKeyInfo(hTmpProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cert->pCertInfo->SubjectPublicKeyInfo, &hSessionKey);
00550         if(!succ)
00551         {
00552             CLEANUP;
00553             std::ostringstream os;
00554             os << "CryptImportPublicKeyInfo failed: " << GetLastError();;
00555             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_KEY_IMPORT_FAILED, this);
00556         }
00557     }
00558     else
00559     {
00560         throw CPKIFCryptoException(m_parent->thisComponent, COMMON_INVALID_INPUT, "Key parameter contents not recognized.");
00561     }
00562 
00563     int maxOut = *pnResultLen;
00564     *pnResultLen = nDataLen;
00565     int err = 0;
00566     memcpy(pResult, pData, nDataLen);
00567     if(_CryptDirection)
00568     {
00569         BOOL last = TRUE;
00570         DWORD resLen = *pnResultLen;
00571         if(!CryptEncrypt(hSessionKey, NULL, last, 0, pResult, &resLen, maxOut))
00572         {
00573             CLEANUP;
00574             std::ostringstream os;
00575             os << "CryptEncrypt failed: " << GetLastError();;
00576             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_ENCRYPT_FAILED, this);
00577         }
00578 
00579         *pnResultLen = resLen;
00580 
00581         if(key.ContainsCertificate())
00582         {
00583             
00584             ReverseBytes(pResult, *pnResultLen);
00585         }
00586     }
00587     else
00588     {
00589         if(!CryptDecrypt(hSessionKey, NULL, TRUE, 0, pResult, (DWORD*)pnResultLen))
00590         {
00591             CLEANUP;
00592             std::ostringstream os;
00593             os << "CryptDecrypt failed: " << GetLastError();;
00594             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_DECRYPT_FAILED, this);
00595         }
00596     }
00597 
00598     CLEANUP;
00599 }
00607 void CPKIFCAPIRaw::Decrypt(
00609     const CPKIFKeyMaterial& key, 
00611     unsigned char* pData, 
00613     int nDataLen, 
00615     unsigned char* pResult,
00618     int* pnResultLen, 
00621     bool pad)
00622 {
00623     m_impl->Crypt<false>(key, pData, nDataLen, pResult, pnResultLen, pad);
00624 }
00632 void CPKIFCAPIRaw::Encrypt(
00634     const CPKIFKeyMaterial& key,
00636     unsigned char* pData,
00638     int nDataLen,
00640     unsigned char* pResult,
00643     int* pnResultLen,
00646     bool pad)
00647 {
00648     m_impl->Crypt<true>(key, pData, nDataLen, pResult, pnResultLen, pad);
00649 }
00660 HCRYPTHASH CreateHashObjectFromData(
00662     HCRYPTPROV hProv,
00665     unsigned char* pHashData,
00667     int nHashDataLen)
00668 {
00669 #undef CLEANUP
00670 #define CLEANUP \
00671 { \
00672     if (NULL != hHash)  \
00673     {   CryptDestroyHash(hHash); hHash = NULL; }  \
00674 } 
00675 
00676     LOG_STRING_DEBUG("CreateHashObjectFromData(HCRYPTPROV hProv, unsigned char* pHashData, int nHashDataLen)", TOOLKIT_CRYPTO_CAPIRAW, 0, NULL);
00677 
00678     HCRYPTHASH hHash = NULL;
00679 
00680     
00681     ALG_ID HashAlg = GetHashAlg((PKIFCRYPTO::HASH_ALG)nHashDataLen);
00682 
00683     
00684     if(!CryptCreateHash(hProv, HashAlg, NULL, 0, &hHash))
00685     {
00686         CLEANUP;
00687 
00688         std::ostringstream os;
00689         os << "CryptCreateHash failed: " << GetLastError();;
00690         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_CREATE_HASH_FAILED, NULL);
00691     }
00692 
00693     DWORD hSize = 0;
00694     DWORD hSizeSize = sizeof(hSize);
00695 
00696     
00697     if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hSize, &hSizeSize, 0))
00698     {
00699         CLEANUP;
00700         std::ostringstream os;
00701         os << "CryptGetHashParam failed: " << GetLastError();;
00702         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_MISC_HASH_CALL_FAILED, NULL);
00703     }
00704     if(nHashDataLen != hSize)
00705     {
00706         CLEANUP;
00707         RAISE_CRYPTO_EXCEPTION("Hash sizes do not match.  Could not set hash object for signing.", TOOLKIT_CRYPTO, PKIFCAPI_MISC_HASH_CALL_FAILED, NULL);
00708     }
00709 
00710     
00711     if(!CryptSetHashParam(hHash, HP_HASHVAL, pHashData, 0))
00712     {
00713         CLEANUP;
00714         std::ostringstream os;
00715         os << "CryptSetHashParam failed: " << GetLastError();;
00716         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_MISC_HASH_CALL_FAILED, NULL);
00717     }
00718 
00719     
00720     return hHash;
00721 }
00734 bool _Verify(
00736     const CPKIFKeyMaterial& key,
00739     unsigned char* pHashData,
00741     int nHashDataLen,
00743     unsigned char* pSignature,
00745     int nSignatureLen)
00746 {
00747 #undef CLEANUP
00748 #define CLEANUP \
00749 { \
00750     if (capiSpki.Algorithm.Parameters.cbData)  \
00751     {   delete[] capiSpki.Algorithm.Parameters.pbData; capiSpki.Algorithm.Parameters.pbData = NULL; capiSpki.Algorithm.Parameters.cbData = 0;}  \
00752     if (clearParams)  \
00753     {   delete[] cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData; cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData = NULL; cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData = 0;}  \
00754     if (NULL != cert)  \
00755     {   CertFreeCertificateContext(cert); cert = NULL; }  \
00756     if (NULL != hHash)  \
00757     {   CryptDestroyHash(hHash); hHash = NULL; }  \
00758     if (NULL != hKey)  \
00759     {   CryptDestroyKey(hKey); hKey = NULL; }  \
00760     if (NULL != hProv)  \
00761     {   CryptReleaseContext(hProv, 0); hProv = NULL; }  \
00762 } 
00763 
00764     LOG_STRING_DEBUG("_Verify(const CPKIFKeyMaterial& key, unsigned char* pHashData, int nHashDataLen, unsigned char* pSignature, int nSignatureLen)", TOOLKIT_CRYPTO_CAPIRAW, 0, NULL);
00765 
00766     BOOL succ = FALSE;
00767     HCRYPTPROV hProv = NULL;
00768     HCRYPTKEY hKey = NULL;
00769     HCRYPTHASH hHash = NULL;
00770     PCCERT_CONTEXT cert = NULL;
00771     DWORD provType = 0;
00772     bool clearParams = false;
00773 
00774     ALG_ID alg;
00775     CERT_PUBLIC_KEY_INFO capiSpki;
00776     memset(&capiSpki, 0, sizeof(CERT_PUBLIC_KEY_INFO));
00777 
00778     
00779     if(key.ContainsCertificate())
00780     {
00781         
00782         cert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
00783             key.GetCertificate(), key.GetCertificateLength());
00784         if(NULL == cert)
00785         {
00786             CLEANUP;
00787             std::ostringstream os;
00788             os << "CertCreateCertificateContext failed: " << GetLastError();;
00789             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_CREATE_CERT_FAILED, NULL);
00790         }
00791 
00792 
00793         if(0 == strcmp(szOID_RSA_RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00794             0 == strcmp(szOID_RSA_MD5RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
00795             0 == strcmp(szOID_RSA_SHA1RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId)) 
00796             alg = CALG_RSA_SIGN;
00797         else
00798             alg = CALG_DSS_SIGN;
00799         provType = GetProvType(cert);
00800 
00801         
00802         succ = CryptAcquireContext(&hProv, NULL, NULL, provType, CRYPT_VERIFYCONTEXT);
00803         if(!succ)
00804         {
00805             CLEANUP;
00806             std::ostringstream os;
00807             os << "CryptAcquireContext failed: " << GetLastError();;
00808             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, NULL);
00809         }
00810 
00811         if(CALG_DSS_SIGN == alg)
00812         {
00813             CPKIFAlgorithmIdentifierPtr workingParams = key.GetWorkingParameters();
00814             if(0 == cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData &&
00815                 workingParams != (CPKIFAlgorithmIdentifier*)NULL)
00816             {
00817                 CPKIFBufferPtr params = workingParams->parameters();
00818                 cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData = params->GetLength();
00819                 cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData = new unsigned char[params->GetLength()];
00820                 memcpy(cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData, (BYTE*)params->GetBuffer(), params->GetLength());
00821                 
00822                 clearParams = true;
00823             }
00824         }
00825 
00826         
00827         succ = CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cert->pCertInfo->SubjectPublicKeyInfo, &hKey);
00828         if(!succ)
00829         {
00830             CLEANUP;
00831             std::ostringstream os;
00832             os << "CryptImportPublicKeyInfo failed: " << GetLastError();;
00833             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_KEY_IMPORT_FAILED, NULL);
00834         }
00835     }
00836     else if(key.ContainsPublicKeyMaterial())
00837     {
00838         CPKIFSubjectPublicKeyInfoPtr spki = key.GetSubjectPublicKeyInfo();
00839         CPKIFAlgorithmIdentifierPtr spkiAlg = spki->alg();
00840         CPKIFOIDPtr spkiAlgOid = spkiAlg->oid();
00841         const char* spkifAlgOidString = spkiAlgOid->ToString();
00842 
00843         capiSpki.Algorithm.Parameters.cbData = 0;
00844 
00845         if(0 == strcmp(szOID_RSA_RSA, spkifAlgOidString))
00846         {
00847             capiSpki.Algorithm.pszObjId = szOID_RSA_RSA;
00848             alg = CALG_RSA_SIGN;
00849         }
00850         else if(0 == strcmp(szOID_RSA_MD5RSA, spkifAlgOidString))
00851         {
00852             capiSpki.Algorithm.pszObjId = szOID_RSA_MD5RSA;
00853             alg = CALG_RSA_SIGN;
00854         }
00855         else if(0 == strcmp(szOID_RSA_SHA1RSA, spkifAlgOidString)) 
00856         {
00857             capiSpki.Algorithm.pszObjId = szOID_RSA_SHA1RSA;
00858             alg = CALG_RSA_SIGN;
00859         }
00860         else
00861         {
00862             capiSpki.Algorithm.pszObjId = szOID_X957_DSA;
00863             alg = CALG_DSS_SIGN;
00864         }
00865 
00866         provType = GetProvType(spkifAlgOidString);
00867 
00868         CPKIFBufferPtr keyBuf = spki->rawKey();
00869         capiSpki.PublicKey.cbData = keyBuf->GetLength();
00870         capiSpki.PublicKey.pbData = (BYTE*)keyBuf->GetBuffer();
00871 
00872         
00873         succ = CryptAcquireContext(&hProv, NULL, NULL, provType, CRYPT_VERIFYCONTEXT);
00874         if(!succ)
00875         {
00876             CLEANUP;
00877             std::ostringstream os;
00878             os << "CryptAcquireContext failed: " << GetLastError();;
00879             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, NULL);
00880         }
00881 
00882         if(CALG_DSS_SIGN == alg)
00883         {
00884             CPKIFAlgorithmIdentifierPtr workingParams = key.GetWorkingParameters();
00885             if(0 == capiSpki.Algorithm.Parameters.cbData &&
00886                 workingParams != (CPKIFAlgorithmIdentifier*)NULL)
00887             {
00888                 CPKIFBufferPtr params = workingParams->parameters();
00889                 capiSpki.Algorithm.Parameters.cbData = params->GetLength();
00890                 capiSpki.Algorithm.Parameters.pbData = new unsigned char[params->GetLength()];
00891                 memcpy(capiSpki.Algorithm.Parameters.pbData, (BYTE*)params->GetBuffer(), params->GetLength());
00892                 
00893                 clearParams = false;
00894             }
00895         }
00896 
00897         
00898         succ = CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &capiSpki, &hKey);
00899         if(!succ)
00900         {
00901             CLEANUP;
00902             std::ostringstream os;
00903             os << "CryptImportPublicKeyInfo failed: " << GetLastError();;
00904             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPI_KEY_IMPORT_FAILED, NULL);
00905         }
00906     }
00907     else
00908     {
00909         CLEANUP;
00910         RAISE_CRYPTO_EXCEPTION("CPKIFCAPIRaw::Verify only supports certificate-based key material", TOOLKIT_CRYPTO, PKIFCAPI_KEY_MATERIAL_NOT_SUPPORTED, NULL);
00911     }
00912 
00913     
00914     
00915     try
00916     {
00917         hHash = CreateHashObjectFromData(hProv, pHashData, nHashDataLen);
00918     }
00919     catch(CPKIFException& e)
00920     {
00921         CLEANUP;
00922         throw e;
00923     }
00924 
00925     unsigned char revSig[513];
00926     if(CALG_RSA_SIGN == alg)
00927     {
00928         for(int ii = nSignatureLen-1, jj = 0; ii >= 0; --ii, ++jj)
00929             revSig[ii] = pSignature[jj];
00930     }
00931     else
00932     {
00933         unsigned char pRevSig[(MAXHASH*2)+5];
00934         const int maxRorS = nHashDataLen;
00935         bool skipRevStuff = false;
00936         int rlen = maxRorS, slen = maxRorS;
00937         try
00938         {
00939             
00940             CACASNWRAPPER_CREATE(Dss_Sig_Value, tmpPDU);
00941             ASN1OpenType asnOpenType;
00942             asnOpenType.data = pSignature;
00943             asnOpenType.numocts = nSignatureLen;
00944             Dss_Sig_Value* tmpAttr = tmpPDU.Decode(asnOpenType);
00945     
00946             atob((char*)pRevSig, (char*)tmpAttr->r + 2, (unsigned int*)&rlen);
00947             ReverseBytes(pRevSig, rlen);
00948             unsigned char* p = pRevSig + rlen; 
00949             if(rlen >= nHashDataLen)
00950             {
00951                 int diff = rlen - nHashDataLen;
00952                 while(diff > 0)
00953                 {
00954                     --p; --diff;
00955                 }
00956             }
00957             else
00958             {
00959                 int diff = nHashDataLen - rlen;
00960                 while(diff > 0)
00961                 {
00962                     *p = 0x00; ++p;
00963                     --diff;
00964                 }
00965             }
00966 
00967             
00968             atob((char*)p, (char*)tmpAttr->s + 2, (unsigned int*)&slen);
00969             ReverseBytes(p, slen);
00970             p = p + slen; 
00971             if(slen >= nHashDataLen)
00972             {
00973                 int diff = slen - nHashDataLen;
00974                 while(diff > 0)
00975                 {
00976                     --p; --diff;
00977                 }
00978             }
00979             else
00980             {
00981                 int diff = nHashDataLen - slen;
00982                 while(diff > 0)
00983                 {
00984                     *p = 0x00; ++p;
00985                     --diff;
00986                 }
00987             }
00988             nSignatureLen = nHashDataLen*2;
00989             memcpy(revSig, pRevSig, nSignatureLen);
00990             skipRevStuff = true;
00991         }
00992         catch(CPKIFException& e)
00993         {
00994             
00995             if(nSignatureLen > MAXHASH)
00996                 throw e;
00997 
00998             
00999             
01000             
01001             
01002 
01003             memcpy(revSig, pSignature, nSignatureLen);
01004             ReverseBytes(revSig, nSignatureLen/2);
01005             ReverseBytes(revSig + nSignatureLen/2, nSignatureLen/2);
01006             skipRevStuff = true;
01007         }
01008         
01009 
01010 
01011 
01012 
01013 
01014 
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028 
01029 
01030 
01031 
01032 
01033 
01034 
01035 
01036 
01037 
01038 
01039 
01040 
01041 
01042 
01043 
01044 
01045 
01046 
01047 
01048 
01049 
01050 
01051 
01052 
01053 
01054 
01055 
01056 
01057 
01058     }
01059 
01060     
01061     succ = CryptVerifySignature(hHash, revSig, nSignatureLen, hKey, NULL, 0);
01062     if(!succ)
01063     {
01064         CLEANUP;
01065         int errcode = GetLastError();
01066 
01067         return false;
01068     }
01069 
01070     CLEANUP;
01071     return true;
01072 }
01081 bool CPKIFCAPIRaw::VerifyCertificate(
01084     const CPKIFCertificate& issCert,
01087     const CPKIFCertificate& subCert)
01088 {
01089     LOG_STRING_DEBUG("CPKIFCAPIRaw::VerifyCertificate(const CPKIFCertificate& issCert, const CPKIFCertificate& subCert)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01090 
01091     CPKIFBufferPtr issBuf = issCert.Encoded();
01092     CPKIFBufferPtr subBuf = subCert.Encoded();
01093 
01094     PCCERT_CONTEXT issCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
01095         issBuf->GetBuffer(), issBuf->GetLength());
01096 
01097 
01098 
01099     if(!issCtx)
01100     {
01101         return false;
01102     }
01103 
01104     int err = 0;
01105     BOOL b = CryptVerifyCertificateSignature(NULL,X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
01106         subBuf->GetBuffer(), subBuf->GetLength(), &issCtx->pCertInfo->SubjectPublicKeyInfo);
01107     if(!b)
01108     {
01109         err = GetLastError();
01110     }
01111 
01112     CertFreeCertificateContext(issCtx);
01113 
01114 
01115     return TRUE == b;
01116 }
01117 
01118 
01128 bool CPKIFCAPIRaw::Verify(
01130     const CPKIFKeyMaterial& key,
01132     unsigned char* pHashData, 
01134     int nHashDataLen,
01136     unsigned char* pSignature,
01138     int nSignatureLen,
01140     PKIFCRYPTO::HASH_ALG hashAlg
01141     )
01142 {
01143     
01144     return _Verify(key, pHashData, nHashDataLen, pSignature, nSignatureLen);
01145 }
01158 void CPKIFCAPIRaw::GenRandom(
01160     unsigned char* buf, 
01162     int len)
01163 {
01164     
01165     
01166     
01167 
01168     LOG_STRING_DEBUG("CPKIFCAPIRaw::GenRandom(unsigned char* buf, int len)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01169 
01170     if(NULL == buf || 0 == len)
01171         return; 
01172 
01173     HCRYPTPROV hProv = NULL;
01174 
01175     
01176     if(NULL != m_impl->m_hProv)
01177         hProv = m_impl->m_hProv;
01178     else
01179     {
01180         if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
01181         {
01182             std::ostringstream os;
01183             os << "CryptAcquireContext failed: " << GetLastError();;
01184             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, NULL);
01185         }
01186     }
01187 
01188     
01189     if(!CryptGenRandom(hProv, len, buf))
01190     {
01191         std::ostringstream os;
01192         os << "CryptGenRandom failed: " << GetLastError();;
01193         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_GEN_RANDOM_FAILED, NULL);
01194     }
01195 
01196     
01197     if(NULL == m_impl->m_hProv)
01198         CryptReleaseContext(hProv, 0);
01199 }
01214 IPKIFHashContext* CPKIFCAPIRaw::HashInit(
01217     PKIFCRYPTO::HASH_ALG alg)
01218 {
01219     LOG_STRING_DEBUG("CPKIFCAPIRaw::HashInit(HASH_ALG alg)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01220 
01221     
01222     ALG_ID hashAlg;
01223     switch(alg)
01224     {
01225     case PKIFCRYPTO::SHA1:
01226         hashAlg = CALG_SHA1;
01227         break;
01228 #ifndef FIPS_MODE
01229     case PKIFCRYPTO::MD5:
01230         hashAlg = CALG_MD5;
01231         break;
01232 #endif
01233         
01234     case PKIFCRYPTO::SHA256:
01235         hashAlg = CALG_SHA_256;
01236         break;
01237     case PKIFCRYPTO::SHA384:
01238         hashAlg = CALG_SHA_384;
01239         break;
01240     case PKIFCRYPTO::SHA512:
01241         hashAlg = CALG_SHA_512;
01242         break;
01243     default:
01244         std::ostringstream os;
01245         os << "Unsupported hash algorithm encountered: " << alg;
01246         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, CRYPTO_ALG_NOT_SUPPORTED, NULL);
01247     }
01248 
01249     
01250     
01251     CPKIFCAPIHashContext* hashCtx = new CPKIFCAPIHashContext();
01252     if(!CryptAcquireContext(&hashCtx->m_hashContext, NULL, m_impl->m_provName, 
01253         m_impl->m_provType ? m_impl->m_provType : PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
01254     {
01255         delete hashCtx;
01256 
01257         std::ostringstream os;
01258         os << "CryptAcquireContext failed: " << GetLastError();;
01259         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, NULL);
01260     }
01261 
01262     if(!CryptCreateHash(hashCtx->m_hashContext, hashAlg, NULL, 0, &hashCtx->m_hash))
01263     {
01264         delete hashCtx;
01265 
01266         std::ostringstream os;
01267         os << "CryptCreateHash failed: " << GetLastError();;
01268         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_CREATE_HASH_FAILED, NULL);
01269     }
01270 
01271     return hashCtx;
01272 }
01287 void CPKIFCAPIRaw::HashUpdate(
01289     IPKIFHashContext* hash, 
01291     unsigned char* pData, 
01293     int nDataLen)
01294 {
01295     LOG_STRING_DEBUG("CPKIFCAPIRaw::HashUpdate(IPKIFHashContext* hash, unsigned char* pData, int nDataLen)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01296 
01297     
01298     
01299     
01300     
01301     if(NULL == hash || 0 > nDataLen)
01302         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HashUpdate.");
01303 
01304     
01305     
01306     CPKIFCAPIHashContext* hashCtx = dynamic_cast<CPKIFCAPIHashContext*>(hash);
01307     if(NULL == hashCtx)
01308         throw CPKIFCryptoException(thisComponent, PKIFCAPI_INCORRECT_HASH_CONTEXT, "Incorrect hash context passed to HashUpdate.");
01309 
01310     if(NULL == hashCtx->m_hashContext || NULL == hashCtx->m_hash)
01311         throw CPKIFCryptoException(thisComponent, PKIFCAPI_EMPTY_HASH_CONTEXT, "Empty hash context passed to HashUpdate.");
01312 
01313     if(!CryptHashData(hashCtx->m_hash, pData, nDataLen, 0))
01314     {
01315         std::ostringstream os;
01316         os << "CryptHashData failed: " << GetLastError();;
01317         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_MISC_HASH_CALL_FAILED, NULL);
01318     }
01319 }
01335 void CPKIFCAPIRaw::HashFinal(
01337     IPKIFHashContext* hash,
01339     unsigned char* pResult, 
01342     int* pnResultLen)
01343 {
01344     LOG_STRING_DEBUG("CPKIFCAPIRaw::HashFinal(IPKIFHashContext* hash, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01345 
01346     
01347     
01348     
01349     
01350     if(NULL == hash || NULL == pResult || NULL == pnResultLen || 0 >= *pnResultLen)
01351         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HashFinal.");
01352 
01353     CPKIFCAPIHashContext* hashCtx = dynamic_cast<CPKIFCAPIHashContext*>(hash);
01354     if(NULL == hashCtx)
01355         throw CPKIFCryptoException(thisComponent, PKIFCAPI_INCORRECT_HASH_CONTEXT, "Incorrect hash context passed to HashFinal.");
01356 
01357     if(NULL == hashCtx->m_hashContext || NULL == hashCtx->m_hash)
01358         throw CPKIFCryptoException(thisComponent, PKIFCAPI_EMPTY_HASH_CONTEXT, "Empty hash context passed to HashUpdate.");
01359 
01360     
01361     if(!CryptGetHashParam(hashCtx->m_hash, HP_HASHVAL, pResult, (DWORD*)pnResultLen, 0)) 
01362     {
01363         std::ostringstream os;
01364         os << "CryptGetHashParam failed: " << GetLastError();;
01365         RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_MISC_HASH_CALL_FAILED, NULL);
01366     }
01367 }
01390 IPKIFRawCryptContext* CPKIFCAPIRaw::CryptInit(
01393     const CPKIFKeyMaterial& key,
01395     bool pad)
01396 {
01397     LOG_STRING_DEBUG("CPKIFCAPIRaw::CryptInit(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01398 
01399     
01400     CPKIFCAPIRawCryptContext* cryptContext = new CPKIFCAPIRawCryptContext;
01401 
01402     BOOL succ = FALSE;
01403     PCCERT_CONTEXT cert = NULL;
01404 
01405     if(key.ContainsSymmetricKeyMaterial())
01406     {
01407         if(NULL == m_impl->m_hProv)
01408         {
01409             
01410             succ = CreatePrivateExponentOneKey(MS_ENHANCED_PROV, PROV_RSA_FULL,
01411                                                 "__PKIFTEMPCONTAINER", AT_KEYEXCHANGE, &m_impl->m_hProv, &m_impl->m_hPubPrivKey);
01412             if (!succ)
01413             {
01414                 if(NULL != m_impl->m_hPubPrivKey)
01415                 {
01416                     CryptDestroyKey(m_impl->m_hPubPrivKey); m_impl->m_hPubPrivKey = NULL;
01417                 }
01418                 if(NULL != m_impl->m_hProv)
01419                 {
01420                     CryptReleaseContext(m_impl->m_hProv, 0); m_impl->m_hProv = NULL;
01421                 }
01422                 std::ostringstream os;
01423                 os << "CreatePrivateExponentOneKey failed: " << GetLastError();;
01424                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SESSION_KEY_ENCRYPT_FAILED, NULL);
01425             }
01426         }
01427 
01428         ALG_ID tmpAlgID = GetSymAlgorithm(key);
01429         if (!ImportPlainSessionBlob(m_impl->m_hProv, m_impl->m_hPubPrivKey, tmpAlgID, (unsigned char*)key.GetSymmetricKey(), key.GetSymmetricKeyLength(), &cryptContext->m_sessionKey))
01430         {
01431             delete cryptContext;
01432             std::ostringstream os;
01433             os << "ImportPlainSessionBlob failed: " << GetLastError();;
01434             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_KEY_IMPORT_FAILED, NULL);
01435         }
01436 
01437         DWORD tmpMode = 0;
01438         switch(key.GetMode())
01439         {
01440         case PKIFCRYPTO::ECB:
01441             tmpMode = CRYPT_MODE_ECB;
01442             break;
01443         case PKIFCRYPTO::CBC:
01444             tmpMode = CRYPT_MODE_CBC;
01445             if(NULL == key.GetIV())
01446                 throw CPKIFCryptoException(thisComponent, CRYPTO_MISSING_IV);
01447             break;
01448         default:
01449             throw CPKIFCryptoException(thisComponent, CRYPTO_MODE_NOT_SUPPORTED);
01450         }
01451 
01452         if(!CryptSetKeyParam(cryptContext->m_sessionKey, KP_MODE, (BYTE*)&tmpMode, 0))
01453         {
01454             delete cryptContext;
01455             std::ostringstream os;
01456             os << "CryptSetKeyParam failed: " << GetLastError();;
01457             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SET_MODE_FAILED, NULL);
01458         }
01459 
01460         if(NULL != key.GetIV() && PKIFCRYPTO::CBC == key.GetMode())
01461         {
01462             if(!CryptSetKeyParam(cryptContext->m_sessionKey, KP_IV, (BYTE*)key.GetIV(), 0))
01463             {
01464                 delete cryptContext;
01465                 std::ostringstream os;
01466                 os << "CryptSetKeyParam failed: " << GetLastError();;
01467                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SET_IV_FAILED, NULL);
01468             }
01469         }
01470 
01471         CPKIFAlgorithm* a = CPKIFAlgorithm::GetAlg(key.GetSymmetricKeyAlgorithm(), key.GetMode());
01472         cryptContext->m_blockLen = a->BlockSize();
01473         cryptContext->m_padbuf = new unsigned char[cryptContext->m_blockLen];
01474         memset(cryptContext->m_padbuf,0x00,cryptContext->m_blockLen);
01475 
01476         cryptContext->m_bNeedsPad = pad;
01477     }
01478     else if(key.ContainsCertificate())
01479     {
01480         
01481         cert = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
01482             key.GetCertificate(), key.GetCertificateLength());
01483         if(NULL == cert)
01484         {
01485             delete cryptContext;
01486             std::ostringstream os;
01487             os << "CertCreateCertificateContext failed: " << GetLastError();;
01488             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_CREATE_CERT_FAILED, NULL);
01489         }
01490 
01491         DWORD provType = 0;
01492         
01493         if(0 == strcmp(szOID_RSA_RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
01494             0 == strcmp(szOID_RSA_MD5RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) ||
01495             0 == strcmp(szOID_RSA_SHA1RSA, cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId)) 
01496             provType = PROV_RSA_FULL;
01497         else
01498         {
01499             delete cryptContext;
01500             CertFreeCertificateContext(cert);
01501             RAISE_CRYPTO_EXCEPTION("Unsupported encryption algorithm identified in certificate.", thisComponent, CRYPTO_ALG_NOT_SUPPORTED, NULL);
01502         }
01503 
01504         
01505         succ = CryptAcquireContext(&cryptContext->m_cryptContext, NULL, NULL, provType, CRYPT_VERIFYCONTEXT);
01506         if(!succ)
01507         {
01508             delete cryptContext;
01509             CertFreeCertificateContext(cert);
01510             std::ostringstream os;
01511             os << "CryptAcquireContext failed: " << GetLastError();;
01512             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, NULL);
01513         }
01514 
01515         
01516         succ = CryptImportPublicKeyInfo(cryptContext->m_cryptContext, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cert->pCertInfo->SubjectPublicKeyInfo, &cryptContext->m_sessionKey);
01517         if(!succ)
01518         {
01519             delete cryptContext;
01520             CertFreeCertificateContext(cert);
01521             std::ostringstream os;
01522             os << "CryptImportPublicKeyInfo failed: " << GetLastError();;
01523             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_KEY_IMPORT_FAILED, NULL);
01524         }
01525 
01526         cryptContext->m_bFromCert = true;
01527         CertFreeCertificateContext(cert);
01528     }
01529     else
01530     {
01531         delete cryptContext;
01532         throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "Key parameter contents not recognized.");
01533     }
01534 
01535     return cryptContext;
01536 }
01547 void CPKIFCAPIRaw::Decrypt(
01550     IPKIFRawCryptContext* cryptContext, 
01552     unsigned char* pData, 
01554     int nDataLen, 
01556     unsigned char* pResult, 
01559     int* pnResultLen, 
01562     bool final)
01563 {
01564     m_impl->CryptFunc<false>(cryptContext, pData, nDataLen, pResult, pnResultLen, final);
01565 }
01576 void CPKIFCAPIRaw::Encrypt(
01579     IPKIFRawCryptContext* cryptContext, 
01581     unsigned char* pData, 
01583     int nDataLen, 
01585     unsigned char* pResult, 
01588     int* pnResultLen, 
01591     bool final)
01592 {
01593     m_impl->CryptFunc<true>(cryptContext, pData, nDataLen, pResult, pnResultLen, final);
01594 }
01595 
01606 template <bool _CryptDirection>
01607 void CPKIFCAPIRawImpl::CryptFunc(
01610     IPKIFRawCryptContext* cryptContext,
01612     unsigned char* pData,
01614     int nDataLen,
01616     unsigned char* pResult,
01618     int* pnResultLen,
01621     bool final)
01622 {
01623     LOG_STRING_DEBUG("CPKIFCAPIRaw::CryptFunc(IPKIFRawCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)", TOOLKIT_CRYPTO_CAPIRAW, 0, this);
01624 
01625     CPKIFCAPIRawCryptContext* icc = dynamic_cast<CPKIFCAPIRawCryptContext*>(cryptContext);
01626     
01627     
01628     if(icc->m_bFromCert || !icc->m_bNeedsPad)
01629     {
01630         int maxOut = *pnResultLen;
01631         *pnResultLen = nDataLen;
01632         int err = 0;
01633         memcpy(pResult, pData, nDataLen);
01634         if(_CryptDirection)
01635         {
01636             DWORD resLen = *pnResultLen;
01637             if(!CryptEncrypt(icc->m_sessionKey, NULL, final, 0, pResult, &resLen, maxOut))
01638             {
01639                 std::ostringstream os;
01640                 os << "CryptEncrypt failed: " << GetLastError();;
01641                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_ENCRYPT_FAILED, NULL);
01642             }
01643 
01644             *pnResultLen = resLen;
01645 
01646             if(icc->m_bFromCert)
01647             {
01648                 
01649                 ReverseBytes(pResult, *pnResultLen);
01650             }
01651         }
01652         else
01653         {
01654             if(!CryptDecrypt(icc->m_sessionKey, NULL, final, 0, pResult, (DWORD*)pnResultLen))
01655             {
01656                 std::ostringstream os;
01657                 os << "CryptDecrypt failed: " << GetLastError();;
01658                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_DECRYPT_FAILED, NULL);
01659             }
01660         }
01661         return;
01662     }
01663     
01664     
01665     int maxOut = *pnResultLen;
01666     int inLen = nDataLen;
01667     unsigned char * start = pData;
01668     unsigned char * outBuf = pResult;
01669 
01670     DWORD updateLen = 0;
01671     DWORD padUpdateLen = 0;
01672     *pnResultLen = 0;
01673     unsigned int finalLen = 0;
01674 
01675     *pnResultLen = 0;
01676     int err = 0;
01677     if(_CryptDirection)
01678     {
01679         DWORD resLen = *pnResultLen;
01680         if(final)
01681         {
01682             
01683             if(icc->m_padlen) {
01684                 memcpy(outBuf,icc->m_padbuf,icc->m_padlen);
01685             }
01686             if(start && inLen) memcpy(outBuf + icc->m_padlen,start,inLen);
01687             updateLen = inLen + icc->m_padlen;
01688             icc->m_padlen = 0;
01689             if(!CryptEncrypt(icc->m_sessionKey, NULL, final, 0, outBuf, &updateLen, maxOut))
01690             {
01691                 std::ostringstream os;
01692                 os << "CryptEncrypt failed: " << GetLastError();;
01693                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_ENCRYPT_FAILED, NULL);
01694             }
01695             *pnResultLen = updateLen;
01696             return;
01697         }
01698 
01699         
01700         if(!start || !inLen) return;
01701         int leftInBlock = icc->m_blockLen - icc->m_padlen;
01702 
01703 
01704         
01705         if(leftInBlock >= inLen) {
01706             memcpy(icc->m_padbuf,start,inLen);
01707             icc->m_padlen += inLen;
01708             *pnResultLen = 0;
01709             return;
01710         }
01711 
01712         
01713         
01714         memcpy(outBuf,icc->m_padbuf,icc->m_padlen);
01715         updateLen = icc->m_padlen;
01716         icc->m_padlen = 0;
01717         
01718         
01719         int trailing = (inLen + updateLen) % icc->m_blockLen ? 
01720             (inLen + updateLen) % icc->m_blockLen : icc->m_blockLen;
01721 
01722         
01723         int copied = inLen - trailing;
01724         memcpy(outBuf+updateLen,start,copied);
01725         start += copied;
01726         updateLen += copied;
01727 
01728         
01729         if(!CryptEncrypt(icc->m_sessionKey, NULL, final, 0, outBuf, &updateLen, maxOut))
01730         {
01731             std::ostringstream os;
01732             os << "CryptEncrypt failed: " << GetLastError();;
01733             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_ENCRYPT_FAILED, NULL);
01734         }
01735 
01736         
01737         memcpy(icc->m_padbuf,start,trailing);
01738         icc->m_padlen += trailing;
01739         *pnResultLen = updateLen;
01740     }
01741     else
01742     {
01743         if(final) {
01744             
01745             if(maxOut < icc->m_padlen) {
01746                 RAISE_CRYPTO_EXCEPTION("Decrypt() called with insufficient buffer available", m_parent->thisComponent, COMMON_INVALID_INPUT, NULL);
01747             }
01748             if(icc->m_padlen) {
01749                 memcpy(outBuf,icc->m_padbuf,icc->m_padlen);
01750             }
01751             if(start && inLen) memcpy(outBuf + icc->m_padlen,start,inLen);
01752             updateLen = inLen + icc->m_padlen;
01753             icc->m_padlen = 0;
01754             if(!CryptDecrypt(icc->m_sessionKey, NULL, final, 0, outBuf, &updateLen))
01755             {
01756                 std::ostringstream os;
01757                 os << "CryptDecrypt failed: " << GetLastError();;
01758                 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_DECRYPT_FAILED, NULL);
01759             }
01760             *pnResultLen = updateLen;
01761             return;
01762         }
01763 
01764         
01765         if(!start || !inLen) return;
01766         int leftInBlock = icc->m_blockLen - icc->m_padlen;
01767         
01768         if(leftInBlock >= inLen) {
01769             memcpy(icc->m_padbuf,start,inLen);
01770             icc->m_padlen += inLen;
01771             *pnResultLen = 0;
01772             return;
01773         }
01774 
01775         
01776         
01777         memcpy(outBuf,icc->m_padbuf,icc->m_padlen);
01778         updateLen = icc->m_padlen;
01779         icc->m_padlen = 0;
01780         
01781         
01782         int trailing = (inLen + updateLen) % icc->m_blockLen ? 
01783             (inLen + updateLen) % icc->m_blockLen : icc->m_blockLen;
01784 
01785         
01786         int copied = inLen - trailing;
01787         memcpy(outBuf+updateLen,start,copied);
01788         start += copied;
01789         updateLen += copied;
01790 
01791         
01792         if(!CryptDecrypt(icc->m_sessionKey, NULL, final, 0, outBuf, &updateLen))
01793         {
01794             std::ostringstream os;
01795             os << "CryptDecrypt failed: " << GetLastError();;
01796             RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_DECRYPT_FAILED, NULL);
01797         }
01798 
01799         
01800         memcpy(icc->m_padbuf,start,trailing);
01801         icc->m_padlen += trailing;
01802         *pnResultLen = updateLen;
01803     }
01804 }
01805 
01806 
01819 IPKIFRawCryptContext* CPKIFCAPIRaw::HMACInit(const CPKIFKeyMaterial &key, PKIFCRYPTO::HASH_ALG ha)
01820 {
01821     LOG_STRING_DEBUG("CPKIFCAPIRaw::HMACInit(const CPKIFKeyMaterial& key, HASH_ALG ha)", thisComponent, 0, this);
01822     RAISE_CRYPTO_EXCEPTION("HMAC operations are not implemented for CAPI.", thisComponent, COMMON_NOT_IMPLEMENTED, this);   
01823     return 0;
01824 }
01825 
01837 void CPKIFCAPIRaw::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)
01838 {
01839     LOG_STRING_DEBUG("CPKIFCAPIRaw::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)", thisComponent, 0, this);
01840     RAISE_CRYPTO_EXCEPTION("HMAC operations are not implemented for CAPI.", thisComponent, COMMON_NOT_IMPLEMENTED, this);   
01841 }
01842 
01854 void CPKIFCAPIRaw::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)
01855 {
01856     LOG_STRING_DEBUG("CPKIFCAPIRaw::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)", thisComponent, 0, this);
01857     RAISE_CRYPTO_EXCEPTION("HMAC operations are not implemented for CAPI.", thisComponent, COMMON_NOT_IMPLEMENTED, this);   
01858 }