--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,896 @@
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <cmssignedobject.h>
+#include <x509cert.h>
+#include <x509certext.h>
+#include <asymmetrickeys.h>
+#include <hash.h>
+#include <asn1enc.h>
+#include <asn1dec.h>
+#include <pkcs7excert.h>
+#include <cmssigneridentifier.h>
+#include <cmscontentinfo.h>
+#include <cmssignerinfo.h>
+#include "cmsutils.h"
+#include "pkcs7asn1.h"
+
+const TInt KSignedDataCertificates = 0;
+const TInt KSignedDataRevocationLists = 1;
+
+const TInt KCmsMinSignedDataElements = 4;
+//
+// Implementation of CMS Signed object
+//
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aIsDetached, aContentData);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
+ {
+ CCmsSignedObject* self = NewLC(aType, aIsDetached, aContentData);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(const CCmsContentInfo& aContentInfo)
+ {
+ CCmsSignedObject* self = NewLC(aContentInfo);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(const CCmsContentInfo& aContentInfo)
+ {
+ CCmsSignedObject* self = new (ELeave) CCmsSignedObject();
+ CleanupStack::PushL(self);
+ self->ConstructL(aContentInfo);
+ return self;
+ }
+
+CCmsSignedObject::CCmsSignedObject() : iVersion(EVersion_1)
+ {
+ }
+
+EXPORT_C CCmsSignedObject::~CCmsSignedObject()
+ {
+ delete iContentInfo;
+ iDigestAlgorithms.ResetAndDestroy();
+ iCertificates.ResetAndDestroy();
+ iSignerInfo.ResetAndDestroy();
+ for(TInt i = 0; i < KCmsMaxSignedDataElements; i++)
+ {
+ delete iDataElements.At(i);
+ }
+ }
+
+
+EXPORT_C TBool CCmsSignedObject::IsCertificateSetPresent() const
+ {
+ return iIsCertificateSetPresent;
+ }
+
+EXPORT_C TBool CCmsSignedObject::IsCertificateRevocationListsPresent() const
+ {
+ return iIsCertificateRevocationListsPresent;
+ }
+
+EXPORT_C TInt CCmsSignedObject::Version() const
+ {
+ return iVersion;
+ }
+
+EXPORT_C const RPointerArray<CCmsCertificateChoice>& CCmsSignedObject::Certificates() const
+ {
+ return iCertificates;
+ }
+
+EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CCmsSignedObject::DigestAlgorithms() const
+ {
+ return iDigestAlgorithms;
+ }
+
+EXPORT_C const CEncapsulatedContentInfo& CCmsSignedObject::ContentInfo() const
+ {
+ return *iContentInfo;
+ }
+
+EXPORT_C const RPointerArray<CCmsSignerInfo>& CCmsSignedObject::SignerInfo() const
+ {
+ return iSignerInfo;
+ }
+
+EXPORT_C void CCmsSignedObject::AddCertificateL(const CX509Certificate& aCert)
+ {
+ CmsUtils::AddCertificateL(iCertificates, aCert);
+ }
+
+void CCmsSignedObject::AddDigestAlgorithmL(TAlgorithmId aDigestAlgorithm)
+ {
+ CmsUtils::AddAlgorithmIdentifierL(iDigestAlgorithms, aDigestAlgorithm);
+ }
+
+EXPORT_C void CCmsSignedObject::AddCertificateL(const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType)
+ {
+ if (aType==CCmsCertificateChoice::ECertificateAttribute)
+ {
+ iVersion=EVersion_3;
+ }
+ CmsUtils::AddCertificateL(iCertificates, aCert, aType);
+ }
+
+void CCmsSignedObject::DecodeSignerInfoL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData);
+ TInt total = signerInfo->Count();
+ CCmsSignerInfo* signer(NULL);
+
+ for(TInt item = 0; item < total; item ++)
+ {
+ signer = CCmsSignerInfo::NewL(signerInfo->At(item)->Encoding());
+ CleanupStack::PushL(signer);
+ User::LeaveIfError(iSignerInfo.Append(signer));
+ CleanupStack::Pop(signer);
+ }
+ CleanupStack::PopAndDestroy(signerInfo);
+ }
+
+void CCmsSignedObject::DecodeEncapsulatedContentInfoL(const TDesC8& aRawData)
+ {
+ iContentInfo = CEncapsulatedContentInfo::NewL(aRawData);
+ }
+
+void CCmsSignedObject::ConstructL(const CCmsContentInfo& aContentInfo)
+ {
+ if(aContentInfo.ContentType() != EContentTypeSignedData)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TASN1DecGeneric decGen(aContentInfo.ContentData());
+ decGen.InitL();
+
+ if(decGen.Tag() == EASN1Sequence && decGen.Class()==EUniversal)
+ {
+ InitSignedObjectL(decGen.Encoding());
+ DecodeSignedDataL(*iEncoding);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+void CCmsSignedObject::ConstructL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData)
+ {
+ if (aContentData==KNullDesC8() && !aIsDetached)
+ {
+ User::Leave(KErrArgument);
+ }
+ iContentInfo=CEncapsulatedContentInfo::NewL(aType, !aIsDetached, aContentData);
+ //For later use to create hash if detached and hash not provided
+ iContentData.Set(aContentData);
+ }
+
+CCmsSignerIdentifier* CCmsSignedObject::BuildSignerIdentifierLC(const CX509Certificate& aCert)
+ {
+ CCmsSignerIdentifier* sid(NULL);
+ const CX509CertExtension* certExt = aCert.Extension(KSubjectKeyId);
+ if (certExt)
+ {
+ CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+ HBufC8* subKeyId=ext->KeyId().AllocL();
+ CleanupStack::PopAndDestroy(ext);
+ CleanupStack::PushL(subKeyId);
+ sid=CCmsSignerIdentifier::NewL(subKeyId);
+ CleanupStack::Pop(subKeyId);
+ CleanupStack::PushL(sid);
+ iVersion=EVersion_3;
+ }
+ else
+ {
+ CX500DistinguishedName* distinguishedName=CX500DistinguishedName::NewLC(aCert.IssuerName());
+ CPKCS7IssuerAndSerialNumber* issuerAndSN=CPKCS7IssuerAndSerialNumber::NewL(distinguishedName, aCert.SerialNumber());
+ CleanupStack::Pop(distinguishedName);
+ CleanupStack::PushL(issuerAndSN);
+ sid=CCmsSignerIdentifier::NewL(issuerAndSN);
+ CleanupStack::Pop(issuerAndSN);
+ CleanupStack::PushL(sid);
+ }
+ return sid;
+ }
+
+
+void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm,
+ TBool aIsHash,
+ const TDesC8& aValue,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ //build Signer Identifier
+ CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert);
+
+ //build digest algorithm and signing algorithm
+ CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
+ const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey();
+ CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), KNullDesC8());
+
+ //build signer info
+ CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue,
+ aIsHash,
+ aKey,
+ sid,
+ digAlg,
+ signingAlg);
+ CleanupStack::Pop(3, sid);
+ CleanupStack::PushL(signerInfo);
+ //add to the signer info list
+ iSignerInfo.AppendL(signerInfo);
+ CleanupStack::Pop();
+
+ //Add the certificate to the list if needed
+ if (aAddCertificate)
+ {
+ AddCertificateL(aCert);
+ }
+
+ //Add the digest algorithm the list if needed
+ AddDigestAlgorithmL(aDigestAlgorithm);
+ }
+
+
+
+void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm,
+ TBool aIsHash,
+ const TDesC8& aValue,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+
+ {
+ //build Signer Identifier
+ CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert);
+
+ //build digest algorithm and signing algorithm
+ CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8());
+ const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey();
+ CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), publicKeyInfo.EncodedParams());
+
+ //build signer info
+ CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue,
+ aIsHash,
+ aKey,
+ sid,
+ digAlg,
+ signingAlg);
+ CleanupStack::Pop(3, sid);
+ CleanupStack::PushL(signerInfo);
+ //add to the signer info list
+ iSignerInfo.AppendL(signerInfo);
+ CleanupStack::Pop();
+
+ //Add the certificate to the list if needed
+ if (aAddCertificate)
+ {
+ AddCertificateL(aCert);
+ }
+
+ //Add the digest algorithm the list if needed
+ AddDigestAlgorithmL(aDigestAlgorithm);
+ }
+
+void CCmsSignedObject::ConstructL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data
+ if (aType != EContentTypeData)
+ {
+ iVersion=EVersion_3;
+ }
+
+ //build EncapsulatedContentInfo
+ iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8());
+
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ ETrue,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+
+ }
+void CCmsSignedObject::ConstructL(TCmsContentInfoType aType,
+ const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data
+ if (aType != EContentTypeData)
+ {
+ iVersion=EVersion_3;
+ }
+
+ //build EncapsulatedContentInfo
+ iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8());
+
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ ETrue,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+
+
+EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CDSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+
+ {
+ TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse;
+ if (isHash)
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ if (iContentData!=KNullDesC8())
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ iContentData,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ //No way to sign if no data content nor its hash.
+ User::Leave(KErrArgument);
+ }
+ }
+ }
+
+EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue,
+ TAlgorithmId aDigestAlgorithm,
+ const CRSAPrivateKey& aKey,
+ const CX509Certificate& aCert,
+ TBool aAddCertificate)
+ {
+ TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse;
+ if (isHash)
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ aHashValue,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ if (iContentData!=KNullDesC8())
+ {
+ BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm,
+ isHash,
+ iContentData,
+ aKey,
+ aCert,
+ aAddCertificate);
+ }
+ else
+ {
+ //No way to sign if no data content nor its hash.
+ User::Leave(KErrArgument);
+ }
+ }
+ }
+
+
+EXPORT_C CASN1EncSequence* CCmsSignedObject::EncodeASN1DERLC() const
+ {
+ // the root sequence contains the signed object
+ CASN1EncSequence* root = CASN1EncSequence::NewLC();
+
+ // Encode version
+ CASN1EncInt* version=CASN1EncInt::NewLC(iVersion);
+ root->AddAndPopChildL(version);
+
+ // Encode Algorithm
+ CASN1EncBase* algorithm=EncodeAlgorithmsLC();
+ root->AddAndPopChildL(algorithm);
+
+
+ // Encode EncapsulatedContentInfo
+ CASN1EncSequence* contentInfo=iContentInfo->EncodeASN1DERLC();
+ root->AddAndPopChildL(contentInfo);
+
+ // Encode option fields certificates SET
+ CASN1EncBase* cert=EncodeCertificatesLC();
+ if (cert)
+ {
+ root->AddAndPopChildL(cert);
+ }
+
+ // Encode signerinfo
+ CASN1EncBase* signerInfo=EncodeSignerInfoLC();
+ root->AddAndPopChildL(signerInfo);
+
+ return root;
+ }
+
+
+CASN1EncBase* CCmsSignedObject::EncodeCertificatesLC() const
+ {
+ return CmsUtils::EncodeCertificatesLC(iCertificates);
+ }
+
+CASN1EncBase* CCmsSignedObject::EncodeAlgorithmsLC() const
+ {
+ return CmsUtils::EncodeDigestAlgorithmsLC(iDigestAlgorithms);
+ }
+
+CASN1EncBase* CCmsSignedObject::EncodeSignerInfoLC() const
+ {
+ CASN1EncSet* signerInfoSet = CASN1EncSet::NewLC();
+ TInt count=iSignerInfo.Count();
+
+ for (TInt i=0;i<count;i++)
+ {
+ CASN1EncSequence* signerInfo=iSignerInfo[i]->EncodeASN1DERLC();
+ signerInfoSet->AddAndPopChildL(signerInfo);
+ }
+ return signerInfoSet;
+ }
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding)
+ {
+ TInt certCount = iCertificates.Count();
+ TInt endEntityPos = -1;
+ TInt endEncodingSize = 0;
+ TPtrC8 endEntityEncoding;
+ TInt cert;
+ TBool valid = EFalse;
+
+ const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier();
+
+ // looks for end entity certificate
+ for(cert = 0; cert < certCount; cert++)
+ {
+ if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
+ {
+ const CX509Certificate& certificate = iCertificates[cert]->Certificate();
+
+ endEncodingSize+= certificate.Encoding().Length();
+
+ if(endEntityPos == -1)
+ {
+ if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
+ {
+ if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
+ {
+ RInteger sn1=RInteger::NewL(certificate.SerialNumber());
+ CleanupClosePushL(sn1);
+ RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
+ CleanupClosePushL(sn2);
+ if (sn1==sn2)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
+ }
+ }
+ else
+ {
+ const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId);
+ if (certExt)
+ {
+ CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+ if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(ext);
+ }
+ }
+ }
+ }
+ }
+
+ // checks if end entity was found
+ if(endEntityPos != -1)
+ {
+ // builds the cert chain encoding by putting the end entity first then all remaining
+ // certs
+ aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
+ TPtr8 encodingPtr(aCertChainEncoding->Des());
+ encodingPtr.Copy(endEntityEncoding);
+ for(cert = 0; cert < certCount; cert++)
+ {
+ if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
+ {
+ const CX509Certificate& certificate = iCertificates[cert]->Certificate();
+ if(cert != endEntityPos)
+ {
+ encodingPtr.Append(certificate.Encoding());
+ }
+ }
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+ return valid;
+ }
+
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding)
+ {
+ TInt certCount = aCertificates.Count();
+ TInt endEntityPos = -1;
+ TInt endEncodingSize = 0;
+ TPtrC8 endEntityEncoding;
+ TInt cert;
+ TBool valid = EFalse;
+ const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier();
+
+ // looks for end entity certificate
+ for(cert = 0; cert < certCount; cert++)
+ {
+ const CX509Certificate& certificate = *aCertificates[cert];
+ endEncodingSize+= certificate.Encoding().Length();
+ if(endEntityPos == -1)
+ {
+ if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
+ {
+ if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
+ {
+ RInteger sn1=RInteger::NewL(certificate.SerialNumber());
+ CleanupClosePushL(sn1);
+ RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
+ CleanupClosePushL(sn2);
+ if (sn1==sn2)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
+ }
+ }
+ else
+ {
+ const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId);
+ if (certExt)
+ {
+ CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+ if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0)
+ {
+ endEntityPos = cert;
+ endEntityEncoding.Set(certificate.Encoding());
+ valid = ValidateSignatureL(aSignerInfo, certificate);
+ }
+ CleanupStack::PopAndDestroy(ext);
+ }
+ }
+ }
+ }
+
+ // checks if end entity was found
+ if(endEntityPos != -1)
+ {
+ // builds the cert chain encoding by putting the end entity first then all remaining
+ // certs
+ aCertChainEncoding = HBufC8::NewLC(endEncodingSize);
+ TPtr8 encodingPtr(aCertChainEncoding->Des());
+ encodingPtr.Copy(endEntityEncoding);
+ for(cert = 0; cert < certCount; cert++)
+ {
+ const CX509Certificate& certificate = *aCertificates[cert];
+
+ if(cert != endEntityPos)
+ {
+ encodingPtr.Append(certificate.Encoding());
+ }
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ return valid;
+ }
+
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash)
+ {
+ if (aIsHash)
+ {
+ SetHash(aContentDataOrHash);
+ }
+ else
+ {
+ SetContentData(aContentDataOrHash);
+ }
+ return ValidateSignerLC(aSignerInfo, aCertChainEncoding);
+ }
+
+EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash)
+ {
+ if (aIsHash)
+ {
+ SetHash(aContentDataOrHash);
+ }
+ else
+ {
+ SetContentData(aContentDataOrHash);
+ }
+ return ValidateSignerLC(aSignerInfo, aCertificates, aCertChainEncoding);
+ }
+
+TBool CCmsSignedObject::ValidateSignatureL(const CCmsSignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert)
+ {
+ delete iSigningAlgorithm;
+ iSigningAlgorithm = NULL;
+ iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.SignatureAlgorithm(), aSignerInfo.DigestAlgorithm());
+
+ delete iSignature;
+ iSignature = NULL;
+ iSignature = aSignerInfo.SignatureValue().AllocL();
+
+ if (aSignerInfo.SignatureAlgorithm().Algorithm()==EDSA)
+ {
+ delete iParameters;
+ iParameters = NULL;
+ CDSAParameters* theDSAParams = iKeyFactory->DSAParametersL(aEndEntityCert.PublicKey().EncodedParams());
+ CleanupStack::PushL(theDSAParams);
+ CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
+ params->SetDSAParamsL(*theDSAParams);
+ SetParametersL(*params);
+ CleanupStack::PopAndDestroy(2, theDSAParams);
+ }
+
+ if (iContentInfo->IsContentDataPresent() || iContentData != KNullDesC8)
+ {
+ return VerifySignatureL(aEndEntityCert.PublicKey().KeyData());
+ }
+ else if (iHash!=KNullDesC8)
+ {
+ return VerifySignatureL(aEndEntityCert.PublicKey().KeyData(), iHash);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ return EFalse;
+ }
+
+ }
+
+void CCmsSignedObject::InitSignedObjectL(const TDesC8& aRawData)
+ {
+ // Populate CSignedObject data members
+ iKeyFactory = new (ELeave) TX509KeyFactory;
+ iEncoding = aRawData.AllocL();
+
+ CSHA1* hash = CSHA1::NewL();
+ CleanupStack::PushL(hash);
+ iFingerprint = hash->Hash(Encoding()).AllocL();
+ CleanupStack::PopAndDestroy(hash);
+ }
+
+void CCmsSignedObject::DecodeSignedDataL(const TDesC8& aRawData)
+ {
+ CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, KCmsMinSignedDataElements, KCmsMaxSignedDataElements);
+ TInt totalItems = signedData->Count();
+ TASN1DecInteger decInt;
+
+ // decodes version
+ iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER());
+ iVersion = decInt.DecodeDERShortL(*signedData->At(0));
+ if (iVersion>4 || iVersion<0)
+ {
+ User::Leave(KErrArgument);
+ }
+ // decodes algorithms
+ iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER());
+ DecodeDigestAlgorithmsL(signedData->At(1)->Encoding());
+ // decodes contentinfo
+ iDataElements.At(EEncapsulatedContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER());
+ DecodeEncapsulatedContentInfoL(signedData->At(2)->Encoding());
+
+ // Checks for optional fields
+ TInt pos = 3; // Skip first non-optional fields
+ do
+ {
+ const TASN1DecGeneric& currentItem = *signedData->At(pos);
+ switch(currentItem.Tag())
+ {
+ case KSignedDataCertificates:
+ {
+ if (currentItem.Class()!=EContextSpecific)
+ {
+ User::Leave(KErrArgument);
+ }
+ iIsCertificateSetPresent=ETrue;
+ iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER());
+ DecodeCertificatesL(currentItem.Encoding());
+ break;
+ }
+ case KSignedDataRevocationLists:
+ {
+ if (currentItem.Class()!=EContextSpecific)
+ {
+ User::Leave(KErrArgument);
+ }
+ iIsCertificateRevocationListsPresent=ETrue;
+ iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER());
+ DecodeRevocationListsL(currentItem.Encoding());
+ break;
+ }
+ default:
+ {
+ //Optional field with wrong tag and class
+ if (pos<totalItems-1)
+ {
+ User::Leave(KErrArgument);
+ }
+ // else Non-optional field
+ }
+ }
+ pos++;
+ }
+ while(pos < totalItems);
+
+ iDataElements.At(ESignedInfo) = new(ELeave) TPtrC8(signedData->At(totalItems-1)->GetContentDER());
+ DecodeSignerInfoL(signedData->At(totalItems-1)->Encoding());
+
+ CleanupStack::PopAndDestroy(signedData);
+ }
+
+void CCmsSignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData)
+ {
+ CmsUtils::DecodeDigestAlgorithmsL(iDigestAlgorithms, aRawData);
+ }
+
+void CCmsSignedObject::DecodeCertificatesL(const TDesC8& aRawData)
+ {
+ CmsUtils::DecodeCertificatesL(iCertificates, aRawData);
+ }
+
+void CCmsSignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/)
+ {
+ }
+
+EXPORT_C const TPtrC8 CCmsSignedObject::SignedDataL() const
+ {
+ if (iContentInfo->IsContentDataPresent())
+ {
+ return iContentInfo->ContentData();
+ }
+ else
+ {
+ if (iContentData!=KNullDesC8)
+ {
+ return iContentData;
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+ return KNullDesC8();
+ }
+
+EXPORT_C void CCmsSignedObject::InternalizeL(RReadStream& /*aStream*/)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+EXPORT_C const TPtrC8* CCmsSignedObject::DataElementEncoding(const TUint aIndex) const
+ {
+ return iDataElements.At(aIndex);
+ }
+
+void CCmsSignedObject::SetContentData(const TDesC8& aContentData)
+ {
+ iContentData.Set(aContentData);
+ }
+
+void CCmsSignedObject::SetHash(const TDesC8& aHash)
+ {
+ iHash.Set(aHash);
+ }
+
+
+