vpnengine/ikecert/src/ikepkiutils.cpp
changeset 0 33413c0669b9
child 2 ef893827b4d1
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2008-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 "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:   static method for certficate handling
       
    15 *
       
    16 */
       
    17 
       
    18 #include <x509cert.h>
       
    19 #include <asn1dec.h>
       
    20 #include <x500dn.h>
       
    21 
       
    22 #include "ikepkiutils.h"
       
    23 #include "ikev1pkiservice.h"
       
    24 #include "ikepublickey.h"
       
    25 #include "utlcrypto.h"
       
    26 #include "ikecert.h"
       
    27 #include "ikecalist.h"
       
    28 #include "ikecaelem.h"
       
    29 #include "ikev2const.h"
       
    30 #include "ikev2payloads.h"
       
    31 #include "ikecertconst.h"
       
    32 
       
    33 EXPORT_C TBool IkePkiUtils::CertifyIdentityL(const CX509Certificate* aCert, 
       
    34                                              TDesC8& aId, TInt aIdType)
       
    35                                           
       
    36     {
       
    37 	TBool status = EFalse;
       
    38 	if ( aCert )
       
    39 	    {	
       
    40 	   //
       
    41 	   // Check that specified identity exist in current certificate
       
    42 	   // data. If aIdType type is ID_DER_ASN1_DN, identity must match
       
    43 	   // with Certificate Subject name. 
       
    44 	   // All other aIdTypes ara checked against SubjectAltNames data,
       
    45 	   // if present 
       
    46 	   //
       
    47 		if ( aIdType == ID_DER_ASN1_DN )
       
    48 		    {
       
    49 	        //
       
    50 	        // Binary DER encoding of an ASN.1 X.500 Distinguished Name identity
       
    51 	        // is certified by comparing it to peer certificate subject name
       
    52 	        //
       
    53 	        			
       
    54 			CX500DistinguishedName* asn1DnName = CX500DistinguishedName::NewLC(aId);
       
    55 		    status = asn1DnName->ExactMatchL(aCert->SubjectName());			   			   
       
    56 		    CleanupStack::PopAndDestroy(asn1DnName);
       
    57 
       
    58 		    }
       
    59 		else
       
    60 		    {
       
    61             //
       
    62             // Other identity types are certified by comparing it to the SubjectAltName field        
       
    63             //
       
    64 			HBufC8* idBuf = HBufC8::NewLC(aId.Length() + 2);
       
    65 			TUint8* idHdr = (TUint8*)idBuf->Des().Ptr();
       
    66 			idHdr[1]      = (TUint8)aId.Length();
       
    67 
       
    68 			switch ( aIdType ) 
       
    69 			    {
       
    70 				case ID_IPV4_ADDR:
       
    71 					idHdr[0] = 0x87;
       
    72 					break;
       
    73 				case ID_FQDN:
       
    74 					idHdr[0] = 0x82;                       
       
    75 					break;
       
    76 				case ID_RFC822_ADDR:
       
    77 					idHdr[0] = 0x81;                                   
       
    78 					break;
       
    79 				case ID_IPV6_ADDR:
       
    80 					idHdr[0] = 0x87;           
       
    81 					break;
       
    82 				default:
       
    83 					idHdr = NULL;
       
    84                     break;
       
    85 		    	}
       
    86 
       
    87 			if ( idHdr )
       
    88 			    {	
       
    89 			   Mem::Copy(&idHdr[2], aId.Ptr(), aId.Length());
       
    90 			   TPtrC8 ptrId(idHdr, (aId.Length() + 2));
       
    91 			   status = IkeCert::AltNameExistsL(aCert, ptrId);
       
    92 		    	}
       
    93 			CleanupStack::PopAndDestroy();  //IdBuf			
       
    94 		    }
       
    95     	}	
       
    96 
       
    97 	return status;
       
    98     }
       
    99 
       
   100 
       
   101 EXPORT_C TBool IkePkiUtils::VerifyIkev2SignatureL(const TDesC8& aSignature, 
       
   102                                                   const TDesC8& aAuthData, 
       
   103                                                   const CX509Certificate& aCert)
       
   104     {
       
   105 	//
       
   106 	// Calculate SHA1 hash over aAuthdata to build reference hash and
       
   107 	// verify IKEv2 signature with it
       
   108 	//
       
   109 	CUtlMessageDigest* Digest = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1);
       
   110 	CleanupStack::PushL(Digest);			
       
   111 	TPtrC8 RefHash = Digest->Final(aAuthData);
       
   112 	TBool Status   = VerifySignatureL(MAJORV2, aSignature, RefHash, aCert);
       
   113 	CleanupStack::PopAndDestroy(Digest);
       
   114 	
       
   115 	return Status; 
       
   116     }	 
       
   117 
       
   118 
       
   119 EXPORT_C TBool IkePkiUtils::VerifyIkev1SignatureL(const TDesC8& aSignature, 
       
   120                                                   const TDesC8& aRefHash, 
       
   121                                                   const CX509Certificate& aCert)
       
   122     {
       
   123 	//
       
   124 	// Verify IKEv1 signature. 
       
   125 	//
       
   126 	return VerifySignatureL(MAJORV1, aSignature, aRefHash, aCert);
       
   127     }	 
       
   128     
       
   129     
       
   130 EXPORT_C HBufC8* IkePkiUtils::GetIdentityFromCertL(TUint8 aIdType, const TDesC8& aCertData)
       
   131     {
       
   132 	//
       
   133 	// Get IKE Identity data from specified Certificate data. The Id
       
   134 	// type parameter specifies the field of Certificate from where the
       
   135 	// Identity data is taken
       
   136 	//
       
   137 	HBufC8* identity;
       
   138 	CX509Certificate* cert = CX509Certificate::NewL(aCertData);
       
   139 	CleanupStack::PushL(cert);			
       
   140 	if ( (aIdType == ID_DER_ASN1_DN) || (aIdType == ID_NOT_DEFINED) || (aIdType > ID_IPV6_ADDR) )
       
   141 	    {       
       
   142 	    // 
       
   143 	    // DER encoded ASN.1 X.500 Distinguished Name as IKE identity
       
   144 		// Get Id data from certificate subject name
       
   145 	    //
       
   146 		identity = IkeCert::GetCertificateFieldDERL(cert, KSubjectName);
       
   147 	    }
       
   148 	else
       
   149 	    {
       
   150 	     //
       
   151 	     // Get IKE Identity from own certifate subject alt name extension (according to IdType value)
       
   152 	     //
       
   153 		identity = IkeCert::GetSubjectAltNameDataL(cert, aIdType); 
       
   154 	    }
       
   155 	CleanupStack::PopAndDestroy(cert); 
       
   156 	
       
   157 	return identity;
       
   158     }	 
       
   159 
       
   160 
       
   161 EXPORT_C TBool IkePkiUtils::GetCertSubjectNameDERL(const CX509Certificate* aCert, 
       
   162                                                    TDes8& aSubjectName)
       
   163     {
       
   164 	TBool status = ETrue;
       
   165 	HBufC8* nameBfr = IkeCert::GetCertificateFieldDERL(aCert, KSubjectName);
       
   166     if ( nameBfr && ( nameBfr->Des().Length() <= aSubjectName.MaxLength() ) )
       
   167 	    {
       
   168 		aSubjectName.Copy(nameBfr->Des());
       
   169 		delete nameBfr;
       
   170 	    }
       
   171 	else 
       
   172 	    {
       
   173 		aSubjectName.SetLength(0);
       
   174 		status = EFalse;
       
   175 	    }
       
   176 
       
   177 	return status;
       
   178     }	        
       
   179  
       
   180 
       
   181 EXPORT_C CX509Certificate* IkePkiUtils::VerifyCertificateL(const CArrayFixFlat<const TCertificateISAKMP*>& aCerts,
       
   182                                                            const CIkeCaList& aTrustedCAList)
       
   183     {
       
   184     const CArrayFixFlat<TCertPayloadIkev2*>* certificateArray = IkePkiUtils::CastCertArray(&aCerts);    
       
   185     return VerifyCertificateL(*certificateArray, aTrustedCAList);
       
   186     
       
   187     }
       
   188 
       
   189  
       
   190 EXPORT_C CX509Certificate* IkePkiUtils::VerifyCertificateL(const CArrayFixFlat<TCertPayloadIkev2*>& aCerts,
       
   191                                                            const CIkeCaList& aTrustedCAList)
       
   192    {
       
   193 	//
       
   194 	// Find a requested certificate or chain of certificates from IKE certificate payload array
       
   195 	// using trusted CA list (iTrustedCAList).
       
   196 	// When requested certificate found verify this certificate. 
       
   197 	//
       
   198 	CX509Certificate* certOk = NULL;	
       
   199 	CX509Certificate* caCert = NULL;
       
   200 	CX509Certificate* currCert=NULL;
       
   201 	const TCertPayloadIkev2* firstCertPayload=NULL;
       
   202 	const TCertPayloadIkev2* certPayload = aCerts.At(0);
       
   203     __ASSERT_DEBUG(certPayload != NULL, User::Invariant());
       
   204     CArrayFixFlat<CX509Certificate*>* caArray=new (ELeave) CArrayFixFlat<CX509Certificate*> (aCerts.Count());
       
   205     CleanupStack::PushL(caArray);
       
   206     for ( TInt i = 0; i < aCerts.Count(); i++  ) 
       
   207         {
       
   208          const TCertPayloadIkev2* currCertPayload=aCerts.At(i);
       
   209          __ASSERT_DEBUG(currCertPayload != NULL, User::Invariant());
       
   210          if ( currCertPayload->GetEncoding() == X509_CERTIFICATE_SIGN )
       
   211         {          
       
   212              firstCertPayload=currCertPayload;
       
   213              const TPtrC8 CertStream(currCertPayload->Certificate(),
       
   214                                     (TPayloadIkev2::Cast(currCertPayload)->GetLength() - 
       
   215                                      TCertPayloadIkev2::Size()));
       
   216              currCert = CX509Certificate::NewLC(CertStream);
       
   217              caArray->AppendL(currCert);
       
   218             }
       
   219         }
       
   220     if ( caArray->Count() == 1)
       
   221            {
       
   222          const TPtrC8 userCertStream(firstCertPayload->Certificate(),
       
   223                                     (TPayloadIkev2::Cast(firstCertPayload)->GetLength() - 
       
   224                                      TCertPayloadIkev2::Size()));
       
   225          firstCertPayload=NULL;
       
   226             CX509Certificate* clientCert = CX509Certificate::NewLC(userCertStream);
       
   227             caCert = IkePkiUtils::FindCaCertificateL(*clientCert, aTrustedCAList);
       
   228             if ( caCert )
       
   229                 {
       
   230                  certOk = IkePkiUtils::VerifyX509CertificateL(*caCert, *clientCert);
       
   231              if ( certOk )  // CertOk = clientCert
       
   232                     {
       
   233                      CleanupStack::Pop(clientCert);  // CertOk = Cert              
       
   234                 clientCert=NULL;
       
   235                 
       
   236                 CleanupStack::PopAndDestroy(currCert);
       
   237                 currCert=NULL;
       
   238                 
       
   239                 CleanupStack::PopAndDestroy(caArray);
       
   240                 caArray=NULL;
       
   241                 
       
   242                 return certOk; 
       
   243                 }
       
   244             }   
       
   245          CleanupStack::PopAndDestroy(clientCert);  // Cert
       
   246          clientCert=NULL;
       
   247          
       
   248          CleanupStack::PopAndDestroy(currCert);
       
   249          currCert=NULL;
       
   250          
       
   251          CleanupStack::PopAndDestroy(caArray);
       
   252          caArray=NULL;
       
   253          return NULL;
       
   254          }
       
   255     if ( caArray->Count()>1 ) //if certificate chain is received
       
   256        {    
       
   257            CX509Certificate* userCert=NULL;
       
   258            CX509Certificate* certChainRoot = IkePkiUtils::VerifyCertChainL(*caArray, userCert, aTrustedCAList);
       
   259            
       
   260            CX509Certificate* realUserCert=userCert; //Real user certificate found from chain as a parameter by reference 
       
   261                              
       
   262            //cleaning
       
   263            TInt certCount=caArray->Count();
       
   264            for ( TInt i=0; i<certCount ;i++)
       
   265                CleanupStack::Pop();
       
   266            CleanupStack::Pop(caArray);
       
   267            for ( TInt i=0; i<certCount ;i++)
       
   268                {
       
   269                 CX509Certificate* itemPtr=caArray->At(i);
       
   270                 if ( realUserCert != itemPtr && certChainRoot != itemPtr )
       
   271                     delete itemPtr;
       
   272                }
       
   273            for ( TInt i=0; i<certCount ;i++)
       
   274                  caArray->Delete(0);
       
   275            delete caArray;
       
   276                
       
   277            if ( certChainRoot )
       
   278                caCert = IkePkiUtils::FindCaCertificateL(*certChainRoot, aTrustedCAList);
       
   279            else
       
   280                caCert=NULL;
       
   281            if ( caCert )
       
   282                certOk = IkePkiUtils::VerifyX509CertificateL(*caCert, *certChainRoot);
       
   283            if ( certChainRoot != userCert )
       
   284            			delete certChainRoot;
       
   285            if ( certOk )
       
   286               return realUserCert;
       
   287               
       
   288            else
       
   289               return NULL;
       
   290            }
       
   291     return NULL;
       
   292     }
       
   293 
       
   294 
       
   295 EXPORT_C const CArrayFixFlat<TCertPayloadIkev2*>* IkePkiUtils::CastCertArray(const CArrayFixFlat<const TCertificateISAKMP*>* aCerts) 
       
   296     { 
       
   297     return reinterpret_cast<const CArrayFixFlat<TCertPayloadIkev2*>*>(aCerts); 
       
   298     }
       
   299 
       
   300 
       
   301 CX509Certificate* IkePkiUtils::VerifyX509CertificateL(const CX509Certificate& aCaCert, 
       
   302                                                       CX509Certificate& aCert)
       
   303     {
       
   304 	TPKIKeyAlgorithm reqKeyType = EPKIInvalidAlgorithm;
       
   305 
       
   306 	switch (aCert.SigningAlgorithm().AsymmetricAlgorithm().Algorithm())
       
   307     	{
       
   308 		case ERSA:
       
   309 			reqKeyType = EPKIRSA;
       
   310 			break;
       
   311 		case EDSA:
       
   312 			reqKeyType = EPKIDSA;
       
   313 			break;
       
   314 		default:
       
   315 			break;
       
   316 	    }
       
   317 
       
   318 	if ( reqKeyType == EPKIInvalidAlgorithm )
       
   319 		return NULL;
       
   320 		
       
   321 	CIkePublicKey* pubKey = CIkePublicKey::NewL(aCaCert);
       
   322 	if ( !pubKey )
       
   323 		return NULL;	
       
   324 
       
   325 	if ( reqKeyType != pubKey->Algorithm() )
       
   326 	    {
       
   327 		delete pubKey;
       
   328 		return NULL;
       
   329 	    }	
       
   330 	CleanupStack::PushL(pubKey);
       
   331 	TInt  ret   = KErrNotSupported;
       
   332 	TBool valid = EFalse;
       
   333 
       
   334 	switch (pubKey->Algorithm())
       
   335     	{
       
   336 		case EPKIRSA:
       
   337 			TRAP(ret, valid = aCert.VerifySignatureL(pubKey->KeyData()));
       
   338 			break;
       
   339 
       
   340 		case EPKIDSA:
       
   341 		    {
       
   342 			TX509KeyFactory keyFactory;
       
   343 			CDSAParameters* params = keyFactory.DSAParametersL(pubKey->KeyParams());
       
   344 			CleanupStack::PushL(params);
       
   345 
       
   346 			CSigningKeyParameters*sgkp = CSigningKeyParameters::NewLC();
       
   347 			sgkp->SetDSAParamsL(*params);
       
   348 			aCert.SetParametersL(*sgkp);
       
   349 			TRAP(ret, valid = aCert.VerifySignatureL(pubKey->KeyData()));
       
   350 			CleanupStack::PopAndDestroy(sgkp); 
       
   351 			CleanupStack::PopAndDestroy(params); 
       
   352 			break;
       
   353 		    }
       
   354 
       
   355 		case EPKIInvalidAlgorithm:
       
   356 			break;
       
   357 	    }
       
   358 			
       
   359 	CX509Certificate* ValidCert = NULL;	
       
   360 	if ( valid && (ret == KErrNone) )
       
   361 	    {
       
   362 		//
       
   363 		// One hour error margin, no warning margin
       
   364 		//
       
   365 		ret = IkeCert::CheckValidityPeriod(aCert, 0, KDefaultErrorMargin);
       
   366 		if ( ret == KErrNone )
       
   367 	    	{	
       
   368 			//
       
   369 			// Verify certificate extensions
       
   370 			//
       
   371 			ret = IkeCert::VerifyCertExtensionsL(aCert);
       
   372 			if ( ret == KErrNone || ret == KCertVerifyCACertificate )
       
   373 				ValidCert = &aCert;			
       
   374 	    	}		
       
   375     	}	
       
   376 		
       
   377 	CleanupStack::PopAndDestroy(pubKey);
       
   378 	return ValidCert;  
       
   379 }
       
   380 
       
   381 
       
   382 CX509Certificate* IkePkiUtils::FindCaCertificateL(const CX509Certificate& aUserCert,
       
   383                                                   const CIkeCaList& aTrustedCAList)
       
   384     {
       
   385 	//
       
   386 	// Find a CA certificate from Trusted CA list (iTrustedCAList) for
       
   387 	// specified user certificate
       
   388 	//	
       
   389 	const CX500DistinguishedName& issuerName = aUserCert.IssuerName();	
       
   390 	CX509Certificate* caCert = NULL;
       
   391 
       
   392     for (TInt i = 0; i < aTrustedCAList.Count(); i++)
       
   393 	    {
       
   394     	//
       
   395 	    // Find CA certificate for current user certificate by
       
   396 	    // comparing certificate issuer name to the subject name of a
       
   397 	    // CA certificate
       
   398 	    //		
       
   399 		caCert = aTrustedCAList.At(i)->Certificate();
       
   400 		if ( issuerName.ExactMatchL(caCert->SubjectName()) )
       
   401 		    {
       
   402 		    break;	
       
   403 		    }
       
   404 		caCert = NULL;
       
   405 	    }	
       
   406 
       
   407 	return caCert;
       
   408     }
       
   409 
       
   410 
       
   411 TBool IkePkiUtils::VerifySignatureL(TInt aIkeVersion, 
       
   412                                     const TDesC8& aSignature, 
       
   413                                     const TDesC8& aRefHash, 
       
   414                                     const CX509Certificate& aCert)
       
   415     {
       
   416 	//
       
   417 	// Verify IKE signature. 
       
   418 	//
       
   419 	TBool status = EFalse;
       
   420 	
       
   421 	if ( aSignature.Length() > 0 )	
       
   422 	    {	    	
       
   423     	CIkePublicKey* publicKey = CIkePublicKey::NewL(aCert);
       
   424     	if ( !publicKey )
       
   425     	    {	    
       
   426     		return EFalse;			
       
   427     	    }
       
   428 
       
   429     	CleanupStack::PushL(publicKey);			
       
   430 
       
   431     	switch (publicKey->Algorithm())
       
   432     	    {
       
   433     		case EPKIRSA:
       
   434     			{
       
   435                 HBufC8 *resBuf;
       
   436                 TUtlCrypto::RsaPublicKeyDecryptL(publicKey->KeyData(), aSignature, resBuf);
       
   437                 CleanupStack::PushL(resBuf);							
       
   438                 
       
   439                 if ( aIkeVersion == MAJORV1 ) 
       
   440                     {
       
   441                     //
       
   442                     // Because IKEv1 signature is not a "real" PKCS1
       
   443                     // encoded signature but pure private encrypted has
       
   444                     // signature is verified by using RSA public key
       
   445                     // decrypt and result comparison to reference hash
       
   446                     //
       
   447                     status = (aRefHash.Compare(*resBuf) == 0); //Compare the result with the hash to see if they match
       
   448                     }
       
   449                 else
       
   450     				{
       
   451                     //
       
   452                     // IKEv2(n) signature is encoded as PKCS1v1_5
       
   453                     // signature (EMSA-PKCS1-v1_5)
       
   454                     // ASN1 encoding of signature is the following:
       
   455                     //	DigestInfo::=SEQUENCE{
       
   456                     //	  digestAlgorithm  AlgorithmIdentifier,
       
   457                     //	  digest OCTET STRING }
       
   458                     //
       
   459                     CArrayPtrFlat<TASN1DecGeneric>* seq = NULL;
       
   460                     TInt position = 0;
       
   461     									
       
   462                     TRAPD(err, seq = DecodeDERL(*resBuf, position));
       
   463                     if ( err == KErrNone )
       
   464                         {
       
   465                         TCleanupItem CleanupSeq(IkeCert::CleanupSequence, seq);						
       
   466                         CleanupStack::PushL(CleanupSeq);
       
   467                         if (seq->Count() == 2)
       
   468                             {
       
   469                             //
       
   470                             // Currently the digestAlgorithm is not
       
   471                             // verified, but only digest value itself is
       
   472                             // compared with reference hash.
       
   473                             // ( see CPKCS1SignatureResult::DoVerifyL() in
       
   474                             //   x509cert.cpp)
       
   475                             // 
       
   476                             const TASN1DecGeneric* gen2 = seq->At(1);                            
       
   477                             TPtrC8 digest(gen2->GetContentDER());
       
   478                             status = (aRefHash.Compare(digest) == 0);
       
   479                             }
       
   480                         CleanupStack::PopAndDestroy(); //CleanupSeq
       
   481                         }
       
   482                     else
       
   483                         {
       
   484                         //
       
   485                         // Verify signature as pure encrypted (SHA1)
       
   486                         // hash as old IKEv1 style "signature" 
       
   487                         //
       
   488                         //DEB(iService.PrintText(_L("Old IKEv1 style signature used by IKEv2 peer !\n"));)					   
       
   489                         status = (aRefHash.Compare(*resBuf) == 0); //Compare the result with the hash to see if they match					   
       
   490                         }	
       
   491     				}
       
   492                 CleanupStack::PopAndDestroy(resBuf);
       
   493     			break;
       
   494     			}
       
   495             case EPKIDSA:
       
   496                 {
       
   497                 const TPtrC8 sigR = aSignature.Left(aSignature.Length() / 2);
       
   498                 const TPtrC8 sigS = aSignature.Right(aSignature.Length() / 2);
       
   499 
       
   500                 status = TUtlCrypto::DsaVerifySignatureL(publicKey->KeyData(), 
       
   501                                                          publicKey->KeyParams(), 
       
   502                                                          sigR, sigS, aRefHash);
       
   503                 break;
       
   504                 }
       
   505             default:        //Only RSA and DSA are valid
       
   506                 User::Invariant();
       
   507             	break;
       
   508     		}
       
   509 
       
   510     	CleanupStack::PopAndDestroy(publicKey);
       
   511 	    }
       
   512 	return status;
       
   513     }	
       
   514 
       
   515 
       
   516 CArrayPtrFlat<TASN1DecGeneric>* IkePkiUtils::DecodeDERL(const TDesC8& aPtr, TInt& aPosition)
       
   517     {
       
   518 	TASN1DecSequence decSeq;
       
   519 	CArrayPtrFlat<TASN1DecGeneric>* seq =	decSeq.DecodeDERLC(aPtr, aPosition);
       
   520 	CleanupStack::Pop(seq);
       
   521 	return seq;
       
   522     }
       
   523 
       
   524 EXPORT_C CX509Certificate* IkePkiUtils::VerifyCertChainL(const CArrayFixFlat<CX509Certificate*>& aCerts, CX509Certificate*& realUserCert, const CIkeCaList& aTrustedCAList)
       
   525     {
       
   526     CX509Certificate* currCaCert=NULL;
       
   527     CX509Certificate* certOk=NULL;
       
   528     CArrayFixFlat<const CX500DistinguishedName*>* issuerArray=new (ELeave) CArrayFixFlat<const CX500DistinguishedName*> (aCerts.Count()); 
       
   529     CArrayFixFlat<const CX500DistinguishedName*>* subjectArray=new (ELeave) CArrayFixFlat<const CX500DistinguishedName*> (aCerts.Count()); 
       
   530     CleanupStack::PushL(issuerArray);
       
   531     CleanupStack::PushL(subjectArray);
       
   532     for ( TInt i = 0; i < aCerts.Count(); i++  ) 
       
   533         {
       
   534         issuerArray->AppendL(&aCerts.At(i)->IssuerName());
       
   535         subjectArray->AppendL(&aCerts.At(i)->SubjectName());
       
   536         }
       
   537     TInt userCertIndex=0; 
       
   538     TInt caCertIndex=0;
       
   539     
       
   540     //find UserCert from aCerts array if not in first certificate payload
       
   541     for ( TInt i = 0; i < (aCerts.Count()); i++  )
       
   542         {
       
   543         for ( TInt j = 0; j < (aCerts.Count()); j++  )
       
   544             {
       
   545             caCertIndex=j;
       
   546             if ( i!=caCertIndex )
       
   547                 {
       
   548                 const CX500DistinguishedName& issuerNameStr=*issuerArray->At(j);
       
   549                 if ( issuerNameStr.ExactMatchL(*subjectArray->At(i)) )
       
   550                     userCertIndex=i+1;
       
   551                 }
       
   552             }
       
   553         if ( userCertIndex == i && i!=caCertIndex )
       
   554             break;
       
   555         userCertIndex=i;
       
   556         }
       
   557     CleanupStack::PopAndDestroy(subjectArray);
       
   558     CleanupStack::PopAndDestroy(issuerArray);
       
   559     CX509Certificate* currCert = aCerts.At(userCertIndex);
       
   560     TInt currCertIndex=0; 
       
   561     realUserCert=currCert;
       
   562     //Verify chain and return highest CA
       
   563     while ( currCertIndex < aCerts.Count())
       
   564         {
       
   565         CX509Certificate* trustedCaCert  = IkePkiUtils::FindCaCertificateL(*currCert, aTrustedCAList);
       
   566         if ( trustedCaCert )
       
   567             return currCert;
       
   568         else
       
   569             {
       
   570             for ( TInt j = 0; j < aCerts.Count(); j++ )
       
   571                 {
       
   572                 currCaCert = aCerts.At(j);
       
   573                 if ( currCert->IssuerName().ExactMatchL(currCaCert->SubjectName()))
       
   574                     {
       
   575                     certOk = IkePkiUtils::VerifyX509CertificateL(*currCaCert, *currCert);
       
   576                     if ( certOk )
       
   577                         break;
       
   578                     }
       
   579                 }       
       
   580             if ( !certOk  ) //if chain is malicious break and return NULL
       
   581                 break;
       
   582             currCertIndex++;
       
   583             currCert=currCaCert;
       
   584             }
       
   585         }
       
   586         return NULL;
       
   587     }