cryptoservices/certificateandkeymgmt/pkcs7/cmssignedobject.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /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);
+	}
+
+
+