00001
00009 #include "ParallelHash.h"
00010 #include "ToolkitUtils.h"
00011 #include "components.h"
00012 #include "PKIFCommonErrors.h"
00013 #include "PKIFMessageException.h"
00014 #include "AlgorithmIdentifier.h"
00015 #include "OID.h"
00016 #include "Buffer.h"
00017 #include "IPKIFCryptoMisc.h"
00018 #include "IPKIFHashContext.h"
00019 #include "PKIFMessageErrors.h"
00020 #include "ASN1Helper.h"
00021 #include "PKIFAlgorithm.h"
00022
00023 #include "private/PrivatePKIFCMSUtils.h"
00024 #include "CryptographicMessageSyntax2004.h"
00025
00026 using namespace std;
00027
00029 struct CPKIFParallelHashImpl
00030 {
00031 enum {thisComponent=TOOLKIT_MESSAGE_PARALLEL_HASH};
00032 std::vector<HashInfo*> m_hashCtx;
00033 bool m_bHashesFinalized;
00034 bool m_bIgnoreUnsupportedAlgorithms;
00035 };
00037
00046 CPKIFParallelHash::CPKIFParallelHash()
00047 :m_impl (new CPKIFParallelHashImpl)
00048 {
00049 LOG_STRING_DEBUG("CPKIFParallelHash::CPKIFParallelHash()", TOOLKIT_CRYPTO_MISC, 0, this);
00050
00051 m_impl->m_bHashesFinalized = false;
00052 m_impl->m_bIgnoreUnsupportedAlgorithms = true;
00053 }
00061 CPKIFParallelHash::~CPKIFParallelHash()
00062 {
00063 LOG_STRING_DEBUG("CPKIFParallelHash::~CPKIFParallelHash()", TOOLKIT_CRYPTO_MISC, 0, this);
00064
00065 FreeHashVector();
00066
00067 delete m_impl;
00068 m_impl = NULL;
00069 }
00087 void CPKIFParallelHash::SetDigestAlgs(
00089 IPKIFCryptoMisc* cMisc,
00091 CCACDigestAlgorithmIdentifiers& digestAlgs)
00092 {
00093 LOG_STRING_DEBUG("CPKIFParallelHash::SetDigestAlgs(IPKIFCryptoMisc* cMisc, CCACDigestAlgorithmIdentifiers& digestAlgs)", TOOLKIT_CRYPTO_MISC, 0, this);
00094
00095
00096 if(NULL == cMisc)
00097 throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00098
00099
00100
00101 if(m_impl->m_hashCtx.empty())
00102 {
00103
00104 if(digestAlgs.empty())
00105 throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "Empty algorithm list passed to SetDigestAlgs.");
00106
00107 CCACDigestAlgorithmIdentifiers::iterator pos;
00108 CCACDigestAlgorithmIdentifiers::iterator end = digestAlgs.end();
00109 for(pos = digestAlgs.begin(); pos != end; ++pos)
00110 {
00111 CPKIFOIDPtr algOID = (*pos)->oid();
00112
00113 PKIFCRYPTO::HASH_ALG hashAlg;
00114
00115
00116 if(GetCACHashAlg(algOID, &hashAlg))
00117 {
00118 HashInfo* hi = NULL;
00119 try
00120 {
00121 hi = new HashInfo();
00122 }
00123 catch(std::bad_alloc& ba)
00124 {
00125 FreeHashVector();
00126 throw ba;
00127 }
00128
00129 hi->m_hashAlg = hashAlg;
00130 hi->m_hashContext = cMisc->HashInit(hashAlg);
00131 m_impl->m_hashCtx.push_back(hi);
00132 }
00133 else
00134 {
00135
00136 if(!m_impl->m_bIgnoreUnsupportedAlgorithms)
00137 throw CPKIFMessageException(m_impl->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm passed to SetDigestAlgs");
00138
00139
00140
00141
00142 }
00143 }
00144 }
00145 else
00146 {
00147 throw CPKIFMessageException(m_impl->thisComponent, MSG_INVALID_STATE, "You must call FreeHashVector before calling SetDigestAlgs.");
00148 }
00149 }
00150
00168 void CPKIFParallelHash::SetDigestAlgs(
00170 IPKIFCryptoMisc* cMisc,
00172 CPKIFBufferPtr digestAlgsBuf)
00173 {
00174 LOG_STRING_DEBUG("CPKIFParallelHash::SetDigestAlgs(IPKIFCryptoMisc* cMisc, CACCMSDigestAlgorithmIdentifiers* digestAlgs)", TOOLKIT_CRYPTO_MISC, 0, this);
00175
00176 CACASNWRAPPER_CREATE(CACCMSDigestAlgorithmIdentifiers, digestAlgsVal);
00177 digestAlgsVal.Decode(digestAlgsBuf->GetBuffer(), digestAlgsBuf->GetLength());
00178
00179
00180 if(NULL == cMisc)
00181 throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00182
00183
00184
00185 if(m_impl->m_hashCtx.empty())
00186 {
00187
00188 if(NULL == digestAlgsVal.data() || 0 == digestAlgsVal->count || NULL == digestAlgsVal->head)
00189 throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "Empty algorithm list passed to SetDigestAlgs.");
00190
00191 DListNode* cur = digestAlgsVal->head;
00192 while(NULL != cur)
00193 {
00194 CACX509V3AlgorithmIdentifier* algID = (CACX509V3AlgorithmIdentifier*)cur->data;
00195
00196
00197 CPKIFAlgorithm * pkifAlg = GetCACHashAlg(algID);
00198
00199 if(pkifAlg)
00200 {
00201 PKIFCRYPTO::HASH_ALG hashAlg = pkifAlg->HashAlg();
00202 HashInfo* hi = NULL;
00203 try
00204 {
00205 hi = new HashInfo();
00206 }
00207 catch(std::bad_alloc& ba)
00208 {
00209 FreeHashVector();
00210 throw ba;
00211 }
00212
00213 hi->m_hashAlg = hashAlg;
00214 hi->m_hashContext = cMisc->HashInit(hashAlg);
00215 m_impl->m_hashCtx.push_back(hi);
00216 }
00217 else
00218 {
00219
00220 if(!m_impl->m_bIgnoreUnsupportedAlgorithms)
00221 throw CPKIFMessageException(m_impl->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm passed to SetDigestAlgs");
00222
00223
00224
00225
00226 }
00227
00228 cur = cur->next;
00229 }
00230 }
00231 else
00232 {
00233
00234 throw CPKIFMessageException(m_impl->thisComponent, MSG_INVALID_STATE, "You must call FreeHashVector before calling SetDigestAlgs.");
00235 }
00236 }
00237
00238
00256
00258
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00334 void CPKIFParallelHash::UpdateMessage(
00336 IPKIFCryptoMisc* cMisc,
00338 unsigned char* buf,
00340 int bufLen)
00341 {
00342 LOG_STRING_DEBUG("CPKIFParallelHash::UpdateMessage(IPKIFCryptoMisc* cMisc, unsigned char* buf, int bufLen)", TOOLKIT_CRYPTO_MISC, 0, this);
00343
00344
00345 if(m_impl->m_hashCtx.empty())
00346 {
00347
00348 throw CPKIFMessageException(m_impl->thisComponent, MSG_INVALID_STATE, "No supported hash algorithms have been set.");
00349 }
00350 else
00351 {
00352
00353 vector<HashInfo*>::iterator pos;
00354 vector<HashInfo*>::iterator end = m_impl->m_hashCtx.end();
00355 for(pos = m_impl->m_hashCtx.begin(); end != pos; ++pos)
00356 {
00357
00358 cMisc->HashUpdate((*pos)->m_hashContext, buf, bufLen);
00359 }
00360 }
00361 }
00372 void CPKIFParallelHash::FinalizeHashes(
00374 IPKIFCryptoMisc* cMisc)
00375 {
00376 LOG_STRING_DEBUG("CPKIFParallelHash::FinalizeHashes(IPKIFCryptoMisc* cMisc)", TOOLKIT_CRYPTO_MISC, 0, this);
00377
00378
00379 if(NULL == cMisc)
00380 throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00381
00382
00383 if(m_impl->m_bHashesFinalized)
00384 return;
00385 else
00386 {
00387
00388 vector<HashInfo*>::iterator pos;
00389 vector<HashInfo*>::iterator end = m_impl->m_hashCtx.end();
00390 int nHashResult = MAXHASH;
00391 for(pos = m_impl->m_hashCtx.begin(); end != pos; ++pos)
00392 {
00393 nHashResult = MAXHASH;
00394 cMisc->HashFinal((*pos)->m_hashContext, (*pos)->m_hashResult, &nHashResult);
00395 }
00396
00397 m_impl->m_bHashesFinalized = true;
00398 }
00399 }
00408 HashInfo* CPKIFParallelHash::GetHashInfo(
00410 PKIFCRYPTO::HASH_ALG alg)
00411 {
00412 LOG_STRING_DEBUG("CPKIFParallelHash::GetHashInfo(HASH_ALG alg)", TOOLKIT_CRYPTO_MISC, 0, this);
00413
00414
00415
00416 vector<HashInfo*>::iterator pos;
00417 vector<HashInfo*>::iterator end = m_impl->m_hashCtx.end();
00418 for(pos = m_impl->m_hashCtx.begin(); end != pos; ++pos)
00419 {
00420 if((*pos)->m_hashAlg == alg)
00421 return *pos;
00422 }
00423
00424 return NULL;
00425 }
00433 void CPKIFParallelHash::FreeHashVector()
00434 {
00435 LOG_STRING_DEBUG("CPKIFParallelHash::FreeHashVector()", TOOLKIT_CRYPTO_MISC, 0, this);
00436
00437
00438 vector<HashInfo*>::iterator pos;
00439 vector<HashInfo*>::iterator end = m_impl->m_hashCtx.end();
00440 for(pos = m_impl->m_hashCtx.begin(); end != pos; ++pos)
00441 {
00442 try
00443 {
00444 delete (*pos)->m_hashContext;
00445 }
00446 catch(...)
00447 {
00448
00449 }
00450
00451 delete *pos;
00452 }
00453 m_impl->m_hashCtx.clear();
00454 m_impl->m_bHashesFinalized = false;
00455 }
00470 void CPKIFParallelHash::SetIgnoreUnsupportedAlgs(
00473 bool b)
00474 {
00475 m_impl->m_bIgnoreUnsupportedAlgorithms = b;
00476 }