cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
chk_chn.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Certificate Chain Checking Routines *
4 * Copyright Peter Gutmann 1996-2009 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "cert.h"
10 #else
11  #include "cert/cert.h"
12 #endif /* Compiler-specific includes */
13 
14 /* This module and chk_cert.c implement the following PKIX checks. For
15  simplicity we use the more compact form of RFC 2459 rather than the 18
16  page long one from RFC 3280.
17 
18  General:
19 
20  (a) Verify the basic certificate information:
21  (1) The certificate signature is valid.
22  (2a) The certificate has not expired.
23  (2b) If present, the private key usage period is satisfied.
24  (3) The certificate has not been revoked.
25  (4a) The subject and issuer name chains correctly.
26  (4b) If present, the subjectAltName and issuerAltName chains
27  correctly.
28 
29  NameConstraints:
30 
31  (b) Verify that the subject name or critical subjectAltName is consistent
32  with the constrained subtrees.
33 
34  (c) Verify that the subject name or critical subjectAltName is consistent
35  with the excluded subtrees.
36 
37  Policy Constraints:
38 
39  (d) Verify that policy information is consistent with the initial policy
40  set:
41  (1) If the require explicit policy state variable is less than or
42  equal to n, a policy identifier in the certificate must be in
43  the initial policy set.
44  (2) If the policy mapping state variable is less than or equal to n,
45  the policy identifier may not be mapped.
46  (3) RFC 3280 addition: If the inhibitAnyPolicy state variable is
47  less than or equal to n, the anyPolicy policy is no longer
48  considered a match (this also extends into (e) and (g) below).
49 
50  (e) Verify that policy information is consistent with the acceptable policy
51  set:
52  (1) If the policies extension is marked critical, the policies
53  extension must lie within the acceptable policy set.
54  (2) The acceptable policy set is assigned the resulting intersection
55  as its new value.
56 
57  (g) Verify that the intersection of the acceptable policy set and the
58  initial policy set is non-null (this is covered by chaining of e(1)).
59 
60  Other Constraints:
61 
62  (f) Step (f) is missing in the original, it should probably be: Verify
63  that the current path length is less than the path length constraint.
64  If a path length constraint is present in the certificate, update it
65  as for policy constraints in (l). RFC 3280 addition: If the
66  certificate is a PKIX path kludge certificate it doesn't count for
67  path length constraint purposes.
68 
69  (h) Recognize and process any other critical extension present in the
70  certificate.
71 
72  (i) Verify that the certificate is a CA certificate.
73 
74  Update of state:
75 
76  (j) If permittedSubtrees is present in the certificate, set the
77  constrained subtrees state variable to the intersection of its
78  previous value and the value indicated in the extension field.
79 
80  (k) If excludedSubtrees is present in the certificate, set the excluded
81  subtrees state variable to the union of its previous value and the
82  value indicated in the extension field.
83 
84  (l) If a policy constraints extension is included in the certificate,
85  modify the explicit policy and policy mapping state variables as
86  follows:
87 
88  For any of { requireExplicitPolicy, inhibitPolicyMapping,
89  inhibitAnyPolicy }, if the constraint value is present and has value
90  r, the state variable is set to the minimum of (a) its current value
91  and (b) the sum of r and n (the current certificate in the
92  sequence)
93 
94  (m) If a key usage extension is marked critical, ensure that the
95  keyCertSign bit is set */
96 
97 #ifdef USE_CERTIFICATES
98 
99 /****************************************************************************
100 * *
101 * Utility Functions *
102 * *
103 ****************************************************************************/
104 
105 /* Get certificate information for a certificate in the chain. The index
106  value can go to -1, indicating the leaf certificate itself rather than a
107  certificate in the chain */
108 
109 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
110 static int getCertInfo( const CERT_INFO *certInfoPtr,
111  INOUT_PTR CERT_INFO **certChainPtr,
112  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) const int certChainIndex )
113  {
114  CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
115 
116  assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
117  assert( isWritePtr( certChainPtr, sizeof( CERT_INFO * ) ) );
118 
119  REQUIRES( certChainIndex >= -1 && \
120  certChainIndex < certChainInfo->chainEnd && \
121  certChainIndex < MAX_CHAINLENGTH );
122 
123  /* Clear return value */
124  *certChainPtr = NULL;
125 
126  /* If it's an index into the certificate chain, return information for
127  the certificate at that position */
128  if( certChainIndex >= 0 && certChainIndex < certChainInfo->chainEnd )
129  {
130  return( krnlAcquireObject( certChainInfo->chain[ certChainIndex ],
132  ( void ** ) certChainPtr,
134  }
135 
136  /* The -1th certificate is the leaf itself */
137  if( certChainIndex == -1 )
138  {
139  *certChainPtr = ( CERT_INFO * ) certInfoPtr;
140  return( CRYPT_OK );
141  }
142 
143  /* We've reached the end of the chain */
144  *certChainPtr = NULL;
145  return( CRYPT_ERROR_NOTFOUND );
146  }
147 
148 /* When checking a particular certificate in a chain via a message sent to
149  the encompassing object we have to explicitly select the certificate that
150  we want to operate on, otherwise all messages will act on the currently-
151  selected certificate in the chain. To do this we temporarily select the
152  target certificate in the chain and then restore the selection state when
153  we're done */
154 
156 static int performAbsTrustOperation( INOUT CERT_INFO *certInfoPtr,
157  IN_ENUM( MESSAGE_TRUSTMGMT ) \
158  const MESSAGE_TRUSTMGMT_TYPE operation,
159  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
160  const int certChainIndex,
162  {
163  CRYPT_CERTIFICATE iLocalCert;
164  CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
165  SELECTION_STATE savedState;
166  int status;
167 
168  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
169  assert( iIssuerCert == NULL || \
170  isWritePtr( iIssuerCert, sizeof( CRYPT_CERTIFICATE ) ) );
171 
172  REQUIRES( certChainIndex >= -1 && \
173  certChainIndex < certChainInfo->chainEnd && \
174  certChainIndex < MAX_CHAINLENGTH );
175 
176  /* Clear return value */
177  if( iIssuerCert != NULL )
178  *iIssuerCert = CRYPT_ERROR;
179 
180  /* Perform the required operation at an absolute chain position */
181  saveSelectionState( savedState, certInfoPtr );
182  certChainInfo->chainPos = certChainIndex;
183  if( certChainIndex == -1 )
184  {
185  /* The -1th certificate is the leaf itself */
186  iLocalCert = certInfoPtr->objectHandle;
187  }
188  else
189  {
190  /* It's an index into the certificate chain, use the certificate at
191  that position */
192  iLocalCert = certChainInfo->chain[ certChainIndex ];
193  }
194  status = krnlSendMessage( certInfoPtr->ownerHandle,
195  IMESSAGE_USER_TRUSTMGMT, &iLocalCert,
196  operation );
197  restoreSelectionState( savedState, certInfoPtr );
198  if( cryptStatusError( status ) )
199  return( status );
200  if( iIssuerCert != NULL )
201  *iIssuerCert = iLocalCert;
202  return( CRYPT_OK );
203  }
204 
205 /* Find the trust anchor in a certificate chain. The definition of a
206  "trusted certificate" is somewhat ambiguous and can have at least two
207  different interpretations:
208 
209  1. Trust the identified certificate in the chain and only verify from
210  there on down.
211 
212  2. Trust the root of the chain that contains the identified certificate
213  (for the purposes of verifying that particular chain only) and verify
214  the whole chain.
215 
216  Situation 1 is useful where there's a requirement that things go up to an
217  external CA somewhere but no-one particularly cares about (or trusts) the
218  external CA. In this case the end user can choose to trust the path at
219  the point where it comes under their control (a local CA or directly
220  trusting the leaf certificates) without having to bother about the
221  external CA.
222 
223  Situation 2 is useful where there's a requirement to use the full PKI
224  model. This can be enabled by having the user mark the root CA as
225  trusted, although this means that all certificates issued by that CA also
226  have to be trusted, removing user control over certificate use. This is
227  required by orthodox PKI theology, followed by all manner of hacks and
228  kludges down the chain to limit what can actually be done with the
229  certificate(s).
230 
231  Est autem fides credere quod nondum vides; cuius fidei merces est videre
232  quod credis (St. Augustine) */
233 
234 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
235 static int findTrustAnchor( INOUT CERT_INFO *certInfoPtr,
236  OUT_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
237  int *trustAnchorIndexPtr,
238  OUT_HANDLE_OPT CRYPT_CERTIFICATE *trustAnchorCert )
239  {
240  CRYPT_CERTIFICATE iIssuerCert = DUMMY_INIT;
241  CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
242  int trustAnchorIndex, status;
243 
244  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
245  assert( isWritePtr( trustAnchorIndexPtr, sizeof( int ) ) );
246  assert( isWritePtr( trustAnchorCert, sizeof( CRYPT_CERTIFICATE ) ) );
247 
248  /* Clear return value */
249  *trustAnchorIndexPtr = CRYPT_ERROR;
250  *trustAnchorCert = CRYPT_ERROR;
251 
252  /* If the leaf certificate is implicitly trusted, exit. Since this is a
253  certificate chain we have to explicitly perform the operation at an
254  absolute position in the chain rather than the currently-selected
255  certificate, specifically the leaf at position -1 */
256  status = performAbsTrustOperation( certInfoPtr, MESSAGE_TRUSTMGMT_CHECK,
257  -1, NULL );
258  if( cryptStatusOK( status ) )
259  {
260  /* Indicate that the leaf is trusted and there's nothing further to
261  do */
262  return( OK_SPECIAL );
263  }
264 
265  /* Walk up the chain looking for the trusted certificate that issued the
266  current one. The evaluated trust anchor certificate position is one
267  past the current position since we're looking for the issuer of the
268  current certificate at position n, which will be located at position
269  n+1:
270 
271  trustAnchorIndex Cert queried trustAnchorCert
272  ---------------- ------------ ---------------
273  0 cert #-1 issuer( #-1 )
274  1 cert #0 issuer( #0 )
275  2 cert #1 issuer( #1 )
276 
277  This means that trustAnchorIndex may end up referencing a certificate
278  past the end of the chain if the trust anchor is present in the trust
279  database but not in the chain */
280  REQUIRES( certChainInfo->chainEnd >= 0 );
281  for( trustAnchorIndex = 0;
282  trustAnchorIndex <= certChainInfo->chainEnd && \
283  trustAnchorIndex < MAX_CHAINLENGTH;
284  trustAnchorIndex++ )
285  {
286  status = performAbsTrustOperation( certInfoPtr,
288  trustAnchorIndex - 1,
289  &iIssuerCert );
290  if( cryptStatusOK( status ) )
291  break;
292  }
293  ENSURES( trustAnchorIndex < MAX_CHAINLENGTH );
294  if( cryptStatusError( status ) || \
295  trustAnchorIndex > certChainInfo->chainEnd )
296  return( CRYPT_ERROR_NOTFOUND );
297  *trustAnchorIndexPtr = trustAnchorIndex;
298  *trustAnchorCert = iIssuerCert;
299 
300  /* If there are more certificates in the chain beyond the one that we
301  stopped at check to see whether the next certificate is the same as
302  the trust anchor. If it is then we use the copy of the certificate
303  in the chain rather than the external one from the trust database */
304  if( trustAnchorIndex < certChainInfo->chainEnd - 1 )
305  {
306  status = krnlSendMessage( certChainInfo->chain[ trustAnchorIndex ],
307  IMESSAGE_COMPARE, &iIssuerCert,
309  if( cryptStatusOK( status ) )
310  *trustAnchorCert = certChainInfo->chain[ trustAnchorIndex ];
311  }
312  return( CRYPT_OK );
313  }
314 
315 /* Set error information for the certificate that caused problems when
316  looking for a trust anchor */
317 
319 static int setTrustAnchorErrorInfo( INOUT CERT_INFO *certInfoPtr )
320  {
322  CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
324  const int lastCertIndex = certChainInfo->chainEnd - 1;
325  int value, status;
326 
327  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
328 
329  ENSURES( lastCertIndex >= 0 && lastCertIndex < certChainInfo->chainEnd );
330 
331  /* Select the certificate that caused the problem, which is the highest-
332  level certificate in the chain */
333  certChainInfo->chainPos = lastCertIndex;
334 
335  /* We couldn't find a trust anchor, either there's a missing link in the
336  chain (CRYPT_ERROR_STUART) and it was truncated before we got to a
337  trusted certificate or it goes to a root certificate but it isn't
338  trusted. Returning error information on this is a bit complex since
339  we've selected the certificate that caused the problem, which means
340  that any attempt to read error status information will read it from
341  this certificate rather than the encapsulating chain object. To get
342  around this we set the error information for the selected certificate
343  rather than the chain */
344  status = krnlSendMessage( certChainInfo->chain[ lastCertIndex ],
345  IMESSAGE_GETATTRIBUTE, &value,
347  if( cryptStatusOK( status ) && value > 0 )
348  {
349  /* We got a root certificate but it's not trusted */
350  attributeType = CRYPT_CERTINFO_TRUSTED_IMPLICIT;
351  }
352  else
353  {
354  /* There's a missing link in the chain and it stops at this
355  certificate */
356  attributeType = CRYPT_CERTINFO_CERTIFICATE;
357  }
358  status = getCertInfo( certInfoPtr, &subjectCertInfoPtr,
359  lastCertIndex );
360  if( cryptStatusOK( status ) )
361  {
362  setErrorInfo( subjectCertInfoPtr, attributeType,
364 
365  /* If we're not at the leaf certificate then we have to unlock the
366  certificate that getCertInfo() provided us */
367  if( certInfoPtr != subjectCertInfoPtr )
368  krnlReleaseObject( subjectCertInfoPtr->objectHandle );
369  }
370 
371  return( CRYPT_ERROR_INVALID );
372  }
373 
374 /****************************************************************************
375 * *
376 * Policy Management Functions *
377 * *
378 ****************************************************************************/
379 
380 #ifdef USE_CERTLEVEL_PKIX_FULL
381 
382 /* Check whether a policy is already present in the policy set */
383 
385 static BOOLEAN isPolicyPresent( const POLICY_DATA *policyData,
386  IN_RANGE( 0, MAX_POLICIES ) const int policyCount,
387  IN_BUFFER( policyValueLength ) const void *policyValue,
388  IN_LENGTH_OID const int policyValueLength )
389  {
390  int i;
391 
392  assert( isReadPtr( policyData, sizeof( POLICY_DATA ) ) );
393  assert( isReadPtr( policyValue, policyValueLength ) );
394 
395  REQUIRES_B( policyCount >= 0 && policyCount < MAX_POLICIES );
396  REQUIRES_B( policyValueLength > 0 && policyValueLength < MAX_POLICY_SIZE );
397 
398  /* Check whether the given policy is already present in the set of
399  acceptable policies */
400  for( i = 0; i < policyCount && i < FAILSAFE_ITERATIONS_MED; i++ )
401  {
402  const POLICY_DATA *policyDataPtr = &policyData[ i ];
403 
404  if( policyDataPtr->length == policyValueLength && \
405  !memcmp( policyDataPtr->data, policyValue, policyValueLength ) )
406  return( TRUE );
407  }
408  ENSURES_B( i < FAILSAFE_ITERATIONS_MED );
409 
410  return( FALSE );
411  }
412 
413 /* Add a policy to the policy set */
414 
416 static int addPolicy( INOUT POLICY_DATA *policyData,
417  IN_RANGE( 0, MAX_POLICIES ) const int policyCount,
418  const ATTRIBUTE_PTR *policyAttributePtr,
419  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
420  const int certChainIndex,
421  const BOOLEAN isMapped )
422  {
423  POLICY_DATA *policyDataPtr;
424  void *policyValuePtr;
425  int policyValueLength, status;
426 
427  assert( isWritePtr( policyData, sizeof( POLICY_DATA ) ) );
428  assert( isReadPtr( policyAttributePtr,
429  sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
430 
431  REQUIRES( policyCount >= 0 && policyCount < MAX_POLICIES );
432  REQUIRES( certChainIndex >= -1 && certChainIndex < MAX_CHAINLENGTH );
433 
434  /* Get the policy value */
435  status = getAttributeDataPtr( policyAttributePtr, &policyValuePtr,
436  &policyValueLength );
437  if( cryptStatusError( status ) )
438  return( status );
439 
440  /* Make sure that this policy isn't already present in the policy set.
441  Since policies are asserted all the way up and down a chain we're
442  going to find more copies in subsequent certificates so duplicates
443  aren't a problem */
444  if( isPolicyPresent( policyData, policyCount, policyValuePtr,
445  policyValueLength ) )
446  return( OK_SPECIAL );
447 
448  /* Copy the policy data to the next empty slot. The policy level is
449  counted from 0 (the EE certificate) to n (the root certificate) so we
450  have to adjust the chain-position indicator by one since it denotes
451  the EE, the containing certificate, with the virtual position -1 and
452  the remainder of the certificates in the chain with positions 0...n */
453  policyDataPtr = &policyData[ policyCount ];
454  memset( policyDataPtr, 0, sizeof( POLICY_DATA ) );
455  policyDataPtr->level = certChainIndex + 1;
456  policyDataPtr->isMapped = isMapped;
457  return( attributeCopyParams( policyDataPtr->data, MAX_POLICY_SIZE,
458  &policyDataPtr->length, policyValuePtr,
459  policyValueLength ) );
460  }
461 
462 /* Add explicit policies to the policy set */
463 
464 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
465 static int addExplicitPolicies( INOUT POLICY_INFO *policyInfo,
466  const ATTRIBUTE_PTR *attributes,
467  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
468  const int certChainIndex )
469  {
470  const ATTRIBUTE_PTR *attributeCursor;
471  int policyCount = policyInfo->noPolicies, iterationCount, status;
472 
473  assert( isWritePtr( policyInfo, sizeof( POLICY_INFO ) ) );
474  assert( isReadPtr( attributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
475 
476  REQUIRES( certChainIndex >= -1 && certChainIndex < MAX_CHAINLENGTH );
477 
478  /* Add all policies to the policy set */
479  for( attributeCursor = findAttributeField( attributes,
481  iterationCount = 0;
482  attributeCursor != NULL && \
483  iterationCount < FAILSAFE_ITERATIONS_LARGE;
484  attributeCursor = findNextFieldInstance( attributeCursor ),
485  iterationCount++ )
486  {
487  if( policyCount >= MAX_POLICIES )
488  return( CRYPT_ERROR_OVERFLOW );
489  status = addPolicy( policyInfo->policies, policyCount,
490  attributeCursor, certChainIndex, FALSE );
491  if( status == OK_SPECIAL )
492  {
493  /* This policy is already present, there's nothing further to
494  do */
495  continue;
496  }
497  if( cryptStatusError( status ) )
498  return( status );
499  policyCount++;
500  }
501  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
502  policyInfo->noPolicies = policyCount;
503 
504  return( CRYPT_OK );
505  }
506 
507 /* Add mapped policies to the policy set */
508 
509 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
510 static int addMappedPolicies( INOUT POLICY_INFO *policyInfo,
511  const ATTRIBUTE_PTR *attributes,
512  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
513  const int certChainIndex )
514  {
515  const ATTRIBUTE_PTR *sourcePolicyAttributeCursor = \
516  findAttributeField( attributes,
519  const ATTRIBUTE_PTR *destPolicyAttributeCursor = \
520  findAttributeField( attributes,
523  int policyCount = policyInfo->noPolicies, iterationCount;
524  int status = CRYPT_OK;
525 
526  assert( isWritePtr( policyInfo, sizeof( POLICY_INFO ) ) );
527  assert( isReadPtr( attributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
528 
529  REQUIRES( certChainIndex >= -1 && certChainIndex < MAX_CHAINLENGTH );
530 
531  /* If there are no mapped policies, we're done */
532  if( sourcePolicyAttributeCursor == NULL )
533  return( CRYPT_OK );
534 
535  /* Add all mapped policies to the policy set */
536  for( iterationCount = 0;
537  sourcePolicyAttributeCursor != NULL && \
538  iterationCount < FAILSAFE_ITERATIONS_LARGE;
539  sourcePolicyAttributeCursor = \
540  findNextFieldInstance( sourcePolicyAttributeCursor ), \
541  destPolicyAttributeCursor = \
542  findNextFieldInstance( destPolicyAttributeCursor ), \
543  iterationCount++ )
544  {
545  void *policyValuePtr;
546  int policyValueLength;
547 
548  REQUIRES( sourcePolicyAttributeCursor != NULL && \
549  destPolicyAttributeCursor != NULL );
550 
551  /* Make sure that we're not trying to map from or to the special-case
552  anyPolicy policy */
553  if( isAnyPolicy( sourcePolicyAttributeCursor ) || \
554  isAnyPolicy( destPolicyAttributeCursor ) )
555  return( CRYPT_ERROR_INVALID );
556 
557  /* Get the source policy and check whether it's present in the
558  policy set */
559  status = getAttributeDataPtr( sourcePolicyAttributeCursor, &policyValuePtr,
560  &policyValueLength );
561  if( cryptStatusError( status ) )
562  continue;
563  if( !isPolicyPresent( policyInfo->policies, policyCount,
564  policyValuePtr, policyValueLength ) )
565  continue;
566 
567  /* The source policy is present, add the corresponding destination
568  policy to the policy set */
569  if( policyCount >= MAX_POLICIES )
570  return( CRYPT_ERROR_OVERFLOW );
571  status = addPolicy( policyInfo->policies, policyCount,
572  destPolicyAttributeCursor, certChainIndex, TRUE );
573  if( status == OK_SPECIAL )
574  {
575  /* This destination policy is already present, there's nothing
576  further to do. This can happen if there's two different
577  source policies mapped to a single destination policy */
578  continue;
579  }
580  if( cryptStatusError( status ) )
581  return( status );
582  policyCount++;
583  }
584  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
585  policyInfo->noPolicies = policyCount;
586 
587  return( CRYPT_OK );
588  }
589 
590 /* Create a certificate policy set from a certificate chain */
591 
592 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
593 static int createPolicySet( OUT POLICY_INFO *policyInfo,
594  IN_OPT const ATTRIBUTE_PTR *trustAnchorAttributes,
595  INOUT CERT_INFO *certInfoPtr,
596  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
597  const int startCertIndex )
598  {
599  BOOLEAN addImplicitPolicy = FALSE;
600  int certIndex = startCertIndex, iterationCount, status;
601 
602  assert( isWritePtr( policyInfo, sizeof( POLICY_INFO ) ) );
603  assert( ( trustAnchorAttributes == NULL ) || \
604  isReadPtr( trustAnchorAttributes,
605  sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
606  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
607 
608  REQUIRES( startCertIndex >= -1 && startCertIndex < MAX_CHAINLENGTH );
609 
610  /* Clear return value */
611  memset( policyInfo, 0, sizeof( POLICY_INFO ) );
612 
613  /* Add trust anchor explicit and mapped policies if required */
614  if( trustAnchorAttributes != NULL && \
615  checkAttributeFieldPresent( trustAnchorAttributes,
617  {
618  status = addExplicitPolicies( policyInfo, trustAnchorAttributes,
619  certIndex );
620  if( cryptStatusError( status ) )
621  return( status );
622  status = addMappedPolicies( policyInfo, trustAnchorAttributes,
623  certIndex );
624  if( cryptStatusError( status ) )
625  return( status );
626  }
627 
628  /* We've checked the trust anchor, move on to the next certificate */
629  certIndex--;
630 
631  /* If there are no policies in the trust anchor, pick up the policies in
632  the first certificate we get to that has any. This is a bit of an
633  ugly hack that's required to deal with things like self-signed CA
634  roots in X.509v1 format where the CA policy doesn't appear until the
635  second certficiate in the chain */
636  if( policyInfo->noPolicies <= 0 )
637  addImplicitPolicy = TRUE;
638 
639  /* Add mapped policies from the remainder of the certificate chain.
640  Note that we don't go all the way down to the EE certificate
641  (certIndex == -1) because any mapping at the end of the chain won't
642  be used any more */
643  for( iterationCount = 0;
644  certIndex >= 0 && iterationCount < MAX_CHAINLENGTH;
645  certIndex--, iterationCount++ )
646  {
648 
649  /* Get information for the current certificate in the chain */
650  status = getCertInfo( certInfoPtr, &subjectCertInfoPtr, certIndex );
651  if( cryptStatusError( status ) )
652  break;
653 
654  if( addImplicitPolicy && \
655  checkAttributeFieldPresent( subjectCertInfoPtr->attributes,
657  {
658  status = addExplicitPolicies( policyInfo,
659  subjectCertInfoPtr->attributes,
660  certIndex );
661  if( cryptStatusError( status ) )
662  return( status );
663  if( policyInfo->noPolicies > 0 )
664  addImplicitPolicy = FALSE;
665  }
666 
667  /* Add any mapped policies present in the current certificate */
668  status = addMappedPolicies( policyInfo,
669  subjectCertInfoPtr->attributes,
670  certIndex );
671  if( cryptStatusError( status ) )
672  {
673  krnlReleaseObject( subjectCertInfoPtr->objectHandle );
674  return( status );
675  }
676 
677  /* Release the certificate again. We don't have to check for it
678  being the chain certificate as we normally would because we never
679  process the certificate at the end of the chain */
680  krnlReleaseObject( subjectCertInfoPtr->objectHandle );
681  }
682  ENSURES( iterationCount < MAX_CHAINLENGTH );
683 
684  return( CRYPT_OK );
685  }
686 #endif /* USE_CERTLEVEL_PKIX_FULL */
687 
688 /****************************************************************************
689 * *
690 * Verify Constraints on a Certificate Chain *
691 * *
692 ****************************************************************************/
693 
694 #ifdef USE_CERTLEVEL_PKIX_FULL
695 
696 /* Check constraints along a certificate chain in certInfoPtr from
697  startCertIndex on down, checked if complianceLevel >=
698  CRYPT_COMPLIANCELEVEL_PKIX_FULL. There are three types of constraints
699  that can cover multiple certificates: path constraints, name constraints,
700  and policy constraints.
701 
702  Path constraints are the easiest to check, just make sure that the number
703  of certificates from the issuer to the leaf is less than the constraint
704  length with special handling for PKIX path-kludge certificates.
705 
706  Name constraints are a bit more difficult, the abstract description
707  requires building and maintaining a (potentially enormous) name
708  constraint tree which is applied to each certificate in turn as it's
709  processed. Since name constraints are practically nonexistant and chains
710  are short it's more efficient to walk down the certificate chain when a
711  constraint is encountered and check each certificate in turn, which
712  avoids having to maintain massive amounts of state information and is no
713  less efficient than a single monolithic state comparison. Again there's
714  special handling for PKIX path-kludge certificates, see chk_cert.c for
715  details.
716 
717  Policy constraints are the hardest of all to deal with because, with the
718  complex mishmash of policies, policy constraints, qualifiers, and mappings
719  it turns out that no-one actually knows how to apply them and even if
720  people could agree, with the de facto use of the policy extension as the
721  kitchenSink extension it's uncertain how to apply the constraints to
722  typical kitchenSink constructs. The ambiguity of name constraints when
723  applied to altNames is bad enough, with a 50/50 split in PKIX about
724  whether it should be an AND or OR operation and whether a DN constraint
725  applies to a subjectName or altName or both. In the absence of any
726  consensus on the issue the latter was fixed in the final version of RFC
727  2459 by somewhat arbitrarily requiring an AND rather than an OR although
728  how many implementations follow exactly this version rather than the
729  dozen earlier drafts or any other profile or interpretation is unknown.
730  With policy constraints it's even worse and no-one seems to be able to
731  agree on what to do with them, or more specifically the people who write
732  the standards don't seem to be aware that there are ambiguities and
733  inconsistencies in the handling of these extensions. Anyone who doesn't
734  believe this is invited to try implementing the path-processing algorithm
735  in RFC 3280 as described by the pseudocode there.
736 
737  For example the various policy constraints in effect act as conditional
738  modifiers on the critical flag of the policies extension and/or the
739  various blah-policy-set settings in the path-processing algorithm so
740  that under various conditions imposed by the constraints the extension
741  goes from being non-critical to being (effectively) critical. In addition
742  the constraint extensions can have their own critical flags which means
743  that we can end up having to chain back through multiple layers of
744  interacting constraint extensions spread across multiple certificates to
745  see what the current interpretation of a particular extension is.
746  Finally, the presence of PKIX path-kludge certificates can turn
747  enforcement of constraints on and off at various stages of path
748  processing with extra special cases containing exceptions to the
749  exceptions. In addition the path-kludge exceptions apply to some
750  constraint types but not to others although the main body of the spec
751  and the pseudocode path-processing algorithm disagree on which ones and
752  when they're in effect (this implementation assumes that the body of the
753  spec is authoritative and the pseudocode represents a buggy attempt to
754  implement the spec rather than the other way round). Since the
755  virtual-criticality can switch itself on and off across certificates
756  depending on where in the path they are, the handling of policy
757  constraints is reduced to complete chaos if we try and interpret them as
758  required by the spec - an independent evaluation of the spec that tried to
759  implement the logic using decision tables ended up with expressions of
760  more than a dozen variables (and that was at a pre-3280 stage before the
761  state space explosion that occurred after that point) which indicates
762  that the issue is more or less incomprehensible. However since it's only
763  applied at the CRYPT_COMPLIANCELEVEL_PKIX_FULL compliance level it's
764  reasonably safe since users should be expecting all sorts of wierd
765  behaviour at this level anyway.
766 
767  The requireExplicitPolicy constraint is particularly bizarre, it
768  specifies the number of additional certificates that can be present in
769  the path before the entire path needs to have policies present. In other
770  words unlike all other length-based constraints (pathLenConstraint,
771  inhibitPolicyMapping, inhibitAnyPolicy) this works both forwards and
772  *backwards* up and down the path, making it the PKI equivalent of a COME
773  FROM in that at some random point down the path a constraint placed who
774  knows where can suddenly retroactively render the previously-valid path
775  invalid. No-one seems to know why it runs backwards or what the purpose
776  of the retroactive triggering after n certificates is, for now we only check
777  forwards down the path in the manner of all the other length-based
778  constraints.
779 
780  Massa make big magic, gunga din */
781 
782 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
783 static int checkConstraints( INOUT CERT_INFO *certInfoPtr,
784  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
785  const int startCertIndex,
786  const ATTRIBUTE_PTR *issuerAttributes,
787  OUT_RANGE( -1, MAX_CHAINLENGTH - 1 ) \
788  int *errorCertIndex,
789  const POLICY_INFO *policyInfo,
790  const BOOLEAN explicitPolicy )
791  {
792  const ATTRIBUTE_PTR *nameConstraintPtr = NULL, *policyConstraintPtr = NULL;
793  const ATTRIBUTE_PTR *inhibitPolicyPtr = NULL, *attributePtr;
794  BOOLEAN hasExcludedSubtrees = FALSE, hasPermittedSubtrees = FALSE;
795  BOOLEAN hasPolicy = FALSE, hasPathLength = FALSE;
796  BOOLEAN hasExplicitPolicy = FALSE, hasInhibitPolicyMap = FALSE;
797  BOOLEAN hasInhibitAnyPolicy = FALSE;
798  int requireExplicitPolicyLevel, inhibitPolicyMapLevel;
799  int inhibitAnyPolicyLevel;
800  int pathLength = DUMMY_INIT, certIndex = startCertIndex;
801  int value, iterationCount, status = CRYPT_OK;
802 
803  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
804  assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
805  assert( isWritePtr( errorCertIndex, sizeof( int ) ) );
806  assert( isReadPtr( policyInfo, sizeof( POLICY_INFO ) ) );
807 
808  REQUIRES( startCertIndex >= -1 && startCertIndex < MAX_CHAINLENGTH );
809 
810  /* Clear return value */
811  *errorCertIndex = CRYPT_ERROR;
812 
813  /* Check for path constraints */
814  status = getAttributeFieldValue( issuerAttributes,
816  CRYPT_ATTRIBUTE_NONE, &value );
817  if( cryptStatusOK( status ) )
818  {
819  pathLength = value;
820  hasPathLength = TRUE;
821  }
822 
823  /* Check for policy constraints */
824  if( explicitPolicy && \
825  checkAttributePresent( issuerAttributes,
827  {
828  /* Policy chaining purely from the presence of a policy extension
829  is only enforced if the explicit-policy option is set */
830  hasPolicy = TRUE;
831  }
832  attributePtr = findAttribute( issuerAttributes,
834  if( attributePtr != NULL )
835  policyConstraintPtr = attributePtr;
836  attributePtr = findAttribute( issuerAttributes,
838  if( attributePtr != NULL )
839  inhibitPolicyPtr = attributePtr;
840 
841  /* Check for name constraints */
842  attributePtr = findAttribute( issuerAttributes,
844  if( attributePtr != NULL )
845  {
846  nameConstraintPtr = attributePtr;
847  hasExcludedSubtrees = \
848  checkAttributeFieldPresent( nameConstraintPtr,
850  hasPermittedSubtrees = \
851  checkAttributeFieldPresent( nameConstraintPtr,
853  }
854 
855  /* If there aren't any critical policies or constraints present (the
856  most common case), we're done */
857  if( !hasPolicy && !hasPathLength && \
858  policyConstraintPtr == NULL && inhibitPolicyPtr == NULL && \
859  nameConstraintPtr == NULL )
860  return( CRYPT_OK );
861 
862  /* Check whether there are requireExplicitPolicy, inhibitPolicyMapping, or
863  inhibitAnyPolicy attributes, which act as conditional modifiers on the
864  criticality and contents of the policies extension */
865  requireExplicitPolicyLevel = inhibitPolicyMapLevel = inhibitAnyPolicyLevel = 0;
866  status = getAttributeFieldValue( policyConstraintPtr,
868  CRYPT_ATTRIBUTE_NONE, &value );
869  if( cryptStatusOK( status ) )
870  {
871  requireExplicitPolicyLevel = value;
872  hasExplicitPolicy = TRUE;
873  }
874  status = getAttributeFieldValue( policyConstraintPtr,
876  CRYPT_ATTRIBUTE_NONE, &value );
877  if( cryptStatusOK( status ) )
878  {
879  inhibitPolicyMapLevel = value;
880  hasInhibitPolicyMap = TRUE;
881  }
882  if( inhibitPolicyPtr != NULL )
883  {
884  status = getAttributeDataValue( inhibitPolicyPtr,
885  &inhibitAnyPolicyLevel );
886  if( cryptStatusError( status ) )
887  return( status );
888  hasInhibitAnyPolicy = TRUE;
889  }
890  status = CRYPT_OK;
891 
892  /* Walk down the chain checking each certificate against the issuer */
893  for( certIndex = startCertIndex, iterationCount = 0;
894  cryptStatusOK( status ) && certIndex >= -1 && \
895  iterationCount < MAX_CHAINLENGTH;
896  certIndex--, iterationCount++ )
897  {
899  POLICY_TYPE policyType;
900  int policyLevel;
901 
902  /* Get information for the current certificate in the chain */
903  status = getCertInfo( certInfoPtr, &subjectCertInfoPtr, certIndex );
904  if( cryptStatusError( status ) )
905  break;
906 
907  /* Check for the presence of further policy constraints. The path
908  length value can only ever be decremented once set so if we find
909  a further value for the length constraint we set the overall
910  value to the smaller of the two */
911  status = getAttributeFieldValue( subjectCertInfoPtr->attributes,
913  CRYPT_ATTRIBUTE_NONE, &policyLevel );
914  if( cryptStatusOK( status ) )
915  {
916  if( !hasExplicitPolicy || policyLevel < requireExplicitPolicyLevel )
917  requireExplicitPolicyLevel = policyLevel;
918  hasExplicitPolicy = TRUE;
919  }
920  status = getAttributeFieldValue( subjectCertInfoPtr->attributes,
922  CRYPT_ATTRIBUTE_NONE, &policyLevel );
923  if( cryptStatusOK( status ) )
924  {
925  if( !hasInhibitPolicyMap || policyLevel < inhibitPolicyMapLevel )
926  inhibitPolicyMapLevel = policyLevel;
927  hasInhibitPolicyMap = TRUE;
928  }
929  status = getAttributeFieldValue( subjectCertInfoPtr->attributes,
931  CRYPT_ATTRIBUTE_NONE, &policyLevel );
932  if( cryptStatusOK( status ) )
933  {
934  if( !hasInhibitAnyPolicy || policyLevel < inhibitAnyPolicyLevel )
935  inhibitAnyPolicyLevel = policyLevel;
936  hasInhibitAnyPolicy = TRUE;
937  }
938  status = CRYPT_OK;
939 
940  /* If any of the policy constraints have triggered then the policy
941  extension is now treated as critical even if it wasn't before */
942  if( ( hasExplicitPolicy && requireExplicitPolicyLevel <= 0 ) || \
943  ( hasInhibitAnyPolicy && inhibitAnyPolicyLevel <= 0 ) )
944  hasPolicy = TRUE;
945 
946  /* Determine the necessary policy check type based on the various
947  policy constraints */
948  policyType = POLICY_NONE;
949  if( hasPolicy )
950  {
951  const BOOLEAN inhibitAnyPolicy = \
952  ( hasInhibitAnyPolicy && inhibitAnyPolicyLevel <= 0 ) ? \
953  TRUE : FALSE;
954 
955  if( hasExplicitPolicy )
956  {
957  if( requireExplicitPolicyLevel > 0 )
958  policyType = inhibitAnyPolicy ? \
959  POLICY_NONE_SPECIFIC : POLICY_NONE;
960  else
961  if( requireExplicitPolicyLevel == 0 )
962  policyType = inhibitAnyPolicy ? \
963  POLICY_SUBJECT_SPECIFIC : POLICY_SUBJECT;
964  else
965  if( requireExplicitPolicyLevel < 0 )
966  policyType = inhibitAnyPolicy ? \
967  POLICY_BOTH_SPECIFIC : POLICY_BOTH;
968  }
969  else
970  policyType = inhibitAnyPolicy ? \
971  POLICY_NONE_SPECIFIC : POLICY_NONE;
972  }
973 
974  /* Check that the current certificate in the chain obeys the
975  constraints set by the overall issuer, possibly modified by other
976  certificates in the chain */
977  if( hasExcludedSubtrees )
978  {
979  status = checkNameConstraints( subjectCertInfoPtr,
980  nameConstraintPtr, TRUE,
981  &subjectCertInfoPtr->errorLocus,
982  &subjectCertInfoPtr->errorType );
983  }
984  if( cryptStatusOK( status ) && hasPermittedSubtrees )
985  {
986  status = checkNameConstraints( subjectCertInfoPtr,
987  nameConstraintPtr, FALSE,
988  &subjectCertInfoPtr->errorLocus,
989  &subjectCertInfoPtr->errorType );
990  }
991  if( cryptStatusOK( status ) && hasPolicy )
992  {
993  /* When we specify the certificate position we have to add one
994  to it because the policy level is counted from 0 (the EE
995  certificate) to n (the root certificate) while the chain-
996  position indicator statrs from the virtual position -1 for
997  the EE certificate that contains the chain */
998  status = checkPolicyConstraints( subjectCertInfoPtr,
999  issuerAttributes, policyType,
1000  policyInfo, certIndex + 1,
1001  ( hasInhibitPolicyMap && \
1002  inhibitPolicyMapLevel <= 0 ) ? \
1003  FALSE : TRUE,
1004  &subjectCertInfoPtr->errorLocus,
1005  &subjectCertInfoPtr->errorType );
1006  }
1007  if( cryptStatusOK( status ) && hasPathLength )
1008  {
1009  status = checkPathConstraints( subjectCertInfoPtr, pathLength,
1010  &subjectCertInfoPtr->errorLocus,
1011  &subjectCertInfoPtr->errorType );
1012  }
1013  if( cryptStatusError( status ) )
1014  {
1015  /* Remember which certificate caused the problem */
1016  *errorCertIndex = certIndex;
1017  }
1018 
1019  /* If there are length constraints, decrement them for each
1020  certificate. At this point we run into another piece of PKIX
1021  weirdness: If there's a path-kludge certificate present it's not
1022  counted for path-length constraint purposes but the exception
1023  only holds for path-length constraint purposes and not for
1024  require/inhibit policy constraint purposes. This is an error in
1025  the spec, sections 4.2.1.12 (policy constraints) and 4.2.1.15
1026  (path constraints) don't permit path-kludge certificate
1027  exceptions while section 6.1.4(h) does. On the other hand given
1028  the confusion in the pseudocode and the fact that it diverges
1029  from the body of the spec in other places as well we treat it as
1030  an error in the (non-authoritative) pseudocode rather than the
1031  (authoritative) spec.
1032 
1033  Unfortunately there's no easy way to tell just from looking at a
1034  certificate whether it's one of these kludge certificates or not
1035  because it looks identical to a CA root certificate (even the
1036  path-building code has to handle this speculatively, falling back
1037  to alternatives if the initial attempt to construct a path fails).
1038 
1039  However, for chain-internal kludge certificates the
1040  chain-assembly code can determine whether it's a path-kludge by
1041  the presence of further certificates higher up in the chain
1042  (although it can't tell whether the chain ends in a path-kludge
1043  or a true CA root certificate because they appear identical). In
1044  the case where the chain-assembly code has been able to identify
1045  the certificate as a path-kludge we can skip it for path length
1046  constraint purposes */
1047  if( hasPathLength && \
1048  ( !( subjectCertInfoPtr->flags & CERT_FLAG_PATHKLUDGE ) ) )
1049  pathLength--;
1050  if( hasExplicitPolicy )
1051  requireExplicitPolicyLevel--;
1052  if( hasInhibitPolicyMap )
1053  inhibitPolicyMapLevel--;
1054  if( hasInhibitAnyPolicy )
1055  inhibitAnyPolicyLevel--;
1056 
1057  /* Release the certificate again unless it's the chain certificate
1058  itself, which is returned by getCertInfo() as the last
1059  certificate in the chain */
1060  if( certInfoPtr != subjectCertInfoPtr )
1061  krnlReleaseObject( subjectCertInfoPtr->objectHandle );
1062  }
1063  ENSURES( iterationCount < MAX_CHAINLENGTH );
1064 
1065  return( status );
1066  }
1067 #endif /* USE_CERTLEVEL_PKIX_FULL */
1068 
1069 /****************************************************************************
1070 * *
1071 * Verify a Certificate Chain *
1072 * *
1073 ****************************************************************************/
1074 
1075 /* Walk down a chain checking each certificate */
1076 
1077 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1078 int checkCertChain( INOUT CERT_INFO *certInfoPtr )
1079  {
1080  CRYPT_CERTIFICATE iIssuerCert;
1081  CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
1083 #ifdef USE_CERTLEVEL_PKIX_FULL
1084  POLICY_INFO policyInfo;
1085  BOOLEAN explicitPolicy = TRUE;
1086 #endif /* USE_CERTLEVEL_PKIX_FULL */
1087  int certIndex, complianceLevel, iterationCount, status;
1088 
1089  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
1090 
1091  /* Determine how much checking we need to perform */
1092  status = krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,
1093  &complianceLevel,
1095  if( cryptStatusError( status ) )
1096  return( status );
1097 #ifdef USE_CERTLEVEL_PKIX_FULL
1098  if( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )
1099  {
1100  int value;
1101 
1102  status = krnlSendMessage( certInfoPtr->ownerHandle,
1103  IMESSAGE_GETATTRIBUTE, &value,
1105  if( cryptStatusOK( status ) && !value )
1106  explicitPolicy = FALSE;
1107  }
1108 #endif /* USE_CERTLEVEL_PKIX_FULL */
1109 
1110  /* Try and find a trust anchor for the chain */
1111  status = findTrustAnchor( certInfoPtr, &certIndex, &iIssuerCert );
1112  if( status == OK_SPECIAL )
1113  {
1114  /* The leaf is implicitly trusted, there's nothing more to do */
1115  return( CRYPT_OK );
1116  }
1117  if( cryptStatusError( status ) )
1118  return( setTrustAnchorErrorInfo( certInfoPtr ) );
1119 
1120  status = krnlAcquireObject( iIssuerCert, OBJECT_TYPE_CERTIFICATE,
1121  ( void ** ) &issuerCertInfoPtr,
1123  if( cryptStatusError( status ) )
1124  return( status );
1125 
1126  /* Add policies (both native and mapped) from the trust anchor to the
1127  policy set */
1128 #ifdef USE_CERTLEVEL_PKIX_FULL
1129  status = createPolicySet( &policyInfo, issuerCertInfoPtr->attributes,
1130  certInfoPtr, certIndex );
1131  if( cryptStatusError( status ) )
1132  {
1133  krnlReleaseObject( issuerCertInfoPtr->objectHandle );
1134  return( status );
1135  }
1136 #endif /* USE_CERTLEVEL_PKIX_FULL */
1137 
1138  /* Check the trust anchor. Since this is the start of the chain there
1139  aren't any constraints placed on it by higher-level certificates so
1140  all that we need to check at this point is the certificate itself and
1141  its signature if it's self-signed */
1142  if( certIndex >= certChainInfo->chainEnd )
1143  {
1144  CRYPT_ATTRIBUTE_TYPE dummyLocus;
1145  CRYPT_ERRTYPE_TYPE dummyType;
1146 
1147  /* The issuer certificate information is coming from the certificate
1148  trust database, don't modify its state when we check it */
1149  status = checkCertDetails( issuerCertInfoPtr, issuerCertInfoPtr,
1150  ( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \
1151  issuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,
1152  NULL, TRUE, TRUE, &dummyLocus, &dummyType );
1153 
1154  }
1155  else
1156  {
1157  /* The issuer certificate is contained in the chain, update its state
1158  when we check it */
1159  status = checkCertDetails( issuerCertInfoPtr, issuerCertInfoPtr,
1160  ( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \
1161  issuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,
1162  NULL, TRUE, TRUE, &issuerCertInfoPtr->errorLocus,
1163  &issuerCertInfoPtr->errorType );
1164  }
1165  if( cryptStatusError( status ) )
1166  {
1167  krnlReleaseObject( issuerCertInfoPtr->objectHandle );
1168  if( certIndex < certChainInfo->chainEnd )
1169  {
1170  /* Remember which certificate caused the problem */
1171  certChainInfo->chainPos = certIndex;
1172  }
1173  return( status );
1174  }
1175 
1176  /* We've checked the trust anchor, move on to the next certificate */
1177  certIndex--;
1178 
1179  /* Walk down the chain from the trusted certificate checking each link
1180  in turn */
1181  for( iterationCount = 0;
1182  cryptStatusOK( status ) && certIndex >= -1 && \
1183  ( status = getCertInfo( certInfoPtr, &subjectCertInfoPtr,
1184  certIndex ) ) == CRYPT_OK && \
1185  iterationCount < MAX_CHAINLENGTH;
1186  certIndex--, iterationCount++ )
1187  {
1188  /* Check the certificate details and signature */
1189  status = checkCertDetails( subjectCertInfoPtr, issuerCertInfoPtr,
1190  ( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \
1191  issuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,
1192  NULL, FALSE, TRUE, &subjectCertInfoPtr->errorLocus,
1193  &subjectCertInfoPtr->errorType );
1194  if( cryptStatusError( status ) )
1195  {
1196  if( cryptArgError( status ) )
1197  {
1198  /* If there's a problem with the issuer's public key we'll
1199  get a parameter error, the most appropriate standard
1200  error code that we can translate this to is a standard
1201  signature error */
1202  status = CRYPT_ERROR_SIGNATURE;
1203  }
1204  break;
1205  }
1206 
1207 #ifdef USE_CERTLEVEL_PKIX_FULL
1208  /* Check any constraints that the issuer certificate may place on
1209  the rest of the chain */
1210  if( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )
1211  {
1212  int errorCertIndex = DUMMY_INIT; /* Needed for gcc */
1213 
1214  status = checkConstraints( certInfoPtr, certIndex,
1215  issuerCertInfoPtr->attributes,
1216  &errorCertIndex, &policyInfo,
1217  explicitPolicy );
1218  if( cryptStatusError( status ) )
1219  {
1220  certIndex = errorCertIndex;
1221  break;
1222  }
1223  }
1224 #endif /* USE_CERTLEVEL_PKIX_FULL */
1225 
1226  /* Move on to the next certificate */
1227  krnlReleaseObject( issuerCertInfoPtr->objectHandle );
1228  issuerCertInfoPtr = subjectCertInfoPtr;
1229  }
1230  ENSURES( iterationCount < MAX_CHAINLENGTH );
1231 
1232  /* If we stopped before we processed all of the certificates in the
1233  chain, select the one that caused the problem. We also have to
1234  unlock the last certificate that we got to if it wasn't the leaf,
1235  which corresponds to the chain itself */
1236  if( cryptStatusError( status ) )
1237  {
1238  certChainInfo->chainPos = certIndex ;
1239  if( issuerCertInfoPtr != certInfoPtr )
1240  krnlReleaseObject( issuerCertInfoPtr->objectHandle );
1241  }
1242 
1243  return( status );
1244  }
1245 #endif /* USE_CERTIFICATES */