|
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 } |