cryptoservices/certificateandkeymgmt/x509/x509cert.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * -- FingerPrint Note:
       
    16 * Developers have to be aware that if they are going to change the fingerprint for this certificate
       
    17 * for a different hash, then there are other places that need to reflect this change
       
    18 * -- Location
       
    19 * void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
       
    20 * EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
       
    21 * Also change the CWTLSCertificate and search for other occurences of the current
       
    22 * hash.
       
    23 * -- TeletexString type support Note:
       
    24 * If the certificate has decoded the members from TeletexString then the return value 
       
    25 * may be incorrect because TeletexString type is not fully supported by this library.
       
    26 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
       
    27 * null characters in the second byte of each character. This will work as expected 
       
    28 * for cases where the string contains ASCII data.
       
    29 *
       
    30 */
       
    31 
       
    32 
       
    33 
       
    34 
       
    35 #include <x509cert.h>
       
    36 #include <x509certext.h>
       
    37 #include "X509time.h"
       
    38 #include <x509keys.h>
       
    39 #include <keyidentifierutil.h>
       
    40 #include <asn1enc.h>
       
    41 #include <asn1dec.h>
       
    42 
       
    43 EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
       
    44 	{
       
    45 	CPKCS1SignatureResult* self = CPKCS1SignatureResult::NewLC(aDigestAlgorithm, aDigest);
       
    46 	CleanupStack::Pop();
       
    47 	return self;
       
    48 	}
       
    49 
       
    50 EXPORT_C CPKCS1SignatureResult* CPKCS1SignatureResult::NewLC(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
       
    51 	{
       
    52 	CPKCS1SignatureResult* self = new(ELeave) CPKCS1SignatureResult;
       
    53 	CleanupStack::PushL(self);
       
    54 	self->ConstructL(aDigestAlgorithm, aDigest);
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 void CPKCS1SignatureResult::ConstructL(const CAlgorithmIdentifier& aDigestAlgorithm, const TDesC8& aDigest)
       
    59 	{
       
    60 	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
       
    61 	iDigest = aDigest.AllocL();
       
    62 	}
       
    63 
       
    64 EXPORT_C TBool CPKCS1SignatureResult::VerifyL(const TDesC8& aResult)
       
    65 	{
       
    66 
       
    67 	TBool res = EFalse;
       
    68 	TRAPD(err, res = DoVerifyL(aResult));
       
    69 	if ((err != KErrNone) && (err != KErrArgument))
       
    70 		{
       
    71 		User::Leave(err);
       
    72 		}
       
    73 	return res;
       
    74 	}
       
    75 
       
    76 TBool CPKCS1SignatureResult::DoVerifyL(const TDesC8& aResult)
       
    77 	{
       
    78 	TBool res = EFalse;
       
    79 	TASN1DecSequence decSeq;
       
    80 	TInt pos = 0;
       
    81 	TInt len = aResult.Length();
       
    82 
       
    83 	const CArrayPtrFlat<TASN1DecGeneric>* seq = decSeq.DecodeDERLC(aResult, pos);
       
    84 	if (seq->Count() == 2)
       
    85 		{
       
    86 		const TASN1DecGeneric* gen1 = seq->At(0);
       
    87 		const TASN1DecGeneric* gen2 = seq->At(1);
       
    88 		CAlgorithmIdentifier* algId = CX509AlgorithmIdentifier::NewLC(gen1->Encoding());
       
    89 		HBufC8* digest = gen2->GetContentDER().AllocL();
       
    90 		if ((*algId == *iDigestAlgorithm) && (*digest == *iDigest)  && (pos == len))
       
    91 			{
       
    92 			res = ETrue;
       
    93 			}
       
    94 		delete digest;
       
    95 		CleanupStack::PopAndDestroy();
       
    96 		}
       
    97 	CleanupStack::PopAndDestroy();
       
    98 	return res;
       
    99 	}
       
   100 
       
   101 
       
   102 EXPORT_C CRSAPublicKey* TX509KeyFactory::RSAPublicKeyL(const TDesC8& aEncoding) const
       
   103 	{
       
   104 	return CX509RSAPublicKey::NewL(aEncoding);
       
   105 	}
       
   106 
       
   107 EXPORT_C CRSASignatureResult* TX509KeyFactory::RSASignatureResultL(const CAlgorithmIdentifier& aDigestAlgorithm, TDesC8& aDigest) const
       
   108 	{
       
   109 	return CPKCS1SignatureResult::NewL(aDigestAlgorithm, aDigest);
       
   110 	}
       
   111 
       
   112 EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const TDesC8& aParamsEncoding, const TDesC8& aEncoding) const
       
   113 	{
       
   114 	return CX509DSAPublicKey::NewL(aParamsEncoding, aEncoding);
       
   115 	}
       
   116 
       
   117 EXPORT_C CDSAPublicKey* TX509KeyFactory::DSAPublicKeyL(const CDSAParameters& aParams, const TDesC8& aEncoding) const
       
   118 	{
       
   119 	return CX509DSAPublicKey::NewL(aParams, aEncoding);
       
   120 	}
       
   121 
       
   122 
       
   123 EXPORT_C CDSASignature* TX509KeyFactory::DSASignatureL(const TDesC8& aEncoding) const
       
   124 	{
       
   125 	return CX509DSASignature::NewL(aEncoding);
       
   126 	}
       
   127 
       
   128 EXPORT_C CDSAParameters* TX509KeyFactory::DSAParametersL(const TDesC8& aParamsEncoding) const
       
   129 {
       
   130 	return (CX509DSAPublicKey::DSAParametersL(aParamsEncoding));
       
   131 }
       
   132 
       
   133 //CX509ValidityPeriod
       
   134 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData)
       
   135 	{
       
   136 	TInt pos = 0;
       
   137 	return CX509ValidityPeriod::NewL(aBinaryData, pos);
       
   138 	}
       
   139 
       
   140 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData)
       
   141 	{
       
   142 	TInt pos = 0;
       
   143 	return CX509ValidityPeriod::NewLC(aBinaryData, pos);
       
   144 	}
       
   145 
       
   146 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewL(const TDesC8& aBinaryData, TInt& aPos)
       
   147 	{
       
   148 	CX509ValidityPeriod* self = CX509ValidityPeriod::NewLC(aBinaryData, aPos);
       
   149 	CleanupStack::Pop();
       
   150 	return self;
       
   151 	}
       
   152 
       
   153 EXPORT_C CX509ValidityPeriod* CX509ValidityPeriod::NewLC(const TDesC8& aBinaryData, TInt& aPos)
       
   154 	{
       
   155 	CX509ValidityPeriod* self = new(ELeave) CX509ValidityPeriod;
       
   156 	CleanupStack::PushL(self);
       
   157 	self->ConstructL(aBinaryData, aPos);
       
   158 	return self;
       
   159 	}
       
   160 
       
   161 CX509ValidityPeriod::CX509ValidityPeriod()
       
   162 	{
       
   163 	}
       
   164 
       
   165 void CX509ValidityPeriod::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
       
   166 	{
       
   167 	TASN1DecSequence encSeq;
       
   168 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos);
       
   169 	if (seq->Count() != 2)
       
   170 		{
       
   171 		User::Leave(KErrArgument);
       
   172 		}
       
   173 	TASN1DecX509Time decTime;
       
   174 	iStart = decTime.DecodeDERL(*(seq->At(0)));
       
   175 	iFinish = decTime.DecodeDERL(*(seq->At(1)));
       
   176 	CleanupStack::PopAndDestroy();//seq + contents
       
   177 	}
       
   178 
       
   179 //algorithm id
       
   180 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
       
   181 	{
       
   182 	TInt pos = 0;
       
   183 	return CX509AlgorithmIdentifier::NewL(aBinaryData, pos);
       
   184 	}
       
   185 
       
   186 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
       
   187 	{
       
   188 	TInt pos = 0;
       
   189 	return CX509AlgorithmIdentifier::NewLC(aBinaryData, pos);
       
   190 	}
       
   191 
       
   192 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
       
   193 	{
       
   194 	CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aBinaryData, aPos);
       
   195 	CleanupStack::Pop();
       
   196 	return self;
       
   197 	}
       
   198 
       
   199 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
       
   200 	{
       
   201 	CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier;
       
   202 	CleanupStack::PushL(self);
       
   203 	self->InitializeL(aBinaryData, aPos);
       
   204 	return self;
       
   205 	}
       
   206 
       
   207 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewL(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
       
   208  	{
       
   209 	CX509AlgorithmIdentifier* self = CX509AlgorithmIdentifier::NewLC(aAlgorithmId, aEncodedParams);
       
   210  	CleanupStack::Pop();
       
   211  	return self;	
       
   212  	}
       
   213  	
       
   214 EXPORT_C CX509AlgorithmIdentifier* CX509AlgorithmIdentifier::NewLC(TAlgorithmId aAlgorithmId, const TDesC8& aEncodedParams)
       
   215  	{
       
   216  	CX509AlgorithmIdentifier* self = new(ELeave) CX509AlgorithmIdentifier(aAlgorithmId);
       
   217  	CleanupStack::PushL(self);
       
   218  	self->ConstructL(aEncodedParams);
       
   219  	return self;				
       
   220  	}
       
   221 
       
   222 CX509AlgorithmIdentifier::CX509AlgorithmIdentifier(TAlgorithmId& aAlgorithmId):CAlgorithmIdentifier(aAlgorithmId)
       
   223  	{
       
   224  	}
       
   225 
       
   226 
       
   227 CX509AlgorithmIdentifier::CX509AlgorithmIdentifier()
       
   228 	{
       
   229 	}
       
   230 
       
   231 void CX509AlgorithmIdentifier::InitializeL(const TDesC8& aBinaryData, TInt& aPos)
       
   232 	{
       
   233 	TASN1DecSequence encSeq;
       
   234 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
       
   235 	TInt count = seq->Count();
       
   236 	TASN1DecObjectIdentifier encOID;
       
   237 	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
       
   238 	CleanupStack::PushL(oid);
       
   239 	TPtrC oidDes(oid->Des()); 
       
   240 	if (oidDes == KDSA)
       
   241 		{
       
   242 		//optional params
       
   243 		if (count > 1)//if we still have stuff left
       
   244 			{
       
   245 			TASN1DecGeneric* gen = seq->At(1);
       
   246 			iEncodedParams = gen->Encoding().AllocL();
       
   247 			}
       
   248 		else
       
   249 			{
       
   250 			iEncodedParams = HBufC8::NewL(1);
       
   251 			*iEncodedParams = KNullDesC8;
       
   252 			}
       
   253 		iAlgorithmId = EDSA;
       
   254 		CleanupStack::PopAndDestroy(2);//seq, oid
       
   255 		return;
       
   256 		}
       
   257 	if (count > 1)
       
   258 		{
       
   259 		TASN1DecGeneric* gen = seq->At(1);
       
   260 		if (oidDes == KDH)
       
   261 			{
       
   262 			iEncodedParams = gen->Encoding().AllocL();
       
   263 			iAlgorithmId = EDH;
       
   264 			CleanupStack::PopAndDestroy(2);//seq, oid
       
   265 			return;
       
   266 			}
       
   267 		if (oidDes == KRSA)
       
   268 			{
       
   269 			iAlgorithmId = ERSA;
       
   270 			TASN1DecNull null;
       
   271 			null.DecodeDERL(*gen);//just to check the syntax is OK
       
   272 			iEncodedParams = HBufC8::NewL(1);
       
   273 			*iEncodedParams = KNullDesC8;
       
   274 			CleanupStack::PopAndDestroy(2);//seq, oid
       
   275 			return;
       
   276 			}
       
   277 		if (oidDes == KMD5)
       
   278 			{
       
   279 			iAlgorithmId = EMD5;
       
   280 			TASN1DecNull null;
       
   281 			null.DecodeDERL(*gen);//just to check the syntax is OK
       
   282 			iEncodedParams = HBufC8::NewL(1);
       
   283 			*iEncodedParams = KNullDesC8;
       
   284 			CleanupStack::PopAndDestroy(2);//seq, oid
       
   285 			return;
       
   286 			}
       
   287 		if (oidDes == KMD2)
       
   288 			{
       
   289 			iAlgorithmId = EMD2;
       
   290 			TASN1DecNull null;
       
   291 			null.DecodeDERL(*gen);//just to check the syntax is OK
       
   292 			iEncodedParams = HBufC8::NewL(1);
       
   293 			*iEncodedParams = KNullDesC8;
       
   294 			CleanupStack::PopAndDestroy(2);//seq, oid
       
   295 			return;
       
   296 			}
       
   297 		if (oidDes == KSHA1)
       
   298 			{
       
   299 			iAlgorithmId = ESHA1;
       
   300 			TASN1DecNull null;
       
   301 			null.DecodeDERL(*gen);//just to check the syntax is OK
       
   302 			iEncodedParams = HBufC8::NewL(1);
       
   303 			*iEncodedParams = KNullDesC8;
       
   304 			CleanupStack::PopAndDestroy(2);//seq, oid
       
   305 			return;
       
   306 			}
       
   307 		}
       
   308 	User::Leave(KErrNotSupported);
       
   309 	}
       
   310 	
       
   311 EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
       
   312 	{
       
   313 	// the root sequence contains the signed object
       
   314 	CASN1EncSequence* root = CASN1EncSequence::NewLC();
       
   315 	
       
   316 	//encode the oid
       
   317 	CASN1EncObjectIdentifier* oid(NULL);
       
   318 	switch (iAlgorithmId)
       
   319 		{
       
   320 	case EDSA:
       
   321 		oid=CASN1EncObjectIdentifier::NewLC(KDSA);
       
   322 		break;
       
   323 		
       
   324 	case EDH:
       
   325 		oid=CASN1EncObjectIdentifier::NewLC(KDH);
       
   326 		break;
       
   327 		
       
   328 	case ERSA:
       
   329 		oid=CASN1EncObjectIdentifier::NewLC(KRSA);
       
   330 		break;
       
   331 		
       
   332 	case EMD5:
       
   333 		oid=CASN1EncObjectIdentifier::NewLC(KMD5);
       
   334 		break;
       
   335 		
       
   336 	case EMD2:
       
   337 		oid=CASN1EncObjectIdentifier::NewLC(KMD2);
       
   338 		break;
       
   339 		
       
   340 	case ESHA1:
       
   341 		oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
       
   342 		break;
       
   343 		
       
   344 	default:
       
   345 		User::Leave(KErrNotSupported);
       
   346 		}
       
   347 	
       
   348 	root->AddAndPopChildL(oid);
       
   349 	
       
   350 	//Encode parameters
       
   351 	if (*iEncodedParams!=KNullDesC8)
       
   352 		{
       
   353 		CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
       
   354 		root->AddAndPopChildL(enc);
       
   355 		}
       
   356 	else
       
   357 		{
       
   358 		if (iAlgorithmId!=EDSA)
       
   359 			{
       
   360 			CASN1EncNull* enc=CASN1EncNull::NewLC();
       
   361 			root->AddAndPopChildL(enc);				
       
   362 			}
       
   363 		}
       
   364 		
       
   365 	return root;		
       
   366 	}
       
   367 	
       
   368 
       
   369 //signing algorithm id
       
   370 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
       
   371 	{
       
   372 	TInt pos = 0;
       
   373 	return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
       
   374 	}
       
   375 
       
   376 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
       
   377 	{
       
   378 	TInt pos = 0;
       
   379 	return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
       
   380 	}
       
   381 
       
   382 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
       
   383 	{
       
   384 	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
       
   385 	CleanupStack::Pop();
       
   386 	return self;
       
   387 	}
       
   388 
       
   389 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
       
   390 	{
       
   391 	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
       
   392 	CleanupStack::PushL(self);
       
   393 	self->ConstructL(aBinaryData, aPos);
       
   394 	return self;
       
   395 	}
       
   396 
       
   397 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
       
   398  	{
       
   399  	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
       
   400  	CleanupStack::Pop();
       
   401  	return self;
       
   402  	}
       
   403  
       
   404 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
       
   405  	{
       
   406  	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
       
   407  	CleanupStack::PushL(self);
       
   408  	self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
       
   409  	return self;
       
   410  	}
       
   411 
       
   412 CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
       
   413 	{
       
   414 	}
       
   415 
       
   416 void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
       
   417 	{
       
   418 	TASN1DecSequence encSeq;
       
   419 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
       
   420 	TInt count = seq->Count();
       
   421 	TASN1DecObjectIdentifier encOID;
       
   422 	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
       
   423 	CleanupStack::PushL(oid);
       
   424 	TPtrC oidDes(oid->Des()); 
       
   425 	//none of the signing algorithms we support have parameters here...
       
   426 	HBufC8* encodedParams = HBufC8::NewLC(1);
       
   427 	*encodedParams = KNullDesC8;
       
   428 
       
   429 	if (oidDes == KDSAWithSHA1)
       
   430 		{
       
   431 		//should be no params, but we allow params encoded as NULL for interop reasons
       
   432 		TAlgorithmId algId = EDSA;
       
   433 		TAlgorithmId digestId = ESHA1;
       
   434 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
       
   435 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
       
   436 		if (count == 1)
       
   437 			{			
       
   438 			CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
       
   439 			return;
       
   440 			}
       
   441 		}
       
   442 
       
   443 	if (oidDes == KMD2WithRSA)
       
   444 		{
       
   445 		TAlgorithmId algId = ERSA;
       
   446 		TAlgorithmId digestId = EMD2;
       
   447 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
       
   448 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
       
   449 		}
       
   450 
       
   451 	if (oidDes == KMD5WithRSA)
       
   452 		{
       
   453 		TAlgorithmId algId = ERSA;
       
   454 		TAlgorithmId digestId = EMD5;
       
   455 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
       
   456 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
       
   457 		}
       
   458 
       
   459 	if (oidDes == KSHA1WithRSA)
       
   460 		{
       
   461 		TAlgorithmId algId = ERSA;
       
   462 		TAlgorithmId digestId = ESHA1;
       
   463 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
       
   464 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
       
   465 		}
       
   466 		//???not sure if we should just leave here...
       
   467 	if (iDigestAlgorithm == NULL)
       
   468 		{	
       
   469 		User::Leave(KErrNotSupported);
       
   470 		}
       
   471 	else
       
   472 		{
       
   473 		if (count != 2)
       
   474 			{
       
   475 			// Shouldn't ever get here, since RFC2459 mandates having 2
       
   476 			// data items.  However, some people miss out the second
       
   477 			// when it's NULL, so we'll not report and error here
       
   478 			}
       
   479 		else
       
   480 			{
       
   481 			TASN1DecGeneric* gen = seq->At(1);
       
   482 			TASN1DecNull null;
       
   483 			null.DecodeDERL(*gen);//just to check the syntax is OK
       
   484 			}
       
   485 		}
       
   486 	CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
       
   487 	}
       
   488 
       
   489 void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
       
   490  	{
       
   491  	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
       
   492  	iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
       
   493  	};
       
   494 
       
   495 //subject public key info
       
   496 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
       
   497 	{
       
   498 	CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
       
   499 	CleanupStack::Pop();
       
   500 	return self;
       
   501 	}
       
   502 
       
   503 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
       
   504 	{
       
   505 	CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
       
   506 	CleanupStack::PushL(self);
       
   507 	self->ConstructL(aBinaryData, aPos);
       
   508 	return self;
       
   509 	}
       
   510 
       
   511 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
       
   512 	{
       
   513 	TInt pos = 0;
       
   514 	return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
       
   515 	}
       
   516 
       
   517 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
       
   518 	{
       
   519 	TInt pos = 0;
       
   520 	return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
       
   521 	}
       
   522 
       
   523 CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
       
   524 	{
       
   525 	}
       
   526 
       
   527 void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
       
   528 	{
       
   529 	TASN1DecSequence encSeq;
       
   530 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
       
   531 	iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
       
   532 	TASN1DecBitString encBS;
       
   533 	iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
       
   534 	CleanupStack::PopAndDestroy();//seq
       
   535 	}
       
   536 
       
   537 //generic X 509 extension syntax
       
   538 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
       
   539 	{
       
   540 	CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
       
   541 	CleanupStack::Pop();
       
   542 	return self;
       
   543 	}
       
   544 
       
   545 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
       
   546 	{
       
   547 	CX509CertExtension* self = new(ELeave) CX509CertExtension;
       
   548 	CleanupStack::PushL(self);
       
   549 	self->ConstructL(aExtension);
       
   550 	return self;
       
   551 	}
       
   552 
       
   553 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
       
   554 	{
       
   555 	CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
       
   556 	CleanupStack::Pop();
       
   557 	return self;
       
   558 	}
       
   559 
       
   560 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
       
   561 	{
       
   562 	CX509CertExtension* self = new(ELeave) CX509CertExtension;
       
   563 	CleanupStack::PushL(self);
       
   564 	self->ConstructL(aBinaryData, aPos);
       
   565 	return self;
       
   566 	}
       
   567 
       
   568 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
       
   569 	{
       
   570 	TInt pos = 0;
       
   571 	return CX509CertExtension::NewL(aBinaryData, pos);
       
   572 	}
       
   573 
       
   574 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
       
   575 	{
       
   576 	TInt pos = 0;
       
   577 	return CX509CertExtension::NewLC(aBinaryData, pos);
       
   578 	}
       
   579 
       
   580 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID, 
       
   581 							const TBool aCritical,
       
   582 							const TDesC8& aCertExtValue)
       
   583 	{
       
   584 	CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
       
   585 	CleanupStack::Pop();
       
   586 	return self;
       
   587 	}
       
   588 
       
   589 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID, 
       
   590 							const TBool aCritical,
       
   591 							const TDesC8& aCertExtValue)
       
   592 	{
       
   593 	CX509CertExtension* self = new(ELeave) CX509CertExtension;
       
   594 	CleanupStack::PushL(self);
       
   595 	self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
       
   596 	return self;
       
   597 	}
       
   598 
       
   599 void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
       
   600 	{
       
   601 	iCritical = aExtension.iCritical;
       
   602 	iId = aExtension.iId->Des().AllocL();
       
   603 	iData = aExtension.iData->Des().AllocL();
       
   604 	}
       
   605 
       
   606 void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
       
   607 	{
       
   608 	TASN1DecSequence encSeq;
       
   609 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
       
   610 
       
   611 	TASN1DecObjectIdentifier encOID;
       
   612 	iId = encOID.DecodeDERL(*(seq->At(0)));
       
   613 	//second is either critical flag, or the ext
       
   614 	TASN1DecGeneric* second = seq->At(1);
       
   615 	if (second->Tag() != EASN1Boolean)
       
   616 		{
       
   617 		iData = second->Encoding().AllocL();
       
   618 		aPos += second->LengthDER();
       
   619 		}
       
   620 	else
       
   621 		{
       
   622 		TASN1DecBoolean encBool;
       
   623 		iCritical = encBool.DecodeDERL(*second);
       
   624 		if (seq->Count() != 3)
       
   625 			{
       
   626 			User::Leave(KErrArgument);
       
   627 			}
       
   628 
       
   629 		TASN1DecGeneric* third = seq->At(2);
       
   630 		iData = third->Encoding().AllocL();
       
   631 		}
       
   632 	CleanupStack::PopAndDestroy();//seq
       
   633 	}
       
   634 
       
   635 void CX509CertExtension::ConstructL(const TDesC& aCertExtOID, 
       
   636 									const TBool aCritical,
       
   637 									const TDesC8& aCertExtValue)
       
   638 	{
       
   639 	iId = aCertExtOID.AllocL();
       
   640 	iCritical = aCritical;
       
   641 	iData = aCertExtValue.AllocL();
       
   642 	}
       
   643 
       
   644 EXPORT_C CX509CertExtension::~CX509CertExtension()
       
   645 	{
       
   646 	delete iData;
       
   647 	delete iId;
       
   648 	}
       
   649 
       
   650 EXPORT_C TBool CX509CertExtension::Critical() const
       
   651 	{
       
   652 	return iCritical;
       
   653 	}
       
   654 
       
   655 EXPORT_C TPtrC CX509CertExtension::Id() const	//OID for the extension
       
   656 	{
       
   657 	return iId->Des();
       
   658 	}
       
   659 
       
   660 EXPORT_C TPtrC8 CX509CertExtension::Data() const	 //the extension itself
       
   661 	{
       
   662 	return iData->Des();
       
   663 	}
       
   664 
       
   665 EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
       
   666 	{
       
   667 	CASN1EncSequence *result = CASN1EncSequence::NewLC();
       
   668 	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
       
   669 	result->AddAndPopChildL(oid);
       
   670 	// Encode critical flag only if true
       
   671 	if (iCritical)
       
   672 		{
       
   673 		CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
       
   674 		result->AddAndPopChildL(critical);
       
   675 		}	
       
   676 	CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
       
   677 	result->AddAndPopChildL(data);
       
   678 	return result;
       
   679 	}
       
   680 
       
   681 CX509CertExtension::CX509CertExtension()
       
   682 	:iCritical(EFalse)
       
   683 	{
       
   684 	}
       
   685 
       
   686 //CX509Certificate
       
   687 EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
       
   688 	{
       
   689 	CX509Certificate* self = CX509Certificate::NewLC(aCert);
       
   690 	CleanupStack::Pop();//self
       
   691 	return self;
       
   692 	}
       
   693 
       
   694 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
       
   695 	{
       
   696 	CX509Certificate* self = new(ELeave) CX509Certificate;
       
   697 	CleanupStack::PushL(self);
       
   698 	self->ConstructL(aCert);
       
   699 	return self;
       
   700 	}
       
   701 
       
   702 EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
       
   703 	{
       
   704 	TInt pos = 0;
       
   705 	return CX509Certificate::NewL(aBinaryData, pos);
       
   706 	}
       
   707 
       
   708 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
       
   709 	{	
       
   710 	TInt pos = 0;
       
   711 	return CX509Certificate::NewLC(aBinaryData, pos);
       
   712 	}
       
   713 
       
   714 EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
       
   715 	{
       
   716 	CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
       
   717 	CleanupStack::Pop();
       
   718 	return self;
       
   719 	}
       
   720 
       
   721 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
       
   722 	{	
       
   723 	CX509Certificate* self = new(ELeave) CX509Certificate();
       
   724 	CleanupStack::PushL(self);
       
   725 	self->ConstructL(aBinaryData, aPos);
       
   726 	return self;
       
   727 	}
       
   728 
       
   729 EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
       
   730 	{
       
   731 	CX509Certificate* self = CX509Certificate::NewLC(aStream);
       
   732 	CleanupStack::Pop();//self
       
   733 	return self;
       
   734 	}
       
   735 
       
   736 EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
       
   737 	{
       
   738 	CX509Certificate* self = new(ELeave) CX509Certificate;
       
   739 	CleanupStack::PushL(self);
       
   740 	self->InternalizeL(aStream);
       
   741 	return self;
       
   742 	}
       
   743 
       
   744 void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
       
   745 	{
       
   746 	TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
       
   747 	gen.InitL();
       
   748 	
       
   749 	// The outermost tag for X509 certificates is always a sequence.
       
   750 	// Since this tag does not form part of the signed data it is possible
       
   751 	// to corrupt the tag by changing it to any other ASN.1 tag and process
       
   752 	// the rest of the certificate as normal.
       
   753 	// However, we still reject the certificate anyway to avoid 
       
   754 	// confusion because the data does not match the X.509 specification.	
       
   755 	if (gen.Tag() != EASN1Sequence)
       
   756 		{
       
   757 		User::Leave(KErrArgument);
       
   758 		}
       
   759 	
       
   760 	aPos += gen.LengthDER();
       
   761 	iKeyFactory = new(ELeave) TX509KeyFactory;
       
   762 
       
   763 	iEncoding = gen.Encoding().AllocL();
       
   764 
       
   765 	TASN1DecSequence encSeq;
       
   766 	TInt pos = 0;
       
   767 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
       
   768 	TASN1DecGeneric* encSigAlg = seq->At(1);
       
   769 	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
       
   770 	TASN1DecBitString encBS;
       
   771 	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
       
   772 	CleanupStack::PopAndDestroy();//seq
       
   773 
       
   774 	CSHA1* hash = CSHA1::NewL();
       
   775 	CleanupStack::PushL(hash);
       
   776 	iFingerprint = hash->Final(Encoding()).AllocL();
       
   777 	CleanupStack::PopAndDestroy();//hash
       
   778 	ConstructCertL();
       
   779 	}
       
   780 
       
   781 void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
       
   782 	{
       
   783 	iKeyFactory = new(ELeave) TX509KeyFactory;
       
   784 
       
   785 	iEncoding = aCertificate.iEncoding->AllocL();
       
   786 	iSignature = aCertificate.iSignature->AllocL();
       
   787 	iFingerprint = aCertificate.iFingerprint->AllocL();
       
   788 	iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());	
       
   789 	iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
       
   790 	iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
       
   791 	iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
       
   792 	iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
       
   793 	iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
       
   794 	iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
       
   795 	iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
       
   796 	iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
       
   797 	TInt count = aCertificate.iExtensions->Count();
       
   798 	for (TInt i = 0; i < count; i++)
       
   799 		{
       
   800 		CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
       
   801 		iExtensions->AppendL(ext);
       
   802 		CleanupStack::Pop();//ext
       
   803 		}
       
   804 	iVersion = aCertificate.Version();
       
   805 	InitDataElementsL(aCertificate);
       
   806 	}
       
   807 
       
   808 void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
       
   809 	{
       
   810 	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
       
   811 	iDataElements->Reset();
       
   812 	TPtrC8 signedData = SignedDataL();
       
   813 	TASN1DecSequence encSeq;
       
   814 	TInt pos = 0;
       
   815 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
       
   816 	pos = 0;
       
   817 
       
   818 	TPtrC8** pElement = iDataElements->Begin();
       
   819 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
       
   820 	for (TInt i = 0; i < 6; i++)	//init all the non-optional elements
       
   821 		{
       
   822 		*pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
       
   823 		}
       
   824 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
       
   825 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
       
   826 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
       
   827 	CleanupStack::PopAndDestroy();
       
   828 	}
       
   829 
       
   830 void CX509Certificate::ConstructCertL()
       
   831 	{
       
   832 	TPtrC8 signedData = SignedDataL();
       
   833 	TASN1DecSequence encSeq;
       
   834 	TInt pos = 0;
       
   835 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
       
   836 	TInt count = seq->Count();
       
   837 	pos = 0;
       
   838 	TASN1DecGeneric* curr = seq->At(pos);
       
   839 	pos++;
       
   840 	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
       
   841 	iDataElements->Reset();
       
   842 	TPtrC8** pElement = iDataElements->Begin();
       
   843 	if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
       
   844 		{
       
   845 		//version!
       
   846 		TASN1DecGeneric ver(curr->GetContentDER());
       
   847 		ver.InitL();
       
   848 		TPtrC8 pVer8 = ver.GetContentDER();
       
   849 		if(pVer8.Length() != 1)
       
   850 			{
       
   851 			User::Leave(KErrArgument);
       
   852 			}
       
   853 		iVersion = (pVer8[0]) + 1;
       
   854 		if ((iVersion < 1) || (iVersion > 3) || (count < 7))
       
   855 			{
       
   856 			User::Leave(KErrArgument);
       
   857 			}
       
   858 		*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   859 		curr = seq->At(pos);
       
   860 		pos++;
       
   861 		}
       
   862 	else
       
   863 		{
       
   864 		*pElement++ = NULL;
       
   865 		}
       
   866 	if (curr->Tag() != EASN1Integer)
       
   867 		{
       
   868 		User::Leave(KErrArgument);
       
   869 		}
       
   870 	iSerialNumber = (curr->GetContentDER()).AllocL();
       
   871 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   872 	curr = seq->At(pos);
       
   873 	pos++;
       
   874 	CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
       
   875 	if (!(SigningAlgorithm() == *(algorithmId)))
       
   876 		{
       
   877 		User::Leave(KErrArgument);
       
   878 		}
       
   879 	CleanupStack::PopAndDestroy();//algorithmId
       
   880 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   881 
       
   882 	curr = seq->At(pos);
       
   883 	pos++;
       
   884 	iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
       
   885 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   886 	curr = seq->At(pos);
       
   887 	pos++;
       
   888 	iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
       
   889 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   890 	curr = seq->At(pos);
       
   891 	pos++;
       
   892 	iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
       
   893 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   894 	curr = seq->At(pos);
       
   895 	pos++;
       
   896 	iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
       
   897 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   898 	//do issuer uid, subject uid, exts
       
   899 	//these are all optional
       
   900 	TBool hasIssuerUid = EFalse;
       
   901 	TBool hasSubjectUid = EFalse;
       
   902 	TBool hasExts = EFalse;
       
   903 	iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
       
   904 	if (pos < count)//otherwise there aren't any of 'em
       
   905 		{
       
   906 		curr = seq->At(pos);
       
   907 		pos++;
       
   908 		if (curr->Class() != EContextSpecific)
       
   909 			{
       
   910 			User::Leave(KErrArgument);
       
   911 			}
       
   912 		switch(curr->Tag())
       
   913 			{
       
   914 			case 1:
       
   915 				{
       
   916 				iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
       
   917 				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   918 				break;
       
   919 				}
       
   920 			case 2:
       
   921 				{
       
   922 				iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
       
   923 				*pElement++ = NULL;
       
   924 				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   925 				break;
       
   926 				}
       
   927 			case 3:
       
   928 				{
       
   929 				DecodeExtsL(curr->GetContentDER(), hasExts);
       
   930 				*pElement++ = NULL;
       
   931 				*pElement++ = NULL;
       
   932 				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   933 				break;
       
   934 				}
       
   935 			default:
       
   936 				{
       
   937 				User::Leave(KErrArgument);
       
   938 				}
       
   939 			}
       
   940 		if (pos < count)
       
   941 			{
       
   942 			curr = seq->At(pos);
       
   943 			pos++;
       
   944 			switch(curr->Tag())
       
   945 				{
       
   946 				case 2:
       
   947 					{
       
   948 					iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
       
   949 					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   950 					break;
       
   951 					}
       
   952 				case 3:
       
   953 					{
       
   954 					DecodeExtsL(curr->GetContentDER(), hasExts);
       
   955 					*pElement++ = NULL;
       
   956 					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   957 					break;
       
   958 					}
       
   959 				default:
       
   960 					{
       
   961 					User::Leave(KErrArgument);
       
   962 					}
       
   963 				}
       
   964 			if (pos < count)
       
   965 				{
       
   966 				curr = seq->At(pos);
       
   967 				pos++;
       
   968 				if (curr->Tag() == 3)
       
   969 					{
       
   970 					DecodeExtsL(curr->GetContentDER(), hasExts);
       
   971 					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
       
   972 					}
       
   973 				else
       
   974 					{
       
   975 					User::Leave(KErrArgument);
       
   976 					}
       
   977 				}
       
   978 			}
       
   979 		}
       
   980 	if (pos != count)
       
   981 		{
       
   982 		User::Leave(KErrArgument);
       
   983 		}
       
   984 	if (!iIssuerUid)
       
   985 		{
       
   986 		iIssuerUid = HBufC8::NewL(1);
       
   987 		*iIssuerUid = KNullDesC8;
       
   988 		}
       
   989 	if (!iSubjectUid)
       
   990 		{
       
   991 		iSubjectUid = HBufC8::NewL(1);
       
   992 		*iSubjectUid = KNullDesC8;
       
   993 		}
       
   994 		
       
   995 	// we have not checked for the certificate version number based on 
       
   996 	// the certificate contents. This is primarily done to avoid BC for 
       
   997 	// clients who are still using malformed certificates.
       
   998 	
       
   999 	CleanupStack::PopAndDestroy();//seq
       
  1000 	}
       
  1001 
       
  1002 CX509Certificate::CX509Certificate()
       
  1003 	:iVersion(1)
       
  1004 	{
       
  1005 	}
       
  1006 
       
  1007 EXPORT_C CX509Certificate::~CX509Certificate()
       
  1008 	{
       
  1009 	delete iIssuerName;
       
  1010 	delete iSubjectName;
       
  1011 	delete iIssuerUid;
       
  1012 	delete iSubjectUid;
       
  1013 	
       
  1014 	if (iDataElements != NULL)
       
  1015 		{
       
  1016 		for (TInt i = 0; i < KX509MaxDataElements; i++)
       
  1017 			{
       
  1018 			delete iDataElements->At(i);
       
  1019 			}
       
  1020 		delete iDataElements;
       
  1021 		}
       
  1022 	if (iExtensions != NULL)
       
  1023 		{
       
  1024 		iExtensions->ResetAndDestroy();
       
  1025 		}
       
  1026 	delete iExtensions;
       
  1027 	}
       
  1028 
       
  1029 EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
       
  1030 	{
       
  1031 	return	(	(*(iSerialNumber) == *(aCert.iSerialNumber)) && 
       
  1032 				(iIssuerName->ExactMatchL(*(aCert.iIssuerName)))	);
       
  1033 	}
       
  1034 
       
  1035 EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
       
  1036 	{
       
  1037 	if (iIssuerName != NULL) //just to check cert is uninitialised
       
  1038 		{
       
  1039 		User::Leave(KErrArgument);
       
  1040 		}
       
  1041 	iKeyFactory = new(ELeave) TX509KeyFactory;
       
  1042 	
       
  1043 	TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
       
  1044 	HBufC8* temp= HBufC8::NewLC(len);	
       
  1045 	TPtr8 ptr=temp->Des();
       
  1046 	aStream.ReadL(ptr,len);
       
  1047 	iEncoding=temp->AllocL();
       
  1048 	CleanupStack::PopAndDestroy(); // temp
       
  1049 
       
  1050 	TASN1DecSequence encSeq;
       
  1051 	TInt pos = 0;
       
  1052 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
       
  1053 	TASN1DecGeneric* encSigAlg = seq->At(1);
       
  1054 	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
       
  1055 	TASN1DecBitString encBS;
       
  1056 	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
       
  1057 	CleanupStack::PopAndDestroy();//seq	
       
  1058 
       
  1059 	CSHA1* hash = CSHA1::NewL();
       
  1060 	CleanupStack::PushL(hash);
       
  1061 	iFingerprint = hash->Final(Encoding()).AllocL();
       
  1062 	CleanupStack::PopAndDestroy();//hash
       
  1063 
       
  1064 	ConstructCertL();
       
  1065 	}
       
  1066 
       
  1067 void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
       
  1068 	{
       
  1069 	TASN1DecSequence encSeq;
       
  1070 	TInt pos = 0;
       
  1071 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
       
  1072 	TInt count = seq->Count();
       
  1073 	for (TInt i = 0; i < count; i++)
       
  1074 		{
       
  1075 		TASN1DecGeneric* gen = seq->At(i);
       
  1076 		CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
       
  1077 		iExtensions->AppendL(ext);
       
  1078 		CleanupStack::Pop();//ext
       
  1079 		}
       
  1080 	CleanupStack::PopAndDestroy();//
       
  1081 	aHasElementAlready = ETrue;
       
  1082 	}
       
  1083 
       
  1084 HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
       
  1085 	{
       
  1086 	if ((aHasElementAlready) || (iVersion ==1))
       
  1087 		{
       
  1088 		User::Leave(KErrArgument);
       
  1089 		}
       
  1090 	aHasElementAlready = ETrue;
       
  1091 	return aBinaryData.AllocL();
       
  1092 	}
       
  1093 
       
  1094 //***************************************************************************************//
       
  1095 //extra accessors
       
  1096 EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
       
  1097 	{
       
  1098 	TASN1DecSequence encSeq;
       
  1099 	TInt pos = 0;
       
  1100 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
       
  1101 	TASN1DecGeneric* gen = seq->At(0);
       
  1102 	TPtrC8 res = gen->Encoding();
       
  1103 	CleanupStack::PopAndDestroy();
       
  1104 	return res;
       
  1105 	}
       
  1106 
       
  1107 EXPORT_C TInt CX509Certificate::Version() const
       
  1108 	{
       
  1109 	return iVersion;
       
  1110 	}
       
  1111 
       
  1112 /**
       
  1113 * If the certificate has decoded the members from TeletexString then the return value 
       
  1114 * may be incorrect because TeletexString type is not fully supported by this library.
       
  1115 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
       
  1116 * null characters in the second byte of each character. This will work as expected 
       
  1117 * for cases where the string contains ASCII data.
       
  1118 */
       
  1119 EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
       
  1120 	{
       
  1121 	return *iIssuerName;
       
  1122 	}
       
  1123 
       
  1124 /**
       
  1125 * If the certificate has decoded the members from TeletexString then the return value 
       
  1126 * may be incorrect because TeletexString type is not fully supported by this library.
       
  1127 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
       
  1128 * null characters in the second byte of each character. This will work as expected 
       
  1129 * for cases where the string contains ASCII data.
       
  1130 */
       
  1131 EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
       
  1132 	{
       
  1133 	return *iSubjectName;
       
  1134 	}
       
  1135 
       
  1136 EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
       
  1137 	{
       
  1138 	return *iExtensions;
       
  1139 	}
       
  1140 
       
  1141 EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
       
  1142 	{
       
  1143 	TInt count = iExtensions->Count();
       
  1144 	for (TInt i = 0; i < count; i++)
       
  1145 		{
       
  1146 		CX509CertExtension* ext = iExtensions->At(i);
       
  1147 		if (ext->Id() == aExtensionName)
       
  1148 			return ext;
       
  1149 		}
       
  1150 	return NULL;
       
  1151 	}
       
  1152 
       
  1153 EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
       
  1154 	{
       
  1155 	return iDataElements->At(aIndex);
       
  1156 	}
       
  1157 
       
  1158 /**
       
  1159 * If the certificate has decoded the members from TeletexString then the return value 
       
  1160 * may be incorrect because TeletexString type is not fully supported by this library.
       
  1161 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
       
  1162 * null characters in the second byte of each character. This will work as expected 
       
  1163 * for cases where the string contains ASCII data.
       
  1164 */
       
  1165 EXPORT_C HBufC* CX509Certificate::IssuerL() const
       
  1166 	{
       
  1167 	return iIssuerName->DisplayNameL();
       
  1168 	}
       
  1169 
       
  1170 /**
       
  1171 * If the certificate has decoded the members from TeletexString then the return value 
       
  1172 * may be incorrect because TeletexString type is not fully supported by this library.
       
  1173 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
       
  1174 * null characters in the second byte of each character. This will work as expected 
       
  1175 * for cases where the string contains ASCII data.
       
  1176 */
       
  1177 EXPORT_C HBufC* CX509Certificate::SubjectL() const
       
  1178 	{
       
  1179 	return iSubjectName->DisplayNameL();
       
  1180 	}
       
  1181 
       
  1182 EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
       
  1183 	{
       
  1184 	if (iSubjectName->Count() > 0)
       
  1185 		{
       
  1186 		return iSubjectName->ExactMatchL(*iIssuerName);
       
  1187 		}
       
  1188 	else
       
  1189 		{
       
  1190 		TBool res = EFalse;
       
  1191 		const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
       
  1192 		const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
       
  1193 		if ((subjectExt) && (issuerExt))
       
  1194 			{
       
  1195 			const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
       
  1196 			const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
       
  1197 			if (subjectAltName->Match(*issuerAltName))
       
  1198 				{
       
  1199 				res = ETrue;
       
  1200 				}
       
  1201 			CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
       
  1202 			}
       
  1203 		return res;
       
  1204 		} 
       
  1205 	}
       
  1206 
       
  1207 
       
  1208 EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const	
       
  1209 	{
       
  1210 	if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
       
  1211 		{
       
  1212 		// The base class handles the RSA case and leaves with KErrNotSupported if
       
  1213 		// it is not RSA.
       
  1214 		return CCertificate::KeyIdentifierL();
       
  1215 		}
       
  1216 	else
       
  1217 		{
       
  1218 		// This handles the DSA case
       
  1219 		CDSAPublicKey* dsaKey = 
       
  1220 						iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(), 
       
  1221 													iSubjectPublicKeyInfo->KeyData());
       
  1222 		CleanupStack::PushL(dsaKey);
       
  1223 		TKeyIdentifier retVal;
       
  1224 		KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
       
  1225 		CleanupStack::PopAndDestroy(dsaKey);
       
  1226 		return retVal;
       
  1227 		}
       
  1228 	}
       
  1229 
       
  1230 EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
       
  1231 	{	
       
  1232 	const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
       
  1233 	if (subjectKeyIdExtStr)
       
  1234 		{
       
  1235 		TKeyIdentifier ret;
       
  1236 		CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
       
  1237 		// Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
       
  1238 		if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
       
  1239 			{
       
  1240 			ret.Copy(subjectKeyIdExt->KeyId());
       
  1241 			CleanupStack::PopAndDestroy(subjectKeyIdExt);
       
  1242 			return ret;
       
  1243 			}
       
  1244 		CleanupStack::PopAndDestroy(subjectKeyIdExt);
       
  1245 		}
       
  1246 		
       
  1247 	return KeyIdentifierL();
       
  1248 	}