CapiCRL.cpp

Go to the documentation of this file.
00001 
00009 #include "CRL.h"
00010 #include "CapiCRL.h"
00011 #include "CRLEntry.h"
00012 #include "ASN1Helper.h"
00013 #include "Certificate.h"
00014 #include "Buffer.h"
00015 #include "Name.h"
00016 #include "PKIFTime.h"
00017 #include "AlgorithmIdentifier.h"
00018 #include "ExtensionsMatch.h"
00019 #include "PKIFException.h"
00020 #include "PKIFX509Extensions2.h"
00021 #include "IssuingDistributionPoint.h"
00022 #include "CertificateIssuer.h"
00023 #include "GeneralName.h"
00024 #include "PKIFBase64.h"
00025 #include <sstream>
00026 #include "PKIFCommonErrors.h"
00027 #include "ToolkitUtils.h"
00028 
00029 using namespace std;
00030 using namespace boost;
00031 
00033 struct CPKIFCapiCRLImpl
00034 {
00042   CPKIFCapiCRLImpl();
00043  
00044   //added 2/24/2005
00045   void ClearContent();
00046   
00047   void populateExtensionsVector();
00048   
00049   CPKIFBufferPtr m_rawCRL;
00050   //CPKIFASNWrapper<CACX509V3CertificateList> m_signedCRL;
00051   std::vector<CPKIFX509ExtensionPtr> m_exts;
00052   std::vector<pair<CPKIFNamePtr, std::map<std::string, CPKIFCRLEntryPtr> > > m_vector;
00053   CPKIFNamePtr m_issuer;
00054   CPKIFTimePtr m_nextUpdate;
00055   CPKIFTimePtr m_thisUpdate;
00056   CPKIFAlgorithmIdentifierPtr m_sigAlg;
00057   CPKIFCapiCRL * m_this;
00058 
00059   CPKIFBufferPtr m_signature;
00060 
00061   PCCRL_CONTEXT m_crl;
00062 };
00063 
00071 CPKIFCapiCRLImpl::CPKIFCapiCRLImpl ()
00072 {
00073     m_crl = NULL;
00074 }
00075 
00076 //added 2/24/2005
00084 void CPKIFCapiCRLImpl::ClearContent()
00085 {
00086     CPKIFBufferPtr tmpBuf;
00087     m_rawCRL = tmpBuf;
00088 
00089     m_exts.clear();
00090 
00091     CPKIFNamePtr tmpIss;
00092     m_issuer = tmpIss;
00093     CPKIFTimePtr tmpNext;
00094     m_nextUpdate = tmpNext;
00095     CPKIFTimePtr tmpThis;
00096     m_thisUpdate = tmpThis;
00097     CPKIFAlgorithmIdentifierPtr tmpSig;
00098     m_sigAlg = tmpSig;
00099 }
00100 
00101 
00114 void CPKIFCapiCRLImpl::populateExtensionsVector()
00115 {
00116     //if we've already populated the extensions vector then return
00117     if(!m_exts.empty())
00118         return;
00119 
00120     //if there are no extensions then return
00121     if(0 == m_crl->pCrlInfo->cExtension)
00122     {
00123         m_exts.clear();
00124         return;
00125     }
00126 
00127     // get the one and only extension mediator, with any additions an app might
00128     // have made
00129     CPKIFX509ExtensionMediator2 * mediator = CPKIFX509ExtensionMediator2::GetInstance();
00130     m_this->IPKIFHasExtensions::GetExtensions (mediator, m_exts);
00131 }
00132 
00134 
00143 void CPKIFCapiCRL::GetExtensionByOID(
00145     const CPKIFOID& oid,
00147     CPKIFX509ExtensionPtr& ref)
00148 {
00149     if(m_impl->m_exts.empty() && m_impl->m_crl->pCrlInfo->cExtension)
00150         m_impl->populateExtensionsVector();
00151 
00152     vector<CPKIFX509ExtensionPtr>::iterator pos;
00153     vector<CPKIFX509ExtensionPtr>::iterator end = m_impl->m_exts.end();
00154     for(pos = m_impl->m_exts.begin(); pos != end; ++pos)
00155     {
00156         if(oid == (*pos)->oid())
00157         {
00158             ref = *pos;
00159             return;
00160         }
00161     }       
00162 }
00171 void CPKIFCapiCRL::GetEncodedExtensions (
00173     CPKIFBufferPtr& buf) 
00174 {
00175     try 
00176     {
00177         HRESULT hr= S_OK;
00178         if(m_impl->m_crl->pCrlInfo->cExtension)
00179         {
00180             _CERT_EXTENSIONS ce;
00181             ce.cExtension = m_impl->m_crl->pCrlInfo->cExtension;
00182             ce.rgExtension = m_impl->m_crl->pCrlInfo->rgExtension;
00183             unsigned char* pvEncoded = NULL;
00184             DWORD pcbEncoded = 0;
00185             CryptEncodeObjectEx(X509_ASN_ENCODING, X509_EXTENSIONS, &ce, 0, NULL, NULL, &pcbEncoded);
00186             pvEncoded = new unsigned char[pcbEncoded];
00187             if(CryptEncodeObjectEx(X509_ASN_ENCODING, X509_EXTENSIONS, &ce, 0, NULL, pvEncoded, &pcbEncoded))
00188             {
00189                 CPKIFBufferPtr encodedExtensions(new CPKIFBuffer(pvEncoded, pcbEncoded));
00190                 buf = encodedExtensions;
00191                 delete[] pvEncoded;
00192                 return;
00193             }
00194             else
00195             {
00196                 delete[] pvEncoded;
00197                 hr = GetLastError();
00198             }
00199         }
00200     }
00201     catch (... /*CPKIFException& e*/)
00202     {
00203         // How do we want to handle the exception?
00204     }
00205 
00206     CPKIFBufferPtr nullExt;
00207     buf = nullExt;
00208 }
00209 
00217 CPKIFCapiCRL::CPKIFCapiCRL(void): m_impl (new CPKIFCapiCRLImpl)
00218 {
00219     m_impl->m_this = this;
00220 }
00228 CPKIFCapiCRL::~CPKIFCapiCRL(void)
00229 {
00230     if(m_impl)
00231     {
00232         if(m_impl->m_crl)
00233         {
00234             CertFreeCRLContext(m_impl->m_crl);
00235             m_impl->m_crl = NULL;
00236         }
00237 
00238         delete m_impl;
00239         m_impl = 0;
00240     }
00241 }
00242 
00243 
00251 void CPKIFCapiCRL::Decode(
00253     const unsigned char* cert, 
00255     int certLen)
00256 {
00257     throw std::exception("CPKIFCapiCRL::Decode has not been implemented.");
00258 }
00259 
00270 int CPKIFCapiCRL::Version() const
00271 {
00272     switch( m_impl->m_crl->pCrlInfo->dwVersion ) 
00273     {
00274         case CRL_V1:
00275             return 1;
00276             break;
00277         case CRL_V2:
00278             return 2;
00279             break;
00280         default:
00281             throw CPKIFException(TOOLKIT_ASN, COMMON_UNSUPPORTED_VERSION, "Unsupported CRL version.");
00282     }
00283 }
00293 CPKIFNamePtr CPKIFCapiCRL::Issuer( ) const
00294 {
00295     if(m_impl->m_issuer == (CPKIFName*)NULL)
00296     {
00297         CPKIFBufferPtr tmpBuf;
00298         tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(m_impl->m_crl->pCrlInfo->Issuer.pbData, m_impl->m_crl->pCrlInfo->Issuer.cbData));
00299 
00300         CPKIFName* tmpName = new CPKIFName(tmpBuf);
00301         CPKIFNamePtr tmpRef(tmpName); 
00302 
00303         CPKIFCapiCRL* nonConstCert = const_cast<CPKIFCapiCRL*>(this);
00304         nonConstCert->m_impl->m_issuer = tmpRef;
00305     }
00306 
00307     return m_impl->m_issuer;
00308 }
00319 CPKIFBufferPtr CPKIFCapiCRL::Encoded() const 
00320 {
00321     if(!m_impl->m_rawCRL)
00322     {
00323         CPKIFBufferPtr tmp(new CPKIFBuffer(m_impl->m_crl->pbCrlEncoded, m_impl->m_crl->cbCrlEncoded));
00324         m_impl->m_rawCRL = tmp;
00325     }
00326     return m_impl->m_rawCRL;
00327 }
00328 
00340 bool CPKIFCapiCRL::CertOnThisCRL(
00342     const CPKIFCertificatePtr& cert, 
00344     CPKIFCRLEntryPtr& crlEntry)
00345 {
00346     PCCERT_CONTEXT certCtx = NULL;
00347 
00348     if(cert == (CPKIFCertificate*)NULL)
00349     {
00350         throw CPKIFException(TOOLKIT_ASN_SUBCOMPONENT, COMMON_INVALID_INPUT, "NULL certificate passed to CertOnThisCRL.");
00351     }
00352 
00353     certCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->Encoded()->GetBuffer(), cert->Encoded()->GetLength());
00354     if(NULL == certCtx)
00355     {
00356         std::ostringstream os;
00357         os << "Failed to parse certificate passed to CertOnThisCRL.  CertCreateCertificateContext failed: " << GetLastError();
00358         throw CPKIFException(TOOLKIT_ASN_SUBCOMPONENT, COMMON_INVALID_INPUT, os.str().c_str());
00359     }
00360 
00361     PCRL_ENTRY pCrlEntry = NULL;
00362     if(CertFindCertificateInCRL(certCtx, m_impl->m_crl, 0, 0, &pCrlEntry))
00363     {
00364         if(pCrlEntry)
00365         {
00366             CPKIFCapiCRLEntryPtr capiCRLEntry(new CPKIFCapiCRLEntry(pCrlEntry));
00367             CPKIFCRLEntryPtr rv = dynamic_pointer_cast<CPKIFCRLEntry, CPKIFCapiCRLEntry>(capiCRLEntry);
00368             crlEntry = rv;
00369             return true;
00370         }
00371         else
00372             return false;
00373     }
00374     else
00375     {
00376         throw std::exception("Failed to search CRL");
00377     }
00378 }
00386 CPKIFBufferPtr CPKIFCapiCRL::Signature() const
00387 {
00388     if(m_impl->m_signature == (CPKIFBuffer*)NULL)
00389     {
00390         CACASNWRAPPER_CREATE(CACX509V3CertificateList, objPDU);
00391         CACX509V3CertificateList* tc = objPDU.Decode(m_impl->m_crl->pbCrlEncoded, m_impl->m_crl->cbCrlEncoded);
00392 
00393         CPKIFBufferPtr tmp(new CPKIFBuffer(tc->signature.data, tc->signature.numbits/8));
00394         CPKIFCapiCRL* nonConstCert = const_cast<CPKIFCapiCRL*>(this);
00395         nonConstCert->m_impl->m_signature = tmp;
00396     }
00397     return m_impl->m_signature;
00398 }
00408 CPKIFTimePtr CPKIFCapiCRL::NextUpdate( ) const
00409 {
00410     if(m_impl->m_nextUpdate == (CPKIFTime*)NULL)
00411     {
00412         unsigned char* pvEncoded = NULL;
00413         DWORD pcbEncoded = 0;
00414         CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME, &m_impl->m_crl->pCrlInfo->NextUpdate, 0, NULL, NULL, &pcbEncoded);
00415         pvEncoded = new unsigned char[pcbEncoded];
00416         if(CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME, &m_impl->m_crl->pCrlInfo->NextUpdate, 0, NULL, pvEncoded, &pcbEncoded))
00417         {
00418             CACASNWRAPPER_CREATE(CACX509V3Time, objPDU);
00419             CACX509V3Time* time = objPDU.Decode(pvEncoded, pcbEncoded);
00420             delete[] pvEncoded;
00421 
00422             CPKIFTime* tmpTime = NULL;
00423             if(time->t == T_CACX509V3Time_utcTime)
00424             {
00425                 tmpTime = new CPKIFTime(time->u.utcTime, UTCTIME);
00426             }
00427             else
00428             {
00429                 tmpTime = new CPKIFTime(time->u.generalTime, GENERALIZEDTIME);
00430             }
00431             CPKIFTimePtr tmpRef(tmpTime); 
00432 
00433             CPKIFCapiCRL* nonConstCert = const_cast<CPKIFCapiCRL*>(this);
00434             nonConstCert->m_impl->m_nextUpdate = tmpRef;
00435         }
00436         else
00437         {
00438             delete[] pvEncoded;
00439             HRESULT hr = GetLastError();
00440         }
00441     }
00442 
00443     return m_impl->m_nextUpdate;
00444 }
00454 CPKIFTimePtr CPKIFCapiCRL::ThisUpdate( ) const
00455 {
00456     if(m_impl->m_thisUpdate == (CPKIFTime*)NULL)
00457     {
00458         unsigned char* pvEncoded = NULL;
00459         DWORD pcbEncoded = 0;
00460         CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME, &m_impl->m_crl->pCrlInfo->ThisUpdate, 0, NULL, pvEncoded, &pcbEncoded);
00461         pvEncoded = new unsigned char[pcbEncoded];
00462         if(CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME, &m_impl->m_crl->pCrlInfo->ThisUpdate, 0, NULL, pvEncoded, &pcbEncoded))
00463         {
00464             CACASNWRAPPER_CREATE(CACX509V3Time, objPDU);
00465             CACX509V3Time* time = objPDU.Decode(pvEncoded, pcbEncoded);
00466             delete[] pvEncoded;
00467 
00468             CPKIFTime* tmpTime = NULL;
00469             if(time->t == T_CACX509V3Time_utcTime)
00470             {
00471                 tmpTime = new CPKIFTime(time->u.utcTime, UTCTIME);
00472             }
00473             else
00474             {
00475                 tmpTime = new CPKIFTime(time->u.generalTime, GENERALIZEDTIME);
00476             }
00477             CPKIFTimePtr tmpRef(tmpTime); 
00478 
00479             CPKIFCapiCRL* nonConstCert = const_cast<CPKIFCapiCRL*>(this);
00480             nonConstCert->m_impl->m_thisUpdate = tmpRef;
00481         }
00482         else
00483         {
00484             delete[] pvEncoded;
00485             HRESULT hr = GetLastError();
00486         }
00487     }
00488 
00489     return m_impl->m_thisUpdate;
00490 }
00500 CPKIFAlgorithmIdentifierPtr CPKIFCapiCRL::SignatureAlgorithm( ) const
00501 {
00502     if(m_impl->m_sigAlg == (CPKIFAlgorithmIdentifier*)NULL)
00503     {
00504         CPKIFOIDPtr algOID(new CPKIFOID(m_impl->m_crl->pCrlInfo->SignatureAlgorithm.pszObjId));
00505 
00506         CPKIFBufferPtr paramBuf;
00507         if(m_impl->m_crl->pCrlInfo->SignatureAlgorithm.Parameters.cbData)
00508         {
00509                 paramBuf = CPKIFBufferPtr(new CPKIFBuffer(m_impl->m_crl->pCrlInfo->SignatureAlgorithm.Parameters.pbData,
00510                                 m_impl->m_crl->pCrlInfo->SignatureAlgorithm.Parameters.cbData));
00511         
00512         }
00513 
00514         CPKIFAlgorithmIdentifierPtr tmpRef(new CPKIFAlgorithmIdentifier(algOID, paramBuf));  
00515 
00516         CPKIFCapiCRL* nonConstCert = const_cast<CPKIFCapiCRL*>(this);
00517         nonConstCert->m_impl->m_sigAlg = tmpRef;
00518     }
00519 
00520     return m_impl->m_sigAlg;
00521 }
00530 bool CPKIFCapiCRL::AreThereAnyUnprocessedCriticalExtensions(
00532     std::vector<CPKIFX509ExtensionPtr>& processedExts)
00533 {
00534     std::vector<CPKIFX509ExtensionPtr>::iterator pos;
00535     std::vector<CPKIFX509ExtensionPtr>::iterator end = m_impl->m_exts.end();
00536     std::vector<CPKIFX509ExtensionPtr>::iterator processedEnd = processedExts.end();
00537     ExtensionsMatch em;
00538     size_t count = processedExts.size();
00539     for(pos = m_impl->m_exts.begin(); pos != end; ++pos)
00540     {
00541         em.SetRHS(*pos);
00542         if((*pos)->isCritical() && processedEnd == find_if(processedExts.begin(), processedExts.end(), em))
00543             return true;
00544     }
00545 
00546     return false;
00547 }
00555 bool CPKIFCapiCRL::operator==(const CPKIFCRL& rhs) const
00556 {
00557     return *this->Encoded() == *rhs.Encoded();
00558 }
00559 
00569 void CPKIFCapiCRL::SetCRL(PCCRL_CONTEXT crl)
00570 {
00571     m_impl->m_crl = crl;
00572 }
00573 
00574 struct CPKIFCapiCRLEntryImpl
00575 {
00576   CPKIFCapiCRLEntryImpl();
00577  
00578   void ClearContent();
00579   
00580   void populateExtensionsVector();
00581   
00582   CPKIFBufferPtr m_rawCRL;
00583   //CPKIFASNWrapper<CACX509V3CertificateList> m_signedCRL;
00584   std::vector<CPKIFX509ExtensionPtr> m_exts;
00585   CPKIFTimePtr m_revocationDate;
00586   CPKIFBufferPtr m_serialNumber; //buffer holds ASCII Hex serial number
00587   CPKIFCapiCRLEntry * m_this;
00588   PCRL_ENTRY m_crlEntry;
00589 };
00590 
00598 CPKIFCapiCRLEntryImpl::CPKIFCapiCRLEntryImpl()
00599 {
00600     m_this = NULL;
00601     m_crlEntry = NULL;
00602 }
00603 
00611 void CPKIFCapiCRLEntryImpl::ClearContent()
00612 {
00613 }
00614 
00622 void CPKIFCapiCRLEntryImpl::populateExtensionsVector()
00623 {
00624     //if we've already populated the extensions vector then return
00625     if(!m_exts.empty())
00626         return;
00627 
00628     //if there are no extensions then return
00629     if(0 == m_crlEntry->cExtension)
00630     {
00631         m_exts.clear();
00632         return;
00633     }
00634 
00635     // get the one and only extension mediator, with any additions an app might
00636     // have made
00637     CPKIFX509ExtensionMediator2 * mediator = CPKIFX509ExtensionMediator2::GetInstance();
00638     m_this->IPKIFHasExtensions::GetExtensions (mediator, m_exts);
00639 }
00640 
00648 CPKIFCapiCRLEntry::CPKIFCapiCRLEntry(PCRL_ENTRY crlEntry) : m_impl(new CPKIFCapiCRLEntryImpl)
00649 {
00650     m_impl->m_this = this;
00651     m_impl->m_crlEntry = crlEntry;
00652 }
00653 
00661 CPKIFCapiCRLEntry::~CPKIFCapiCRLEntry()
00662 {
00663 }
00664 
00672 bool CPKIFCapiCRLEntry::AreThereAnyUnprocessedCriticalExtensions(std::vector<CPKIFX509ExtensionPtr>& processedExts)
00673 {
00674     std::vector<CPKIFX509ExtensionPtr>::iterator pos;
00675     std::vector<CPKIFX509ExtensionPtr>::iterator end = m_impl->m_exts.end();
00676     std::vector<CPKIFX509ExtensionPtr>::iterator processedEnd = processedExts.end();
00677     ExtensionsMatch em;
00678     size_t count = processedExts.size();
00679     for(pos = m_impl->m_exts.begin(); pos != end; ++pos)
00680     {
00681         em.SetRHS(*pos);
00682         if((*pos)->isCritical() && processedEnd == find_if(processedExts.begin(), processedExts.end(), em))
00683             return true;
00684     }
00685 
00686     return false;
00687 }
00688 
00697 void CPKIFCapiCRLEntry::GetEncodedExtensions (CPKIFBufferPtr& buf)
00698 {
00699     try 
00700     {
00701         HRESULT hr= S_OK;
00702         if(m_impl->m_crlEntry->cExtension)
00703         {
00704             _CERT_EXTENSIONS ce;
00705             ce.cExtension = m_impl->m_crlEntry->cExtension;
00706             ce.rgExtension = m_impl->m_crlEntry->rgExtension;
00707             unsigned char* pvEncoded = NULL;
00708             DWORD pcbEncoded = 0;
00709             CryptEncodeObjectEx(X509_ASN_ENCODING, X509_EXTENSIONS, &ce, 0, NULL, NULL, &pcbEncoded);
00710             pvEncoded = new unsigned char[pcbEncoded];
00711             if(CryptEncodeObjectEx(X509_ASN_ENCODING, X509_EXTENSIONS, &ce, 0, NULL, pvEncoded, &pcbEncoded))
00712             {
00713                 CPKIFBufferPtr encodedExtensions(new CPKIFBuffer(pvEncoded, pcbEncoded));
00714                 buf = encodedExtensions;
00715                 delete[] pvEncoded;
00716                 return;
00717             }
00718             else
00719             {
00720                 delete[] pvEncoded;
00721                 hr = GetLastError();
00722             }
00723         }
00724     }
00725     catch (... /*CPKIFException& e*/)
00726     {
00727         // How do we want to handle the exception?
00728     }
00729 
00730     CPKIFBufferPtr nullExt;
00731     buf = nullExt;
00732 }
00733 
00743 void CPKIFCapiCRLEntry::GetExtensionByOID(const CPKIFOID& oid, CPKIFX509ExtensionPtr& ref)
00744 {
00745     if(m_impl->m_exts.empty() && m_impl->m_crlEntry->cExtension)
00746         m_impl->populateExtensionsVector();
00747 
00748     vector<CPKIFX509ExtensionPtr>::iterator pos;
00749     vector<CPKIFX509ExtensionPtr>::iterator end = m_impl->m_exts.end();
00750     for(pos = m_impl->m_exts.begin(); pos != end; ++pos)
00751     {
00752         if(oid == (*pos)->oid())
00753         {
00754             ref = *pos;
00755             return;
00756         }
00757     }       
00758 }
00759 
00769 const char* CPKIFCapiCRLEntry::SerialNumber() const
00770 {
00771     if(m_impl->m_serialNumber == (CPKIFBuffer*)NULL)
00772     {
00773         CPKIFBufferPtr tmp(new CPKIFBuffer);
00774         int len = (m_impl->m_crlEntry->SerialNumber.cbData * 2) + 3;
00775         unsigned char* tmpBuf = tmp->AllocateBuffer(len - 1);
00776         memset(tmpBuf, 0x00, len);
00777         tmpBuf[0] = '0';
00778         tmpBuf[1] = 'x';
00779         btoa((char*)m_impl->m_crlEntry->SerialNumber.pbData, (char*)tmpBuf+2, m_impl->m_crlEntry->SerialNumber.cbData);
00780 
00781         CPKIFCapiCRLEntry* nonConst = const_cast<CPKIFCapiCRLEntry*>(this);
00782         nonConst->m_impl->m_serialNumber = tmp;
00783     }
00784     return (char*)m_impl->m_serialNumber->GetBuffer();
00785 }
00786 
00795 const CPKIFTimePtr CPKIFCapiCRLEntry::RevocationDate() const
00796 {
00797     if(m_impl->m_revocationDate == (CPKIFTime*)NULL)
00798     {
00799         unsigned char* pvEncoded = NULL;
00800         DWORD pcbEncoded = 0;
00801         CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME, &m_impl->m_revocationDate, 0, NULL, pvEncoded, &pcbEncoded);
00802         pvEncoded = new unsigned char[pcbEncoded];
00803         if(CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CHOICE_OF_TIME, &m_impl->m_revocationDate, 0, NULL, pvEncoded, &pcbEncoded))
00804         {
00805             CACASNWRAPPER_CREATE(CACX509V3Time, objPDU);
00806             CACX509V3Time* time = objPDU.Decode(pvEncoded, pcbEncoded);
00807             delete[] pvEncoded;
00808 
00809             CPKIFTime* tmpTime = NULL;
00810             if(time->t == T_CACX509V3Time_utcTime)
00811             {
00812                 tmpTime = new CPKIFTime(time->u.utcTime, UTCTIME);
00813             }
00814             else
00815             {
00816                 tmpTime = new CPKIFTime(time->u.generalTime, GENERALIZEDTIME);
00817             }
00818             CPKIFTimePtr tmpRef(tmpTime); 
00819 
00820             CPKIFCapiCRLEntry* nonConst = const_cast<CPKIFCapiCRLEntry*>(this);
00821             nonConst->m_impl->m_revocationDate = tmpRef;
00822         }
00823         else
00824         {
00825             delete[] pvEncoded;
00826             HRESULT hr = GetLastError();
00827         }
00828     }
00829 
00830     return m_impl->m_revocationDate;
00831 }

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