CACCMSUtils.cpp

Go to the documentation of this file.
00001 
00009 #include "PKIFCMSUtils.h"
00010 #include "PKIFMemoryUtils.h"
00011 #include "private/PrivatePKIFCMSUtils.h"
00012 #include "Attribute.h"
00013 #include "Certificate.h"
00014 #include "KeyUsage.h"
00015 #include "OID.h"
00016 #include "AttrMatch.h"
00017 #include "AlgorithmIdentifier.h"
00018 #include "MessageDigestAttribute.h"
00019 #include "ContentTypeAttribute.h"
00020 #include "SignerInfo.h"
00021 #include "IssuerAndSerialNumber.h"
00022 #include "SubjectKeyIdentifier.h"
00023 #include "SubjectPublicKeyInfo.h"
00024 #include "Name.h"
00025 #include "KEKRecipInfoDetails.h"
00026 #include "CountersignatureAttribute.h"
00027 
00028 #include "PKIFCertificateNodeEntry.h"
00029 #include "PathResults.h"
00030 #include "ToolkitUtils.h"
00031 #include "components.h"
00032 #include "PKIFMessageException.h"
00033 #include "PKIFCommonErrors.h"
00034 #include "ASN1Helper.h"
00035 #include "Buffer.h"
00036 #include "OID.h"
00037 #include "IPKIFColleague.h"
00038 #include "IPKIFCryptoKeyAgree.h"
00039 #include "ParallelHash.h"
00040 #include "PKIFCMSMessageMemoryHelper.h"
00041 #include "PKIFFuncStorage.h"
00042 #include "PKIFAlgorithm.h"
00043 
00044 #include "PKIX1Algorithms88.h"
00045 #include "CryptographicMessageSyntax2004.h"
00046 #include "ECC-CMS.h"
00047 
00048 #include "IPKIFCryptoKeyIDOperations.h"
00049 #include "IPKIFCryptoMisc.h"
00050 #include "IPKIFCryptoRawOperations.h"
00051 #include "IPKIFPathBuild.h"
00052 #include "IPKIFPathValidate.h"
00053 #include "IPKIFHashContext.h"
00054 #include "IPKIFKeyAgreeContext.h"
00055 
00056 #include "PKIFCryptoPPUtils.h"
00057 
00058 #include "SignedData.h"
00059 
00060 #include "PKIFCAPIErrors.h"
00061 #include "PKIFCryptoPPErrors.h"
00062 #include "PKIFNSSErrors.h"
00063 using namespace std;
00064 
00078 void PKIFCMS_API keyUsageChecker_Signature(
00080     const CPKIFCertificateNodeEntryPtr& certNode,
00082     CPKIFPathValidationResults& results,
00084     CertificateType type)
00085 {
00086     if(EE == type)
00087     {
00088         CPKIFCertificatePtr curCert = certNode->GetCert();
00089         CPKIFKeyUsagePtr keyUsage = curCert->GetExtension<CPKIFKeyUsage>();
00091         if(keyUsage != (CPKIFKeyUsage*)NULL && (keyUsage->DigitalSignature() || keyUsage->NonRepudiation()))
00092         {
00093             CPKIFX509ExtensionPtr keyUsage2 = keyUsage;
00094             certNode->MarkExtensionAsProcessed(keyUsage2);
00095         }
00096     }
00097 }
00111 void PKIFCMS_API keyUsageChecker_Encryption(
00114     const CPKIFCertificateNodeEntryPtr& certNode,
00116     CPKIFPathValidationResults& results,
00118     CertificateType type)
00119 {
00120     if(EE == type)
00121     {
00122         CPKIFCertificatePtr curCert = certNode->GetCert();
00123         CPKIFKeyUsagePtr keyUsage = curCert->GetExtension<CPKIFKeyUsage>();
00124         if(keyUsage != (CPKIFKeyUsage*)NULL && keyUsage->KeyEncipherment())
00125         {
00126             CPKIFX509ExtensionPtr keyUsage2 = keyUsage;
00127             certNode->MarkExtensionAsProcessed(keyUsage2);
00128         }
00129     }
00130 }
00131 
00145 void PKIFCMS_API keyUsageChecker_KeyAgreement(
00148     const CPKIFCertificateNodeEntryPtr& certNode,
00150     CPKIFPathValidationResults& results,
00152     CertificateType type)
00153 {
00154     if(EE == type)
00155     {
00156         CPKIFCertificatePtr curCert = certNode->GetCert();
00157         CPKIFKeyUsagePtr keyUsage = curCert->GetExtension<CPKIFKeyUsage>();
00158         if(keyUsage != (CPKIFKeyUsage*)NULL && keyUsage->KeyAgreement())
00159         {
00160             CPKIFX509ExtensionPtr keyUsage2 = keyUsage;
00161             certNode->MarkExtensionAsProcessed(keyUsage2);
00162         }
00163     }
00164 }
00165 #if 0
00166 
00173 void PKIFCMS_API CopyOID(
00175     ASN1OBJID* dest, 
00177     ASN1OBJID* src)
00178 {
00179     dest->numids = src->numids;
00180     for(unsigned int ii = 0; ii < src->numids; ++ii)
00181         dest->subid[ii] = src->subid[ii];
00182 }
00183 #endif
00184 
00192 CPKIFAlgorithm * GetCACHashAlg(
00194     CACX509V3AlgorithmIdentifier* alg
00195     )
00196 {
00197     if(0 == alg) return 0;
00198 
00199     CPKIFOIDPtr algOID(new CPKIFOID(alg->algorithm.subid, alg->algorithm.numids));
00200     CPKIFAlgorithm * pkifAlg = CPKIFAlgorithm::GetAlg(algOID);
00201     if (*(pkifAlg->OID()) != *algOID) {
00202         return 0;
00203     }
00204     return pkifAlg;
00205 }
00213 CPKIFAlgorithm * GetCACSymAlg(
00215     CACX509V3AlgorithmIdentifier* alg 
00216 )
00217 {
00218     if(0 == alg) return 0;
00219 
00220     CPKIFOIDPtr algOID(new CPKIFOID(alg->algorithm.subid, alg->algorithm.numids));
00221     CPKIFAlgorithm * pkifAlg = CPKIFAlgorithm::GetAlg(algOID);
00222     if (*(pkifAlg->OID()) != *algOID) {
00223         return 0;
00224     }
00225     return pkifAlg;
00226 }
00234 bool ModeRequiresIV(
00236     PKIFCRYPTO::SYMKEY_MODE mode)
00237 {
00238     if(PKIFCRYPTO::ECB == mode)
00239         return false;
00240     else
00241         return true;
00242 }
00243 
00244 
00245 
00246 
00247 // Destructor
00248 
00258 void EncodeDSASignature(
00260     unsigned char* sig,
00262     int nSigLen, 
00264     unsigned char** sigData,
00266     int* numocts)
00267 {
00268     if(NULL == sig || 0 == nSigLen || MAXHASH*2 < nSigLen || NULL == sigData || NULL == numocts || 0 != nSigLen%2)
00269         throw CPKIFMessageException(TOOLKIT_MESSAGE_ASN, COMMON_INVALID_INPUT, "An input to EncodeDSASignature was invalid."); 
00270 
00271     //MAXHASH instead of MAXHASH/2 because it'll be an ASCII HEX input
00272     const int asciiHexHash = (MAXHASH*2) + 5;
00273     char r[asciiHexHash]; memset(r, 0, asciiHexHash); r[0] = '0'; r[1] = 'x'; //memsets added 11/7/2003
00274     char s[asciiHexHash]; memset(s, 0, asciiHexHash); s[0] = '0'; s[1] = 'x'; 
00275     
00276     //added this offset business 11/7/2003
00277     int offset = 2;
00278     if(sig[0] >= (unsigned char)0x80)
00279     {
00280         r[2] = '0'; ++offset;
00281         r[3] = '0'; ++offset;
00282     }
00283     btoa((char*)sig, r+offset, nSigLen/2);
00284 
00285     offset = 2;
00286     if(sig[(nSigLen/2)] >= (unsigned char)0x80)
00287     {
00288         s[2] = '0'; ++offset;
00289         s[3] = '0'; ++offset;
00290     }
00291     btoa((char*)sig+(nSigLen/2), s+offset, nSigLen/2);
00292     
00293     Dss_Sig_Value dssSigVal; 
00294     dssSigVal.r = r;
00295     dssSigVal.s = s;
00296 
00297     CACASNWRAPPER_CREATE(Dss_Sig_Value, tmpPDU);
00298     ASN1OpenType* data1 = tmpPDU.Encode(&dssSigVal);
00299 
00300     *numocts = data1->numocts;
00301     *sigData = new unsigned char[data1->numocts + 1];
00302     memcpy(*sigData, data1->data, data1->numocts);
00303     delete data1;//added 11/9
00304 }
00312 void AddSignedAttributes(
00314     unsigned char* hashResult, 
00316     int nHashResult, 
00318     CPKIFOIDPtr& eContentType, 
00320     CPKIFAttributeList& sas)
00321 {
00322     //first, see if there's any work to do (i.e. if the content type is not id-data and/or
00323     //signed attributes are already present we have work to do - else return)
00324     if(*g_data == eContentType && sas.empty())
00325         return;
00326 
00327     //next look through the collected attributes and see if we have message digest and/or content type
00328     //attributes already present
00329     bool foundMD = false, foundCT = false;
00330 
00331     AttrMatch attrSearch;
00332     attrSearch.SetRHS(g_messageDigestAttribute);
00333     CPKIFAttributeList::iterator end = sas.end();
00334     if(end != find_if(sas.begin(), sas.end(), attrSearch))
00335         foundMD = true;
00336     
00337     attrSearch.SetRHS(g_contentTypeAttribute);
00338     if(end != find_if(sas.begin(), sas.end(), attrSearch))
00339         foundCT = true;
00340 
00341     if(!foundMD)
00342     {
00343         CPKIFMessageDigestAttributePtr mdAttr(new CPKIFMessageDigestAttribute());
00344         CPKIFBufferPtr mdBuf(new CPKIFBuffer(hashResult, nHashResult));
00345         mdAttr->SetMessageDigest(mdBuf);
00346         sas.push_back(mdAttr);
00347     }
00348 
00349     if(!foundCT)
00350     {
00351         CPKIFContentTypeAttributePtr ctAttr(new CPKIFContentTypeAttribute());
00352         ctAttr->SetContentType(eContentType);
00353         sas.push_back(ctAttr);
00354     }
00355 }
00363 void SetupAttributesInObjectiveStructure(
00365     CPKIFAttributeList& attrs,
00367     DList& objAttrs)
00368 {
00369     objAttrs.count = 0;
00370     objAttrs.head = NULL;
00371     objAttrs.tail = NULL;
00372 
00373     DListNode* cur = NULL;
00374     CPKIFAttributeList::iterator sasPos;
00375     CPKIFAttributeList::iterator sasEnd = attrs.end();
00376     for(sasPos = attrs.begin(); sasPos != sasEnd; ++sasPos)
00377     {
00378         CPKIFBufferList bl;
00379         (*sasPos)->GetValues(bl);
00380 
00381         if(NULL == cur)
00382         {
00383             NEW_NODE(cur)
00384         }
00385         else
00386         {
00387             NEW_NEXT_AND_ADVANCE(cur)
00388         }
00389 
00390         CPKIFBufferList::iterator bufPos;
00391         DListNode* cur2 = NULL;
00392 
00393         CACCMSAttribute* attr = new CACCMSAttribute;
00394         CPKIFStringPtr str(new std::string((*sasPos)->GetOID()->ToString()));
00395         ASN1OBJID* tmpOid = ConvertStringToASN1OBJID(str);
00396         CopyOID(&attr->attrType, tmpOid);
00397         if(tmpOid)
00398             delete tmpOid;
00399         //CopyOID(&attr->attrType, (*sasPos)->GetOID()->raw());
00400 
00401         DList* attrVals = new DList;//;&attr->attrValues;
00402         attrVals->count = 0;
00403         attrVals->head = NULL;
00404         attrVals->tail = NULL;
00405 
00406         cur->data = attr;
00407         CPKIFBufferList::iterator bufEnd = bl.end();
00408         for(bufPos = bl.begin(); bufPos != bufEnd; ++bufPos)
00409         {
00410             if(NULL == cur2)
00411             {
00412                 NEW_NODE(cur2)
00413             }
00414             else
00415             {
00416                 NEW_NEXT_AND_ADVANCE(cur2)
00417             }
00418 
00419             ASN1OpenType* tmpOT = new ASN1OpenType;
00420             tmpOT->numocts = (*bufPos)->GetLength();
00421             tmpOT->data = new unsigned char[tmpOT->numocts];
00422             memcpy((void*)tmpOT->data, (*bufPos)->GetBuffer(), tmpOT->numocts);
00423             cur2->data = tmpOT;
00424 
00425             SET_HEAD_TAIL_INCREMENT((*attrVals), cur2)
00426         }
00427 
00428         SET_HEAD_TAIL_INCREMENT(objAttrs, cur)
00429 
00430         CACASNWRAPPER_CREATE(CACCMSAttributeValues, avs);
00431         ASN1OpenType* aot = avs.Encode(attrVals);
00432 
00433         attr->attrValues.data = new unsigned char[aot->numocts];
00434         // XXX TODO (REVIEW): Make sure this cast is decent and there's not a better function to use
00435         memcpy((void *)attr->attrValues.data,aot->data,aot->numocts);
00436         attr->attrValues.numocts = aot->numocts;
00437         delete aot;
00438 
00439         DListNode* cur = NULL, *tmp = NULL;
00440         cur = attrVals->head;
00441         while(NULL != cur)
00442         {
00443             ASN1OpenType* tmpOT = (ASN1OpenType*)cur->data;
00444             if(NULL != tmpOT->data)
00445                 delete[] tmpOT->data;
00446 
00447             delete tmpOT;
00448 
00449             tmp = cur->next;
00450             delete cur;
00451             cur = tmp;
00452         }
00453 
00454         if(attrVals != NULL)
00455             delete attrVals;
00456 
00457         //XXX***CLEAN UP ATTRVALS
00458 
00459     }
00460 }
00471 void GetSignerInfo(
00473     CACCMSSignerInfo* tmpSignerInfo,
00475     CPKIFSignerInfoPtr& siPos, 
00477     unsigned char* hashResult, 
00479     int nHashResult, 
00481     IPKIFMediatorPtr m,
00483     CPKIFOIDPtr& eContentType,
00485     PKIFCRYPTO::HASH_ALG hashAlg,
00487     bool useSKIDIfPresent)
00488 {
00489     IPKIFCryptoKeyIDOperations* cm = m->GetMediator<IPKIFCryptoKeyIDOperations>();
00490     IPKIFCryptoMisc* cMisc = m->GetMediator<IPKIFCryptoMisc>();
00491 
00492     //The hash value that is passed in is the hash of the data that is covered by the signed data
00493     //object that is parent to the signer info passed in.  This function will prepare the signer info,
00494     //including signature generation and attribute set-up.  Essentially, there are two scenarios that we support
00495     //(hopefully that's all there are) for signed attribute preparation:
00496     //  -if a signed attribute has been included by the caller, the target of the signature is the DER encoding 
00497     //      of the signed attributes.  In such cases the signed attributes must include content type and message 
00498     //      digest, where the message digest is the hash passed to this function.  
00499     //  - if the type of encapsulated data is not id-data then the content type must be included as a signed
00500     //      attribute (along with message digest).
00501 
00502     //Get the certificate from the credential and set-up the SignerIdentifer.  The following code AUTOMATICALLY
00503     //selects the type of signer identifier based on the presence/absence of a subject key ID in the signer's
00504     //certificate.
00505     if(!siPos->Decoded())
00506     {
00507         if(NULL == hashResult || 0 == nHashResult)
00508             throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_UNSUPPORTED_ALG, "SignerInfo contains an unsupported hash algorithm or a signer is being added to an object with detached content after encoding.");
00509 
00510         CPKIFCertificatePtr cert = siPos->GetCredential()->GetCertificate();
00511         CPKIFSubjectKeyIdentifierPtr skid = cert->GetExtension<CPKIFSubjectKeyIdentifier>();
00512         if(skid != (CPKIFSubjectKeyIdentifier*)NULL && useSKIDIfPresent)
00513         {
00514             tmpSignerInfo->version = CACCMSv3; 
00515 
00516             //use skid if present
00517             tmpSignerInfo->sid.t = 2;
00518             CPKIFBufferPtr skidBuf = skid->KeyIdentifier();
00519             tmpSignerInfo->sid.u.subjectKeyIdentifier = new CACCMSSubjectKeyIdentifier;
00520             tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts = skidBuf->GetLength();
00521             tmpSignerInfo->sid.u.subjectKeyIdentifier->data = new unsigned char[tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts];
00522             memcpy((void*)tmpSignerInfo->sid.u.subjectKeyIdentifier->data, skidBuf->GetBuffer(), tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts);
00523         }
00524         else
00525         {
00526             tmpSignerInfo->version = CACCMSv1; 
00527 
00528             //otherwise use issuer DN and serial number
00529             tmpSignerInfo->sid.t = 1;
00530             tmpSignerInfo->sid.u.issuerAndSerialNumber = new CACCMSIssuerAndSerialNumber;
00531             tmpSignerInfo->sid.u.issuerAndSerialNumber->serialNumber = cert->SerialNumber();
00532 
00533             CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
00534             CACX509V3Name *tmpName = NULL;
00535             CPKIFBufferPtr nameBuf = cert->Issuer()->rawName();
00536             tmpName = objPDU.Decode(nameBuf->GetBuffer(), nameBuf->GetLength());
00537             //CACX509V3Name *tmpName2 = &tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer;
00538             //tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer = *tmpName; 
00539             //CopyName(&tmpName2, *tmpName);
00540             CopyName(&tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer, *tmpName);
00541             //tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer = *cert->Issuer()->rawName();
00542         }
00543 
00544         tmpSignerInfo->m.signedAttrsPresent = 0;
00545 
00546         //de-hardcoded usage of SHA1 - 11/06/2003
00547         CPKIFStringPtr str(new std::string(siPos->GetDigestAlg()->oid()->ToString())); 
00548         ASN1OBJID* tmpOid = ConvertStringToASN1OBJID(str);
00549         CopyOID(&tmpSignerInfo->digestAlgorithm.algorithm, tmpOid);
00550         if(tmpOid)
00551             delete tmpOid;
00552         //CopyOID(&tmpSignerInfo->digestAlgorithm.algorithm, siPos->GetDigestAlg()->oid()->raw());
00553         tmpSignerInfo->digestAlgorithm.m.parametersPresent = 1;
00554         tmpSignerInfo->digestAlgorithm.parameters.data = nullParams;
00555         tmpSignerInfo->digestAlgorithm.parameters.numocts = 2;
00556 
00557         {//begin signed attribute block
00558             CPKIFAttributeList sas;
00559             siPos->GetSignedAttributes(sas);
00560 
00561             AddSignedAttributes(hashResult, nHashResult, eContentType, sas);
00562             SetupAttributesInObjectiveStructure(sas, tmpSignerInfo->signedAttrs);
00563             
00564             if(!sas.empty())
00565                 tmpSignerInfo->m.signedAttrsPresent = 1;
00566         }//end signed attribute block
00567 
00568         unsigned char* signThis = hashResult;
00569         int nSignThisLen = nHashResult;
00570 
00571         HashInfo* hi = NULL;
00572         if(tmpSignerInfo->m.signedAttrsPresent)
00573         {
00574             //fix-up DER encoding of signed attributes
00575 
00576             hi = ComputeSignedAttrHash(tmpSignerInfo, cMisc);
00577 
00578             signThis = hi->m_hashResult;
00579             nSignThisLen = CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize();
00580         }
00581 
00582         unsigned char sig[500]; memset(sig, 0, 500);
00583         int nSigLen = 500;
00584         try
00585         {
00586             cm->Sign(*siPos->GetCredential(), signThis, nSignThisLen, sig, &nSigLen, hashAlg);
00587         }
00588         catch(CPKIFException& e)
00589         {
00590             if(NULL != hi)
00591                 delete hi;
00592 
00593             std::string reason = "Error generating signature using credential named: ";
00594             reason.append(siPos->GetCredential()->Name());
00595 
00596             CPKIFMessageException me(TOOLKIT_MESSAGE_ASN, MSG_SIGNATURE_GENERATION_ERROR, reason.c_str());
00597             me.push_info(e);
00598             //delete e;
00599             throw me;
00600         }
00601 
00602         if(NULL != hi)
00603             delete hi;
00604 
00605         CPKIFStringPtr anotherStr2; 
00606         CPKIFAlgorithmIdentifierPtr certAlg = cert->SubjectPublicKeyInfo()->alg();
00607         if(DSA_CLASS == GetAlgClass(certAlg))
00608         {
00609             //need to encode the DSA signature
00610             EncodeDSASignature(sig, nSigLen, (unsigned char**)&tmpSignerInfo->signature.data, (int*)&tmpSignerInfo->signature.numocts);
00611 
00612             if(PKIFCRYPTO::SHA1 == hashAlg)
00613             {
00614                 CPKIFStringPtr tmpOidSt(new std::string(g_dsaWithSHA1->ToString())); 
00615                 anotherStr2 = tmpOidSt;
00616             }
00617         }
00618         else if(RSA_CLASS == GetAlgClass(certAlg))
00619         {
00620             tmpSignerInfo->signature.data = new unsigned char[nSigLen];
00621             memcpy((void*)tmpSignerInfo->signature.data, sig, nSigLen);
00622             tmpSignerInfo->signature.numocts = nSigLen;
00623 
00624             if(PKIFCRYPTO::MD5 == hashAlg)
00625             {
00626                 CPKIFStringPtr tmpOidSt(new std::string(g_md5WithRSAEncryption->ToString())); 
00627                 anotherStr2 = tmpOidSt;
00628             }
00629             else if(PKIFCRYPTO::SHA1 == hashAlg)
00630             {
00631                 CPKIFStringPtr tmpOidSt(new std::string(g_sha1WithRSAEncryption->ToString())); 
00632                 anotherStr2 = tmpOidSt;
00633             }
00634             else if(PKIFCRYPTO::SHA224 == hashAlg)
00635             {
00636                 CPKIFStringPtr tmpOidSt(new std::string(g_sha224WithRSAEncryption->ToString())); 
00637                 anotherStr2 = tmpOidSt;
00638             }
00639             else if(PKIFCRYPTO::SHA256 == hashAlg)
00640             {
00641                 CPKIFStringPtr tmpOidSt(new std::string(g_sha256WithRSAEncryption->ToString())); 
00642                 anotherStr2 = tmpOidSt;
00643             }
00644             else if(PKIFCRYPTO::SHA384 == hashAlg)
00645             {
00646                 CPKIFStringPtr tmpOidSt(new std::string(g_sha384WithRSAEncryption->ToString())); 
00647                 anotherStr2 = tmpOidSt;
00648             }
00649             else if(PKIFCRYPTO::SHA512 == hashAlg)
00650             {
00651                 CPKIFStringPtr tmpOidSt(new std::string(g_sha512WithRSAEncryption->ToString())); 
00652                 anotherStr2 = tmpOidSt;
00653             }
00654         }
00655         else if(ECDSA_CLASS == GetAlgClass(certAlg))
00656         {
00657             EncodeDSASignature(sig, nSigLen, (unsigned char**)&tmpSignerInfo->signature.data, (int*)&tmpSignerInfo->signature.numocts);
00658             if(PKIFCRYPTO::SHA1 == hashAlg)
00659             {
00660                 CPKIFStringPtr tmpOidSt(new std::string(g_ecdsa_sha1->ToString())); 
00661                 anotherStr2 = tmpOidSt;
00662             }
00663             else if(PKIFCRYPTO::SHA224 == hashAlg)
00664             {
00665                 CPKIFStringPtr tmpOidSt(new std::string(g_ecdsa_sha224->ToString())); 
00666                 anotherStr2 = tmpOidSt;
00667             }
00668             else if(PKIFCRYPTO::SHA256 == hashAlg)
00669             {
00670                 CPKIFStringPtr tmpOidSt(new std::string(g_ecdsa_sha256->ToString())); 
00671                 anotherStr2 = tmpOidSt;
00672             }
00673             else if(PKIFCRYPTO::SHA384 == hashAlg)
00674             {
00675                 CPKIFStringPtr tmpOidSt(new std::string(g_ecdsa_sha384->ToString())); 
00676                 anotherStr2 = tmpOidSt;
00677             }
00678             else if(PKIFCRYPTO::SHA512 == hashAlg)
00679             {
00680                 CPKIFStringPtr tmpOidSt(new std::string(g_ecdsa_sha512->ToString())); 
00681                 anotherStr2 = tmpOidSt;
00682             }
00683         }
00684         else
00685         {
00686             tmpSignerInfo->signature.data = new unsigned char[nSigLen];
00687             memcpy((void*)tmpSignerInfo->signature.data, sig, nSigLen);
00688             tmpSignerInfo->signature.numocts = nSigLen;
00689         }
00690 
00691         if(!anotherStr2)
00692         {
00693             CPKIFStringPtr tmpOidSt(new std::string(certAlg->oid()->ToString())); 
00694             anotherStr2 = tmpOidSt;
00695         }
00696         ASN1OBJID* anotherTmpOid = ConvertStringToASN1OBJID(anotherStr2);
00697         CopyOID(&tmpSignerInfo->signatureAlgorithm.algorithm, anotherTmpOid);
00698         if(anotherTmpOid)
00699             delete anotherTmpOid;
00700         //CopyOID(&tmpSignerInfo->signatureAlgorithm.algorithm, certAlg->oid()->raw());
00701 
00702         if(certAlg->hasParameters())
00703         {
00704             tmpSignerInfo->signatureAlgorithm.m.parametersPresent = 1;
00705 
00706             CPKIFBufferPtr params = certAlg->parameters();
00707             tmpSignerInfo->signatureAlgorithm.parameters.numocts = params->GetLength();
00708             tmpSignerInfo->signatureAlgorithm.parameters.data = new unsigned char[tmpSignerInfo->signatureAlgorithm.parameters.numocts];
00709             memcpy((void*)tmpSignerInfo->signatureAlgorithm.parameters.data, params->GetBuffer(), tmpSignerInfo->signatureAlgorithm.parameters.numocts);
00710         }
00711         else
00712             tmpSignerInfo->signatureAlgorithm.m.parametersPresent = 0;
00713 
00714         tmpSignerInfo->m.unsignedAttrsPresent = 0;
00715         {//begin unsigned attribute block
00716             CPKIFAttributeList sas;
00717             siPos->GetUnsignedAttributes(sas);
00718 
00719             SetupAttributesInObjectiveStructure(sas, tmpSignerInfo->unsignedAttrs);
00720             
00721             if(!sas.empty())
00722                 tmpSignerInfo->m.unsignedAttrsPresent = 1;
00723         }//end unsigned attribute block
00724     }
00725     else
00726     {
00727         //if the signer info was recovered from an existing message and has a signature then the only change
00728         //permitted will be to add unsigned attributes
00729         switch(siPos->GetSignerIdentifierChoice())
00730         {
00731         case CPKIFSignerInfo::SKID:
00732             {
00733                 CPKIFBufferPtr skidBuf = siPos->GetSKID();
00734                 tmpSignerInfo->version = CACCMSv3; 
00735 
00736                 //use skid if present
00737                 tmpSignerInfo->sid.t = 2;
00738                 tmpSignerInfo->sid.u.subjectKeyIdentifier = new CACCMSSubjectKeyIdentifier;
00739                 tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts = skidBuf->GetLength();
00740                 tmpSignerInfo->sid.u.subjectKeyIdentifier->data = new unsigned char[tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts];
00741                 memcpy((void*)tmpSignerInfo->sid.u.subjectKeyIdentifier->data, skidBuf->GetBuffer(), tmpSignerInfo->sid.u.subjectKeyIdentifier->numocts);
00742             }
00743             break;
00744         case CPKIFSignerInfo::ISSUERANDSERIAL:
00745             {
00746                 tmpSignerInfo->version = CACCMSv1; 
00747 
00748                 CPKIFIssuerAndSerialNumberPtr issAndSN = siPos->GetIssuerAndSerialNumber();
00749                 CPKIFNamePtr name = issAndSN->GetName();
00750                 const char* sn = issAndSN->GetSerialNumber();
00751 
00752                 //otherwise use issuer DN and serial number
00753                 tmpSignerInfo->sid.t = 1;
00754                 tmpSignerInfo->sid.u.issuerAndSerialNumber = new CACCMSIssuerAndSerialNumber;
00755                 tmpSignerInfo->sid.u.issuerAndSerialNumber->serialNumber = sn;
00756                 
00757                 CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
00758                 CACX509V3Name *tmpName = NULL;
00759                 CPKIFBufferPtr nameBuf = name->rawName();
00760                 tmpName = objPDU.Decode(nameBuf->GetBuffer(), nameBuf->GetLength());
00761                 //tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer = *tmpName;
00762                 CopyName(&tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer, *tmpName); 
00763                 //tmpSignerInfo->sid.u.issuerAndSerialNumber->issuer = *name->rawName();
00764             }
00765             break;
00766         default:
00767             throw CPKIFMessageException(TOOLKIT_MESSAGE_ASN, COMMON_UNSUPPORTED_CHOICE, "Unsupported signer info choice");
00768         }
00769 
00770         //de-hardcoded usage of SHA1 - 12/09/2003
00771         CPKIFStringPtr str2(new std::string(siPos->GetDigestAlg()->oid()->ToString())); 
00772         ASN1OBJID* tmpOid = ConvertStringToASN1OBJID(str2);
00773         CopyOID(&tmpSignerInfo->digestAlgorithm.algorithm, tmpOid);
00774         if(tmpOid)
00775             delete tmpOid;
00776         //CopyOID(&tmpSignerInfo->digestAlgorithm.algorithm, siPos->GetDigestAlg()->oid()->raw());
00777         tmpSignerInfo->digestAlgorithm.m.parametersPresent = 1;
00778         tmpSignerInfo->digestAlgorithm.parameters.data = nullParams;
00779         tmpSignerInfo->digestAlgorithm.parameters.numocts = 2;
00780 
00781         tmpSignerInfo->m.signedAttrsPresent = 0;
00782 
00783         {//begin signed attribute block
00784             CPKIFAttributeList sas;
00785             siPos->GetSignedAttributes(sas);
00786 
00787             AddSignedAttributes(hashResult, nHashResult, eContentType, sas);
00788             SetupAttributesInObjectiveStructure(sas, tmpSignerInfo->signedAttrs);
00789             
00790             if(!sas.empty())
00791                 tmpSignerInfo->m.signedAttrsPresent = 1;
00792         }//end signed attribute block
00793 
00794         CPKIFAlgorithmIdentifierPtr sigAlg = siPos->GetSignatureAlgorithm();
00795         CPKIFBufferPtr sig = siPos->GetSignature();
00796 
00797         tmpSignerInfo->signature.numocts = sig->GetLength();
00798         tmpSignerInfo->signature.data = new unsigned char[tmpSignerInfo->signature.numocts];
00799         memcpy((void*)tmpSignerInfo->signature.data, sig->GetBuffer(), tmpSignerInfo->signature.numocts);
00800 
00801 
00802         CPKIFStringPtr thurdStr(new std::string(sigAlg->oid()->ToString())); 
00803         ASN1OBJID* thirdTmpOid = ConvertStringToASN1OBJID(thurdStr);
00804         CopyOID(&tmpSignerInfo->signatureAlgorithm.algorithm, thirdTmpOid);
00805         if(thirdTmpOid)
00806             delete thirdTmpOid;
00807         //CopyOID(&tmpSignerInfo->signatureAlgorithm.algorithm, sigAlg->oid()->raw());
00808 
00809         if(sigAlg->hasParameters())
00810         {
00811             CPKIFBufferPtr algParams = sigAlg->parameters();
00812             tmpSignerInfo->signatureAlgorithm.m.parametersPresent = 1;
00813             tmpSignerInfo->signatureAlgorithm.parameters.numocts = algParams->GetLength();
00814 
00815             tmpSignerInfo->signatureAlgorithm.parameters.data = new unsigned char[tmpSignerInfo->signatureAlgorithm.parameters.numocts];
00816             memcpy((void*)tmpSignerInfo->signatureAlgorithm.parameters.data, algParams->GetBuffer(), tmpSignerInfo->signatureAlgorithm.parameters.numocts);
00817         }
00818         else
00819         {
00820             tmpSignerInfo->signatureAlgorithm.m.parametersPresent = 0;
00821         }
00822 
00823         tmpSignerInfo->m.unsignedAttrsPresent = 0;
00824         {//begin unsigned attribute block
00825             CPKIFAttributeList sas;
00826             siPos->GetUnsignedAttributes(sas);
00827 
00828             SetupAttributesInObjectiveStructure(sas, tmpSignerInfo->unsignedAttrs);
00829             
00830             if(!sas.empty())
00831                 tmpSignerInfo->m.unsignedAttrsPresent = 1;
00832         }//end unsigned attribute block
00833     }
00834 }
00842 HashInfo* ComputeSignedAttrHash(
00844     CACCMSSignerInfo* si, 
00846     IPKIFCryptoMisc* cMisc)
00847 {
00848     if(si->m.signedAttrsPresent)
00849     {
00850         CPKIFAlgorithm * hashAlg = GetCACHashAlg(&si->digestAlgorithm);
00851         if(!hashAlg)
00852             return NULL; //unknown hash alg
00853 
00854         OOCTXT ctxt;
00855         initContext (&ctxt);
00856         setBEREncBufPtr(&ctxt, NULL, 0);
00857         OOCTXT* pctxt = &ctxt;
00858 
00859         unsigned char* tmpP = NULL;
00860         int len = BEREncCACCMSSignedAttributes(pctxt, &si->signedAttrs, ASN1EXPL);
00861         if(0 < len)
00862         {
00863             tmpP = (unsigned char*)getBEREncBufPtr(&ctxt);
00864         }
00865 
00866         IPKIFHashContext* hc = NULL;
00867         HashInfo* hi = new HashInfo(); //context field does not matter in this case
00868         try
00869         {
00870             hi->m_hashAlg = hashAlg->HashAlg();
00871             hc = cMisc->HashInit(hi->m_hashAlg);
00872             cMisc->HashUpdate(hc, tmpP, len);
00873             int nResultLen = MAXHASH;
00874             cMisc->HashFinal(hc, hi->m_hashResult, &nResultLen);
00875             delete hc;
00876         }
00877         catch(CPKIFException& e)
00878         {
00879             if(NULL != hc)
00880                 delete hc;
00881 
00882             if(NULL != hi)
00883                 delete hi;
00884             //freeEncodeBuffer(&ctxt);
00885             //memFreeAll(&ctxt);
00886             freeContext(&ctxt);
00887             throw e;
00888         }
00889 
00890         //freeEncodeBuffer(&ctxt);
00891         //memFreeAll(&ctxt);
00892         freeContext(&ctxt);
00893 
00894         return hi;
00895     }
00896     else
00897         return NULL;
00898 }
00909 bool CompareHashes(
00911     HashInfo* hi2,
00913     CACCMSSignerInfo* si)
00914 {
00915     if(NULL == hi2 || NULL == si || !si->m.signedAttrsPresent)
00916         return false;
00917 
00918     DListNode* cur = si->signedAttrs.head;
00919     while(NULL != cur)
00920     {
00921         CACCMSAttribute* curAttr = (CACCMSAttribute*)cur->data;
00922         CPKIFOIDPtr curAttrType(new CPKIFOID(curAttr->attrType.subid, curAttr->attrType.numids));
00923         if(*g_messageDigestAttribute == *curAttrType)
00924         {
00925             CACASNWRAPPER_CREATE(CACCMSAttributeValues, attrValues);
00926             attrValues.Decode(curAttr->attrValues);
00927 
00928             if(0 != attrValues->count)
00929             {
00930                 CACCMSAttributeValue* curVal = (CACCMSAttributeValue*)attrValues->head->data;
00931 
00932                 OOCTXT ctxt;
00933                 initContext (&ctxt);
00934                 setBERDecBufPtr(&ctxt, curVal->data, curVal->numocts, NULL, NULL);
00935                 OOCTXT* pctxt = &ctxt;
00936 
00937                 unsigned char* hashVal = NULL;
00938                 unsigned int hashValLen = 0;
00939 
00940                 int stat = decodeDynOctStr (pctxt, (const OSOCTET* *)&hashVal, (OSUINT32 *)&hashValLen, ASN1EXPL, curVal->numocts);
00941                 if (stat != ASN_OK)
00942                 {
00943                     //freeEncodeBuffer(&ctxt);
00944                     //memFreeAll(&ctxt);
00945                     freeContext(&ctxt);
00946                     throw CPKIFMessageException(TOOLKIT_MESSAGE_ASN, ASN1_DECODE_ERROR, "Failed to decode hash value");
00947                 }
00948 
00949                 bool match = true;
00950                 if(hi2->m_hashAlg != hashValLen)
00951                     match = false;
00952 
00953                 if(0 != memcmp(hi2->m_hashResult, hashVal, hashValLen))
00954                     match = false;
00955 
00956                 //clean up the context
00957                 //if(hashVal)
00958                 //{
00959                 //  memFreePtr (&ctxt, hashVal);
00960                 //}
00961                 //freeEncodeBuffer(&ctxt);
00962                 //memFreeAll(&ctxt);
00963                 freeContext(&ctxt);
00964 
00965                 return match;
00966             }
00967         }
00968 
00969         cur = cur->next;
00970     }
00971 
00972     return false;
00973 }
00974 
00975 //*****************************************************************************
00976 //  utility functions
00977 //*****************************************************************************
00978 //compare RID info with info from a cert that is also passed as parameters
00986 bool RIDMatch(
00988     CACCMSRecipientIdentifier* rid, 
00990     CPKIFNamePtr& issuer, 
00992     const char* serial, 
00994     CPKIFSubjectKeyIdentifierPtr& skid)
00995 {
00996     //if there's nothing to compare return false
00997     if(NULL == rid)
00998         return false;
00999 
01000     switch(rid->t)
01001     {
01002     case 1: //issuer and serial
01003         {
01004         if(NULL == serial 
01005             || issuer == (CPKIFName*)NULL 
01006             || NULL == rid->u.issuerAndSerialNumber
01007             || NULL == rid->u.issuerAndSerialNumber->serialNumber)
01008             return false;
01009 
01010         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
01011         ASN1OpenType* data1 = objPDU.Encode(&(rid->u.issuerAndSerialNumber->issuer));
01012         CPKIFBufferPtr tmpBuf;
01013         if(data1 != NULL)
01014         {
01015              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
01016             delete data1;
01017         }
01018         CPKIFNamePtr ridName(new CPKIFName(tmpBuf));
01019         //CPKIFNamePtr ridName(new CPKIFName(rid->u.issuerAndSerialNumber->issuer));
01020         if(0 == stricmp(rid->u.issuerAndSerialNumber->serialNumber, serial) &&
01021             *ridName == *issuer)
01022             return true;
01023         else
01024             return false;
01025         }
01026         break;
01027     case 2: //skid
01028         {
01029         if(skid == (CPKIFSubjectKeyIdentifier*)NULL 
01030             || NULL == rid->u.subjectKeyIdentifier
01031             || NULL == rid->u.subjectKeyIdentifier->data 
01032             || 0 == rid->u.subjectKeyIdentifier->numocts)
01033             return false;
01034 
01035         CPKIFBufferPtr skidBuf = skid->KeyIdentifier();
01036 
01037         if(skidBuf == (CPKIFBuffer*)NULL ||
01038             rid->u.subjectKeyIdentifier->numocts != skidBuf->GetLength())
01039             return false;
01040 
01041         if(0 == memcmp(skidBuf->GetBuffer(), rid->u.subjectKeyIdentifier->data, rid->u.subjectKeyIdentifier->numocts))
01042             return true;
01043         else
01044             return false;
01045         }
01046         break;
01047     default:
01048         return false;
01049     }
01050 }
01058 bool RIDMatch(
01060     CACCMSKeyAgreeRecipientIdentifier* rid, 
01062     CPKIFNamePtr& issuer, 
01064     const char* serial, 
01066     CPKIFSubjectKeyIdentifierPtr& skid)
01067 {
01068     //if there's nothing to compare return false
01069     if(NULL == rid)
01070         return false;
01071 
01072     switch(rid->t)
01073     {
01074     case 1: //issuer and serial
01075         {
01076         if(NULL == serial 
01077             || issuer == (CPKIFName*)NULL 
01078             || NULL == rid->u.issuerAndSerialNumber
01079             || NULL == rid->u.issuerAndSerialNumber->serialNumber)
01080             return false;
01081 
01082         CACASNWRAPPER_CREATE(CACX509V3Name, objPDU);
01083         ASN1OpenType* data1 = objPDU.Encode(&(rid->u.issuerAndSerialNumber->issuer));
01084         CPKIFBufferPtr tmpBuf;
01085         if(data1 != NULL)
01086         {
01087              tmpBuf = CPKIFBufferPtr(new CPKIFBuffer(data1->data, data1->numocts));
01088             delete data1;
01089         }
01090         CPKIFNamePtr ridName(new CPKIFName(tmpBuf));
01091         //CPKIFNamePtr ridName(new CPKIFName(rid->u.issuerAndSerialNumber->issuer));
01092         if(0 == stricmp(rid->u.issuerAndSerialNumber->serialNumber, serial) &&
01093             *ridName == *issuer)
01094             return true;
01095         else
01096             return false;
01097         }
01098         break;
01099     case 2: //skid (not supporting date and whatnot)
01100         {
01101         if(skid == (CPKIFSubjectKeyIdentifier*)NULL 
01102             || NULL == rid->u.rKeyId->subjectKeyIdentifier.data 
01103             || 0 == rid->u.rKeyId->subjectKeyIdentifier.numocts)
01104             return false;
01105 
01106         CPKIFBufferPtr skidBuf = skid->KeyIdentifier();
01107 
01108         if(skidBuf == (CPKIFBuffer*)NULL ||
01109             rid->u.rKeyId->subjectKeyIdentifier.numocts != skidBuf->GetLength())
01110             return false;
01111 
01112         if(0 == memcmp(skidBuf->GetBuffer(), rid->u.rKeyId->subjectKeyIdentifier.data, rid->u.rKeyId->subjectKeyIdentifier.numocts))
01113             return true;
01114         else
01115             return false;
01116         }
01117         break;
01118     default:
01119         return false;
01120     }
01121 }
01122 
01123 //given a credential, a crypto interface pointer and a recipient bag find the recipient info that matches the 
01124 //credential and return decrypted key material.
01135 CPKIFKeyMaterialPtr GetSymmetricKey(
01137     const CPKIFKEKRecipInfoDetailsPtr& kek,
01139     IPKIFCryptoRawOperations* cKeyID,
01141     CACCMSRecipientInfos* ris)
01142 {
01143     //declare an (initially empty) key material pointer.  this function returns the empty km upon failure
01144     //or a populated km upon success
01145     CPKIFKeyMaterialPtr km;
01146 
01147     //sanity check the inputs - if anything is not kosher return the empty km
01148     if(NULL == ris || 0 == ris->count || kek == (CPKIFKEKRecipInfoDetails*)NULL)
01149         return km;
01150 
01151     //gather some info about the credential that will be used to decrypt the key
01152     CPKIFBufferPtr kid = kek->GetKeyIdentifier();
01153     if(kid == (CPKIFBuffer*)NULL)
01154         return km;
01155 
01156     //iterate over all of the recipient infos looking for a kekri with a key identifier that matches the kek passed in
01157     DListNode* cur = ris->head;
01158     while(NULL != cur)
01159     {
01160         CACCMSRecipientInfo* ri = (CACCMSRecipientInfo*)cur->data;
01161 
01162         switch(ri->t)
01163         {
01164             case 3: //kekri
01165             {
01166                 //get pointer to kekri stucture
01167                 CACCMSKEKRecipientInfo* kekri = ri->u.kekri;
01168 
01169                 //temporarily put the key id from the current kekri into a CPKIFBufferPtr for comparison purposes
01170                 CPKIFBuffer tmpKID(false, (unsigned char*)kekri->kekid.keyIdentifier.data, kekri->kekid.keyIdentifier.numocts);
01171                 if(*kid == tmpKID)
01172                 {
01173                     //if they match - allocate an outbound buffer and a key material object
01174                     //throw bad_alloc
01175                     CPKIFKeyMaterialPtr kmFound(new CPKIFKeyMaterial);
01176                     unsigned char* pResult = new unsigned char[kekri->encryptedKey.numocts];
01177                     int nResultLen = kekri->encryptedKey.numocts;
01178 
01179                     CPKIFKeyMaterialPtr theKEK = kek->GetKEK();
01180 
01181                     if(kekri->keyEncryptionAlgorithm.m.parametersPresent)
01182                     {
01183                         OOCTXT ctxt;
01184                         initContext (&ctxt);
01185                         setBERDecBufPtr(&ctxt, kekri->keyEncryptionAlgorithm.parameters.data, kekri->keyEncryptionAlgorithm.parameters.numocts, NULL, NULL);
01186                         OOCTXT* pctxt = &ctxt;
01187 
01188                         unsigned char* hashVal = NULL;
01189                         unsigned int hashValLen = 0;
01190 
01191                         int stat = decodeDynOctStr (pctxt, (const OSOCTET* *)&hashVal, (OSUINT32 *)&hashValLen, ASN1EXPL, kekri->keyEncryptionAlgorithm.parameters.numocts);
01192                         if (stat != ASN_OK)
01193                         {
01194                             //freeEncodeBuffer(&ctxt);
01195                             //memFreeAll(&ctxt);
01196                             freeContext(&ctxt);
01197                             throw CPKIFMessageException(TOOLKIT_MESSAGE_ASN, ASN1_DECODE_ERROR, "Failed to decode hash value");
01198                         }
01199 
01200                         theKEK->SetIV(hashVal, hashValLen);
01201 
01202                         //clean up the context
01203                         //freeEncodeBuffer(&ctxt);
01204                         //memFreeAll(&ctxt);
01205                         freeContext(&ctxt);
01206                     }
01207 
01208                     try
01209                     {
01210                         cKeyID->Decrypt(*theKEK, (unsigned char*)kekri->encryptedKey.data, kekri->encryptedKey.numocts, pResult, &nResultLen);
01211                     }
01212                     catch(...)
01213                     {
01214                         //if any exception is throw delete the result buffer and return
01215                         if(pResult)
01216                             delete[] pResult;
01217 
01218                         throw;
01219                     }
01220                     
01221                     //associate the decrypted key with the key material pointer
01222                     kmFound->SetSymmetricKey(pResult, nResultLen);
01223 
01224                     //clean up the temp buffer containing the decrypted key
01225                     memset(pResult, 0, nResultLen); delete[] pResult;
01226                     return kmFound;
01227                 }
01228                 break;
01229             }
01230             case 1: //ktri
01231             case 2: //kari
01232             default:
01233                 //don't choke - don't use
01234                 break;
01235         }
01236 
01237         cur = cur->next;
01238     }
01239 
01240     //if nothing was found return the empty km
01241     return km;
01242 }
01250 CPKIFCertificatePtr GetOriginatorCertFromOriginatorInfo(
01252     CACCMSKeyAgreeRecipientInfo* kari, 
01254     CACCMSOriginatorInfo* oi)
01255 {
01256     CPKIFCertificatePtr emptyCert;
01257     if(!kari || !oi || !oi->m.certsPresent)
01258         return emptyCert;
01259 
01260     DListNode* iter = oi->certs.head;
01261     while(NULL != iter)
01262     {
01263         CACCMSCertificateChoices* curChoice = (CACCMSCertificateChoices*)iter->data;
01264         if(T_CACCMSCertificateChoices_certificate != curChoice->t)
01265         {
01266             iter = iter->next;
01267             continue;
01268         }
01269 
01270         ASN1OpenType* cert = (ASN1OpenType*)curChoice->u.certificate;
01271 
01272         try
01273         {
01274             CPKIFCertificatePtr newCert(new CPKIFCertificate());
01275             newCert->Decode(cert->data, cert->numocts);
01276 
01277             if(T_CACCMSOriginatorIdentifierOrKey_subjectKeyIdentifier == kari->originator.t)
01278             {
01279                 CPKIFSubjectKeyIdentifierPtr skid = newCert->GetExtension<CPKIFSubjectKeyIdentifier>();
01280                 if(skid != (CPKIFSubjectKeyIdentifier*)NULL)
01281                 {
01282                     CPKIFBufferPtr skidBuf = skid->KeyIdentifier();
01283                     if(skidBuf->GetLength() == (kari->originator.u.subjectKeyIdentifier->numocts) &&
01284                         0 == memcmp(skidBuf->GetBuffer(), kari->originator.u.subjectKeyIdentifier->data, skidBuf->GetLength()))
01285                     return newCert;
01286                 }
01287             }
01288             else if(T_CACCMSOriginatorIdentifierOrKey_originatorKey == kari->originator.t)
01289             {
01290                 CPKIFBufferPtr rawKey = newCert->SubjectPublicKeyInfo()->rawKey();
01291                 if(rawKey->GetLength() == (kari->originator.u.originatorKey->publicKey.numbits/8) &&
01292                     0 == memcmp(rawKey->GetBuffer(), kari->originator.u.originatorKey->publicKey.data, rawKey->GetLength()))
01293                     return newCert;
01294             }
01295             else if(T_CACCMSOriginatorIdentifierOrKey_issuerAndSerialNumber == kari->originator.t)
01296             {
01297                 //XXX***IMPLEMENT ME
01298             }
01299         }
01300         catch(CPKIFException&)
01301         {
01302             //don't bother the caller with malformed certs
01303         }
01304         catch(std::bad_alloc& ba)
01305         {
01306             //empty the list
01307             throw ba;
01308         }
01309 
01310         iter = iter->next;
01311     }
01312     return emptyCert;
01313 }
01314 
01327 CPKIFBufferPtr GetOriginatorPublicKey(
01329     CACCMSKeyAgreeRecipientInfo* kari, 
01331     CACCMSOriginatorInfo* oi, 
01333     CPKIFCertificatePtr& origCert)
01334 {
01335     //make sure no garbage is passed in as origCert
01336     CPKIFCertificatePtr emptyCert;
01337     origCert = emptyCert;
01338 
01339     CPKIFBufferPtr origPubKey;
01340     if(T_CACCMSOriginatorIdentifierOrKey_originatorKey == kari->originator.t)
01341     {
01342         //prepare key for return
01343         CPKIFBufferPtr tmprv(new CPKIFBuffer(kari->originator.u.originatorKey->publicKey.data, kari->originator.u.originatorKey->publicKey.numbits/8));
01344         origPubKey = tmprv;
01345     }
01346 
01347     if(oi)
01348     {
01349         //find the cert in the cert bag
01350         origCert = GetOriginatorCertFromOriginatorInfo(kari, oi);
01351     }
01352 
01353     if(origCert == (CPKIFCertificate*)NULL)
01354     {
01355         //if it wasn't in the bag, see if we have it locally somewhere
01356     }
01357 
01358     if(origCert != (CPKIFCertificate*)NULL && origPubKey == (CPKIFBuffer*)NULL)
01359     {
01360         origPubKey = origCert->GetSubjectPublicKeyInfo()->rawKey();
01361     }
01362 
01363     return origPubKey;
01364 }
01365 
01374 CPKIFKeyMaterialPtr GetSymmetricKey(
01376     CPKIFCredentialPtr& cred,
01378     IPKIFCryptoKeyIDOperations* cKeyID,
01380     CACCMSRecipientInfos* ris,
01381     IPKIFCryptoKeyAgree* ka,
01382     IPKIFCryptoRawOperations* cRaw,
01383     CACCMSOriginatorInfo* oi)
01384 {
01385     CPKIFKeyMaterialPtr km;
01386     if(NULL == ris || 0 == ris->count)
01387         return km;
01388 
01389     //gather some info about the credential that will be used to decrypt the key
01390     CPKIFCertificatePtr cert = cred->GetCertificate();
01391     if(cert == (CPKIFCertificate*)NULL)
01392         return km;
01393 
01394     CPKIFNamePtr issuer = cert->Issuer();
01395     const char* serial = cert->SerialNumber();
01396     CPKIFSubjectKeyIdentifierPtr skid = cert->GetExtension<CPKIFSubjectKeyIdentifier>();
01397 
01398     DListNode* cur = ris->head;
01399     while(NULL != cur)
01400     {
01401         CACCMSRecipientInfo* ri = (CACCMSRecipientInfo*)cur->data;
01402 
01403         switch(ri->t)
01404         {
01405             case 1: //ktri
01406                 {
01407                 CACCMSKeyTransRecipientInfo* ktri = ri->u.ktri;
01408                 if(RIDMatch(&ktri->rid, issuer, serial, skid))
01409                 {
01410                     unsigned char* pResult = new unsigned char[ktri->encryptedKey.numocts];
01411                     int nResultLen = ktri->encryptedKey.numocts;
01412 
01413                     //added try/catch 04/30/03
01414                     try
01415                     {
01416                         cKeyID->Decrypt(*cred, (unsigned char*)ktri->encryptedKey.data, ktri->encryptedKey.numocts, pResult, &nResultLen);
01417                     }
01418                     catch(CPKIFException& e)
01419                     {
01420                         if(pResult)
01421                             delete[] pResult;
01422 
01423                         throw e;
01424                     }
01425                     catch(std::exception& se)
01426                     {
01427                         if(pResult)
01428                             delete[] pResult;
01429 
01430                         throw se;
01431                     }
01432                     
01433                     CPKIFKeyMaterialPtr kmFound(new CPKIFKeyMaterial);
01434                     kmFound->SetSymmetricKey(pResult, nResultLen);
01435                     delete[] pResult;
01436                     return kmFound;
01437                 }
01438                 }
01439                 break;
01440             case 2: //kari
01441                 {
01442                 if(!ka) break;
01443                 //get a pointer to the key agreement recipient info structure
01444                 CACCMSKeyAgreeRecipientInfo* kari = ri->u.kari;
01445 
01446                 //determine the key encryption algorithm
01447                 CPKIFOIDPtr kekAlgOID(new CPKIFOID(kari->keyEncryptionAlgorithm.algorithm.subid, kari->keyEncryptionAlgorithm.algorithm.numids));
01448                 CPKIFAlgorithm* kekAlg = CPKIFAlgorithm::GetAlg(kekAlgOID);
01449 
01450                 //get the originator public key and certificate, if available.
01451                 CPKIFCertificatePtr origCert;
01452                 CPKIFBufferPtr origPublicKey = GetOriginatorPublicKey(kari, oi, origCert);
01453                 if(origCert != (CPKIFCertificate*)NULL)
01454                 {
01455                     //*** XXX validate the certificate if it was recovered... this won't happen with the current
01456                     //implementation of GetOriginatorPublicKey()
01457                 }
01458                 CPKIFAlgorithm * kwAlg = 0;
01459                 
01460                 // a context that will hold the shared secret and can produce a derived
01461                 // key
01462                 IPKIFKeyAgreeContextPtr ctx;
01463 
01464                 if(*kekAlgOID == *g_ecdh_std_sha1kdf) {
01465                     if(!ri->u.kari->keyEncryptionAlgorithm.m.parametersPresent) {
01466                         // XXX *** break or throw? for now, just break. something above
01467                         // will throw
01468                         break;
01469                     }
01470                     CACASNWRAPPER_CREATE(ECC_CMS_SharedInfo,ecsPDU);
01471                     ECC_CMS_SharedInfo * si = ecsPDU.Decode( ri->u.kari->keyEncryptionAlgorithm.parameters );
01472                     if(!si) {
01473                         break;
01474                     }
01475                     CPKIFOIDPtr kwAlgOID(new CPKIFOID(si->keyInfo.algorithm.subid,si->keyInfo.algorithm.numids));
01476                     kwAlg = CPKIFAlgorithm::GetAlg(kwAlgOID);
01477                     if(!kwAlg) {
01478                         // XXX *** might better throw here
01479                         break;
01480                     }
01481                     ctx = ka->SecretAgree(cred,origPublicKey, kekAlg);
01482 
01483                 } else if(*kekAlgOID == *g_ecmqv_sha1kdf) {
01484                     if(!ri->u.kari->keyEncryptionAlgorithm.m.parametersPresent) {
01485                         // XXX *** break or throw? for now, just break. something above
01486                         // will throw
01487                         break;
01488                     }
01489                     if(!ri->u.kari->m.ukmPresent) {
01490                         // XXX *** break or throw? for now, just break. something above
01491                         // will throw
01492                         break;
01493                     }
01494                     CACASNWRAPPER_CREATE(ECC_CMS_SharedInfo,ecsPDU);
01495                     ECC_CMS_SharedInfo * si = ecsPDU.Decode( ri->u.kari->keyEncryptionAlgorithm.parameters );
01496                     if(!si) {
01497                         break;
01498                     }
01499                     CPKIFOIDPtr kwAlgOID(new CPKIFOID(si->keyInfo.algorithm.subid,si->keyInfo.algorithm.numids));
01500                     kwAlg = CPKIFAlgorithm::GetAlg(kwAlgOID);
01501                     if(!kwAlg) {
01502                         // XXX *** might better throw here
01503                         break;
01504                     }
01505                     CACASNWRAPPER_CREATE(MQVuserKeyingMaterial,ukmPDU);
01506                     MQVuserKeyingMaterial * ukm = ukmPDU.Decode(ri->u.kari->ukm.data, ri->u.kari->ukm.numocts);
01507                     CPKIFBufferPtr ephemPK(new CPKIFBuffer(ukm->ephemeralPublicKey.publicKey.data,ukm->ephemeralPublicKey.publicKey.numbits/8));
01508                     ctx = ka->SecretAgree(cred, ephemPK, origPublicKey, kekAlg);
01509                     
01510                 } else {
01511                     break; // allow other attempts even if this function doesn't recognize the KA scheme
01512                 }
01513 
01514                 CPKIFKeyMaterialPtr kek;
01515                 CPKIFBufferPtr sharedInfo(new CPKIFBuffer(ri->u.kari->keyEncryptionAlgorithm.parameters.data,ri->u.kari->keyEncryptionAlgorithm.parameters.numocts));
01516                 ctx->AppendSharedInfo(sharedInfo);
01517                 kek = ka->DeriveKey(ctx,kwAlg->KeySize());
01518                 if(!kek) break;
01519                 kek->SetSymmetricKeyAlgorithm(kwAlg->SymkeyAlg());
01520                 kek->SetMode(kwAlg->SymkeyMode());  
01521                 
01522                 //loop over the recipient keys until the one that matches the current credential is found
01523                 DListNode* node = kari->recipientEncryptedKeys.head;
01524                 CACCMSRecipientEncryptedKey* rid = NULL;
01525                 for(OSUINT32 ii = 0; ii < kari->recipientEncryptedKeys.count; ++ii)
01526                 {
01527                     rid = (CACCMSRecipientEncryptedKey*)node->data;
01528                     if(RIDMatch(&rid->rid, issuer, serial, skid))
01529                     {
01530                         //having found the RID, allocate some space for the decrypted key then call decrypt
01531                         unsigned char* pResult = new unsigned char[rid->encryptedKey.numocts];
01532                         int nResultLen = rid->encryptedKey.numocts;
01533 
01534                         try
01535                         {
01536                             cRaw->Decrypt(*kek, (unsigned char*)rid->encryptedKey.data, rid->encryptedKey.numocts, pResult, &nResultLen);
01537                         }
01538                         catch(CPKIFException& e)
01539                         {
01540                             if(pResult)
01541                                 delete[] pResult;
01542 
01543                             throw e;
01544                         }
01545                         catch(std::exception& se)
01546                         {
01547                             if(pResult)
01548                                 delete[] pResult;
01549 
01550                             throw se;
01551                         }
01552 
01553                         //pass the decrypted key back to the caller
01554                         CPKIFKeyMaterialPtr kmFound(new CPKIFKeyMaterial);
01555                         kmFound->SetSymmetricKey(pResult, nResultLen);
01556                         delete[] pResult;
01557                         return kmFound;
01558                     }
01559                     node = node->next;
01560                 }
01561 
01562                 }
01563                 break;
01564             case 3: //kekri
01565                 //don't choke - don't use
01566                 break;
01567         }
01568 
01569         cur = cur->next;
01570     }
01571 
01572     return km;
01573 }
01581 CPKIFCredentialPtr AutoDiscoverDecryptionKey(
01583     IPKIFCryptoKeyIDOperations* cKeyID, 
01585     CACCMSRecipientInfos* ris)
01586 {
01587     //this function will attempt to locate a stored key that matches a recipient info in the current message.
01588 
01589     CPKIFCredentialPtr tmpCred;
01590     if(NULL == cKeyID || NULL == ris || 0 == ris->count)
01591         return tmpCred;
01592 
01593     //ask the crypto mediator for a list of all keys that may be used for key encipherment
01594     bitset<9> ku = PKIFCRYPTO::KeyEncipherment;
01595     CPKIFCredentialList vKeyID;
01596     try
01597     {
01598         cKeyID->GetKeyList(vKeyID, &ku);
01599     }
01600     catch(CPKIFException& e)
01601     {
01602         throw e;
01603     }
01604 
01605     CPKIFCredentialList::iterator pos, match;
01606     CPKIFCredentialList::iterator end = vKeyID.end();
01607     for(pos = vKeyID.begin(); pos != end; ++pos)
01608     {
01609         CPKIFCertificatePtr cert = (*pos)->GetCertificate();
01610         if(cert == (CPKIFCertificate*)NULL)
01611             continue;
01612 
01613         CPKIFNamePtr issuer = cert->Issuer();
01614         const char* serial = cert->SerialNumber();
01615         CPKIFSubjectKeyIdentifierPtr skid = cert->GetExtension<CPKIFSubjectKeyIdentifier>();
01616 
01617         //we only support ktri option currently, iterate over all ktris for each possible
01618         //key encipherment key returning the first key that matches a ktri
01619         DListNode* cur = ris->head;
01620         while(NULL != cur)
01621         {
01622             CACCMSRecipientInfo* ri = (CACCMSRecipientInfo*)cur->data;
01623 
01624             switch(ri->t)
01625             {
01626                 case 1: //ktri
01627                     {
01628                     CACCMSKeyTransRecipientInfo* ktri = ri->u.ktri;
01629                     if(RIDMatch(&ktri->rid, issuer, serial, skid))
01630                         return *pos;//return the current credential if we find a RID match
01631                     }
01632                     break;
01633                 case 2: //kari
01634                 case 3: //kekri
01635                     //don't choke - don't use
01636                     break;
01637             }
01638 
01639             cur = cur->next;
01640         }
01641     }
01642 
01643     return tmpCred;
01644 }
01654 void EncodeIVAsOctetString(
01656     unsigned char* iv,
01658     int ivLen, 
01660     unsigned char** encodedIV, 
01662     int* encodedIVLen)
01663 {
01664     OOCTXT ctxt;
01665     initContext (&ctxt);
01666     setBEREncBufPtr(&ctxt, NULL, 0);
01667     OOCTXT* pctxt = &ctxt;
01668 
01669     int stat = encodeOctStr (pctxt, (const OSOCTET*)iv, (OSUINT32)ivLen, ASN1EXPL);
01670     if (stat < 0)
01671     {
01672         throw CPKIFMessageException(TOOLKIT_MESSAGE_ASN, ASN1_ENCODE_ERROR, "Failed to encode IV value");
01673     }
01674 
01675     *encodedIVLen = stat;
01676     char* tmpP = (char*)getBEREncBufPtr(&ctxt);
01677 
01678     *encodedIV = new unsigned char[*encodedIVLen];
01679     memcpy(*encodedIV, tmpP, *encodedIVLen);
01680 
01681     //clean up the context
01682     freeEncodeBuffer(&ctxt);
01683     memFreeAll(&ctxt);
01684 }
01685 
01686 //This function takes a signer info and a credential and returns an encoded signer info suitable for pushing into
01687 //a countersignature extension.
01699 CPKIFBufferPtr PKIFCMS_API Countersign(
01701     CPKIFSignerInfoPtr& siToCounterSign,
01703     CPKIFSignerInfoPtr& countersignerSI,
01705     IPKIFMediatorPtr& mediator)
01706 {
01707     //*****************************************************************
01708     //  sanity check the inputs
01709     //*****************************************************************
01710     if(siToCounterSign == (CPKIFSignerInfo*)NULL || countersignerSI == (CPKIFSignerInfo*)NULL || NULL == mediator)
01711         throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_INVALID_INPUT, "One or more NULL parameters passed to VerifyCounterSignatures.");
01712 
01713     CPKIFBufferPtr sigBP = siToCounterSign->GetSignature();
01714     if(sigBP == (CPKIFBuffer*)NULL)
01715         throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_INVALID_INPUT, "The SignerInfo to countersign does not contain a signature.");
01716 
01717     IPKIFCryptoMisc* cMisc = mediator->GetMediator<IPKIFCryptoMisc>();
01718     if(NULL == cMisc)
01719         throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_MEDIATOR_MISSING, "IPKIFCryptoMisc interface is not available.");
01720 
01721     //*****************************************************************
01722     //  hash the signature from the signer info to countersign
01723     //*****************************************************************
01724 
01725     CPKIFAlgorithmIdentifierPtr counterSignerDigestAlg = countersignerSI->GetDigestAlg();
01726     PKIFCRYPTO::HASH_ALG ha = PKIFCRYPTO::SHA1;
01727     if(!GetCACHashAlg(counterSignerDigestAlg->oid(), &ha))
01728             throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_UNSUPPORTED_ALG, "Unsupported hashing algorithm encountered during countersignature generation.");
01729 
01730     unsigned char hashResult[MAXHASH];
01731     int hashResultLen = MAXHASH;
01732     if(!countersignerSI->Decoded())
01733     {
01734         CPKIFCredentialPtr cred = countersignerSI->GetCredential();
01735         if(cred == (CPKIFCredential*)NULL)
01736             throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_INVALID_INPUT, "The SignerInfo of the countersigner does not contain a credential.");
01737 
01738         IPKIFHashContext* hi = cMisc->HashInit(ha);
01739         cMisc->HashUpdate(hi, (unsigned char*)sigBP->GetBuffer(), sigBP->GetLength());
01740         cMisc->HashFinal(hi, hashResult, &hashResultLen);
01741         delete hi;
01742     }
01743 
01744     //*****************************************************************
01745     //  populate an Objective SignerInfo object with details from the
01746     //  countersigner SignerInfo object that was passed in (including
01747     //  signature generation, signed attribute preparation, etc.)
01748     //*****************************************************************
01749     //changed to memory helper object 11/11/2003
01750     PKIFCMSMessageMemoryHelper mhSignerInfo;
01751     mhSignerInfo.pSignerInfo = new CACCMSSignerInfo;
01752     GetSignerInfo(mhSignerInfo.pSignerInfo, countersignerSI,  hashResult, hashResultLen, mediator, g_data, ha, true);
01753 
01754     //*****************************************************************
01755     //  encode the countersigner signer info and return the encoded blob
01756     //*****************************************************************
01757     CACASNWRAPPER_CREATE(CACCMSSignerInfo, tmpPDU);
01758     ASN1OpenType* data1 = tmpPDU.Encode(mhSignerInfo.pSignerInfo);
01759 
01760     //next, update the countersignerSI
01761     CPKIFBufferPtr data1Buf(new CPKIFBuffer(data1->data, data1->numocts));
01762     CPKIFSignerInfoPtr newCountersignerSI(new CPKIFSignerInfo(data1Buf));
01763     //CPKIFSignerInfoPtr newCountersignerSI(new CPKIFSignerInfo(*mhSignerInfo.pSignerInfo));
01764     countersignerSI = newCountersignerSI;
01765 
01766     CPKIFBufferPtr tmp;
01767     try
01768     {
01769         //copy the buffer info a buffer ptr to be returned to the caller
01770         CPKIFBufferPtr tmpTmp(new CPKIFBuffer((unsigned char*)data1->data, data1->numocts));
01771         tmp = tmpTmp;
01772         delete data1; data1 = NULL;
01773     }
01774     catch(std::bad_alloc& ba)
01775     {
01776         if(data1)
01777             delete data1;
01778         throw ba;
01779     }
01780 
01781     return tmp;
01782 }
01783 
01800 void PKIFCMS_API VerifyCounterSignatures(
01803     CPKIFSignedDataPtr& sd,
01806     CPKIFSignerInfoPtr& si,
01809     IPKIFMediatorPtr& mediator,
01812     CPKIFPathSettingsPtr& settings,
01815     CPKIFSignerInfoList& sis, 
01818     vector<CMSVerificationStatus>& statusVector,
01821     CPKIFCertificateList& certVector,
01824     vector<CPKIFCertificatePathPtr>& pathVector)
01825 {
01826     CPKIFFuncStoragePtr keyUsageSigFunctor3(new CPKIFFuncStorage(keyUsageChecker_Signature));
01827 
01828     //*****************************************************************
01829     //  sanity check the inputs
01830     //*****************************************************************
01831     if(sd == (CPKIFSignedData*)NULL || si == (CPKIFSignerInfo*)NULL || mediator == (IPKIFMediator*)NULL)
01832         throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_INVALID_INPUT, "One or more NULL parameters passed to VerifyCounterSignatures.");
01833 
01834     IPKIFCryptoRawOperations* cRaw = mediator->GetMediator<IPKIFCryptoRawOperations>();
01835     if(NULL == cRaw)
01836         throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_MEDIATOR_MISSING, "IPKIFCryptoRawOperations interface is not available.");
01837 
01838     IPKIFCryptoMisc* cMisc = mediator->GetMediator<IPKIFCryptoMisc>();
01839     if(NULL == cMisc)
01840         throw CPKIFMessageException(TOOLKIT_MESSAGE, COMMON_MEDIATOR_MISSING, "IPKIFCryptoMisc interface is not available.");
01841 
01842     //*****************************************************************
01843     //  extract the CounterSignature attribute from the coutnersigned 
01844     //  SignerInfo then get and hash the signature
01845     //*****************************************************************
01846     CPKIFCountersignatureAttributePtr csAttr = si->GetUnsignedAttribute<CPKIFCountersignatureAttribute>();
01847     if(csAttr == (CPKIFCountersignatureAttribute*)NULL)
01848         return;
01849 
01850     CPKIFBufferPtr sigBP = si->GetSignature();
01851     if(sigBP == (CPKIFBuffer*)NULL)
01852         return;
01853 
01854     HashInfo hi2;
01855     hi2.m_hashAlg = PKIFCRYPTO::SHA1;
01856 
01857     int hashResultLen = MAXHASH;
01858 
01859     PKIFCRYPTO::HASH_ALG ha = PKIFCRYPTO::SHA1;
01860 
01861     CPKIFAlgorithmIdentifierPtr sigAlg = si->GetDigestAlg();
01862     GetCACHashAlg(sigAlg->oid(), &ha);
01863     GetCACHashAlg(sigAlg->oid(), &hi2.m_hashAlg);
01864 
01865     IPKIFHashContext* hi = cMisc->HashInit(ha);
01866     cMisc->HashUpdate(hi, (unsigned char*)sigBP->GetBuffer(), sigBP->GetLength());
01867     cMisc->HashFinal(hi, hi2.m_hashResult, &hashResultLen);
01868     delete hi;
01869 
01870     //*****************************************************************
01871     //  Get the encoded SignerInfos from the CounterSignature attribute
01872     //  and iterate over them verifying each and populating the 
01873     //  outbound sis and statusVector variables.
01874     //*****************************************************************
01875     CPKIFBufferList bl;
01876     csAttr->GetValues(bl);
01877 
01878     CPKIFBufferList::iterator blPos;
01879     CPKIFBufferList::iterator blEnd = bl.end();
01880     int ii = 0;
01881     CPKIFCertificatePtr emptyCert;
01882     for(blPos = bl.begin(); blPos != blEnd; ++blPos, ++ii)
01883     {
01884         //first, decode the buffer - if ANY fails to parse let the caller handle the exception
01885         CACASNWRAPPER_CREATE(CACCMSSignerInfo, tmpPDU);
01886         CACCMSSignerInfo* curSI = tmpPDU.Decode((*blPos)->GetBuffer(), (*blPos)->GetLength());
01887         CPKIFBufferPtr curSIBuf(new CPKIFBuffer((*blPos)->GetBuffer(), (*blPos)->GetLength()));
01888 
01889         //next, create a CPKIFSignerInfoPtr and add entries to both sis and statusVector        
01890         CPKIFSignerInfoPtr newSI(new CPKIFSignerInfo(curSIBuf));
01891         //CPKIFSignerInfoPtr newSI(new CPKIFSignerInfo(*curSI));
01892         sis.push_back(newSI);
01893         statusVector.push_back(NOT_VERIFIED);
01894         certVector.push_back(emptyCert);
01895 
01896         //next, get the signer's cert from the signed data that was passed in
01897         //if it can't be found - continue to the next countersignature
01898         //CPKIFBufferPtr curSIBuf(new CPKIFBuffer((*blPos)->GetBuffer(), (*blPos)->GetLength()));
01899         CPKIFBufferPtr signerCert = sd->GetSignersCert(curSIBuf);
01900         //CPKIFBufferPtr signerCert = sd->GetSignersCert(curSI);
01901         if(signerCert == (CPKIFCertificate*)NULL)
01902             continue;
01903         else
01904         {
01905             CPKIFCertificatePtr newSignerCert(new CPKIFCertificate);
01906             newSignerCert->Decode(signerCert->GetBuffer(), signerCert->GetLength());
01907             certVector[ii] = newSignerCert;
01908         }
01909 
01910         //next, determine if it's necessary to generate a hash over signed attributes
01911         HashInfo* hi = NULL;
01912         bool deleteHI = false;
01913         if(curSI->m.signedAttrsPresent)
01914         {
01915             hi = ComputeSignedAttrHash(curSI, cMisc);
01916             deleteHI = true;
01917             if(!CompareHashes(&hi2, curSI))
01918             {
01919                 //if hash of data does not match the hash contained in the signed attr bag
01920                 //or if there is no content hash in the signed attr bag then fail
01921                 statusVector[ii] = CMS_SIGNATURE_INVALID;
01922                 delete hi;
01923                 continue;
01924             }
01925         }
01926         else
01927             hi = &hi2;
01928 
01929         //set up a key material object to hold the signer's cert
01930         CPKIFKeyMaterial key;
01931         key.SetCertificate(signerCert->GetBuffer(), signerCert->GetLength());
01932 
01933         bool bRetrySigWithParams = false;
01934         //invoke verify - passing either the hash that was calculated over the signature or the hash calculated over
01935         //the signed attributes.        
01936         try
01937         {
01938             if(!cRaw->Verify(key, hi->m_hashResult, CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize(), (unsigned char*)curSI->signature.data, curSI->signature.numocts, hi->m_hashAlg))
01939             {
01940                 if(NULL != hi && deleteHI)
01941                     delete hi;
01942                 statusVector[ii] = CMS_SIGNATURE_INVALID;
01943                 return;
01944             }
01945             else
01946             {
01947                 if(NULL != hi && deleteHI)
01948                     delete hi;
01949                 statusVector[ii] = CMS_SIGNATURE_VERIFIED;
01950             }
01951         }
01952         catch(CPKIFException& ce)
01953         {
01954             if(PKIFCAPING_KEY_IMPORT_FAILED != ce.GetErrorCode() && 
01955                 PKIFCAPI_KEY_IMPORT_FAILED != ce.GetErrorCode() && 
01956                 PKIF_CRYPTOPP_RAW_IMPORT_FAILED != ce.GetErrorCode() &&
01957                 PKIFNSS_CERT_IMPORT_FAILED != ce.GetErrorCode())
01958             {
01959                 throw ce;
01960             }
01961             else
01962             {
01963                 bRetrySigWithParams = true;
01964             }
01965         }
01966         IPKIFPathBuild* cBuild = mediator->GetMediator<IPKIFPathBuild>();
01967         if(NULL == cBuild)
01968             continue;
01969 
01970         IPKIFPathValidate* cValidate = mediator->GetMediator<IPKIFPathValidate>();
01971         if(NULL == cValidate)
01972             continue;
01973 
01974         CPKIFCertificatePathPtr tmpPath(new CPKIFCertificatePath);
01975         pathVector.push_back(tmpPath);
01976 
01977         CPKIFPathValidationResultsPtr tmpValResults(new CPKIFPathValidationResults);
01978 
01979         CPKIFCertificatePtr signersCert(new CPKIFCertificate());
01980         signersCert->Decode(signerCert->GetBuffer(), signerCert->GetLength());
01981         tmpPath->SetTarget(signersCert);
01982 
01983         //if settings have been associated with this object use them
01984         //otherwise defer to the default settings (either globally set
01985         //or defined to be very permissive)
01986         if(settings != (CPKIFPathSettings*)NULL)
01987             tmpPath->SetPathSettings(settings);
01988 
01989         try
01990         {
01991             do
01992             {
01993                 if(!cBuild->BuildPath(*tmpPath))
01994                 {
01995                     //stop looking for paths - continue to next countersignature
01996                     break; 
01997                 }
01998                 if(cValidate->ValidatePath(*tmpPath, *tmpValResults, keyUsageSigFunctor3))
01999                 {
02000                     if(NOT_REVOKED == tmpValResults->GetRevocationStatusMostSevere())
02001                     {
02002                         if(bRetrySigWithParams)
02003                         {
02004                             CPKIFAlgorithmIdentifierPtr wp = tmpValResults->GetWorkingParams();
02005                              key.SetWorkingParameters(wp);
02006                             if(!cRaw->Verify(key, hi->m_hashResult, CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize(), (unsigned char*)curSI->signature.data, curSI->signature.numocts, hi->m_hashAlg))
02007                             {
02008                                 if(NULL != hi && deleteHI)
02009                                     delete hi;
02010                                 statusVector[ii] = CMS_SIGNATURE_INVALID;
02011                                 return;
02012                             }
02013                             else
02014                             {
02015                                 if(NULL != hi && deleteHI)
02016                                     delete hi;
02017                                 statusVector[ii] = CMS_SIGNATURE_VERIFIED;
02018                             }
02019                         }
02020 
02021                         statusVector[ii] = REV_STATUS_VERIFIED;
02022 
02023                         //stop looking for paths - continue to next countersignature
02024                         break; 
02025                     }
02026                     else
02027                     {
02028                         if(bRetrySigWithParams)
02029                         {
02030                             CPKIFAlgorithmIdentifierPtr wp = tmpValResults->GetWorkingParams();
02031                              key.SetWorkingParameters(wp);
02032                             if(!cRaw->Verify(key, hi->m_hashResult, CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize(), (unsigned char*)curSI->signature.data, curSI->signature.numocts, hi->m_hashAlg))
02033                             {
02034                                 if(NULL != hi && deleteHI)
02035                                     delete hi;
02036                                 statusVector[ii] = CMS_SIGNATURE_INVALID;
02037                                 return;
02038                             }
02039                             else
02040                             {
02041                                 if(NULL != hi && deleteHI)
02042                                     delete hi;
02043                                 statusVector[ii] = CMS_SIGNATURE_VERIFIED;
02044                             }
02045                         }
02046 
02047                         statusVector[ii] = CERT_PATH_VERIFIED;
02048 
02049                         //stop looking for paths - continue to next countersignature
02050                         break; 
02051                     }
02052                 }
02053                 else
02054                 {
02055                     if(!tmpValResults->GetBasicChecksSuccessfullyPerformed() ||
02056                         !tmpValResults->GetCertSignaturesVerified())
02057                     {
02058 
02059                         if(bRetrySigWithParams)
02060                         {
02061                             if(NULL != hi && deleteHI)
02062                                 delete hi;
02063                             statusVector[ii] = CMS_SIGNATURE_INVALID;
02064                             return;
02065                         }
02066 
02067                         statusVector[ii] = CERT_PATH_INVALID; //set the status but keep looking
02068 
02069                         //continue to try another path  
02070                         continue;
02071                     }
02072                     else if(REVOKED == tmpValResults->GetRevocationStatusMostSevere())
02073                     {
02074                         if(bRetrySigWithParams)
02075                         {
02076                             if(NULL != hi && deleteHI)
02077                                 delete hi;
02078                             statusVector[ii] = CMS_SIGNATURE_INVALID;
02079                             return;
02080                         }
02081 
02082                         statusVector[ii] = REV_STATUS_INVALID;
02083 
02084                         //see if the signer was revoked - if so, stop looking and return false now
02085                         //if they don't match then a CA cert was revoked and we should keep looking
02086                         //for a good path
02087                         CPKIFCertificateNodeEntryPtr errantCertNode = tmpValResults->GetCertificate();
02088                         if(errantCertNode != (CPKIFCertificateNodeEntry*)NULL)
02089                         {
02090                             CPKIFCertificatePtr errantCert = errantCertNode->GetCert();
02091                             if(errantCert != (CPKIFCertificate*)NULL && *errantCert == *signersCert)
02092                             {
02093                                 //continue to try another path
02094                                 continue;
02095                             }
02096                         }
02097                     }
02098                     else if(tmpValResults->GetBasicChecksSuccessfullyPerformed() &&
02099                         tmpValResults->GetCertSignaturesVerified())
02100                     {                       
02101                         if(bRetrySigWithParams)
02102                         {
02103                             CPKIFAlgorithmIdentifierPtr wp = tmpValResults->GetWorkingParams();
02104                              key.SetWorkingParameters(wp);
02105                             if(!cRaw->Verify(key, hi->m_hashResult, CPKIFAlgorithm::GetAlg(hi->m_hashAlg)->DigestSize(), (unsigned char*)curSI->signature.data, curSI->signature.numocts, hi->m_hashAlg))
02106                             {
02107                                 if(NULL != hi && deleteHI)
02108                                     delete hi;
02109                                 statusVector[ii] = CMS_SIGNATURE_INVALID;
02110                                 return;
02111                             }
02112                             else
02113                             {
02114                                 if(NULL != hi && deleteHI)
02115                                     delete hi;
02116                                 statusVector[ii] = CMS_SIGNATURE_VERIFIED;
02117                             }
02118                         }
02119                         statusVector[ii] = CERT_PATH_VERIFIED; //verification successful but revocation not checked
02120 
02121                         //continue to try another path
02122                         continue;
02123                     }
02124                 }
02125             }while(1);
02126         }
02127         catch(CPKIFException&)
02128         {
02129             //continue to next countersignature
02130             continue;
02131         }
02132     }
02133 
02134 }
02143 void PopulateKARIDFromKeyMaterial(
02145     CACCMSKeyAgreeRecipientIdentifier* rid,
02148     CPKIFKeyMaterialPtr& km)
02149 {
02150     CPKIFBufferPtr certBuf(new CPKIFBuffer());
02151     int rawLen = km->GetCertificateLength();
02152     unsigned char * cbRaw = certBuf->AllocateBuffer(rawLen);
02153     km->GetCertificate(cbRaw,&rawLen);
02154     CPKIFCertificatePtr cert(new CPKIFCertificate());
02155     cert->Decode(certBuf->GetBuffer(),rawLen);
02156     CPKIFSubjectKeyIdentifierPtr skid = cert->GetExtension<CPKIFSubjectKeyIdentifier>();
02157     if(skid) {
02158         CPKIFBufferPtr skidBuf = skid->KeyIdentifier();
02159         rid->t = T_CACCMSKeyAgreeRecipientIdentifier_rKeyId;
02160         rid->u.rKeyId = new CACCMSRecipientKeyIdentifier;
02161         memset(&(rid->u.rKeyId),0x00,sizeof(CACCMSRecipientKeyIdentifier));
02162         int skidLen = skidBuf->GetLength();
02163         rid->u.rKeyId->subjectKeyIdentifier.numocts = skidLen;
02164         rid->u.rKeyId->subjectKeyIdentifier.data = new unsigned char[skidLen];
02165         memcpy((void*)rid->u.rKeyId->subjectKeyIdentifier.data,skidBuf->GetBuffer(),skidLen);
02166     } else {
02167         rid->t = T_CACCMSKeyAgreeRecipientIdentifier_issuerAndSerialNumber;
02168         rid->u.issuerAndSerialNumber = new CACCMSIssuerAndSerialNumber;
02169         memset(rid->u.issuerAndSerialNumber,0x00,sizeof(CACCMSIssuerAndSerialNumber));
02170         rid->u.issuerAndSerialNumber->serialNumber = cert->SerialNumber();
02171         CPKIFBufferPtr nb = cert->Issuer()->rawName();
02172         CACASNWRAPPER_CREATE(CACX509V3Name, namePDU);
02173         CACX509V3Name * iName = namePDU.Decode(nb->GetBuffer(),nb->GetLength());
02174         CopyName(&rid->u.issuerAndSerialNumber->issuer, *iName);
02175     }
02176 }

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