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 }