SignedData.cpp

Go to the documentation of this file.
00001 
00009 #include "SignedData.h"
00010 #include "private/PrivatePKIFCMSUtils.h"
00011 
00012 #include "Certificate.h"
00013 #include "Buffer.h"
00014 #include "OID.h"
00015 #include "Attribute.h"
00016 #include "EncapsulatedContentInfo.h"
00017 #include "ASN1Helper.h"
00018 #include "ParallelHash.h"
00019 #include "PKIFCMSMessageMemoryHelper.h"
00020 #include "CRL.h"
00021 #include "SignerInfo.h"
00022 #include "AlgorithmIdentifier.h"
00023 #include "GottaMatch.h"
00024 #include "Name.h"
00025 #include "SubjectKeyIdentifier.h"
00026 #include "IssuerNameAndSerialNumberBasedSearch.h"
00027 #include "KeyIDBasedSearch.h"
00028 #include "PKIFFuncStorage.h"
00029 #include "ContentTypeAttribute.h"
00030 #include "PKIFAlgorithm.h"
00031 #include "PKIFBase64.h"
00032 #include "BasicConstraints.h"
00033 
00034 #include "IPKIFCryptoRawOperations.h"
00035 #include "IPKIFCertSearch.h"
00036 #include "IPKIFCertRepositoryUpdate.h"
00037 #include "IPKIFPathValidate.h"
00038 #include "IPKIFCRLRepositoryUpdate.h"
00039 #include "IPKIFPathBuild.h"
00040 #include "IPKIFCryptoMisc.h"
00041 #include "IPKIFCryptoKeyIDOperations.h"
00042 
00043 // XXX REMOVEME: when new error codes are available
00044 #include "PKIFCAPIErrors.h"
00045 #include "PKIFNSSErrors.h"
00046 #include "PKIFCryptoPPErrors.h"
00047 using namespace std;
00048 
00049 using boost::dynamic_pointer_cast;
00050 
00051 #include <iterator>
00052 unsigned char nullParams[] = {0x05,0x00};
00053 
00055 struct CPKIFSignedDataImpl
00056 {
00057 
00058     CPKIFSignedData* m_parent;
00066     CPKIFSignedDataImpl () 
00067     {
00068         m_parent = NULL;
00069     }
00077     CPKIFSignedDataImpl (CPKIFSignedData  *p) 
00078     {
00079         m_parent = p;
00080     }
00081 
00082     CPKIFBufferPtr GetSignersCert(CACCMSSignerInfo* tmpSignerInfo);
00083     bool _Verify(int signerIndex, CMSVerificationStatus& status, CPKIFCertificatePtr& sc, CMSPathValidationStatus minStatus);
00084     void GetCandidateSignersCerts(CACCMSSignerInfo* tmpSignerInfo, IPKIFNameAndKeyList& certs);
00085 
00086     //m_signedData contains the baseline contents for the instance.  all other members
00087     //are added to m_signedData.  thus when creating a new message m_signedData is empty
00088     //until encode.  when parsing a message m_signedData is filled upon decode.  helper
00089     //members are populated as fields are accessed.  additional fields may be added via
00090     //calls to add functions.
00091     CPKIFASNWrapper<CACCMSSignedData>* m_signedData;
00092     bool m_bDecodedContent;     //set to true after decoding, set to false when content is added manually
00093 
00094     CPKIFSignedData::CMSVersion m_version;                              //value set by CalculateAndSetVersion
00095     CCACDigestAlgorithmIdentifiers m_digestAlgorithms;  //used in collection of algs from SignerInfos
00096     
00097     CPKIFEncapsulatedContentInfoPtr m_encapContentInfo; 
00098     CPKIFFuncStoragePtr m_kuChecker;
00099 
00100     //the following two fields may contain: nothing, manually added items, items from decoded message
00101     //or manually added items plus items from decoded message 
00102     CPKIFCertificateList m_certificates;                    
00103     CPKIFCRLList m_crls;
00104     
00105     CPKIFSignerInfoList m_signerInfos;  //contains ONLY manually added signer infos that will be used to 
00106                                     //generate a signature when encode is called.  signer infos from
00107                                     //a decoded message are not used to generate a signature when 
00108                                     //encode is called.
00109 
00110     //members related to hashing of data using all associated hash algs
00111     CPKIFParallelHash m_detachedData;
00112     bool m_bDetached;   //used to indicate a detached message has been started.  no signer infos
00113                         //can be added when this is set to true.
00114     CPKIFBufferPtr m_decodeBuf; //added 10/20/03
00115 
00116     //members related to verification
00117     CPKIFCertificatePathPtr m_path;
00118     CPKIFPathValidationResultsPtr m_valResults;
00119     CPKIFPathSettingsPtr m_settings;
00120     IPKIFMediatorPtr m_med;
00121 
00122     //*****************************************************************************
00123     //  private functions
00124     //*****************************************************************************
00125     void AddCerts(CACCMSSignedData* signedData);            //adds certs to CACCMSSignedData structure
00126     void AddCRLs(CACCMSSignedData* signedData);             //adds crls to CACCMSSignedData structure
00127     void BuildDigestAlgList(CACCMSSignedData* signedData);  //gathers digest algs from SignerInfos
00128     void AddSignerInfos(CACCMSSignedData* signedData,       //adds SignerInfos to CACCMSSignedData structure
00129                             IPKIFMediatorPtr& m);
00130     void RemoveSignerInfos(CACCMSSignedData* signedData);   //removes decoded SignerInfos from CACCMSSignedData structure
00131 
00132     void CalculateAndSetVersion();  //used to set version based on rules in RFC3369
00133 
00134     //CPKIFBufferPtr GetSignersCert(CACCMSSignerInfo* tmpSignerInfo);
00135 
00136     void MakeSignedData();
00137     void FreeSignedData();
00138     void CallingAllGets();
00139 };
00141 
00142 #define NEW_VERIFY_FUNC 1
00143 //*************************************************************************************************
00144 //  CPKIFParallelHash member functions and related utility functions 
00145 //*************************************************************************************************
00146 
00147 
00148 //*****************************************************************************
00149 //  constructors, destructors, clear, makzenfree
00150 //*****************************************************************************
00160 CPKIFSignedData::CPKIFSignedData()
00161     :m_impl (new CPKIFSignedDataImpl)
00162 {
00163     LOG_STRING_DEBUG("CPKIFSignedData::CPKIFSignedData()", TOOLKIT_CRYPTO_MISC, 0, this);
00164 
00165     m_impl->m_parent = this;
00166     m_impl->m_bDecodedContent = false;
00167     m_impl->m_bDetached = false;
00168 
00169     m_impl->m_version = CMSv0;
00170 
00171     m_impl->m_signedData = NULL;
00172     m_impl->MakeSignedData();
00173 
00174     SetContentType(g_signedData);
00175 }
00183 CPKIFSignedData::~CPKIFSignedData()
00184 {
00185     LOG_STRING_DEBUG("CPKIFSignedData::~CPKIFSignedData()", TOOLKIT_CRYPTO_MISC, 0, this);
00186 
00187     m_impl->FreeSignedData();
00188 
00189     //RemoveMediatorAssociations();
00190 
00191     delete m_impl;
00192     m_impl = NULL;
00193 }
00201 void CPKIFSignedData::AddMediator(
00203     IPKIFMediatorPtr& m)
00204 {
00205     m_impl->m_med = m;
00206 }
00214 IPKIFMediatorPtr CPKIFSignedData::GetMediator()
00215 {
00216     return m_impl->m_med;
00217 }
00225 void CPKIFSignedDataImpl::MakeSignedData()
00226 {
00227     LOG_STRING_DEBUG("CPKIFSignedData::MakeSignedData()", TOOLKIT_CRYPTO_MISC, 0, this);
00228 
00229     FreeSignedData();
00230 
00231     //throw bad_alloc (this function is invoked from the constructor and ClearContent)
00232     m_signedData = new CPKIFASNWrapper<CACCMSSignedData>( BEREncCACCMSSignedData, BERDecCACCMSSignedData );
00233 }
00241 void CPKIFSignedDataImpl::FreeSignedData()
00242 {
00243     LOG_STRING_DEBUG("CPKIFSignedData::FreeSignedData()", TOOLKIT_CRYPTO_MISC, 0, this);
00244 
00245     //if we ever do this then we need to reset the m_bDecodedContent flag to false
00246     //because we no longer have decoded content
00247     m_bDecodedContent = false; //added 10/17/2003
00248     if(NULL != m_signedData)
00249         delete m_signedData;
00250     m_signedData = NULL;
00251 
00252     CPKIFBufferPtr emptyBP;
00253     m_decodeBuf = emptyBP;
00254 }
00266 void CPKIFSignedData::ClearContent(
00269     bool removeMediatorAssociationsAndPathSettings)
00270 {
00271     LOG_STRING_DEBUG("CPKIFSignedData::ClearContent(bool removeMediatorAssociations)", TOOLKIT_CRYPTO_MISC, 0, this);
00272 
00273     //free and make
00274     m_impl->FreeSignedData();
00275     m_impl->MakeSignedData();
00276 
00277     //falsify the bools
00278     m_impl->m_bDecodedContent = false;
00279     m_impl->m_bDetached = false;
00280 
00281     //zero the version
00282     m_impl->m_version = CMSv0;
00283 
00284     //clear the lists
00285     m_impl->m_digestAlgorithms.clear();
00286     m_impl->m_certificates.clear();                 
00287     m_impl->m_crls.clear();
00288     m_impl->m_signerInfos.clear();  
00289 
00290     //create and assign a stack of empty smart pointers
00291     CPKIFEncapsulatedContentInfoPtr tmpECIP;
00292     m_impl->m_encapContentInfo = tmpECIP;   
00293     
00294     CPKIFCertificatePathPtr tmpPath;
00295     m_impl->m_path = tmpPath;
00296     
00297     CPKIFPathValidationResultsPtr tmpResults;
00298     m_impl->m_valResults = tmpResults;
00299     
00300     //added 10/17/2003
00301     if(removeMediatorAssociationsAndPathSettings)
00302     {
00303         //moved this here (changing the meaning of the param) 2/23/2005 CRW
00304         CPKIFPathSettingsPtr tmpSettings;
00305         m_impl->m_settings = tmpSettings;
00306 
00307         //RemoveMediatorAssociations();
00308 
00309         IPKIFMediatorPtr tmp;
00310         m_impl->m_med = tmp;
00311     }
00312 }
00313 
00314 //*****************************************************************************
00315 //  field manipulation functions
00316 //*****************************************************************************
00317 //version (required)
00337 CPKIFSignedData::CMSVersion CPKIFSignedData::GetVersion() const
00338 {
00339     return m_impl->m_version;
00340 }
00341 
00342 //encapsulated content info (required)
00354 CPKIFEncapsulatedContentInfoPtr CPKIFSignedData::GetEncapsulatedContent() const
00355 {
00356     LOG_STRING_DEBUG("CPKIFSignedData::GetEncapsulatedContent()", TOOLKIT_CRYPTO_MISC, 0, this);
00357 
00358     //data associated with a message may be in any of the following:
00359     //  - m_encapContentInfo member (via SetEncapsulatedContent)
00360     //  - in the m_signedData structure (via Decode)
00361     //  - detached (not covered by this function - preservation of detached data is app's job)
00362 
00363     if(m_impl->m_encapContentInfo == (CPKIFEncapsulatedContentInfo*)NULL && m_impl->m_bDecodedContent)
00364     {
00365         //if m_encapContentInfo is empty (i.e. no ecip was manually associated) and
00366         //we decoded a message, create a new CPKIFEncapsulatedContentInfoPtr object
00367         //from the decoded message and store it in m_encapContentInfo.
00368         //m_bDecodedContent is only set to true following an invocation of Decode that does not
00369         //throw an exception.  we needn't check for existance of m_signedData.
00370         //throw bad_alloc
00371         CPKIFEncapsulatedContentInfoPtr tmpECIP(new CPKIFEncapsulatedContentInfo());
00372 
00373         //content type is required so if we get here then we have one (if there wasn't one
00374         //we'd've failed in the parser)
00375         //throw bad_alloc or CPKIFException
00376         CPKIFOIDPtr tmpOID(new CPKIFOID((*m_impl->m_signedData)->encapContentInfo.eContentType.subid, (*m_impl->m_signedData)->encapContentInfo.eContentType.numids));
00377         tmpECIP->SetOID(tmpOID);
00378 
00379         //actual content is optional - add it to the object if it's there...
00380         if((*m_impl->m_signedData)->encapContentInfo.m.eContentPresent)
00381         {
00382             //throw bad_alloc
00383             CPKIFBufferPtr tmpBuf(new CPKIFBuffer((*m_impl->m_signedData)->encapContentInfo.eContent.data, (*m_impl->m_signedData)->encapContentInfo.eContent.numocts));
00384             tmpECIP->SetContent(tmpBuf);
00385         }
00386 
00387         //save the new ecip
00388         CPKIFSignedData* nonConst = const_cast<CPKIFSignedData*>(this);
00389         nonConst->m_impl->m_encapContentInfo = tmpECIP;
00390     }
00391 
00392     //at this point, m_encapContentInfo could contain content that was manually added via 
00393     //SetEncapsulatedContent, content from a decoded message or be empty.
00394     return m_impl->m_encapContentInfo;
00395 }
00417 void CPKIFSignedData::SetEncapsulatedContent(
00419     CPKIFEncapsulatedContentInfoPtr& ecip)
00420 {
00421     LOG_STRING_DEBUG("CPKIFSignedData::SetEncapsulatedContent(CPKIFEncapsulatedContentInfoPtr& ecip)", TOOLKIT_CRYPTO_MISC, 0, this);
00422 
00423     //accept no NULLs
00424     if(ecip == (CPKIFEncapsulatedContentInfo*)NULL)
00425         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00426 
00427     //make sure the object passed in has all the pieces we'll need (i.e. just an OID
00428     //as content can be NULL and be detached)
00429     CPKIFOIDPtr tmpOID = ecip->GetOID();
00430     if(tmpOID == (CPKIFOID*)NULL)
00431         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT, "The EncapsulatedContentInfo object must contain an OID.");
00432 
00433     m_impl->m_encapContentInfo = ecip;
00434     m_impl->m_bDecodedContent = false;  //from this point forward we will be ignoring (*m_signedData)->encapContentInfo
00435 }
00450 void CPKIFSignedData::UpdateMessage(
00452     unsigned char* buf,
00454     int bufLen) //used to set-up detached messages
00455 {
00456     LOG_STRING_DEBUG("CPKIFSignedData::UpdateMessage(unsigned char* buf, int bufLen)", TOOLKIT_CRYPTO_MISC, 0, this);
00457 
00458     if(NULL == GetMediator())
00459         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "Mediator is not available.");
00460 
00461     //get a pointer to IPKIFCryptoMisc to perform hashing 
00462     IPKIFCryptoMisc* cMisc = GetMediator()->GetMediator<IPKIFCryptoMisc>();
00463     if(NULL == cMisc)
00464         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "Could not obtain pointer to IPKIFCryptoMisc interface.");
00465 
00466     if(!m_impl->m_bDetached)
00467     {
00468         //if we haven't already started a detached message, we need to collect the digest algs from
00469         //the associated SignerInfos.  signer infos should be locked after this is done to prevent
00470         //introduction of a different hash alg.
00471 
00472         //create a signed data structure and populate the digest algs field
00473         //throw bad_alloc
00474         PKIFCMSMessageMemoryHelper mhSignedData;
00475         mhSignedData.pSignedData = new CACCMSSignedData;
00476         memset(mhSignedData.pSignedData, 0, sizeof(CACCMSSignedData));
00477 
00478         try
00479         {
00480             m_impl->BuildDigestAlgList(mhSignedData.pSignedData);
00481         }
00482         catch(...)
00483         {
00484             //BuildDigestAlgList can throw bad_alloc or CPKIFException - we let it pass on and let 
00485             //PKIFCMSMessageMemoryHelper take care of the clean up but must make sure we don't leave 
00486             //m_digestAlgorithms partially filled
00487             m_impl->m_digestAlgorithms.clear();
00488             throw;
00489         }
00490 
00491         //pass the collection of algs to the detached data member and update the hash
00492         // m_impl->m_detachedData.SetDigestAlgs(cMisc, &mhSignedData.pSignedData->digestAlgorithms);
00493         // m_impl->m_bDetached = true;
00494 
00495         // XXX TO DO
00496         // Should we use deferred parsing instead of the decode/encode/decode that is now being
00497         // performed because of the deobjectification?
00498 
00499         CACASNWRAPPER_CREATE(CACCMSDigestAlgorithmIdentifiers, digestAlgsVal);
00500         ASN1OpenType* encodedAlgs = digestAlgsVal.Encode(&mhSignedData.pSignedData->digestAlgorithms);
00501         CPKIFBufferPtr data(new CPKIFBuffer (encodedAlgs->data, encodedAlgs->numocts));
00502 
00503         if (encodedAlgs != NULL)
00504         {
00505             delete encodedAlgs;
00506         }
00507         m_impl->m_detachedData.SetDigestAlgs(cMisc, data);
00508         m_impl->m_bDetached = true;
00509     }
00510 
00511     //update the running hash for all hash algs (let the caller catch exceptions)
00512     m_impl->m_detachedData.UpdateMessage(cMisc, buf, bufLen);
00513 }
00514 
00515 //certificates (optional)
00526 void CPKIFSignedData::AddCertificate(
00529     CPKIFCertificatePtr& cert)
00530 {
00531     LOG_STRING_DEBUG("CPKIFSignedData::AddCertificate(CPKIFCertificatePtr& cert)", TOOLKIT_CRYPTO_MISC, 0, this);
00532 
00533     //accept no NULLs
00534     if(cert == (CPKIFCertificate*)NULL)
00535         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00536 
00537     //accept no empty certs
00538     CPKIFBufferPtr encCert = cert->Encoded();
00539     if(encCert == (CPKIFBuffer*)NULL || 0 == encCert->GetLength())
00540         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00541 
00542     m_impl->m_certificates.push_back(cert);
00543 }
00551 void CPKIFSignedData::GetCertificates(
00553     CPKIFCertificateList& certs)
00554 {
00555     LOG_STRING_DEBUG("CPKIFSignedData::GetCertificates(CPKIFCertificateList& certs)", TOOLKIT_CRYPTO_MISC, 0, this);
00556 
00557     //return list containing contents of m_certificates plus certs in m_signedData.
00558     //destroy certs in m_signedData after adding them to m_certificates (don't really
00559     //destroy certs - just change flag so they don't get ignored in the future).
00560 
00561     //removed the following line 7/22/2004 because it is not desirable - Armen
00562     //certs.clear();
00563 
00564     //first, update m_certificates with any certs from m_signedData
00565     if(m_impl->m_signedData != NULL && NULL != (*m_impl->m_signedData).data() && (*m_impl->m_signedData)->m.certificatesPresent)
00566     {
00567         DListNode* iter = (*m_impl->m_signedData)->certificates.head;
00568         while(NULL != iter)
00569         {
00570             CACCMSCertificateChoices* curChoice = (CACCMSCertificateChoices*)iter->data;
00571             if(T_CACCMSCertificateChoices_certificate != curChoice->t)
00572             {
00573                 iter = iter->next;
00574                 continue;
00575             }
00576 
00577             ASN1OpenType* cert = (ASN1OpenType*)curChoice->u.certificate;
00578 
00579             try
00580             {
00581                 CPKIFCertificatePtr newCert(new CPKIFCertificate());
00582                 newCert->Decode(cert->data, cert->numocts);
00583                 m_impl->m_certificates.push_back(newCert);
00584             }
00585             catch(CPKIFException&)
00586             {
00587                 //don't bother the caller with malformed certs
00588             }
00589             catch(std::bad_alloc& ba)
00590             {
00591                 //empty the list
00592                 m_impl->m_certificates.clear();
00593                 throw ba;
00594             }
00595     
00596             iter = iter->next;
00597         }
00598 
00599         (*m_impl->m_signedData)->m.certificatesPresent = 0;
00600     }
00601 
00602     //next, copy the contents of the m_certificates list to the certs list
00603     copy(m_impl->m_certificates.begin(), m_impl->m_certificates.end(), back_inserter(certs));
00604 }
00605 
00606 //crls (optional)
00617 void CPKIFSignedData::AddCRL(
00619     CPKIFCRLPtr& crl)
00620 {
00621     LOG_STRING_DEBUG("CPKIFSignedData::AddCRL(CPKIFCRLPtr& crl)", TOOLKIT_CRYPTO_MISC, 0, this);
00622 
00623     //accept no NULLs
00624     if(crl == (CPKIFCRL*)NULL)
00625         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00626 
00627     //accept no empty certs
00628     CPKIFBufferPtr encCRL = crl->Encoded();
00629     if(encCRL == (CPKIFBuffer*)NULL || 0 == encCRL->GetLength())
00630         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00631 
00632     m_impl->m_crls.push_back(crl);
00633 }
00641 void CPKIFSignedData::GetCRLs(
00643     CPKIFCRLList& crls)
00644 {
00645     LOG_STRING_DEBUG("CPKIFSignedData::GetCRLs(CPKIFCRLList& crls)", TOOLKIT_CRYPTO_MISC, 0, this);
00646 
00647     //return list containing contents of m_crls plus crls in m_signedData.
00648     //destroy crls in m_signedData after adding them to m_crls (don't really
00649     //destroy crls - just change flag so they don't get ignored in the future).
00650 
00651     crls.clear();
00652 
00653     //first, update m_crls with any crls from m_signedData
00654     if(m_impl->m_signedData != NULL && NULL != (*m_impl->m_signedData).data() && (*m_impl->m_signedData)->m.crlsPresent)
00655     {
00656         DListNode* iter = (*m_impl->m_signedData)->crls.head;
00657         while(NULL != iter)
00658         {
00659             CACCMSRevocationInfoChoice* curChoice = (CACCMSRevocationInfoChoice*)iter->data;
00660 
00661             if(T_CACCMSRevocationInfoChoice_crl != curChoice->t)
00662             {
00663                 iter = iter->next;
00664                 continue;
00665             }
00666 
00667             ASN1OpenType* crl = (ASN1OpenType*)curChoice->u.crl;
00668 
00669             try
00670             {
00671                 CPKIFCRLPtr newCRL(new CPKIFCRL());
00672                 newCRL->Decode(crl->data, crl->numocts);
00673                 m_impl->m_crls.push_back(newCRL);
00674             }
00675             catch(CPKIFException&)
00676             {
00677                 //don't bother the caller with malformed crls
00678             }
00679             catch(std::bad_alloc& ba)
00680             {
00681                 //empty the list
00682                 m_impl->m_crls.clear();
00683                 throw ba;
00684             }
00685 
00686             iter = iter->next;
00687         }
00688 
00689         (*m_impl->m_signedData)->m.crlsPresent = 0;
00690     }
00691 
00692     //next, copy the contents of the m_crls list to the crls list
00693     copy(m_impl->m_crls.begin(), m_impl->m_crls.end(), back_inserter(crls));
00694 }
00717 void CPKIFSignedData::AddSignerInfo(
00721     CPKIFSignerInfoPtr& si)
00722 {
00723     LOG_STRING_DEBUG("CPKIFSignedData::AddSignerInfo(CPKIFSignerInfoPtr& si)", TOOLKIT_CRYPTO_MISC, 0, this);
00724 
00725     if(m_impl->m_bDetached)
00726         throw CPKIFMessageException(thisComponent, MSG_INVALID_STATE, "All signers must be added prior to calling UpdateMessage.");
00727 
00728     //accept no NULLs
00729     if(si == (CPKIFSignerInfo*)NULL)
00730         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00731 
00732     //make sure it has everything we need
00733 
00734     m_impl->m_signerInfos.push_back(si);
00735 }
00744 void CPKIFSignedData::GetSignerInfos(
00746     CPKIFSignerInfoList& sis)
00747 {
00748     LOG_STRING_DEBUG("CPKIFSignedData::GetSignerInfos(CPKIFSignerInfoList& sis)", TOOLKIT_CRYPTO_MISC, 0, this);
00749 
00750     sis.clear();
00751 
00752     copy(m_impl->m_signerInfos.begin(), m_impl->m_signerInfos.end(), back_inserter(sis));
00753 
00754     CACASNWRAPPER_CREATE(CACCMSSignerInfo, InfoWrapper);
00755 
00756     if((*m_impl->m_signedData).data() != NULL && 0 != (*m_impl->m_signedData)->signerInfos.count)
00757     {
00758         DListNode* cur = (*m_impl->m_signedData)->signerInfos.head;
00759         while(NULL != cur)
00760         {
00761             ASN1OpenType *data = InfoWrapper.Encode((CACCMSSignerInfo*)cur->data);
00762             CPKIFBufferPtr siBuf(new CPKIFBuffer(data->data, data->numocts));
00763             delete data;
00764 
00765             CPKIFSignerInfoPtr si(new CPKIFSignerInfo(siBuf));
00766             //CPKIFSignerInfoPtr si(new CPKIFSignerInfo(*(CACCMSSignerInfo*)cur->data));
00767             sis.push_back(si);
00768 
00769             m_impl->m_signerInfos.push_back(si);
00770 
00771             cur = cur->next;
00772         }
00773         (*m_impl->m_signedData)->signerInfos.count = 0;
00774     }
00775 }
00776 
00777 //*****************************************************************************
00778 //  encode and decode functions
00779 //*****************************************************************************
00806 CPKIFBufferPtr CPKIFSignedData::Encode()
00807 {
00808     LOG_STRING_DEBUG("CPKIFSignedData::Encode()", TOOLKIT_CRYPTO_MISC, 0, this);
00809 
00810     //We may be encoding:
00811     //  - using stuff added since creation of this instance
00812     //  - using stuff from m_signedData
00813     //  - using stuff from m_signedData plus stuff added since parsing
00814 
00815     //*****************************************************************
00816     //  sanity check the inputs
00817     //*****************************************************************
00818     if(NULL == GetMediator())
00819         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "Mediator is not available.");
00820 
00821     IPKIFCryptoKeyIDOperations* cKeyID = GetMediator()->GetMediator<IPKIFCryptoKeyIDOperations>();
00822     if(NULL == cKeyID)
00823         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCryptoKeyIDOperations interface is not available.");
00824 
00825     IPKIFCryptoMisc* cMisc = GetMediator()->GetMediator<IPKIFCryptoMisc>();
00826     if(NULL == cMisc)
00827         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCryptoMisc interface is not available.");
00828 
00829     CPKIFEncapsulatedContentInfoPtr ecip = GetEncapsulatedContent();
00830     if(ecip == (CPKIFEncapsulatedContentInfo*)NULL || ecip->GetOID() == (CPKIFOID*)NULL)
00831         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT, "EncapsulatedContentInfo is not available.");
00832 
00833     //*****************************************************************
00834     //  prepare the signed data structure to encode
00835     //*****************************************************************
00836     //throw bad_alloc
00837     PKIFCMSMessageMemoryHelper mhSignedData;
00838     mhSignedData.pSignedData = new CACCMSSignedData;
00839     memset(mhSignedData.pSignedData, 0, sizeof(CACCMSSignedData));
00840     
00841     //add any certs and crls to the message to encode (can throw bad_alloc)
00842     m_impl->AddCerts(mhSignedData.pSignedData);
00843     m_impl->AddCRLs(mhSignedData.pSignedData);
00844 
00845     //iterate over the signer infos and build a list of all digest algs
00846     try
00847     {
00848         m_impl->BuildDigestAlgList(mhSignedData.pSignedData);
00849     }
00850     catch(...)
00851     {
00852         //BuildDigestAlgList can throw bad_alloc or CPKIFException - we let it pass on and let 
00853         //PKIFCMSMessageMemoryHelper take care of the clean up but must make sure we don't leave 
00854         //m_digestAlgorithms partially filled
00855         m_impl->m_digestAlgorithms.clear();
00856         throw;
00857     }
00858 
00859     //set up the content type of the data that was signed
00860     CPKIFStringPtr str(new std::string(ecip->GetOID()->ToString())); 
00861     ASN1OBJID* tmpOid = ConvertStringToASN1OBJID(str);
00862     CopyOID(&mhSignedData.pSignedData->encapContentInfo.eContentType, tmpOid);
00863 
00864     if(NULL != tmpOid)
00865         delete tmpOid;
00866     //mhSignedData.pSignedData->encapContentInfo.eContentType = *ecip->GetOID()->raw();
00867     //mhSignedData.pSignedData->encapContentInfo.eContentType = *tmpOid;
00868 
00869     //see if the content is encapsulated or detached
00870     CPKIFBufferPtr ecipBuf = ecip->GetContent();
00871     if(ecipBuf != (CPKIFBuffer*)NULL)
00872     {
00873         //if encapsulated add it to the message
00874         mhSignedData.pSignedData->encapContentInfo.m.eContentPresent = 1;
00875         mhSignedData.pSignedData->encapContentInfo.eContent.data = ecipBuf->GetBuffer();
00876         mhSignedData.pSignedData->encapContentInfo.eContent.numocts = ecipBuf->GetLength();
00877     
00878         //clear out any old hash info (if present)
00879         m_impl->m_detachedData.FreeHashVector();
00880         m_impl->m_bDetached = false; //added 04/08/2003 CRW
00881 
00882         //hash the content (UpdateMessage can throw)
00883         UpdateMessage((unsigned char*)mhSignedData.pSignedData->encapContentInfo.eContent.data, mhSignedData.pSignedData->encapContentInfo.eContent.numocts);
00884     }
00885     else
00886         mhSignedData.pSignedData->encapContentInfo.m.eContentPresent = 0;
00887 
00888     //next, determine the data to be hashed and hash it (this can throw)
00889     m_impl->m_detachedData.FinalizeHashes(cMisc);
00890 
00891     //AddSignerInfos can throw bad_alloc
00892     // GCC doesn't like this->GetMediator() as a function parameter when a reference is required
00893     IPKIFMediatorPtr med = this->GetMediator();
00894     m_impl->AddSignerInfos(mhSignedData.pSignedData, med);
00895 
00896     //set the version
00897     m_impl->CalculateAndSetVersion();
00898     mhSignedData.pSignedData->version = (CACCMSCMSVersion)GetVersion();
00899 
00900     CACASNWRAPPER_CREATE(CACCMSSignedData, objPDU);
00901     ASN1OpenType* data1 = NULL;
00902     
00903     try
00904     {
00905         data1 = objPDU.Encode(mhSignedData.pSignedData);
00906     }
00907     catch(...)
00908     {
00909         //we must remove pre-existing signer infos from the list in the memory helper before cleanup
00910         //re-throw any exception
00911         m_impl->RemoveSignerInfos(mhSignedData.pSignedData);
00912         throw;
00913     }
00914     
00915     CPKIFBufferPtr tmp;
00916     try
00917     {
00918         //copy the buffer info a buffer ptr to be returned to the caller
00919         CPKIFBufferPtr tmpTmp(new CPKIFBuffer((unsigned char*)data1->data, data1->numocts));
00920         tmp = tmpTmp;
00921         delete data1; data1 = NULL;
00922     }
00923     catch(std::bad_alloc& ba)
00924     {
00925         if(data1)
00926             delete data1;
00927         throw ba;
00928     }
00929 
00930     //because we reused any signer infos from the decoded message directly,
00931     //it is necessary to remove them from the list before cleaning up
00932     m_impl->RemoveSignerInfos(mhSignedData.pSignedData);
00933 
00934     //immediately after encoding - decode the message and remove all members
00935     //to keep the object in a suitable state
00936     //XXX-DEFER should the state be maintained in this clear and decode fashion
00937     //      or should another means be implemented (possibly storage of the
00938     //      encoded buffer with state-related macros at the beginning of every 
00939     //      function to trigger decodes as necessary)
00940     ClearContent(false);
00941     Decode(tmp);
00942     m_impl->CallingAllGets();
00943 
00944     return tmp;
00945 }
00969 void CPKIFSignedData::Decode(
00972     CPKIFBufferPtr& buf)
00973 {
00974     LOG_STRING_DEBUG("CPKIFSignedData::Decode(CPKIFBufferPtr& buf)", TOOLKIT_CRYPTO_MISC, 0, this);
00975 
00976     //moved this stuff above input check 2/23/2005 CRW
00977     //make sure hash object is empty (moved up here from below try/catch 10/17/2003)
00978     m_impl->m_detachedData.FreeHashVector();
00979     m_impl->m_bDetached = false; //added 4/8/2003 CRW
00980     ClearContent(false); //added this to clear out all members 2/23/2005 CRW
00981 
00982     //if the input is empty - fail now
00983     if(buf == (CPKIFBuffer*)NULL)
00984     {
00985         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT);
00986     }
00987 
00988     try
00989     {
00990         //otherwise try to parse it into the signed data member
00991         //breakdown of m_signedData into PKIF classes will occur on demand
00992         (*m_impl->m_signedData).Decode(buf->GetBuffer(), buf->GetLength());
00993         m_impl->m_bDecodedContent = true;
00994         m_impl->m_decodeBuf = buf; //gotta keep the raw buffer alive to facilitate object reuse - 10/20/03
00995 
00996         switch((*m_impl->m_signedData)->version)
00997         {
00998         case CACCMSv0:
00999             m_impl->m_version = CPKIFSignedData::CMSv0;
01000             break;
01001         case CACCMSv1:
01002             m_impl->m_version = CPKIFSignedData::CMSv1;
01003             break;
01004         case CACCMSv2:
01005             m_impl->m_version = CPKIFSignedData::CMSv2;
01006             break;
01007         case CACCMSv3:
01008             m_impl->m_version = CPKIFSignedData::CMSv3;
01009             break;
01010         case CACCMSv4:
01011             m_impl->m_version = CPKIFSignedData::CMSv4;
01012             break;
01013         }
01014     }
01015     catch(CPKIFException& e)
01016     {
01017         unsigned char * decoded = NULL;
01018         unsigned long decodedLen;
01019         bool b = PEMDecode((char *)buf->GetBuffer(), &decoded, &decodedLen);
01020         if(b)
01021         {
01022             try
01023             {
01024                 (*m_impl->m_signedData).InitContext();
01025                 (*m_impl->m_signedData).Decode(decoded, decodedLen);
01026 
01027                 CPKIFBufferPtr tmp(new CPKIFBuffer(decoded, decodedLen));
01028                 m_impl->m_bDecodedContent = true;
01029                 m_impl->m_decodeBuf = tmp;
01030 
01031                 switch((*m_impl->m_signedData)->version)
01032                 {
01033                 case CACCMSv0:
01034                     m_impl->m_version = CPKIFSignedData::CMSv0;
01035                     break;
01036                 case CACCMSv1:
01037                     m_impl->m_version = CPKIFSignedData::CMSv1;
01038                     break;
01039                 case CACCMSv2:
01040                     m_impl->m_version = CPKIFSignedData::CMSv2;
01041                     break;
01042                 case CACCMSv3:
01043                     m_impl->m_version = CPKIFSignedData::CMSv3;
01044                     break;
01045                 case CACCMSv4:
01046                     m_impl->m_version = CPKIFSignedData::CMSv4;
01047                     break;
01048                 }
01049 
01050                 if(NULL != decoded)
01051                     delete decoded;
01052 
01053             }catch(CPKIFException& e)
01054             {
01055                 if(NULL != decoded)
01056                     delete decoded;
01057 
01058                 CPKIFMessageException me(thisComponent, MSG_DECODE_FAILED);
01059                 me.push_info(e);
01060                 //delete e;
01061                 throw me;
01062             }
01063         }else
01064         {
01065             if(NULL != decoded)
01066                     delete decoded;
01067             CPKIFMessageException me(thisComponent, MSG_DECODE_FAILED);
01068             me.push_info(e);
01069             throw me;
01070         }
01071     }
01072 }
01073 
01074 //*****************************************************************************
01075 //  message verification (and related) functions
01076 //*****************************************************************************
01077 //Functor<void, TYPELIST_3(const CPKIFCertificateNodeEntryPtr&, CPKIFPathValidationResults&, CertificateType)> keyUsageSigFunctor2(keyUsageChecker_Signature);
01140 bool CPKIFSignedData::Verify(
01142     int signerIndex, 
01144     CMSVerificationStatus& status,
01146     CMSPathValidationStatus minStatus)
01147 {
01148     CPKIFCertificatePtr signersCert; //empty cert object
01149     return m_impl->_Verify(signerIndex, status, signersCert, minStatus);
01150 }
01213 bool CPKIFSignedData::Verify(
01215     int signerIndex, 
01217     CMSVerificationStatus& status, 
01220     CPKIFCertificatePtr& signersCert, 
01222     CMSPathValidationStatus minStatus)
01223 {
01224     return m_impl->_Verify(signerIndex, status, signersCert, minStatus);
01225 }
01226 
01227 #ifndef NEW_VERIFY_FUNC
01228 
01242 bool CPKIFSignedData::_Verify(
01244     int signerIndex, 
01246     CMSVerificationStatus& status, 
01249     CPKIFCertificatePtr& sc, 
01251     CMSPathValidationStatus minStatus)
01252 {
01253     LOG_STRING_DEBUG("CPKIFSignedData::_Verify(int signerIndex,...", TOOLKIT_CRYPTO_MISC, 0, this);
01254 
01255     status = NOT_VERIFIED;
01256 
01257     PKIFFuncStorage keyUsageSigFunctor2(keyUsageChecker_Signature);
01258 
01259     //collect the necessary interfaces:
01260     //      IPKIFCryptoMisc - to prepare hashes
01261     //      IPKIFCryptoRawOperations - to perform signature verification
01262     if(NULL == GetMediator())
01263         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "Mediator is not available.");
01264 
01265     IPKIFCryptoMisc* cMisc = GetMediator()->GetMediator<IPKIFCryptoMisc>();
01266     if(NULL == cMisc)
01267         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCryptoMisc interface is not available.");
01268     IPKIFCryptoRawOperations* cRaw = GetMediator()->GetMediator<IPKIFCryptoRawOperations>();
01269     if(NULL == cRaw)
01270         throw CPKIFMessageException(thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCryptoRawOperations interface is not available.");
01271 
01272     //added 3/17 CRW
01273     if(NULL == m_signedData->data())
01274         throw CPKIFMessageException(thisComponent, MSG_INVALID_STATE, "Message has not been decoded.");
01275 
01276     //see if data was present that needs hashing (if m_bDetached is set then we've already hashed)
01277     if((*m_signedData)->encapContentInfo.m.eContentPresent && !m_bDetached)
01278     {
01279         //if content is present in the message throw out anything that was passed in via UpdateMessage
01280         m_detachedData.FreeHashVector();
01281         m_bDetached = false; //added 04/08/2003 CRW
01282         UpdateMessage((unsigned char*)(*m_signedData)->encapContentInfo.eContent.data, (*m_signedData)->encapContentInfo.eContent.numocts);
01283     }
01284 
01285     CPKIFOIDPtr encapType = GetEncapsulatedContent()->GetOID();
01286 
01287     //finalize all hashes (either initialized above or via external call to UpdateMessage)
01288     m_detachedData.FinalizeHashes(cMisc);
01289 
01290     //iterate over all signed infos
01291     bool b = false;
01292     HASH_ALG hashAlg;
01293     DListNode* cur = (*m_signedData)->signerInfos.head;
01294     for(int ii = 0; ii < signerIndex && NULL != cur; ++ii)
01295         cur = cur->next;
01296 
01297     if(NULL == cur)
01298         throw CPKIFMessageException(thisComponent, MSG_INVALID_INDEX, "signerIndex is invalid.");
01299 
01300     CACCMSSignerInfo* si = (CACCMSSignerInfo*)cur->data;
01301     CPKIFBufferPtr signerCert;
01302 
01303     bool deleteHI = false;
01304 
01305     //see if a cert was passed in - if so use it - if not look in the signers info for the cert
01306     if(sc != (CPKIFCertificate*)NULL)
01307         signerCert = sc->Encoded();
01308     else
01309     {
01310         CPKIFCertificatePtr tmpSC;
01311         GetSignersCert(signerIndex, tmpSC);
01312         if(tmpSC != (CPKIFCertificate*)NULL)
01313             signerCert = tmpSC->Encoded();
01314     }
01315 
01316     //if we got a cert - try to get a hash alg and continue
01317     if(signerCert != (CPKIFBuffer*)NULL && GetCACHashAlg(&si->digestAlgorithm, &hashAlg))
01318     {
01319         //if we got a hash alg try to get a hash result
01320         HashInfo* hi = NULL;
01321 
01322         if(!si->m.signedAttrsPresent)
01323         {
01324             //if no signed attrs are present then retrieve the hash of the data     
01325             hi = m_detachedData.GetHashInfo(hashAlg);
01326         }
01327         else
01328         {
01329             //get the hash of the data
01330             HashInfo* hi2 = m_detachedData.GetHashInfo(hashAlg);
01331 
01332             //then compute the hash over the signed attrs (this will be used for verification below)
01333             hi = ComputeSignedAttrHash(si, cMisc);
01334             deleteHI = true;
01335 
01336             if(!CompareHashes(hi2, si))
01337             {
01338                 //if hash of data does not match the hash contained in the signed attr bag
01339                 //or if there is no content hash in the signed attr bag then fail
01340                 status = CMS_SIGNATURE_INVALID;
01341                 return false;
01342             }
01343 
01344             //added 04/28/2003
01345             CPKIFSignerInfo tmpSI(*si);
01346             CPKIFContentTypeAttributePtr ct = tmpSI.GetSignedAttribute<CPKIFContentTypeAttribute>();
01347             if(ct == (CPKIFContentTypeAttribute*)NULL)
01348             {
01349                 status = CMS_SIGNATURE_INVALID;
01350                 return false;
01351             }
01352             else
01353             {
01354                 CPKIFOIDPtr ctType = ct->GetContentType();
01355                 if(ctType == (CPKIFOID*)NULL || !(*ctType == *encapType))
01356                 {
01357                     status = CMS_SIGNATURE_INVALID;
01358                     return false;
01359                 }
01360             }
01361                 
01362         }
01363 
01364         if(NULL != hi)
01365         {
01366             //if we got a hash result fix up a key material class and try to verify the signature
01367             CPKIFKeyMaterial key;
01368             key.SetCertificate(signerCert->GetBuffer(), signerCert->GetLength());
01369 
01370             if(!cRaw->Verify(key, hi->m_hashResult, hi->m_hashAlg, (unsigned char*)si->signature.data, si->signature.numocts))
01371             {
01372                 if(NULL != hi && deleteHI)
01373                     delete hi;
01374                 status = CMS_SIGNATURE_INVALID;
01375                 return false;
01376             }
01377             else
01378             {
01379                 if(NULL != hi && deleteHI)
01380                     delete hi;
01381                 status = CMS_SIGNATURE_VERIFIED;
01382             }
01383         }
01384         else
01385         {
01386             throw CPKIFMessageException(thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm.");       
01387         }       
01388     }
01389     else
01390     {
01391         throw CPKIFMessageException(thisComponent, MSG_NO_CERTIFICATE, "No signers certificate was present in the message.");
01392     }
01393 
01394     //added 04/26/2003 - CRW
01395     if(PVS_NOT_VALIDATED == minStatus)
01396         return true;
01397 
01398     IPKIFPathBuild* cBuild = GetMediator()->GetMediator<IPKIFPathBuild>();
01399     if(NULL == cBuild)
01400         return false;
01401 
01402     IPKIFPathValidate* cValidate = GetMediator()->GetMediator<IPKIFPathValidate>();
01403     if(NULL == cValidate)
01404         return false;
01405 
01406     CPKIFCertificatePathPtr tmpPath(new CPKIFCertificatePath);
01407     m_path = tmpPath;
01408 
01409     CPKIFPathValidationResultsPtr tmpValResults(new CPKIFPathValidationResults);
01410     m_valResults = tmpValResults;
01411 
01412     CPKIFCertificatePtr signersCert(new CPKIFCertificate());
01413     signersCert->Decode(signerCert->GetBuffer(), signerCert->GetLength());
01414     m_path->SetTarget(signersCert);
01415 
01416     //if settings have been associated with this object use them
01417     //otherwise defer to the default settings (either globally set
01418     //or defined to be very permissive)
01419     if(m_settings != (CPKIFPathSettings*)NULL)
01420         m_path->SetPathSettings(m_settings);
01421 
01422     try
01423     {
01424         do
01425         {
01426             if(!cBuild->BuildPath(*m_path))
01427             {
01428                 return false;
01429             }
01430             if(cValidate->ValidatePath(*m_path, *m_valResults, &keyUsageSigFunctor2))
01431             {
01432                 if(NOT_REVOKED == m_valResults->GetRevocationStatusMostSevere())
01433                 {
01434                     status = REV_STATUS_VERIFIED;
01435                     return true;    
01436                 }
01437                 else
01438                 {
01439                     status = CERT_PATH_VERIFIED;
01440                     return PVS_REV_STATUS_VERIFIED > minStatus; //return true only if min status
01441                                                                 //is less than rev status verified
01442                 }
01443             }
01444             else
01445             {
01446                 if(!m_valResults->GetBasicChecksSuccessfullyPerformed() ||
01447                     !m_valResults->GetCertSignaturesVerified())
01448                 {
01449                     status = CERT_PATH_INVALID; //set the status but keep looking
01450                 }
01451                 else if(REVOKED == m_valResults->GetRevocationStatusMostSevere())
01452                 {
01453                     status = REV_STATUS_INVALID;
01454 
01455                     //see if the signer was revoked - if so, stop looking and return false now
01456                     //if they don't match then a CA cert was revoked and we should keep looking
01457                     //for a good path
01458                     CPKIFCertificateNodeEntryPtr errantCertNode = m_valResults->GetCertificate();
01459                     if(errantCertNode != (CPKIFCertificateNodeEntry*)NULL)
01460                     {
01461                         CPKIFCertificatePtr errantCert = errantCertNode->GetCert();
01462                         if(errantCert != (CPKIFCertificate*)NULL && *errantCert == *signersCert)
01463                             return false;
01464                     }
01465                 }
01466                 else if(m_valResults->GetBasicChecksSuccessfullyPerformed() &&
01467                     m_valResults->GetCertSignaturesVerified())
01468                 {
01469                     status = CERT_PATH_VERIFIED; //verification successful but revocation not checked
01470                     if(PVS_REV_STATUS_VERIFIED > minStatus) //if min say OK return true - else keep looking
01471                         return true;
01472                 }
01473             }
01474         }while(1);
01475     }
01476     catch(CPKIFException& e)
01477     {
01478         LOG_STRING_ERROR(e.print()->c_str(), thisComponent, COMMON_UNKNOWN_ERROR, this);
01479         return false;
01480     }
01481 }
01482 #endif
01483 
01493 void CPKIFSignedData::SetPathSettings(
01495     CPKIFPathSettingsPtr& settings)
01496 {
01497     //do allow NULL to be passed to clear out any custom path settings in favor of defaults
01498     m_impl->m_settings = settings;
01499 }
01509 CPKIFCertificatePathPtr CPKIFSignedData::GetPath() const
01510 {
01511     return m_impl->m_path;
01512 }
01520 CPKIFPathValidationResultsPtr CPKIFSignedData::GetValidationResults() const
01521 {
01522     return m_impl->m_valResults;
01523 }
01537 void CPKIFSignedData::GetSignersCert(
01539     int signerIndex,
01541     CPKIFCertificatePtr& cert)
01542 {
01543     LOG_STRING_DEBUG("CPKIFSignedData::GetSignersCert(int signerIndex, CPKIFCertificatePtr& cert)", TOOLKIT_CRYPTO_MISC, 0, this);
01544 
01545     if(NULL == m_impl->m_signedData || NULL == (*m_impl->m_signedData).data())
01546         throw CPKIFMessageException(thisComponent, MSG_INVALID_STATE, "Decoded message not present.");
01547 
01548     CPKIFCertificatePtr emptyCert;
01549     cert = emptyCert;
01550 
01551     DListNode* cur = (*m_impl->m_signedData)->signerInfos.head;
01552     for(int ii = 0; ii < signerIndex && NULL != cur; ++ii)
01553         cur = cur->next;
01554 
01555     if(NULL == cur)
01556         return;
01557 
01558     CACCMSSignerInfo* si = (CACCMSSignerInfo*)cur->data;
01559     CPKIFBufferPtr signerCert = m_impl->GetSignersCert(si);
01560     if (signerCert == (CPKIFBuffer*)NULL)
01561         return;
01562 
01563     //throw bad_alloc
01564     CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
01565 
01566     //throw PKIFException
01567     tmpCert->Decode(signerCert->GetBuffer(), signerCert->GetLength());
01568 
01569     //set outbound cert variable to the parsed cert
01570     cert = tmpCert;
01571 }
01580 size_t CPKIFSignedData::GetNumberOfSigners() const
01581 {
01582     LOG_STRING_DEBUG("CPKIFSignedData::GetNumberOfSigners()", TOOLKIT_CRYPTO_MISC, 0, this);
01583 
01584     if(NULL == m_impl->m_signedData || NULL == (*m_impl->m_signedData).data())
01585         return 0;
01586     else if((*m_impl->m_signedData)->signerInfos.count > 0)
01587         return (*m_impl->m_signedData)->signerInfos.count;
01588     else
01589     {
01590         //added this and if after the else above 10/21/2003
01591         //we've already reset the signerInfo count and everything is in the sis array
01592         return m_impl->m_signerInfos.size();
01593     }
01594 }
01605 CPKIFSignerInfoPtr CPKIFSignedData::GetSignersInfo(
01607     int signerIndex)
01608 {
01609     LOG_STRING_DEBUG("CPKIFSignedData::GetSignersInfo()", TOOLKIT_CRYPTO_MISC, 0, this);
01610 
01611     CPKIFSignerInfoPtr tmpSI;
01612     if(NULL == m_impl->m_signedData || NULL == (*m_impl->m_signedData).data())
01613         throw CPKIFMessageException(thisComponent, COMMON_INVALID_INPUT, "Decoded message not present.");
01614 
01615     DListNode* cur = (*m_impl->m_signedData)->signerInfos.head;
01616     for(int ii = 0; ii < signerIndex && NULL != cur; ++ii)
01617         cur = cur->next;
01618 
01619     if(NULL == cur)
01620         return tmpSI;
01621 
01622     CACCMSSignerInfo* si = (CACCMSSignerInfo*)cur->data;
01623     CACASNWRAPPER_CREATE(CACCMSSignerInfo, InfoWrapper); 
01624     ASN1OpenType *data = InfoWrapper.Encode(si);
01625     CPKIFBufferPtr siBuf(new CPKIFBuffer(data->data, data->numocts));
01626     delete data;
01627 
01628     //throw bad_alloc or PKIFException
01629     //CPKIFSignerInfoPtr sip(new CPKIFSignerInfo(*si));
01630     CPKIFSignerInfoPtr sip(new CPKIFSignerInfo(siBuf));
01631     return sip;
01632 }
01633 
01634 //*****************************************************************************
01635 //  private functions
01636 //*****************************************************************************
01645 void CPKIFSignedDataImpl::AddCerts(
01647     CACCMSSignedData* signedData)
01648 {
01649     LOG_STRING_DEBUG("CPKIFSignedData::AddCerts(CACCMSSignedData* signedData)", TOOLKIT_CRYPTO_MISC, 0, this);
01650 
01651     //get the complete list of certs that should be included in the message
01652     CPKIFCertificateList certs;
01653     m_parent->GetCertificates(certs);
01654 
01655     //if there are certs in one of the sources proceed.  first set count to zero
01656     //and presence indicator to true.
01657     signedData->certificates.count = 0;
01658 
01659     if(certs.empty())
01660     {
01661         //bail out if there are no certs to include
01662         signedData->m.certificatesPresent = 0;
01663         return;
01664     }
01665     else
01666         signedData->m.certificatesPresent = 1;
01667 
01668     DListNode* cur = NULL;
01669 
01670     //iterate over certs in m_certificates list
01671     CPKIFCertificateList::iterator certPos; 
01672     CPKIFCertificateList::iterator certEnd = certs.end();
01673     for(certPos = certs.begin(); certPos != certEnd; ++certPos)
01674     {
01675         //throw bad_alloc - memory helper in the caller will handle clean up    
01676         if(NULL == cur)
01677         {
01678             NEW_NODE(cur)
01679         }
01680         else
01681         {
01682             NEW_NEXT_AND_ADVANCE(cur)
01683         }
01684 
01685         CACCMSCertificateChoices* tmpChoice = new CACCMSCertificateChoices;
01686         tmpChoice->t = T_CACCMSCertificateChoices_certificate;
01687         tmpChoice->u.certificate = new ASN1OpenType;
01688         
01689         //certs were screened when added to make sure the encoded buffer existed
01690         tmpChoice->u.certificate->data = (*certPos)->Encoded()->GetBuffer();
01691         tmpChoice->u.certificate->numocts = (*certPos)->Encoded()->GetLength();
01692         
01693         cur->data = tmpChoice;
01694 
01695         SET_HEAD_TAIL_INCREMENT(signedData->certificates, cur)
01696     }   
01697 }
01706 void CPKIFSignedDataImpl::AddCRLs(
01708     CACCMSSignedData* signedData)
01709 {
01710     LOG_STRING_DEBUG("CPKIFSignedData::AddCRLs(CACCMSSignedData* signedData)", TOOLKIT_CRYPTO_MISC, 0, this);
01711 
01712     //get the complete list of crls that should be included in the message
01713     CPKIFCRLList crls;
01714     m_parent->GetCRLs(crls);
01715 
01716     //if there are crls in one of the sources proceed.  first set count to zero
01717     //and presence indicator to true.
01718     signedData->crls.count = 0;
01719 
01720     if(crls.empty())
01721     {
01722         signedData->m.crlsPresent = 0;
01723         return;
01724     }
01725     else
01726         signedData->m.crlsPresent = 1;
01727 
01728     DListNode* cur = NULL;
01729 
01730     //iterate over certs in m_certificates list
01731     CPKIFCRLList::iterator crlPos;  
01732     CPKIFCRLList::iterator crlEnd = crls.end();
01733     for(crlPos = crls.begin(); crlPos != crlEnd; ++crlPos)
01734     {
01735         //throw bad_alloc - memory helper in the caller will handle clean up    
01736         if(NULL == cur)
01737         {
01738             NEW_NODE(cur)
01739         }
01740         else
01741         {
01742             NEW_NEXT_AND_ADVANCE(cur)
01743         }
01744 
01745         CACCMSRevocationInfoChoice* revChoice = new CACCMSRevocationInfoChoice;
01746         revChoice->t = T_CACCMSRevocationInfoChoice_crl;
01747         revChoice->u.crl = new ASN1OpenType;
01748 
01749         //crls were screened when added to make sure the encoded buffer existed
01750         revChoice->u.crl->data = (*crlPos)->Encoded()->GetBuffer();
01751         revChoice->u.crl->numocts = (*crlPos)->Encoded()->GetLength();
01752 
01753         cur->data = revChoice;
01754 
01755         SET_HEAD_TAIL_INCREMENT(signedData->crls, cur)
01756     }   
01757 }
01765 void CPKIFSignedDataImpl::BuildDigestAlgList(
01767     CACCMSSignedData* signedData)
01768 {
01769     LOG_STRING_DEBUG("CPKIFSignedData::BuildDigestAlgList(CACCMSSignedData* signedData)", TOOLKIT_CRYPTO_MISC, 0, this);
01770 
01771     //need to build a list of algs from m_signerInfos and from m_signedData
01772     DListNode* cur = NULL;
01773     
01774     //declare an iterator that will identify the end of the growing list each iteration
01775     CCACDigestAlgorithmIdentifiers::iterator digAlgsEnd;
01776 
01777     //clear the lists of digest algs
01778     m_digestAlgorithms.clear();
01779     signedData->digestAlgorithms.count = 0;
01780 
01781     //add all algs from the decoded structure
01782     if(m_signedData && (*m_signedData).data())
01783     {
01784         DListNode* existing = (*m_signedData)->digestAlgorithms.head;
01785         while(NULL != existing)
01786         {
01787             //throw either bad_alloc or CPKIFException
01788 
01789             //CPKIFAlgorithmIdentifier creation
01790             CPKIFOIDPtr algOID(new CPKIFOID(((CACX509V3AlgorithmIdentifier*)existing->data)->algorithm.subid,
01791                                 ((CACX509V3AlgorithmIdentifier*)existing->data)->algorithm.numids));
01792                         CPKIFBufferPtr paramBuf;
01793             if(((CACX509V3AlgorithmIdentifier*)existing->data)->m.parametersPresent)
01794             {
01795                 paramBuf = CPKIFBufferPtr(new CPKIFBuffer(((CACX509V3AlgorithmIdentifier*)existing->data)->parameters.data,
01796                             ((CACX509V3AlgorithmIdentifier*)existing->data)->parameters.numocts));
01797             
01798             
01799             }
01800             
01801             CPKIFAlgorithmIdentifierPtr tmpAlg(new CPKIFAlgorithmIdentifier(algOID, paramBuf)); 
01802             //CPKIFAlgorithmIdentifierPtr tmpAlg(new CPKIFAlgorithmIdentifier(*((CACX509V3AlgorithmIdentifier*)existing->data)));   
01803 
01804             //assume that the same alg didn't appear in an encoded message twice
01805             m_digestAlgorithms.push_back(tmpAlg);
01806 
01807             existing = existing->next;
01808         }
01809     }
01810 
01811     //iterate over m_signerInfos
01812     CPKIFSignerInfoList::iterator pos;
01813     CPKIFSignerInfoList::iterator end = m_signerInfos.end();
01814     for(pos = m_signerInfos.begin(); pos != end; ++pos)
01815     {
01816         //get the alg from the current signer info object
01817         CPKIFAlgorithmIdentifierPtr digestAlg = (*pos)->GetDigestAlg();
01818 
01819         //get end of the current alg list
01820         digAlgsEnd = m_digestAlgorithms.end();
01821 
01822         //set up a predicate object to handle alg ID comparison
01823         GottaMatch<CPKIFAlgorithmIdentifierPtr> gm;
01824         gm.SetRHS(digestAlg);
01825 
01826         //search the m_digestAlgorithms and see if the alg from cur signer is already in the list
01827         if(digAlgsEnd == find_if(m_digestAlgorithms.begin(), m_digestAlgorithms.end(), gm))
01828         {
01829             //if not alread in the list - add it
01830             m_digestAlgorithms.push_back(digestAlg);
01831         }
01832     }
01833 
01834     //at this point m_digestAlgorithms has everything from the decoded message and any
01835     //algs from m_signerInfos that weren't present in the decoded set
01836     if(!m_digestAlgorithms.empty())
01837     {
01838         //now we iterate over the list and prepare an objective structure
01839         //containing the algs that will be present in the message
01840         CCACDigestAlgorithmIdentifiers::iterator pos;
01841         CCACDigestAlgorithmIdentifiers::iterator end = m_digestAlgorithms.end();
01842         for(pos = m_digestAlgorithms.begin(); pos != end; ++pos)
01843         {
01844             CPKIFAlgorithmIdentifierPtr digestAlg = (*pos);
01845 
01846             if(NULL == cur)
01847             {
01848                 NEW_NODE(cur)
01849             }
01850             else
01851             {
01852                 NEW_NEXT_AND_ADVANCE(cur)
01853             }
01854 
01855             //build list in Objective structure (throw bad_alloc - memory helper in caller will clean
01856             //up any previously allocated memory)
01857             CACX509V3AlgorithmIdentifier* tmpDA = new CACX509V3AlgorithmIdentifier;
01858 
01859             tmpDA->m.parametersPresent = 1;
01860             tmpDA->parameters.data = g_nullParams;
01861             tmpDA->parameters.numocts = 2;
01862             CPKIFStringPtr str(new std::string(digestAlg->oid()->ToString())); 
01863             ASN1OBJID* tmpOid = ConvertStringToASN1OBJID(str);
01864 
01865             CopyOID(&tmpDA->algorithm, tmpOid);
01866 
01867             if( NULL != tmpOid)
01868                 delete tmpOid;
01869             //tmpDA->algorithm = *(digestAlg->oid()->raw());
01870             //tmpDA->algorithm = *tmpOid;
01871 
01872             cur->data = (void*)tmpDA;
01873 
01874             SET_HEAD_TAIL_INCREMENT(signedData->digestAlgorithms, cur)
01875         }
01876     }
01877 }
01888 void CPKIFSignedDataImpl::AddSignerInfos(
01890     CACCMSSignedData* signedData,
01892     IPKIFMediatorPtr& cm)
01893 {
01894     LOG_STRING_DEBUG("CPKIFSignedData::AddSignerInfos(CACCMSSignedData* signedData, IPKIFMediator* cm)", TOOLKIT_CRYPTO_MISC, 0, this);
01895 
01896     //set the count to zero - it will be incremented for each decoded signer and each signer
01897     //added via AddSignerInfo
01898     signedData->signerInfos.count = 0;
01899 
01900     //first, add any signer infos that were present in the decoded message
01901     if(NULL != m_signedData && NULL != (*m_signedData).data() && (*m_signedData)->signerInfos.count > 0)
01902     {
01903         DListNode* cur = NULL;
01904         DListNode* existing = (*m_signedData)->signerInfos.head;
01905         while(NULL != existing)
01906         {
01907             //throw bad_alloc
01908             if(NULL == cur)
01909             {
01910                 NEW_NODE(cur)
01911             }
01912             else
01913             {
01914                 NEW_NEXT_AND_ADVANCE(cur)
01915             }
01916 
01917             cur->data = existing->data;
01918 
01919             existing = existing->next;
01920 
01921             SET_HEAD_TAIL_INCREMENT(signedData->signerInfos, cur)
01922         }
01923     }
01924 
01925     //next, see if there are any newly added signers - if not return now
01926     if(m_signerInfos.empty())
01927         return;
01928 
01929     //if so proceed
01930     DListNode* cur = NULL;
01931     
01932     PKIFCRYPTO::HASH_ALG hashAlg;
01933     CPKIFSignerInfoList::iterator siPos;
01934     CPKIFSignerInfoList::iterator siEnd = m_signerInfos.end();
01935     for(siPos = m_signerInfos.begin(); siPos != siEnd; ++siPos)
01936     {
01937         CACCMSSignerInfo* tmpSignerInfo = new CACCMSSignerInfo;
01938 
01939         if(!GetCACHashAlg((*siPos)->GetDigestAlg()->oid(), &hashAlg))
01940         {
01941             delete tmpSignerInfo;
01942 
01943             //remove any existing signer infos from the list
01944             RemoveSignerInfos(signedData);
01945 
01946             //XXX-DEFER It may be better to produce as many signer infos as possible
01947             //          and report a collection of failures.  for now if one fails all fail
01948             //continue;
01949             throw CPKIFMessageException(m_parent->thisComponent, COMMON_UNSUPPORTED_ALG, "SignerInfo contains an unsupported hash algorithm.");
01950         }
01951 
01952         HashInfo* hi = m_detachedData.GetHashInfo(hashAlg);
01953         //moved failure to GetSignerInfo to support reenocding of existing
01954         //signers when adding a timestamp to an object with detached data
01955         //if(NULL == hi)
01956         //{
01957         //  //remove any existing signer infos from the list
01958         //  RemoveSignerInfos(signedData);
01959 
01960         //  //clean up what we just allocated
01961         //  delete tmpSignerInfo;
01962 
01963         //  //pass the exception on to the caller
01964         //  throw CPKIFMessageException(thisComponent, COMMON_UNSUPPORTED_ALG, "SignerInfo contains an unsupported hash algorithm.");
01965         //}
01966 
01967         try
01968         {
01969             if(hi) 
01970             {
01971             CPKIFOIDPtr encapCIOID = m_encapContentInfo->GetOID();
01972             GetSignerInfo(tmpSignerInfo, *siPos, hi->m_hashResult, hi->m_hashAlg, cm, encapCIOID, hi->m_hashAlg);
01973             //GetSignerInfo(tmpSignerInfo, *siPos, hi->m_hashResult, hi->m_hashAlg, cm, m_encapContentInfo->GetOID());
01974             } else {
01975             CPKIFOIDPtr encapCIOID = m_encapContentInfo->GetOID();
01976             GetSignerInfo(tmpSignerInfo, *siPos, NULL, 0, cm, encapCIOID, PKIFCRYPTO::SHA1); //This will throw an exception so hash type doesn't matter
01977             }
01978         }
01979         catch(CPKIFException& e)
01980         {
01981             //remove any existing signer infos from the list
01982             RemoveSignerInfos(signedData);
01983 
01984             //clean up what we just allocated
01985             delete tmpSignerInfo;
01986 
01987             //pass the exception on to the caller
01988             throw e;
01989         }
01990 
01991         if(NULL == cur)
01992         {
01993             NEW_NODE(cur)
01994         }
01995         else
01996         {
01997             NEW_NEXT_AND_ADVANCE(cur)
01998         }
01999 
02000         cur->data = (void*)tmpSignerInfo;
02001 
02002         SET_HEAD_TAIL_INCREMENT(signedData->signerInfos, cur)
02003     }
02004 }
02013 void CPKIFSignedDataImpl::RemoveSignerInfos(
02015     CACCMSSignedData* signedData)
02016 {
02017     LOG_STRING_DEBUG("CPKIFSignedData::RemoveSignerInfos(CACCMSSignedData* signedData)", TOOLKIT_CRYPTO_MISC, 0, this);
02018 
02019     //the purpose of this function is to disassociate previously existing signer info objects from
02020     //newly created signer info objects so we don't end up freeing things twice.  essentially, the
02021     //signer infos from a decoded message are temporarily patched into the signer info list of a
02022     //newly encoded message and must be removed before the memory helper object fires.
02023     if(NULL != m_signedData && NULL != (*m_signedData).data() && (*m_signedData)->signerInfos.count)
02024     {
02025         //added tmp stuff 11/11/2003
02026         DListNode* cur = signedData->signerInfos.head, *tmp;
02027         for(unsigned int ii = 0; ii < (*m_signedData)->signerInfos.count && NULL != cur; ++ii, --signedData->signerInfos.count)
02028         {
02029             tmp = cur;
02030             cur = cur->next;
02031             delete tmp;
02032         }
02033         signedData->signerInfos.head = cur;
02034     }
02035 }
02043 void CPKIFSignedDataImpl::CalculateAndSetVersion()
02044 {
02045     LOG_STRING_DEBUG("CPKIFSignedData::CalculateAndSetVersion()", TOOLKIT_CRYPTO_MISC, 0, this);
02046 
02047     //RFC3369 defines a simple algorithm to calculate the version.  It's not quite implemented here
02048     //because we provide no support for attribute certificates
02049 
02050     //assume the version is one
02051     m_version = CPKIFSignedData::CMSv1;
02052 
02053     CPKIFEncapsulatedContentInfoPtr ecip = m_parent->GetEncapsulatedContent();
02054     if(ecip == (CPKIFEncapsulatedContentInfo*)NULL)
02055         return; //should never happen - ths function is only called inside Encode and it requires an ecip
02056 
02057     CPKIFOIDPtr encapType = ecip->GetOID();
02058     if(encapType == (CPKIFOID*)NULL)
02059         return; //ditto - Encode requires an ecip OID
02060 
02061     if(!(*g_data == *encapType))
02062     {
02063         m_version = CPKIFSignedData::CMSv3;
02064         return;
02065     }
02066 
02067     //CPKIFSignerInfoList sis;
02068     //GetSignerInfos(sis);
02069 
02070     //CPKIFSignerInfoList::iterator pos;
02071     //CPKIFSignerInfoList::iterator end = sis.end();
02072     //for(pos = sis.begin(); pos != end; ++pos)
02073     //{
02074     //  if((*pos)->Version() == CMSv3)
02075     //  {
02076     //      m_version = CMSv3;
02077     //      return;
02078     //  }
02079     //}
02080 
02081     //due to the fact that calling GetSignerInfos removes entries from the 
02082     //objective structure and stores PKIF versions in a vector, the above code
02083     //will not do in this spot.  we need to iterate over the objective structures
02084     //directly.
02085     if((*m_signedData).data() != NULL && 0 != (*m_signedData)->signerInfos.count)
02086     {
02087         DListNode* cur = (*m_signedData)->signerInfos.head;
02088         while(NULL != cur)
02089         {
02090             CACCMSSignerInfo* tmp = (CACCMSSignerInfo*)cur->data;
02091             if(tmp->version == CPKIFSignedData::CMSv3)
02092             {
02093                 m_version = CPKIFSignedData::CMSv3;
02094                 return;
02095             }
02096             cur = cur->next;
02097         }
02098     }
02099 
02100     return;
02101 }
02102 
02110 CPKIFBufferPtr CPKIFSignedData::GetSignersCert(
02112     CPKIFBufferPtr tmpSignerInfoBuf
02113     /*CACCMSSignerInfo* tmpSignerInfo*/)
02114 {
02115     LOG_STRING_DEBUG("CPKIFSignedData::GetSignersCert(CACCMSSignerInfo* tmpSignerInfo)", TOOLKIT_CRYPTO_MISC, 0, this);
02116 
02117     CACASNWRAPPER_CREATE(CACCMSSignerInfo, tmpPDU);
02118     //shared_ptr<CACCMSSignerInfo> tmpSignerInfo (tmpPDU.Decode(tmpSignerInfoBuf->GetBuffer(), tmpSignerInfoBuf->GetLength()));
02119     CACCMSSignerInfo* tmpSignerInfo = tmpPDU.Decode(tmpSignerInfoBuf->GetBuffer(), tmpSignerInfoBuf->GetLength());
02120 
02121 
02122     //given a signer info structure search the cert bag for the signer's certificate
02123 
02124     CPKIFNamePtr issuer;
02125     const char* serial = NULL;
02126     CPKIFBufferPtr skid;
02127 
02128     if(NULL == tmpSignerInfo || NULL == m_impl->m_signedData || NULL == m_impl->m_signedData->data()) 
02129         return skid; //not returning skid - just a handy empty buffer object
02130 
02131     //first determine if we are searching using key id or iss dn/serial number
02132     if(1 == tmpSignerInfo->sid.t)
02133     {
02134         //issuer/serial
02135         serial = tmpSignerInfo->sid.u.issuerAndSerialNumber->serialNumber;
02136 
02137         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
02138         ASN1OpenType* data1 = objPDU.Encode(&(tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer));
02139         CPKIFBufferPtr tmpBuf;
02140         if(data1 != NULL)
02141         {
02142              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
02143             delete data1;
02144         }
02145         CPKIFNamePtr tmpNP(new CPKIFName(tmpBuf));
02146         //CPKIFNamePtr tmpNP(new CPKIFName(tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer));
02147         issuer = tmpNP;
02148     }
02149     else if(2 == tmpSignerInfo->sid.t)
02150     {
02151         //skid
02152         CPKIFBufferPtr tmpBP(new CPKIFBuffer(tmpSignerInfo->sid.u.subjectKeyIdentifier->data, tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts));
02153         skid = tmpBP;
02154     }
02155     else
02156     {
02157         CPKIFBufferPtr tmpBP;
02158         return tmpBP;
02159     }
02160 
02161     //iterate over all certs in the cert bag
02162     DListNode* cur = NULL;
02163     if((*m_impl->m_signedData)->m.certificatesPresent && 0 < (*m_impl->m_signedData)->certificates.count)   //added 11/6/2003 - head is not necessarily NULL 
02164         cur = (*m_impl->m_signedData)->certificates.head;
02165     while(NULL != cur)
02166     {
02167         CACCMSCertificateChoices* curChoice = (CACCMSCertificateChoices*)cur->data;
02168         if(T_CACCMSCertificateChoices_certificate != curChoice->t)
02169         {
02170             cur = cur->next;
02171             continue;
02172         }
02173 
02174         ASN1OpenType* curCert = (ASN1OpenType*)curChoice->u.certificate;
02175 
02176         try
02177         {
02178             //convert to a PKIF object
02179             CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
02180             tmpCert->Decode(curCert->data, curCert->numocts);
02181 
02182             //see if there's a match - if so return a buffer containing raw cert
02183             if(NULL != serial && issuer != (CPKIFName*)NULL)
02184             {
02185                 if(0 == strcmp(serial, tmpCert->SerialNumber()) &&
02186                     *issuer == *tmpCert->Issuer())
02187                     return tmpCert->Encoded();
02188             }
02189             else
02190             {
02191                 CPKIFSubjectKeyIdentifierPtr skidFromCert = tmpCert->GetExtension<CPKIFSubjectKeyIdentifier>();
02192                 if(skidFromCert != (CPKIFSubjectKeyIdentifier*)NULL)
02193                 {
02194                     CPKIFBufferPtr skidValue = skidFromCert->KeyIdentifier();
02195                     if(*skidValue == *skid)
02196                         return tmpCert->Encoded();
02197                 }
02198             }
02199         }
02200         catch(CPKIFException&)
02201         {
02202             //EXCEPTION DELETION
02203             //eat any exceptions - if we fail to find a cert we'll report that but
02204             //not any failures to parse certs in the bag
02205             //delete e;
02206         }
02207 
02208         cur = cur->next;
02209     }   
02210 
02211     CPKIFCertificateList certBagContents;
02212     GetCertificates(certBagContents);
02213 
02214     CPKIFCertificateList::iterator cPos;
02215     CPKIFCertificateList::iterator cEnd = certBagContents.end();
02216     for(cPos = certBagContents.begin(); cPos != cEnd; ++cPos)
02217     {
02218         try
02219         {
02220             //see if there's a match - if so return a buffer containing raw cert
02221             if(NULL != serial && issuer != (CPKIFName*)NULL)
02222             {
02223                 if(0 == strcmp(serial, (*cPos)->SerialNumber()) &&
02224                     *issuer == *(*cPos)->Issuer())
02225                     return (*cPos)->Encoded();
02226             }
02227             else
02228             {
02229                 CPKIFSubjectKeyIdentifierPtr skidFromCert = (*cPos)->GetExtension<CPKIFSubjectKeyIdentifier>();
02230                 if(skidFromCert != (CPKIFSubjectKeyIdentifier*)NULL)
02231                 {
02232                     CPKIFBufferPtr skidValue = skidFromCert->KeyIdentifier();
02233                     if(*skidValue == *skid)
02234                         return (*cPos)->Encoded();
02235                 }
02236             }
02237         }
02238         catch(CPKIFException&)
02239         {
02240             //EXCEPTION DELETION
02241             //eat any exceptions - if we fail to find a cert we'll report that but
02242             //not any failures to parse certs in the bag
02243             //delete e;
02244         }
02245 
02246     }
02247 
02248 
02249     try
02250     {
02251         //if we get here then we's empty handed.  poke around any associated cert stores
02252         //if a search interface is available
02253         IPKIFCertSearch* certSearch = NULL;
02254         if(NULL != GetMediator())
02255             certSearch = GetMediator()->GetMediator<IPKIFCertSearch>();
02256         if(NULL != certSearch)
02257         {
02258             CPKIFCertificateList certList;
02259             if(1 == tmpSignerInfo->sid.t)
02260             {
02261                 //issuer/serial
02262                 CPKIFIssuerNameAndSerialNumberBasedSearch inasnbs;
02263                 inasnbs.SetIssuerName(issuer);
02264                             // new
02265                 CPKIFStringPtr serialStr (new std::string(serial));
02266                 inasnbs.SetSerialNumber(serialStr);
02267                 
02268                 // old
02269                             //inasnbs.SetSerialNumber(CPKIFStringPtr(new std::string(serial)));
02270 
02271                 certSearch->FindCertificates(&inasnbs, certList, ALL);
02272             }
02273             else if(2 == tmpSignerInfo->sid.t)
02274             {
02275                 //skid
02276                 CPKIFKeyIDBasedSearch kidbs;
02277                 kidbs.SetKeyID(skid);
02278 
02279                 certSearch->FindCertificates(&kidbs, certList, ALL);
02280             }
02281 
02282             //it's possible that we find more than one cert - however we'll just operate using the first one
02283             if(!certList.empty())
02284             {
02285                 return certList.front()->Encoded();
02286             }
02287         }
02288     }
02289     catch(...)
02290     {
02291     }
02292 
02293     CPKIFBufferPtr tmpBP;
02294     return tmpBP;
02295 }
02296 
02305 CPKIFBufferPtr CPKIFSignedDataImpl::GetSignersCert(
02307     CACCMSSignerInfo* tmpSignerInfo)
02308 {
02309     LOG_STRING_DEBUG("CPKIFSignedData::GetSignersCert(CACCMSSignerInfo* tmpSignerInfo)", TOOLKIT_CRYPTO_MISC, 0, this);
02310 
02311     //given a signer info structure search the cert bag for the signer's certificate
02312 
02313     CPKIFNamePtr issuer;
02314     const char* serial = NULL;
02315     CPKIFBufferPtr skid;
02316 
02317     if(NULL == tmpSignerInfo || NULL == m_signedData || NULL == m_signedData->data())
02318         return skid; //not returning skid - just a handy empty buffer object
02319 
02320     //first determine if we are searching using key id or iss dn/serial number
02321     if(1 == tmpSignerInfo->sid.t)
02322     {
02323         //issuer/serial
02324         serial = tmpSignerInfo->sid.u.issuerAndSerialNumber->serialNumber;
02325 
02326         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
02327         ASN1OpenType* data1 = objPDU.Encode(&(tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer));
02328         CPKIFBufferPtr tmpBuf;
02329         if(data1 != NULL)
02330         {
02331              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
02332             delete data1;
02333         }
02334         CPKIFNamePtr tmpNP(new CPKIFName(tmpBuf));
02335         //CPKIFNamePtr tmpNP(new CPKIFName(tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer));
02336         issuer = tmpNP;
02337     }
02338     else if(2 == tmpSignerInfo->sid.t)
02339     {
02340         //skid
02341         CPKIFBufferPtr tmpBP(new CPKIFBuffer(tmpSignerInfo->sid.u.subjectKeyIdentifier->data, tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts));
02342         skid = tmpBP;
02343     }
02344     else
02345     {
02346         CPKIFBufferPtr tmpBP;
02347         return tmpBP;
02348     }
02349 
02350     //iterate over all certs in the cert bag
02351     DListNode* cur = NULL;
02352     if((*m_signedData)->m.certificatesPresent && 0 < (*m_signedData)->certificates.count)   //added 11/6/2003 - head is not necessarily NULL 
02353         cur = (*m_signedData)->certificates.head;
02354     while(NULL != cur)
02355     {
02356         CACCMSCertificateChoices* curChoice = (CACCMSCertificateChoices*)cur->data;
02357 
02358         if(T_CACCMSCertificateChoices_certificate != curChoice->t)
02359         {
02360             cur = cur->next;
02361             continue;
02362         }
02363         ASN1OpenType* curCert = (ASN1OpenType*)curChoice->u.certificate;
02364 
02365         try
02366         {
02367             //convert to a PKIF object
02368             CPKIFCertificatePtr tmpCert(new CPKIFCertificate);
02369             tmpCert->Decode(curCert->data, curCert->numocts);
02370 
02371             //see if there's a match - if so return a buffer containing raw cert
02372             if(NULL != serial && issuer != (CPKIFName*)NULL)
02373             {
02374                 if(0 == strcmp(serial, tmpCert->SerialNumber()) &&
02375                     *issuer == *tmpCert->Issuer())
02376                     return tmpCert->Encoded();
02377             }
02378             else
02379             {
02380                 CPKIFSubjectKeyIdentifierPtr skidFromCert = tmpCert->GetExtension<CPKIFSubjectKeyIdentifier>();
02381                 if(skidFromCert != (CPKIFSubjectKeyIdentifier*)NULL)
02382                 {
02383                     CPKIFBufferPtr skidValue = skidFromCert->KeyIdentifier();
02384                     if(*skidValue == *skid)
02385                         return tmpCert->Encoded();
02386                 }
02387             }
02388         }
02389         catch(CPKIFException&)
02390         {
02391             //EXCEPTION DELETION
02392             //eat any exceptions - if we fail to find a cert we'll report that but
02393             //not any failures to parse certs in the bag
02394             //delete e;
02395         }
02396 
02397         cur = cur->next;
02398     }   
02399 
02400     CPKIFCertificateList certBagContents;
02401     m_parent->GetCertificates(certBagContents);
02402 
02403     CPKIFCertificateList::iterator cPos;
02404     CPKIFCertificateList::iterator cEnd = certBagContents.end();
02405     for(cPos = certBagContents.begin(); cPos != cEnd; ++cPos)
02406     {
02407         try
02408         {
02409             //see if there's a match - if so return a buffer containing raw cert
02410             if(NULL != serial && issuer != (CPKIFName*)NULL)
02411             {
02412                 if(0 == strcmp(serial, (*cPos)->SerialNumber()) &&
02413                     *issuer == *(*cPos)->Issuer())
02414                     return (*cPos)->Encoded();
02415             }
02416             else
02417             {
02418                 CPKIFSubjectKeyIdentifierPtr skidFromCert = (*cPos)->GetExtension<CPKIFSubjectKeyIdentifier>();
02419                 if(skidFromCert != (CPKIFSubjectKeyIdentifier*)NULL)
02420                 {
02421                     CPKIFBufferPtr skidValue = skidFromCert->KeyIdentifier();
02422                     if(*skidValue == *skid)
02423                         return (*cPos)->Encoded();
02424                 }
02425             }
02426         }
02427         catch(CPKIFException&)
02428         {
02429             //EXCEPTION DELETION
02430             //eat any exceptions - if we fail to find a cert we'll report that but
02431             //not any failures to parse certs in the bag
02432             //delete e;
02433         }
02434 
02435     }
02436 
02437 
02438     try
02439     {
02440         //if we get here then we's empty handed.  poke around any associated cert stores
02441         //if a search interface is available
02442         IPKIFCertSearch* certSearch = NULL;
02443         if(NULL != m_med)
02444             certSearch = m_med->GetMediator<IPKIFCertSearch>();
02445         if(NULL != certSearch)
02446         {
02447             CPKIFCertificateList certList;
02448             if(1 == tmpSignerInfo->sid.t)
02449             {
02450                 //issuer/serial
02451                 CPKIFIssuerNameAndSerialNumberBasedSearch inasnbs;
02452                 inasnbs.SetIssuerName(issuer);
02453 
02454                             // new
02455                 CPKIFStringPtr serialStr (new std::string(serial));
02456                 inasnbs.SetSerialNumber(serialStr);
02457 
02458                             // old          
02459                             //inasnbs.SetSerialNumber(CPKIFStringPtr(new std::string(serial)));
02460 
02461                 certSearch->FindCertificates(&inasnbs, certList, ALL);
02462             }
02463             else if(2 == tmpSignerInfo->sid.t)
02464             {
02465                 //skid
02466                 CPKIFKeyIDBasedSearch kidbs;
02467                 kidbs.SetKeyID(skid);
02468 
02469                 certSearch->FindCertificates(&kidbs, certList, ALL);
02470             }
02471 
02472             //it's possible that we find more than one cert - however we'll just operate using the first one
02473             if(!certList.empty())
02474             {
02475                 return certList.front()->Encoded();
02476             }
02477         }
02478     }
02479     catch(...)
02480     {
02481     }
02482 
02483     CPKIFBufferPtr tmpBP;
02484     return tmpBP;
02485 }
02486 
02494 void CPKIFSignedDataImpl::CallingAllGets()
02495 {
02496     LOG_STRING_DEBUG("CPKIFSignedData::CallingAllGets()", TOOLKIT_CRYPTO_MISC, 0, this);
02497 
02498     //added 10/7/2003 - to avoid scope issues related to Objective buffer that
02499     //was being used to hold information following Encode
02500 #if defined (WIN32) || defined (_WIN32)
02501     GetVersion();
02502 #endif
02503 
02504     m_parent->GetEncapsulatedContent();
02505 
02506     CPKIFCertificateList certs;
02507     m_parent->GetCertificates(certs);
02508 
02509     CPKIFCRLList crls;
02510     m_parent->GetCRLs(crls);
02511 
02512     CPKIFSignerInfoList sis;
02513     m_parent->GetSignerInfos(sis);
02514 }
02522 void CPKIFSignedDataImpl::GetCandidateSignersCerts(
02524     CACCMSSignerInfo* tmpSignerInfo, 
02526     IPKIFNameAndKeyList& certs)
02527 {
02528     LOG_STRING_DEBUG("CPKIFSignedData::GetCandidateSignersCerts(CACCMSSignerInfo* tmpSignerInfo, CPKIFCertificateList& certs)", TOOLKIT_CRYPTO_MISC, 0, this);
02529 
02530     //given a signer info structure search the cert bag for the signer's certificate
02531 
02532     CPKIFNamePtr issuer;
02533     const char* serial = NULL;
02534     CPKIFBufferPtr skid;
02535 
02536     if(NULL == tmpSignerInfo || NULL == m_signedData || NULL == m_signedData->data())
02537         return; //not returning skid - just a handy empty buffer object
02538 
02539     //first determine if we are searching using key id or iss dn/serial number
02540     if(1 == tmpSignerInfo->sid.t)
02541     {
02542         //issuer/serial
02543         serial = tmpSignerInfo->sid.u.issuerAndSerialNumber->serialNumber;
02544 
02545         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
02546         ASN1OpenType* data1 = objPDU.Encode(&(tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer));
02547         CPKIFBufferPtr tmpBuf;
02548         if(data1 != NULL)
02549         {
02550              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
02551             delete data1;
02552         }
02553         CPKIFNamePtr tmpNP(new CPKIFName(tmpBuf));
02554         //CPKIFNamePtr tmpNP(new CPKIFName(tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer));
02555         issuer = tmpNP;
02556     }
02557     else if(2 == tmpSignerInfo->sid.t)
02558     {
02559         //skid
02560         CPKIFBufferPtr tmpBP(new CPKIFBuffer(tmpSignerInfo->sid.u.subjectKeyIdentifier->data, tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts));
02561         skid = tmpBP;
02562     }
02563 
02564     //if we get here then we's empty handed.  poke around any associated cert stores
02565     //if a search interface is available
02566     try
02567     {
02568         IPKIFCertSearch* certSearch = NULL;
02569         if(NULL != m_med)
02570             certSearch = m_med->GetMediator<IPKIFCertSearch>();
02571         if(NULL != certSearch)
02572         {
02573             //CPKIFCertificateList certList;
02574             if(1 == tmpSignerInfo->sid.t)
02575             {
02576                 //issuer/serial
02577                 CPKIFIssuerNameAndSerialNumberBasedSearch inasnbs;
02578                 inasnbs.SetIssuerName(issuer);
02579 
02580                 // new
02581                 CPKIFStringPtr serialStr (new std::string(serial));
02582                 inasnbs.SetSerialNumber(serialStr);             
02583 
02584                 certSearch->FindKeys(&inasnbs, certs, ALL);
02585             }
02586             else if(2 == tmpSignerInfo->sid.t)
02587             {
02588                 //skid
02589                 CPKIFKeyIDBasedSearch kidbs;
02590                 kidbs.SetKeyID(skid);
02591 
02592                 certSearch->FindKeys(&kidbs, certs, ALL);
02593             }
02594 
02595             //it's possible that we find more than one cert - however we'll just operate using the first one
02596             //if(!certList.empty())
02597             //{
02598             //  //return certList.front()->Encoded();
02599             //  copy(certList.begin(), certList.end(), back_inserter(certs));
02600             //}
02601         }
02602     }
02603     catch(CPKIFException&)
02604     {
02605         //ignore exceptions - if we don't find it we don't find it
02606     }
02607 
02608 //  CPKIFBufferPtr tmpBP;
02609 //  return tmpBP;
02610 }
02611 
02612 void CPKIFSignedData::SetKeyUsageChecker(CPKIFFuncStoragePtr& kuChecker)
02613 {
02614     m_impl->m_kuChecker = kuChecker;
02615 }
02616 
02617 #ifdef NEW_VERIFY_FUNC
02618 
02644 bool CPKIFSignedDataImpl::_Verify(
02646     int signerIndex, 
02648     CMSVerificationStatus& status, 
02651     CPKIFCertificatePtr& sc, 
02653     CMSPathValidationStatus minStatus)
02654 {
02655 #undef SET_BEST
02656 #define SET_BEST \
02657 {\
02658     if(curStatus > bestStatus || bestStatus == NOT_VERIFIED) \
02659     {\
02660         bestCert = candidateSignerCerts[currCertPos];\
02661         bestPath = m_path;\
02662         bestStatus = curStatus;\
02663     }\
02664 }
02665 // !!! GB: Changed certPos = candidateSignerCerts.begin();\ in this macro
02666 // to currCertPos = 0;
02667 #undef LOOK_FOR_MORE
02668 #define LOOK_FOR_MORE() \
02669 { \
02670     if(lookBeyondTheBag)\
02671     {\
02672         lookBeyondTheBag = false;\
02673         GetCandidateSignersCerts(si, candidateSignerCerts);\
02674     }\
02675 }
02676 
02677 #undef RETURN
02678 #define RETURN(b) \
02679 { \
02680     bool finalAnswer = b;\
02681     if(finalAnswer && bRetrySigWithParams)\
02682     {\
02683         CPKIFAlgorithmIdentifierPtr wp = m_valResults->GetWorkingParams();\
02684         key.SetWorkingParameters(wp);\
02685         if(!cRaw->Verify(key, hi->m_hashResult, CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize(), (unsigned char*)si->signature.data, si->signature.numocts, hi->m_hashAlg))\
02686         {\
02687             if(deleteHI)\
02688             {\
02689                 delete hi;\
02690             }\
02691             bestStatus = CMS_SIGNATURE_INVALID;\
02692             finalAnswer = false;\
02693         }\
02694     }\
02695     if(deleteHI)\
02696     {\
02697         delete hi;\
02698     }\
02699     status = bestStatus;\
02700     m_path = bestPath;\
02701     return finalAnswer;\
02702 }
02703 
02704     LOG_STRING_DEBUG("CPKIFSignedData::_Verify(int signerIndex, CMSVerificationStatus& status, ...", TOOLKIT_CRYPTO_MISC, 0, this);
02705 
02706     //initialize the outbound status to NOT_VERIFIED - i.e. set it to indicate that we haven't done anything
02707     //since we haven't done anything yet - this will be set to the bestStatus value in RETURN
02708     status = NOT_VERIFIED;
02709 
02710     if(!m_kuChecker)
02711     {
02712         CPKIFFuncStoragePtr keyUsageSigFunctor2(new CPKIFFuncStorage(keyUsageChecker_Signature));
02713         m_kuChecker = keyUsageSigFunctor2;
02714     }
02715 
02716     //curStatus should be used as a temporary status vehicle - bestStatus will maintain the high water
02717     //mark during processing
02718     CMSVerificationStatus curStatus = NOT_VERIFIED;
02719     bool bRetrySigWithParams = false; //added 2/17/2005
02720     CPKIFKeyMaterial key;
02721 
02722     //collect the necessary interfaces (there are other optional interfaces that will be used if present):
02723     //      IPKIFCryptoMisc - to prepare hashes
02724     //      IPKIFCryptoRawOperations - to perform signature verification
02725     if(NULL == m_med)
02726         throw CPKIFMessageException(m_parent->thisComponent, COMMON_MEDIATOR_MISSING, "Mediator is not available.");
02727 
02728     IPKIFCryptoMisc* cMisc = m_med->GetMediator<IPKIFCryptoMisc>();
02729     if(NULL == cMisc)
02730         throw CPKIFMessageException(m_parent->thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCryptoMisc interface is not available.");
02731     IPKIFCryptoRawOperations* cRaw = m_med->GetMediator<IPKIFCryptoRawOperations>();
02732     if(NULL == cRaw)
02733         throw CPKIFMessageException(m_parent->thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFCryptoRawOperations interface is not available.");
02734 
02735     IPKIFPathBuild* cBuild = NULL;
02736     IPKIFPathValidate* cValidate = NULL;
02737     if(minStatus > PVS_NOT_VALIDATED)
02738     {
02739         cBuild = m_med->GetMediator<IPKIFPathBuild>();
02740         if(NULL == cBuild)
02741             throw CPKIFMessageException(m_parent->thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFPathBuild interface is not available.");
02742 
02743         cValidate = m_med->GetMediator<IPKIFPathValidate>();
02744         if(NULL == cValidate)
02745             throw CPKIFMessageException(m_parent->thisComponent, COMMON_MEDIATOR_MISSING, "IPKIFPathValidate interface is not available.");
02746     }
02747 
02748     //added 3/17 CRW
02749     if(NULL == m_signedData->data())
02750         throw CPKIFMessageException(m_parent->thisComponent, MSG_INVALID_STATE, "Message has not been decoded.");
02751 
02752     //see if data was present that needs hashing (if m_bDetached is set then we've already hashed)
02753     if((*m_signedData)->encapContentInfo.m.eContentPresent && !m_bDetached)
02754     {
02755         //if content is present in the message throw out anything that was passed in via UpdateMessage
02756         m_detachedData.FreeHashVector();
02757         m_bDetached = false; //added 04/08/2003 CRW
02758         m_parent->UpdateMessage((unsigned char*)(*m_signedData)->encapContentInfo.eContent.data, (*m_signedData)->encapContentInfo.eContent.numocts);
02759     }
02760 
02761     CPKIFOIDPtr encapType = m_parent->GetEncapsulatedContent()->GetOID();
02762 
02763     //finalize all hashes (either initialized above or via external call to UpdateMessage)
02764     m_detachedData.FinalizeHashes(cMisc);
02765 
02766     //iterate over all signer infos and select the one corresponding to the requested index
02767     bool b = false;
02768     
02769     DListNode* cur = (*m_signedData)->signerInfos.head;
02770     for(int ii = 0; ii < signerIndex && NULL != cur; ++ii)
02771         cur = cur->next;
02772 
02773     //if there isn't one that corresponds to the index - fail
02774     if(NULL == cur)
02775         throw CPKIFMessageException(m_parent->thisComponent, MSG_INVALID_INDEX, "signerIndex is invalid.");
02776 
02777     CACCMSSignerInfo* si = (CACCMSSignerInfo*)cur->data;
02778     CPKIFAlgorithm * pkifAlg = GetCACHashAlg(&si->digestAlgorithm);
02779     if(!pkifAlg)
02780         throw CPKIFMessageException(m_parent->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm.");     
02781     PKIFCRYPTO::HASH_ALG hashAlg = pkifAlg->HashAlg();
02782     CPKIFBufferPtr signerCert;
02783     IPKIFNameAndKeyList candidateSignerCerts;
02784     bool lookBeyondTheBag = true;           //boolean to indicate if sources other than cert bag should be tried
02785 
02786     //see if a cert was passed in... 
02787     if(sc != (CPKIFCertificate*)NULL)
02788     {
02789         //if so use it 
02790 //      lookBeyondTheBag = false;           //when we are passed a signer cert that is the only cert we will try
02791         signerCert = sc->Encoded();
02792         candidateSignerCerts.push_back(sc);
02793     }
02794     else
02795     {
02796         //if not look in the signers info for the cert
02797         CPKIFCertificatePtr tmpSC;
02798         m_parent->GetSignersCert(signerIndex, tmpSC);
02799         if(tmpSC != (CPKIFCertificate*)NULL)
02800         {
02801             signerCert = tmpSC->Encoded();
02802             candidateSignerCerts.push_back(tmpSC);
02803         }
02804     }
02805 
02806     if(candidateSignerCerts.empty())
02807     {
02808         GetCandidateSignersCerts(si, candidateSignerCerts);
02809     }
02810 
02811     IPKIFNameAndKeyPtr bestCert;                    //pointer to the best candidate cert so far
02812     CMSVerificationStatus bestStatus = NOT_VERIFIED;//status of bestCert
02813     CPKIFCertificatePathPtr bestPath;           //path associated with bestCert
02814     vector<CPKIFCertificatePathPtr> allPaths;   //vector containing all paths that have been tried (for bestCert and others)
02815 
02816     //***************************************************************************************************
02817     //  Next, calculate or obtain hash result for signature verification and process mandatory
02818     //  signed CMS attributes.
02819     //***************************************************************************************************
02820     HashInfo* hi = NULL;    //pointer to hash result calculated with the hash alg retrieved from SignerInfo
02821     bool deleteHI = false;  //bool to indicate if HashInfo object must be cleaned up (i.e. was created and not retrieved from parallel hash)
02822 
02823     //determine if signed attributes are present so we know what to hash
02824     if(!si->m.signedAttrsPresent)
02825     {
02826         //if no signed attrs are present then retrieve the hash of the data     
02827         hi = m_detachedData.GetHashInfo(hashAlg);
02828     }
02829     else
02830     {
02831         //get the hash of the data
02832         HashInfo* hi2 = m_detachedData.GetHashInfo(hashAlg);
02833 
02834         //then compute the hash over the signed attrs (this will be used for verification below)
02835         hi = ComputeSignedAttrHash(si, cMisc);
02836         deleteHI = true;
02837 
02838         if(!CompareHashes(hi2, si))
02839         {
02840             //if hash of data does not match the hash contained in the signed attr bag
02841             //or if there is no content hash in the signed attr bag then fail
02842             //changed from curStatus = 11/6/2003
02843             bestStatus = CMS_SIGNATURE_INVALID;
02844             RETURN(false); //no need to keep looking for a cert - the hash of the data is not correct
02845         }
02846 
02847         //added 04/28/2003
02848         CACASNWRAPPER_CREATE(CACCMSSignerInfo, InfoWrapper);
02849         ASN1OpenType *siData = InfoWrapper.Encode(si);
02850         CPKIFBufferPtr siBuf(new CPKIFBuffer(siData->data, siData->numocts));
02851         delete siData;
02852 
02853         //CPKIFSignerInfo tmpSI(*si);
02854         CPKIFSignerInfo tmpSI(siBuf);
02855 
02856         CPKIFContentTypeAttributePtr ct = tmpSI.GetSignedAttribute<CPKIFContentTypeAttribute>();
02857         if(ct == (CPKIFContentTypeAttribute*)NULL)
02858         {
02859             //changed from curStatus = 11/6/2003
02860             bestStatus = CMS_SIGNATURE_INVALID;
02861             RETURN(false); //no need to keep looking for a cert - a required attribute is not present
02862         }
02863         else
02864         {
02865             CPKIFOIDPtr ctType = ct->GetContentType();
02866             if(ctType == (CPKIFOID*)NULL || !(*ctType == *encapType))
02867             {
02868                 //changed from curStatus = 11/6/2003
02869                 bestStatus = CMS_SIGNATURE_INVALID;
02870                 RETURN(false); //no need to keep looking for a cert - content type mismatch
02871             }
02872         }
02873             
02874     }
02875 
02876     IPKIFCertRepositoryUpdate* certUpdate = m_med->GetMediator<IPKIFCertRepositoryUpdate>();
02877     if(certUpdate)
02878     {
02879         CPKIFCertificateList certBagContents;
02880         m_parent->GetCertificates(certBagContents);
02881 
02882         CPKIFCertificateList::iterator cPos;
02883         CPKIFCertificateList::iterator cEnd = certBagContents.end();
02884         for(cPos = certBagContents.begin(); cPos != cEnd; ++cPos)
02885         {
02886             CPKIFBasicConstraintsPtr bc = (*cPos)->GetExtension<CPKIFBasicConstraints>();
02887             if(bc != (CPKIFBasicConstraints*)NULL)
02888             {
02889                 if(bc->isCA())
02890                     certUpdate->AddCertificate(CA, *cPos);
02891             }
02892         }
02893     }
02894 
02895     IPKIFCRLRepositoryUpdate* crlUpdate = m_med->GetMediator<IPKIFCRLRepositoryUpdate>();
02896     if(crlUpdate)
02897     {
02898         CPKIFCRLList crlBagContents;
02899         m_parent->GetCRLs(crlBagContents);
02900 
02901         CPKIFGeneralNamePtr dummyGN;
02902 
02903         CPKIFCRLList::iterator cPos;
02904         CPKIFCRLList::iterator cEnd = crlBagContents.end();
02905         for(cPos = crlBagContents.begin(); cPos != cEnd; ++cPos)
02906         {
02907             crlUpdate->AddCRL(*cPos, dummyGN);
02908         }
02909     }
02910 
02911     if(NULL == hi)
02912         throw CPKIFMessageException(m_parent->thisComponent, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm or detached data not attached prior to invoking Verify.");      
02913 
02914     //At this point we have located the desired SignerInfo and we have collected 0 or more candidate 
02915     //certificates for that SignerInfo (either passed in as the sc param or from the cert bag associated
02916     //with the SignedData message).  We need to iterate over the candidate certs until we either find a cert
02917     //that meets our verification requirements or run out of certs to try.
02918 
02919     //CPKIFCertificateList::iterator certPos;       //pointer to the current position in the vector
02920     size_t currCertPos = 0;
02921 
02922     //candidateSignerCerts can change during an iteration - thus the end position should not be stored
02923     //changed from certPos != to certPos < 11/17/2003
02924     //for(certPos = candidateSignerCerts.begin(); certPos < candidateSignerCerts.end(); ++certPos)
02925     for(currCertPos = 0; currCertPos < candidateSignerCerts.size(); ++currCertPos)
02926     {
02927         CPKIFCertificatePtr curCert = dynamic_pointer_cast<CPKIFCertificate, IPKIFNameAndKey>(candidateSignerCerts[currCertPos]);
02928         if(curCert)
02929         {
02930             signerCert = curCert->Encoded();
02931 
02932             //prepare a key material object with the cert...
02933             key.SetCertificate(signerCert->GetBuffer(), signerCert->GetLength());
02934         }
02935         else
02936         {
02937             CPKIFBufferPtr empty;
02938             signerCert = empty;
02939             key.SetSubjectPublicKeyInfo(candidateSignerCerts[currCertPos]->GetSubjectPublicKeyInfo());
02940         }
02941 
02942         CPKIFAlgorithmIdentifierPtr tmpAI;
02943         key.SetWorkingParameters(tmpAI);
02944         
02945         //added catch block and bool to cause signature verification to be retried once we have working params
02946         bRetrySigWithParams = false;
02947         try
02948         {
02949             //then attempt verification
02950             if(!cRaw->Verify(key, hi->m_hashResult, CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize(), (unsigned char*)si->signature.data, si->signature.numocts, hi->m_hashAlg))
02951             {
02952                 curStatus = CMS_SIGNATURE_INVALID;
02953                 SET_BEST
02954                 LOOK_FOR_MORE()
02955                 continue;
02956             }
02957             else
02958             {
02959                 curStatus = CMS_SIGNATURE_VERIFIED;
02960             }
02961         }
02962         catch(CPKIFException& ce)
02963         {
02964             if(PKIFCAPING_KEY_IMPORT_FAILED != ce.GetErrorCode() && PKIFCAPI_KEY_IMPORT_FAILED != ce.GetErrorCode() && PKIFNSS_CERT_IMPORT_FAILED != ce.GetErrorCode())
02965             {
02966                 throw ce;
02967             }
02968             else
02969             {
02970                 bRetrySigWithParams = true;
02971             }
02972         }
02973 
02974         //added 04/26/2003 - CRW
02975         if(PVS_NOT_VALIDATED == minStatus)
02976             RETURN(true);
02977 
02978         if(!signerCert)
02979         {
02980             IPKIFTrustAnchorPtr ta = dynamic_pointer_cast<IPKIFTrustAnchor, IPKIFNameAndKey>(candidateSignerCerts[currCertPos]);
02981             if(ta)
02982             {
02983                 CPKIFCertificatePathPtr tmpPath(new CPKIFCertificatePath);
02984                 m_path = tmpPath;
02985                 m_path->SetTrustRoot(ta);
02986                 bestPath = m_path;
02987 
02988                 CPKIFPathValidationResultsPtr tmpValResults(new CPKIFPathValidationResults);
02989                 m_valResults = tmpValResults;
02990                 m_valResults->SetTargetIsTrustAnchor(true);
02991                 m_valResults->SetTrustAnchor(ta);
02992 
02993                 bestStatus = REV_STATUS_VERIFIED;
02994                 RETURN(true);
02995             }
02996             else
02997             {
02998                 RETURN(false);
02999             }
03000         }
03001 
03002         CPKIFCertificatePathPtr tmpPath(new CPKIFCertificatePath);
03003         m_path = tmpPath;
03004 
03005         allPaths.push_back(m_path);
03006 
03007         CPKIFPathValidationResultsPtr tmpValResults(new CPKIFPathValidationResults);
03008         m_valResults = tmpValResults;
03009 
03010         CPKIFCertificatePtr signersCert(new CPKIFCertificate());
03011         signersCert->Decode(signerCert->GetBuffer(), signerCert->GetLength());
03012         m_path->SetTarget(signersCert);
03013 
03014         //if settings have been associated with this object use them
03015         //otherwise defer to the default settings (either globally set
03016         //or defined to be very permissive)
03017         if(m_settings != (CPKIFPathSettings*)NULL)
03018             m_path->SetPathSettings(m_settings);
03019 
03020         try
03021         {
03022             //This do/while will iteratively call Build and Validate until all paths have been tried
03023             //or a good path has been found.  
03024             do
03025             {
03026                 if(!cBuild->BuildPath(*m_path))
03027                 {
03028                     SET_BEST
03029                     LOOK_FOR_MORE()
03030                     break;
03031                 }
03032                 if(cValidate->ValidatePath(*m_path, *m_valResults, m_kuChecker))
03033                 {
03034                     if(NOT_REVOKED == m_valResults->GetRevocationStatusMostSevere())
03035                     {
03036                         curStatus = REV_STATUS_VERIFIED;
03037                         SET_BEST
03038                         RETURN(true);   
03039                     }
03040                     else
03041                     {
03042                         curStatus = CERT_PATH_VERIFIED;
03043                         //added 8/27/2004
03044                         SET_BEST
03045                         if(PVS_REV_STATUS_VERIFIED > minStatus)
03046                             RETURN(true);
03047                     }
03048                 }
03049                 else
03050                 {
03051                     if(!m_valResults->GetBasicChecksSuccessfullyPerformed() ||
03052                         !m_valResults->GetCertSignaturesVerified())
03053                     {
03054                         curStatus = CERT_PATH_INVALID; //set the status but keep looking
03055                         SET_BEST
03056                     }
03057                     else if(REVOKED == m_valResults->GetRevocationStatusMostSevere())
03058                     {
03059                         //see if the signer was revoked - if so, stop looking and return false now
03060                         //if they don't match then a CA cert was revoked and we should keep looking
03061                         //for a good path
03062                         CPKIFCertificateNodeEntryPtr errantCertNode = m_valResults->GetCertificate();
03063                         if(errantCertNode != (CPKIFCertificateNodeEntry*)NULL)
03064                         {
03065                             CPKIFCertificatePtr errantCert = errantCertNode->GetCert();
03066                             if(errantCert != (CPKIFCertificate*)NULL && *errantCert == *signersCert)
03067                             {
03068                                 curStatus = REV_STATUS_INVALID;
03069                                 SET_BEST
03070                                 LOOK_FOR_MORE()
03071                                 break;
03072                             }
03073                             else
03074                             {
03075                                 //added this condition 8/27/2004
03076                                 curStatus = REV_STATUS_INVALID;
03077                                 SET_BEST
03078                                 RETURN(false)
03079                             }
03080                         }
03081                     }
03082                     else if(m_valResults->GetBasicChecksSuccessfullyPerformed() &&
03083                         m_valResults->GetCertSignaturesVerified())
03084                     {
03085                         curStatus = CERT_PATH_VERIFIED; //verification successful but revocation not checked
03086                         SET_BEST
03087                         if(PVS_REV_STATUS_VERIFIED > minStatus) //if min say OK return true - else keep looking
03088                             RETURN(true);
03089                     }
03090                 }
03091             }while(1);
03092         }
03093         catch(CPKIFException& e)
03094         {
03095             LOG_STRING_ERROR(e.print()->c_str(), m_parent->thisComponent, COMMON_UNKNOWN_ERROR, this);
03096             SET_BEST
03097             LOOK_FOR_MORE()
03098         }
03099     }
03100 
03101     RETURN(false);
03102 }
03103 #endif
03104 

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