cms/src/CCMSSignedData.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:20:08 +0200
changeset 0 164170e6151a
permissions -rw-r--r--
Revision: 201004

/*
* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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 FILES
#include <x500dn.h>
#include <asn1dec.h>
#include <asn1enc.h>

#include "CCMSSignedData.h"

// CONSTANTS
const TInt KMinNumberOfSubModules = 4;
const TInt KMaxNumberOfSubModules = 6;
const TInt KDefaultGranularity = 1;
const TInt KDefaultVersion = 1;
const TInt KAlternativeVersion = 3;
const TUint8 KCertificateSetTag = 0;
const TUint8 KRevokedCertificatesTag = 1;

// Defaulta id-data oid
_LIT( KIDDataOID, "1.2.840.113549.1.7.1" );

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CCMSSignedData::CCMSSignedData
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMSSignedData::CCMSSignedData()
    {
    }

// -----------------------------------------------------------------------------
// CCMSSignedData::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
EXPORT_C void CCMSSignedData::ConstructL()
    {
	iVersion = KDefaultVersion;
	iDigestAlgorithmIdentifiers =
				new( ELeave )CArrayPtrFlat< CCMSX509AlgorithmIdentifier >
														( KDefaultGranularity );
	iContentInfo = CCMSEncapsulatedContentInfo::NewLC();
	CleanupStack::Pop( iContentInfo );
	iSignerInfos =
				new( ELeave )CArrayPtrFlat< CCMSSignerInfo >
														( KDefaultGranularity );
    }

// -----------------------------------------------------------------------------
// CCMSSignedData::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
EXPORT_C void CCMSSignedData::ConstructL(
	const CArrayPtr< CCMSX509AlgorithmIdentifier >& aDigestAlgorithmIdentifiers,
   	const CCMSEncapsulatedContentInfo& aContentInfo,
   	const CArrayPtr< CCMSSignerInfo >& aSignerInfos,
   	const CArrayPtr< CCMSCertificateChoices >* aCertificates,
   	const CArrayPtr< CCMSX509CertificateList >* aRevokedCertificates )
    {
	SetSignerInfosL( aSignerInfos );
	SetDigestAlgorithmIdentifiersL( aDigestAlgorithmIdentifiers );
	SetEncapsulatedContentInfoL( aContentInfo );

	SetCertificatesL( aCertificates );
	SetRevokedCertificatesL( aRevokedCertificates );
    }

// -----------------------------------------------------------------------------
// CCMSSignedData::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMSSignedData* CCMSSignedData::NewLC()
	{
	CCMSSignedData* self = new( ELeave ) CCMSSignedData();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMSSignedData* CCMSSignedData::NewLC(
	const CArrayPtr< CCMSX509AlgorithmIdentifier >& aDigestAlgorithmIdentifiers,
   	const CCMSEncapsulatedContentInfo& aContentInfo,
   	const CArrayPtr< CCMSSignerInfo >& aSignerInfos )
    {
    CCMSSignedData* self = new( ELeave ) CCMSSignedData();
    CleanupStack::PushL( self );
    self->ConstructL( aDigestAlgorithmIdentifiers,
    				  aContentInfo,
    				  aSignerInfos,
    				  NULL,
    				  NULL );
    return self;
    }

// -----------------------------------------------------------------------------
// CCMSSignedData::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CCMSSignedData* CCMSSignedData::NewLC(
	const CArrayPtr< CCMSX509AlgorithmIdentifier >& aDigestAlgorithmIdentifiers,
   	const CCMSEncapsulatedContentInfo& aContentInfo,
   	const CArrayPtr< CCMSSignerInfo >& aSignerInfos,
   	const CArrayPtr< CCMSCertificateChoices >* aCertificates,
   	const CArrayPtr< CCMSX509CertificateList >* aRevokedCertificates )
    {
    CCMSSignedData* self = new( ELeave ) CCMSSignedData();
    CleanupStack::PushL( self );
    self->ConstructL( aDigestAlgorithmIdentifiers,
    				  aContentInfo,
    				  aSignerInfos,
    				  aCertificates,
    				  aRevokedCertificates );
    return self;
    }

// Destructor
CCMSSignedData::~CCMSSignedData()
    {
	if( iDigestAlgorithmIdentifiers )
		{
		iDigestAlgorithmIdentifiers->ResetAndDestroy();
		delete iDigestAlgorithmIdentifiers;
		}
	delete iContentInfo;
	if( iSignerInfos )
		{
		iSignerInfos->ResetAndDestroy();
		delete iSignerInfos;
		}
	if( iCertificates )
		{
		iCertificates->ResetAndDestroy();
		delete iCertificates;
		}
	if( iRevokedCertificates )
		{
		iRevokedCertificates->ResetAndDestroy();
		delete iRevokedCertificates;
		}
    }

// -----------------------------------------------------------------------------
// CCMSSignedData::DecodeL
// Decrypts raw data to this instance
// -----------------------------------------------------------------------------
void CCMSSignedData::DecodeL( const TDesC8& aRawData )
	{
	CArrayPtr<TASN1DecGeneric>* itemsData =
							DecodeSequenceLC( aRawData,
											  KMinNumberOfSubModules,
											  KMaxNumberOfSubModules );
	TInt pos = 0;
	// decode Version
	TASN1DecInteger version;
	TInt tmpVersion;
	tmpVersion = version.DecodeDERShortL( *itemsData->At( pos++ ) );

	// decode digest algorithms
	CArrayPtrFlat< CCMSX509AlgorithmIdentifier >* tmpAlgs =
		new( ELeave )CArrayPtrFlat< CCMSX509AlgorithmIdentifier >
													( KDefaultGranularity );
	CleanupStack::PushL( tmpAlgs );
	CleanupResetAndDestroyPushL( *tmpAlgs );

	//there must be atleast 1 algorithm
	CArrayPtr<TASN1DecGeneric>* digestAlgorithms =
		DecodeSequenceLC( itemsData->At( pos++ )->Encoding(),
						  1,
						  KMaxTInt );
	TInt algCount = digestAlgorithms->Count();
	for( TInt i = 0; i < algCount; i++ )
		{
		CCMSX509AlgorithmIdentifier* alg =
										CCMSX509AlgorithmIdentifier::NewL();
		CleanupStack::PushL( alg );
		alg->DecodeL( digestAlgorithms->At( i )->Encoding() );
		tmpAlgs->AppendL( alg );
		CleanupStack::Pop( alg );
		}
	CleanupStack::PopAndDestroy( digestAlgorithms );

	// decode encapsulated content info
	CCMSEncapsulatedContentInfo* tmpInfo = CCMSEncapsulatedContentInfo::NewLC();
	tmpInfo->DecodeL( itemsData->At( pos++ )->Encoding() );

	CArrayPtrFlat< CCMSCertificateChoices >* tmpCerts = NULL;

	// decode possible certificate set
	if( itemsData->At( pos )->Tag() == KCertificateSetTag )
		{
		tmpCerts =
			new( ELeave )CArrayPtrFlat< CCMSCertificateChoices >
													( KDefaultGranularity );
		CleanupStack::PushL( tmpCerts );
		CleanupResetAndDestroyPushL( *tmpCerts );
		TASN1DecSequence decSeq;
		CArrayPtr<TASN1DecGeneric>* certs =
			decSeq.DecodeDERLC( *itemsData->At( pos++ ) );
		TInt certCount = certs->Count();
		for( TInt i = 0; i < certCount; i++ )
			{
			CCMSCertificateChoices* tmpCert =
				CCMSCertificateChoices::NewLC();
			tmpCert->DecodeL( certs->At( i )->Encoding() );
			tmpCerts->AppendL( tmpCert );
			CleanupStack::Pop( tmpCert );
			}
		CleanupStack::PopAndDestroy( certs );
		}

	// decode possible revoked certificates
	CArrayPtrFlat< CCMSX509CertificateList >* tmpRevokedCertificates = NULL;
	if( ( pos < itemsData->Count() ) &&
		( itemsData->At( pos )->Tag() == KRevokedCertificatesTag ) )
		{
		tmpRevokedCertificates =
			new( ELeave )CArrayPtrFlat< CCMSX509CertificateList >
													( KDefaultGranularity );
		CleanupStack::PushL( tmpRevokedCertificates );
		CleanupResetAndDestroyPushL( *tmpRevokedCertificates );

		TASN1DecSequence decSeq;
		CArrayPtr<TASN1DecGeneric>* certs =
			decSeq.DecodeDERLC( *itemsData->At( pos++ ) );

		TInt certCount = certs->Count();
		for( TInt i = 0; i < certCount; i++ )
			{
			CCMSX509CertificateList* tmpCert = CCMSX509CertificateList::NewLC();
			tmpCert->DecodeL( certs->At( i )->Encoding() );
			tmpRevokedCertificates->AppendL( tmpCert );
			CleanupStack::Pop( tmpCert );
			}
		CleanupStack::PopAndDestroy( certs );
		}

	// decode Signer Infos
	if( pos >= itemsData->Count() )
		{
		// Missing mandatory signer infos
		User::Leave( KErrArgument );
		}

	CArrayPtrFlat< CCMSSignerInfo >* tmpSignerInfos =
		new( ELeave )CArrayPtrFlat< CCMSSignerInfo >( KDefaultGranularity );
	CleanupStack::PushL( tmpSignerInfos );
	CleanupResetAndDestroyPushL( *tmpSignerInfos );

	CArrayPtr<TASN1DecGeneric>* sInfos =
		DecodeSequenceLC( itemsData->At( pos )->Encoding() );

	TInt sInfoCount = sInfos->Count();
	for( TInt j = 0; j < sInfoCount; j++ )
		{
		CCMSSignerInfo* tmpInfo = CCMSSignerInfo::NewL();
		CleanupStack::PushL( tmpInfo );
		tmpInfo->DecodeL( sInfos->At( j )->Encoding() );
		tmpSignerInfos->AppendL( tmpInfo );
		CleanupStack::Pop( tmpInfo );
		}
	CleanupStack::PopAndDestroy( sInfos );

	// All done, setting new values
	iSignerInfos->ResetAndDestroy();
	delete iSignerInfos;
	iSignerInfos = tmpSignerInfos;

	CleanupStack::Pop( tmpSignerInfos ); // ResetAndDestroy
	CleanupStack::Pop( tmpSignerInfos ); // Normal cleanup

	if( iRevokedCertificates )
		{
		iRevokedCertificates->ResetAndDestroy();
		delete iRevokedCertificates;
		}
	iRevokedCertificates = tmpRevokedCertificates;
	if( tmpRevokedCertificates )
		{
		CleanupStack::Pop( tmpRevokedCertificates ); // ResetAndDestroy
		CleanupStack::Pop( tmpRevokedCertificates ); // Normal cleanup
		}

	if( iCertificates )
		{
		iCertificates->ResetAndDestroy();
		delete iCertificates;
		}
	iCertificates = tmpCerts;
	if( tmpCerts )
		{
		CleanupStack::Pop( tmpCerts ); // ResetAndDestory
		CleanupStack::Pop( tmpCerts ); // Normal cleanup
		}

	delete iContentInfo;
	iContentInfo = tmpInfo;
	CleanupStack::Pop( tmpInfo );

	iDigestAlgorithmIdentifiers->ResetAndDestroy();
	delete iDigestAlgorithmIdentifiers;
	iDigestAlgorithmIdentifiers = tmpAlgs;
	CleanupStack::Pop( tmpAlgs ); // ResetAndDestroy
	CleanupStack::Pop( tmpAlgs ); // Normal cleanup

	iVersion = tmpVersion;

	CleanupStack::PopAndDestroy( itemsData );
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::EncoderLC
// Returns ASN1 encoder for this instance
// -----------------------------------------------------------------------------

CASN1EncBase* CCMSSignedData::EncoderLC() const
	{
	CASN1EncSequence* root = CASN1EncSequence::NewLC();

	// Add version
	CASN1EncInt* version = CASN1EncInt::NewLC( iVersion );
	root->AddAndPopChildL( version );

	// Add digest algorithms
	CASN1EncSequence* digestAlgorithms = CASN1EncSequence::NewLC();
	digestAlgorithms->SetTag( EASN1Set, EUniversal );
	TInt count = iDigestAlgorithmIdentifiers->Count();
	if( count == 0 )
		{
		// there is no mandatory algorithms
		User::Leave( KErrArgument );
		}
	for( TInt i = 0; i < count; i++ )
		{
		CCMSX509AlgorithmIdentifier* alg =
			iDigestAlgorithmIdentifiers->At( i );
		CASN1EncBase* algEnc = alg->EncoderLC();
		digestAlgorithms->AddAndPopChildL( algEnc );
		}
	root->AddAndPopChildL( digestAlgorithms );

	// add encapsulated content info
	CASN1EncBase* encContentInfo = iContentInfo->EncoderLC();
	root->AddAndPopChildL( encContentInfo );

	// add possible certificates
	if( iCertificates &&
		iCertificates->Count() > 0 )
		{
		CASN1EncSequence* certificates = CASN1EncSequence::NewLC();
		certificates->SetTag( KCertificateSetTag );
		TInt certCount = iCertificates->Count();
		for( TInt i = 0; i < certCount; i++ )
			{
			CCMSCertificateChoices* cert = iCertificates->At( i );
			CASN1EncBase* certEnc = cert->EncoderLC();
			certificates->AddAndPopChildL( certEnc );
			}
		root->AddAndPopChildL( certificates );
		}

	// add possible revoked certificates
	if( iRevokedCertificates &&
		iRevokedCertificates->Count() > 0 )
		{
		CASN1EncSequence* certificates = CASN1EncSequence::NewLC();
		certificates->SetTag( KRevokedCertificatesTag );
		TInt certCount = iRevokedCertificates->Count();
		for( TInt i = 0; i < certCount; i++ )
			{
			CCMSX509CertificateList* list = iRevokedCertificates->At( i );
			CASN1EncBase* rCerts = list->EncoderLC();
			certificates->AddAndPopChildL( rCerts );
			}
		root->AddAndPopChildL( certificates );
		}

	// add signer infos
	CASN1EncSequence* signerInfos = CASN1EncSequence::NewLC();
	signerInfos->SetTag( EASN1Set, EUniversal );
	TInt sCount = iSignerInfos->Count();
	if( sCount == 0 )
		{
		// there is no mandatory signer infos
		User::Leave( KErrArgument );
		}

	for( TInt j = 0; j < sCount; j++ )
		{
		CASN1EncBase* sInfo = iSignerInfos->At( j )->EncoderLC();
		signerInfos->AddAndPopChildL( sInfo );
		}
	root->AddAndPopChildL( signerInfos );
	return root;
	}
// -----------------------------------------------------------------------------
// CCMSSignedData::Version
// Getter for Version
// -----------------------------------------------------------------------------
EXPORT_C TInt CCMSSignedData::Version() const
	{
	return iVersion;
	}
// -----------------------------------------------------------------------------
// CCMSSignedData::DigestAlgorithmIdentifiers
// Getter for DigestAlgorithmIdentifiers
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSX509AlgorithmIdentifier >&
	CCMSSignedData::DigestAlgorithmIdentifiers() const
	{
	return *iDigestAlgorithmIdentifiers;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::EncapsulatedContentInfo
// Getter for EncapsulatedContentInfo
// -----------------------------------------------------------------------------
EXPORT_C const CCMSEncapsulatedContentInfo&
	CCMSSignedData::EncapsulatedContentInfo() const
	{
	return *iContentInfo;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::SignerInfos
// Getter for SignerInfos
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSSignerInfo >&
	CCMSSignedData::SignerInfos() const
	{
	return *iSignerInfos;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::Certificates
// Getter for Certificates
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSCertificateChoices >*
	CCMSSignedData::Certificates() const
	{
	return iCertificates;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::RevokedCertificates
// Getter for RevokedCertificates
// -----------------------------------------------------------------------------
EXPORT_C const CArrayPtr< CCMSX509CertificateList >*
	CCMSSignedData::RevokedCertificates() const
	{
	return iRevokedCertificates;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::SetDigestAlgorithmIdentifiersL
// Setter for DigestAlgorithmIdentifiers, takes copy
// -----------------------------------------------------------------------------
EXPORT_C void CCMSSignedData::SetDigestAlgorithmIdentifiersL(
	const CArrayPtr< CCMSX509AlgorithmIdentifier >& aDigestAlgorithmIdentifiers )
	{
	CArrayPtrFlat< CCMSX509AlgorithmIdentifier >* tmpAlgs =
		new( ELeave )CArrayPtrFlat< CCMSX509AlgorithmIdentifier >( KDefaultGranularity );
	CleanupStack::PushL( tmpAlgs );
	TInt algCount = aDigestAlgorithmIdentifiers.Count();
	for( TInt i = 0; i < algCount; i++ )
		{
		CCMSX509AlgorithmIdentifier* origAlg = aDigestAlgorithmIdentifiers[ i ];
		CCMSX509AlgorithmIdentifier* tmpAlg = NULL;
		if( origAlg->DigestAlgorithm() )
			{
			tmpAlg =
			CCMSX509AlgorithmIdentifier::NewL( origAlg->AlgorithmIdentifier(),
											   *origAlg->DigestAlgorithm() );
			}
		else
			{
			tmpAlg =
			CCMSX509AlgorithmIdentifier::NewL( origAlg->AlgorithmIdentifier() );
			}
		CleanupStack::PushL( tmpAlg );
		tmpAlgs->AppendL( tmpAlg );
		CleanupStack::Pop( tmpAlg );
		}
	delete iDigestAlgorithmIdentifiers;
	iDigestAlgorithmIdentifiers = tmpAlgs;
	CleanupStack::Pop( tmpAlgs );
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::SetEncapsulatedContentInfoL
// Setter for EncapsulatedContentInfo, takes copy
// -----------------------------------------------------------------------------
EXPORT_C void CCMSSignedData::SetEncapsulatedContentInfoL(
	const CCMSEncapsulatedContentInfo& aContentInfo )
	{
	CCMSEncapsulatedContentInfo* copy =
		CCMSEncapsulatedContentInfo::NewLC( aContentInfo.ContentType(),
											aContentInfo.Content() );
	delete iContentInfo;
	iContentInfo = copy;
	CleanupStack::Pop( copy );
	ValidateVersion();
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::SetSignerInfosL
// Setter for SignerInfos, takes copy
// -----------------------------------------------------------------------------
EXPORT_C void CCMSSignedData::SetSignerInfosL(
	const CArrayPtr< CCMSSignerInfo >& aSignerInfos )
	{
	TInt sigCount = aSignerInfos.Count();
	// creating right size array directly, adding 1 to avoid panic in case that
	// sigCount is zero.
	CArrayPtrFlat< CCMSSignerInfo >* tmpSignInfos =
		new( ELeave )CArrayPtrFlat< CCMSSignerInfo >( sigCount + 1 );
	CleanupStack::PushL( tmpSignInfos );
	CleanupResetAndDestroyPushL( *tmpSignInfos );
	for( TInt i = 0; i < sigCount; i++ )
		{
		HBufC8* tmpEncoding;
		aSignerInfos[ i ]->EncodeL( tmpEncoding );
		CleanupStack::PushL( tmpEncoding );
		CCMSSignerInfo* tmpSig = CCMSSignerInfo::NewL();
		CleanupStack::PushL( tmpSig );
		tmpSig->DecodeL( *tmpEncoding );
		tmpSignInfos->AppendL( tmpSig );
		CleanupStack::Pop( tmpSig );
		CleanupStack::PopAndDestroy( tmpEncoding );
		}
	if( iSignerInfos )
		{
		iSignerInfos->ResetAndDestroy();
		delete iSignerInfos;
		}
	iSignerInfos = tmpSignInfos;
	CleanupStack::Pop( tmpSignInfos ); // ResetAndDestroy
	CleanupStack::Pop( tmpSignInfos ); // normal cleanup
	ValidateVersion();
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::SetCertificatesL
// Setter for Certificates, takes copy
// -----------------------------------------------------------------------------
EXPORT_C void CCMSSignedData::SetCertificatesL(
	const CArrayPtr< CCMSCertificateChoices >* aCertificates )
	{
	CArrayPtrFlat< CCMSCertificateChoices >* tmpCertificates = NULL;
	if( aCertificates )
		{
		TInt certCount = aCertificates->Count();
		// creating right size array directly, adding 1 to avoid panic in case 
		// that certCount is zero.
		tmpCertificates =
			new( ELeave )CArrayPtrFlat< CCMSCertificateChoices >( certCount + 1 );
		CleanupStack::PushL( tmpCertificates );
		CleanupResetAndDestroyPushL( *tmpCertificates );
		for( TInt i = 0; i < certCount; i++ )
			{
			CCMSCertificateChoices* copy =
				CCMSCertificateChoices::NewLC();
			CCMSCertificateChoices* orig = aCertificates->At( i );
			if( orig->AttrCert() )
				{
				copy->SetAttrCertL( *orig->AttrCert() );
				}
			else if( orig->Certificate() )
				{
				copy->SetCertificateL( *orig->Certificate() );
				}
			else
				{
				User::Leave( KErrArgument );
				}
			tmpCertificates->AppendL( copy );
			CleanupStack::Pop( copy );
			}
		CleanupStack::Pop( tmpCertificates ); // ResetAndDestroy
		CleanupStack::Pop( tmpCertificates ); // Normal cleanup
		}
	if( iCertificates )
		{
		iCertificates->ResetAndDestroy();
		delete iCertificates;
		}
	iCertificates = tmpCertificates;
	ValidateVersion();
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::SetRevokedCertificatesL
// Setter for RevokedCertificates, takes copy
// -----------------------------------------------------------------------------
EXPORT_C void CCMSSignedData::SetRevokedCertificatesL(
	const CArrayPtr< CCMSX509CertificateList >* aRevokedCertificates )
	{
	CArrayPtrFlat< CCMSX509CertificateList >* tmpCerts = NULL;
	if( aRevokedCertificates )
		{
		TInt certCount = aRevokedCertificates->Count();
		// creating right size array directly, adding 1 to avoid panic in case 
		// that certCount is zero.
		tmpCerts =
			new( ELeave )CArrayPtrFlat< CCMSX509CertificateList >
														( certCount + 1 );
		CleanupStack::PushL( tmpCerts );
		CleanupResetAndDestroyPushL( *tmpCerts );
		for( TInt i = 0; i < certCount; i++ )
			{
			CCMSX509CertificateList* copy =
				CCMSX509CertificateList::NewLC();

			HBufC8* tmpData;
			aRevokedCertificates->At( i )->EncodeL( tmpData );
			CleanupStack::PushL( tmpData );
			copy->DecodeL( *tmpData );
			CleanupStack::PopAndDestroy( tmpData );
			tmpCerts->AppendL( copy );
			CleanupStack::Pop( copy );
			}
		CleanupStack::Pop( tmpCerts ); // ResetAndDestroy
		CleanupStack::Pop( tmpCerts ); // Normal cleanup
		}

	if( iRevokedCertificates )
		{
		iRevokedCertificates->ResetAndDestroy();
		delete iRevokedCertificates;
		}
	iRevokedCertificates = tmpCerts;
	}

// -----------------------------------------------------------------------------
// CCMSSignedData::ValidateVersion
// Validates that iVersion is correct
// -----------------------------------------------------------------------------
void CCMSSignedData::ValidateVersion()
	{
	iVersion = KDefaultVersion;
	// if the encapsulated content type is other than id-data
	// then the value of version shall be 3.
	if( iContentInfo &&
		( iContentInfo->ContentType() != KIDDataOID ) )
		{
		iVersion = KAlternativeVersion;
		return; // no reason to continue
		}

	// if any of the elements of SignerInfos are version 3,
	// then the value of version shall be 3.
	if( iSignerInfos->Count() )
		{
		TInt sigCount = iSignerInfos->Count();
		for( TInt i = 0; i < sigCount; i++ )
			{
			if( iSignerInfos->At( i )->CMSVersion() == KAlternativeVersion )
				{
				iVersion = KAlternativeVersion;
				return; // no reason to continue
				}
			}
		}

	// if attribute certificates are present, the
	// then the value of version shall be 3.
	if( iCertificates )
		{
		TInt certCount = iCertificates->Count();
		for( TInt i = 0; i < certCount; i++ )
			{
			if( iCertificates->At( i )->AttrCert() )
				{
				iVersion = KAlternativeVersion;
				return; // no reason to continue
				}
			}
		}
	}
//  End of File