cryptoservices/certificateandkeymgmt/x509/x509cert.cpp
changeset 8 35751d3474b7
parent 0 2c201484c85f
child 17 cd501b96611d
--- a/cryptoservices/certificateandkeymgmt/x509/x509cert.cpp	Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/certificateandkeymgmt/x509/x509cert.cpp	Thu Sep 10 14:01:51 2009 +0300
@@ -1,1248 +1,1248 @@
-/*
-* Copyright (c) 1998-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: 
-* -- FingerPrint Note:
-* Developers have to be aware that if they are going to change the fingerprint for this certificate
-* for a different hash, then there are other places that need to reflect this change
-* -- Location
-* void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-* EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
-* Also change the CWTLSCertificate and search for other occurences of the current
-* hash.
-* -- TeletexString type support Note:
-* If the certificate has decoded the members from TeletexString then the return value 
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
-* null characters in the second byte of each character. This will work as expected 
-* for cases where the string contains ASCII data.
-*
-*/
-
-
-
-
-#include <x509cert.h>
-#include <x509certext.h>
-#include "X509time.h"
-#include <x509keys.h>
-#include <keyidentifierutil.h>
-#include <asn1enc.h>
-#include <asn1dec.h>
-
-EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
-	{
-	CPKCS1SignatureResult* self = CPKCS1SignatureResult::NewLC(aDigestAlgorithm, aDigest);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewLC(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
-	{
-	CPKCS1SignatureResult* self = new(ELeave) CPKCS1SignatureResult;
-	CleanupStack::PushL(self);
-	self->ConstructL(aDigestAlgorithm, aDigest);
-	return self;
-	}
-
-void CPKCS1SignatureResult::ConstructL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
-	{
-	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
-	iDigest = aDigest.AllocL();
-	}
-
-EXPORT_C TBool CPKCS1SignatureResult::VerifyL(const TDesC8& aResult)
-	{
-
-	TBool res = EFalse;
-	TRAPD(err, res = DoVerifyL(aResult));
-	if ((err != KErrNone) && (err != KErrArgument))
-		{
-		User::Leave(err);
-		}
-	return res;
-	}
-
-TBool CPKCS1SignatureResult::DoVerifyL(const TDesC8& aResult)
-	{
-	TBool res = EFalse;
-	TASN1DecSequence decSeq;
-	TInt pos = 0;
-	TInt len = aResult.Length();
-
-	const CArrayPtrFlat<TASN1DecGeneric>* seq = decSeq.DecodeDERLC(aResult, pos);
-	if (seq->Count() == 2)
-		{
-		const TASN1DecGeneric* gen1 = seq->At(0);
-		const TASN1DecGeneric* gen2 = seq->At(1);
-		CAlgorithmIdentifier* algId = CX509AlgorithmIdentifier::NewLC(gen1->Encoding());
-		HBufC8* digest = gen2->GetContentDER().AllocL();
-		if ((*algId == *iDigestAlgorithm) && (*digest == *iDigest)  && (pos == len))
-			{
-			res = ETrue;
-			}
-		delete digest;
-		CleanupStack::PopAndDestroy();
-		}
-	CleanupStack::PopAndDestroy();
-	return res;
-	}
-
-
-EXPORT_C CRSAPublicKey* TX509KeyFactory::RSAPublicKeyL(const TDesC8& aEncoding) const
-	{
-	return CX509RSAPublicKey::NewL(aEncoding);
-	}
-
-EXPORT_C CRSASignatureResult* TX509KeyFactory::RSASignatureResultL(const CAlgorithmIdentifier& aDigestAlgorithm, TDesC8& aDigest) const
-	{
-	return CPKCS1SignatureResult::NewL(aDigestAlgorithm, aDigest);
-	}
-
-EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const TDesC8& aParamsEncoding, const TDesC8& aEncoding) const
-	{
-	return CX509DSAPublicKey::NewL(aParamsEncoding, aEncoding);
-	}
-
-EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const CDSAParameters& aParams, const TDesC8& aEncoding) const
-	{
-	return CX509DSAPublicKey::NewL(aParams, aEncoding);
-	}
-
-
-EXPORT_C CDSASignature* TX509KeyFactory::DSASignatureL(const TDesC8& aEncoding) const
-	{
-	return CX509DSASignature::NewL(aEncoding);
-	}
-
-EXPORT_C CDSAParameters* TX509KeyFactory::DSAParametersL(const TDesC8& aParamsEncoding) const
-{
-	return (CX509DSAPublicKey::DSAParametersL(aParamsEncoding));
-}
-
-//CX509ValidityPeriod
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509ValidityPeriod::NewL(aBinaryData, pos);
-	}
-
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509ValidityPeriod::NewLC(aBinaryData, pos);
-	}
-
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509ValidityPeriod* self = CX509ValidityPeriod::NewLC(aBinaryData, aPos);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509ValidityPeriod* self = new(ELeave) CX509ValidityPeriod;
-	CleanupStack::PushL(self);
-	self->ConstructL(aBinaryData, aPos);
-	return self;
-	}
-
-CX509ValidityPeriod::CX509ValidityPeriod()
-	{
-	}
-
-void CX509ValidityPeriod::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	TASN1DecSequence encSeq;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos);
-	if (seq->Count() != 2)
-		{
-		User::Leave(KErrArgument);
-		}
-	TASN1DecX509Time decTime;
-	iStart = decTime.DecodeDERL(*(seq->At(0)));
-	iFinish = decTime.DecodeDERL(*(seq->At(1)));
-	CleanupStack::PopAndDestroy();//seq + contents
-	}
-
-//algorithm id
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509AlgorithmIdentifier::NewL(aBinaryData, pos);
-	}
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509AlgorithmIdentifier::NewLC(aBinaryData, pos);
-	}
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aBinaryData, aPos);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier;
-	CleanupStack::PushL(self);
-	self->InitializeL(aBinaryData, aPos);
-	return self;
-	}
-
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
- 	{
-	CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aAlgorithmId, aEncodedParams);
- 	CleanupStack::Pop();
- 	return self;	
- 	}
- 	
-EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
- 	{
- 	CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier(aAlgorithmId);
- 	CleanupStack::PushL(self);
- 	self->ConstructL(aEncodedParams);
- 	return self;				
- 	}
-
-CX509AlgorithmIdentifier::CX509AlgorithmIdentifier(TAlgorithmId& aAlgorithmId):CAlgorithmIdentifier(aAlgorithmId)
- 	{
- 	}
-
-
-CX509AlgorithmIdentifier::CX509AlgorithmIdentifier()
-	{
-	}
-
-void CX509AlgorithmIdentifier::InitializeL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	TASN1DecSequence encSeq;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
-	TInt count = seq->Count();
-	TASN1DecObjectIdentifier encOID;
-	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
-	CleanupStack::PushL(oid);
-	TPtrC oidDes(oid->Des()); 
-	if (oidDes == KDSA)
-		{
-		//optional params
-		if (count > 1)//if we still have stuff left
-			{
-			TASN1DecGeneric* gen = seq->At(1);
-			iEncodedParams = gen->Encoding().AllocL();
-			}
-		else
-			{
-			iEncodedParams = HBufC8::NewL(1);
-			*iEncodedParams = KNullDesC8;
-			}
-		iAlgorithmId = EDSA;
-		CleanupStack::PopAndDestroy(2);//seq, oid
-		return;
-		}
-	if (count > 1)
-		{
-		TASN1DecGeneric* gen = seq->At(1);
-		if (oidDes == KDH)
-			{
-			iEncodedParams = gen->Encoding().AllocL();
-			iAlgorithmId = EDH;
-			CleanupStack::PopAndDestroy(2);//seq, oid
-			return;
-			}
-		if (oidDes == KRSA)
-			{
-			iAlgorithmId = ERSA;
-			TASN1DecNull null;
-			null.DecodeDERL(*gen);//just to check the syntax is OK
-			iEncodedParams = HBufC8::NewL(1);
-			*iEncodedParams = KNullDesC8;
-			CleanupStack::PopAndDestroy(2);//seq, oid
-			return;
-			}
-		if (oidDes == KMD5)
-			{
-			iAlgorithmId = EMD5;
-			TASN1DecNull null;
-			null.DecodeDERL(*gen);//just to check the syntax is OK
-			iEncodedParams = HBufC8::NewL(1);
-			*iEncodedParams = KNullDesC8;
-			CleanupStack::PopAndDestroy(2);//seq, oid
-			return;
-			}
-		if (oidDes == KMD2)
-			{
-			iAlgorithmId = EMD2;
-			TASN1DecNull null;
-			null.DecodeDERL(*gen);//just to check the syntax is OK
-			iEncodedParams = HBufC8::NewL(1);
-			*iEncodedParams = KNullDesC8;
-			CleanupStack::PopAndDestroy(2);//seq, oid
-			return;
-			}
-		if (oidDes == KSHA1)
-			{
-			iAlgorithmId = ESHA1;
-			TASN1DecNull null;
-			null.DecodeDERL(*gen);//just to check the syntax is OK
-			iEncodedParams = HBufC8::NewL(1);
-			*iEncodedParams = KNullDesC8;
-			CleanupStack::PopAndDestroy(2);//seq, oid
-			return;
-			}
-		}
-	User::Leave(KErrNotSupported);
-	}
-	
-EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
-	{
-	// the root sequence contains the signed object
-	CASN1EncSequence* root = CASN1EncSequence::NewLC();
-	
-	//encode the oid
-	CASN1EncObjectIdentifier* oid(NULL);
-	switch (iAlgorithmId)
-		{
-	case EDSA:
-		oid=CASN1EncObjectIdentifier::NewLC(KDSA);
-		break;
-		
-	case EDH:
-		oid=CASN1EncObjectIdentifier::NewLC(KDH);
-		break;
-		
-	case ERSA:
-		oid=CASN1EncObjectIdentifier::NewLC(KRSA);
-		break;
-		
-	case EMD5:
-		oid=CASN1EncObjectIdentifier::NewLC(KMD5);
-		break;
-		
-	case EMD2:
-		oid=CASN1EncObjectIdentifier::NewLC(KMD2);
-		break;
-		
-	case ESHA1:
-		oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
-		break;
-		
-	default:
-		User::Leave(KErrNotSupported);
-		}
-	
-	root->AddAndPopChildL(oid);
-	
-	//Encode parameters
-	if (*iEncodedParams!=KNullDesC8)
-		{
-		CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
-		root->AddAndPopChildL(enc);
-		}
-	else
-		{
-		if (iAlgorithmId!=EDSA)
-			{
-			CASN1EncNull* enc=CASN1EncNull::NewLC();
-			root->AddAndPopChildL(enc);				
-			}
-		}
-		
-	return root;		
-	}
-	
-
-//signing algorithm id
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
-	}
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
-	}
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
-	CleanupStack::PushL(self);
-	self->ConstructL(aBinaryData, aPos);
-	return self;
-	}
-
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
- 	{
- 	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
- 	CleanupStack::Pop();
- 	return self;
- 	}
- 
-EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
- 	{
- 	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
- 	CleanupStack::PushL(self);
- 	self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
- 	return self;
- 	}
-
-CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
-	{
-	}
-
-void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	TASN1DecSequence encSeq;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
-	TInt count = seq->Count();
-	TASN1DecObjectIdentifier encOID;
-	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
-	CleanupStack::PushL(oid);
-	TPtrC oidDes(oid->Des()); 
-	//none of the signing algorithms we support have parameters here...
-	HBufC8* encodedParams = HBufC8::NewLC(1);
-	*encodedParams = KNullDesC8;
-
-	if (oidDes == KDSAWithSHA1)
-		{
-		//should be no params, but we allow params encoded as NULL for interop reasons
-		TAlgorithmId algId = EDSA;
-		TAlgorithmId digestId = ESHA1;
-		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
-		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
-		if (count == 1)
-			{			
-			CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
-			return;
-			}
-		}
-
-	if (oidDes == KMD2WithRSA)
-		{
-		TAlgorithmId algId = ERSA;
-		TAlgorithmId digestId = EMD2;
-		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
-		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
-		}
-
-	if (oidDes == KMD5WithRSA)
-		{
-		TAlgorithmId algId = ERSA;
-		TAlgorithmId digestId = EMD5;
-		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
-		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
-		}
-
-	if (oidDes == KSHA1WithRSA)
-		{
-		TAlgorithmId algId = ERSA;
-		TAlgorithmId digestId = ESHA1;
-		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
-		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
-		}
-		//???not sure if we should just leave here...
-	if (iDigestAlgorithm == NULL)
-		{	
-		User::Leave(KErrNotSupported);
-		}
-	else
-		{
-		if (count != 2)
-			{
-			// Shouldn't ever get here, since RFC2459 mandates having 2
-			// data items.  However, some people miss out the second
-			// when it's NULL, so we'll not report and error here
-			}
-		else
-			{
-			TASN1DecGeneric* gen = seq->At(1);
-			TASN1DecNull null;
-			null.DecodeDERL(*gen);//just to check the syntax is OK
-			}
-		}
-	CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
-	}
-
-void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
- 	{
- 	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
- 	iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
- 	};
-
-//subject public key info
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
-	CleanupStack::PushL(self);
-	self->ConstructL(aBinaryData, aPos);
-	return self;
-	}
-
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
-	}
-
-EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
-	}
-
-CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
-	{
-	}
-
-void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	TASN1DecSequence encSeq;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
-	iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
-	TASN1DecBitString encBS;
-	iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
-	CleanupStack::PopAndDestroy();//seq
-	}
-
-//generic X 509 extension syntax
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
-	{
-	CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
-	{
-	CX509CertExtension* self = new(ELeave) CX509CertExtension;
-	CleanupStack::PushL(self);
-	self->ConstructL(aExtension);
-	return self;
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509CertExtension* self = new(ELeave) CX509CertExtension;
-	CleanupStack::PushL(self);
-	self->ConstructL(aBinaryData, aPos);
-	return self;
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509CertExtension::NewL(aBinaryData, pos);
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509CertExtension::NewLC(aBinaryData, pos);
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID, 
-							const TBool aCritical,
-							const TDesC8& aCertExtValue)
-	{
-	CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID, 
-							const TBool aCritical,
-							const TDesC8& aCertExtValue)
-	{
-	CX509CertExtension* self = new(ELeave) CX509CertExtension;
-	CleanupStack::PushL(self);
-	self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
-	return self;
-	}
-
-void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
-	{
-	iCritical = aExtension.iCritical;
-	iId = aExtension.iId->Des().AllocL();
-	iData = aExtension.iData->Des().AllocL();
-	}
-
-void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	TASN1DecSequence encSeq;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
-
-	TASN1DecObjectIdentifier encOID;
-	iId = encOID.DecodeDERL(*(seq->At(0)));
-	//second is either critical flag, or the ext
-	TASN1DecGeneric* second = seq->At(1);
-	if (second->Tag() != EASN1Boolean)
-		{
-		iData = second->Encoding().AllocL();
-		aPos += second->LengthDER();
-		}
-	else
-		{
-		TASN1DecBoolean encBool;
-		iCritical = encBool.DecodeDERL(*second);
-		if (seq->Count() != 3)
-			{
-			User::Leave(KErrArgument);
-			}
-
-		TASN1DecGeneric* third = seq->At(2);
-		iData = third->Encoding().AllocL();
-		}
-	CleanupStack::PopAndDestroy();//seq
-	}
-
-void CX509CertExtension::ConstructL(const TDesC& aCertExtOID, 
-									const TBool aCritical,
-									const TDesC8& aCertExtValue)
-	{
-	iId = aCertExtOID.AllocL();
-	iCritical = aCritical;
-	iData = aCertExtValue.AllocL();
-	}
-
-EXPORT_C CX509CertExtension::~CX509CertExtension()
-	{
-	delete iData;
-	delete iId;
-	}
-
-EXPORT_C TBool CX509CertExtension::Critical() const
-	{
-	return iCritical;
-	}
-
-EXPORT_C TPtrC CX509CertExtension::Id() const	//OID for the extension
-	{
-	return iId->Des();
-	}
-
-EXPORT_C TPtrC8 CX509CertExtension::Data() const	 //the extension itself
-	{
-	return iData->Des();
-	}
-
-EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
-	{
-	CASN1EncSequence *result = CASN1EncSequence::NewLC();
-	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
-	result->AddAndPopChildL(oid);
-	// Encode critical flag only if true
-	if (iCritical)
-		{
-		CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
-		result->AddAndPopChildL(critical);
-		}	
-	CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
-	result->AddAndPopChildL(data);
-	return result;
-	}
-
-CX509CertExtension::CX509CertExtension()
-	:iCritical(EFalse)
-	{
-	}
-
-//CX509Certificate
-EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
-	{
-	CX509Certificate* self = CX509Certificate::NewLC(aCert);
-	CleanupStack::Pop();//self
-	return self;
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
-	{
-	CX509Certificate* self = new(ELeave) CX509Certificate;
-	CleanupStack::PushL(self);
-	self->ConstructL(aCert);
-	return self;
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
-	{
-	TInt pos = 0;
-	return CX509Certificate::NewL(aBinaryData, pos);
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
-	{	
-	TInt pos = 0;
-	return CX509Certificate::NewLC(aBinaryData, pos);
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
-	CleanupStack::Pop();
-	return self;
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
-	{	
-	CX509Certificate* self = new(ELeave) CX509Certificate();
-	CleanupStack::PushL(self);
-	self->ConstructL(aBinaryData, aPos);
-	return self;
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
-	{
-	CX509Certificate* self = CX509Certificate::NewLC(aStream);
-	CleanupStack::Pop();//self
-	return self;
-	}
-
-EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
-	{
-	CX509Certificate* self = new(ELeave) CX509Certificate;
-	CleanupStack::PushL(self);
-	self->InternalizeL(aStream);
-	return self;
-	}
-
-void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
-	{
-	TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
-	gen.InitL();
-	
-	// The outermost tag for X509 certificates is always a sequence.
-	// Since this tag does not form part of the signed data it is possible
-	// to corrupt the tag by changing it to any other ASN.1 tag and process
-	// the rest of the certificate as normal.
-	// However, we still reject the certificate anyway to avoid 
-	// confusion because the data does not match the X.509 specification.	
-	if (gen.Tag() != EASN1Sequence)
-		{
-		User::Leave(KErrArgument);
-		}
-	
-	aPos += gen.LengthDER();
-	iKeyFactory = new(ELeave) TX509KeyFactory;
-
-	iEncoding = gen.Encoding().AllocL();
-
-	TASN1DecSequence encSeq;
-	TInt pos = 0;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
-	TASN1DecGeneric* encSigAlg = seq->At(1);
-	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
-	TASN1DecBitString encBS;
-	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
-	CleanupStack::PopAndDestroy();//seq
-
-	CSHA1* hash = CSHA1::NewL();
-	CleanupStack::PushL(hash);
-	iFingerprint = hash->Final(Encoding()).AllocL();
-	CleanupStack::PopAndDestroy();//hash
-	ConstructCertL();
-	}
-
-void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
-	{
-	iKeyFactory = new(ELeave) TX509KeyFactory;
-
-	iEncoding = aCertificate.iEncoding->AllocL();
-	iSignature = aCertificate.iSignature->AllocL();
-	iFingerprint = aCertificate.iFingerprint->AllocL();
-	iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());	
-	iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
-	iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
-	iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
-	iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
-	iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
-	iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
-	iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
-	iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
-	TInt count = aCertificate.iExtensions->Count();
-	for (TInt i = 0; i < count; i++)
-		{
-		CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
-		iExtensions->AppendL(ext);
-		CleanupStack::Pop();//ext
-		}
-	iVersion = aCertificate.Version();
-	InitDataElementsL(aCertificate);
-	}
-
-void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
-	{
-	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
-	iDataElements->Reset();
-	TPtrC8 signedData = SignedDataL();
-	TASN1DecSequence encSeq;
-	TInt pos = 0;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
-	pos = 0;
-
-	TPtrC8** pElement = iDataElements->Begin();
-	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
-	for (TInt i = 0; i < 6; i++)	//init all the non-optional elements
-		{
-		*pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
-		}
-	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
-	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
-	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
-	CleanupStack::PopAndDestroy();
-	}
-
-void CX509Certificate::ConstructCertL()
-	{
-	TPtrC8 signedData = SignedDataL();
-	TASN1DecSequence encSeq;
-	TInt pos = 0;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
-	TInt count = seq->Count();
-	pos = 0;
-	TASN1DecGeneric* curr = seq->At(pos);
-	pos++;
-	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
-	iDataElements->Reset();
-	TPtrC8** pElement = iDataElements->Begin();
-	if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
-		{
-		//version!
-		TASN1DecGeneric ver(curr->GetContentDER());
-		ver.InitL();
-		TPtrC8 pVer8 = ver.GetContentDER();
-		if(pVer8.Length() != 1)
-			{
-			User::Leave(KErrArgument);
-			}
-		iVersion = (pVer8[0]) + 1;
-		if ((iVersion < 1) || (iVersion > 3) || (count < 7))
-			{
-			User::Leave(KErrArgument);
-			}
-		*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-		curr = seq->At(pos);
-		pos++;
-		}
-	else
-		{
-		*pElement++ = NULL;
-		}
-	if (curr->Tag() != EASN1Integer)
-		{
-		User::Leave(KErrArgument);
-		}
-	iSerialNumber = (curr->GetContentDER()).AllocL();
-	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-	curr = seq->At(pos);
-	pos++;
-	CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
-	if (!(SigningAlgorithm() == *(algorithmId)))
-		{
-		User::Leave(KErrArgument);
-		}
-	CleanupStack::PopAndDestroy();//algorithmId
-	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-
-	curr = seq->At(pos);
-	pos++;
-	iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
-	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-	curr = seq->At(pos);
-	pos++;
-	iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
-	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-	curr = seq->At(pos);
-	pos++;
-	iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
-	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-	curr = seq->At(pos);
-	pos++;
-	iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
-	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-	//do issuer uid, subject uid, exts
-	//these are all optional
-	TBool hasIssuerUid = EFalse;
-	TBool hasSubjectUid = EFalse;
-	TBool hasExts = EFalse;
-	iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
-	if (pos < count)//otherwise there aren't any of 'em
-		{
-		curr = seq->At(pos);
-		pos++;
-		if (curr->Class() != EContextSpecific)
-			{
-			User::Leave(KErrArgument);
-			}
-		switch(curr->Tag())
-			{
-			case 1:
-				{
-				iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
-				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-				break;
-				}
-			case 2:
-				{
-				iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
-				*pElement++ = NULL;
-				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-				break;
-				}
-			case 3:
-				{
-				DecodeExtsL(curr->GetContentDER(), hasExts);
-				*pElement++ = NULL;
-				*pElement++ = NULL;
-				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-				break;
-				}
-			default:
-				{
-				User::Leave(KErrArgument);
-				}
-			}
-		if (pos < count)
-			{
-			curr = seq->At(pos);
-			pos++;
-			switch(curr->Tag())
-				{
-				case 2:
-					{
-					iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
-					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-					break;
-					}
-				case 3:
-					{
-					DecodeExtsL(curr->GetContentDER(), hasExts);
-					*pElement++ = NULL;
-					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-					break;
-					}
-				default:
-					{
-					User::Leave(KErrArgument);
-					}
-				}
-			if (pos < count)
-				{
-				curr = seq->At(pos);
-				pos++;
-				if (curr->Tag() == 3)
-					{
-					DecodeExtsL(curr->GetContentDER(), hasExts);
-					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
-					}
-				else
-					{
-					User::Leave(KErrArgument);
-					}
-				}
-			}
-		}
-	if (pos != count)
-		{
-		User::Leave(KErrArgument);
-		}
-	if (!iIssuerUid)
-		{
-		iIssuerUid = HBufC8::NewL(1);
-		*iIssuerUid = KNullDesC8;
-		}
-	if (!iSubjectUid)
-		{
-		iSubjectUid = HBufC8::NewL(1);
-		*iSubjectUid = KNullDesC8;
-		}
-		
-	// we have not checked for the certificate version number based on 
-	// the certificate contents. This is primarily done to avoid BC for 
-	// clients who are still using malformed certificates.
-	
-	CleanupStack::PopAndDestroy();//seq
-	}
-
-CX509Certificate::CX509Certificate()
-	:iVersion(1)
-	{
-	}
-
-EXPORT_C CX509Certificate::~CX509Certificate()
-	{
-	delete iIssuerName;
-	delete iSubjectName;
-	delete iIssuerUid;
-	delete iSubjectUid;
-	
-	if (iDataElements != NULL)
-		{
-		for (TInt i = 0; i < KX509MaxDataElements; i++)
-			{
-			delete iDataElements->At(i);
-			}
-		delete iDataElements;
-		}
-	if (iExtensions != NULL)
-		{
-		iExtensions->ResetAndDestroy();
-		}
-	delete iExtensions;
-	}
-
-EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
-	{
-	return	(	(*(iSerialNumber) == *(aCert.iSerialNumber)) && 
-				(iIssuerName->ExactMatchL(*(aCert.iIssuerName)))	);
-	}
-
-EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
-	{
-	if (iIssuerName != NULL) //just to check cert is uninitialised
-		{
-		User::Leave(KErrArgument);
-		}
-	iKeyFactory = new(ELeave) TX509KeyFactory;
-	
-	TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
-	HBufC8* temp= HBufC8::NewLC(len);	
-	TPtr8 ptr=temp->Des();
-	aStream.ReadL(ptr,len);
-	iEncoding=temp->AllocL();
-	CleanupStack::PopAndDestroy(); // temp
-
-	TASN1DecSequence encSeq;
-	TInt pos = 0;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
-	TASN1DecGeneric* encSigAlg = seq->At(1);
-	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
-	TASN1DecBitString encBS;
-	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
-	CleanupStack::PopAndDestroy();//seq	
-
-	CSHA1* hash = CSHA1::NewL();
-	CleanupStack::PushL(hash);
-	iFingerprint = hash->Final(Encoding()).AllocL();
-	CleanupStack::PopAndDestroy();//hash
-
-	ConstructCertL();
-	}
-
-void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
-	{
-	TASN1DecSequence encSeq;
-	TInt pos = 0;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
-	TInt count = seq->Count();
-	for (TInt i = 0; i < count; i++)
-		{
-		TASN1DecGeneric* gen = seq->At(i);
-		CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
-		iExtensions->AppendL(ext);
-		CleanupStack::Pop();//ext
-		}
-	CleanupStack::PopAndDestroy();//
-	aHasElementAlready = ETrue;
-	}
-
-HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
-	{
-	if ((aHasElementAlready) || (iVersion ==1))
-		{
-		User::Leave(KErrArgument);
-		}
-	aHasElementAlready = ETrue;
-	return aBinaryData.AllocL();
-	}
-
-//***************************************************************************************//
-//extra accessors
-EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
-	{
-	TASN1DecSequence encSeq;
-	TInt pos = 0;
-	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
-	TASN1DecGeneric* gen = seq->At(0);
-	TPtrC8 res = gen->Encoding();
-	CleanupStack::PopAndDestroy();
-	return res;
-	}
-
-EXPORT_C TInt CX509Certificate::Version() const
-	{
-	return iVersion;
-	}
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value 
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
-* null characters in the second byte of each character. This will work as expected 
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
-	{
-	return *iIssuerName;
-	}
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value 
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
-* null characters in the second byte of each character. This will work as expected 
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
-	{
-	return *iSubjectName;
-	}
-
-EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
-	{
-	return *iExtensions;
-	}
-
-EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
-	{
-	TInt count = iExtensions->Count();
-	for (TInt i = 0; i < count; i++)
-		{
-		CX509CertExtension* ext = iExtensions->At(i);
-		if (ext->Id() == aExtensionName)
-			return ext;
-		}
-	return NULL;
-	}
-
-EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
-	{
-	return iDataElements->At(aIndex);
-	}
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value 
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
-* null characters in the second byte of each character. This will work as expected 
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C HBufC* CX509Certificate::IssuerL() const
-	{
-	return iIssuerName->DisplayNameL();
-	}
-
-/**
-* If the certificate has decoded the members from TeletexString then the return value 
-* may be incorrect because TeletexString type is not fully supported by this library.
-* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
-* null characters in the second byte of each character. This will work as expected 
-* for cases where the string contains ASCII data.
-*/
-EXPORT_C HBufC* CX509Certificate::SubjectL() const
-	{
-	return iSubjectName->DisplayNameL();
-	}
-
-EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
-	{
-	if (iSubjectName->Count() > 0)
-		{
-		return iSubjectName->ExactMatchL(*iIssuerName);
-		}
-	else
-		{
-		TBool res = EFalse;
-		const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
-		const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
-		if ((subjectExt) && (issuerExt))
-			{
-			const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
-			const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
-			if (subjectAltName->Match(*issuerAltName))
-				{
-				res = ETrue;
-				}
-			CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
-			}
-		return res;
-		} 
-	}
-
-
-EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const	
-	{
-	if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
-		{
-		// The base class handles the RSA case and leaves with KErrNotSupported if
-		// it is not RSA.
-		return CCertificate::KeyIdentifierL();
-		}
-	else
-		{
-		// This handles the DSA case
-		CDSAPublicKey* dsaKey = 
-						iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(), 
-													iSubjectPublicKeyInfo->KeyData());
-		CleanupStack::PushL(dsaKey);
-		TKeyIdentifier retVal;
-		KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
-		CleanupStack::PopAndDestroy(dsaKey);
-		return retVal;
-		}
-	}
-
-EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
-	{	
-	const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
-	if (subjectKeyIdExtStr)
-		{
-		TKeyIdentifier ret;
-		CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
-		// Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
-		if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
-			{
-			ret.Copy(subjectKeyIdExt->KeyId());
-			CleanupStack::PopAndDestroy(subjectKeyIdExt);
-			return ret;
-			}
-		CleanupStack::PopAndDestroy(subjectKeyIdExt);
-		}
-		
-	return KeyIdentifierL();
-	}
+/*
+* Copyright (c) 1998-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: 
+* -- FingerPrint Note:
+* Developers have to be aware that if they are going to change the fingerprint for this certificate
+* for a different hash, then there are other places that need to reflect this change
+* -- Location
+* void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+* EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
+* Also change the CWTLSCertificate and search for other occurences of the current
+* hash.
+* -- TeletexString type support Note:
+* If the certificate has decoded the members from TeletexString then the return value 
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
+* null characters in the second byte of each character. This will work as expected 
+* for cases where the string contains ASCII data.
+*
+*/
+
+
+
+
+#include <x509cert.h>
+#include <x509certext.h>
+#include "X509time.h"
+#include <x509keys.h>
+#include <keyidentifierutil.h>
+#include <asn1enc.h>
+#include <asn1dec.h>
+
+EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
+	{
+	CPKCS1SignatureResult* self = CPKCS1SignatureResult::NewLC(aDigestAlgorithm, aDigest);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewLC(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
+	{
+	CPKCS1SignatureResult* self = new(ELeave) CPKCS1SignatureResult;
+	CleanupStack::PushL(self);
+	self->ConstructL(aDigestAlgorithm, aDigest);
+	return self;
+	}
+
+void CPKCS1SignatureResult::ConstructL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
+	{
+	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
+	iDigest = aDigest.AllocL();
+	}
+
+EXPORT_C TBool CPKCS1SignatureResult::VerifyL(const TDesC8& aResult)
+	{
+
+	TBool res = EFalse;
+	TRAPD(err, res = DoVerifyL(aResult));
+	if ((err != KErrNone) && (err != KErrArgument))
+		{
+		User::Leave(err);
+		}
+	return res;
+	}
+
+TBool CPKCS1SignatureResult::DoVerifyL(const TDesC8& aResult)
+	{
+	TBool res = EFalse;
+	TASN1DecSequence decSeq;
+	TInt pos = 0;
+	TInt len = aResult.Length();
+
+	const CArrayPtrFlat<TASN1DecGeneric>* seq = decSeq.DecodeDERLC(aResult, pos);
+	if (seq->Count() == 2)
+		{
+		const TASN1DecGeneric* gen1 = seq->At(0);
+		const TASN1DecGeneric* gen2 = seq->At(1);
+		CAlgorithmIdentifier* algId = CX509AlgorithmIdentifier::NewLC(gen1->Encoding());
+		HBufC8* digest = gen2->GetContentDER().AllocL();
+		if ((*algId == *iDigestAlgorithm) && (*digest == *iDigest)  && (pos == len))
+			{
+			res = ETrue;
+			}
+		delete digest;
+		CleanupStack::PopAndDestroy();
+		}
+	CleanupStack::PopAndDestroy();
+	return res;
+	}
+
+
+EXPORT_C CRSAPublicKey* TX509KeyFactory::RSAPublicKeyL(const TDesC8& aEncoding) const
+	{
+	return CX509RSAPublicKey::NewL(aEncoding);
+	}
+
+EXPORT_C CRSASignatureResult* TX509KeyFactory::RSASignatureResultL(const CAlgorithmIdentifier& aDigestAlgorithm, TDesC8& aDigest) const
+	{
+	return CPKCS1SignatureResult::NewL(aDigestAlgorithm, aDigest);
+	}
+
+EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const TDesC8& aParamsEncoding, const TDesC8& aEncoding) const
+	{
+	return CX509DSAPublicKey::NewL(aParamsEncoding, aEncoding);
+	}
+
+EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const CDSAParameters& aParams, const TDesC8& aEncoding) const
+	{
+	return CX509DSAPublicKey::NewL(aParams, aEncoding);
+	}
+
+
+EXPORT_C CDSASignature* TX509KeyFactory::DSASignatureL(const TDesC8& aEncoding) const
+	{
+	return CX509DSASignature::NewL(aEncoding);
+	}
+
+EXPORT_C CDSAParameters* TX509KeyFactory::DSAParametersL(const TDesC8& aParamsEncoding) const
+{
+	return (CX509DSAPublicKey::DSAParametersL(aParamsEncoding));
+}
+
+//CX509ValidityPeriod
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509ValidityPeriod::NewL(aBinaryData, pos);
+	}
+
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509ValidityPeriod::NewLC(aBinaryData, pos);
+	}
+
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509ValidityPeriod* self = CX509ValidityPeriod::NewLC(aBinaryData, aPos);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509ValidityPeriod* self = new(ELeave) CX509ValidityPeriod;
+	CleanupStack::PushL(self);
+	self->ConstructL(aBinaryData, aPos);
+	return self;
+	}
+
+CX509ValidityPeriod::CX509ValidityPeriod()
+	{
+	}
+
+void CX509ValidityPeriod::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	TASN1DecSequence encSeq;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos);
+	if (seq->Count() != 2)
+		{
+		User::Leave(KErrArgument);
+		}
+	TASN1DecX509Time decTime;
+	iStart = decTime.DecodeDERL(*(seq->At(0)));
+	iFinish = decTime.DecodeDERL(*(seq->At(1)));
+	CleanupStack::PopAndDestroy();//seq + contents
+	}
+
+//algorithm id
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509AlgorithmIdentifier::NewL(aBinaryData, pos);
+	}
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509AlgorithmIdentifier::NewLC(aBinaryData, pos);
+	}
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aBinaryData, aPos);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier;
+	CleanupStack::PushL(self);
+	self->InitializeL(aBinaryData, aPos);
+	return self;
+	}
+
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
+ 	{
+	CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aAlgorithmId, aEncodedParams);
+ 	CleanupStack::Pop();
+ 	return self;	
+ 	}
+ 	
+EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
+ 	{
+ 	CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier(aAlgorithmId);
+ 	CleanupStack::PushL(self);
+ 	self->ConstructL(aEncodedParams);
+ 	return self;				
+ 	}
+
+CX509AlgorithmIdentifier::CX509AlgorithmIdentifier(TAlgorithmId& aAlgorithmId):CAlgorithmIdentifier(aAlgorithmId)
+ 	{
+ 	}
+
+
+CX509AlgorithmIdentifier::CX509AlgorithmIdentifier()
+	{
+	}
+
+void CX509AlgorithmIdentifier::InitializeL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	TASN1DecSequence encSeq;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
+	TInt count = seq->Count();
+	TASN1DecObjectIdentifier encOID;
+	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
+	CleanupStack::PushL(oid);
+	TPtrC oidDes(oid->Des()); 
+	if (oidDes == KDSA)
+		{
+		//optional params
+		if (count > 1)//if we still have stuff left
+			{
+			TASN1DecGeneric* gen = seq->At(1);
+			iEncodedParams = gen->Encoding().AllocL();
+			}
+		else
+			{
+			iEncodedParams = HBufC8::NewL(1);
+			*iEncodedParams = KNullDesC8;
+			}
+		iAlgorithmId = EDSA;
+		CleanupStack::PopAndDestroy(2);//seq, oid
+		return;
+		}
+	if (count > 1)
+		{
+		TASN1DecGeneric* gen = seq->At(1);
+		if (oidDes == KDH)
+			{
+			iEncodedParams = gen->Encoding().AllocL();
+			iAlgorithmId = EDH;
+			CleanupStack::PopAndDestroy(2);//seq, oid
+			return;
+			}
+		if (oidDes == KRSA)
+			{
+			iAlgorithmId = ERSA;
+			TASN1DecNull null;
+			null.DecodeDERL(*gen);//just to check the syntax is OK
+			iEncodedParams = HBufC8::NewL(1);
+			*iEncodedParams = KNullDesC8;
+			CleanupStack::PopAndDestroy(2);//seq, oid
+			return;
+			}
+		if (oidDes == KMD5)
+			{
+			iAlgorithmId = EMD5;
+			TASN1DecNull null;
+			null.DecodeDERL(*gen);//just to check the syntax is OK
+			iEncodedParams = HBufC8::NewL(1);
+			*iEncodedParams = KNullDesC8;
+			CleanupStack::PopAndDestroy(2);//seq, oid
+			return;
+			}
+		if (oidDes == KMD2)
+			{
+			iAlgorithmId = EMD2;
+			TASN1DecNull null;
+			null.DecodeDERL(*gen);//just to check the syntax is OK
+			iEncodedParams = HBufC8::NewL(1);
+			*iEncodedParams = KNullDesC8;
+			CleanupStack::PopAndDestroy(2);//seq, oid
+			return;
+			}
+		if (oidDes == KSHA1)
+			{
+			iAlgorithmId = ESHA1;
+			TASN1DecNull null;
+			null.DecodeDERL(*gen);//just to check the syntax is OK
+			iEncodedParams = HBufC8::NewL(1);
+			*iEncodedParams = KNullDesC8;
+			CleanupStack::PopAndDestroy(2);//seq, oid
+			return;
+			}
+		}
+	User::Leave(KErrNotSupported);
+	}
+	
+EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
+	{
+	// the root sequence contains the signed object
+	CASN1EncSequence* root = CASN1EncSequence::NewLC();
+	
+	//encode the oid
+	CASN1EncObjectIdentifier* oid(NULL);
+	switch (iAlgorithmId)
+		{
+	case EDSA:
+		oid=CASN1EncObjectIdentifier::NewLC(KDSA);
+		break;
+		
+	case EDH:
+		oid=CASN1EncObjectIdentifier::NewLC(KDH);
+		break;
+		
+	case ERSA:
+		oid=CASN1EncObjectIdentifier::NewLC(KRSA);
+		break;
+		
+	case EMD5:
+		oid=CASN1EncObjectIdentifier::NewLC(KMD5);
+		break;
+		
+	case EMD2:
+		oid=CASN1EncObjectIdentifier::NewLC(KMD2);
+		break;
+		
+	case ESHA1:
+		oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
+		break;
+		
+	default:
+		User::Leave(KErrNotSupported);
+		}
+	
+	root->AddAndPopChildL(oid);
+	
+	//Encode parameters
+	if (*iEncodedParams!=KNullDesC8)
+		{
+		CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
+		root->AddAndPopChildL(enc);
+		}
+	else
+		{
+		if (iAlgorithmId!=EDSA)
+			{
+			CASN1EncNull* enc=CASN1EncNull::NewLC();
+			root->AddAndPopChildL(enc);				
+			}
+		}
+		
+	return root;		
+	}
+	
+
+//signing algorithm id
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
+	}
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
+	}
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
+	CleanupStack::PushL(self);
+	self->ConstructL(aBinaryData, aPos);
+	return self;
+	}
+
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
+ 	{
+ 	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
+ 	CleanupStack::Pop();
+ 	return self;
+ 	}
+ 
+EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
+ 	{
+ 	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
+ 	CleanupStack::PushL(self);
+ 	self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
+ 	return self;
+ 	}
+
+CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
+	{
+	}
+
+void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	TASN1DecSequence encSeq;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
+	TInt count = seq->Count();
+	TASN1DecObjectIdentifier encOID;
+	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
+	CleanupStack::PushL(oid);
+	TPtrC oidDes(oid->Des()); 
+	//none of the signing algorithms we support have parameters here...
+	HBufC8* encodedParams = HBufC8::NewLC(1);
+	*encodedParams = KNullDesC8;
+
+	if (oidDes == KDSAWithSHA1)
+		{
+		//should be no params, but we allow params encoded as NULL for interop reasons
+		TAlgorithmId algId = EDSA;
+		TAlgorithmId digestId = ESHA1;
+		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+		if (count == 1)
+			{			
+			CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
+			return;
+			}
+		}
+
+	if (oidDes == KMD2WithRSA)
+		{
+		TAlgorithmId algId = ERSA;
+		TAlgorithmId digestId = EMD2;
+		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+		}
+
+	if (oidDes == KMD5WithRSA)
+		{
+		TAlgorithmId algId = ERSA;
+		TAlgorithmId digestId = EMD5;
+		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+		}
+
+	if (oidDes == KSHA1WithRSA)
+		{
+		TAlgorithmId algId = ERSA;
+		TAlgorithmId digestId = ESHA1;
+		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
+		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
+		}
+		//???not sure if we should just leave here...
+	if (iDigestAlgorithm == NULL)
+		{	
+		User::Leave(KErrNotSupported);
+		}
+	else
+		{
+		if (count != 2)
+			{
+			// Shouldn't ever get here, since RFC2459 mandates having 2
+			// data items.  However, some people miss out the second
+			// when it's NULL, so we'll not report and error here
+			}
+		else
+			{
+			TASN1DecGeneric* gen = seq->At(1);
+			TASN1DecNull null;
+			null.DecodeDERL(*gen);//just to check the syntax is OK
+			}
+		}
+	CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
+	}
+
+void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
+ 	{
+ 	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
+ 	iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
+ 	};
+
+//subject public key info
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
+	CleanupStack::PushL(self);
+	self->ConstructL(aBinaryData, aPos);
+	return self;
+	}
+
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
+	}
+
+EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
+	}
+
+CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
+	{
+	}
+
+void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	TASN1DecSequence encSeq;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
+	iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
+	TASN1DecBitString encBS;
+	iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
+	CleanupStack::PopAndDestroy();//seq
+	}
+
+//generic X 509 extension syntax
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
+	{
+	CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
+	{
+	CX509CertExtension* self = new(ELeave) CX509CertExtension;
+	CleanupStack::PushL(self);
+	self->ConstructL(aExtension);
+	return self;
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509CertExtension* self = new(ELeave) CX509CertExtension;
+	CleanupStack::PushL(self);
+	self->ConstructL(aBinaryData, aPos);
+	return self;
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509CertExtension::NewL(aBinaryData, pos);
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509CertExtension::NewLC(aBinaryData, pos);
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID, 
+							const TBool aCritical,
+							const TDesC8& aCertExtValue)
+	{
+	CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID, 
+							const TBool aCritical,
+							const TDesC8& aCertExtValue)
+	{
+	CX509CertExtension* self = new(ELeave) CX509CertExtension;
+	CleanupStack::PushL(self);
+	self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
+	return self;
+	}
+
+void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
+	{
+	iCritical = aExtension.iCritical;
+	iId = aExtension.iId->Des().AllocL();
+	iData = aExtension.iData->Des().AllocL();
+	}
+
+void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	TASN1DecSequence encSeq;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
+
+	TASN1DecObjectIdentifier encOID;
+	iId = encOID.DecodeDERL(*(seq->At(0)));
+	//second is either critical flag, or the ext
+	TASN1DecGeneric* second = seq->At(1);
+	if (second->Tag() != EASN1Boolean)
+		{
+		iData = second->Encoding().AllocL();
+		aPos += second->LengthDER();
+		}
+	else
+		{
+		TASN1DecBoolean encBool;
+		iCritical = encBool.DecodeDERL(*second);
+		if (seq->Count() != 3)
+			{
+			User::Leave(KErrArgument);
+			}
+
+		TASN1DecGeneric* third = seq->At(2);
+		iData = third->Encoding().AllocL();
+		}
+	CleanupStack::PopAndDestroy();//seq
+	}
+
+void CX509CertExtension::ConstructL(const TDesC& aCertExtOID, 
+									const TBool aCritical,
+									const TDesC8& aCertExtValue)
+	{
+	iId = aCertExtOID.AllocL();
+	iCritical = aCritical;
+	iData = aCertExtValue.AllocL();
+	}
+
+EXPORT_C CX509CertExtension::~CX509CertExtension()
+	{
+	delete iData;
+	delete iId;
+	}
+
+EXPORT_C TBool CX509CertExtension::Critical() const
+	{
+	return iCritical;
+	}
+
+EXPORT_C TPtrC CX509CertExtension::Id() const	//OID for the extension
+	{
+	return iId->Des();
+	}
+
+EXPORT_C TPtrC8 CX509CertExtension::Data() const	 //the extension itself
+	{
+	return iData->Des();
+	}
+
+EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
+	{
+	CASN1EncSequence *result = CASN1EncSequence::NewLC();
+	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
+	result->AddAndPopChildL(oid);
+	// Encode critical flag only if true
+	if (iCritical)
+		{
+		CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
+		result->AddAndPopChildL(critical);
+		}	
+	CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
+	result->AddAndPopChildL(data);
+	return result;
+	}
+
+CX509CertExtension::CX509CertExtension()
+	:iCritical(EFalse)
+	{
+	}
+
+//CX509Certificate
+EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
+	{
+	CX509Certificate* self = CX509Certificate::NewLC(aCert);
+	CleanupStack::Pop();//self
+	return self;
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
+	{
+	CX509Certificate* self = new(ELeave) CX509Certificate;
+	CleanupStack::PushL(self);
+	self->ConstructL(aCert);
+	return self;
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
+	{
+	TInt pos = 0;
+	return CX509Certificate::NewL(aBinaryData, pos);
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
+	{	
+	TInt pos = 0;
+	return CX509Certificate::NewLC(aBinaryData, pos);
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+	{	
+	CX509Certificate* self = new(ELeave) CX509Certificate();
+	CleanupStack::PushL(self);
+	self->ConstructL(aBinaryData, aPos);
+	return self;
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
+	{
+	CX509Certificate* self = CX509Certificate::NewLC(aStream);
+	CleanupStack::Pop();//self
+	return self;
+	}
+
+EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
+	{
+	CX509Certificate* self = new(ELeave) CX509Certificate;
+	CleanupStack::PushL(self);
+	self->InternalizeL(aStream);
+	return self;
+	}
+
+void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+	{
+	TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
+	gen.InitL();
+	
+	// The outermost tag for X509 certificates is always a sequence.
+	// Since this tag does not form part of the signed data it is possible
+	// to corrupt the tag by changing it to any other ASN.1 tag and process
+	// the rest of the certificate as normal.
+	// However, we still reject the certificate anyway to avoid 
+	// confusion because the data does not match the X.509 specification.	
+	if (gen.Tag() != EASN1Sequence)
+		{
+		User::Leave(KErrArgument);
+		}
+	
+	aPos += gen.LengthDER();
+	iKeyFactory = new(ELeave) TX509KeyFactory;
+
+	iEncoding = gen.Encoding().AllocL();
+
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
+	TASN1DecGeneric* encSigAlg = seq->At(1);
+	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
+	TASN1DecBitString encBS;
+	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
+	CleanupStack::PopAndDestroy();//seq
+
+	CSHA1* hash = CSHA1::NewL();
+	CleanupStack::PushL(hash);
+	iFingerprint = hash->Final(Encoding()).AllocL();
+	CleanupStack::PopAndDestroy();//hash
+	ConstructCertL();
+	}
+
+void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
+	{
+	iKeyFactory = new(ELeave) TX509KeyFactory;
+
+	iEncoding = aCertificate.iEncoding->AllocL();
+	iSignature = aCertificate.iSignature->AllocL();
+	iFingerprint = aCertificate.iFingerprint->AllocL();
+	iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());	
+	iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
+	iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
+	iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
+	iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
+	iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
+	iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
+	iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
+	iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
+	TInt count = aCertificate.iExtensions->Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
+		iExtensions->AppendL(ext);
+		CleanupStack::Pop();//ext
+		}
+	iVersion = aCertificate.Version();
+	InitDataElementsL(aCertificate);
+	}
+
+void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
+	{
+	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
+	iDataElements->Reset();
+	TPtrC8 signedData = SignedDataL();
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
+	pos = 0;
+
+	TPtrC8** pElement = iDataElements->Begin();
+	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+	for (TInt i = 0; i < 6; i++)	//init all the non-optional elements
+		{
+		*pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
+		}
+	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
+	CleanupStack::PopAndDestroy();
+	}
+
+void CX509Certificate::ConstructCertL()
+	{
+	TPtrC8 signedData = SignedDataL();
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
+	TInt count = seq->Count();
+	pos = 0;
+	TASN1DecGeneric* curr = seq->At(pos);
+	pos++;
+	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
+	iDataElements->Reset();
+	TPtrC8** pElement = iDataElements->Begin();
+	if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
+		{
+		//version!
+		TASN1DecGeneric ver(curr->GetContentDER());
+		ver.InitL();
+		TPtrC8 pVer8 = ver.GetContentDER();
+		if(pVer8.Length() != 1)
+			{
+			User::Leave(KErrArgument);
+			}
+		iVersion = (pVer8[0]) + 1;
+		if ((iVersion < 1) || (iVersion > 3) || (count < 7))
+			{
+			User::Leave(KErrArgument);
+			}
+		*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+		curr = seq->At(pos);
+		pos++;
+		}
+	else
+		{
+		*pElement++ = NULL;
+		}
+	if (curr->Tag() != EASN1Integer)
+		{
+		User::Leave(KErrArgument);
+		}
+	iSerialNumber = (curr->GetContentDER()).AllocL();
+	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+	curr = seq->At(pos);
+	pos++;
+	CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
+	if (!(SigningAlgorithm() == *(algorithmId)))
+		{
+		User::Leave(KErrArgument);
+		}
+	CleanupStack::PopAndDestroy();//algorithmId
+	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+
+	curr = seq->At(pos);
+	pos++;
+	iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
+	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+	curr = seq->At(pos);
+	pos++;
+	iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
+	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+	curr = seq->At(pos);
+	pos++;
+	iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
+	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+	curr = seq->At(pos);
+	pos++;
+	iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
+	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+	//do issuer uid, subject uid, exts
+	//these are all optional
+	TBool hasIssuerUid = EFalse;
+	TBool hasSubjectUid = EFalse;
+	TBool hasExts = EFalse;
+	iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
+	if (pos < count)//otherwise there aren't any of 'em
+		{
+		curr = seq->At(pos);
+		pos++;
+		if (curr->Class() != EContextSpecific)
+			{
+			User::Leave(KErrArgument);
+			}
+		switch(curr->Tag())
+			{
+			case 1:
+				{
+				iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
+				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+				break;
+				}
+			case 2:
+				{
+				iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
+				*pElement++ = NULL;
+				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+				break;
+				}
+			case 3:
+				{
+				DecodeExtsL(curr->GetContentDER(), hasExts);
+				*pElement++ = NULL;
+				*pElement++ = NULL;
+				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+				break;
+				}
+			default:
+				{
+				User::Leave(KErrArgument);
+				}
+			}
+		if (pos < count)
+			{
+			curr = seq->At(pos);
+			pos++;
+			switch(curr->Tag())
+				{
+				case 2:
+					{
+					iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
+					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+					break;
+					}
+				case 3:
+					{
+					DecodeExtsL(curr->GetContentDER(), hasExts);
+					*pElement++ = NULL;
+					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+					break;
+					}
+				default:
+					{
+					User::Leave(KErrArgument);
+					}
+				}
+			if (pos < count)
+				{
+				curr = seq->At(pos);
+				pos++;
+				if (curr->Tag() == 3)
+					{
+					DecodeExtsL(curr->GetContentDER(), hasExts);
+					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
+					}
+				else
+					{
+					User::Leave(KErrArgument);
+					}
+				}
+			}
+		}
+	if (pos != count)
+		{
+		User::Leave(KErrArgument);
+		}
+	if (!iIssuerUid)
+		{
+		iIssuerUid = HBufC8::NewL(1);
+		*iIssuerUid = KNullDesC8;
+		}
+	if (!iSubjectUid)
+		{
+		iSubjectUid = HBufC8::NewL(1);
+		*iSubjectUid = KNullDesC8;
+		}
+		
+	// we have not checked for the certificate version number based on 
+	// the certificate contents. This is primarily done to avoid BC for 
+	// clients who are still using malformed certificates.
+	
+	CleanupStack::PopAndDestroy();//seq
+	}
+
+CX509Certificate::CX509Certificate()
+	:iVersion(1)
+	{
+	}
+
+EXPORT_C CX509Certificate::~CX509Certificate()
+	{
+	delete iIssuerName;
+	delete iSubjectName;
+	delete iIssuerUid;
+	delete iSubjectUid;
+	
+	if (iDataElements != NULL)
+		{
+		for (TInt i = 0; i < KX509MaxDataElements; i++)
+			{
+			delete iDataElements->At(i);
+			}
+		delete iDataElements;
+		}
+	if (iExtensions != NULL)
+		{
+		iExtensions->ResetAndDestroy();
+		}
+	delete iExtensions;
+	}
+
+EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
+	{
+	return	(	(*(iSerialNumber) == *(aCert.iSerialNumber)) && 
+				(iIssuerName->ExactMatchL(*(aCert.iIssuerName)))	);
+	}
+
+EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
+	{
+	if (iIssuerName != NULL) //just to check cert is uninitialised
+		{
+		User::Leave(KErrArgument);
+		}
+	iKeyFactory = new(ELeave) TX509KeyFactory;
+	
+	TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
+	HBufC8* temp= HBufC8::NewLC(len);	
+	TPtr8 ptr=temp->Des();
+	aStream.ReadL(ptr,len);
+	iEncoding=temp->AllocL();
+	CleanupStack::PopAndDestroy(); // temp
+
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
+	TASN1DecGeneric* encSigAlg = seq->At(1);
+	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
+	TASN1DecBitString encBS;
+	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
+	CleanupStack::PopAndDestroy();//seq	
+
+	CSHA1* hash = CSHA1::NewL();
+	CleanupStack::PushL(hash);
+	iFingerprint = hash->Final(Encoding()).AllocL();
+	CleanupStack::PopAndDestroy();//hash
+
+	ConstructCertL();
+	}
+
+void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
+	{
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
+	TInt count = seq->Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		TASN1DecGeneric* gen = seq->At(i);
+		CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
+		iExtensions->AppendL(ext);
+		CleanupStack::Pop();//ext
+		}
+	CleanupStack::PopAndDestroy();//
+	aHasElementAlready = ETrue;
+	}
+
+HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
+	{
+	if ((aHasElementAlready) || (iVersion ==1))
+		{
+		User::Leave(KErrArgument);
+		}
+	aHasElementAlready = ETrue;
+	return aBinaryData.AllocL();
+	}
+
+//***************************************************************************************//
+//extra accessors
+EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
+	{
+	TASN1DecSequence encSeq;
+	TInt pos = 0;
+	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
+	TASN1DecGeneric* gen = seq->At(0);
+	TPtrC8 res = gen->Encoding();
+	CleanupStack::PopAndDestroy();
+	return res;
+	}
+
+EXPORT_C TInt CX509Certificate::Version() const
+	{
+	return iVersion;
+	}
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value 
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
+* null characters in the second byte of each character. This will work as expected 
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
+	{
+	return *iIssuerName;
+	}
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value 
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
+* null characters in the second byte of each character. This will work as expected 
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
+	{
+	return *iSubjectName;
+	}
+
+EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
+	{
+	return *iExtensions;
+	}
+
+EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
+	{
+	TInt count = iExtensions->Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		CX509CertExtension* ext = iExtensions->At(i);
+		if (ext->Id() == aExtensionName)
+			return ext;
+		}
+	return NULL;
+	}
+
+EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
+	{
+	return iDataElements->At(aIndex);
+	}
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value 
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
+* null characters in the second byte of each character. This will work as expected 
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C HBufC* CX509Certificate::IssuerL() const
+	{
+	return iIssuerName->DisplayNameL();
+	}
+
+/**
+* If the certificate has decoded the members from TeletexString then the return value 
+* may be incorrect because TeletexString type is not fully supported by this library.
+* Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
+* null characters in the second byte of each character. This will work as expected 
+* for cases where the string contains ASCII data.
+*/
+EXPORT_C HBufC* CX509Certificate::SubjectL() const
+	{
+	return iSubjectName->DisplayNameL();
+	}
+
+EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
+	{
+	if (iSubjectName->Count() > 0)
+		{
+		return iSubjectName->ExactMatchL(*iIssuerName);
+		}
+	else
+		{
+		TBool res = EFalse;
+		const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
+		const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
+		if ((subjectExt) && (issuerExt))
+			{
+			const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
+			const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
+			if (subjectAltName->Match(*issuerAltName))
+				{
+				res = ETrue;
+				}
+			CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
+			}
+		return res;
+		} 
+	}
+
+
+EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const	
+	{
+	if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
+		{
+		// The base class handles the RSA case and leaves with KErrNotSupported if
+		// it is not RSA.
+		return CCertificate::KeyIdentifierL();
+		}
+	else
+		{
+		// This handles the DSA case
+		CDSAPublicKey* dsaKey = 
+						iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(), 
+													iSubjectPublicKeyInfo->KeyData());
+		CleanupStack::PushL(dsaKey);
+		TKeyIdentifier retVal;
+		KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
+		CleanupStack::PopAndDestroy(dsaKey);
+		return retVal;
+		}
+	}
+
+EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
+	{	
+	const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
+	if (subjectKeyIdExtStr)
+		{
+		TKeyIdentifier ret;
+		CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
+		// Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
+		if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
+			{
+			ret.Copy(subjectKeyIdExt->KeyId());
+			CleanupStack::PopAndDestroy(subjectKeyIdExt);
+			return ret;
+			}
+		CleanupStack::PopAndDestroy(subjectKeyIdExt);
+		}
+		
+	return KeyIdentifierL();
+	}