First public contribution.
2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
22 //only function is remove
23 TPKIXConstraint::TPKIXConstraint( CPKIXValidationState& aState,
24 CPKIXValidationResultBase& aResult)
25 :iState(aState), iResult(aResult)
29 void TPKIXConstraint::Remove(CArrayPtrFlat<CX509CertExtension>& aCriticalExtensions, const TDesC& aOID)
31 TInt count = aCriticalExtensions.Count();
32 for (TInt i = 0; i < count; i++)
34 CX509CertExtension* ext = aCriticalExtensions.At(i);
35 if (ext->Id() == aOID)
37 aCriticalExtensions.Delete(i);
45 TPKIXPolicyConstraint::TPKIXPolicyConstraint( CPKIXValidationState& aState,
46 CPKIXValidationResultBase& aResult)
47 :TPKIXConstraint(aState, aResult)
51 void TPKIXPolicyConstraint::CleanupPolicyInfoArray(TAny* aPolicies)
53 CArrayPtrFlat<CX509CertPolicyInfo>* array = REINTERPRET_CAST(CArrayPtrFlat<CX509CertPolicyInfo>*, aPolicies);
54 array->ResetAndDestroy();
58 void TPKIXPolicyConstraint::CheckCertPoliciesL(const CX509Certificate& aCert)
60 const CX509CertExtension* ext = aCert.Extension(KCertPolicies);
61 CX509CertPoliciesExt* policyExt = NULL;
64 policyExt = CX509CertPoliciesExt::NewLC(ext->Data());
66 if (iState.iPos > iState.iPolicyRequired)
70 iResult.SetErrorAndLeaveL(ERequiredPolicyNotFound, iState.iPos);
72 const CArrayPtrFlat<CX509CertPolicyInfo>& policies = policyExt->Policies();
73 if ((iState.iUserPolicies->Count() == 0) || (PolicyIsPresentL(policies, *iState.iUserPolicies)))
78 iResult.SetErrorAndLeaveL(ERequiredPolicyNotFound, iState.iPos);
83 if (!iState.iAnyAuthorityPolicy)
85 iState.iAuthorityConstrainedPolicies->ResetAndDestroy();//AP becomes NULL
90 IntersectCertPoliciesL(*policyExt);
93 TInt count = iState.iAuthorityConstrainedPolicies->Count();
94 for (TInt i = 0; i < count; i++)
96 const CX509CertPolicyInfo* policy = iState.iAuthorityConstrainedPolicies->At(i);
97 if (policy->Qualifiers().Count() > 0)
99 iResult.AppendWarningL(TValidationStatus(ECriticalCertPoliciesWithQualifiers, i));
103 Remove(*(iState.iCriticalExts), KCertPolicies);
105 CleanupStack::PopAndDestroy();//policyExt
109 void TPKIXPolicyConstraint::IntersectCertPoliciesL(const CX509CertPoliciesExt& aPolicyExt)
111 //1 intersect AP and CP, assign result to newAP
112 CArrayPtrFlat<CX509CertPolicyInfo>* newAP;
113 TInt certPolicyCount = aPolicyExt.Policies().Count();
114 if (iState.iAnyAuthorityPolicy)
116 newAP = new(ELeave) CArrayPtrFlat<CX509CertPolicyInfo> (1);
117 TCleanupItem cleanupPolicies(CleanupPolicyInfoArray, newAP);
118 CleanupStack::PushL(cleanupPolicies);
119 for (TInt i = 0; i < certPolicyCount; i++)
121 CX509CertPolicyInfo* info = CX509CertPolicyInfo::NewLC(*(aPolicyExt.Policies().At(i)));
122 newAP->AppendL(info);
125 iState.iAnyAuthorityPolicy = EFalse;
129 newAP = IntersectionLC(aPolicyExt.Policies(), *(iState.iAuthorityConstrainedPolicies));
132 TInt mappedCount = iState.iMappedPolicies->Count();
133 for (TInt i = 0; i < mappedCount; i++)
135 CX509PolicyMapping* mapping = iState.iMappedPolicies->At(i);
136 TInt apCount = iState.iAuthorityConstrainedPolicies->Count();
137 //2 for each mapping in MP, if issuer is in AP and subject is in CP, add subject to newAP
138 for (TInt j = 0; j < apCount; j++)
140 CX509CertPolicyInfo* aCP = iState.iAuthorityConstrainedPolicies->At(j);
141 if (aCP->Id() == mapping->IssuerPolicy())
143 for (TInt k = 0; k < certPolicyCount; k++)
145 CX509CertPolicyInfo* cp = aPolicyExt.Policies().At(k);
146 if (mapping->SubjectPolicy() == cp->Id())
148 CX509CertPolicyInfo* newPolicy = CX509CertPolicyInfo::NewLC(*cp);
149 newAP->AppendL(newPolicy);
156 //new acceptable policies = intersection
157 iState.iAuthorityConstrainedPolicies->ResetAndDestroy();
158 delete iState.iAuthorityConstrainedPolicies;
159 iState.iAuthorityConstrainedPolicies = newAP;
160 CleanupStack::Pop();//newAP
163 void TPKIXPolicyConstraint::UpdatePolicyConstraintsL(const CX509Certificate& aCert)
166 const CX509CertExtension* ext = aCert.Extension(KPolicyMapping);
167 if ((iState.iPos <= iState.iPolicyMapping) && (ext))
169 CX509PolicyMappingExt* policyMappingExt = CX509PolicyMappingExt::NewLC(ext->Data());
170 const CArrayPtrFlat<CX509PolicyMapping>& mappings = policyMappingExt->Mappings();
171 //for each policy mapping
172 TInt countM = mappings.Count();
173 for (TInt i = 0; i < countM; i++)
175 CX509PolicyMapping* mapping = mappings.At(i);
176 CX509PolicyMapping* newMapping = CX509PolicyMapping::NewLC(*mapping);
177 iState.iMappedPolicies->AppendL(newMapping);
179 TInt uCount = iState.iUserPolicies->Count();
180 for (TInt j = 0; j < uCount; j++)
182 HBufC* userPolicy = iState.iUserPolicies->At(j);
183 if (newMapping->IssuerPolicy() == *userPolicy)
185 HBufC* newUP = newMapping->SubjectPolicy().AllocL();
186 CleanupStack::PushL(newUP);
187 iState.iUserPolicies->AppendL(newUP);
193 CleanupStack::PopAndDestroy();//mapping ext
195 iState.iPolicyMapping --;
196 iState.iPolicyRequired --;
198 ext = aCert.Extension(KPolicyConstraints);
201 CX509PolicyConstraintsExt* policyConstraintsExt = CX509PolicyConstraintsExt::NewLC(ext->Data());
202 UpdateConstraint(policyConstraintsExt->InhibitPolicyMapping(), iState.iPolicyMapping);
203 UpdateConstraint(policyConstraintsExt->ExplicitPolicyRequired(), iState.iPolicyRequired);
204 CleanupStack::PopAndDestroy();//constraint ext
205 //remove it from the 'critical list'
208 Remove(*(iState.iCriticalExts), KPolicyConstraints);
214 TBool TPKIXPolicyConstraint::PolicyIsPresentL( const CArrayPtrFlat<CX509CertPolicyInfo>& aPolicies,
215 const CArrayPtr<HBufC>& aAcceptablePolicies)
217 TInt certCount = aPolicies.Count();
218 TInt chainCount = aAcceptablePolicies.Count();
219 for (TInt i = 0; i < certCount; i++)
221 CX509CertPolicyInfo* certPolicy = aPolicies.At(i);
222 for (TInt j = 0; j < chainCount; j++)
224 HBufC* chainPolicy = aAcceptablePolicies.At(j);
225 if (certPolicy->Id() == chainPolicy->Des())
234 void TPKIXPolicyConstraint::UpdateConstraint(const TX509PolicyConstraint& aConstraint, TInt& aCountdown)
236 if (aConstraint.iRequired)
238 if (aConstraint.iCountdown < aCountdown)
239 aCountdown = aConstraint.iCountdown;
243 void TPKIXPolicyConstraint::FinishPolicyCheckL()
245 if (iState.iUserConstrainedPolicies)
247 TBool passed = EFalse;
248 if (!(iState.iAnyAuthorityPolicy))
249 {//policy from user policies must be in authority policy set
250 if ((PolicyIsPresentL(*(iState.iAuthorityConstrainedPolicies), *(iState.iUserPolicies))))
257 iResult.SetErrorAndLeaveL(ERequiredPolicyNotFound, iState.iPos);
262 CArrayPtrFlat<CX509CertPolicyInfo>* TPKIXPolicyConstraint::IntersectionLC(
263 const CArrayPtrFlat<CX509CertPolicyInfo>& aFirst,
264 const CArrayPtrFlat<CX509CertPolicyInfo>& aSecond)
265 //constructs an array of certificate policy objects,
266 //populating it with policies that occur in both of the array parameters
268 CArrayPtrFlat<CX509CertPolicyInfo>* inter = new(ELeave) CArrayPtrFlat<CX509CertPolicyInfo> (1);
269 TCleanupItem cleanupPolicies(CleanupPolicyInfoArray, inter);
270 CleanupStack::PushL(cleanupPolicies);
271 TInt count1 = aFirst.Count();
272 TInt count2 = aSecond.Count();
273 for (TInt i = 0; i < count1; i++)
275 CX509CertPolicyInfo* policy1 = aFirst.At(i);
276 for (TInt j = 0; j < count2; j++)
278 CX509CertPolicyInfo* policy2 = aSecond.At(j);
279 if (policy1->Id() == policy2->Id())
281 CX509CertPolicyInfo* info = CX509CertPolicyInfo::NewLC(*policy1);
282 inter->AppendL(info);
292 TPKIXNameConstraint::TPKIXNameConstraint( CPKIXValidationState& aState,
293 CPKIXValidationResultBase& aResult)
294 :TPKIXConstraint(aState, aResult)
298 void TPKIXNameConstraint::CheckNameConstraintsL(const CX509Certificate& aCert)
300 //*do the subject name
301 if (NameIsPresentL(aCert.SubjectName(), *(iState.iExcludedDNSubtrees)))
303 iResult.SetErrorAndLeaveL(ENameIsExcluded, iState.iPos);
305 TInt pCount = iState.iPermittedDNSubtrees->Count();
306 if ((pCount > 0) && (!(NameIsPresentL(aCert.SubjectName(), *(iState.iPermittedDNSubtrees)))))
308 iResult.SetErrorAndLeaveL(ENameNotPermitted, iState.iPos);
311 const CX509CertExtension* ext = aCert.Extension(KSubjectAltName);
314 CX509AltNameExt* altNameExt = CX509AltNameExt::NewLC(ext->Data());
315 const CArrayPtrFlat<CX509GeneralName>& altName = altNameExt->AltName();
316 TInt count = altName.Count();
317 for (TInt i = 0; i < count; i++)
319 const CX509GeneralName* gN = altName.At(i);
322 case EX509DirectoryName://X500DN
324 const CX500DistinguishedName* dN = CX500DistinguishedName::NewLC(gN->Data());
325 if (NameIsPresentL(*dN, *(iState.iExcludedDNSubtrees)))
327 iResult.SetErrorAndLeaveL(ENameIsExcluded, iState.iPos);
329 if ((pCount > 0) && (!(NameIsPresentL(*dN, *(iState.iPermittedDNSubtrees)))))
331 iResult.SetErrorAndLeaveL(ENameNotPermitted, iState.iPos);
333 CleanupStack::PopAndDestroy();
336 case EX509RFC822Name://IA5String
338 const CX509RFC822Name* name = CX509RFC822Name::NewLC(gN->Data());
339 if (NameIsPresent(*name, *(iState.iExcludedRFC822Subtrees)))
341 iResult.SetErrorAndLeaveL(ENameIsExcluded, iState.iPos);
343 if ((iState.iPermittedRFC822Subtrees->Count() > 0) && (!(NameIsPresent(*name, *(iState.iPermittedRFC822Subtrees)))))
345 iResult.SetErrorAndLeaveL(ENameNotPermitted, iState.iPos);
347 CleanupStack::PopAndDestroy();
350 case EX509URI://IA5String
352 const CX509IPBasedURI* name = CX509IPBasedURI::NewLC(gN->Data());
353 const CX509DNSName& domain = name->Host();
354 if (NameIsPresent(domain, *(iState.iExcludedDNSNameSubtrees)))
356 iResult.SetErrorAndLeaveL(ENameIsExcluded, iState.iPos);
358 if ((iState.iPermittedDNSNameSubtrees->Count() > 0) && (!(NameIsPresent(domain, *(iState.iPermittedDNSNameSubtrees)))))
360 iResult.SetErrorAndLeaveL(ENameNotPermitted, iState.iPos);
362 CleanupStack::PopAndDestroy();
365 case EX509DNSName://IA5String
367 const CX509DNSName* name = CX509DNSName::NewLC(gN->Data());
368 if (NameIsPresent(*name, *(iState.iExcludedDNSNameSubtrees)))
370 iResult.SetErrorAndLeaveL(ENameIsExcluded, iState.iPos);
372 if ((iState.iPermittedDNSNameSubtrees->Count() > 0) && (!(NameIsPresent(*name, *(iState.iPermittedDNSNameSubtrees)))))
374 iResult.SetErrorAndLeaveL(ENameNotPermitted, iState.iPos);
376 CleanupStack::PopAndDestroy();
379 case EX509IPAddress://octet string
381 const CX509IPAddress* name = CX509IPAddress::NewLC(gN->Data());
382 if (NameIsPresent(*name, *(iState.iExcludedIPAddressSubtrees)))
384 iResult.SetErrorAndLeaveL(ENameIsExcluded, iState.iPos);
386 if ((iState.iPermittedIPAddressSubtrees->Count() > 0) && (!(NameIsPresent(*name, *(iState.iPermittedIPAddressSubtrees)))))
388 iResult.SetErrorAndLeaveL(ENameNotPermitted, iState.iPos);
390 CleanupStack::PopAndDestroy();
395 //we've handled this now, so can remove it from the critical list
396 Remove(*(iState.iCriticalExts), KSubjectAltName);
397 CleanupStack::PopAndDestroy();//altNameExt
401 void TPKIXNameConstraint::UpdateNameConstraintsL(const CX509Certificate& aCert)
403 const CX509CertExtension* ext = aCert.Extension(KNameConstraints);
406 CX509NameConstraintsExt* nameCons = CX509NameConstraintsExt::NewLC(ext->Data());
407 const CArrayPtrFlat<CX509GeneralSubtree>& excSubtrees = nameCons->ExcludedSubtrees();
408 TInt count = excSubtrees.Count();
409 for (TInt i = 0; i < count; i++)
411 const CX509GeneralSubtree* subtree = excSubtrees.At(i);
412 const CX509GeneralName& gN = subtree->Name();
415 case EX509DirectoryName://X500DN
417 CX500DistinguishedName* name = CX500DistinguishedName::NewLC(gN.Data());
418 iState.iExcludedDNSubtrees->AppendL(name);
422 case EX509RFC822Name://IA5String
424 CX509RFC822Name* name = CX509RFC822Name::NewLC(gN.Data());
425 iState.iExcludedRFC822Subtrees->AppendL(name);
429 case EX509URI://IA5String
431 CX509IPBasedURI* name = CX509IPBasedURI::NewLC(gN.Data());
432 CX509DNSName* domain = CX509DNSName::NewLC(name->Host());
433 iState.iExcludedDNSNameSubtrees->AppendL(domain);
435 CleanupStack::PopAndDestroy();
438 case EX509DNSName://IA5String
440 CX509DNSName* name = CX509DNSName::NewLC(gN.Data());
441 iState.iExcludedDNSNameSubtrees->AppendL(name);
445 case EX509IPAddress://octet string
447 CX509IPSubnetMask* name = CX509IPSubnetMask::NewLC(gN.Data());
448 iState.iExcludedIPAddressSubtrees->AppendL(name);
454 User::Leave(KErrNotSupported);
459 const CArrayPtrFlat<CX509GeneralSubtree>& perSubtrees = nameCons->PermittedSubtrees();
460 count = perSubtrees.Count();
461 for (TInt j = 0; j < count; j++)
463 const CX509GeneralSubtree* subtree = perSubtrees.At(j);
464 const CX509GeneralName& gN = subtree->Name();
467 case EX509DirectoryName://X500DN
469 CX500DistinguishedName* name = CX500DistinguishedName::NewLC(gN.Data());
470 iState.iPermittedDNSubtrees->AppendL(name);
474 case EX509RFC822Name://IA5String
476 CX509RFC822Name* name = CX509RFC822Name::NewLC(gN.Data());
477 iState.iPermittedRFC822Subtrees->AppendL(name);
481 case EX509URI://IA5String
483 CX509IPBasedURI* name = CX509IPBasedURI::NewLC(gN.Data());
484 CX509DNSName* domain = CX509DNSName::NewLC(name->Host());
485 iState.iPermittedDNSNameSubtrees->AppendL(domain);
487 CleanupStack::PopAndDestroy();
490 case EX509DNSName://IA5String
492 CX509DNSName* name = CX509DNSName::NewLC(gN.Data());
493 iState.iPermittedDNSNameSubtrees->AppendL(name);
497 case EX509IPAddress://octet string
499 CX509IPSubnetMask* name = CX509IPSubnetMask::NewLC(gN.Data());
500 iState.iPermittedIPAddressSubtrees->AppendL(name);
506 User::Leave(KErrNotSupported);
511 CleanupStack::PopAndDestroy();//nameConsExt
512 //we've handled this now, so can remove it from the critical list
513 Remove(*(iState.iCriticalExts), KNameConstraints);
519 TBool TPKIXNameConstraint::NameIsPresentL( const CX500DistinguishedName& aSubject,
520 const CArrayPtrFlat<CX500DistinguishedName>& aSubtrees)
522 TInt count = aSubtrees.Count();
523 for (TInt i = 0; i < count; i++)
525 const CX500DistinguishedName* excluded = aSubtrees.At(i);
526 if (aSubject.IsWithinSubtreeL(*excluded))
534 TBool TPKIXNameConstraint::NameIsPresent( const CX509DomainName& aSubject,
535 const CArrayPtrFlat<CX509DomainName>& aSubtrees)
537 TInt count = aSubtrees.Count();
538 for (TInt i = 0; i < count; i++)
540 const CX509DomainName* excluded = aSubtrees.At(i);
541 if (aSubject.IsWithinSubtree(*excluded))
549 TBool TPKIXNameConstraint::NameIsPresent( const CX509IPAddress& aSubject,
550 const CArrayPtrFlat<CX509IPSubnetMask>& aSubtrees)
552 TInt count = aSubtrees.Count();
553 for (TInt i = 0; i < count; i++)
555 const CX509IPSubnetMask* excluded = aSubtrees.At(i);
556 if (aSubject.IsWithinSubtree(*excluded))
565 TPKIXBasicConstraint::TPKIXBasicConstraint( CPKIXValidationState& aState,
566 CPKIXValidationResultBase& aResult)
567 :TPKIXConstraint(aState, aResult)
571 void TPKIXBasicConstraint::CheckCertSubjectTypeL(const CX509Certificate& aCert)
573 TBool markedAsCA = EFalse;
574 TBool actsAsCA = iState.iPos > 0;
575 const CX509CertExtension* ext = aCert.Extension(KBasicConstraints);
578 CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC(ext->Data());
579 markedAsCA = basic->IsCA();
580 CleanupStack::PopAndDestroy();
582 if (actsAsCA && (!markedAsCA))
584 iResult.SetErrorAndLeaveL(ENotCACert, iState.iPos);
588 void TPKIXBasicConstraint::UpdatePathLengthConstraintsL(const CX509Certificate& aCert)
590 const CX509CertExtension* ext = aCert.Extension(KBasicConstraints);
593 CX509BasicConstraintsExt* basic = CX509BasicConstraintsExt::NewLC(ext->Data());
594 TInt pathLength = basic->MaxChainLength();
597 iResult.SetErrorAndLeaveL(ENegativePathLengthSpecified, iState.iPos);
599 if (iState.iPos > pathLength)
601 iState.iMaxPathLength = pathLength + 1;
603 Remove(*(iState.iCriticalExts), KBasicConstraints);
604 CleanupStack::PopAndDestroy();//basic
608 //key usage constraint
609 TPKIXKeyUsageConstraint::TPKIXKeyUsageConstraint( CPKIXValidationState& aState,
610 CPKIXValidationResultBase& aResult)
611 :TPKIXConstraint(aState, aResult)
615 void TPKIXKeyUsageConstraint::CheckKeyUsageL(const CX509Certificate& aCert)
617 //if key usage is critical and this is a CA cert, the keyCertSign bit must be set
618 const CX509CertExtension* ext = aCert.Extension(KKeyUsage);
621 CX509KeyUsageExt* keyUsage = CX509KeyUsageExt::NewLC(ext->Data());
622 if ( (iState.iPos > 0) && (!(keyUsage->IsSet(EX509KeyCertSign))))
624 iResult.SetErrorAndLeaveL(EBadKeyUsage, iState.iPos);
626 CleanupStack::PopAndDestroy();
627 //we've processed this critical ext, so remove it
628 Remove(*(iState.iCriticalExts), KKeyUsage);