00001
00009 #include "PKIFCAPI2.h"
00010 #include "ToolkitUtils.h"
00011 #include "CAPIUtils.h"
00012 #include "PKIFCAPICredential2.h"
00013 #include "PKIFCAPICryptContext2.h"
00014
00015 #include "PKIFCryptoErrors.h"
00016 #include "PKIFCAPIErrors.h"
00017 #include "PKIFCryptoException.h"
00018
00019 #include "SubjectPublicKeyInfo.h"
00020 #include "Certificate.h"
00021 #include "KeyUsage.h"
00022
00023 #include "boost/numeric/conversion/cast.hpp"
00024
00025 using boost::numeric_cast;
00026 using boost::bad_numeric_cast;
00027
00028 #include <atlbase.h>
00029 #include <sstream>
00030 using namespace std;
00031
00032 BYTESREVERSED g_bytesReversed = UNSET;
00033
00034
00035
00036
00038 struct CPKIFCAPI2Impl
00039 {
00040 CPKIFCAPI2* m_parent;
00048 CPKIFCAPI2Impl ()
00049 {
00050 m_parent = NULL;
00051 }
00059 CPKIFCAPI2Impl (CPKIFCAPI2 *p)
00060 {
00061 m_parent = p;
00062 }
00063 HCRYPTPROV m_hProv;
00064 HCERTSTORE m_hCertStore;
00065 DWORD m_flags;
00066
00067 char* m_provider;
00068 int m_sysStoRegLoc;
00069 int m_provType;
00070
00071
00072
00073 void GetContext();
00074 bool CertMatchesCurContext(PCCERT_CONTEXT cert) const;
00075 BYTESREVERSED CheckReversed(HCRYPTKEY * key);
00076 CPKIFCAPICredential2* MakeCAPICredential(PCCERT_CONTEXT cert) const;
00077 };
00079
00088 CPKIFCAPI2::CPKIFCAPI2(
00090 const char* provider,
00092 int provType,
00094 int sysStoRegLoc)
00095 :m_impl (new CPKIFCAPI2Impl), IPKIFCAPISource(sysStoRegLoc, NULL)
00096 {
00097 LOG_STRING_DEBUG("CPKIFCAPI::CPKIFCAPI(void)", TOOLKIT_CRYPTO_CAPI, 0, this);
00098
00099 m_impl->m_parent = this;
00100 m_impl->m_provType = provType;
00101 m_impl->m_sysStoRegLoc = sysStoRegLoc;
00102 m_impl->m_provider = NULL;
00103
00104 size_t len = 0;
00105 if(provider)
00106 {
00107 len = strlen(provider);
00108 m_impl->m_provider = new char[len + 1];
00109
00110
00111 strcpy(m_impl->m_provider, provider);
00112 }
00113
00114 m_impl->m_hProv = NULL;
00115 m_impl->m_hCertStore = NULL;
00116
00117
00118 m_impl->m_flags = 0;
00119 if(CERT_SYSTEM_STORE_LOCAL_MACHINE == m_impl->m_sysStoRegLoc)
00120 m_impl->m_flags = CRYPT_MACHINE_KEYSET;
00121 }
00129 CPKIFCAPI2::~CPKIFCAPI2(void)
00130 {
00131 LOG_STRING_DEBUG("CPKIFCAPI::~CPKIFCAPI(void)", TOOLKIT_CRYPTO_CAPI, 0, this);
00132
00133 if(m_impl->m_provider)
00134 delete[] m_impl->m_provider;
00135
00136 if(NULL != m_impl->m_hProv)
00137 {
00138 CryptReleaseContext(m_impl->m_hProv, 0); m_impl->m_hProv = NULL;
00139 }
00140
00141 if(NULL != m_impl->m_hCertStore)
00142 {
00143
00144 BOOL certSucc = CertCloseStore(m_impl->m_hCertStore,CERT_CLOSE_STORE_CHECK_FLAG);
00145 int ceerr = GetLastError();
00146 m_impl->m_hCertStore = NULL;
00147 #if 0 // this was the #else
00148 CertCloseStore(m_hCertStore, 0);
00149 m_hCertStore = NULL;
00150 #endif
00151 }
00152
00153 delete m_impl;
00154 m_impl = NULL;
00155 }
00163 void CPKIFCAPI2::Initialize()
00164 {
00165 LOG_STRING_DEBUG("CPKIFCAPI2::Initialize()", TOOLKIT_CRYPTO_CAPI, 0, this);
00166
00167 m_impl->GetContext();
00168 }
00169
00183 void CPKIFCAPI2Impl::GetContext()
00184 {
00185 LOG_STRING_DEBUG("CPKIFCAPI2::GetContext()", TOOLKIT_CRYPTO_CAPI, 0, this);
00186
00187
00188
00189 if(NULL == m_hProv && NULL != m_provider)
00190 {
00191 DWORD cbName;
00192 DWORD dwType;
00193 DWORD dwIndex;
00194 CHAR *pszName = NULL;
00195
00196
00197
00198 dwIndex = 0;
00199 while(CryptEnumProviders(dwIndex, NULL, 0, &dwType, NULL, &cbName))
00200 {
00201
00202
00203
00204
00205
00206 if (!(pszName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, cbName)))
00207 {
00208 throw CPKIFCryptoException(m_parent->thisComponent, COMMON_MEMORY_ALLOC_FAILURE, "");
00209 }
00210
00211
00212 if (CryptEnumProviders(dwIndex++, NULL, 0, &dwType, pszName, &cbName))
00213 {
00214
00215 if(strlen(pszName) == strlen(m_provider) && 0 == stricmp(pszName, m_provider) && dwType == m_provType)
00216 {
00217 LocalFree(pszName);
00218 return;
00219 }
00220 }
00221 else
00222 {
00223 LocalFree(pszName);
00224 std::ostringstream os;
00225 os << "CryptEnumProviders failed: " << GetLastError();
00226 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, this);
00227 }
00228 LocalFree(pszName);
00229 }
00230
00231
00232 RAISE_CRYPTO_EXCEPTION("No provider matching the specified provider name and provider type could be found.", m_parent->thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, this);
00233
00234
00235
00236
00237
00238
00239
00240
00241 }
00242 }
00243
00255 bool CPKIFCAPI2Impl::CertMatchesCurContext(
00257 PCCERT_CONTEXT cert) const
00258 {
00259 LOG_STRING_DEBUG("CPKIFCAPI2::CertMatchesCurContext(PCCERT_CONTEXT cert)", TOOLKIT_CRYPTO_CAPI, 0, this);
00260
00261 try
00262 {
00263
00264 CPKIFCAPICredential2 tmp(m_provider, m_provType, m_sysStoRegLoc);
00265 tmp.m_certContext = CertDuplicateCertificateContext(cert);
00266 return m_parent->OwnsKey(tmp);
00267 }
00268 catch(CPKIFException& )
00269 {
00270
00271 return false;
00272 }
00273 catch(...)
00274 {
00275 _ASSERT(false);
00276 return false;
00277 }
00278 }
00305 CPKIFCAPICredential2* CPKIFCAPI2Impl::MakeCAPICredential(
00307 PCCERT_CONTEXT cert) const
00308 {
00309 LOG_STRING_DEBUG("CPKIFCAPI2::MakeCAPICredential(PCCERT_CONTEXT cert)", TOOLKIT_CRYPTO_CAPI, 0, this);
00310
00311 char* name = NULL;
00312 CPKIFCAPICredential2* newKeyID = NULL;
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 DWORD dw = CertGetNameString(cert,CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, 0, 0, 0);
00326 if(1 == dw)
00327 {
00328 std::ostringstream os;
00329 os << "CertGetNameString failed: " << GetLastError();
00330 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_GET_NAME_FAILED, this);
00331 }
00332
00333 name = new char[dw + 1];
00334 dw = CertGetNameString(cert,CERT_NAME_FRIENDLY_DISPLAY_TYPE,0,NULL, name, dw);
00335 if(1 == dw)
00336 {
00337 delete[] name; name = NULL;
00338 std::ostringstream os;
00339 os << "CertGetNameString failed: " << GetLastError();
00340 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_GET_NAME_FAILED, this);
00341 }
00342
00343
00344 unsigned char* tmpKeyID = NULL;
00345 DWORD tmpKeyIDLen = 0;
00346
00347 BOOL succ = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID ,
00348 NULL, &tmpKeyIDLen);
00349 if(succ)
00350 {
00351
00352 tmpKeyID = (unsigned char *)malloc(tmpKeyIDLen);
00353 if(NULL == tmpKeyID)
00354 {
00355 throw CPKIFCryptoException(m_parent->thisComponent, COMMON_MEMORY_ALLOC_FAILURE);
00356 }
00357
00358
00359 succ = CertGetCertificateContextProperty(cert,
00360 CERT_KEY_IDENTIFIER_PROP_ID, (void *)tmpKeyID, &tmpKeyIDLen);
00361 if(!succ)
00362 {
00363 free(tmpKeyID); tmpKeyID = NULL;
00364
00365 std::ostringstream os;
00366 os << "CertGetCertificateContextProperty failed: " << GetLastError();
00367 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_KEY_PROV_INFO_FAILED, this);
00368 }
00369 }
00370
00371 char* tmpKeyIDASCII = new char[(tmpKeyIDLen*2) + 1];
00372 btoa((const char*)tmpKeyID, tmpKeyIDASCII, tmpKeyIDLen);
00373
00374 try
00375 {
00376 newKeyID = new CPKIFCAPICredential2(m_provider, m_provType, m_sysStoRegLoc);
00377 CPKIFStringPtr tmpSP(new std::string(name));
00378 newKeyID->m_name = tmpSP;
00379 CPKIFStringPtr tmpSP2(new std::string(tmpKeyIDASCII));
00380 newKeyID->m_id = tmpSP2;
00381
00382 delete[] name; name = NULL;
00383 free(tmpKeyID); tmpKeyID = NULL;
00384 delete[] tmpKeyIDASCII; tmpKeyIDASCII = NULL;
00385
00386 newKeyID->m_certContext = CertDuplicateCertificateContext(cert);
00387 return newKeyID;
00388 }
00389 catch(...)
00390 {
00391 if(NULL != name)
00392 {
00393 delete[] name; name = NULL;
00394 }
00395 if(NULL != newKeyID)
00396 {
00397 delete newKeyID;
00398 }
00399
00400 std::ostringstream os;
00401 os << "Unknown error creating credential: " << GetLastError();
00402 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, COMMON_UNKNOWN_ERROR, this);
00403 }
00404 }
00405
00406
00407
00417 bool CPKIFCAPI2::OwnsKey(
00419 const CPKIFCredential& keyID) const
00420 {
00421 LOG_STRING_DEBUG("CPKIFCAPI2::OwnsKey(const CPKIFCredential& keyID)", TOOLKIT_CRYPTO_CAPI, 0, this);
00422
00423
00424 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&keyID);
00425
00426
00427 if(NULL == ck2)
00428 return false;
00429
00430
00431 if(NULL == m_impl->m_provider && 0 == m_impl->m_provType)
00432 return true;
00433
00434
00435 return ck2->ProviderInfoMatches(m_impl->m_provider, m_impl->m_provType);
00436 }
00437
00450 void CPKIFCAPI2::GetKeyList(
00452 CPKIFCredentialList& v,
00454 CPKIFKeyUsagePtr& ku)
00455 {
00456 bitset<9> tmp = ku->GetKeyUsage();
00457 GetKeyList(v, &tmp);
00458 }
00459
00473 void CPKIFCAPI2::GetKeyList(
00475 CPKIFCredentialList& v,
00477 bitset<9>* ku)
00478 {
00479 LOG_STRING_DEBUG("CPKIFCAPI2::GetKeyList(CPKIFCredentialList& v, bitset<9>* ku)", TOOLKIT_CRYPTO_CAPI, 0, this);
00480
00481 m_impl->GetContext();
00482
00483 HRESULT hr = S_OK;
00484 DWORD dw = 0;
00485
00486 const size_t originalCount = v.size();
00487
00488 USES_CONVERSION;
00489
00490
00491
00492 if(NULL == m_impl->m_hCertStore)
00493 {
00494 m_impl->m_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL,
00495 CERT_STORE_OPEN_EXISTING_FLAG | m_impl->m_sysStoRegLoc, T2OLE("MY"));
00496 if(NULL == m_impl->m_hCertStore)
00497 {
00498 std::ostringstream os;
00499 os << "CertOpenStore failed: " << GetLastError();
00500 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_FAILED_TO_OPEN_CERT_STORE, this);
00501 }
00502 }
00503
00504 PCCERT_CONTEXT pPrevCertContext = NULL;
00505 BOOL keyUsagePresent = false;
00506 BYTE kuBits[2];
00507 CPKIFCAPICredential2* keyID = NULL;
00508
00509 try
00510 {
00511 pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hCertStore, pPrevCertContext);
00512 while(NULL != pPrevCertContext)
00513 {
00514
00515 keyUsagePresent = CertGetIntendedKeyUsage(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, pPrevCertContext->pCertInfo, (BYTE*)&kuBits, sizeof(kuBits));
00516
00517
00518
00519 if(CertHasKey(pPrevCertContext) && m_impl->CertMatchesCurContext(pPrevCertContext) &&
00520 (!keyUsagePresent || (keyUsagePresent && keyUsageTest(kuBits, ku))))
00521 {
00522
00523 keyID = m_impl->MakeCAPICredential(pPrevCertContext);
00524
00525
00526 CPKIFCredentialPtr tmpCred(keyID);
00527 v.push_back(tmpCred);
00528
00529 keyID = NULL;
00530 }
00531
00532 pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hCertStore, pPrevCertContext);
00533 }
00534 }
00535 catch(...)
00536 {
00537 if(NULL != keyID)
00538 {
00539
00540 delete keyID; keyID = NULL;
00541 }
00542
00543 if(NULL != pPrevCertContext)
00544 {
00545
00546 CertFreeCertificateContext(pPrevCertContext); pPrevCertContext = NULL;
00547 }
00548
00549 std::ostringstream os;
00550 os << "Unknown failure in GetKeyList. GetLastError returns: " << GetLastError();
00551 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, COMMON_UNKNOWN_ERROR, this);
00552 }
00553 }
00554
00555
00556
00569 CPKIFCredentialPtr CPKIFCAPI2::MakeKeyID(
00572 const std::string& asciiHexKeyID)
00573 {
00574 #undef CLEANUP
00575 #define CLEANUP \
00576 { \
00577 if (NULL != bin) \
00578 { delete[] bin; bin = NULL; } \
00579 if (NULL != cert) \
00580 { CertFreeCertificateContext(cert); cert = NULL; } \
00581 }
00582
00583 LOG_STRING_DEBUG("CPKIFCAPI2::MakeKeyID(const std::string& asciiHexKeyID)", TOOLKIT_CRYPTO_CAPI, 0, this);
00584
00585 char* bin = NULL;
00586 PCCERT_CONTEXT cert = NULL;
00587
00588 CPKIFCAPICredential2* newKeyID = NULL;
00589
00590
00591 const char* hex = asciiHexKeyID.c_str();
00592 unsigned int len = 0;
00593
00594 try
00595 {
00596 len = numeric_cast<unsigned int>(asciiHexKeyID.length()/2);
00597 }
00598 catch(bad_numeric_cast &)
00599 {
00600 throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "Key identifier is an impossibly long number.");
00601 }
00602 bin = new char[len];
00603 if(0 != atob(bin, const_cast<char*>(hex), &len))
00604 {
00605 CLEANUP;
00606
00607 std::string reason;
00608 FormatErrorMessage(reason, "Key ID contains non-ASCII hexadecimal characters.", -1, __FILE__, __LINE__);
00609 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, reason.c_str());
00610 }
00611
00612
00613 CRYPT_HASH_BLOB b;
00614 b.cbData = len;
00615 b.pbData = (BYTE*)bin;
00616
00617
00618 USES_CONVERSION;
00619 if(NULL == m_impl->m_hCertStore)
00620 {
00621 m_impl->m_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, CERT_STORE_OPEN_EXISTING_FLAG | m_impl->m_sysStoRegLoc, T2OLE("MY"));
00622 if(NULL == m_impl->m_hCertStore)
00623 {
00624 CLEANUP;
00625
00626 std::ostringstream os;
00627 os << "CertOpenStore failed: " << GetLastError();
00628 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_FAILED_TO_OPEN_CERT_STORE, this);
00629 }
00630 }
00631
00632 cert = CertFindCertificateInStore(m_impl->m_hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER, (void*)&b, NULL);
00633
00634 try
00635 {
00636 if(NULL != cert && true == m_impl->CertMatchesCurContext(cert))
00637 {
00638
00639 newKeyID = m_impl->MakeCAPICredential(cert);
00640 }
00641 }
00642 catch(CPKIFException& e)
00643 {
00644 if(NULL != newKeyID)
00645 {
00646 delete newKeyID; newKeyID = NULL;
00647 }
00648
00649 CLEANUP;
00650 throw e;
00651 }
00652
00653 CLEANUP;
00654 CPKIFCredentialPtr tmp(newKeyID);
00655 return tmp;
00656 }
00657
00684 void CPKIFCAPI2::Sign(
00686 const CPKIFCredential& key,
00688 unsigned char* pHashData,
00690 int nHashDataLen,
00692 unsigned char* pSignature,
00695 int* nSignatureLen,
00697 PKIFCRYPTO::HASH_ALG hashAlg
00698 )
00699 {
00700 #undef CLEANUP
00701 #define CLEANUP \
00702 { \
00703 if (NULL != hHash) \
00704 { CryptDestroyHash(hHash); hHash = NULL; } \
00705 if (NULL != tmpHashCtx && true == freeContext) \
00706 { CryptReleaseContext(tmpHashCtx, 0); tmpHashCtx = NULL; } \
00707 }
00708
00709 LOG_STRING_DEBUG("CPKIFCAPI2::Sign(const CPKIFCredential& key,...", TOOLKIT_CRYPTO_CAPI, 0, this);
00710
00711 m_impl->GetContext();
00712
00713 int err = 0;
00714
00715
00716
00717 HCRYPTPROV tmpHashCtx = NULL;
00718 HCRYPTHASH hHash = NULL;
00719 bool freeContext = false;
00720
00721 ALG_ID HashAlg = GetHashAlg((PKIFCRYPTO::HASH_ALG)nHashDataLen);
00722
00723
00724 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&key);
00725 if(NULL == ck2)
00726 {
00727 throw CPKIFCryptoException(thisComponent, CRYPTO_UNRECOGNIZED_CREDENTIAL, "Credential type not recognized.");
00728 }
00729
00730 if(NULL == ck2->m_keyProviderInfo)
00731 {
00732
00733 CPKIFCAPICredential2* k2 = const_cast<CPKIFCAPICredential2*>(ck2);
00734 k2->SetKeyProviderInfo();
00735 }
00736
00737 USES_CONVERSION;
00738
00739 if(NULL == m_impl->m_hProv)
00740 {
00741 if(!CryptAcquireContext(&tmpHashCtx, OLE2T(ck2->m_keyProviderInfo->pwszContainerName), OLE2T(ck2->m_keyProviderInfo->pwszProvName), ck2->m_keyProviderInfo->dwProvType, m_impl->m_flags))
00742 {
00743 std::ostringstream os;
00744 os << "CryptAcquireContext failed: " << GetLastError();
00745 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, this);
00746 }
00747
00748 freeContext = true;
00749 }
00750 else
00751 tmpHashCtx = m_impl->m_hProv;
00752
00753
00754 if(NULL != ck2->m_password)
00755 {
00756
00757 HCRYPTKEY userKey = NULL;
00758 if(!CryptGetUserKey(tmpHashCtx, ck2->m_keyProviderInfo->dwKeySpec, &userKey))
00759 {
00760 CLEANUP;
00761
00762 std::ostringstream os;
00763 os << "CryptGetUserKey failed: " << GetLastError();
00764 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_GET_USER_KEY_FAILED, this);
00765 }
00766
00767 if(!CryptSetProvParam(tmpHashCtx, PP_SIGNATURE_PIN, ck2->m_password, 0))
00768 {
00769 CLEANUP;
00770
00771 CryptDestroyKey(userKey);
00772 std::ostringstream os;
00773 os << "CryptSetProvParam failed: " << GetLastError();
00774 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SET_PASSWORD_FAILED, this);
00775 }
00776
00777 CryptDestroyKey(userKey);
00778 }
00779
00780 if(!CryptCreateHash(tmpHashCtx, HashAlg, NULL, 0, &hHash))
00781 {
00782 CLEANUP;
00783
00784 std::ostringstream os;
00785 os << "CryptCreateHash failed: " << GetLastError();
00786 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_CREATE_HASH_FAILED, this);
00787 }
00788 DWORD hSize = 0;
00789 DWORD hSizeSize = sizeof(hSize);
00790 if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hSize, &hSizeSize, 0))
00791 {
00792 CLEANUP;
00793
00794 std::ostringstream os;
00795 os << "CryptGetHashParam failed: " << GetLastError();
00796 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_MISC_HASH_CALL_FAILED, this);
00797 }
00798
00799 if(nHashDataLen != hSize)
00800 {
00801 CLEANUP;
00802
00803 std::string reason;
00804 FormatErrorMessage(reason, "Hash sizes do not match. Could not set hash object for signing.", -1, __FILE__, __LINE__);
00805 throw CPKIFCryptoException(thisComponent, PKIFCAPI_MISC_HASH_CALL_FAILED, reason.c_str());
00806 }
00807
00808 if(!CryptSetHashParam(hHash, HP_HASHVAL, pHashData, 0))
00809 {
00810 CLEANUP;
00811
00812 std::ostringstream os;
00813 os << "CryptSetHashParam failed: " << GetLastError();
00814 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_MISC_HASH_CALL_FAILED, this);
00815 }
00816
00817 if(!CryptSignHash(hHash, ck2->m_keyProviderInfo->dwKeySpec, NULL, 0, pSignature, (DWORD*)nSignatureLen))
00818 {
00819 CLEANUP;
00820
00821 std::ostringstream os;
00822 os << "CryptSignHash failed: " << GetLastError();
00823 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SIGN_FAILED, this);
00824 }
00825
00826 if(DSA_CLASS != GetAlgClass(key.GetCertificate()->SubjectPublicKeyInfo()->alg()))
00827 ReverseBytes(pSignature, *nSignatureLen);
00828 else
00829 {
00830 ReverseBytes(pSignature, *nSignatureLen/2);
00831 ReverseBytes(pSignature+(*nSignatureLen/2), *nSignatureLen/2);
00832 }
00833
00834 CLEANUP;
00835 }
00836
00854 void CPKIFCAPI2::Decrypt(
00857 const CPKIFCredential& key,
00859 unsigned char* pData,
00861 int nDataLen,
00863 unsigned char* pResult,
00866 int* pnResultLen)
00867 {
00868 #undef CLEANUP
00869 #define CLEANUP \
00870 { \
00871 if (NULL != userKey) \
00872 { CryptDestroyKey(userKey); userKey = NULL; } \
00873 if (NULL != tmpCtx && TRUE == freeContext) \
00874 { CryptReleaseContext(tmpCtx, 0); tmpCtx = NULL; } \
00875 }
00876
00877 LOG_STRING_DEBUG("CPKIFCAPI2::Decrypt(const CPKIFCredential& key,...", TOOLKIT_CRYPTO_CAPI, 0, this);
00878
00879 m_impl->GetContext();
00880
00881 USES_CONVERSION;
00882
00883 HCRYPTPROV tmpCtx = NULL;
00884 BOOL freeContext = false;
00885
00886
00887 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&key);
00888 if(NULL == ck2)
00889 {
00890 throw CPKIFCryptoException(thisComponent, CRYPTO_UNRECOGNIZED_CREDENTIAL, "Credential type not recognized.");
00891 }
00892
00893 if(NULL == ck2->m_keyProviderInfo)
00894 {
00895
00896 CPKIFCAPICredential2* k2 = const_cast<CPKIFCAPICredential2*>(ck2);
00897 k2->SetKeyProviderInfo();
00898 }
00899
00900 if(NULL == m_impl->m_hProv)
00901 {
00902 DWORD keySpec = 0;
00903
00904 if(!CryptAcquireCertificatePrivateKey(ck2->m_certContext, 0, 0, &tmpCtx, &keySpec, &freeContext))
00905 {
00906 std::ostringstream os;
00907 os << "CryptAcquireContext failed: " << GetLastError();
00908 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, this);
00909 }
00910 }
00911 else
00912 tmpCtx = m_impl->m_hProv;
00913
00914 HCRYPTKEY userKey = NULL;
00915 if(!CryptGetUserKey(tmpCtx, ck2->m_keyProviderInfo->dwKeySpec, &userKey))
00916 {
00917 CLEANUP;
00918
00919 std::ostringstream os;
00920 os << "CryptGetUserKey failed: " << GetLastError();
00921 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_GET_USER_KEY_FAILED, this);
00922 }
00923
00924
00925 if(NULL != ck2->m_password)
00926 {
00927
00928 if(!CryptSetProvParam(tmpCtx, PP_SIGNATURE_PIN, ck2->m_password, 0))
00929 {
00930 CLEANUP;
00931
00932 std::ostringstream os;
00933 os << "CryptSetProvParam failed: " << GetLastError();
00934 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SET_PASSWORD_FAILED, this);
00935 }
00936 }
00937
00938 memcpy(pResult, pData, nDataLen);
00939 *pnResultLen = nDataLen;
00940
00941 ReverseBytes(pResult, nDataLen);
00942
00943 if(!CryptDecrypt(userKey, NULL, true, 0, pResult, (DWORD*)pnResultLen))
00944 {
00945 CLEANUP;
00946
00947 std::ostringstream os;
00948 os << "CryptDecrypt failed: " << GetLastError();
00949 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_DECRYPT_FAILED, this);
00950 }
00951
00952
00953
00954
00955
00956
00957 const char* pwszProvName = OLE2T(ck2->m_keyProviderInfo->pwszProvName);
00958 if(strlen(pwszProvName) == strlen("ActivCard Gold Cryptographic Service Provider") &&
00959 0 == stricmp("ActivCard Gold Cryptographic Service Provider", pwszProvName))
00960 {
00961 if(UNSET == g_bytesReversed)
00962 g_bytesReversed = m_impl->CheckReversed(&userKey);
00963
00964 if(REV == g_bytesReversed)
00965 ReverseBytes(pResult, *pnResultLen);
00966 }
00967 CLEANUP;
00968 }
00969
00981 void CPKIFCAPI2::Encrypt(
00984 const CPKIFCredential& key,
00986 unsigned char* pData,
00988 int nDataLen,
00990 unsigned char* pResult,
00993 int* pnResultLen)
00994 {
00995 LOG_STRING_DEBUG("CPKIFCAPI2::Encrypt(const CPKIFCredential& key, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_CAPI, 0, this);
00996
00997 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "Encrypt operations are not implemented for stored key material");
00998 }
00999
01011 bool CPKIFCAPI2::Verify(
01014 const CPKIFCredential& key,
01017 unsigned char* pHashData,
01019 int nHashDataLen,
01021 unsigned char* pSignature,
01023 int nSignatureLen,
01025 PKIFCRYPTO::HASH_ALG hashAlg
01026 )
01027 {
01028 LOG_STRING_DEBUG("CPKIFCAPI2::Verify(const CPKIFCredential& key, unsigned char* pHashData, int nHashDataLen, unsigned char* pSignature, int nSignatureLen)", TOOLKIT_CRYPTO_CAPI, 0, this);
01029
01030 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "Verify operations are not implemented for stored key material");
01031 }
01032
01051 IPKIFCryptContext* CPKIFCAPI2::CryptInit(
01054 CPKIFCredentialPtr& key,
01056 bool pad)
01057 {
01058 LOG_STRING_DEBUG("CPKIFCAPI2::CryptInit(CPKIFCredentialPtr& key)", TOOLKIT_CRYPTO_CAPI, 0, this);
01059
01060
01061 if(key == (CPKIFCredential*)NULL)
01062 {
01063 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL or invalid key passed to CPKIFCAPI2::CryptInit.");
01064 }
01065
01066 m_impl->GetContext();
01067
01068 USES_CONVERSION;
01069
01070
01071 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&(*key));
01072 if(NULL == ck2)
01073 {
01074 throw CPKIFCryptoException(thisComponent, CRYPTO_UNRECOGNIZED_CREDENTIAL, "Credential type not recognized.");
01075 }
01076
01077 if(NULL == ck2->m_keyProviderInfo)
01078 {
01079
01080 CPKIFCAPICredential2* k2 = const_cast<CPKIFCAPICredential2*>(ck2);
01081 k2->SetKeyProviderInfo();
01082 }
01083
01084 DWORD keySpec = 0;
01085 BOOL freeContext = false;
01086 CPKIFCAPICryptContext2* cryptContext = new CPKIFCAPICryptContext2();
01087 if(!CryptAcquireCertificatePrivateKey(ck2->m_certContext, 0, 0, &cryptContext->m_cryptContext, &keySpec, &freeContext))
01088 {
01089 delete cryptContext;
01090 std::ostringstream os;
01091 os << "CryptAcquireContext failed: " << GetLastError();
01092 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_ACQUIRE_CONTEXT_FAILED, this);
01093 }
01094
01095 if(!CryptGetUserKey(cryptContext->m_cryptContext, ck2->m_keyProviderInfo->dwKeySpec, &cryptContext->m_userKey))
01096 {
01097 delete cryptContext;
01098 std::ostringstream os;
01099 os << "CryptGetUserKey failed: " << GetLastError();
01100 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_GET_USER_KEY_FAILED, this);
01101 }
01102
01103
01104 if(NULL != ck2->m_password)
01105 {
01106
01107 if(!CryptSetProvParam(cryptContext->m_cryptContext, PP_SIGNATURE_PIN, ck2->m_password, 0))
01108 {
01109 std::ostringstream os;
01110 os << "CryptSetProvParam failed: " << GetLastError();
01111 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SET_PASSWORD_FAILED, this);
01112 }
01113 }
01114
01115 cryptContext->m_cred = key;
01116 return cryptContext;
01117 }
01118
01135 void CPKIFCAPI2::Decrypt(
01138 IPKIFCryptContext* cryptContext,
01140 unsigned char* pData,
01142 int nDataLen,
01144 unsigned char* pResult,
01147 int* pnResultLen,
01150 bool final)
01151 {
01152 LOG_STRING_DEBUG("CPKIFCAPI2::Decrypt(IPKIFCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)", TOOLKIT_CRYPTO_CAPI, 0, this);
01153
01154 if(NULL == cryptContext)
01155 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL or invalid credential passed to CPKIFCAPI2::Decrypt.");
01156
01157 CPKIFCAPICryptContext2* ccc = dynamic_cast<CPKIFCAPICryptContext2*>(cryptContext);
01158
01159
01160 if(NULL == ccc)
01161 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL or invalid credential passed to CPKIFCAPI2::Decrypt.");
01162
01163 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&(*cryptContext->GetCredential()));
01164 if(NULL == ck2)
01165 {
01166 throw CPKIFCryptoException(thisComponent, CRYPTO_UNRECOGNIZED_CREDENTIAL, "Credential type not recognized.");
01167 }
01168
01169 memcpy(pResult, pData, nDataLen);
01170 *pnResultLen = nDataLen;
01171
01172 ReverseBytes(pResult, nDataLen);
01173
01174 if(!CryptDecrypt(ccc->m_userKey, NULL, true, 0, pResult, (DWORD*)pnResultLen))
01175 {
01176 std::ostringstream os;
01177 os << "CryptDecrypt failed: " << GetLastError();
01178 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_DECRYPT_FAILED, this);
01179 }
01180
01181 USES_CONVERSION;
01182
01183
01184
01185 const char* pwszProvName = OLE2T(ck2->m_keyProviderInfo->pwszProvName);
01186 if(strlen(pwszProvName) == strlen("ActivCard Gold Cryptographic Service Provider") &&
01187 0 == stricmp("ActivCard Gold Cryptographic Service Provider", pwszProvName))
01188 {
01189 if(UNSET == g_bytesReversed)
01190 g_bytesReversed = m_impl->CheckReversed(&(ccc->m_userKey));
01191
01192 if(REV == g_bytesReversed)
01193 ReverseBytes(pResult, *pnResultLen);
01194
01195 }
01196 }
01197
01208 void CPKIFCAPI2::Encrypt(
01211 IPKIFCryptContext* cryptContext,
01213 unsigned char* pData,
01215 int nDataLen,
01217 unsigned char* pResult,
01220 int* pnResultLen,
01223 bool final)
01224 {
01225 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "Encrypt operations are not implemented for stored key material");
01226 }
01227
01238 BYTESREVERSED CPKIFCAPI2Impl::CheckReversed(
01240 HCRYPTKEY * key)
01241 {
01242
01243 const unsigned char * testblock = (unsigned char *)"1234";
01244 DWORD datalen = 4;
01245 DWORD blocksizelen = sizeof(DWORD);
01246 DWORD blocksize = 0;
01247 CryptGetKeyParam(*key,KP_BLOCKLEN,(BYTE *)&blocksize,&blocksizelen,0x00);
01248
01249 unsigned char* pResult = new unsigned char[blocksize];
01250 memset(pResult,0x00,blocksize);
01251 memcpy(pResult,testblock,datalen);
01252
01253 if(!CryptEncrypt(*key, NULL, true, 0, pResult, &datalen, blocksize))
01254 {
01255 std::ostringstream os;
01256 os << "CryptDecrypt failed: " << GetLastError();
01257 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, CRYPTO_ENCRYPT_FAILED, this);
01258 }
01259
01260 if(!CryptDecrypt(*key, NULL, true, 0, pResult, &datalen))
01261 {
01262 std::ostringstream os;
01263 os << "CryptDecrypt failed: " << GetLastError();
01264 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_DECRYPT_FAILED, this);
01265 }
01266
01267 if(memcmp(pResult, "1234", datalen) == 0)
01268 return NOTREV;
01269
01270
01271 return REV;
01272
01273 }