00001
00009 #include "PKIFCNGCAPI.h"
00010 #include "ToolkitUtils.h"
00011 #include "CAPIUtils.h"
00012 #include "PKIFCAPICredential2.h"
00013 #include "PKIFCAPICryptContext2.h"
00014 #include "PKIFCNGKeyAgreeContext.h"
00015 #include "PKIFBCryptPublicKey.h"
00016 #include "PKIFCryptoPPKeyMaterial.h"
00017 #include "PKIFAlgorithm.h"
00018
00019 #include "PKIFCryptoErrors.h"
00020 #include "PKIFCAPIErrors.h"
00021 #include "PKIFCryptoException.h"
00022
00023 #include "SubjectPublicKeyInfo.h"
00024 #include "Certificate.h"
00025 #include "KeyUsage.h"
00026
00027
00028 #include "boost/numeric/conversion/cast.hpp"
00029
00030 using boost::numeric_cast;
00031 using boost::bad_numeric_cast;
00032
00033 #include <atlbase.h>
00034 #include <sstream>
00035 using namespace std;
00036
00037 #include "PKIFCNGUtils.h"
00038
00039 #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
00040 #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
00041
00042
00044 struct CPKIFCNGCAPIImpl
00045 {
00046 CPKIFCNGCAPI* m_parent;
00054 CPKIFCNGCAPIImpl ()
00055 {
00056 m_parent = NULL;
00057 }
00065 CPKIFCNGCAPIImpl (CPKIFCNGCAPI *p)
00066 {
00067 m_parent = p;
00068 }
00069 HCRYPTPROV m_hProv;
00070 HCERTSTORE m_hCertStore;
00071 DWORD m_flags;
00072
00073 char* m_provider;
00074 int m_sysStoRegLoc;
00075 int m_provType;
00076
00077 bool CertCanBeUsedByCurrentColleague(PCCERT_CONTEXT cert) const;
00078
00079 CPKIFCAPICredential2* MakeCAPICredential(PCCERT_CONTEXT cert) const;
00080 };
00082
00091 CPKIFCNGCAPI::CPKIFCNGCAPI(
00093 const char* provider,
00095 int provType,
00097 int sysStoRegLoc)
00098 :m_impl (new CPKIFCNGCAPIImpl), IPKIFCAPISource(sysStoRegLoc, NULL)
00099 {
00100 LOG_STRING_DEBUG("CPKIFCAPI::CPKIFCAPI(void)", TOOLKIT_CRYPTO_CAPI, 0, this);
00101
00102 m_impl->m_parent = this;
00103 m_impl->m_provType = provType;
00104 m_impl->m_sysStoRegLoc = sysStoRegLoc;
00105 m_impl->m_provider = NULL;
00106
00107 size_t len = 0;
00108 if(provider)
00109 {
00110 len = strlen(provider);
00111 m_impl->m_provider = new char[len + 1];
00112
00113
00114 strcpy(m_impl->m_provider, provider);
00115 }
00116
00117 m_impl->m_hProv = NULL;
00118 m_impl->m_hCertStore = NULL;
00119
00120
00121 m_impl->m_flags = 0;
00122 if(CERT_SYSTEM_STORE_LOCAL_MACHINE == m_impl->m_sysStoRegLoc)
00123 m_impl->m_flags = CRYPT_MACHINE_KEYSET;
00124 }
00132 CPKIFCNGCAPI::~CPKIFCNGCAPI(void)
00133 {
00134 LOG_STRING_DEBUG("CPKIFCAPI::~CPKIFCAPI(void)", TOOLKIT_CRYPTO_CAPI, 0, this);
00135
00136 if(m_impl->m_provider)
00137 delete[] m_impl->m_provider;
00138
00139 if(NULL != m_impl->m_hProv)
00140 {
00141 CryptReleaseContext(m_impl->m_hProv, 0); m_impl->m_hProv = NULL;
00142 }
00143
00144 if(NULL != m_impl->m_hCertStore)
00145 {
00146 BOOL certSucc = CertCloseStore(m_impl->m_hCertStore,CERT_CLOSE_STORE_CHECK_FLAG);
00147 #ifdef _DEBUG
00148 int ceerr = GetLastError();
00149 #endif
00150 m_impl->m_hCertStore = NULL;
00151 }
00152
00153 delete m_impl;
00154 m_impl = NULL;
00155 }
00163 void CPKIFCNGCAPI::Initialize()
00164 {
00165 LOG_STRING_DEBUG("CPKIFCNGCAPI::Initialize()", TOOLKIT_CRYPTO_CAPI, 0, this);
00166
00167
00168
00169 }
00170
00171
00183 bool CPKIFCNGCAPIImpl::CertCanBeUsedByCurrentColleague(
00185 PCCERT_CONTEXT cert) const
00186 {
00187 LOG_STRING_DEBUG("CPKIFCNGCAPI::CertCanBeUsedByCurrentColleague(PCCERT_CONTEXT cert)", TOOLKIT_CRYPTO_CAPI, 0, this);
00188
00189 try
00190 {
00191
00192 CPKIFCAPICredential2 tmp(m_provider, m_provType, m_sysStoRegLoc);
00193 tmp.m_certContext = CertDuplicateCertificateContext(cert);
00194 return m_parent->OwnsKey(tmp);
00195 }
00196 catch(CPKIFException& )
00197 {
00198
00199 return false;
00200 }
00201 catch(...)
00202 {
00203 _ASSERT(false);
00204 return false;
00205 }
00206 }
00233 CPKIFCAPICredential2* CPKIFCNGCAPIImpl::MakeCAPICredential(
00235 PCCERT_CONTEXT cert) const
00236 {
00237 LOG_STRING_DEBUG("CPKIFCNGCAPI::MakeCAPICredential(PCCERT_CONTEXT cert)", TOOLKIT_CRYPTO_CAPI, 0, this);
00238
00239 pkif_char_array name(0);
00240 std::auto_ptr<CPKIFCAPICredential2> newKeyID((CPKIFCAPICredential2*) 0);
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 DWORD ccount = CertGetNameString(cert,CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, 0, 0, 0);
00255 if(1 == ccount)
00256 {
00257 std::ostringstream os;
00258 os << "CertGetNameString failed: " << GetLastError();
00259 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_GET_NAME_FAILED, this);
00260 }
00261
00262
00263 name.reset(new char[ccount]);
00264 ccount = CertGetNameString(cert,CERT_NAME_FRIENDLY_DISPLAY_TYPE,0,NULL, name, ccount);
00265 if(1 == ccount)
00266 {
00267 std::ostringstream os;
00268 os << "CertGetNameString failed: " << GetLastError();
00269 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_GET_NAME_FAILED, this);
00270 }
00271
00272
00273 DWORD tmpKeyIDLen = 0;
00274
00275 BOOL succ = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID ,
00276 NULL, &tmpKeyIDLen);
00277 if(!succ)
00278 {
00279 std::ostringstream os;
00280 os << "CertGetCertificateContextProperty failed: " << GetLastError();
00281 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_KEY_PROV_INFO_FAILED, this);
00282 }
00283 pkif_byte_array tmpKeyID(new unsigned char[tmpKeyIDLen]);
00284
00285 succ = CertGetCertificateContextProperty(cert,
00286 CERT_KEY_IDENTIFIER_PROP_ID, (void *)tmpKeyID.get(), &tmpKeyIDLen);
00287 if(!succ)
00288 {
00289 std::ostringstream os;
00290 os << "CertGetCertificateContextProperty failed: " << GetLastError();
00291 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, PKIFCAPI_KEY_PROV_INFO_FAILED, this);
00292 }
00293
00294 pkif_char_array tmpKeyIDASCII(new char[(tmpKeyIDLen*2) + 1]);
00295 btoa((const char*)tmpKeyID.get(), tmpKeyIDASCII.get(), tmpKeyIDLen);
00296
00297 try
00298 {
00299 newKeyID.reset(new CPKIFCAPICredential2(m_provider, m_provType, m_sysStoRegLoc));
00300 CPKIFStringPtr tmpSP(new std::string(name));
00301 newKeyID->m_name = tmpSP;
00302 CPKIFStringPtr tmpSP2(new std::string(tmpKeyIDASCII));
00303 newKeyID->m_id = tmpSP2;
00304 newKeyID->m_certContext = CertDuplicateCertificateContext(cert);
00305 return newKeyID.release();
00306 }
00307 catch(...)
00308 {
00309 std::ostringstream os;
00310 os << "Unknown error creating credential: " << GetLastError();
00311 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), m_parent->thisComponent, COMMON_UNKNOWN_ERROR, this);
00312 }
00313 }
00314
00315
00316
00326 bool CPKIFCNGCAPI::OwnsKey(
00328 const CPKIFCredential& keyID) const
00329 {
00330 LOG_STRING_DEBUG("CPKIFCNGCAPI::OwnsKey(const CPKIFCredential& keyID)", TOOLKIT_CRYPTO_CAPI, 0, this);
00331
00332
00333 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&keyID);
00334
00335
00336 if(NULL == ck2)
00337 return false;
00338
00339
00340 if(NULL == m_impl->m_provider && 0 == m_impl->m_provType)
00341 return true;
00342
00343
00344 return ck2->ProviderInfoMatches(m_impl->m_provider, m_impl->m_provType);
00345 }
00346
00359 void CPKIFCNGCAPI::GetKeyList(
00361 CPKIFCredentialList& v,
00363 CPKIFKeyUsagePtr& ku)
00364 {
00365 bitset<9> tmp = ku->GetKeyUsage();
00366 GetKeyList(v, &tmp);
00367 }
00368
00382 void CPKIFCNGCAPI::GetKeyList(
00384 CPKIFCredentialList& v,
00386 bitset<9>* ku)
00387 {
00388 LOG_STRING_DEBUG("CPKIFCNGCAPI::GetKeyList(CPKIFCredentialList& v, bitset<9>* ku)", TOOLKIT_CRYPTO_CAPI, 0, this);
00389
00390 HRESULT hr = S_OK;
00391 DWORD dw = 0;
00392
00393 const size_t originalCount = v.size();
00394
00395 USES_CONVERSION;
00396
00397
00398
00399 if(NULL == m_impl->m_hCertStore)
00400 {
00401 m_impl->m_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL,
00402 CERT_STORE_OPEN_EXISTING_FLAG | m_impl->m_sysStoRegLoc, T2OLE("MY"));
00403 if(NULL == m_impl->m_hCertStore)
00404 {
00405 std::ostringstream os;
00406 os << "CertOpenStore failed: " << GetLastError();
00407 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_FAILED_TO_OPEN_CERT_STORE, this);
00408 }
00409 }
00410
00411 PCCERT_CONTEXT pPrevCertContext = NULL;
00412 BOOL keyUsagePresent = false;
00413 BYTE kuBits[2];
00414 CPKIFCAPICredential2* keyID = NULL;
00415
00416 try
00417 {
00418
00419
00420
00421 pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hCertStore, pPrevCertContext);
00422 while(NULL != pPrevCertContext)
00423 {
00424
00425 keyUsagePresent = CertGetIntendedKeyUsage(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, pPrevCertContext->pCertInfo, (BYTE*)&kuBits, sizeof(kuBits));
00426
00427
00428
00429 if(CertHasKey(pPrevCertContext) && m_impl->CertCanBeUsedByCurrentColleague(pPrevCertContext) &&
00430 (!keyUsagePresent || (keyUsagePresent && keyUsageTest(kuBits, ku))))
00431 {
00432
00433 keyID = m_impl->MakeCAPICredential(pPrevCertContext);
00434
00435
00436 CPKIFCredentialPtr tmpCred(keyID);
00437 v.push_back(tmpCred);
00438
00439 keyID = NULL;
00440 }
00441
00442 pPrevCertContext = CertEnumCertificatesInStore(m_impl->m_hCertStore, pPrevCertContext);
00443 }
00444 }
00445 catch(...)
00446 {
00447 if(NULL != keyID)
00448 {
00449
00450 delete keyID; keyID = NULL;
00451 }
00452
00453 if(NULL != pPrevCertContext)
00454 {
00455
00456 CertFreeCertificateContext(pPrevCertContext); pPrevCertContext = NULL;
00457 }
00458
00459 std::ostringstream os;
00460 os << "Unknown failure in GetKeyList. GetLastError returns: " << GetLastError();
00461 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, COMMON_UNKNOWN_ERROR, this);
00462 }
00463 }
00464
00465
00466
00479 CPKIFCredentialPtr CPKIFCNGCAPI::MakeKeyID(
00482 const std::string& asciiHexKeyID)
00483 {
00484 LOG_STRING_DEBUG("CPKIFCNGCAPI::MakeKeyID(const std::string& asciiHexKeyID)", TOOLKIT_CRYPTO_CAPI, 0, this);
00485
00486 pkif_char_array bin(NULL);
00487 PCCERT_CONTEXT_PKIF cert(0);
00488
00489 std::auto_ptr<CPKIFCAPICredential2> newKeyID;
00490
00491
00492 const char* hex = asciiHexKeyID.c_str();
00493 unsigned int len = 0;
00494
00495 try
00496 {
00497 len = numeric_cast<unsigned int>(asciiHexKeyID.length()/2);
00498 }
00499 catch(bad_numeric_cast &)
00500 {
00501 throw CPKIFException(TOOLKIT_CRYPTO, COMMON_INVALID_INPUT, "Key identifier is an impossibly long number.");
00502 }
00503 bin.reset(new char[len]);
00504 if(0 != atob(bin, const_cast<char*>(hex), &len))
00505 {
00506 std::string reason;
00507 FormatErrorMessage(reason, "Key ID contains non-ASCII hexadecimal characters.", -1, __FILE__, __LINE__);
00508 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, reason.c_str());
00509 }
00510
00511
00512 CRYPT_HASH_BLOB b;
00513 b.cbData = len;
00514 b.pbData = (BYTE*)bin.get();
00515
00516
00517 USES_CONVERSION;
00518 if(NULL == m_impl->m_hCertStore)
00519 {
00520 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"));
00521 if(NULL == m_impl->m_hCertStore)
00522 {
00523 std::ostringstream os;
00524 os << "CertOpenStore failed: " << GetLastError();
00525 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_FAILED_TO_OPEN_CERT_STORE, this);
00526 }
00527 }
00528
00529 cert.reset(CertFindCertificateInStore(m_impl->m_hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER, (void*)&b, NULL));
00530
00531 if(NULL != cert.get() && true == m_impl->CertCanBeUsedByCurrentColleague(cert))
00532 {
00533
00534 newKeyID.reset(m_impl->MakeCAPICredential(cert));
00535 }
00536
00537 CPKIFCredentialPtr rv(newKeyID.release());
00538 return rv;
00539 }
00540
00567 void CPKIFCNGCAPI::Sign(
00569 const CPKIFCredential& key,
00571 unsigned char* pHashData,
00573 int nHashDataLen,
00575 unsigned char* pSignature,
00578 int* nSignatureLen,
00580 PKIFCRYPTO::HASH_ALG hashAlg
00581 )
00582 {
00583 LOG_STRING_DEBUG("CPKIFCNGCAPI::Sign(const CPKIFCredential& key,...", TOOLKIT_CRYPTO_CAPI, 0, this);
00584
00585 NCRYPT_PROV_HANDLE_PKIF hProvider(0);
00586 NCRYPT_KEY_HANDLE_PKIF hKey(0);
00587 SECURITY_STATUS cngStatus = ERROR_SUCCESS;
00588 DWORD cbSignature = 0;
00589 BCRYPT_PKCS1_PADDING_INFO PKCS1PaddingInfo= {0};
00590
00591 NCRYPT_KEY_HANDLE hKeyPtr = 0;
00592
00593
00594
00595 int err = 0;
00596
00597
00598
00599 HCRYPTPROV tmpHashCtx = NULL;
00600 bool freeContext = false;
00601
00602
00603 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&key);
00604 if(NULL == ck2)
00605 {
00606 throw CPKIFCryptoException(thisComponent, CRYPTO_UNRECOGNIZED_CREDENTIAL, "Credential type not recognized.");
00607 }
00608
00609 if(NULL == ck2->m_keyProviderInfo)
00610 {
00611
00612 CPKIFCAPICredential2* k2 = const_cast<CPKIFCAPICredential2*>(ck2);
00613 k2->SetKeyProviderInfo();
00614 }
00615
00616
00617
00618 if(FAILED(cngStatus = NCryptOpenStorageProvider(
00619 &hProvider,
00620 MS_KEY_STORAGE_PROVIDER,
00621 0)))
00622 {
00623 std::ostringstream os;
00624 os << "NCryptOpenStorageProvider failed: " << cngStatus;
00625 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_OPEN_STORAGE_PROVIDER_FAILED, NULL);
00626 }
00627
00628 if(FAILED(cngStatus = NCryptOpenKey(
00629 hProvider,
00630 &hKey,
00631 ck2->m_keyProviderInfo->pwszContainerName,
00632 0,
00633 0)))
00634 {
00635 DWORD ks = 0;
00636 BOOL gottaFree = FALSE;
00637 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE tmpKey;
00638 if(!CryptAcquireCertificatePrivateKey(ck2->m_certContext,
00639 CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG,NULL,&tmpKey,&ks,&gottaFree))
00640 {
00641 std::ostringstream os;
00642 os << "Unable to access key material: " << cngStatus;
00643 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_OPEN_KEY_FAILED, NULL);
00644 }
00645 if(ks == CERT_NCRYPT_KEY_SPEC) {
00646 hKey.reset(tmpKey);
00647 } else {
00648 if(FAILED(cngStatus = NCryptTranslateHandle(
00649 NULL,&hKey,tmpKey,NULL,ks,0)))
00650 {
00651
00652
00653 if(gottaFree) {
00654 CryptReleaseContext(tmpKey,0);
00655 }
00656 std::ostringstream os;
00657 os << "Unable to access legacy key material from CAPING: " << cngStatus;
00658 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_OPEN_KEY_FAILED, NULL);
00659 }
00660 }
00661
00662
00663 if(!gottaFree)
00664 {
00665 hKeyPtr = hKey.release();
00666 } else {
00667 hKeyPtr = hKey.get();
00668 }
00669
00670
00671 }
00672 else
00673 {
00674 hKeyPtr = hKey.get();
00675 }
00676
00677
00678 if(NULL != ck2->m_password)
00679 {
00680 USES_CONVERSION;
00681 if( FAILED(cngStatus = NCryptSetProperty(
00682 hKeyPtr,
00683 NCRYPT_PIN_PROPERTY,
00684 ck2->m_password,
00685
00686
00687 ck2->m_nPasswordLen,
00688 0)))
00689 {
00690 std::ostringstream os;
00691 os << "CryptSetProvParam failed: " << GetLastError();
00692 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, PKIFCAPI_SET_PASSWORD_FAILED, this);
00693 }
00694
00695 }
00696
00697 LPCWSTR sHashAlg = NULL;
00698 switch(hashAlg)
00699 {
00700 case PKIFCRYPTO::SHA1:
00701 PKCS1PaddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
00702 sHashAlg = NCRYPT_SHA1_ALGORITHM;
00703 break;
00704 case PKIFCRYPTO::SHA256:
00705 PKCS1PaddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM;
00706 sHashAlg = NCRYPT_SHA256_ALGORITHM;
00707 break;
00708 case PKIFCRYPTO::SHA384:
00709 PKCS1PaddingInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM;
00710 sHashAlg = NCRYPT_SHA384_ALGORITHM;
00711 break;
00712 case PKIFCRYPTO::SHA512:
00713 PKCS1PaddingInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM;
00714 sHashAlg = NCRYPT_SHA512_ALGORITHM;
00715 break;
00716 default:
00717 std::ostringstream os;
00718 os << "Unsupported hash algorithm encountered: " << hashAlg;
00719 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00720 }
00721
00722 BCRYPT_PKCS1_PADDING_INFO * pi = 0;
00723 DWORD pflags = 0;
00724
00725
00726 DWORD algPropSize = 0;
00727 if(FAILED(cngStatus = NCryptGetProperty(hKeyPtr,NCRYPT_ALGORITHM_GROUP_PROPERTY,
00728 NULL,0,&algPropSize,0)))
00729 {
00730 RAISE_CRYPTO_EXCEPTION("Unable to obtain signature algorithm group for key", TOOLKIT_CRYPTO, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00731 }
00732 pkif_byte_array algName(new unsigned char[algPropSize]);
00733 memset(algName,0x00,algPropSize);
00734 if(FAILED(cngStatus = NCryptGetProperty(hKeyPtr,NCRYPT_ALGORITHM_GROUP_PROPERTY,
00735 algName,algPropSize,&algPropSize,0)))
00736 {
00737 RAISE_CRYPTO_EXCEPTION("Unable to obtain signature algorithm group for key", TOOLKIT_CRYPTO, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00738 }
00739 if(0 == wcscmp(NCRYPT_RSA_ALGORITHM_GROUP,(wchar_t *)algName.get()))
00740 {
00741 pi = &PKCS1PaddingInfo;
00742 pflags = BCRYPT_PAD_PKCS1;
00743 }
00744
00745 if(FAILED(cngStatus = NCryptSignHash(hKeyPtr,pi,(PBYTE)pHashData,nHashDataLen,pSignature,
00746 *nSignatureLen,&cbSignature,pflags)))
00747 {
00748 std::ostringstream os;
00749 os << "NCryptSignHash failed to sign hash: " << cngStatus;
00750 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_SIGN_HASH_FAILED, NULL);
00751 }
00752
00753 *nSignatureLen = cbSignature;
00754
00755 }
00756
00774 void CPKIFCNGCAPI::Decrypt(
00777 const CPKIFCredential& key,
00779 unsigned char* pData,
00781 int nDataLen,
00783 unsigned char* pResult,
00786 int* pnResultLen)
00787 {
00788 LOG_STRING_DEBUG("CPKIFCNGCAPI::Decrypt(const CPKIFCredential& key,...", TOOLKIT_CRYPTO_CAPI, 0, this);
00789
00790 NCRYPT_PROV_HANDLE_PKIF hProvider(0);
00791 NCRYPT_KEY_HANDLE_PKIF hKey(0);
00792 SECURITY_STATUS secStatus = ERROR_SUCCESS;
00793 DWORD cbCipherText = 0;
00794
00795 USES_CONVERSION;
00796
00797 HCRYPTPROV tmpCtx = NULL;
00798 BOOL freeContext = false;
00799
00800
00801 const CPKIFCAPICredential2* ck2 = dynamic_cast<const CPKIFCAPICredential2*>(&key);
00802 if(NULL == ck2)
00803 {
00804 throw CPKIFCryptoException(thisComponent, CRYPTO_UNRECOGNIZED_CREDENTIAL, "Credential type not recognized.");
00805 }
00806
00807 if(NULL == ck2->m_keyProviderInfo)
00808 {
00809
00810 CPKIFCAPICredential2* k2 = const_cast<CPKIFCAPICredential2*>(ck2);
00811 k2->SetKeyProviderInfo();
00812 }
00813
00814
00815 if(FAILED(secStatus = NCryptOpenStorageProvider(
00816 &hProvider,
00817 MS_KEY_STORAGE_PROVIDER,
00818 0)))
00819 {
00820 std::ostringstream os;
00821 os << "NCryptOpenStorageProvider failed: " << GetLastError();;
00822 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_OPEN_STORAGE_PROVIDER_FAILED, NULL);
00823 }
00824
00825 if(FAILED(secStatus = NCryptOpenKey(
00826 hProvider,
00827 &hKey,
00828 ck2->m_keyProviderInfo->pwszContainerName,
00829 0,
00830 0)))
00831 {
00832 std::ostringstream os;
00833 os << "NCryptOpenKey failed: " << GetLastError();;
00834 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_OPEN_KEY_FAILED, NULL);
00835 }
00836
00837 int paddingFlag = NCRYPT_PAD_PKCS1_FLAG;
00838
00839 if(FAILED(secStatus = NCryptDecrypt(
00840 hKey,
00841 (PBYTE)pData,
00842 nDataLen,
00843 NULL,
00844 NULL,
00845 0,
00846 &cbCipherText,
00847 paddingFlag)))
00848 {
00849 std::ostringstream os;
00850 os << "NCryptDecrypt failed: " << GetLastError();;
00851 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_DECRYPT_FAILED, NULL);
00852
00853 }
00854 if(FAILED(secStatus = NCryptDecrypt(
00855 hKey,
00856 (PBYTE)pData,
00857 nDataLen,
00858 NULL,
00859 pResult,
00860 *pnResultLen,
00861 &cbCipherText,
00862 paddingFlag)))
00863 {
00864 std::ostringstream os;
00865 os << "NCryptDecrypt failed: " << GetLastError();;
00866 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), TOOLKIT_CRYPTO, PKIFCAPING_DECRYPT_FAILED, NULL);
00867 }
00868 *pnResultLen = cbCipherText;
00869 }
00870
00882 void CPKIFCNGCAPI::Encrypt(
00885 const CPKIFCredential& key,
00887 unsigned char* pData,
00889 int nDataLen,
00891 unsigned char* pResult,
00894 int* pnResultLen)
00895 {
00896 LOG_STRING_DEBUG("CPKIFCNGCAPI::Encrypt(const CPKIFCredential& key, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_CAPI, 0, this);
00897
00898 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "Encrypt operations are not implemented for stored key material");
00899 }
00900
00912 bool CPKIFCNGCAPI::Verify(
00915 const CPKIFCredential& key,
00918 unsigned char* pHashData,
00920 int nHashDataLen,
00922 unsigned char* pSignature,
00924 int nSignatureLen,
00926 PKIFCRYPTO::HASH_ALG hashAlg
00927 )
00928 {
00929 LOG_STRING_DEBUG("CPKIFCNGCAPI::Verify(const CPKIFCredential& key, unsigned char* pHashData, int nHashDataLen, unsigned char* pSignature, int nSignatureLen)", TOOLKIT_CRYPTO_CAPI, 0, this);
00930
00931 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "Verify operations are not implemented for stored key material");
00932 }
00933
00952 IPKIFCryptContext* CPKIFCNGCAPI::CryptInit(
00955 CPKIFCredentialPtr& key,
00957 bool pad)
00958 {
00959 LOG_STRING_DEBUG("CPKIFCNGCAPI::CryptInit(CPKIFCredentialPtr& key)", TOOLKIT_CRYPTO_CAPI, 0, this);
00960
00961 RAISE_CRYPTO_EXCEPTION("Context-based operations are unimplemented for CNG stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
00962 return 0;
00963
00964 }
00965
00982 void CPKIFCNGCAPI::Decrypt(
00985 IPKIFCryptContext* cryptContext,
00987 unsigned char* pData,
00989 int nDataLen,
00991 unsigned char* pResult,
00994 int* pnResultLen,
00997 bool final)
00998 {
00999 LOG_STRING_DEBUG("CPKIFCNGCAPI::Decrypt(IPKIFCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)", TOOLKIT_CRYPTO_CAPI, 0, this);
01000 RAISE_CRYPTO_EXCEPTION("Context-based operations are unimplemented for CNG stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
01001 }
01002
01013 void CPKIFCNGCAPI::Encrypt(
01016 IPKIFCryptContext* cryptContext,
01018 unsigned char* pData,
01020 int nDataLen,
01022 unsigned char* pResult,
01025 int* pnResultLen,
01028 bool final)
01029 {
01030 LOG_STRING_DEBUG("CPKIFCNGCAPI::Encrypt(IPKIFCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)", TOOLKIT_CRYPTO_CAPI, 0, this);
01031 RAISE_CRYPTO_EXCEPTION("Context-based operations are unimplemented for CNG stored key material.",thisComponent,COMMON_NOT_IMPLEMENTED,this);
01032 }
01033
01034
01035
01049 IPKIFKeyAgreeContextPtr CPKIFCNGCAPI::SecretAgree(
01052 CPKIFCredentialPtr& myPrivateKey,
01054 const CPKIFCertificatePtr& theirCert,
01056 const CPKIFAlgorithm * alg)
01057 {
01058 LOG_STRING_DEBUG("SecretAgree(CPKIFCredentialPtr& myPrivateKey, const CPKIFCertificatePtr& theirCert,const CPKIFAlgorithm * alg)", TOOLKIT_CRYPTO_CAPI, 0, this);
01059
01060 CPKIFCryptoPPKeyMaterialPtr km(new CPKIFCryptoPPKeyMaterial(*theirCert));
01061 CPKIFBufferPtr rawKey = km->GetRawSPKI();
01062 return SecretAgree(myPrivateKey, rawKey, alg);
01063 }
01064
01082 IPKIFKeyAgreeContextPtr CPKIFCNGCAPI::SecretAgree(
01085 CPKIFCredentialPtr& myPrivateKey,
01089 const CPKIFBufferPtr& theirPublicKey,
01091 const CPKIFAlgorithm * alg)
01092 {
01093 IPKIFKeyAgreeContextPtr rv;
01094 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "Not yet implemented.");
01095 return rv;
01096 }
01097
01098
01113 IPKIFKeyAgreeContextPtr CPKIFCNGCAPI::SecretAgree(
01115 const CPKIFCredentialPtr& myPrivateKey,
01117 CPKIFCredentialPtr & ephemeralKeyPair,
01119 const CPKIFCertificatePtr& theirCert,
01121 const CPKIFAlgorithm * alg)
01122 {
01123 IPKIFKeyAgreeContextPtr rv;
01124 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "CNG does not provide authenticated key agreement.");
01125 return rv;
01126 }
01127
01145 IPKIFKeyAgreeContextPtr CPKIFCNGCAPI::SecretAgree(
01147 const CPKIFCredentialPtr& myPrivateKey,
01149 CPKIFCredentialPtr & ephemeralKeyPair,
01151 const CPKIFBufferPtr& theirPublicKey,
01153 const CPKIFAlgorithm * alg)
01154 {
01155 IPKIFKeyAgreeContextPtr rv;
01156 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "CNG does not provide authenticated key agreement.");
01157 return rv;
01158 }
01159
01160
01161
01177 IPKIFKeyAgreeContextPtr CPKIFCNGCAPI::SecretAgree(
01179 const CPKIFCredentialPtr& myPrivateKey,
01182 const CPKIFBufferPtr& ephemeralPublicKey,
01184 const CPKIFCertificatePtr& theirCert,
01186 const CPKIFAlgorithm * alg)
01187 {
01188 IPKIFKeyAgreeContextPtr rv;
01189 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "CNG does not provide authenticated key agreement.");
01190 return rv;
01191 }
01192
01211 IPKIFKeyAgreeContextPtr CPKIFCNGCAPI::SecretAgree(
01213 const CPKIFCredentialPtr& myPrivateKey,
01216 const CPKIFBufferPtr& ephemeralPublicKey,
01218 const CPKIFBufferPtr& theirPublicKey,
01220 const CPKIFAlgorithm * alg)
01221 {
01222 IPKIFKeyAgreeContextPtr rv;
01223 throw CPKIFCryptoException(thisComponent, COMMON_NOT_IMPLEMENTED, "CNG does not provide authenticated key agreement.");
01224 return rv;
01225 }
01226
01235 CPKIFKeyMaterialPtr CPKIFCNGCAPI::DeriveKey(
01237 const IPKIFKeyAgreeContextPtr & context,
01239 unsigned long keyLen
01240 )
01241 {
01242 CPKIFKeyMaterialPtr key;
01243 return key;
01244 }