os/security/cryptoservices/certificateandkeymgmt/x509/x509cert.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 1998-2010 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         if (oidDes == KSHA224)
   309             {
   310             iAlgorithmId = ESHA224;
   311             TASN1DecNull null;
   312             null.DecodeDERL(*gen);//just to check the syntax is OK
   313             iEncodedParams = HBufC8::NewL(1);
   314             *iEncodedParams = KNullDesC8;
   315             CleanupStack::PopAndDestroy(2);//seq, oid
   316             return;
   317             }
   318         if (oidDes == KSHA256)
   319             {
   320             iAlgorithmId = ESHA256;
   321             TASN1DecNull null;
   322             null.DecodeDERL(*gen);//just to check the syntax is OK
   323             iEncodedParams = HBufC8::NewL(1);
   324             *iEncodedParams = KNullDesC8;
   325             CleanupStack::PopAndDestroy(2);//seq, oid
   326             return;
   327             }      
   328         if (oidDes == KSHA384)
   329             {
   330             iAlgorithmId = ESHA384;
   331             TASN1DecNull null;
   332             null.DecodeDERL(*gen);//just to check the syntax is OK
   333             iEncodedParams = HBufC8::NewL(1);
   334             *iEncodedParams = KNullDesC8;
   335             CleanupStack::PopAndDestroy(2);//seq, oid
   336             return;
   337             }        
   338         if (oidDes == KSHA512)
   339             {
   340             iAlgorithmId = ESHA512;
   341             TASN1DecNull null;
   342             null.DecodeDERL(*gen);//just to check the syntax is OK
   343             iEncodedParams = HBufC8::NewL(1);
   344             *iEncodedParams = KNullDesC8;
   345             CleanupStack::PopAndDestroy(2);//seq, oid
   346             return;
   347             }         
   348 	
   349 		}
   350 	User::Leave(KErrNotSupported);
   351 	}
   352 	
   353 EXPORT_C CASN1EncSequence* CX509AlgorithmIdentifier::EncodeASN1DERLC() const
   354 	{
   355 	// the root sequence contains the signed object
   356 	CASN1EncSequence* root = CASN1EncSequence::NewLC();
   357 	
   358 	//encode the oid
   359 	CASN1EncObjectIdentifier* oid(NULL);
   360 	switch (iAlgorithmId)
   361 		{
   362 	case EDSA:
   363 		oid=CASN1EncObjectIdentifier::NewLC(KDSA);
   364 		break;
   365 		
   366 	case EDH:
   367 		oid=CASN1EncObjectIdentifier::NewLC(KDH);
   368 		break;
   369 		
   370 	case ERSA:
   371 		oid=CASN1EncObjectIdentifier::NewLC(KRSA);
   372 		break;
   373 		
   374 	case EMD5:
   375 		oid=CASN1EncObjectIdentifier::NewLC(KMD5);
   376 		break;
   377 		
   378 	case EMD2:
   379 		oid=CASN1EncObjectIdentifier::NewLC(KMD2);
   380 		break;
   381 		
   382 	case ESHA1:
   383 		oid=CASN1EncObjectIdentifier::NewLC(KSHA1);
   384 		break;
   385 
   386 	case ESHA224:
   387 		oid=CASN1EncObjectIdentifier::NewLC(KSHA224);
   388 		break;
   389 
   390 	case ESHA256:
   391 		oid=CASN1EncObjectIdentifier::NewLC(KSHA256);
   392 		break;
   393 
   394 	case ESHA384:
   395 		oid=CASN1EncObjectIdentifier::NewLC(KSHA384);
   396 		break;
   397 
   398 	case ESHA512:
   399 		oid=CASN1EncObjectIdentifier::NewLC(KSHA512);
   400 		break;
   401 		
   402 	default:
   403 		User::Leave(KErrNotSupported);
   404 		}
   405 	
   406 	root->AddAndPopChildL(oid);
   407 	
   408 	//Encode parameters
   409 	if (*iEncodedParams!=KNullDesC8)
   410 		{
   411 		CASN1EncEncoding* enc=CASN1EncEncoding::NewLC(*iEncodedParams);
   412 		root->AddAndPopChildL(enc);
   413 		}
   414 	else
   415 		{
   416 		if (iAlgorithmId!=EDSA)
   417 			{
   418 			CASN1EncNull* enc=CASN1EncNull::NewLC();
   419 			root->AddAndPopChildL(enc);				
   420 			}
   421 		}
   422 		
   423 	return root;		
   424 	}
   425 	
   426 
   427 //signing algorithm id
   428 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData)
   429 	{
   430 	TInt pos = 0;
   431 	return CX509SigningAlgorithmIdentifier::NewL(aBinaryData, pos);
   432 	}
   433 
   434 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData)
   435 	{
   436 	TInt pos = 0;
   437 	return CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, pos);
   438 	}
   439 
   440 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const TDesC8& aBinaryData, TInt& aPos)
   441 	{
   442 	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aBinaryData, aPos);
   443 	CleanupStack::Pop();
   444 	return self;
   445 	}
   446 
   447 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const TDesC8& aBinaryData, TInt& aPos)
   448 	{
   449 	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
   450 	CleanupStack::PushL(self);
   451 	self->ConstructL(aBinaryData, aPos);
   452 	return self;
   453 	}
   454 
   455 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
   456  	{
   457  	CX509SigningAlgorithmIdentifier* self = CX509SigningAlgorithmIdentifier::NewLC(aAsymmetricAlgorithm, aDigestAlgorithm);
   458  	CleanupStack::Pop();
   459  	return self;
   460  	}
   461  
   462 EXPORT_C CX509SigningAlgorithmIdentifier* CX509SigningAlgorithmIdentifier::NewLC(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
   463  	{
   464  	CX509SigningAlgorithmIdentifier* self = new(ELeave) CX509SigningAlgorithmIdentifier;
   465  	CleanupStack::PushL(self);
   466  	self->ConstructL(aAsymmetricAlgorithm, aDigestAlgorithm);
   467  	return self;
   468  	}
   469 
   470 CX509SigningAlgorithmIdentifier::CX509SigningAlgorithmIdentifier()
   471 	{
   472 	}
   473 
   474 void CX509SigningAlgorithmIdentifier::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   475 	{
   476 	TASN1DecSequence encSeq;
   477 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 1, KMaxTInt);
   478 	TInt count = seq->Count();
   479 	TASN1DecObjectIdentifier encOID;
   480 	HBufC* oid = encOID.DecodeDERL(*(seq->At(0)));
   481 	CleanupStack::PushL(oid);
   482 	TPtrC oidDes(oid->Des()); 
   483 	//none of the signing algorithms we support have parameters here...
   484 	HBufC8* encodedParams = HBufC8::NewLC(1);
   485 	*encodedParams = KNullDesC8;
   486 
   487 	if (oidDes == KDSAWithSHA1)
   488 		{
   489 		//should be no params, but we allow params encoded as NULL for interop reasons
   490 		TAlgorithmId algId = EDSA;
   491 		TAlgorithmId digestId = ESHA1;
   492 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   493 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   494 		if (count == 1)
   495 			{			
   496 			CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
   497 			return;
   498 			}
   499 		}
   500 
   501 	if (oidDes == KMD2WithRSA)
   502 		{
   503 		TAlgorithmId algId = ERSA;
   504 		TAlgorithmId digestId = EMD2;
   505 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   506 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   507 		}
   508 
   509 	if (oidDes == KMD5WithRSA)
   510 		{
   511 		TAlgorithmId algId = ERSA;
   512 		TAlgorithmId digestId = EMD5;
   513 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   514 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   515 		}
   516 
   517 	if (oidDes == KSHA1WithRSA  || oidDes == KSHA1WithRSASignature)
   518 		{
   519 		TAlgorithmId algId = ERSA;
   520 		TAlgorithmId digestId = ESHA1;
   521 		iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   522 		iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   523 		}
   524 
   525 	if (oidDes == KSHA224WithRSA)
   526          {
   527          TAlgorithmId algId = ERSA;
   528          TAlgorithmId digestId = ESHA224;
   529          iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   530          iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   531          }
   532 	
   533 	if (oidDes == KSHA256WithRSA)
   534          {
   535          TAlgorithmId algId = ERSA;
   536          TAlgorithmId digestId = ESHA256;
   537          iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   538          iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   539          }
   540 
   541 	if (oidDes == KSHA384WithRSA)
   542          {
   543          TAlgorithmId algId = ERSA;
   544          TAlgorithmId digestId = ESHA384;
   545          iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   546          iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   547          }
   548 
   549 	if (oidDes == KSHA512WithRSA)
   550          {
   551          TAlgorithmId algId = ERSA;
   552          TAlgorithmId digestId = ESHA512;
   553          iDigestAlgorithm = CAlgorithmIdentifier::NewL(digestId, encodedParams->Des());
   554          iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(algId, encodedParams->Des());
   555          }
   556 
   557 		//???not sure if we should just leave here...
   558 	if (iDigestAlgorithm == NULL)
   559 		{	
   560 		User::Leave(KErrNotSupported);
   561 		}
   562 	else
   563 		{
   564 		if (count != 2)
   565 			{
   566 			// Shouldn't ever get here, since RFC2459 mandates having 2
   567 			// data items.  However, some people miss out the second
   568 			// when it's NULL, so we'll not report and error here
   569 			}
   570 		else
   571 			{
   572 			TASN1DecGeneric* gen = seq->At(1);
   573 			TASN1DecNull null;
   574 			null.DecodeDERL(*gen);//just to check the syntax is OK
   575 			}
   576 		}
   577 	CleanupStack::PopAndDestroy(3);//seq, oid, encodedParams
   578 	}
   579 
   580 void CX509SigningAlgorithmIdentifier::ConstructL(const CAlgorithmIdentifier& aAsymmetricAlgorithm, const CAlgorithmIdentifier& aDigestAlgorithm)
   581  	{
   582  	iDigestAlgorithm = CAlgorithmIdentifier::NewL(aDigestAlgorithm);
   583  	iAsymmetricAlgorithm = CAlgorithmIdentifier::NewL(aAsymmetricAlgorithm);
   584  	};
   585 
   586 //subject public key info
   587 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData, TInt& aPos)
   588 	{
   589 	CX509SubjectPublicKeyInfo* self = CX509SubjectPublicKeyInfo::NewLC(aBinaryData, aPos);
   590 	CleanupStack::Pop();
   591 	return self;
   592 	}
   593 
   594 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData, TInt& aPos)
   595 	{
   596 	CX509SubjectPublicKeyInfo* self = new(ELeave) CX509SubjectPublicKeyInfo;
   597 	CleanupStack::PushL(self);
   598 	self->ConstructL(aBinaryData, aPos);
   599 	return self;
   600 	}
   601 
   602 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewL(const TDesC8& aBinaryData)
   603 	{
   604 	TInt pos = 0;
   605 	return CX509SubjectPublicKeyInfo::NewL(aBinaryData, pos);
   606 	}
   607 
   608 EXPORT_C CX509SubjectPublicKeyInfo* CX509SubjectPublicKeyInfo::NewLC(const TDesC8& aBinaryData)
   609 	{
   610 	TInt pos = 0;
   611 	return CX509SubjectPublicKeyInfo::NewLC(aBinaryData, pos);
   612 	}
   613 
   614 CX509SubjectPublicKeyInfo::CX509SubjectPublicKeyInfo()
   615 	{
   616 	}
   617 
   618 void CX509SubjectPublicKeyInfo::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   619 	{
   620 	TASN1DecSequence encSeq;
   621 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
   622 	iAlgId = CX509AlgorithmIdentifier::NewL(seq->At(0)->Encoding());
   623 	TASN1DecBitString encBS;
   624 	iEncodedKeyData = encBS.ExtractOctetStringL(*(seq->At(1)));
   625 	CleanupStack::PopAndDestroy();//seq
   626 	}
   627 
   628 //generic X 509 extension syntax
   629 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const CX509CertExtension& aExtension)
   630 	{
   631 	CX509CertExtension* self = CX509CertExtension::NewLC(aExtension);
   632 	CleanupStack::Pop();
   633 	return self;
   634 	}
   635 
   636 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const CX509CertExtension& aExtension)
   637 	{
   638 	CX509CertExtension* self = new(ELeave) CX509CertExtension;
   639 	CleanupStack::PushL(self);
   640 	self->ConstructL(aExtension);
   641 	return self;
   642 	}
   643 
   644 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData, TInt& aPos)
   645 	{
   646 	CX509CertExtension* self = CX509CertExtension::NewLC(aBinaryData, aPos);
   647 	CleanupStack::Pop();
   648 	return self;
   649 	}
   650 
   651 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData, TInt& aPos)
   652 	{
   653 	CX509CertExtension* self = new(ELeave) CX509CertExtension;
   654 	CleanupStack::PushL(self);
   655 	self->ConstructL(aBinaryData, aPos);
   656 	return self;
   657 	}
   658 
   659 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC8& aBinaryData)
   660 	{
   661 	TInt pos = 0;
   662 	return CX509CertExtension::NewL(aBinaryData, pos);
   663 	}
   664 
   665 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC8& aBinaryData)
   666 	{
   667 	TInt pos = 0;
   668 	return CX509CertExtension::NewLC(aBinaryData, pos);
   669 	}
   670 
   671 EXPORT_C CX509CertExtension* CX509CertExtension::NewL(const TDesC& aCertExtOID, 
   672 							const TBool aCritical,
   673 							const TDesC8& aCertExtValue)
   674 	{
   675 	CX509CertExtension* self = CX509CertExtension::NewLC(aCertExtOID, aCritical, aCertExtValue);
   676 	CleanupStack::Pop();
   677 	return self;
   678 	}
   679 
   680 EXPORT_C CX509CertExtension* CX509CertExtension::NewLC(const TDesC& aCertExtOID, 
   681 							const TBool aCritical,
   682 							const TDesC8& aCertExtValue)
   683 	{
   684 	CX509CertExtension* self = new(ELeave) CX509CertExtension;
   685 	CleanupStack::PushL(self);
   686 	self->ConstructL(aCertExtOID, aCritical, aCertExtValue);
   687 	return self;
   688 	}
   689 
   690 void CX509CertExtension::ConstructL(const CX509CertExtension& aExtension)
   691 	{
   692 	iCritical = aExtension.iCritical;
   693 	iId = aExtension.iId->Des().AllocL();
   694 	iData = aExtension.iData->Des().AllocL();
   695 	}
   696 
   697 void CX509CertExtension::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   698 	{
   699 	TASN1DecSequence encSeq;
   700 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, aPos, 2, KMaxTInt);
   701 
   702 	TASN1DecObjectIdentifier encOID;
   703 	iId = encOID.DecodeDERL(*(seq->At(0)));
   704 	//second is either critical flag, or the ext
   705 	TASN1DecGeneric* second = seq->At(1);
   706 	if (second->Tag() != EASN1Boolean)
   707 		{
   708 		iData = second->Encoding().AllocL();
   709 		aPos += second->LengthDER();
   710 		}
   711 	else
   712 		{
   713 		TASN1DecBoolean encBool;
   714 		iCritical = encBool.DecodeDERL(*second);
   715 		if (seq->Count() != 3)
   716 			{
   717 			User::Leave(KErrArgument);
   718 			}
   719 
   720 		TASN1DecGeneric* third = seq->At(2);
   721 		iData = third->Encoding().AllocL();
   722 		}
   723 	CleanupStack::PopAndDestroy();//seq
   724 	}
   725 
   726 void CX509CertExtension::ConstructL(const TDesC& aCertExtOID, 
   727 									const TBool aCritical,
   728 									const TDesC8& aCertExtValue)
   729 	{
   730 	iId = aCertExtOID.AllocL();
   731 	iCritical = aCritical;
   732 	iData = aCertExtValue.AllocL();
   733 	}
   734 
   735 EXPORT_C CX509CertExtension::~CX509CertExtension()
   736 	{
   737 	delete iData;
   738 	delete iId;
   739 	}
   740 
   741 EXPORT_C TBool CX509CertExtension::Critical() const
   742 	{
   743 	return iCritical;
   744 	}
   745 
   746 EXPORT_C TPtrC CX509CertExtension::Id() const	//OID for the extension
   747 	{
   748 	return iId->Des();
   749 	}
   750 
   751 EXPORT_C TPtrC8 CX509CertExtension::Data() const	 //the extension itself
   752 	{
   753 	return iData->Des();
   754 	}
   755 
   756 EXPORT_C CASN1EncSequence* CX509CertExtension::EncodeASN1DERLC() const
   757 	{
   758 	CASN1EncSequence *result = CASN1EncSequence::NewLC();
   759 	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(*iId);
   760 	result->AddAndPopChildL(oid);
   761 	// Encode critical flag only if true
   762 	if (iCritical)
   763 		{
   764 		CASN1EncBoolean *critical = CASN1EncBoolean::NewLC(iCritical);
   765 		result->AddAndPopChildL(critical);
   766 		}	
   767 	CASN1EncOctetString *data = CASN1EncOctetString::NewLC(*iData);
   768 	result->AddAndPopChildL(data);
   769 	return result;
   770 	}
   771 
   772 CX509CertExtension::CX509CertExtension()
   773 	:iCritical(EFalse)
   774 	{
   775 	}
   776 
   777 //CX509Certificate
   778 EXPORT_C CX509Certificate* CX509Certificate::NewL(const CX509Certificate& aCert)
   779 	{
   780 	CX509Certificate* self = CX509Certificate::NewLC(aCert);
   781 	CleanupStack::Pop();//self
   782 	return self;
   783 	}
   784 
   785 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const CX509Certificate& aCert)
   786 	{
   787 	CX509Certificate* self = new(ELeave) CX509Certificate;
   788 	CleanupStack::PushL(self);
   789 	self->ConstructL(aCert);
   790 	return self;
   791 	}
   792 
   793 EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData)
   794 	{
   795 	TInt pos = 0;
   796 	return CX509Certificate::NewL(aBinaryData, pos);
   797 	}
   798 
   799 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData)
   800 	{	
   801 	TInt pos = 0;
   802 	return CX509Certificate::NewLC(aBinaryData, pos);
   803 	}
   804 
   805 EXPORT_C CX509Certificate* CX509Certificate::NewL(const TDesC8& aBinaryData, TInt& aPos)
   806 	{
   807 	CX509Certificate* self = CX509Certificate::NewLC(aBinaryData, aPos);
   808 	CleanupStack::Pop();
   809 	return self;
   810 	}
   811 
   812 EXPORT_C CX509Certificate* CX509Certificate::NewLC(const TDesC8& aBinaryData, TInt& aPos)
   813 	{	
   814 	CX509Certificate* self = new(ELeave) CX509Certificate();
   815 	CleanupStack::PushL(self);
   816 	self->ConstructL(aBinaryData, aPos);
   817 	return self;
   818 	}
   819 
   820 EXPORT_C CX509Certificate* CX509Certificate::NewL(RReadStream& aStream)
   821 	{
   822 	CX509Certificate* self = CX509Certificate::NewLC(aStream);
   823 	CleanupStack::Pop();//self
   824 	return self;
   825 	}
   826 
   827 EXPORT_C CX509Certificate* CX509Certificate::NewLC(RReadStream& aStream)
   828 	{
   829 	CX509Certificate* self = new(ELeave) CX509Certificate;
   830 	CleanupStack::PushL(self);
   831 	self->InternalizeL(aStream);
   832 	return self;
   833 	}
   834 
   835 void CX509Certificate::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
   836 	{
   837 	TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
   838 	gen.InitL();
   839 	
   840 	// The outermost tag for X509 certificates is always a sequence.
   841 	// Since this tag does not form part of the signed data it is possible
   842 	// to corrupt the tag by changing it to any other ASN.1 tag and process
   843 	// the rest of the certificate as normal.
   844 	// However, we still reject the certificate anyway to avoid 
   845 	// confusion because the data does not match the X.509 specification.	
   846 	if (gen.Tag() != EASN1Sequence)
   847 		{
   848 		User::Leave(KErrArgument);
   849 		}
   850 	
   851 	aPos += gen.LengthDER();
   852 	iKeyFactory = new(ELeave) TX509KeyFactory;
   853 
   854 	iEncoding = gen.Encoding().AllocL();
   855 
   856 	TASN1DecSequence encSeq;
   857 	TInt pos = 0;
   858 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
   859 	TASN1DecGeneric* encSigAlg = seq->At(1);
   860 	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
   861 	TASN1DecBitString encBS;
   862 	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
   863 	CleanupStack::PopAndDestroy();//seq
   864 
   865 	CSHA1* hash = CSHA1::NewL();
   866 	CleanupStack::PushL(hash);
   867 	iFingerprint = hash->Final(Encoding()).AllocL();
   868 	CleanupStack::PopAndDestroy();//hash
   869 	ConstructCertL();
   870 	}
   871 
   872 void CX509Certificate::ConstructL(const CX509Certificate& aCertificate)
   873 	{
   874 	iKeyFactory = new(ELeave) TX509KeyFactory;
   875 
   876 	iEncoding = aCertificate.iEncoding->AllocL();
   877 	iSignature = aCertificate.iSignature->AllocL();
   878 	iFingerprint = aCertificate.iFingerprint->AllocL();
   879 	iSigningAlgorithm = CSigningAlgorithmIdentifier::NewL(aCertificate.SigningAlgorithm());	
   880 	iSerialNumber = aCertificate.iSerialNumber->Des().AllocL();
   881 	iIssuerName = CX500DistinguishedName::NewL(*(aCertificate.iIssuerName));
   882 	iValidityPeriod = new(ELeave) CValidityPeriod(*(aCertificate.iValidityPeriod));
   883 	iSubjectName = CX500DistinguishedName::NewL(*(aCertificate.iSubjectName));
   884 	iSubjectPublicKeyInfo = CSubjectPublicKeyInfo::NewL(*(aCertificate.iSubjectPublicKeyInfo));
   885 	iIssuerUid = aCertificate.iIssuerUid->Des().AllocL();
   886 	iSubjectUid = aCertificate.iSubjectUid->Des().AllocL();
   887 	iExtensions = new(ELeave) CArrayPtrFlat<CX509CertExtension> (1);
   888 	TInt count = aCertificate.iExtensions->Count();
   889 	for (TInt i = 0; i < count; i++)
   890 		{
   891 		CX509CertExtension* ext = CX509CertExtension::NewLC(*aCertificate.iExtensions->At(i));
   892 		iExtensions->AppendL(ext);
   893 		CleanupStack::Pop();//ext
   894 		}
   895 	iVersion = aCertificate.Version();
   896 	InitDataElementsL(aCertificate);
   897 	}
   898 
   899 void CX509Certificate::InitDataElementsL(const CX509Certificate& aCertificate)
   900 	{
   901 	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
   902 	iDataElements->Reset();
   903 	TPtrC8 signedData = SignedDataL();
   904 	TASN1DecSequence encSeq;
   905 	TInt pos = 0;
   906 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
   907 	pos = 0;
   908 
   909 	TPtrC8** pElement = iDataElements->Begin();
   910 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EVersionNumber)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
   911 	for (TInt i = 0; i < 6; i++)	//init all the non-optional elements
   912 		{
   913 		*pElement++ = new(ELeave) TPtrC8(seq->At(pos++)->Encoding());
   914 		}
   915 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EIssuerUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
   916 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::ESubjectUID)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
   917 	*pElement++ = aCertificate.DataElementEncoding(CX509Certificate::EExtensionList)? new(ELeave) TPtrC8(seq->At(pos++)->Encoding()):NULL;
   918 	CleanupStack::PopAndDestroy();
   919 	}
   920 
   921 void CX509Certificate::ConstructCertL()
   922 	{
   923 	TPtrC8 signedData = SignedDataL();
   924 	TASN1DecSequence encSeq;
   925 	TInt pos = 0;
   926 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(signedData, pos, 6, KMaxTInt);//6 is the minimum number of elements in an x509 cert
   927 	TInt count = seq->Count();
   928 	pos = 0;
   929 	TASN1DecGeneric* curr = seq->At(pos);
   930 	pos++;
   931 	iDataElements = new(ELeave) TFixedArray<TPtrC8*, KX509MaxDataElements>;
   932 	iDataElements->Reset();
   933 	TPtrC8** pElement = iDataElements->Begin();
   934 	if ((curr->Class() == EContextSpecific) && (curr->Tag() == 0))
   935 		{
   936 		//version!
   937 		TASN1DecGeneric ver(curr->GetContentDER());
   938 		ver.InitL();
   939 		TPtrC8 pVer8 = ver.GetContentDER();
   940 		if(pVer8.Length() != 1)
   941 			{
   942 			User::Leave(KErrArgument);
   943 			}
   944 		iVersion = (pVer8[0]) + 1;
   945 		if ((iVersion < 1) || (iVersion > 3) || (count < 7))
   946 			{
   947 			User::Leave(KErrArgument);
   948 			}
   949 		*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   950 		curr = seq->At(pos);
   951 		pos++;
   952 		}
   953 	else
   954 		{
   955 		*pElement++ = NULL;
   956 		}
   957 	if (curr->Tag() != EASN1Integer)
   958 		{
   959 		User::Leave(KErrArgument);
   960 		}
   961 	iSerialNumber = (curr->GetContentDER()).AllocL();
   962 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   963 	curr = seq->At(pos);
   964 	pos++;
   965 	CX509SigningAlgorithmIdentifier* algorithmId = CX509SigningAlgorithmIdentifier::NewLC(curr->Encoding());
   966 	if (!(SigningAlgorithm() == *(algorithmId)))
   967 		{
   968 		User::Leave(KErrArgument);
   969 		}
   970 	CleanupStack::PopAndDestroy();//algorithmId
   971 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   972 
   973 	curr = seq->At(pos);
   974 	pos++;
   975 	iIssuerName = CX500DistinguishedName::NewL(curr->Encoding());
   976 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   977 	curr = seq->At(pos);
   978 	pos++;
   979 	iValidityPeriod = CX509ValidityPeriod::NewL(curr->Encoding());
   980 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   981 	curr = seq->At(pos);
   982 	pos++;
   983 	iSubjectName = CX500DistinguishedName::NewL(curr->Encoding());
   984 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   985 	curr = seq->At(pos);
   986 	pos++;
   987 	iSubjectPublicKeyInfo = CX509SubjectPublicKeyInfo::NewL(curr->Encoding());
   988 	*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
   989 	//do issuer uid, subject uid, exts
   990 	//these are all optional
   991 	TBool hasIssuerUid = EFalse;
   992 	TBool hasSubjectUid = EFalse;
   993 	TBool hasExts = EFalse;
   994 	iExtensions = new(ELeave)CArrayPtrFlat<CX509CertExtension> (1);
   995 	if (pos < count)//otherwise there aren't any of 'em
   996 		{
   997 		curr = seq->At(pos);
   998 		pos++;
   999 		if (curr->Class() != EContextSpecific)
  1000 			{
  1001 			User::Leave(KErrArgument);
  1002 			}
  1003 		switch(curr->Tag())
  1004 			{
  1005 			case 1:
  1006 				{
  1007 				iIssuerUid = DecodeUidL(curr->GetContentDER(), hasIssuerUid);
  1008 				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
  1009 				break;
  1010 				}
  1011 			case 2:
  1012 				{
  1013 				iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
  1014 				*pElement++ = NULL;
  1015 				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
  1016 				break;
  1017 				}
  1018 			case 3:
  1019 				{
  1020 				DecodeExtsL(curr->GetContentDER(), hasExts);
  1021 				*pElement++ = NULL;
  1022 				*pElement++ = NULL;
  1023 				*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
  1024 				break;
  1025 				}
  1026 			default:
  1027 				{
  1028 				User::Leave(KErrArgument);
  1029 				}
  1030 			}
  1031 		if (pos < count)
  1032 			{
  1033 			curr = seq->At(pos);
  1034 			pos++;
  1035 			switch(curr->Tag())
  1036 				{
  1037 				case 2:
  1038 					{
  1039 					iSubjectUid = DecodeUidL(curr->GetContentDER(), hasSubjectUid);
  1040 					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
  1041 					break;
  1042 					}
  1043 				case 3:
  1044 					{
  1045 					DecodeExtsL(curr->GetContentDER(), hasExts);
  1046 					*pElement++ = NULL;
  1047 					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
  1048 					break;
  1049 					}
  1050 				default:
  1051 					{
  1052 					User::Leave(KErrArgument);
  1053 					}
  1054 				}
  1055 			if (pos < count)
  1056 				{
  1057 				curr = seq->At(pos);
  1058 				pos++;
  1059 				if (curr->Tag() == 3)
  1060 					{
  1061 					DecodeExtsL(curr->GetContentDER(), hasExts);
  1062 					*pElement++ = new(ELeave) TPtrC8(curr->Encoding());
  1063 					}
  1064 				else
  1065 					{
  1066 					User::Leave(KErrArgument);
  1067 					}
  1068 				}
  1069 			}
  1070 		}
  1071 	if (pos != count)
  1072 		{
  1073 		User::Leave(KErrArgument);
  1074 		}
  1075 	if (!iIssuerUid)
  1076 		{
  1077 		iIssuerUid = HBufC8::NewL(1);
  1078 		*iIssuerUid = KNullDesC8;
  1079 		}
  1080 	if (!iSubjectUid)
  1081 		{
  1082 		iSubjectUid = HBufC8::NewL(1);
  1083 		*iSubjectUid = KNullDesC8;
  1084 		}
  1085 		
  1086 	// we have not checked for the certificate version number based on 
  1087 	// the certificate contents. This is primarily done to avoid BC for 
  1088 	// clients who are still using malformed certificates.
  1089 	
  1090 	CleanupStack::PopAndDestroy();//seq
  1091 	}
  1092 
  1093 CX509Certificate::CX509Certificate()
  1094 	:iVersion(1)
  1095 	{
  1096 	}
  1097 
  1098 EXPORT_C CX509Certificate::~CX509Certificate()
  1099 	{
  1100 	delete iIssuerName;
  1101 	delete iSubjectName;
  1102 	delete iIssuerUid;
  1103 	delete iSubjectUid;
  1104 	
  1105 	if (iDataElements != NULL)
  1106 		{
  1107 		for (TInt i = 0; i < KX509MaxDataElements; i++)
  1108 			{
  1109 			delete iDataElements->At(i);
  1110 			}
  1111 		delete iDataElements;
  1112 		}
  1113 	if (iExtensions != NULL)
  1114 		{
  1115 		iExtensions->ResetAndDestroy();
  1116 		}
  1117 	delete iExtensions;
  1118 	}
  1119 
  1120 EXPORT_C TBool CX509Certificate::IsEqualL(const CX509Certificate& aCert) const
  1121 	{
  1122 	return	(	(*(iSerialNumber) == *(aCert.iSerialNumber)) && 
  1123 				(iIssuerName->ExactMatchL(*(aCert.iIssuerName)))	);
  1124 	}
  1125 
  1126 EXPORT_C void CX509Certificate::InternalizeL(RReadStream& aStream)
  1127 	{
  1128 	if (iIssuerName != NULL) //just to check cert is uninitialised
  1129 		{
  1130 		User::Leave(KErrArgument);
  1131 		}
  1132 	iKeyFactory = new(ELeave) TX509KeyFactory;
  1133 	
  1134 	TInt len = aStream.ReadInt32L(); //Read the length of the streamed encoding
  1135 	HBufC8* temp= HBufC8::NewLC(len);	
  1136 	TPtr8 ptr=temp->Des();
  1137 	aStream.ReadL(ptr,len);
  1138 	iEncoding=temp->AllocL();
  1139 	CleanupStack::PopAndDestroy(); // temp
  1140 
  1141 	TASN1DecSequence encSeq;
  1142 	TInt pos = 0;
  1143 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);	
  1144 	TASN1DecGeneric* encSigAlg = seq->At(1);
  1145 	iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(encSigAlg->Encoding());
  1146 	TASN1DecBitString encBS;
  1147 	iSignature = encBS.ExtractOctetStringL(*(seq->At(2)));
  1148 	CleanupStack::PopAndDestroy();//seq	
  1149 
  1150 	CSHA1* hash = CSHA1::NewL();
  1151 	CleanupStack::PushL(hash);
  1152 	iFingerprint = hash->Final(Encoding()).AllocL();
  1153 	CleanupStack::PopAndDestroy();//hash
  1154 
  1155 	ConstructCertL();
  1156 	}
  1157 
  1158 void CX509Certificate::DecodeExtsL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
  1159 	{
  1160 	TASN1DecSequence encSeq;
  1161 	TInt pos = 0;
  1162 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(aBinaryData, pos);
  1163 	TInt count = seq->Count();
  1164 	for (TInt i = 0; i < count; i++)
  1165 		{
  1166 		TASN1DecGeneric* gen = seq->At(i);
  1167 		CX509CertExtension* ext = CX509CertExtension::NewLC(gen->Encoding());
  1168 		iExtensions->AppendL(ext);
  1169 		CleanupStack::Pop();//ext
  1170 		}
  1171 	CleanupStack::PopAndDestroy();//
  1172 	aHasElementAlready = ETrue;
  1173 	}
  1174 
  1175 HBufC8* CX509Certificate::DecodeUidL(const TDesC8& aBinaryData, TBool& aHasElementAlready)
  1176 	{
  1177 	if ((aHasElementAlready) || (iVersion ==1))
  1178 		{
  1179 		User::Leave(KErrArgument);
  1180 		}
  1181 	aHasElementAlready = ETrue;
  1182 	return aBinaryData.AllocL();
  1183 	}
  1184 
  1185 //***************************************************************************************//
  1186 //extra accessors
  1187 EXPORT_C const TPtrC8 CX509Certificate::SignedDataL() const
  1188 	{
  1189 	TASN1DecSequence encSeq;
  1190 	TInt pos = 0;
  1191 	CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(*iEncoding, pos, 3, 3);
  1192 	TASN1DecGeneric* gen = seq->At(0);
  1193 	TPtrC8 res = gen->Encoding();
  1194 	CleanupStack::PopAndDestroy();
  1195 	return res;
  1196 	}
  1197 
  1198 EXPORT_C TInt CX509Certificate::Version() const
  1199 	{
  1200 	return iVersion;
  1201 	}
  1202 
  1203 /**
  1204 * If the certificate has decoded the members from TeletexString then the return value 
  1205 * may be incorrect because TeletexString type is not fully supported by this library.
  1206 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
  1207 * null characters in the second byte of each character. This will work as expected 
  1208 * for cases where the string contains ASCII data.
  1209 */
  1210 EXPORT_C const CX500DistinguishedName& CX509Certificate::IssuerName() const
  1211 	{
  1212 	return *iIssuerName;
  1213 	}
  1214 
  1215 /**
  1216 * If the certificate has decoded the members from TeletexString then the return value 
  1217 * may be incorrect because TeletexString type is not fully supported by this library.
  1218 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
  1219 * null characters in the second byte of each character. This will work as expected 
  1220 * for cases where the string contains ASCII data.
  1221 */
  1222 EXPORT_C const CX500DistinguishedName& CX509Certificate::SubjectName() const
  1223 	{
  1224 	return *iSubjectName;
  1225 	}
  1226 
  1227 EXPORT_C const CArrayPtrFlat<CX509CertExtension>& CX509Certificate::Extensions() const
  1228 	{
  1229 	return *iExtensions;
  1230 	}
  1231 
  1232 EXPORT_C const CX509CertExtension* CX509Certificate::Extension(const TDesC& aExtensionName) const
  1233 	{
  1234 	TInt count = iExtensions->Count();
  1235 	for (TInt i = 0; i < count; i++)
  1236 		{
  1237 		CX509CertExtension* ext = iExtensions->At(i);
  1238 		if (ext->Id() == aExtensionName)
  1239 			return ext;
  1240 		}
  1241 	return NULL;
  1242 	}
  1243 
  1244 EXPORT_C const TPtrC8* CX509Certificate::DataElementEncoding(const TUint aIndex) const
  1245 	{
  1246 	return iDataElements->At(aIndex);
  1247 	}
  1248 
  1249 /**
  1250 * If the certificate has decoded the members from TeletexString then the return value 
  1251 * may be incorrect because TeletexString type is not fully supported by this library.
  1252 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
  1253 * null characters in the second byte of each character. This will work as expected 
  1254 * for cases where the string contains ASCII data.
  1255 */
  1256 EXPORT_C HBufC* CX509Certificate::IssuerL() const
  1257 	{
  1258 	return iIssuerName->DisplayNameL();
  1259 	}
  1260 
  1261 /**
  1262 * If the certificate has decoded the members from TeletexString then the return value 
  1263 * may be incorrect because TeletexString type is not fully supported by this library.
  1264 * Instead the decode methods perform a direct conversion from 8 to 16bits by adding 
  1265 * null characters in the second byte of each character. This will work as expected 
  1266 * for cases where the string contains ASCII data.
  1267 */
  1268 EXPORT_C HBufC* CX509Certificate::SubjectL() const
  1269 	{
  1270 	return iSubjectName->DisplayNameL();
  1271 	}
  1272 
  1273 EXPORT_C TBool CX509Certificate::IsSelfSignedL() const
  1274 	{
  1275 	if (iSubjectName->Count() > 0)
  1276 		{
  1277 		return iSubjectName->ExactMatchL(*iIssuerName);
  1278 		}
  1279 	else
  1280 		{
  1281 		TBool res = EFalse;
  1282 		const CX509CertExtension* subjectExt = Extension(KIssuerAltName);
  1283 		const CX509CertExtension* issuerExt = Extension(KSubjectAltName);
  1284 		if ((subjectExt) && (issuerExt))
  1285 			{
  1286 			const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
  1287 			const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
  1288 			if (subjectAltName->Match(*issuerAltName))
  1289 				{
  1290 				res = ETrue;
  1291 				}
  1292 			CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
  1293 			}
  1294 		return res;
  1295 		} 
  1296 	}
  1297 
  1298 
  1299 EXPORT_C TKeyIdentifier CX509Certificate::KeyIdentifierL() const	
  1300 	{
  1301 	if (iSubjectPublicKeyInfo->AlgorithmId() != EDSA)
  1302 		{
  1303 		// The base class handles the RSA case and leaves with KErrNotSupported if
  1304 		// it is not RSA.
  1305 		return CCertificate::KeyIdentifierL();
  1306 		}
  1307 	else
  1308 		{
  1309 		// This handles the DSA case
  1310 		CDSAPublicKey* dsaKey = 
  1311 						iKeyFactory->DSAPublicKeyL(iSubjectPublicKeyInfo->EncodedParams(), 
  1312 													iSubjectPublicKeyInfo->KeyData());
  1313 		CleanupStack::PushL(dsaKey);
  1314 		TKeyIdentifier retVal;
  1315 		KeyIdentifierUtil::DSAKeyIdentifierL(*dsaKey, retVal);
  1316 		CleanupStack::PopAndDestroy(dsaKey);
  1317 		return retVal;
  1318 		}
  1319 	}
  1320 
  1321 EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdentifierL() const
  1322 	{	
  1323 	const CX509CertExtension* subjectKeyIdExtStr = this->Extension(KSubjectKeyId);
  1324 	if (subjectKeyIdExtStr)
  1325 		{
  1326 		TKeyIdentifier ret;
  1327 		CX509SubjectKeyIdExt *subjectKeyIdExt = CX509SubjectKeyIdExt::NewLC(subjectKeyIdExtStr->Data());
  1328 		// Currently, we do not support key identifiers larger than 160 bits - make sure not to overflow the descriptor
  1329 		if (subjectKeyIdExt->KeyId().Length() <= ret.MaxLength())
  1330 			{
  1331 			ret.Copy(subjectKeyIdExt->KeyId());
  1332 			CleanupStack::PopAndDestroy(subjectKeyIdExt);
  1333 			return ret;
  1334 			}
  1335 		CleanupStack::PopAndDestroy(subjectKeyIdExt);
  1336 		}
  1337 		
  1338 	return KeyIdentifierL();
  1339 	}
  1340 
  1341 
  1342 EXPORT_C TKeyIdentifier CX509Certificate::SubjectKeyIdL() const
  1343 	{
  1344 	// if it is a v1 or v2 type then there is no way of knowing which is a CA, treat all certs as CA as done in the certificate recognizer.
  1345 	if (Version() < 3 )
  1346 		{
  1347 		return SubjectKeyIdentifierL();
  1348 		}
  1349 	
  1350 	// if it is x509 v3 certificate then check for the basic constraint extension.
  1351 	const CX509CertExtension* ext = Extension(KBasicConstraints);
  1352 	if (ext)
  1353 		{
  1354 		CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC(ext->Data());
  1355 		TBool markedAsCA = basic->IsCA();
  1356 		CleanupStack::PopAndDestroy(basic);
  1357 		// it can be an intermediate as well as root CA
  1358 		if ( markedAsCA )
  1359 			{
  1360 			return SubjectKeyIdentifierL();
  1361 			}
  1362 		}
  1363 	// For non-CA certs, use the recommended method of computing it from RFC5280, section 4.2.1.2
  1364 	return KeyIdentifierL();									
  1365 		
  1366 	}
  1367