EvidenceRecordVerifier.cpp

Go to the documentation of this file.
00001 
00009 //PKIF includes
00010 #include "pkif.h"
00011 #include "PKIFAlgorithm.h"
00012 #include "PKIFCryptUtils.h"
00013 
00014 //PKIFCMS includes
00015 #include "PKIFCMS.h"
00016 
00017 //PKIFERS includes
00018 #include "ArchiveTimestamp.h"
00019 #include "EvidenceRecord.h"
00020 #include "EvidenceRecordVerifier.h"
00021 #include "IPKIFSecuritySuitability.h"
00022 
00023 //PKIFTSP includes
00024 #include "PKIFTSP.h"
00025 
00026 #include <stdexcept>
00027 #include <cstring>
00028 #include <iterator>
00029 
00030 //*****************************************************************************
00031 //  Memory Helper and Impl
00032 //*****************************************************************************
00034 struct PKIFEvidenceRecordVerifierImpl 
00035 {
00036     //data alternatives
00037     CPKIFBufferPtr m_orig;
00038     CPKIFParallelHashPtr m_ph;
00039 
00040     IPKIFMediatorPtr m_currentMediator;
00041     CPKIFPathSettingsPtr m_currentPS;
00042 
00043     IPKIFSecuritySuitabilityPtr m_ssp;
00044 
00045     std::vector<CPKIFExMediatorPtr> m_archiveMediators;
00046     std::vector<CPKIFExPathSettingsPtr> m_archivePathSettings;
00047 
00048     CPKIFBufferPtr GetHash(PKIFCRYPTO::HASH_ALG ha, IPKIFMediatorPtr& m);
00049 
00050     IPKIFMediatorPtr GetMediator(CPKIFTimePtr& toi);
00051     CPKIFPathSettingsPtr GetPathSettings(CPKIFTimePtr& toi);
00052 
00053     SeqResultsPtr m_seqResults;
00054 };
00062 IPKIFMediatorPtr PKIFEvidenceRecordVerifierImpl::GetMediator(CPKIFTimePtr& toi)
00063 {
00064     IPKIFMediatorPtr empty;
00065     CPKIFTimePtr highWater;
00066 
00067     //walk the list of ex-meds and see if the time of interest falls into any of those
00068     std::vector<CPKIFExMediatorPtr>::iterator pos;
00069     std::vector<CPKIFExMediatorPtr>::iterator end = m_archiveMediators.end();
00070     for(pos = m_archiveMediators.begin(); pos != end; ++pos)
00071     {
00072         CPKIFTimePtr notBefore = (*pos)->first->notBefore();
00073         CPKIFTimePtr notAfter = (*pos)->first->notAfter();
00074 
00075         if(*notBefore <= *toi && *toi <= *notAfter)
00076             return (*pos)->second;
00077 
00078         if(!highWater || *highWater < *notAfter)
00079             highWater = notAfter;
00080     }
00081 
00082     //if not, then either the time of interest is current enough to use current meds or we fail and
00083     //return NULL.
00084     if(m_archiveMediators.empty())
00085         return m_currentMediator; //only one
00086     else if(highWater && *toi > *highWater)
00087         return m_currentMediator;
00088     else
00089         return empty;
00090 }
00098 CPKIFPathSettingsPtr PKIFEvidenceRecordVerifierImpl::GetPathSettings(CPKIFTimePtr& toi)
00099 {
00100     CPKIFPathSettingsPtr empty;
00101     CPKIFTimePtr highWater;
00102 
00103     //walk the list of ex-meds and see if the time of interest falls into any of those
00104     std::vector<CPKIFExPathSettingsPtr>::iterator pos;
00105     std::vector<CPKIFExPathSettingsPtr>::iterator end = m_archivePathSettings.end();
00106     for(pos = m_archivePathSettings.begin(); pos != end; ++pos)
00107     {
00108         CPKIFTimePtr notBefore = (*pos)->first->notBefore();
00109         CPKIFTimePtr notAfter = (*pos)->first->notAfter();
00110 
00111         if(*notBefore <= *toi && *toi <= *notAfter)
00112             return (*pos)->second;
00113 
00114         if(!highWater || *highWater < *notAfter)
00115             highWater = notAfter;
00116     }
00117 
00118     //if not, then either the time of interest is current enough to use current settings or 
00119     //we fail and return NULL.
00120     if(m_archivePathSettings.empty())
00121         return m_currentPS;
00122     else if(*toi > *highWater)
00123         return m_currentPS;
00124     else
00125         return empty;
00126 }
00134 CPKIFBufferPtr PKIFEvidenceRecordVerifierImpl::GetHash(PKIFCRYPTO::HASH_ALG ha, IPKIFMediatorPtr& m)
00135 {
00136     CPKIFBufferPtr emptyBP;
00137 
00138     if(m_orig != (CPKIFBuffer*)NULL)
00139     {
00140         if(m != (IPKIFMediator*)NULL)
00141         {
00142             IPKIFCryptoMisc* cm = m->GetMediator<IPKIFCryptoMisc>();
00143             if(cm)
00144             {
00145                 IPKIFHashContext* hc = cm->HashInit(ha);
00146                 if(hc)
00147                 {
00148                     CPKIFBufferPtr newBP(new CPKIFBuffer);
00149                     unsigned char* hashResult = newBP->AllocateBuffer(ha);
00150                     int resultLen = ha;
00151                     cm->HashUpdate(hc, (unsigned char*)m_orig->GetBuffer(), m_orig->GetLength());
00152                     cm->HashFinal(hc, hashResult, &resultLen);
00153                     delete hc;
00154                     return newBP;
00155                 }
00156             }
00157         }
00158     }
00159     else if(m_ph != (CPKIFParallelHash*)NULL)
00160     {
00161         HashInfo* hi = m_ph->GetHashInfo(ha);
00162         if(NULL != hi)
00163         {
00164             CPKIFBufferPtr newBP(new CPKIFBuffer(hi->m_hashResult, hi->m_hashAlg));
00165             return newBP;
00166         }
00167     }
00168 
00169     return emptyBP;
00170 }
00172 
00180 CPKIFTimePtr GetTimeFromTimestamp(
00182     CPKIFContentInfoPtr& ci)
00183 {
00184     CPKIFTimePtr emptyTime;
00185 
00186     //declare a TSTInfo object and try to parse the contents from the ContentInfo
00187     CPKIFTSTInfoPtr tstInfo;
00188 
00189     CPKIFSignedData sd;
00190 
00191     try
00192     {
00193         //try to parse the contents from the ContentInfo
00194         CPKIFBufferPtr content = ci->GetContent();
00195         sd.Decode(content);
00196     }
00197     catch(CPKIFException&)
00198     {
00199         return emptyTime;
00200     }
00201 
00202     CPKIFEncapsulatedContentInfoPtr ecip = sd.GetEncapsulatedContent();
00203 
00204     try
00205     {
00206         CPKIFTSTInfoPtr tmpTstInfo(new CPKIFTSTInfo);
00207 
00208         //try to parse the contents from the ContentInfo
00209         CPKIFBufferPtr content = ecip->GetContent();
00210         tmpTstInfo->Decode(content);
00211 
00212         tstInfo = tmpTstInfo;
00213     }
00214     catch(CPKIFException&)
00215     {
00216         return emptyTime;
00217     }
00218 
00219     return tstInfo->GetGeneralizedTime();
00220 }
00228 CPKIFAlgorithmIdentifierPtr GetHashAlgorithmFromTimestamp(
00230     CPKIFContentInfoPtr& ci)
00231 {
00232     CPKIFAlgorithmIdentifierPtr emptyHashAlg;
00233 
00234     //declare a TSTInfo object and try to parse the contents from the ContentInfo
00235     CPKIFTSTInfoPtr tstInfo;
00236 
00237     CPKIFSignedData sd;
00238 
00239     try
00240     {
00241         //try to parse the contents from the ContentInfo
00242         CPKIFBufferPtr content = ci->GetContent();
00243         sd.Decode(content);
00244     }
00245     catch(CPKIFException&)
00246     {
00247         return emptyHashAlg;
00248     }
00249 
00250     CPKIFEncapsulatedContentInfoPtr ecip = sd.GetEncapsulatedContent();
00251 
00252     try
00253     {
00254         CPKIFTSTInfoPtr tmpTstInfo(new CPKIFTSTInfo);
00255 
00256         //try to parse the contents from the ContentInfo
00257         CPKIFBufferPtr content = ecip->GetContent();
00258         tmpTstInfo->Decode(content);
00259 
00260         tstInfo = tmpTstInfo;
00261     }
00262     catch(CPKIFException&)
00263     {
00264         return emptyHashAlg;
00265     }
00266 
00267     //get the message imprint from the timestamp
00268     CPKIFMessageImprintPtr mi = tstInfo->GetMessageImprint();
00269     if(!mi)
00270         return emptyHashAlg;
00271 
00272     //and return the hash algorithm from it
00273     return mi->GetHashAlgorithm();
00274 }
00275 
00286 CPKIFBufferPtr HashBuffer(
00288     CPKIFAlgorithm* ha,
00290     CPKIFBufferPtr& bp,
00292     IPKIFMediatorPtr& m)
00293 {
00294     CPKIFBufferPtr rv;
00295     IPKIFCryptoMisc* cm = NULL;
00296 
00297     //first try to get interface from mediator set
00298     if(m)
00299         cm = m->GetMediator<IPKIFCryptoMisc>();
00300 
00301     //failing that, get default platform appropriate interface
00302     if(!cm)
00303         cm = GetPlatformCryptoMisc();
00304 
00305     //failing that, fail
00306     if(!cm)
00307         return rv;
00308 
00309     //create a buffer to return
00310     CPKIFBufferPtr tmpBP(new CPKIFBuffer);
00311     IPKIFHashContext* h = NULL;
00312 
00313     try
00314     {
00315         //create a hash context for the given alg
00316         h = cm->HashInit(ha->HashAlg());
00317 
00318         cm->HashUpdate(h, (unsigned char*)bp->GetBuffer(), bp->GetLength());
00319         
00320         int outBufLen = ha->DigestSize();
00321         unsigned char* outBuf = tmpBP->AllocateBuffer(outBufLen);
00322 
00323         cm->HashFinal(h, outBuf, &outBufLen);
00324 
00325         delete h; h = NULL;
00326     }
00327     catch(CPKIFException&)
00328     {
00329         if(h) delete h;
00330     }
00331     catch(...)
00332     {
00333         if(h) delete h;
00334     }
00335 
00336     rv = tmpBP;
00337     return rv;
00338 }
00339 
00340 //*****************************************************************************
00341 //  CPKIFEvidenceRecordVerifier implementation
00342 //*****************************************************************************
00350 CPKIFEvidenceRecordVerifier::CPKIFEvidenceRecordVerifier(void) : m_impl(new PKIFEvidenceRecordVerifierImpl)
00351 {
00352 }
00360 CPKIFEvidenceRecordVerifier::~CPKIFEvidenceRecordVerifier(void)
00361 {
00362     if(m_impl)
00363         delete m_impl;
00364 }
00372 void CPKIFEvidenceRecordVerifier::SetCurrentMediator(
00374     IPKIFMediatorPtr& currentMediator)
00375 {
00376     m_impl->m_currentMediator = currentMediator;
00377 }
00385 IPKIFMediatorPtr CPKIFEvidenceRecordVerifier::GetCurrentMediator()
00386 {
00387     return m_impl->m_currentMediator;
00388 }
00396 void CPKIFEvidenceRecordVerifier::SetCurrentPathSettings(CPKIFPathSettingsPtr& currentPS)
00397 {
00398     m_impl->m_currentPS = currentPS;
00399 }
00407 CPKIFPathSettingsPtr CPKIFEvidenceRecordVerifier::GetCurrentPathSettings()
00408 {
00409     return m_impl->m_currentPS;
00410 }
00418 IPKIFMediatorPtr CPKIFEvidenceRecordVerifier::GetArchiveMediator(CPKIFTimePtr& t)
00419 {
00420     std::vector<CPKIFExMediatorPtr>::iterator pos;
00421     std::vector<CPKIFExMediatorPtr>::iterator end = m_impl->m_archiveMediators.end();
00422     for(pos = m_impl->m_archiveMediators.begin(); pos != end; ++pos)
00423     {
00424         CPKIFTimePtr notBefore = (*pos)->first->notBefore();
00425         CPKIFTimePtr notAfter = (*pos)->first->notAfter();
00426         if(*t > *notBefore && *t < *notAfter)
00427             return (*pos)->second;
00428     }
00429 
00430     IPKIFMediatorPtr empty;
00431     return empty;
00432 }
00440 void CPKIFEvidenceRecordVerifier::AddArchiveMediator(CPKIFExMediatorPtr& archiveMediator)
00441 {
00442     m_impl->m_archiveMediators.push_back(archiveMediator);
00443 }
00451 void CPKIFEvidenceRecordVerifier::GetArchiveMediators(
00453     std::vector<CPKIFExMediatorPtr>& v) const
00454 {
00455     v.clear();
00456     copy(m_impl->m_archiveMediators.begin(),m_impl->m_archiveMediators.end(),back_inserter(v));
00457 }
00465 CPKIFPathSettingsPtr CPKIFEvidenceRecordVerifier::GetArchivePathSettings(CPKIFTimePtr& t)
00466 {
00467     std::vector<CPKIFExPathSettingsPtr>::iterator pos;
00468     std::vector<CPKIFExPathSettingsPtr>::iterator end = m_impl->m_archivePathSettings.end();
00469     for(pos = m_impl->m_archivePathSettings.begin(); pos != end; ++pos)
00470     {
00471         CPKIFTimePtr notBefore = (*pos)->first->notBefore();
00472         CPKIFTimePtr notAfter = (*pos)->first->notAfter();
00473         if(*t > *notBefore && *t < *notAfter)
00474             return (*pos)->second;
00475     }
00476 
00477     CPKIFPathSettingsPtr empty;
00478     return empty;
00479 }
00487 void CPKIFEvidenceRecordVerifier::AddArchivePathSettings(
00489     CPKIFExPathSettingsPtr& ps)
00490 {
00491     m_impl->m_archivePathSettings.push_back(ps);
00492 }
00500 void CPKIFEvidenceRecordVerifier::GetArchivePathSettings(
00502     std::vector<CPKIFExPathSettingsPtr>& v) const
00503 {
00504     v.clear();
00505     copy(m_impl->m_archivePathSettings.begin(),m_impl->m_archivePathSettings.end(),back_inserter(v));
00506 }
00514 void CPKIFEvidenceRecordVerifier::SetDataComplete(CPKIFBufferPtr& origData)
00515 {
00516     m_impl->m_orig = origData;
00517 }
00525 void CPKIFEvidenceRecordVerifier::SetDataHashSet(CPKIFParallelHashPtr& ph)
00526 {
00527     m_impl->m_ph = ph;
00528 }
00536 CPKIFBufferPtr CPKIFEvidenceRecordVerifier::GetHash(PKIFCRYPTO::HASH_ALG ha, IPKIFMediatorPtr& m)
00537 {
00538     return m_impl->GetHash(ha, m);
00539 }
00547 void CPKIFEvidenceRecordVerifier::SetSecuritySuitabilityPolicy(const IPKIFSecuritySuitabilityPtr& ssp)
00548 {
00549     m_impl->m_ssp = ssp;
00550 }
00558 IPKIFSecuritySuitabilityPtr CPKIFEvidenceRecordVerifier::GetSecuritySuitabilityPolicy() const
00559 {
00560     return m_impl->m_ssp;
00561 }
00562 
00579 SeqResultsPtr CPKIFEvidenceRecordVerifier::Verify(CPKIFEvidenceRecordPtr& er)
00580 {
00581     //the first timestamp to be verified will be the one applied most recently.  this must
00582     //be valid using currently valid stuff at the current time.
00583     IPKIFMediatorPtr activeMediator = m_impl->m_currentMediator;
00584     CPKIFPathSettingsPtr activePathSettings = m_impl->m_currentPS;
00585     CPKIFTimePtr timeOfInterest = CPKIFTime::CurrentTime();
00586 
00587     //check for non-null inputs
00588     if(!er)
00589     {
00590     }
00591 
00592     //check the version
00593     if(1 != er->GetVersion())
00594     {
00595     }
00596 
00597     //CryptoInfo and EncryptionInfo are not supported - ignore them if present
00598 
00599     //prepare a parallel hash object with the indicated hash algorithms
00600 
00601     //iterate over the evidence record
00602     CPKIFArchiveTimestampSequencePtr seq = er->GetArchiveTimestampSequence();
00603     SeqResultsPtr seqResults(new SeqResults);
00604 
00605     CPKIFArchiveTimestampSequence::reverse_iterator rSeqPos = seq->rbegin();
00606     CPKIFArchiveTimestampSequence::reverse_iterator rSeqEnd = seq->rend();
00607     while(rSeqPos != rSeqEnd)
00608     {
00609         CPKIFArchiveTimestampChainPtr chain = (*rSeqPos);
00610 
00611         ChainResultsPtr cr(new ChainResults);
00612         seqResults->push_back(cr);
00613 
00614         CPKIFArchiveTimestampChain::reverse_iterator rChainPos = chain->rbegin();
00615         CPKIFArchiveTimestampChain::reverse_iterator rChainEnd = chain->rend();
00616         while(rChainPos != rChainEnd)
00617         {
00618             CPKIFArchiveTimestampPtr curAts = (*rChainPos);
00619             CPKIFContentInfoPtr curTimestamp = curAts->GetTimestamp();
00620 
00621             CPKIFAlgorithmIdentifierPtr curHashAlgId = GetHashAlgorithmFromTimestamp(curTimestamp);
00622             CPKIFAlgorithm* pHa = CPKIFAlgorithm::GetAlg(curHashAlgId->oid());
00623             PKIFCRYPTO::HASH_ALG curHashAlg = pHa->HashAlg();
00624 
00625             if(m_impl->m_ssp)
00626             {
00627                 if(!m_impl->m_ssp->IsAlgorithmSuitable(curHashAlgId))
00628                 {
00629                     throw std::runtime_error("Unsuitable hash algorithm in timestamp.");
00630                 }
00631             }
00632 
00633             CPKIFTimestampVerifierPtr tv(new CPKIFTimestampVerifier);
00634 
00635             ++rChainPos;
00636             if(rChainPos == rChainEnd)
00637             {
00638                 ++rSeqPos;
00639                 if(rSeqPos == rSeqEnd)
00640                 {
00641                     //this is the first initial timestamp and must be verified against the original data
00642                     CPKIFBufferPtr hashOfData = GetHash(curHashAlg, activeMediator);
00643                     tv->SetDataHash(hashOfData, curHashAlg);
00644                 }
00645                 else
00646                 {
00647                     //this is the first timestamp in this chain and must be verified against the 
00648                     //preceding element in the sequence, if any, plus the original data
00649                     chain = *rSeqPos;
00650 
00651                     CPKIFBufferPtr hashOfData = GetHash(curHashAlg, activeMediator);
00652                     CPKIFBufferPtr hashOfChain = CalculateHashOfArchiveTimestampChain(chain, activeMediator, curHashAlg);
00653 
00654                     CPKIFBufferPtr tmpBuf(new CPKIFBuffer);
00655                     unsigned char* pTmpBuf = tmpBuf->AllocateBuffer(hashOfData->GetLength() + hashOfChain->GetLength());
00656                     memcpy(pTmpBuf, hashOfData->GetBuffer(), hashOfData->GetLength());
00657                     memcpy(pTmpBuf+hashOfData->GetLength(),hashOfChain->GetBuffer(), hashOfChain->GetLength());
00658 
00659                     tv->SetDataComplete(tmpBuf);
00660                 }
00661             }
00662             else
00663             {
00664                 //this is not the first timestamp in this chain and must be verified against
00665                 //the preceding element in the chain
00666                 CPKIFArchiveTimestampPtr prevAts = *rChainPos;
00667 
00668                 //need to hash the timestamp field from the prevAts
00669                 CPKIFContentInfoPtr ci = prevAts->GetTimestamp();
00670 
00671                 CPKIFBufferPtr encodedTimestamp = ci->Encode();
00672                 tv->SetDataComplete(encodedTimestamp);
00673             }           
00674 
00675             tv->SetComparisonTime(timeOfInterest);
00676             tv->SetMediator(activeMediator);
00677             tv->SetPathSettings(activePathSettings);
00678             tv->Verify(curTimestamp);
00679 
00680             cr->push_back(tv);
00681 
00682             timeOfInterest = GetTimeFromTimestamp(curTimestamp);
00683             activeMediator = m_impl->GetMediator(timeOfInterest);
00684             activePathSettings = m_impl->GetPathSettings(timeOfInterest);
00685         }
00686     }
00687 
00688     return seqResults;
00689 }

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