os/security/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,613 @@
1.4 +/*
1.5 +* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include "pkixcertchainao.h"
1.23 +#include "pkixCons.h"
1.24 +#include <x509keys.h>
1.25 +#include <pkixcertchain.h>
1.26 +#include "x509constraintext.h"
1.27 +
1.28 +CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore,
1.29 + CPKIXCertChainBase &aPKIXCertChain,
1.30 + const RPointerArray<CX509Certificate>& aRootCerts)
1.31 + {
1.32 + CPKIXCertChainAO* self = new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain);
1.33 + CleanupStack::PushL(self);
1.34 + self->ConstructL(aRootCerts);
1.35 + CleanupStack::Pop(self);
1.36 + return self;
1.37 + }
1.38 +
1.39 +CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore,
1.40 + CPKIXCertChainBase &aPKIXCertChain,
1.41 + const TUid aClient)
1.42 + {
1.43 + return new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain, aClient);
1.44 + }
1.45 +
1.46 +CPKIXCertChainAO::~CPKIXCertChainAO()
1.47 + {
1.48 + Cancel();
1.49 +
1.50 + delete iRoots;
1.51 + delete iBuilder;
1.52 + delete iCertsFromStoreRoots;
1.53 + }
1.54 +
1.55 +CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore,
1.56 + CPKIXCertChainBase &aPKIXCertChain)
1.57 + : CActive(EPriorityNormal), iCertStore(&aCertStore), iPKIXCertChain(aPKIXCertChain)
1.58 + {
1.59 + CActiveScheduler::Add(this);
1.60 + }
1.61 +
1.62 +CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore,
1.63 + CPKIXCertChainBase &aPKIXCertChain,
1.64 + const TUid aClient)
1.65 + : CActive(EPriorityNormal), iCertStore(&aCertStore),
1.66 + iPKIXCertChain(aPKIXCertChain), iClient(aClient)
1.67 + {
1.68 + CActiveScheduler::Add(this);
1.69 + }
1.70 +
1.71 +void CPKIXCertChainAO::ConstructL(const RPointerArray<CX509Certificate>& aRootCerts)
1.72 + {
1.73 + CPKIXCertsFromClient* roots = CPKIXCertsFromClient::NewLC(aRootCerts);
1.74 + iRoots = CPKIXChainBuilder::NewL();
1.75 + iRoots->AddSourceL(roots);
1.76 + CleanupStack::Pop(roots);
1.77 + }
1.78 +
1.79 +void CPKIXCertChainAO::RunL()
1.80 + {
1.81 + User::LeaveIfError(iStatus.Int());
1.82 +
1.83 + switch (iState)
1.84 + {
1.85 + case EAddRoots:
1.86 + HandleEAddRootsL();
1.87 + break;
1.88 +
1.89 + case ERootsInitialized:
1.90 + HandleERootsInitializedL();
1.91 + break;
1.92 +
1.93 + case EBuildChainStart:
1.94 + HandleEBuildChainStartL();
1.95 + break;
1.96 +
1.97 + case EBuildChainAddCandidateEnd:
1.98 + HandleEBuildChainAddCandidateEndL();
1.99 + break;
1.100 +
1.101 + case EBuildChainCertsFromStoreBegin:
1.102 + HandleEBuildChainCertsFromStoreBeginL();
1.103 + break;
1.104 +
1.105 + case EBuildChainCertsFromStoreEnd:
1.106 + HandleEBuildChainCertsFromStoreEndL();
1.107 + break;
1.108 +
1.109 + case EAddCandidateIntermediateCertsEnd:
1.110 + HandleEAddCandidateIntermediateCertsEndL();
1.111 + break;
1.112 +
1.113 + case EValidateEnd:
1.114 + HandleEValidateEndL();
1.115 + break;
1.116 +
1.117 + default:
1.118 + User::Panic(_L("CPKIXCertChainAO"), 1);
1.119 + break;
1.120 + }
1.121 + }
1.122 +
1.123 +TInt CPKIXCertChainAO::RunError(TInt aError)
1.124 +{
1.125 + iPKIXCertChain.RemoveLastCerts(iNumberOfAddedCertificates);
1.126 + iNumberOfAddedCertificates = 0;
1.127 +
1.128 + delete iRoots;
1.129 + iRoots = 0;
1.130 +
1.131 + delete iBuilder;
1.132 + iBuilder = 0;
1.133 + delete iCertsFromStoreRoots;
1.134 + iCertsFromStoreRoots = 0;
1.135 +
1.136 + iValidationResult->RemovePolicies();
1.137 +
1.138 + User::RequestComplete(iOriginalRequestStatus, aError);
1.139 + return KErrNone;
1.140 +}
1.141 +
1.142 +/**
1.143 + * Creates a list of all the certificates retrieved from the store based on the filter passed.
1.144 + */
1.145 +
1.146 +void CPKIXCertChainAO::HandleEAddRootsL()
1.147 + {
1.148 + __ASSERT_DEBUG(!iCertsFromStoreRoots, User::Panic(_L("CPKICCertChainAO"), 1));
1.149 + iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore, iClient);
1.150 + iCertsFromStoreRoots->Initialize(iStatus);
1.151 + iState = ERootsInitialized;
1.152 + SetActive();
1.153 + }
1.154 +
1.155 +/**
1.156 + * Adds the list of certificates retrieved from the store, iRoots (CPKIXChainBuilder)
1.157 + * maintains a templatized list of all the certificates in MPKIXCertSource format.
1.158 + */
1.159 +
1.160 +void CPKIXCertChainAO::HandleERootsInitializedL()
1.161 + {
1.162 + iRoots->AddSourceL(iCertsFromStoreRoots);
1.163 + // Ownership has been passed to iRoots
1.164 + iCertsFromStoreRoots = 0;
1.165 + iState = EBuildChainStart;
1.166 + TRequestStatus* status = &iStatus;
1.167 + User::RequestComplete(status, KErrNone);
1.168 + SetActive();
1.169 + }
1.170 +
1.171 +void CPKIXCertChainAO::HandleEBuildChainStartL()
1.172 + {
1.173 + if ( false == iPKIXCertChain.ChainHasRoot())
1.174 + {
1.175 + if (iPKIXCertChain.Chain().Count() == 0)
1.176 + {
1.177 + iState = EValidateEnd;
1.178 + TRequestStatus* status = &iStatus;
1.179 + User::RequestComplete(status, KErrNone);
1.180 + }
1.181 + else
1.182 + {
1.183 + //1) look for an issuer that's a root
1.184 + iRoots->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
1.185 + iState = EBuildChainAddCandidateEnd;
1.186 + }
1.187 + }
1.188 + else
1.189 + {
1.190 + // This is the correct state as at this point the chain of certificate has been build upto a
1.191 + // root certificate.
1.192 + iState = EValidateEnd;
1.193 + TRequestStatus* status = &iStatus;
1.194 + User::RequestComplete(status, KErrNone);
1.195 + }
1.196 + SetActive();
1.197 + }
1.198 +
1.199 +void CPKIXCertChainAO::HandleEBuildChainAddCandidateEndL()
1.200 + {
1.201 + if (iAddIssuerResult)
1.202 + {
1.203 + iPKIXCertChain.SetChainHasRoot(ETrue);
1.204 + iState = EValidateEnd;
1.205 + }
1.206 + else
1.207 + {
1.208 + //2) look for a non-root issuer in intermediate certs
1.209 + iBuilder = CPKIXChainBuilder::NewL();
1.210 +
1.211 + CPKIXCertsFromClient* serverCerts = CPKIXCertsFromClient::NewLC(iPKIXCertChain.IntermediateCerts());
1.212 + iBuilder->AddSourceL(serverCerts);
1.213 + CleanupStack::Pop(serverCerts);
1.214 +
1.215 + iState = EBuildChainCertsFromStoreBegin;
1.216 + }
1.217 +
1.218 + TRequestStatus* status = &iStatus;
1.219 + User::RequestComplete(status, KErrNone);
1.220 + SetActive();
1.221 + }
1.222 +
1.223 +void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreBeginL()
1.224 + {
1.225 + //3) look for a non-root issuer in the store
1.226 + iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore);
1.227 + iCertsFromStoreRoots->Initialize(iStatus);
1.228 + iState = EBuildChainCertsFromStoreEnd;
1.229 + SetActive();
1.230 + }
1.231 +
1.232 +void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreEndL()
1.233 + {
1.234 + iBuilder->AddSourceL(iCertsFromStoreRoots);
1.235 + iCertsFromStoreRoots = 0;
1.236 +
1.237 + iBuilder->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
1.238 + iState = EAddCandidateIntermediateCertsEnd;
1.239 + SetActive();
1.240 + }
1.241 +
1.242 +void CPKIXCertChainAO::HandleEAddCandidateIntermediateCertsEndL()
1.243 + {
1.244 + if (iAddIssuerResult)
1.245 + {
1.246 + // cert is a pointer to something we don't own
1.247 + CX509Certificate* cert = iPKIXCertChain.Chain().At(iPKIXCertChain.Chain().Count() - 1);
1.248 +
1.249 + /* If the issuer is not a self signed certificate then it cannot be trusted anchor for the chain
1.250 + * validation process, this means that we restart the certification validation process.
1.251 + */
1.252 +
1.253 + if (!(cert->IsSelfSignedL()))
1.254 + {
1.255 + iState = EBuildChainStart;
1.256 + }
1.257 + else
1.258 + {
1.259 + iState = EValidateEnd;
1.260 + }
1.261 + }
1.262 + else
1.263 + {
1.264 + iState = EValidateEnd;
1.265 + }
1.266 +
1.267 + delete iBuilder;
1.268 + iBuilder = 0;
1.269 +
1.270 + TRequestStatus* status = &iStatus;
1.271 + User::RequestComplete(status, KErrNone);
1.272 + SetActive();
1.273 + }
1.274 +
1.275 +void CPKIXCertChainAO::HandleEValidateEndL()
1.276 + {
1.277 + InitParamsL();
1.278 +
1.279 + __ASSERT_DEBUG(iValidationResult, User::Panic(_L("CPKICCertChainAO"), 1));
1.280 + DoValidateL(*iValidationResult, iValidationTime, iInitialPolicies);
1.281 +
1.282 + User::RequestComplete(iOriginalRequestStatus, KErrNone);
1.283 + }
1.284 +
1.285 +void CPKIXCertChainAO::DoCancel()
1.286 + {
1.287 + delete iRoots;
1.288 + iRoots = 0;
1.289 +
1.290 + delete iBuilder;
1.291 + iBuilder = 0;
1.292 +
1.293 + delete iCertsFromStoreRoots;
1.294 + iCertsFromStoreRoots = 0;
1.295 +
1.296 + User::RequestComplete(iOriginalRequestStatus, KErrCancel);
1.297 + }
1.298 +
1.299 +void CPKIXCertChainAO::ValidateL(CPKIXValidationResultBase& aValidationResult,
1.300 + const TTime& aValidationTime,
1.301 + const CArrayPtr<HBufC>* aInitialPolicies,
1.302 + TRequestStatus& aStatus)
1.303 + {
1.304 + aValidationResult.Reset();
1.305 + iValidationResult = &aValidationResult;
1.306 + iValidationTime = aValidationTime;
1.307 + iInitialPolicies = aInitialPolicies;
1.308 + iOriginalRequestStatus = &aStatus;
1.309 + iNumberOfAddedCertificates = 0;
1.310 +
1.311 + __ASSERT_ALWAYS(!IsActive(), User::Panic(_L("CPKICCertChainAO"), 1));
1.312 +
1.313 + if (!iRoots)
1.314 + {
1.315 + // If iRoots is 0, it means that the caller gave a uid and that
1.316 + // we must retrieve the trusted certificates from the different
1.317 + // stores
1.318 + iRoots = CPKIXChainBuilder::NewL();
1.319 + iState = EAddRoots;
1.320 + }
1.321 + else
1.322 + {
1.323 + // The caller gave a set of certificates it trusts,
1.324 + // so we don't have to retrieve anything from the stores
1.325 + iState = EBuildChainStart;
1.326 + }
1.327 +
1.328 + aStatus = KRequestPending;
1.329 + TRequestStatus *status = &iStatus;
1.330 + User::RequestComplete(status, KErrNone);
1.331 + SetActive();
1.332 + }
1.333 +
1.334 +void CPKIXCertChainAO::CancelValidate()
1.335 + {
1.336 + Cancel();
1.337 + }
1.338 +
1.339 +void CPKIXCertChainAO::InitParamsL()
1.340 +/*
1.341 +this function initialises signing key parameters for the certificates
1.342 +-only DSA needs these at present
1.343 +-we get the signing key, from the spki of the issuer
1.344 +-if it's dsa, we look for params here
1.345 + -if we find them we initialise the cert with them
1.346 + -otherwise, we look in the issuer's issuer
1.347 + -if we don't find them there we give up.
1.348 +*/
1.349 + {
1.350 +
1.351 + // If the root is DSA signed, set its parameters
1.352 +
1.353 + TInt count = iPKIXCertChain.Chain().Count();
1.354 +
1.355 + CX509Certificate* current = iPKIXCertChain.Chain().At(count-1);
1.356 + TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
1.357 +
1.358 + if (signingAlgorithm == EDSA)
1.359 + {
1.360 +
1.361 + const CSubjectPublicKeyInfo& key = current->PublicKey();
1.362 + SetParamsL(*current, key.EncodedParams());
1.363 +
1.364 + }
1.365 +
1.366 + // Also the rest of the chain
1.367 +
1.368 + for (TInt i = count - 2; i >= 0; i--)
1.369 + {
1.370 +
1.371 + current = iPKIXCertChain.Chain().At(i);
1.372 + TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
1.373 +
1.374 + if (signingAlgorithm == EDSA)
1.375 + {
1.376 +
1.377 + // Look down the chain for parameters
1.378 +
1.379 + for (TInt j = i+1; j < count; j++)
1.380 + {
1.381 +
1.382 + CX509Certificate* issuer = iPKIXCertChain.Chain().At(j);
1.383 + const CSubjectPublicKeyInfo& key = issuer->PublicKey();
1.384 + if (key.EncodedParams() != KNullDesC8 && key.AlgorithmId() == EDSA)
1.385 + {
1.386 + SetParamsL(*current, key.EncodedParams());
1.387 + break;
1.388 + }
1.389 +
1.390 + }
1.391 +
1.392 + }
1.393 +
1.394 + }
1.395 + }
1.396 +
1.397 +void CPKIXCertChainAO::SetParamsL(CX509Certificate& aCert, const TPtrC8& aEncodedParams)
1.398 + {
1.399 + TX509KeyFactory factory;
1.400 + CDSAParameters* theDSAParams = factory.DSAParametersL(aEncodedParams);
1.401 + CleanupStack::PushL(theDSAParams);
1.402 +
1.403 + CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
1.404 + params->SetDSAParamsL(*theDSAParams);
1.405 +
1.406 + aCert.SetParametersL(*params);
1.407 +
1.408 + CleanupStack::PopAndDestroy(2, theDSAParams);
1.409 + }
1.410 +
1.411 +void CPKIXCertChainAO::DoValidateL(CPKIXValidationResultBase& aValidationResult,
1.412 + const TTime& aValidationTime,
1.413 + const CArrayPtr<HBufC>* aInitialPolicies)
1.414 + {
1.415 + if (!iPKIXCertChain.ChainHasRoot())
1.416 + {
1.417 + aValidationResult.SetError(EChainHasNoRoot, 0);
1.418 + }
1.419 + else
1.420 + {
1.421 + CPKIXValidationState* state = CPKIXValidationState::NewLC(aValidationTime, iPKIXCertChain.Chain().Count(), aInitialPolicies);
1.422 + TRAPD(err, ProcessCertsL(*state, aValidationResult));
1.423 + //a leave here means either:
1.424 + // -a validation error, in which case we've set the error field in result, or
1.425 + // -some other error (e.g. OOM) in which case error is still EChainHasNoRoot
1.426 + if ((err != KErrNone) && ((aValidationResult.Error().iReason) == EChainHasNoRoot))
1.427 + //then we left with a non-validation-related error, so leave again...
1.428 + {
1.429 + User::Leave(err);
1.430 + }
1.431 + CleanupStack::PopAndDestroy(state);
1.432 + }
1.433 + }
1.434 +
1.435 +// ProcessCertsL: This function validates a complete certificate
1.436 +// chain. If an error occurs in this function the function
1.437 +// SetErrorAndLeaveL must be called.
1.438 +//
1.439 +// Note Do not use SetErrorAndLeaveL with EChainHasNoRoot (see TRAP code in
1.440 +// CPKIXCertChainAO::DoValidateL )
1.441 +void CPKIXCertChainAO::ProcessCertsL(CPKIXValidationState& aState,
1.442 + CPKIXValidationResultBase& aResult) const
1.443 + {
1.444 + TPKIXPolicyConstraint policy(aState, aResult);
1.445 + TPKIXNameConstraint name(aState, aResult);
1.446 + TPKIXBasicConstraint basic(aState, aResult);
1.447 + TPKIXKeyUsageConstraint keyUsage(aState, aResult);
1.448 + for (; aState.iPos >= 0; aState.iPos--)
1.449 + {
1.450 + aState.iMaxPathLength--;
1.451 + if (aState.iMaxPathLength < aState.iPos)
1.452 + {
1.453 + aResult.SetErrorAndLeaveL(EPathTooLong, aState.iPos);
1.454 + }
1.455 + const CX509Certificate* current = iPKIXCertChain.Chain().At(aState.iPos);
1.456 + CCertificateValidationWarnings* certWarnings = CCertificateValidationWarnings::NewLC(aState.iPos);
1.457 + aResult.AppendCertificateValidationObjectL(*certWarnings);
1.458 + CleanupStack::Pop(certWarnings);
1.459 + CriticalExtsL(aState, *current);
1.460 + CheckCriticalExtsL(aState, aResult);
1.461 + CheckSignatureAndNameL(*current, aState, aResult);
1.462 + //!!!!NO!!checks for revocation at this time!!
1.463 +
1.464 + if (!(current->ValidityPeriod().Valid(aState.iValidationTime)))
1.465 + {
1.466 + //validity period invalid, now check how to report this
1.467 + if (iPKIXCertChain.ValidityPeriodCheckFatal())
1.468 + {
1.469 + aResult.SetErrorAndLeaveL(EDateOutOfRange, aState.iPos);
1.470 + }
1.471 + else
1.472 + {
1.473 + aResult.AppendWarningL(TValidationStatus(EDateOutOfRange, aState.iPos));
1.474 + }
1.475 + }
1.476 +
1.477 + policy.CheckCertPoliciesL(*current);
1.478 + name.CheckNameConstraintsL(*current);
1.479 + keyUsage.CheckKeyUsageL(*current);
1.480 + if (aState.iPos < (iPKIXCertChain.Chain().Count() - 1))
1.481 + {
1.482 + basic.CheckCertSubjectTypeL(*current);
1.483 + }
1.484 + basic.UpdatePathLengthConstraintsL(*current);
1.485 + name.UpdateNameConstraintsL(*current);
1.486 + policy.UpdatePolicyConstraintsL(*current);
1.487 + aState.iCriticalExts->Reset();
1.488 + }
1.489 + policy.FinishPolicyCheckL();
1.490 + //*copy* all policies from aState.iAuthorityConstrainedPolicies into aResult.iPolicies
1.491 + TInt policyCount = aState.iAuthorityConstrainedPolicies->Count();
1.492 + for (TInt i = 0; i < policyCount; i ++)
1.493 + {
1.494 + CX509CertPolicyInfo* policyInfo = CX509CertPolicyInfo::NewLC(*(aState.iAuthorityConstrainedPolicies->At(i)));
1.495 + aResult.AppendPolicyL(*policyInfo);
1.496 + CleanupStack::Pop(policyInfo);
1.497 + }
1.498 +
1.499 + aResult.SetError(EValidatedOK, 0);
1.500 + }
1.501 +
1.502 +void CPKIXCertChainAO::CriticalExtsL(CPKIXValidationState& aState,
1.503 + const CX509Certificate& aCert) const
1.504 + {
1.505 + const CArrayPtrFlat<CX509CertExtension>& exts = aCert.Extensions();
1.506 + TInt count = exts.Count();
1.507 + for (TInt i = 0; i < count; i++)
1.508 + {
1.509 + CX509CertExtension* ext = exts.At(i);
1.510 + if (ext->Critical())
1.511 + {
1.512 + aState.iCriticalExts->AppendL(ext);
1.513 + }
1.514 + }
1.515 + }
1.516 +
1.517 +void CPKIXCertChainAO::CheckSignatureAndNameL(const CX509Certificate& aCert, CPKIXValidationState& aState,
1.518 + CPKIXValidationResultBase& aResult) const
1.519 + {
1.520 + TInt issuerPos = aState.iPos + 1;
1.521 + if (issuerPos == iPKIXCertChain.Chain().Count())
1.522 + //then it's the root
1.523 + {
1.524 + if (aCert.IssuerName().ExactMatchL(aCert.SubjectName()))
1.525 + //then it claims to be self signed, sig must verify
1.526 + {
1.527 + if (!(aCert.VerifySignatureL(aCert.PublicKey().KeyData())))
1.528 + {
1.529 + aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
1.530 + }
1.531 + }
1.532 + else
1.533 + //we generate a warning
1.534 + {
1.535 + aResult.AppendWarningL(TValidationStatus(ERootCertNotSelfSigned, aState.iPos));
1.536 + }
1.537 + }
1.538 + else
1.539 + //then it isn't the root: so names must chain & sigs must verify
1.540 + {
1.541 + const CX509Certificate* issuer = iPKIXCertChain.Chain().At(issuerPos);
1.542 + if (!(aCert.IssuerName().ExactMatchL(issuer->SubjectName())))
1.543 + {
1.544 + aResult.SetErrorAndLeaveL(ENamesDontChain, aState.iPos);
1.545 + }
1.546 + if (!(aCert.VerifySignatureL(issuer->PublicKey().KeyData())))
1.547 + {
1.548 + aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
1.549 + }
1.550 + }
1.551 + }
1.552 +
1.553 +void CPKIXCertChainAO::CheckCriticalExtsL(CPKIXValidationState& aState, CPKIXValidationResultBase& aResult) const
1.554 + {
1.555 + TBool foundUnrecognisedCritExt;
1.556 +
1.557 + // retrieve the supported list of critical extensions. If a critical extension is found whose OID matches an
1.558 + // element in this set then certificate validation shall treat this as a warning instead of an error.
1.559 + const RPointerArray<TDesC>& supportedCritExt = iPKIXCertChain.SupportedCriticalExtensions();
1.560 +
1.561 + TInt count = aState.iCriticalExts->Count();
1.562 + TInt supportedCount = supportedCritExt.Count();
1.563 + for (TInt i = 0; i < count; i++)
1.564 + {
1.565 + foundUnrecognisedCritExt = ETrue;
1.566 + const CX509CertExtension* ext = aState.iCriticalExts->At(i);
1.567 + const TPtrC& extName = ext->Id();
1.568 +
1.569 + for (TInt j = 0; j < supportedCount; ++j)
1.570 + {
1.571 + if (extName == *supportedCritExt[j])
1.572 + {
1.573 + foundUnrecognisedCritExt = EFalse;
1.574 + HBufC* oid = extName.AllocLC();
1.575 + aResult.AppendCriticalExtensionWarningL(*oid);
1.576 + CleanupStack::Pop(oid);
1.577 + break;
1.578 + }
1.579 + }
1.580 +
1.581 + if (extName == KExtendedKeyUsage)
1.582 + {
1.583 + aResult.AppendWarningL(TValidationStatus(ECriticalExtendedKeyUsage, aState.iPos));
1.584 + }
1.585 + else if (extName == KPolicyMapping)
1.586 + {
1.587 + aResult.AppendWarningL(TValidationStatus(ECriticalPolicyMapping, aState.iPos));
1.588 + }
1.589 + else if (extName == KInhibitAnyPolicy)
1.590 + {
1.591 + //ignore this in the same way
1.592 + }
1.593 + else if (extName == KDeviceIdListConstraint)
1.594 + {
1.595 + aResult.AppendWarningL(TValidationStatus(ECriticalDeviceId, aState.iPos));
1.596 + }
1.597 + else if(extName == KSidListConstraint)
1.598 + {
1.599 + aResult.AppendWarningL(TValidationStatus(ECriticalSid, aState.iPos));
1.600 + }
1.601 + else if(extName == KVidListConstraint)
1.602 + {
1.603 + aResult.AppendWarningL(TValidationStatus(ECriticalVid, aState.iPos));
1.604 + }
1.605 + else if(extName == KCapabilitiesConstraint)
1.606 + {
1.607 + aResult.AppendWarningL(TValidationStatus(ECriticalCapabilities, aState.iPos));
1.608 + }
1.609 +
1.610 + if (foundUnrecognisedCritExt)
1.611 + {
1.612 + aResult.SetErrorAndLeaveL(EUnrecognizedCriticalExtension, aState.iPos);
1.613 + }
1.614 +
1.615 + }
1.616 + }