ParallelHash.cpp

Go to the documentation of this file.
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)  //added for TAP purposes 9/5/03
00092 {
00093     LOG_STRING_DEBUG("CPKIFParallelHash::SetDigestAlgs(IPKIFCryptoMisc* cMisc, CCACDigestAlgorithmIdentifiers& digestAlgs)", TOOLKIT_CRYPTO_MISC, 0, this);
00094 
00095     // SAS add 03/10/2004
00096     if(NULL == cMisc)
00097         throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00098 
00099 
00100     //check to see if we already have some hash contexts
00101     if(m_impl->m_hashCtx.empty())
00102     {
00103         //if not, create some - if no hash algs are passed in throw an error
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             //try to get a PKIF identifier for the hashing algorithm
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();   //clean up anything allocated by an earlier loop and bail out
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                 //if alg is not supported and ignore is set to false - clean up and bail out
00136                 if(!m_impl->m_bIgnoreUnsupportedAlgorithms)
00137                     throw CPKIFMessageException(m_impl->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm passed to SetDigestAlgs");
00138 
00139                 //typically, in CMS usage case, we can let an unsupported hashing algorithm pass
00140                 //as long as we never attempt to verify the signature associated with that hash algorithm.
00141                 //if we try to verify the signature associated with an unsupported algorithm then we can fail.
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     // SAS add 03/10/2004
00180     if(NULL == cMisc)
00181         throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00182 
00183 
00184     //check to see if we already have some hash contexts
00185     if(m_impl->m_hashCtx.empty())
00186     {
00187         //if not, create some - if no hash algs are passed in throw an error
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             //try to get a PKIF identifier for the hashing algorithm
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();   //clean up anything allocated by an earlier iteration and bail out
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                 //if alg is not supported and ignore is set to false - clean up and bail out
00220                 if(!m_impl->m_bIgnoreUnsupportedAlgorithms)
00221                     throw CPKIFMessageException(m_impl->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm passed to SetDigestAlgs");
00222 
00223                 //typically, in CMS usage case, we can let an unsupported hashing algorithm pass
00224                 //as long as we never attempt to verify the signature associated with that hash algorithm.
00225                 //if we try to verify the signature associated with an unsupported algorithm then we can fail.
00226             }
00227 
00228             cur = cur->next;
00229         }
00230     }
00231     else
00232     {
00233         //if so, bail out
00234         throw CPKIFMessageException(m_impl->thisComponent, MSG_INVALID_STATE, "You must call FreeHashVector before calling SetDigestAlgs.");
00235     }
00236 }
00237 
00238 
00256 /*void CPKIFParallelHash::SetDigestAlgs(
00258     IPKIFCryptoMisc* cMisc,
00260     CACCMSDigestAlgorithmIdentifiers* digestAlgs) 
00261 {
00262     LOG_STRING_DEBUG("CPKIFParallelHash::SetDigestAlgs(IPKIFCryptoMisc* cMisc, CACCMSDigestAlgorithmIdentifiers* digestAlgs)", TOOLKIT_CRYPTO_MISC, 0, this);
00263 
00264     // SAS add 03/10/2004
00265     if(NULL == cMisc)
00266         throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00267 
00268 
00269     //check to see if we already have some hash contexts
00270     if(m_impl->m_hashCtx.empty())
00271     {
00272         //if not, create some - if no hash algs are passed in throw an error
00273         if(NULL == digestAlgs || 0 == digestAlgs->count || NULL == digestAlgs->head)
00274             throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "Empty algorithm list passed to SetDigestAlgs.");
00275 
00276         DListNode* cur = digestAlgs->head;
00277         while(NULL != cur)
00278         {
00279             CACX509V3AlgorithmIdentifier* algID = (CACX509V3AlgorithmIdentifier*)cur->data;
00280 
00281             HASH_ALG hashAlg;
00282 
00283             //try to get a PKIF identifier for the hashing algorithm
00284             if(GetCACHashAlg(algID, &hashAlg))
00285             {
00286                 HashInfo* hi = NULL;
00287                 try
00288                 {
00289                     hi = new HashInfo();
00290                 }
00291                 catch(std::bad_alloc& ba)
00292                 {
00293                     FreeHashVector();   //clean up anything allocated by an earlier iteration and bail out
00294                     throw ba;
00295                 }
00296 
00297                 hi->m_hashAlg = hashAlg;
00298                 hi->m_hashContext = cMisc->HashInit(hashAlg);
00299                 m_impl->m_hashCtx.push_back(hi);
00300             }
00301             else
00302             {
00303                 //if alg is not supported and ignore is set to false - clean up and bail out
00304                 if(!m_impl->m_bIgnoreUnsupportedAlgorithms)
00305                     throw CPKIFMessageException(m_impl->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm passed to SetDigestAlgs");
00306 
00307                 //typically, in CMS usage case, we can let an unsupported hashing algorithm pass
00308                 //as long as we never attempt to verify the signature associated with that hash algorithm.
00309                 //if we try to verify the signature associated with an unsupported algorithm then we can fail.
00310             }
00311 
00312             cur = cur->next;
00313         }
00314     }
00315     else
00316     {
00317         //if so, bail out
00318         throw CPKIFMessageException(m_impl->thisComponent, MSG_INVALID_STATE, "You must call FreeHashVector before calling SetDigestAlgs.");
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     //see if we already have a hash context
00345     if(m_impl->m_hashCtx.empty())
00346     {
00347         //if not - fail
00348         throw CPKIFMessageException(m_impl->thisComponent, MSG_INVALID_STATE, "No supported hash algorithms have been set.");
00349     }
00350     else
00351     {
00352         //if so, then update each hash with the new data (let crypto exceptions pass back to caller)
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             //throw any exceptions from HashUpdate
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     // SAS add 03/10/2004
00379     if(NULL == cMisc)
00380         throw CPKIFMessageException(m_impl->thisComponent, COMMON_INVALID_INPUT, "cMisc was NULL.");
00381 
00382     //if hashes have already been finalized then silently do nothing
00383     if(m_impl->m_bHashesFinalized)
00384         return;
00385     else
00386     {
00387         //finalize all hashes - storing the results in the HashInfo object stored in the vector
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     //iterate over all hash infos and return the first (and presumably only) one
00415     //that matches the alg passed in
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     //iterate over all HashInfo objects in the vector and set them free
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             //paranoid try - should never catch anything here
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 }

Generated on Mon Nov 15 11:15:52 2010 for PublicKeyInfrastructureFramework(PKIF) by  doxygen 1.5.6