00001
00010 #include "PKIFCryptoPPRaw.h"
00011 #include "PKIFCryptoPPRawContext.h"
00012 #include "PKIFCryptoPPUtils.h"
00013
00014 #include "PKIFCryptoException.h"
00015 #include "PKIFKeyMaterial.h"
00016 #include "SubjectPublicKeyInfo.h"
00017 #include "PKIFAlgorithm.h"
00018
00019 #include "ToolkitUtils.h"
00020 #include "PKIFCryptoPPErrors.h"
00021 #include "PKIFCryptoErrors.h"
00022 #include "Certificate.h"
00023 #include "Buffer.h"
00024
00025 #include "PKIFCryptUtils.h"
00026
00027 #include "PKIFCryptoPPKeyMaterial.h"
00028
00029 #include <sstream>
00030
00031 #include "boost/numeric/conversion/cast.hpp"
00032
00033 #include "cryptlib.h"
00034 #include "pubkey.h"
00035 #include "sha.h"
00036 #include "queue.h"
00037 #include "osrng.h"
00038 #include "rsa.h"
00039 #include "dsa.h"
00040 #include "eccrypto.h"
00041 #include "asn.h"
00042 #include "dsa.h"
00043 #include "modes.h"
00044 #include "aes.h"
00045 #include "hmac.h"
00046 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
00047 #include "md5.h"
00048
00049 #include "PKIFCryptoPPExternalDigest.h"
00050
00051 using namespace CryptoPP;
00052
00053 template<bool _CryptDirection>
00054 static void _ASymCrypt(const CPKIFKeyMaterial& key, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool pad = true);
00055
00056
00057
00066 CPKIFCryptoPPRaw::CPKIFCryptoPPRaw(void)
00067 {
00068 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::CPKIFCryptoPPRaw(void)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00069 }
00077 CPKIFCryptoPPRaw::~CPKIFCryptoPPRaw(void)
00078 {
00079 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::~CPKIFCryptoPPRaw(void)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00080 }
00088 void CPKIFCryptoPPRaw::Initialize()
00089 {
00090 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::Initialize()", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00091 }
00103 bool CPKIFCryptoPPRaw::SupportsAlgorithm(
00105 const CPKIFKeyMaterial& key)
00106 {
00107 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::SupportsAlgorithm(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00108 if(key.ContainsSymmetricKeyMaterial())
00109 {
00110 try
00111 {
00112 switch(key.GetSymmetricKeyAlgorithm()) {
00113 case PKIFCRYPTO::AES:
00114 case PKIFCRYPTO::AES128:
00115 case PKIFCRYPTO::AES192:
00116 case PKIFCRYPTO::AES256:
00117
00118 return true;
00119 break;
00120 default:
00121 return false;
00122 break;
00123 }
00124 }
00125 catch(CPKIFCryptoException& e)
00126 {
00127 if(CRYPTO_ALG_NOT_SUPPORTED == e.GetErrorCode())
00128 {
00129
00130
00131
00132
00133 return false;
00134 }
00135 else
00136 throw e;
00137 }
00138 } else {
00139 CPKIFSubjectPublicKeyInfoPtr spki = key.GetSubjectPublicKeyInfo();
00140 if(!spki) {
00141 CPKIFCryptoPPKeyMaterialPtr cppKM(new CPKIFCryptoPPKeyMaterial(key));
00142 spki = cppKM->GetSubjectPublicKeyInfo();
00143 }
00144 if(!spki) return false;
00145 CPKIFAlgorithm * alg = CPKIFAlgorithm::GetAlg(spki->alg()->oid());
00146 switch(alg->AsymkeyAlg()) {
00147 case PKIFCRYPTO::RSA:
00148 case PKIFCRYPTO::ECC:
00149 case PKIFCRYPTO::DSS:
00150 return true;
00151 break;
00152 default:
00153 return false;
00154 }
00155 }
00156 return false;
00157 }
00168 void CPKIFCryptoPPRaw::Sign(
00170 const CPKIFKeyMaterial& key,
00172 unsigned char* pHashData,
00174 int nHashDataLen,
00176 unsigned char* pSignature,
00179 int* nSignatureLen,
00181 PKIFCRYPTO::HASH_ALG hashAlg)
00182 {
00183 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::Sign(const CPKIFKeyMaterial& key,...)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00184
00185 RAISE_CRYPTO_EXCEPTION("Signing operations are not implemented for raw key material.", thisComponent, COMMON_NOT_IMPLEMENTED, this);
00186 }
00187
00195 void CPKIFCryptoPPRaw::Decrypt(
00197 const CPKIFKeyMaterial& key,
00199 unsigned char* pData,
00201 int nDataLen,
00203 unsigned char* pResult,
00206 int* pnResultLen,
00210 bool pad)
00211 {
00212 if(key.ContainsSymmetricKeyMaterial()) {
00213 CPKIFCryptoPPRawContext * ctx = static_cast<CPKIFCryptoPPRawContext *>(this->CryptInit(key,pad));
00214 try {
00215 Decrypt(ctx,pData,nDataLen,pResult,pnResultLen,true);
00216 } catch(...) {
00217 delete ctx;
00218 throw;
00219 }
00220 delete ctx;
00221 } else {
00222 _ASymCrypt<false>(key, pData, nDataLen, pResult, pnResultLen, pad);
00223 }
00224 }
00232 void CPKIFCryptoPPRaw::Encrypt(
00234 const CPKIFKeyMaterial& key,
00236 unsigned char* pData,
00238 int nDataLen,
00240 unsigned char* pResult,
00243 int* pnResultLen,
00247 bool pad)
00248 {
00249 if(key.ContainsSymmetricKeyMaterial()) {
00250 CPKIFCryptoPPRawContext * ctx = static_cast<CPKIFCryptoPPRawContext *>(this->CryptInit(key,pad));
00251 try {
00252 Encrypt(ctx,pData,nDataLen,pResult,pnResultLen,true);
00253 } catch(...) {
00254 delete ctx;
00255 throw;
00256 }
00257 delete ctx;
00258 } else {
00259 _ASymCrypt<true>(key, pData, nDataLen, pResult, pnResultLen, pad);
00260 }
00261 }
00262
00280 IPKIFRawCryptContext* CPKIFCryptoPPRaw::HMACInit(const CPKIFKeyMaterial &key, PKIFCRYPTO::HASH_ALG ha)
00281 {
00282 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::HMACInit(const CPKIFKeyMaterial& key, HASH_ALG ha)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00283
00284 if(!key.ContainsSymmetricKeyMaterial())
00285 {
00286 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, "HMACInit() only makes sense for symmetric keys.");
00287 }
00288
00289 CPKIFCryptoPPRawContext * ctx = new CPKIFCryptoPPRawContext();
00290 try {
00291 switch(ha) {
00292 case PKIFCRYPTO::SHA1:
00293 ctx->m_hashCtx = new HMAC<CryptoPP::SHA1>(key.GetSymmetricKey(),key.GetSymmetricKeyLength());
00294 break;
00295 #if !defined(FIPS_MODE)
00296 case PKIFCRYPTO::MD5:
00297 ctx->m_hashCtx = new HMAC<CryptoPP::Weak::MD5>(key.GetSymmetricKey(),key.GetSymmetricKeyLength());
00298 break;
00299 #endif
00300 case PKIFCRYPTO::SHA224:
00301 ctx->m_hashCtx = new HMAC<CryptoPP::SHA224>(key.GetSymmetricKey(),key.GetSymmetricKeyLength());
00302 break;
00303 case PKIFCRYPTO::SHA256:
00304 ctx->m_hashCtx = new HMAC<CryptoPP::SHA256>(key.GetSymmetricKey(),key.GetSymmetricKeyLength());
00305 break;
00306 case PKIFCRYPTO::SHA384:
00307 ctx->m_hashCtx = new HMAC<CryptoPP::SHA384>(key.GetSymmetricKey(),key.GetSymmetricKeyLength());
00308 break;
00309 case PKIFCRYPTO::SHA512:
00310 ctx->m_hashCtx = new HMAC<CryptoPP::SHA512>(key.GetSymmetricKey(),key.GetSymmetricKeyLength());
00311 break;
00312 default:
00313 std::ostringstream os;
00314 os << "Unsupported hash algorithm encountered: " << ha;
00315 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00316 break;
00317 }
00318 }catch(CryptoPP::Exception &) {
00319 RAISE_CRYPTO_EXCEPTION("Invalid key material for HMAC algorithm", thisComponent, COMMON_INVALID_INPUT, NULL);
00320 }
00321
00322 return ctx;
00323 }
00324
00336 void CPKIFCryptoPPRaw::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)
00337 {
00338 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::HMACUpdate(IPKIFRawCryptContext* ctx, unsigned char* pData, int nDataLen)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00339
00340
00341
00342
00343 if(NULL == ctx || 0 > nDataLen)
00344 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HMACUpdate.");
00345
00346
00347
00348 CPKIFCryptoPPRawContext* ictx = dynamic_cast<CPKIFCryptoPPRawContext*>(ctx);
00349 if(NULL == ictx)
00350 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Incorrect context passed to HMACUpdate.");
00351
00352 if(NULL == ictx->m_hashCtx)
00353 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_EMPTY_HASH_CONTEXT, "Empty context passed to HMACUpdate.");
00354 if(nDataLen) ictx->m_hashCtx->Update(pData,nDataLen);
00355 }
00356
00369 void CPKIFCryptoPPRaw::HMACFinal(IPKIFRawCryptContext* ctx, unsigned char* pResult, int* pnResultLen)
00370 {
00371 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::HMACFinal(IPKIFRawContext* ctx, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00372
00373
00374
00375
00376
00377 if(NULL == ctx || NULL == pResult || NULL == pnResultLen || 0 >= *pnResultLen)
00378 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HMACFinal.");
00379
00380 CPKIFCryptoPPRawContext* hmacCtx = dynamic_cast<CPKIFCryptoPPRawContext*>(ctx);
00381 if(NULL == hmacCtx)
00382 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Incorrect context passed to HMACFinal().");
00383
00384 if(NULL == hmacCtx->m_hashCtx)
00385 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_EMPTY_HASH_CONTEXT, "Empty context passed to HMACFinal().");
00386 try {
00387 if(hmacCtx->m_hashCtx->DigestSize() > boost::numeric_cast<unsigned int, int>(*pnResultLen))
00388 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Mismatch between buffer size and hash context passed to HashFinal.");
00389 }catch( boost::numeric::bad_numeric_cast & ) {
00390 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Comparison error between buffer size and hash context passed to HashFinal.");
00391 }
00392
00393 hmacCtx->m_hashCtx->Final(pResult);
00394 *pnResultLen = hmacCtx->m_hashCtx->DigestSize();
00395
00396 }
00397
00398
00410 static bool _Verify(
00412 const CPKIFKeyMaterial& key,
00415 unsigned char* pHashData,
00417 int nHashDataLen,
00419 unsigned char* pSignature,
00421 int nSignatureLen,
00423 PKIFCRYPTO::HASH_ALG hashAlg
00424 )
00425 {
00426 LOG_STRING_DEBUG("_Verify(const CPKIFKeyMaterial& key, unsigned char* pHashData, int nHashDataLen, unsigned char* pSignature, int nSignatureLen)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, NULL);
00427 CPKIFCryptoPPKeyMaterial * km = 0;
00428 km = dynamic_cast<CPKIFCryptoPPKeyMaterial *>(const_cast<CPKIFKeyMaterial *>(&key));
00429
00430
00431
00432 CPKIFCryptoPPKeyMaterialPtr kmp;
00433 if(!km) {
00434 try {
00435 kmp = CPKIFCryptoPPKeyMaterialPtr(new CPKIFCryptoPPKeyMaterial(key));
00436 }catch(CPKIFException &){
00437
00438 kmp = CPKIFCryptoPPKeyMaterialPtr((CPKIFCryptoPPKeyMaterial *)0);
00439 }
00440 km = kmp.get();
00441 }
00442
00443 if(!km)
00444 {
00445 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00446 }
00447
00448 CPKIFBufferPtr spkiBuf = km->GetRawSPKI();
00449 ByteQueue keyReader;
00450 keyReader.Put(spkiBuf->GetBuffer(), spkiBuf->GetLength());
00451
00452 PK_Verifier * verifier = 0;
00453 const CPKIFAlgorithm * alg = km->GetKeyAlg();
00454 bool isDSA = false;
00455 switch(alg->AsymkeyAlg()) {
00456 case PKIFCRYPTO::RSA:
00457 switch(hashAlg) {
00458 case PKIFCRYPTO::SHA1:
00459 verifier = new RSASS<PKCS1v15,CryptoPP::SHA1>::Verifier(keyReader);
00460 break;
00461 case PKIFCRYPTO::SHA256:
00462 verifier = new RSASS<PKCS1v15,CryptoPP::SHA256>::Verifier(keyReader);
00463 break;
00464 case PKIFCRYPTO::SHA384:
00465 verifier = new RSASS<PKCS1v15,CryptoPP::SHA384>::Verifier(keyReader);
00466 break;
00467 case PKIFCRYPTO::SHA512:
00468 verifier = new RSASS<PKCS1v15,CryptoPP::SHA512>::Verifier(keyReader);
00469 break;
00470 default:
00471 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00472 break;
00473 }
00474 break;
00475 case PKIFCRYPTO::ECC:
00476 isDSA = true;
00477 switch(hashAlg) {
00478 case PKIFCRYPTO::SHA1:
00479 verifier = new ECDSA<ECP,CryptoPP::SHA1>::Verifier(keyReader);
00480 break;
00481 case PKIFCRYPTO::SHA256:
00482 verifier = new ECDSA<ECP,CryptoPP::SHA256>::Verifier(keyReader);
00483 break;
00484 case PKIFCRYPTO::SHA384:
00485 verifier = new ECDSA<ECP,CryptoPP::SHA384>::Verifier(keyReader);
00486 break;
00487 case PKIFCRYPTO::SHA512:
00488 verifier = new ECDSA<ECP,CryptoPP::SHA512>::Verifier(keyReader);
00489 break;
00490 default:
00491 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00492 break;
00493 }
00494 break;
00495 case PKIFCRYPTO::DSS:
00496
00497
00498
00499 if(!km->HasParams())
00500 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_RAW_IMPORT_FAILED);
00501 isDSA = true;
00502 switch(hashAlg) {
00503 case PKIFCRYPTO::SHA1:
00504 verifier = new DSA::Verifier(keyReader);
00505 break;
00506 default:
00507 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00508 break;
00509 }
00510 break;
00511 default:
00512 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00513 break;
00514 }
00515
00516 PKIFCryptoPPExternalDigestAccumulator * ed = NewEDAccumulator(pHashData,nHashDataLen);
00517 if(!isDSA) {
00518 verifier->InputSignature(*ed,pSignature,nSignatureLen);
00519 }else{
00520
00521
00522 size_t targetLen = verifier->SignatureLength();
00523 unsigned char * converted = new unsigned char[targetLen];
00524 try {
00525 targetLen = DSAConvertSignatureFormat(converted,targetLen,DSA_P1363,pSignature,nSignatureLen,DSA_DER);
00526 }catch(BERDecodeErr &){
00527
00528 delete[] converted;
00529 converted = 0;
00530 }
00531 if(converted) {
00532 verifier->InputSignature(*ed,converted,targetLen);
00533 delete[] converted;
00534 converted = 0;
00535 } else {
00536 verifier->InputSignature(*ed,pSignature,nSignatureLen);
00537 }
00538 }
00539 bool verified = verifier->Verify(ed);
00540 delete verifier;
00541 return verified;
00542 }
00551 bool CPKIFCryptoPPRaw::VerifyCertificate(
00554 const CPKIFCertificate& issCert,
00557 const CPKIFCertificate& subCert)
00558 {
00559 CPKIFCryptoPPKeyMaterial issKey(issCert);
00560
00561
00562
00563 CPKIFBufferPtr tbsCertificate = GetTBSCertSequence(subCert);
00564 CPKIFAlgorithm * sigAlg = CPKIFAlgorithm::GetAlg(subCert.SignatureAlgorithm()->oid());
00565 if(!sigAlg) {
00566 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00567 }
00568 IPKIFHashContext * dig = HashInit(sigAlg->HashAlg());
00569 boost::shared_ptr<IPKIFHashContext> digPtr(dig);
00570 HashUpdate(digPtr.get(),const_cast<unsigned char *>(tbsCertificate->GetBuffer()),tbsCertificate->GetLength());
00571 int hashLen = CPKIFAlgorithm::GetAlg(sigAlg->HashAlg())->DigestSize();
00572 unsigned char * hashVal = new unsigned char[hashLen];
00573
00574 CPKIFBufferPtr hashBuf(new CPKIFBuffer(true,hashVal,hashLen));
00575 HashFinal(digPtr.get(),hashVal,&hashLen);
00576 CPKIFBufferPtr sigBuf = subCert.Signature();
00577 return _Verify(issKey,hashVal,hashLen,const_cast<unsigned char *>(sigBuf->GetBuffer()),sigBuf->GetLength(),
00578 sigAlg->HashAlg());
00579 }
00580
00581 bool VerifyCertificateWithCryptoPP(CPKIFSubjectPublicKeyInfoPtr& spki, const CPKIFCertificate& subCert)
00582 {
00583 CPKIFCryptoPPKeyMaterial issKey(spki);
00584
00585
00586
00587 CPKIFBufferPtr tbsCertificate = GetTBSCertSequence(subCert);
00588 CPKIFAlgorithm * sigAlg = CPKIFAlgorithm::GetAlg(subCert.SignatureAlgorithm()->oid());
00589 if(!sigAlg) {
00590 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00591 }
00592
00593 IPKIFCryptoMisc* cm = GetPlatformCryptoMisc();
00594
00595 IPKIFHashContext * dig = cm->HashInit(sigAlg->HashAlg());
00596 boost::shared_ptr<IPKIFHashContext> digPtr(dig);
00597 cm->HashUpdate(digPtr.get(),const_cast<unsigned char *>(tbsCertificate->GetBuffer()),tbsCertificate->GetLength());
00598 int hashLen = CPKIFAlgorithm::GetAlg(sigAlg->HashAlg())->DigestSize();
00599 unsigned char * hashVal = new unsigned char[hashLen];
00600
00601 CPKIFBufferPtr hashBuf(new CPKIFBuffer(true,hashVal,hashLen));
00602 cm->HashFinal(digPtr.get(),hashVal,&hashLen);
00603 CPKIFBufferPtr sigBuf = subCert.Signature();
00604 return _Verify(issKey,hashVal,hashLen,const_cast<unsigned char *>(sigBuf->GetBuffer()),sigBuf->GetLength(),
00605 sigAlg->HashAlg());
00606 }
00607
00618 bool CPKIFCryptoPPRaw::Verify(
00620 const CPKIFKeyMaterial& key,
00622 unsigned char* pHashData,
00624 int nHashDataLen,
00626 unsigned char* pSignature,
00628 int nSignatureLen,
00630 PKIFCRYPTO::HASH_ALG hashAlg)
00631 {
00632
00633 return _Verify(key, pHashData, nHashDataLen, pSignature, nSignatureLen, hashAlg);
00634 }
00645 void CPKIFCryptoPPRaw::GenRandom(
00647 unsigned char* buf,
00649 int len)
00650 {
00651 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::GenRandom(unsigned char* buf, int len)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00652
00653 if(NULL == buf || 0 == len)
00654 return;
00655
00656 if(len && !buf)
00657 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL output buffer passed to GenRandom.");
00658
00659
00660 AutoSeededRandomPool rng;
00661 rng.GenerateBlock(buf,len);
00662
00663 }
00677 IPKIFHashContext* CPKIFCryptoPPRaw::HashInit(
00680 PKIFCRYPTO::HASH_ALG alg)
00681 {
00682 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::HashInit(HASH_ALG alg)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00683
00684
00685
00686 CPKIFCryptoPPRawContext* hashCtx = new CPKIFCryptoPPRawContext();
00687 switch(alg)
00688 {
00689 case PKIFCRYPTO::SHA1:
00690 hashCtx->m_hashCtx = new CryptoPP::SHA1();
00691 break;
00692 #ifndef FIPS_MODE
00693 case PKIFCRYPTO::MD5:
00694 hashCtx->m_hashCtx = new CryptoPP::Weak::MD5();
00695 break;
00696 #endif
00697 case PKIFCRYPTO::SHA224:
00698 hashCtx->m_hashCtx = new CryptoPP::SHA224();
00699 break;
00700 case PKIFCRYPTO::SHA256:
00701 hashCtx->m_hashCtx = new CryptoPP::SHA256();
00702 break;
00703 case PKIFCRYPTO::SHA384:
00704 hashCtx->m_hashCtx = new CryptoPP::SHA384();
00705 break;
00706 case PKIFCRYPTO::SHA512:
00707 hashCtx->m_hashCtx = new CryptoPP::SHA512();
00708 break;
00709 default:
00710 std::ostringstream os;
00711 os << "Unsupported hash algorithm encountered: " << alg;
00712 RAISE_CRYPTO_EXCEPTION(os.str().c_str(), thisComponent, CRYPTO_ALG_NOT_SUPPORTED, NULL);
00713 }
00714 return hashCtx;
00715 }
00728 void CPKIFCryptoPPRaw::HashUpdate(
00730 IPKIFHashContext* hash,
00732 unsigned char* pData,
00734 int nDataLen)
00735 {
00736 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::HashUpdate(IPKIFHashContext* hash, unsigned char* pData, int nDataLen)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00737
00738
00739
00740
00741 if(0 == hash || 0 > nDataLen)
00742 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HashUpdate.");
00743
00744
00745
00746 CPKIFCryptoPPRawContext* hashCtx = dynamic_cast<CPKIFCryptoPPRawContext*>(hash);
00747 if(0 == hashCtx)
00748 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Incorrect hash context passed to HashUpdate.");
00749
00750 if(0 == hashCtx->m_hashCtx)
00751 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_EMPTY_HASH_CONTEXT, "Empty hash context passed to HashUpdate.");
00752
00753 hashCtx->m_hashCtx->Update(pData, nDataLen);
00754
00755 }
00768 void CPKIFCryptoPPRaw::HashFinal(
00770 IPKIFHashContext* hash,
00772 unsigned char* pResult,
00775 int* pnResultLen)
00776 {
00777 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::HashFinal(IPKIFHashContext* hash, unsigned char* pResult, int* pnResultLen)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00778
00779
00780
00781
00782
00783 if(NULL == hash || NULL == pResult || NULL == pnResultLen || 0 >= *pnResultLen)
00784 throw CPKIFCryptoException(thisComponent, COMMON_INVALID_INPUT, "NULL input passed to HashFinal.");
00785
00786 CPKIFCryptoPPRawContext* hashCtx = dynamic_cast<CPKIFCryptoPPRawContext*>(hash);
00787 if(NULL == hashCtx)
00788 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Incorrect hash context passed to HashFinal.");
00789
00790 if(NULL == hashCtx->m_hashCtx)
00791 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_EMPTY_HASH_CONTEXT, "Empty hash context passed to HashUpdate.");
00792 try {
00793 if(hashCtx->m_hashCtx->DigestSize() > boost::numeric_cast<unsigned int,int>(*pnResultLen))
00794 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Mismatch between buffer size and hash context passed to HashFinal.");
00795 }catch( boost::numeric::bad_numeric_cast & ) {
00796 throw CPKIFCryptoException(thisComponent, PKIFCRYPTOPP_INCORRECT_HASH_CONTEXT, "Comparison error between buffer size and hash context passed to HashFinal.");
00797 }
00798
00799 hashCtx->m_hashCtx->Final(pResult);
00800 *pnResultLen = hashCtx->m_hashCtx->DigestSize();
00801 }
00802
00818 IPKIFRawCryptContext* CPKIFCryptoPPRaw::CryptInit(
00821 const CPKIFKeyMaterial& key,
00823 bool pad)
00824 {
00825 LOG_STRING_DEBUG("CPKIFCryptoPPRaw::CryptInit(const CPKIFKeyMaterial& key)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, this);
00826
00827
00828 if(!key.ContainsSymmetricKeyMaterial()) {
00829 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, "CryptInit() only makes sense for symmetric keys.");
00830 }
00831
00832 if(key.GetMode() == PKIFCRYPTO::CBC && NULL == key.GetIV()) {
00833 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, CRYPTO_MISSING_IV);
00834 }
00835
00836 switch(key.GetSymmetricKeyAlgorithm()) {
00837 case PKIFCRYPTO::AES:
00838 case PKIFCRYPTO::AES128:
00839 case PKIFCRYPTO::AES192:
00840 case PKIFCRYPTO::AES256:
00841 break;
00842 default:
00843 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, PKIF_CRYPTOPP_UNSUPPORTED_ALG);
00844 }
00845
00846
00847 CPKIFCryptoPPRawContext * ctx = new CPKIFCryptoPPRawContext();
00848
00849 ctx->m_keyLen = key.GetSymmetricKeyLength();
00850 ctx->m_rawKey = new unsigned char[ctx->m_keyLen];
00851 memcpy(ctx->m_rawKey, key.GetSymmetricKey(), ctx->m_keyLen);
00852 if(NULL != key.GetIV())
00853 {
00854 ctx->m_ivLen = CPKIFAlgorithm::GetAlg(key.GetSymmetricKeyAlgorithm())->BlockSize();
00855 ctx->m_iv = new unsigned char[ctx->m_ivLen];
00856 memcpy(ctx->m_iv, key.GetIV(), ctx->m_ivLen);
00857 }
00858 ctx->m_keyMode = key.GetMode();
00859 ctx->m_keyAlgorithm = key.GetSymmetricKeyAlgorithm();
00860
00861
00862 ctx->m_bNeedsPad = pad;
00863
00864
00865
00866 return ctx;
00867 }
00876 void CPKIFCryptoPPRaw::Decrypt(
00879 IPKIFRawCryptContext* cryptContext,
00881 unsigned char* pData,
00883 int nDataLen,
00885 unsigned char* pResult,
00888 int* pnResultLen,
00891 bool final)
00892 {
00893 CryptFunc<false>(cryptContext, pData, nDataLen, pResult, pnResultLen, final);
00894 }
00903 void CPKIFCryptoPPRaw::Encrypt(
00906 IPKIFRawCryptContext* cryptContext,
00908 unsigned char* pData,
00910 int nDataLen,
00912 unsigned char* pResult,
00915 int* pnResultLen,
00918 bool final)
00919 {
00920 CryptFunc<true>(cryptContext, pData, nDataLen, pResult, pnResultLen, final);
00921 }
00933 template <bool _CryptDirection>
00934 void CPKIFCryptoPPRaw::CryptFunc(
00937 IPKIFRawCryptContext* cryptContext,
00939 unsigned char* pData,
00941 int nDataLen,
00943 unsigned char* pResult,
00945 int* pnResultLen,
00948 bool final)
00949 {
00950 LOG_STRING_DEBUG("CPKIFCryptoPPRaw CryptFunc(IPKIFRawCryptContext* cryptContext, unsigned char* pData, int nDataLen, unsigned char* pResult, int* pnResultLen, bool final)", TOOLKIT_CRYPTO_CRYPTOPPRAW, 0, NULL);
00951
00952 CPKIFCryptoPPRawContext* icc = dynamic_cast<CPKIFCryptoPPRawContext*>(cryptContext);
00953 if(!icc)
00954 {
00955 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPPRaw CryptFunc called with an invalid context.", TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, NULL);
00956 }
00957
00958
00959 if(!icc->m_ctx)
00960 {
00961 SymmetricCipher * cipher = 0;
00962 int keyLen = icc->m_keyLen;
00963 const unsigned char * rawKey = icc->m_rawKey;
00964 int ivLen = CPKIFAlgorithm::GetAlg(icc->m_keyAlgorithm)->BlockSize();
00965 const unsigned char * iv = icc->m_iv;
00966
00967 switch(icc->m_keyAlgorithm) {
00968 case PKIFCRYPTO::AES:
00969 case PKIFCRYPTO::AES128:
00970 case PKIFCRYPTO::AES192:
00971 case PKIFCRYPTO::AES256:
00972 try {
00973 switch(icc->m_keyMode) {
00974 case PKIFCRYPTO::CBC:
00975 if(_CryptDirection){
00976 cipher = new CBC_Mode<CryptoPP::AES>::Encryption(rawKey,keyLen,iv);
00977 } else {
00978 cipher = new CBC_Mode<CryptoPP::AES>::Decryption(rawKey,keyLen,iv);
00979 }
00980 break;
00981 case PKIFCRYPTO::ECB:
00982 if(_CryptDirection){
00983 cipher = new ECB_Mode<CryptoPP::AES>::Encryption(rawKey,keyLen);
00984 } else {
00985 cipher = new ECB_Mode<CryptoPP::AES>::Decryption(rawKey,keyLen);
00986 }
00987 break;
00988 case PKIFCRYPTO::CTR:
00989 if(_CryptDirection){
00990 cipher = new CTR_Mode<CryptoPP::AES>::Encryption(rawKey,keyLen,iv);
00991 } else {
00992 cipher = new CTR_Mode<CryptoPP::AES>::Decryption(rawKey,keyLen,iv);
00993 }
00994 break;
00995 default:
00996 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPPRaw CryptFunc called with an invalid context.", TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, NULL);
00997 break;
00998 }
00999 }catch(CryptoPP::Exception &) {
01000 RAISE_CRYPTO_EXCEPTION("Crypto++ key material did not match cipher and mode",TOOLKIT_CRYPTO_CRYPTOPPRAW,COMMON_INVALID_INPUT, NULL);
01001 }catch(CPKIFException &) {
01002 throw;
01003 }catch(...){
01004 RAISE_CRYPTO_EXCEPTION("Unknown error setting up crypto context. Most likely improperly initialized key material.",
01005 TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, NULL);
01006 }
01007 break;
01008 default:
01009 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPPRaw CryptFunc called with an invalid context.", TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, NULL);
01010 break;
01011
01012 }
01013
01014 icc->m_ctx = new StreamTransformationFilter(*cipher, new ByteQueue(),
01015 icc->m_bNeedsPad ? CryptoPP::StreamTransformationFilter::DEFAULT_PADDING :
01016 CryptoPP::StreamTransformationFilter::NO_PADDING);
01017 }
01018 try {
01019 if(nDataLen > 0) {
01020 icc->m_ctx->Put(pData,nDataLen);
01021 }
01022 if(final) {
01023 icc->m_ctx->MessageEnd();
01024 }
01025 }catch(CryptoPP::Exception & e){
01026
01027 RAISE_CRYPTO_EXCEPTION(e.what(),TOOLKIT_CRYPTO_CRYPTOPPRAW,COMMON_INVALID_INPUT,NULL);
01028 }
01029 ByteQueue * outTrans = dynamic_cast<ByteQueue *>(icc->m_ctx->AttachedTransformation());
01030
01031
01032 int avail = static_cast<int>(outTrans->MaxRetrievable());
01033 if(avail > 0) {
01034 outTrans->Get(pResult,*pnResultLen);
01035 if(*pnResultLen > avail) *pnResultLen = avail;
01036 if(final && outTrans->MaxRetrievable() > 0)
01037 RAISE_CRYPTO_EXCEPTION("CPKIFCryptoPPRaw CryptFunc (finalize) called with a buffer that's too small for the output.",
01038 TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_INVALID_INPUT, NULL);
01039 }
01040 }
01041
01052 template<bool _CryptDirection>
01053 void _ASymCrypt(
01055 const CPKIFKeyMaterial& key,
01057 unsigned char* pData,
01059 int nDataLen,
01061 unsigned char* pResult,
01063 int* pnResultLen,
01065 bool pad)
01066 {
01067 throw CPKIFCryptoException(TOOLKIT_CRYPTO_CRYPTOPPRAW, COMMON_NOT_IMPLEMENTED, "The crypto++ raw colleague does not currently support asymmetric encryption operations.");
01068 }