cryptoservices/certificateandkeymgmt/tpkcs7/tcmsstep.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/tpkcs7/tcmsstep.cpp	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,1100 @@
+/*
+* 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 "tcmsstep.h"
+#include <testexecutelog.h>
+#include <asnpkcs.h>
+#include <pkcs7signedobject.h>
+#include <asn1enc.h>
+#include <cmssignedobject.h>
+#include <cmsdefs.h>
+#include <hash.h>
+#include <asymmetric.h>
+#include <cmssigneridentifier.h>
+#include <x509certext.h>
+#include <pkixcertchain.h>
+#include <cmscontentinfo.h>
+#include "validate.h"
+
+
+CTCmsBaseStep::CTCmsBaseStep()
+	{
+	}
+
+CTCmsBaseStep::~CTCmsBaseStep()
+	{
+	iFs.Close ();
+	delete iDataContent;
+	delete iExpectedEncoding;
+	__UHEAP_MARKEND;
+	}
+
+TVerdict CTCmsBaseStep::doTestStepPreambleL()
+	{
+	__UHEAP_MARK;	
+	User::LeaveIfError (iFs.Connect());	
+	
+	//Read the data to be signed
+	iDataContent = readFileL(_L("Data"));
+	
+	if (iDataContent == NULL)
+		{
+		iDataContent=KNullDesC8().AllocL();
+		}
+	
+	//Read the expected data type
+	TPtrC contentDataType;
+	if (GetStringFromConfig(ConfigSection(), _L("ExpectedDataType"), contentDataType))
+		{
+		iExpectedDataType=CovertContentDataTypeNameToDataType(contentDataType);			
+		}
+
+	//Read the expected result
+	iExpectedEncoding = readFileL(_L("Result"));
+	if (!iExpectedEncoding)
+		{
+		INFO_PRINTF1(_L("Failed to read 'Result' section of script"));
+		SetTestStepResult(ETestSuiteError);			
+		}
+
+	GetIntFromConfig(ConfigSection(), _L("ExpectedResult"), iExpectedResult);	
+	GetBoolFromConfig(ConfigSection(), _L("IsOOMTest"), iIsOOMTest);
+	return TestStepResult();	
+	}
+
+TInt CTCmsBaseStep::CovertContentDataTypeNameToDataType(const TDesC& aDataTypeName)
+	{
+	if (aDataTypeName.Compare(_L("DATA"))==0)
+		{
+		return EContentTypeData;	
+		}
+	else	if (aDataTypeName.Compare(_L("SIGNEDDATA"))==0)
+				{
+				return EContentTypeSignedData;
+				}
+		 else	if (aDataTypeName.Compare(_L("ENVELOPEDDATA"))==0)
+					 {
+					 return EContentTypeEnvelopedData;	
+					 }
+			  else	if (aDataTypeName.Compare(_L("DIGESTEDDATA"))==0)
+						{
+						return EContentTypeDigestedData;
+						}
+					else 	if (aDataTypeName.Compare(_L("ENCRYPTEDDATA"))==0)
+								{
+								return EContentTypeEncryptedData;
+								}
+							else 	if (aDataTypeName.Compare(_L("SIGNEDANDENVELOPEDDATA"))==0)
+										{
+										return CPKCS7ContentInfo::EContentTypeSignedAndEnvelopedData;	
+										}
+									else	if (aDataTypeName.Compare(_L("AUTHDATA"))==0)
+												{
+												return EContentTypeAuthenticatedData;	
+												}
+											else
+												{
+												User::Leave(KErrArgument);
+												return EContentTypeData;
+												}
+	}
+
+HBufC8* CTCmsBaseStep::readFileL (TPtrC tag)
+	{
+	TPtrC fileName;
+	if (GetStringFromConfig(ConfigSection(), tag, fileName) == EFalse)
+		{
+		return NULL;
+		}
+
+	RFile file;
+	if (file.Open(iFs, fileName, EFileRead) != KErrNone)
+		{
+		INFO_PRINTF2(_L("Cannot open file %S for reading"), &fileName);
+		return NULL;
+		}
+	CleanupClosePushL(file);
+	TInt fileSize = 0;
+	User::LeaveIfError(file.Size(fileSize));
+	HBufC8* result = HBufC8::NewMaxL(fileSize);
+	TPtr8 rawDataPtr(result->Des());
+	file.Read (rawDataPtr);
+	CleanupStack::PopAndDestroy (&file);
+	INFO_PRINTF3(_L("Read %d octets from %S"), result->Size(), &fileName);
+	return result;
+	}
+
+void CTCmsBaseStep::OutputResultToFileL(const TDesC8& aSignature)
+	{
+	TDriveUnit sysDrive (RFs::GetSystemDrive());
+	TBuf<128> rName (sysDrive.Name());;
+	rName.Append(_L("\\tpkcs7\\myresults\\"));
+			
+	TInt err=iFs.MkDir(rName);
+	if (err!=KErrNone && err!=KErrAlreadyExists)
+		{
+		User::Leave(err);	
+		}
+				
+	RFile file;
+	CleanupClosePushL(file);
+	
+	_LIT(KExtension, ".der");
+	rName.Append(ConfigSection());
+	rName.Append(KExtension);
+	rName.LowerCase();
+	User::LeaveIfError(file.Replace(iFs, rName, EFileWrite | EFileStream));
+	User::LeaveIfError(file.Write(aSignature));
+	CleanupStack::PopAndDestroy(&file);
+	}
+
+
+HBufC8* CTCmsBaseStep::CreateDEREncodingLC(const CASN1EncBase& aEncoding)
+	{	
+	TUint len = aEncoding.LengthDER();
+	HBufC8* buf = HBufC8::NewMaxLC(len);
+	TUint pos = 0;
+	TPtr8 bufptr(buf->Des());
+	aEncoding.WriteDERL(bufptr, pos);
+	return buf;
+	}
+
+TVerdict CTCmsBaseStep::doTestStepL()
+	{
+	if (!iIsOOMTest)
+		{
+		TRAPD(err, doTestL();)
+		if (err!=iExpectedResult)
+			{
+			SetTestStepResult(EFail);
+			User::Leave(err);
+			}
+		return TestStepResult();
+		}
+	else
+		{
+		return doOOMTestL();	
+		}	
+	}
+
+TVerdict CTCmsBaseStep::doOOMTestL()
+	{
+	TVerdict verdict = EFail;
+ 	TInt countAfter = 0;
+	TInt countBefore = 0;
+ 	for (TInt oomCount = 0; ; oomCount++)
+ 		{
+ 		__UHEAP_RESET;
+ 		__UHEAP_SETFAIL(RHeap::EDeterministic, oomCount);
+ 		countBefore = User::CountAllocCells();
+ 		TRAPD(error, doTestL());
+ 		countAfter = User::CountAllocCells();
+ 		__UHEAP_RESET;
+ 		if (error != KErrNoMemory)
+ 			{
+ 			verdict = EPass;
+ 			INFO_PRINTF2(_L("OOM Status %d"),error);
+			INFO_PRINTF1(_L("Test outcome : Passed"));
+ 			break;
+ 			}
+ 		else
+ 			{
+ 			if (countBefore != countAfter)
+ 				{
+ 				INFO_PRINTF2(_L("OOM Status %d"),error);
+ 				INFO_PRINTF2(_L("OOM Failed at %d"), oomCount);
+ 				SetTestStepResult(EFail);
+ 				break;
+ 				}
+ 			}
+ 		INFO_PRINTF2(_L("OOM Failed Point status %d"), error);
+		}
+	INFO_PRINTF3(_L("Heap alloc count ok: %d final vs %d initial"), countAfter,countBefore);
+ 	SetTestStepResult(verdict);
+ 	if (verdict==EFail)
+	 	{
+ 		User::Leave(KErrGeneral);	 		
+	 	}	 	
+ 	return verdict;
+	}
+
+
+//
+// Implementation of CMS Data Test Step
+//
+CTCmsDataStep::CTCmsDataStep()
+	{
+	}
+
+CTCmsDataStep::~CTCmsDataStep()
+	{
+	}
+
+	
+void CTCmsDataStep::doTestL()
+	{
+	__UHEAP_MARK;
+	CCmsContentInfo* content=CCmsContentInfo::NewL(EContentTypeData, *iDataContent);
+	CleanupStack::PushL(content);
+	CASN1EncSequence* contentSeq=content->EncodeASN1DERLC();
+	HBufC8* signature=CreateDEREncodingLC(*contentSeq);
+	CleanupStack::Pop(signature);
+	CleanupStack::PopAndDestroy(2, content);
+	CleanupStack::PushL(signature);
+	//OutputResultToFileL(signature->Des());
+
+	TBool r=signature->Compare(*iExpectedEncoding);
+	if (r!=0 && !iIsOOMTest)
+		{
+		INFO_PRINTF1(_L("CMS Data Type Encoding Error"));
+		User::Leave(KErrGeneral);
+		}
+	else
+		{
+		DecodingAndCheckL(*iExpectedEncoding);
+		}
+
+	CleanupStack::PopAndDestroy(signature);	
+	}
+void CTCmsDataStep::DecodingAndCheckL(TDesC8& aRawData)
+	{
+	INFO_PRINTF1(_L("Start CMS Data Type Decoding"));
+	CCmsContentInfo* content=CCmsContentInfo::NewL(aRawData);
+	CleanupStack::PushL(content);
+	if (content->ContentType()!=EContentTypeData)
+		{
+		INFO_PRINTF1(_L("CMS Data Type is not as expected"));
+		User::Leave(KErrGeneral);
+		}
+	else
+		{
+		if (content->ContentData()!=iDataContent->Des())
+			{
+			INFO_PRINTF1(_L("CMS Data Content is not as expected"));
+			User::Leave(KErrGeneral);					
+			}
+		}
+	CleanupStack::PopAndDestroy(content);		
+	}
+//
+// Implementation of CMS Data Test Step
+//
+CTCmsDataDecodingStep::CTCmsDataDecodingStep()
+	{
+	}
+
+CTCmsDataDecodingStep::~CTCmsDataDecodingStep()
+	{
+	}
+
+void CTCmsDataDecodingStep::doTestL()
+	{
+	DecodingAndCheckL(*iExpectedEncoding);	
+	}
+
+
+//
+// Implementation of Signed Data Test Base Step
+//
+CTSignedDataBaseStep::CTSignedDataBaseStep() : iContentType(EContentTypeData), iRsaAlgorithm(ETrue) 
+	{
+	}
+
+CTSignedDataBaseStep::~CTSignedDataBaseStep()
+	{
+	iDecPKCS8Data.ResetAndDestroy();
+	iCertificates.ResetAndDestroy();
+	iSignerInfoVersion.Close();
+	iHashName.Close();
+	iValidateResults.Close();
+	iSignedAttributePresent.Close();
+	iUnSignedAttributePresent.Close();
+	delete iRootCertificate;
+	delete iAdditionalCertificate;
+	delete iAdditionalEncodedCertificate;
+	}
+
+
+TInt CTSignedDataBaseStep::CovertHashNameToAlgorithmId(const TDesC& aHashName)
+	{
+	if (aHashName.Compare(_L("SHA1"))==0)
+		{
+		return ESHA1;	
+		}
+	else if (aHashName.Compare(_L("MD5"))==0)
+			{
+			return EMD5;
+			}
+		 else
+			 {
+			 return EMD2;	
+			 }
+	}
+
+TInt CTSignedDataBaseStep::CovertCertificateNameToCertificateType(const TDesC& aCertificateName)
+	{
+	if (aCertificateName.Compare(_L("X509"))==0)
+		{
+		return CCmsCertificateChoice::ECertificateX509;	
+		}
+	else if (aCertificateName.Compare(_L("Attribute"))==0)
+			{
+			return CCmsCertificateChoice::ECertificateAttribute;
+			}
+		 else
+			 {
+			 return CCmsCertificateChoice::ECertificateExtendedCerificate;	
+			 }
+	}
+
+
+TVerdict CTSignedDataBaseStep::doTestStepPreambleL()
+	{
+	if (CTCmsBaseStep::doTestStepPreambleL()==EFail)
+		{
+		SetTestStepResult(EFail);
+		}
+	else
+		{
+		//Read the configurations
+		GetBoolFromConfig(ConfigSection(), _L("HashAvailable"), iIsHashAvailable);
+		GetBoolFromConfig(ConfigSection(), _L("DataDetached"), iIsDetached);
+		GetBoolFromConfig(ConfigSection(), _L("CertificateSetPresent"), iCertificateSetPresent);
+		GetBoolFromConfig(ConfigSection(), _L("CRLsSetPresent"), iCRLsSetPresent);
+		GetIntFromConfig(ConfigSection(), _L("SignedDataVersion"), iSignedDataVersion);
+		GetIntFromConfig(ConfigSection(), _L("AlgorithmCount"), iAlgorithmCount);
+		GetIntFromConfig(ConfigSection(), _L("CertsCount"), iCertsCount);
+		GetIntFromConfig(ConfigSection(), _L("SignerCount"), iSignerCount);
+		GetBoolFromConfig(ConfigSection(), _L("NoCertSet"), iNoCertSet);
+		GetBoolFromConfig(ConfigSection(), _L("ValidateUsingUserCerts"), iValidateUsingUserCerts);
+		GetBoolFromConfig(ConfigSection(), _L("NoSigning"), iNoSigning);
+		GetBoolFromConfig(ConfigSection(), _L("NoValidationTest"), iNoValidationTest);
+		GetBoolFromConfig(ConfigSection(), _L("TwoStepCreation"), iTwoStepCreation);
+		GetBoolFromConfig(ConfigSection(), _L("ValidationDetachedWithoutInput"), iValidationDetachedWithoutInput);
+		
+
+		HBufC8* certificate = readFileL(_L("RootCertificate"));
+		if (certificate)
+			{
+			CleanupStack::PushL(certificate);
+			iRootCertificate = CX509Certificate::NewL(*certificate);
+			CleanupStack::PopAndDestroy (certificate);
+			}
+
+		certificate = readFileL(_L("AddtionalCertificate"));
+		if (certificate)
+			{
+			CleanupStack::PushL(certificate);
+			iAdditionalCertificate = CX509Certificate::NewL(*certificate);
+			CleanupStack::PopAndDestroy (certificate);			
+			}
+		TPtrC certTypeName;
+		if (GetStringFromConfig(ConfigSection(), _L("AdditionalEncodedCertificateType"), certTypeName))
+			{
+			iAdditionalEncodedCertificateType=CovertCertificateNameToCertificateType(certTypeName);
+			iAdditionalEncodedCertificate=readFileL (_L("AdditionalEncodedCertificate"));				
+			}
+					
+		//Read the certificates, private keys and hash algorithm
+		TInt index(0);
+		
+		TName fKeyName;
+		fKeyName.Format(_L("PrivateKey_%d"), index);
+		
+		TName fCertName;
+		fCertName.Format(_L("Certificate_%d"), index);
+		
+		TName fHashAlgorithmName;
+		fHashAlgorithmName.Format(_L("HashAlgorithm_%d"), index);
+
+		TName fValidationResult;
+		fValidationResult.Format(_L("ValidationResult_%d"), index);
+		
+		TName fSignedAttributePresent;
+		fSignedAttributePresent.Format(_L("SignedAttributePresent_%d"), index);
+		
+		TName fUnSignedAttributePresent;
+		fUnSignedAttributePresent.Format(_L("UnSignedAttributePresent_%d"), index);
+
+		TName fSignerInfoVersion;
+		fSignerInfoVersion.Format(_L("SignerInfoVersion_%d"), index);
+
+		TPtrC hashName;
+		TBool vResult(EFalse);
+		TBool sAP(EFalse);
+		TBool uSAP(EFalse);
+		TInt signerInfoVersion;
+		TPtrC keyName;
+		TPtrC certName;
+		
+		while ( GetStringFromConfig(ConfigSection(), fKeyName, keyName)
+				&& GetStringFromConfig(ConfigSection(), fCertName, certName)
+				&& GetStringFromConfig(ConfigSection(), fHashAlgorithmName, hashName)
+				&& GetBoolFromConfig(ConfigSection(), fValidationResult, vResult)
+				&& GetBoolFromConfig(ConfigSection(), fSignedAttributePresent, sAP)
+				&& GetBoolFromConfig(ConfigSection(), fUnSignedAttributePresent, uSAP)
+				&& GetIntFromConfig(ConfigSection(), fSignerInfoVersion, signerInfoVersion) )
+			{
+			//Construct private keys
+			HBufC8* privateKey(NULL);
+			if ((privateKey=readFileL(fKeyName))!=NULL)
+				{
+				CleanupStack::PushL (privateKey);
+				CDecPKCS8Data* pkcs8Data=TASN1DecPKCS8::DecodeDERL(privateKey->Des());
+				CleanupStack::PushL (pkcs8Data);
+				iDecPKCS8Data.AppendL(pkcs8Data);
+				CleanupStack::Pop(pkcs8Data);
+				CleanupStack::PopAndDestroy(privateKey);	
+				}
+			
+			//Construct X509 certificate
+			HBufC8* cert(NULL);
+			if ((cert=readFileL(fCertName))!=NULL)
+				{
+				CleanupStack::PushL (cert);
+				CX509Certificate* x509cert=CX509Certificate::NewLC(cert->Des());		
+				iCertificates.AppendL(x509cert);
+				CleanupStack::Pop(x509cert);
+				CleanupStack::PopAndDestroy(cert);				
+				}
+				
+			TInt hashId=CovertHashNameToAlgorithmId(hashName);		
+			iHashName.AppendL(hashId);
+					
+			iValidateResults.AppendL(vResult);
+			iSignedAttributePresent.AppendL(sAP);
+			iUnSignedAttributePresent.AppendL(uSAP);
+			iSignerInfoVersion.AppendL(signerInfoVersion);
+			
+			//for next pair
+			index++;
+			fKeyName.Format(_L("PrivateKey_%d"), index);
+			fCertName.Format(_L("Certificate_%d"), index);
+			fHashAlgorithmName.Format(_L("HashAlgorithm_%d"), index);
+			fValidationResult.Format(_L("ValidationResult_%d"), index);
+			fSignedAttributePresent.Format(_L("SignedAttributePresent_%d"), index);
+			fUnSignedAttributePresent.Format(_L("UnSignedAttributePresent_%d"), index);
+			fSignerInfoVersion.Format(_L("SignerInfoVersion_%d"), index);
+			}			
+		}
+	return TestStepResult();
+	}
+
+CMessageDigest* CTSignedDataBaseStep::CreateHashLC(TAlgorithmId aAlgorithmId)
+	{
+	CMessageDigest* hash(NULL);
+	switch (aAlgorithmId)
+		{
+	case EMD2:
+		hash=CMD2::NewL();
+		break;
+		
+	case EMD5:
+		hash=CMD5::NewL();
+		break;
+		
+	case ESHA1:
+		hash=CSHA1::NewL();
+		break;
+		
+	default:
+		User::Leave(KErrNotSupported);
+		}
+	CleanupStack::PushL(hash);
+	return hash;		
+	}
+
+
+//
+// Implementation of CMS Signed Data Test Step
+//
+CTCmsSignedDataStep::CTCmsSignedDataStep()
+	{
+	}
+
+CTCmsSignedDataStep::~CTCmsSignedDataStep()
+	{
+	}
+
+
+void CTCmsSignedDataStep::CheckAndValidateSignedDataL(TDesC8& aRawData)
+	{
+	//Decode the content info encoding read from predefined file	
+	CCmsContentInfo* content=CCmsContentInfo::NewL(aRawData);
+	CleanupStack::PushL(content);
+	if (content->ContentType()!=EContentTypeSignedData)
+		{
+		INFO_PRINTF1(_L("Content Type is not Signed Data"));
+		User::Leave(KErrGeneral);
+		}
+	else
+		{
+		//Decode the signed data and check the fields
+		CCmsSignedObject* signedData=CCmsSignedObject::NewL(*content);
+		CleanupStack::PushL(signedData);	
+		CheckSignedDataFieldsL(*signedData);
+		
+		//Validate the signatures
+		const RPointerArray<CCmsSignerInfo>& signerInfos=signedData->SignerInfo();
+		CheckSignerInfoFieldsL(signerInfos);
+		
+		if (!iNoValidationTest)
+			{
+			TInt count=signerInfos.Count();
+			for (TInt i=0;i<count;i++)
+				{
+				HBufC8* certificateEncoding = NULL;
+				
+				CMessageDigest* hash(NULL);
+				if (iIsHashAvailable)
+					{
+					hash=CreateHashLC((TAlgorithmId)iHashName[i]);
+					}
+					
+				TBool isValid(EFalse);
+				if (iValidateUsingUserCerts)
+					{
+					INFO_PRINTF1(_L("Test validation by using given certificates"));
+					if (iIsHashAvailable)
+						{
+						isValid = signedData->ValidateSignerLC(*signerInfos[i], iCertificates, certificateEncoding, ETrue, hash->Hash(iDataContent->Des()));
+						}
+					else 
+						{
+						if (iIsDetached)
+							{
+							if (!iValidationDetachedWithoutInput)
+								{
+								isValid = signedData->ValidateSignerLC(*signerInfos[i], iCertificates, certificateEncoding, EFalse, iDataContent->Des());
+								}
+							else
+								{
+								isValid = signedData->ValidateSignerLC(*signerInfos[i], iCertificates, certificateEncoding);	
+								}							
+							}
+						else
+							{
+							isValid = signedData->ValidateSignerLC(*signerInfos[i], iCertificates, certificateEncoding);	
+							}
+						}					
+					}
+				else
+					{
+					INFO_PRINTF1(_L("Test validation by using the embedded certificates"));
+					
+					if (iIsHashAvailable)
+						{
+						isValid = signedData->ValidateSignerLC(*signerInfos[i], certificateEncoding, ETrue, hash->Hash(iDataContent->Des()));
+						}
+					else 
+						{
+						if (iIsDetached)
+							{
+							if (!iValidationDetachedWithoutInput)
+								{
+								isValid = signedData->ValidateSignerLC(*signerInfos[i], certificateEncoding, EFalse, iDataContent->Des());	
+								}
+							else
+								{
+								isValid = signedData->ValidateSignerLC(*signerInfos[i], certificateEncoding);	
+								}
+							}
+						else
+							{
+							isValid = signedData->ValidateSignerLC(*signerInfos[i], certificateEncoding);	
+							}
+						}					
+					}
+									
+				if (!isValid)
+					{
+					INFO_PRINTF1(_L("Couldn't validate signer"));
+					}
+				else
+					{
+					CActiveScheduler* sched = NULL;
+					if (CActiveScheduler::Current() == NULL)
+						{
+						INFO_PRINTF1(_L("Installing scheduler"));
+						sched = new (ELeave) CActiveScheduler();
+						CleanupStack::PushL (sched);
+						CActiveScheduler::Install (sched);
+						}
+					RPointerArray<CX509Certificate> roots (&iRootCertificate, 1);
+					CPKIXCertChain * chain = CPKIXCertChain::NewLC(iFs, *certificateEncoding, roots);
+					
+					TTime tm;
+					_LIT(KDateCorrect1,"20061128:"); 
+					TBuf <24> theDate(KDateCorrect1); 
+					TInt err=tm.Set(theDate); 
+					if(err)
+						{
+						tm.HomeTime();
+						}
+						
+					CPKIXValidationResult* result = CPKIXValidationResult::NewLC();
+					CTPKCS7Validator* validator = new (ELeave) CTPKCS7Validator (chain, result, &tm);
+					validator->doValidate ();
+					sched->Start ();
+					if (result->Error().iReason == EValidatedOK)
+						{
+						isValid = ETrue;
+						INFO_PRINTF1(_L("Validation success"));
+						}
+					else
+						{
+						isValid = EFalse;
+						INFO_PRINTF2(_L("Validation failed: %d"), result->Error().iReason);
+						}
+	        		delete validator;
+					CleanupStack::PopAndDestroy(result);
+					CleanupStack::PopAndDestroy(chain);
+					if (sched)
+						{
+						CActiveScheduler::Install (NULL);
+						CleanupStack::PopAndDestroy (sched);
+						}
+					}
+				
+				CleanupStack::PopAndDestroy(certificateEncoding);				
+				if (hash)
+					{
+					CleanupStack::PopAndDestroy(hash);	
+					}				
+				
+				if (isValid!=iValidateResults[i])
+					{
+					INFO_PRINTF1(_L("validate result not as expected"));
+					User::Leave(KErrGeneral);
+					}
+				}			
+			}
+		CleanupStack::PopAndDestroy(signedData);
+		}
+	CleanupStack::PopAndDestroy(content);						
+	}
+
+void CTCmsSignedDataStep::CheckEncapsulatedContentFieldsL(const CEncapsulatedContentInfo& aEncapContentInfo)
+	{
+	if (aEncapContentInfo.ContentType()!=EContentTypeData)
+		{
+		INFO_PRINTF1(_L("Encapsulated data Content is not data content type"));
+		User::Leave(KErrGeneral);
+		}
+	else
+		{
+		if (aEncapContentInfo.IsContentDataPresent() == iIsDetached)
+			{
+			INFO_PRINTF1(_L("Encapsulated data Content attachment not as expected"));
+			User::Leave(KErrGeneral);
+			}
+		else
+			{
+			if (aEncapContentInfo.IsContentDataPresent() && aEncapContentInfo.ContentData()!=*iDataContent)
+				{
+				INFO_PRINTF1(_L("Encapsulated data Content not as expected"));
+				User::Leave(KErrGeneral);
+				}
+			}
+		}		
+	}
+
+void CTCmsSignedDataStep::CheckAlgorithmSetFieldsL(const RPointerArray<CX509AlgorithmIdentifier>& aAlgorithms)
+	{
+	if (iAlgorithmCount!=aAlgorithms.Count())
+		{
+		INFO_PRINTF1(_L("Number of Algorithm ID is not as expected"));
+		User::Leave(KErrGeneral);
+		}
+	}
+
+void CTCmsSignedDataStep::CheckCertificateSetFieldsL(const CCmsSignedObject& aSignedData)
+	{
+	if (aSignedData.IsCertificateSetPresent())
+		{
+		const RPointerArray<CCmsCertificateChoice>& certSet=aSignedData.Certificates();
+		if (iCertsCount!=certSet.Count())
+			{
+			INFO_PRINTF1(_L("Number of Certificates is not as expected"));
+			User::Leave(KErrGeneral);
+			}
+		else
+			{
+			//Signer Certificate is in the Signed data
+			if (!iNoCertSet)
+				{
+				TInt count = iCertificates.Count();
+				for (TInt i=0;i<count;i++)
+					{
+					if (certSet[i]->CertificateType()==CCmsCertificateChoice::ECertificateX509 && !iCertificates[i]->IsEqualL(certSet[i]->Certificate()))
+						{
+						INFO_PRINTF2(_L("X509 Certificates %d is not as expected"), i);
+						User::Leave(KErrGeneral);						
+						}
+					}
+				}
+			
+			if (iAdditionalCertificate || iAdditionalEncodedCertificate)
+				{
+				if (certSet[iCertsCount-1]->CertificateType()==CCmsCertificateChoice::ECertificateAttribute && 
+						certSet[iCertsCount-1]->AttributeCertificate()->Compare(*iAdditionalEncodedCertificate)!=0)
+					{
+					INFO_PRINTF1(_L("Additional Attribute Certificates is not as expected"));
+					User::Leave(KErrGeneral);						
+					}
+				else if (certSet[iCertsCount-1]->CertificateType()==CCmsCertificateChoice::ECertificateX509)
+						{
+						if (iAdditionalCertificate && !certSet[iCertsCount-1]->Certificate().IsEqualL(*iAdditionalCertificate))
+							{
+							INFO_PRINTF1(_L("Additional X509 Certificates is not as expected"));
+							User::Leave(KErrGeneral);																					
+							}
+						else
+							{
+							if (iAdditionalEncodedCertificate)
+								{
+								CX509Certificate* addX509Cert=CX509Certificate::NewLC(*iAdditionalEncodedCertificate);
+								if (!certSet[iCertsCount-1]->Certificate().IsEqualL(*addX509Cert))
+									{
+									INFO_PRINTF1(_L("Additional X509 Certificates is not as expected"));
+									User::Leave(KErrGeneral);										
+									}
+								CleanupStack::PopAndDestroy(addX509Cert);
+								}
+							}
+						}
+				}
+			}
+		}
+	}
+
+void CTCmsSignedDataStep::CheckSignerInfoFieldsL(const RPointerArray<CCmsSignerInfo>& signerInfos)
+	{
+	TInt count=signerInfos.Count();
+	if (iDecPKCS8Data.Count()!=count && iSignerCount!=count)
+		{
+		INFO_PRINTF1(_L("Number of Signer Info is not as expected"));
+		User::Leave(KErrGeneral);
+		}
+	for (TInt i=0;i<count;i++)
+		{
+		if (signerInfos[i]->IsSignedAttributesPresent()!=iSignedAttributePresent[i]
+			|| signerInfos[i]->IsUnsignedAttributesPresent()!=iUnSignedAttributePresent[i]
+			|| signerInfos[i]->Version()!=iSignerInfoVersion[i])
+			{
+			INFO_PRINTF1(_L("Signed or Unsigned Attribute presence or Signer Version is not as expected"));
+			User::Leave(KErrGeneral);
+			}
+			
+		const CX509AlgorithmIdentifier& digestId=signerInfos[i]->DigestAlgorithm();
+		if (digestId.Algorithm()!=(TAlgorithmId)iHashName[i])
+			{
+			INFO_PRINTF1(_L("Digest Algorithm ID is not as expected"));
+			User::Leave(KErrGeneral);
+			}
+			
+		const CX509AlgorithmIdentifier& sigId=signerInfos[i]->SignatureAlgorithm();
+		if (iDecPKCS8Data[i]->Algorithm()!=sigId.Algorithm())
+			{
+			INFO_PRINTF1(_L("Signature Algorithm ID is not as expected"));
+			User::Leave(KErrGeneral);
+			}
+			
+		const CCmsSignerIdentifier& signerId=signerInfos[i]->SignerIdentifier();
+		if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber)
+			{
+			if (!iCertificates[i]->IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName()))
+				{
+				INFO_PRINTF1(_L("Issuer name is not as expected"));
+				User::Leave(KErrGeneral);
+				}
+			else
+				{
+				RInteger sn1=RInteger::NewL(iCertificates[i]->SerialNumber());
+				CleanupClosePushL(sn1);
+				RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber());
+				CleanupClosePushL(sn2);
+				if (sn1!=sn2)
+					{
+					INFO_PRINTF1(_L("Serial number is not as expected"));
+					User::Leave(KErrGeneral);					
+					}
+				CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1
+					
+				}
+			}
+		else if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::ESubjectKeyIdentifier)
+				{
+				const CX509CertExtension* certExt = iCertificates[i]->Extension(KSubjectKeyId);
+				if (certExt)
+					{
+					CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data());
+					if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())!=0)
+						{
+						INFO_PRINTF1(_L("Subject Key Id is not as expected"));
+						User::Leave(KErrGeneral);
+						}
+					CleanupStack::PopAndDestroy(ext);
+					}
+				}
+		}
+	}
+
+void CTCmsSignedDataStep::CheckSignedDataFieldsL(const CCmsSignedObject& aSignedData)
+	{		
+	if (aSignedData.IsCertificateSetPresent()!=iCertificateSetPresent ||
+		aSignedData.IsCertificateRevocationListsPresent()!=iCRLsSetPresent ||
+		aSignedData.Version()!=iSignedDataVersion)
+		{
+		INFO_PRINTF1(_L("cert present or CRL present or version not as expected"));
+		User::Leave(KErrGeneral);
+		}
+	else
+		{
+		const CEncapsulatedContentInfo& encapContentInfo=aSignedData.ContentInfo();
+		CheckEncapsulatedContentFieldsL(encapContentInfo);
+		const RPointerArray<CX509AlgorithmIdentifier>& algorithms=aSignedData.DigestAlgorithms();
+		CheckAlgorithmSetFieldsL(algorithms);
+		CheckCertificateSetFieldsL(aSignedData);
+		}
+	}
+
+void CTCmsSignedDataStep::doTestL()
+	{
+	__UHEAP_MARK;
+	
+	CCmsSignedObject* signedData(NULL);
+	TInt count=iDecPKCS8Data.Count();
+	
+	//Create Signed Object
+	for (TInt i=0;i<count;i++)
+		{
+		//Get the key pair
+		CDecPKCS8Data* decPKCS8Data=iDecPKCS8Data[i];
+		MPKCS8DecodedKeyPairData* keyPair = decPKCS8Data->KeyPairData();
+		
+		CMessageDigest* hash(NULL);
+		TPtrC8 hashValue;
+		if (iIsHashAvailable)
+			{
+			hash=CreateHashLC((TAlgorithmId)iHashName[i]);
+			hashValue.Set(hash->Hash(iDataContent->Des()));
+			}
+		
+		//If it is the first time, a signed object needs to be created
+		if (i==0)
+			{
+			if (iIsHashAvailable)
+				{
+				if (decPKCS8Data->Algorithm()==ERSA)
+					{
+					const CRSAPrivateKey& RSAPrivateKey=static_cast<CPKCS8KeyPairRSA*>(keyPair)->PrivateKey();
+					if (!iTwoStepCreation)
+						{
+						signedData=CCmsSignedObject::NewL((TCmsContentInfoType)iContentType,
+															hashValue,
+															(TAlgorithmId)iHashName[i],
+															RSAPrivateKey,
+															*iCertificates[i],
+															!iNoCertSet);
+						CleanupStack::PushL(signedData);																
+						}
+					else
+						{
+						signedData=CCmsSignedObject::NewL((TCmsContentInfoType)iContentType, iIsDetached, iDataContent->Des());
+						CleanupStack::PushL(signedData);
+						signedData->SignL(hashValue, (TAlgorithmId)iHashName[i], RSAPrivateKey, *iCertificates[i], !iNoCertSet);
+						}
+					}
+				else
+					{
+					const CDSAPrivateKey& DSAPrivateKey=static_cast<CPKCS8KeyPairDSA*>(keyPair)->PrivateKey();
+					if (!iTwoStepCreation)
+						{
+						signedData=CCmsSignedObject::NewL((TCmsContentInfoType)iContentType,
+															hashValue,
+															(TAlgorithmId)iHashName[i],
+															DSAPrivateKey,
+															*iCertificates[i],
+															!iNoCertSet);
+						CleanupStack::PushL(signedData);																	
+						}
+					else
+						{
+						signedData=CCmsSignedObject::NewL((TCmsContentInfoType)iContentType, iIsDetached, iDataContent->Des());
+						CleanupStack::PushL(signedData);
+						signedData->SignL(hashValue, (TAlgorithmId)iHashName[i], DSAPrivateKey, *iCertificates[i], !iNoCertSet);
+						}
+					iRsaAlgorithm=EFalse;			
+					}
+				CleanupStack::Pop(signedData);	
+				CleanupStack::PopAndDestroy(hash);
+				CleanupStack::PushL(signedData);
+				}		
+			else
+				{
+				signedData=CCmsSignedObject::NewL((TCmsContentInfoType)iContentType, iIsDetached, iDataContent->Des());
+				CleanupStack::PushL(signedData);
+				if (!iNoSigning)
+					{
+					if (decPKCS8Data->Algorithm()==ERSA)
+						{
+						const CRSAPrivateKey& RSAPrivateKey=static_cast<CPKCS8KeyPairRSA*>(keyPair)->PrivateKey();
+						signedData->SignL(KNullDesC8, (TAlgorithmId)iHashName[i], RSAPrivateKey, *iCertificates[i], !iNoCertSet);
+						}
+					else
+						{
+						const CDSAPrivateKey& DSAPrivateKey=static_cast<CPKCS8KeyPairDSA*>(keyPair)->PrivateKey();
+						signedData->SignL(KNullDesC8, (TAlgorithmId)iHashName[i], DSAPrivateKey, *iCertificates[i], !iNoCertSet);
+						iRsaAlgorithm=EFalse;
+						}												
+					}
+				}
+			}
+		else
+			{
+			//multiple signatures
+			if (iIsHashAvailable)
+				{
+				if (decPKCS8Data->Algorithm()==ERSA)
+					{
+					const CRSAPrivateKey& RSAPrivateKey=static_cast<CPKCS8KeyPairRSA*>(keyPair)->PrivateKey();
+					signedData->SignL(hashValue, (TAlgorithmId)iHashName[i], RSAPrivateKey, *iCertificates[i], !iNoCertSet);
+					}
+				else
+					{
+					const CDSAPrivateKey& DSAPrivateKey=static_cast<CPKCS8KeyPairDSA*>(keyPair)->PrivateKey();
+					signedData->SignL(hashValue, (TAlgorithmId)iHashName[i], DSAPrivateKey, *iCertificates[i], !iNoCertSet);
+					iRsaAlgorithm=EFalse;
+					}
+				CleanupStack::PopAndDestroy(hash);	
+				}
+			else
+				{
+				if (decPKCS8Data->Algorithm()==ERSA)
+					{
+					const CRSAPrivateKey& RSAPrivateKey=static_cast<CPKCS8KeyPairRSA*>(keyPair)->PrivateKey();
+					signedData->SignL(KNullDesC8, (TAlgorithmId)iHashName[i], RSAPrivateKey, *iCertificates[i], !iNoCertSet);
+					}
+				else
+					{
+					const CDSAPrivateKey& DSAPrivateKey=static_cast<CPKCS8KeyPairDSA*>(keyPair)->PrivateKey();
+					signedData->SignL(KNullDesC8, (TAlgorithmId)iHashName[i], DSAPrivateKey, *iCertificates[i], !iNoCertSet);
+					iRsaAlgorithm=EFalse;
+					}						
+				}
+			}	
+		}
+	
+	if (iAdditionalCertificate)
+		{
+		signedData->AddCertificateL(*iAdditionalCertificate);	
+		}
+
+ 	if (iAdditionalEncodedCertificate)
+ 		{
+ 		signedData->AddCertificateL(*iAdditionalEncodedCertificate, (CCmsCertificateChoice::TCertificateType)iAdditionalEncodedCertificateType);
+ 		}
+		
+	//Encoding the Signed object
+	CASN1EncSequence* signedObjectSeq=signedData->EncodeASN1DERLC();
+	HBufC8* buf=CreateDEREncodingLC(*signedObjectSeq);
+
+	//Encoding the wrapper Content Info
+	CCmsContentInfo* content=CCmsContentInfo::NewL(EContentTypeSignedData, *buf);
+	CleanupStack::PushL(content);
+	CASN1EncSequence* contentSeq=content->EncodeASN1DERLC();
+	HBufC8* signature=CreateDEREncodingLC(*contentSeq);
+	CleanupStack::Pop(signature);
+	CleanupStack::PopAndDestroy(5, signedData);	//contentSeq,content,buf,signedObjectSeq,signedData
+	CleanupStack::PushL(signature);
+
+
+	//write the result to a file, for initial debuging
+	//OutputResultToFileL(signature->Des());
+	
+	//Compare the result with the expected result, if the signature algorithms are RSA
+		
+	if (iRsaAlgorithm)
+		{
+		
+		//Check if the signature is the same as expected
+		TBool r=signature->Compare(*iExpectedEncoding);
+		if (r!=0 && !iIsOOMTest)
+			{
+			INFO_PRINTF1(_L("RSA Signature Encoding Error"));
+			User::Leave(KErrGeneral);
+			}
+		else
+			{
+			CheckAndValidateSignedDataL(*iExpectedEncoding);
+			}
+		}
+	else	
+		{
+		CheckAndValidateSignedDataL(*iExpectedEncoding);
+		CheckAndValidateSignedDataL(*signature);		
+		}	
+			
+	CleanupStack::PopAndDestroy(signature);
+	__UHEAP_MARKEND;
+	}
+
+//
+// Implementation of CMS Signed Data Decoding Test Step
+//
+
+CTCmsSignedDataDecodingStep::CTCmsSignedDataDecodingStep()
+	{
+	}
+
+CTCmsSignedDataDecodingStep::~CTCmsSignedDataDecodingStep()
+	{
+	}
+
+void CTCmsSignedDataDecodingStep::doTestL()
+	{
+	__UHEAP_MARK;
+	CheckAndValidateSignedDataL(*iExpectedEncoding);
+	__UHEAP_MARKEND;
+	}
+
+//
+// Implementation of CMS Content Info Test step
+//
+CTCmsContentInfoDecodingStep::CTCmsContentInfoDecodingStep()
+	{	
+	}
+
+CTCmsContentInfoDecodingStep::~CTCmsContentInfoDecodingStep()
+	{	
+	}
+	
+void CTCmsContentInfoDecodingStep::doTestL()
+	{
+	INFO_PRINTF1(_L("Start CMS Data Type Decoding"));
+	CCmsContentInfo* content=CCmsContentInfo::NewL(*iExpectedEncoding);
+	CleanupStack::PushL(content);
+	if (content->ContentType()!=iExpectedDataType)
+		{
+		INFO_PRINTF1(_L("CMS Data Type is not as expected"));
+		User::Leave(KErrGeneral);
+		}
+	CleanupStack::PopAndDestroy(content);		
+	}