cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
chk_cert.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Certificate Checking Routines *
4 * Copyright Peter Gutmann 1997-2010 *
5 * *
6 ****************************************************************************/
7 
8 #include <ctype.h>
9 #if defined( INC_ALL )
10  #include "cert.h"
11  #include "asn1.h"
12  #include "asn1_ext.h"
13 #else
14  #include "cert/cert.h"
15  #include "enc_dec/asn1.h"
16  #include "enc_dec/asn1_ext.h"
17 #endif /* Compiler-specific includes */
18 
19 #ifdef USE_CERTIFICATES
20 
21 /****************************************************************************
22 * *
23 * Utility Routines *
24 * *
25 ****************************************************************************/
26 
27 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
28 
29 /* Check whether disallowed CA-only attributes are present in a (non-CA)
30  attribute list. We report the error as a constraint derived from the CA
31  flag rather than the attribute itself since it's the absence of the flag
32  that renders the presence of the attribute invalid */
33 
34 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
35 static BOOLEAN invalidAttributesPresent( const ATTRIBUTE_PTR *attributePtr,
36  const BOOLEAN isIssuer,
37  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
38  CRYPT_ATTRIBUTE_TYPE *errorLocus,
39  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
40  CRYPT_ERRTYPE_TYPE *errorType )
41  {
42  assert( isReadPtr( attributePtr, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
43  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
44  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
45 
46  /* Check for entire disallowed attributes */
47 #ifdef USE_CERTLEVEL_PKIX_FULL
48  if( checkAttributePresent( attributePtr, \
50  checkAttributePresent( attributePtr, \
52  checkAttributePresent( attributePtr, \
54  checkAttributePresent( attributePtr, \
56  {
57  setErrorValues( CRYPT_CERTINFO_CA, isIssuer ? \
60  return( TRUE );
61  }
62 #endif /* USE_CERTLEVEL_PKIX_FULL */
63 
64  /* Check for a particular field of an attribute that's invalid rather
65  than the entire attribute (the specific exclusion of path-length
66  constraints in basicConstraints was introduced in RFC 3280) */
67  if( checkAttributeFieldPresent( attributePtr, \
69  {
70  setErrorValues( CRYPT_CERTINFO_CA, isIssuer ? \
73  return( TRUE );
74  }
75 
76  return( FALSE );
77  }
78 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
79 
80 #ifdef USE_CERTLEVEL_PKIX_FULL
81 
82 /* Check whether a certificate is a PKIX path-kludge certificate, which
83  allows extra certificates to be kludged into the path without violating
84  any constraints */
85 
87 static BOOLEAN isPathKludge( const CERT_INFO *certInfoPtr )
88  {
89  int value, status;
90 
91  assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
92 
93  /* Perform a quick-reject check for certificates that haven't been
94  identified by the certificate chain processing code as path-kludge
95  certificates */
96  if( !( certInfoPtr->flags & CERT_FLAG_PATHKLUDGE ) )
97  return( FALSE );
98 
99  /* Only CA path-kludge certificates are exempt from constraint
100  enforcement. Non-CA path kludges shouldn't ever occur but who knows
101  what other weirdness future RFCs will dream up, so we perform an
102  explicit check here */
103  status = getAttributeFieldValue( certInfoPtr->attributes,
105  CRYPT_ATTRIBUTE_NONE, &value );
106  return( ( cryptStatusOK( status ) && value ) ? TRUE : FALSE );
107  }
108 #endif /* USE_CERTLEVEL_PKIX_FULL */
109 
110 /****************************************************************************
111 * *
112 * Check Name Constraints *
113 * *
114 ****************************************************************************/
115 
116 #ifdef USE_CERTLEVEL_PKIX_FULL
117 
118 /* Perform a wildcarded compare of two strings in attributes. Certificates
119  don't use standard ? and * regular-expression wildcards but instead
120  specify the constraint as a form of longest-suffix filter that's applied
121  to the string (with the usual pile of special-case exceptions that apply
122  to any certificate-related rules) so that e.g. www.foo.com would be
123  constrained using foo.com (or more usually .foo.com to avoid erroneous
124  matches for strings like www.barfoo.com) */
125 
126 typedef enum {
127  MATCH_NONE, /* No special-case matching rules */
128  MATCH_EMAIL, /* Match using email address mailbox exception */
129  MATCH_URI, /* Match only DNS name portion of URI */
130  MATCH_LAST /* Last valid match rule type */
131  } MATCH_TYPE;
132 
134 static BOOLEAN wildcardMatch( const ATTRIBUTE_PTR *constrainedAttribute,
135  const ATTRIBUTE_PTR *constrainingAttribute,
136  IN_ENUM_OPT( MATCH ) const MATCH_TYPE matchType )
137  {
138  const BYTE *constrainingString, *constrainedString;
139  int constrainingStringLength, constrainedStringLength;
140  BOOLEAN isWildcardMatch;
141  int startPos, status;
142 
143  assert( isReadPtr( constrainedAttribute, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
144  assert( isReadPtr( constrainingAttribute, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
145 
146  REQUIRES_B( matchType >= MATCH_NONE && matchType < MATCH_LAST );
147 
148  status = getAttributeDataPtr( constrainingAttribute,
149  ( void ** ) &constrainingString,
150  &constrainingStringLength );
151  if( cryptStatusError( status ) )
152  return( FALSE );
153  status = getAttributeDataPtr( constrainedAttribute,
154  ( void ** ) &constrainedString,
155  &constrainedStringLength );
156  if( cryptStatusError( status ) )
157  return( FALSE );
158  isWildcardMatch = ( *constrainingString == '.' ) ? TRUE : FALSE;
159 
160  /* Determine the start position of the constraining string within the
161  constrained string:
162 
163  xxxxxyyyyy - Constrained string
164  yyyyy - Constraining string
165  ^
166  |
167  startPos
168 
169  If the constraining string is longer than the constrained string
170  (making startPos negative), it can never match */
171  startPos = constrainedStringLength - constrainingStringLength;
172  if( startPos < 0 || startPos > MAX_INTLENGTH_SHORT )
173  return( FALSE );
174 
175  /* Handle special-case match requirements (PKIX section 4.2.1.11) */
176  switch( matchType )
177  {
178  case MATCH_EMAIL:
179  /* Email addresses have a special-case requirement where the
180  absence of a wildcard-match indicator (the leading dot)
181  indicates that the mailbox has to be located directly on the
182  constraining hostname rather than merely within that domain,
183  i.e. [email protected] is a valid match for .bar.com but not
184  for bar.com, which would require [email protected] to match */
185  ENSURES_B( startPos <= constrainedStringLength );
186  if( !isWildcardMatch && \
187  ( startPos < 1 || constrainedString[ startPos - 1 ] != '@' ) )
188  return( FALSE );
189  break;
190 
191  case MATCH_URI:
192  {
193  URL_INFO urlInfo;
194 
195  /* URIs can contain trailing location information that isn't
196  regarded as part of the URI for matching purposes so before
197  performing the match we have to parse the URL and only use
198  the DNS name portion */
199  status = sNetParseURL( &urlInfo, constrainedString,
200  constrainedStringLength, URL_TYPE_NONE );
201  if( cryptStatusError( status ) )
202  {
203  /* Exactly what to do in the case of a URL parse error is a
204  bit complicated. The standard action is to fail closed,
205  otherwise anyone who creates a URL that the certificate
206  software can't parse but that's still accepted by other
207  apps (who in general will bend over backwards to try and
208  accept almost any malformed URI, if they didn't do this
209  then half the Internet would stop working) would be able
210  to bypass the name constraint. However this mode of
211  handling is complicated by the fact that to report a
212  failure at this point we need to report a match for
213  excluded subtrees but a non-match for permitted subtrees.
214  Since it's more likely that we'll encounter a permitted-
215  subtrees whitelist we report the constraint as being not
216  matched which will reject the certificate for permitted-
217  subtrees (who in their right mind would trust something as
218  flaky as PKI software to reliably apply an excluded-
219  subtrees blacklist? Even something as trivial as
220  "ex%41mple.com", let alone "ex%u0041mple.com",
221  "ex&#x41;mple.com", or "ex%EF%BC%A1mpple.com", is likely
222  to trivially fool all certificate software in existence,
223  so permitted-subtrees will never work anyway). In
224  addition we throw an exception in debug mode */
225  assert( DEBUG_WARN );
226  return( FALSE );
227  }
228 
229  /* Adjust the constrained string information to contain only the
230  DNS name portion of the URI */
231  constrainedString = urlInfo.host;
232  startPos = urlInfo.hostLen - constrainingStringLength;
233  if( startPos < 0 || startPos > MAX_INTLENGTH_SHORT )
234  return( FALSE );
235  ENSURES_B( rangeCheckZ( startPos, constrainingStringLength, \
236  urlInfo.hostLen ) );
237 
238  /* URIs have a special-case requirement where the absence of a
239  wildcard-match indicator (the leading dot) indicates that the
240  constraining DNS name is for a standalone host and not a
241  portion of the constrained string's DNS name. This means
242  that the DNS-name portion of the URI must be an exact match
243  for the constraining string */
244  if( !isWildcardMatch && startPos != 0 )
245  return( FALSE );
246  }
247  }
248  ENSURES_B( rangeCheckZ( startPos, constrainingStringLength, \
249  constrainedStringLength ) );
250 
251  /* Check whether the constraining string is a suffix of the constrained
252  string. For DNS name constraints the rule for RFC 3280 became
253  "adding to the LHS" as for other constraints, in RFC 2459 it was
254  another special case where it had to be a subdomain as if an
255  implicit "." was present */
256  return( !strCompare( constrainedString + startPos, constrainingString,
257  constrainingStringLength ) ? TRUE : FALSE );
258  }
259 
261 static BOOLEAN matchAltnameComponent( const ATTRIBUTE_PTR *constrainedAttribute,
262  const ATTRIBUTE_PTR *constrainingAttribute,
263  IN_ATTRIBUTE \
265  {
266  assert( isReadPtr( constrainedAttribute, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
267  assert( isReadPtr( constrainingAttribute, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
268 
269  REQUIRES( attributeType == CRYPT_CERTINFO_DIRECTORYNAME || \
270  attributeType == CRYPT_CERTINFO_RFC822NAME || \
271  attributeType == CRYPT_CERTINFO_DNSNAME || \
272  attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
273 
274  /* If the attribute being matched is a DN, use a DN-specific match */
275  if( attributeType == CRYPT_CERTINFO_DIRECTORYNAME )
276  {
277  void **constrainedDnPtr, **constrainingDnPtr;
278  int status;
279 
280  status = getAttributeDataDN( constrainedAttribute,
281  &constrainedDnPtr );
282  if( cryptStatusError( status ) )
283  return( FALSE );
284  status = getAttributeDataDN( constrainingAttribute, &constrainingDnPtr );
285  if( cryptStatusError( status ) )
286  return( FALSE );
287  return( compareDN( *constrainingDnPtr, *constrainedDnPtr, TRUE,
288  NULL ) );
289  }
290 
291  /* It's a string name, use a substring match with attribute type-specific
292  special cases */
293  return( wildcardMatch( constrainedAttribute, constrainingAttribute,
294  ( attributeType == CRYPT_CERTINFO_RFC822NAME ) ? \
295  MATCH_EMAIL : \
296  ( attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER ) ? \
297  MATCH_URI : \
298  MATCH_NONE ) );
299  }
300 
302 static BOOLEAN checkAltnameConstraints( const ATTRIBUTE_PTR *subjectAttributes,
303  const ATTRIBUTE_PTR *issuerAttributes,
304  IN_ATTRIBUTE \
305  const CRYPT_ATTRIBUTE_TYPE attributeType,
306  const BOOLEAN isExcluded )
307  {
308  const ATTRIBUTE_PTR *attributePtr, *constrainedAttributePtr;
309  int iterationCount;
310 
311  assert( isReadPtr( subjectAttributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
312  assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
313 
314  REQUIRES( attributeType == CRYPT_CERTINFO_DIRECTORYNAME || \
315  attributeType == CRYPT_CERTINFO_RFC822NAME || \
316  attributeType == CRYPT_CERTINFO_DNSNAME || \
317  attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
318 
319  /* Check for the presence of constrained or constraining altName
320  components. If either are absent, there are no constraints to
321  apply */
322  attributePtr = findAttributeField( issuerAttributes,
323  isExcluded ? \
326  attributeType );
327  if( attributePtr == NULL )
328  return( TRUE );
329 
330  for( constrainedAttributePtr = \
331  findAttributeField( subjectAttributes,
332  CRYPT_CERTINFO_SUBJECTALTNAME, attributeType ), \
333  iterationCount = 0;
334  constrainedAttributePtr != NULL && \
335  iterationCount < FAILSAFE_ITERATIONS_LARGE;
336  constrainedAttributePtr = \
337  findNextFieldInstance( constrainedAttributePtr ), \
338  iterationCount++ )
339  {
340  const ATTRIBUTE_PTR *attributeCursor;
341  int innerIterationCount;
342  BOOLEAN isMatch = FALSE;
343 
344  /* Step through the constraining attributes checking if any match
345  the constrained attribute. If it's an excluded subtree then none
346  can match, if it's a permitted subtree then at least one must
347  match */
348  for( attributeCursor = attributePtr, \
349  innerIterationCount = 0;
350  attributeCursor != NULL && !isMatch && \
351  innerIterationCount < FAILSAFE_ITERATIONS_LARGE;
352  attributeCursor =
353  findNextFieldInstance( attributeCursor ), \
354  innerIterationCount++ )
355  {
356  isMatch = matchAltnameComponent( constrainedAttributePtr,
357  attributeCursor,
358  attributeType );
359  }
360  ENSURES_B( innerIterationCount < FAILSAFE_ITERATIONS_LARGE );
361  if( isExcluded == isMatch )
362  return( FALSE );
363  }
364  ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_LARGE );
365 
366  return( TRUE );
367  }
368 
369 /* Check name constraints placed by an issuer, checked if complianceLevel >=
370  CRYPT_COMPLIANCELEVEL_PKIX_FULL */
371 
372 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
373 int checkNameConstraints( const CERT_INFO *subjectCertInfoPtr,
374  const ATTRIBUTE_PTR *issuerAttributes,
375  const BOOLEAN isExcluded,
376  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
377  CRYPT_ATTRIBUTE_TYPE *errorLocus,
378  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
379  CRYPT_ERRTYPE_TYPE *errorType )
380  {
381  const ATTRIBUTE_PTR *subjectAttributes = subjectCertInfoPtr->attributes;
382  const CRYPT_ATTRIBUTE_TYPE constraintType = isExcluded ? \
383  CRYPT_CERTINFO_EXCLUDEDSUBTREES : CRYPT_CERTINFO_PERMITTEDSUBTREES;
385  BOOLEAN isMatch = FALSE;
386 
387  assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
388  assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
389  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
390  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
391 
392  /* If this is a PKIX path-kludge CA certificate then the name
393  constraints don't apply to it (PKIX section 4.2.1.11). This is
394  required in order to allow extra certificates to be kludged into the
395  path without violating the constraint. For example with the chain:
396 
397  Issuer Subject Constraint
398  ------ ------- ----------
399  Root CA permitted = "EE"
400  CA' CA'
401  CA EE
402 
403  the kludge certificate CA' must be excluded from name constraint
404  restrictions in order for the path to be valid. Obviously this is
405  only necessary for constraints set by the immediate parent but PKIX
406  says it's for constraints set by all certificates in the chain (!!),
407  thus making the pathkludge certificate exempt from any name
408  constraints and not just the one that would cause problems */
409  if( isPathKludge( subjectCertInfoPtr ) )
410  return( CRYPT_OK );
411 
412  /* Check the subject DN if constraints exist. If it's an excluded
413  subtree then none can match, if it's a permitted subtree then at
414  least one must match. We also check for the special case of an
415  empty subject DN, which acts as a wildcard that matches/doesn't
416  match permitted/excluded as required */
417  attributePtr = findAttributeField( issuerAttributes, constraintType,
419  if( attributePtr != NULL && subjectCertInfoPtr->subjectName != NULL )
420  {
421  int iterationCount;
422 
423  for( iterationCount = 0;
424  attributePtr != NULL && !isMatch && \
425  iterationCount < FAILSAFE_ITERATIONS_LARGE;
426  iterationCount++ )
427  {
428  DN_PTR **dnPtrPtr;
429  int status;
430 
431  status = getAttributeDataDN( attributePtr, &dnPtrPtr );
432  if( cryptStatusOK( status ) )
433  {
434  /* Check whether the constraining DN is a substring of the
435  subject DN. For example if the constraining DN is
436  C=US/O=Foo/OU=Bar and the subject DN is
437  C=US/O=Foo/OU=Bar/CN=Baz then compareDN() will return
438  TRUE to indicate that it's a substring */
439  isMatch = compareDN( *dnPtrPtr,
440  subjectCertInfoPtr->subjectName, TRUE,
441  NULL );
442  }
443  attributePtr = findNextFieldInstance( attributePtr );
444  }
445  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
446  if( isExcluded == isMatch )
447  {
450  return( CRYPT_ERROR_INVALID );
451  }
452  }
453 
454  /* DN constraints apply to both the main subject DN and any other DNs
455  that may be present as subject altNames, so after we've checked the
456  main DN we check any altName DNs as well */
457  if( !checkAltnameConstraints( subjectAttributes, issuerAttributes,
458  CRYPT_CERTINFO_DIRECTORYNAME, isExcluded ) )
459  {
462  return( CRYPT_ERROR_INVALID );
463  }
464 
465  /* Compare the Internet-related names if constraints exist. We don't
466  have to check for the special case of an email address in the DN
467  since the certificate import code transparently maps this to the
468  appropriate altName component */
469  if( !checkAltnameConstraints( subjectAttributes, issuerAttributes,
470  CRYPT_CERTINFO_RFC822NAME, isExcluded ) || \
471  !checkAltnameConstraints( subjectAttributes, issuerAttributes,
472  CRYPT_CERTINFO_DNSNAME, isExcluded ) || \
473  !checkAltnameConstraints( subjectAttributes, issuerAttributes,
475  isExcluded ) )
476  {
479  return( CRYPT_ERROR_INVALID );
480  }
481 
482  return( CRYPT_OK );
483  }
484 #endif /* USE_CERTLEVEL_PKIX_FULL */
485 
486 /****************************************************************************
487 * *
488 * Check Policy Constraints *
489 * *
490 ****************************************************************************/
491 
492 #ifdef USE_CERTLEVEL_PKIX_FULL
493 
494 /* Check whether a policy is the wildcard anyPolicy */
495 
497 BOOLEAN isAnyPolicy( const ATTRIBUTE_PTR *attributePtr )
498  {
499  void *policyOidPtr;
500  int policyOidLength, status;
501 
502  assert( isReadPtr( attributePtr, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
503 
504  status = getAttributeDataPtr( attributePtr, &policyOidPtr,
505  &policyOidLength );
506  if( cryptStatusError( status ) )
507  return( FALSE );
508  return( ( policyOidLength == sizeofOID( OID_ANYPOLICY ) && \
509  !memcmp( policyOidPtr, OID_ANYPOLICY,
510  sizeofOID( OID_ANYPOLICY ) ) ) ? TRUE : FALSE );
511  }
512 
513 /* Check whether a set of policies contains an instance of the anyPolicy
514  wildcard */
515 
517 static BOOLEAN containsAnyPolicy( const ATTRIBUTE_PTR *attributePtr,
518  IN_ATTRIBUTE \
519  const CRYPT_ATTRIBUTE_TYPE attributeType )
520  {
521  int iterationCount;
522 
523  assert( isReadPtr( attributePtr, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
524 
525  REQUIRES_B( attributeType >= CRYPT_CERTINFO_FIRST_EXTENSION && \
526  attributeType <= CRYPT_CERTINFO_LAST );
527 
528  for( attributePtr = findAttributeField( attributePtr, \
529  attributeType, CRYPT_ATTRIBUTE_NONE ), \
530  iterationCount = 0;
531  attributePtr != NULL && \
532  iterationCount < FAILSAFE_ITERATIONS_LARGE;
533  attributePtr = findNextFieldInstance( attributePtr ), \
534  iterationCount++ )
535  {
536  if( isAnyPolicy( attributePtr ) )
537  return( TRUE );
538  }
539  ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_LARGE );
540 
541  return( FALSE );
542  }
543 
544 /* Check the type of policy present in a certificate and make sure that it's
545  valid */
546 
548 static BOOLEAN checkPolicyType( IN_OPT const ATTRIBUTE_PTR *attributePtr,
549  OUT_BOOL BOOLEAN *hasPolicy,
550  OUT_BOOL BOOLEAN *hasAnyPolicy,
551  const BOOLEAN inhibitAnyPolicy )
552  {
553  int iterationCount;
554 
555  assert( attributePtr == NULL || \
556  isReadPtr( attributePtr, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
557  assert( isWritePtr( hasPolicy, sizeof( BOOLEAN ) ) );
558  assert( isWritePtr( hasAnyPolicy, sizeof( BOOLEAN ) ) );
559 
560  /* Clear return values */
561  *hasPolicy = *hasAnyPolicy = FALSE;
562 
563  /* Make sure that there's a policy present and that it's a specific
564  policy if an explicit policy is required (the ability to disallow the
565  wildcard policy via inhibitAnyPolicy was introduced in RFC 3280 along
566  with the introduction of anyPolicy) */
567  if( attributePtr == NULL )
568  return( FALSE );
569  for( iterationCount = 0;
570  attributePtr != NULL && iterationCount < FAILSAFE_ITERATIONS_LARGE;
571  attributePtr = findNextFieldInstance( attributePtr ), iterationCount++ )
572  {
573  if( isAnyPolicy( attributePtr ) )
574  *hasAnyPolicy = TRUE;
575  else
576  *hasPolicy = TRUE;
577  }
578  ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_LARGE );
579  if( inhibitAnyPolicy )
580  {
581  /* The wildcard anyPolicy isn't valid for the subject, if there's no
582  other policy set then this is an error, otherwise we continue
583  without the wildcard match allowed */
584  if( !*hasPolicy )
585  return( FALSE );
586  *hasAnyPolicy = FALSE;
587  }
588 
589  return( TRUE );
590  }
591 
592 /* Check whether a given policy is present in a certificate */
593 
595 BOOLEAN isPolicyPresent( const ATTRIBUTE_PTR *subjectAttributes,
596  IN_BUFFER( issuerPolicyValueLength ) \
597  const void *issuerPolicyValue,
598  IN_LENGTH_OID const int issuerPolicyValueLength )
599  {
600  const ATTRIBUTE_PTR *attributeCursor;
601  int iterationCount, status;
602 
603  assert( isReadPtr( subjectAttributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
604  assert( isReadPtr( issuerPolicyValue, issuerPolicyValueLength ) );
605 
606  REQUIRES_B( issuerPolicyValueLength > 0 && \
607  issuerPolicyValueLength < MAX_POLICY_SIZE );
608 
609  for( attributeCursor = subjectAttributes, iterationCount = 0;
610  attributeCursor != NULL && iterationCount < FAILSAFE_ITERATIONS_LARGE;
611  attributeCursor = findNextFieldInstance( attributeCursor ), \
612  iterationCount++ )
613  {
614  void *subjectPolicyValuePtr;
615  int subjectPolicyValueLength;
616 
617  status = getAttributeDataPtr( attributeCursor, &subjectPolicyValuePtr,
618  &subjectPolicyValueLength );
619  if( cryptStatusError( status ) )
620  continue;
621  if( issuerPolicyValueLength == subjectPolicyValueLength && \
622  !memcmp( issuerPolicyValue, subjectPolicyValuePtr,
623  issuerPolicyValueLength ) )
624  return( TRUE );
625  }
626  ENSURES_B( iterationCount < FAILSAFE_ITERATIONS_LARGE );
627 
628  return( FALSE );
629  }
630 
631 /* Check policy constraints placed by an issuer, checked if complianceLevel
632  >= CRYPT_COMPLIANCELEVEL_PKIX_FULL */
633 
634 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 7, 8 ) ) \
635 int checkPolicyConstraints( const CERT_INFO *subjectCertInfoPtr,
636  const ATTRIBUTE_PTR *issuerAttributes,
637  IN_ENUM_OPT( POLICY ) const POLICY_TYPE policyType,
638  IN_OPT const POLICY_INFO *policyInfo,
639  IN_RANGE( 0, MAX_CHAINLENGTH ) const int policyLevel,
640  const BOOLEAN allowMappedPolicies,
641  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
642  CRYPT_ATTRIBUTE_TYPE *errorLocus,
643  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
644  CRYPT_ERRTYPE_TYPE *errorType )
645  {
646  const ATTRIBUTE_PTR *constrainingAttributePtr = \
647  findAttributeField( issuerAttributes,
650  const ATTRIBUTE_PTR *constrainedAttributePtr = \
651  findAttributeField( subjectCertInfoPtr->attributes,
654  BOOLEAN subjectHasPolicy, issuerHasPolicy;
655  BOOLEAN subjectHasAnyPolicy, issuerHasAnyPolicy;
656  int iterationCount;
657 
658  assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
659  assert( isReadPtr( issuerAttributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
660  assert( ( policyInfo == NULL && policyLevel == 0 ) || \
661  ( isReadPtr( policyInfo, sizeof( POLICY_INFO ) ) && \
662  ( policyLevel >= 0 && policyLevel < MAX_CHAINLENGTH ) ) );
663  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
664  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
665 
666  REQUIRES( policyType >= POLICY_NONE && policyType < POLICY_LAST );
667  REQUIRES( policyLevel >= 0 && policyLevel < MAX_CHAINLENGTH );
668 
669  /* If there's a policy mapping present then neither the issuer nor
670  subject domain policies can be the wildcard anyPolicy (PKIX section
671  4.2.1.6) */
672  if( containsAnyPolicy( issuerAttributes,
674  containsAnyPolicy( issuerAttributes,
676  {
679  return( CRYPT_ERROR_INVALID );
680  }
681 
682  /* If there's no requirement for a policy and there's none set, we're
683  done */
684  if( policyType == POLICY_NONE && constrainedAttributePtr == NULL )
685  return( CRYPT_OK );
686 
687  /* Check the subject policy */
688  if( !checkPolicyType( constrainedAttributePtr, &subjectHasPolicy,
689  &subjectHasAnyPolicy,
690  ( policyType == POLICY_NONE_SPECIFIC || \
691  policyType == POLICY_SUBJECT_SPECIFIC || \
692  policyType == POLICY_BOTH_SPECIFIC ) ? \
693  TRUE : FALSE ) )
694  {
697  return( CRYPT_ERROR_INVALID );
698  }
699 
700  /* If there's no requirement for an issuer policy and there's none set
701  by the issuer, we're done */
702  if( ( ( policyType == POLICY_SUBJECT ) || \
703  ( policyType == POLICY_SUBJECT_SPECIFIC ) ) && \
704  constrainingAttributePtr == NULL )
705  return( CRYPT_OK );
706 
707  /* Check the issuer policy */
708  if( !checkPolicyType( constrainingAttributePtr , &issuerHasPolicy,
709  &issuerHasAnyPolicy,
710  ( policyType == POLICY_BOTH_SPECIFIC ) ? \
711  TRUE : FALSE ) )
712  {
715  return( CRYPT_ERROR_INVALID );
716  }
717 
718  /* Both the issuer and subject have some sort of policy, if either are
719  anyPolicy wildcards (introduced in RFC 3280 section 4.2.1.5) then
720  it's considered a match */
721  if( subjectHasAnyPolicy || issuerHasAnyPolicy )
722  return( CRYPT_OK );
723 
724  /* An explicit policy is required, make sure that at least one of the
725  issuer policies matches at least one of the subject policies. Note
726  that there's no exception for PKIX path-kludge certificates, this is
727  an error in the RFC for which the text at this point is unchanged
728  from RFC 2459. In fact this contradicts the path-processing
729  pesudocode but since that in turn contradicts the main text in a
730  number of places we take the main text as definitive, not the buggy
731  pseudocode */
732  if( policyInfo != NULL )
733  {
734  const POLICY_DATA *policyData = policyInfo->policies;
735  int i;
736 
737  for( i = 0; i < policyInfo->noPolicies && \
738  i < FAILSAFE_ITERATIONS_MED; i++ )
739  {
740  if( policyData[ i ].isMapped && !allowMappedPolicies )
741  continue;
742  if( isPolicyPresent( constrainedAttributePtr,
743  policyData[ i ].data,
744  policyData[ i ].length ) )
745  return( CRYPT_OK );
746  }
747  ENSURES( i < FAILSAFE_ITERATIONS_MED );
748  }
749  else
750  {
751  ATTRIBUTE_PTR *constrainingAttributeCursor;
752 
753  for( constrainingAttributeCursor = \
754  ( ATTRIBUTE_PTR * ) constrainingAttributePtr, \
755  iterationCount = 0;
756  constrainingAttributeCursor != NULL && \
757  iterationCount < FAILSAFE_ITERATIONS_LARGE;
758  constrainingAttributeCursor = \
759  findNextFieldInstance( constrainingAttributeCursor ), \
760  iterationCount++ )
761  {
762  void *constrainingPolicyValuePtr;
763  int constrainingPolicyValueLength, status;
764 
765  status = getAttributeDataPtr( constrainingAttributeCursor,
766  &constrainingPolicyValuePtr,
767  &constrainingPolicyValueLength );
768  if( cryptStatusError( status ) )
769  break;
770  if( isPolicyPresent( constrainedAttributePtr,
771  constrainingPolicyValuePtr,
772  constrainingPolicyValueLength ) )
773  return( CRYPT_OK );
774  }
775  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
776  }
777 
778  /* We couldn't find a matching policy, report an error */
780  return( CRYPT_ERROR_INVALID );
781  }
782 #endif /* USE_CERTLEVEL_PKIX_FULL */
783 
784 /****************************************************************************
785 * *
786 * Check Path Constraints *
787 * *
788 ****************************************************************************/
789 
790 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
791 
792 /* Check path constraints placed by an issuer, checked if complianceLevel
793  >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL */
794 
795 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
796 int checkPathConstraints( const CERT_INFO *subjectCertInfoPtr,
797  IN_LENGTH_SHORT_Z const int pathLength,
798  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
799  CRYPT_ATTRIBUTE_TYPE *errorLocus,
800  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
801  CRYPT_ERRTYPE_TYPE *errorType )
802  {
803  int value, status;
804 
805  assert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
806  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
807  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
808 
809  REQUIRES( pathLength >= 0 && pathLength < MAX_INTLENGTH_SHORT );
810 
811 #ifdef USE_CERTLEVEL_PKIX_FULL
812  /* If this is a PKIX path-kludge certificate then the path length
813  constraints don't apply to it (PKIX section 4.2.1.10). This is
814  required in order to allow extra certificates to be kludged into the
815  path without violating the name constraint */
816  if( isPathKludge( subjectCertInfoPtr ) )
817  return( CRYPT_OK );
818 #endif /* USE_CERTLEVEL_PKIX_FULL */
819 
820  /* If the path length constraint hasn't been triggered yet we're OK */
821  if( pathLength > 0 )
822  return( CRYPT_OK );
823 
824  /* If the certificate is self-signed (i.e. the certificate is applying
825  the constraint to itself) then a path length constraint of zero is
826  valid. Checking only the subject certificate information is safe
827  because the calling code has guaranteed that if the certificate is
828  self-signed then the issuer attributes are the attributes from the
829  subject certificate */
830  if( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED )
831  return( CRYPT_OK );
832 
833  /* The path length constraint is in effect, the next certificate down
834  the chain must be an end-entity certificate */
835  status = getAttributeFieldValue( subjectCertInfoPtr->attributes,
837  CRYPT_ATTRIBUTE_NONE, &value );
838  if( cryptStatusOK( status ) && value > 0 )
839  {
842  return( CRYPT_ERROR_INVALID );
843  }
844 
845  return( CRYPT_OK );
846  }
847 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
848 
849 /****************************************************************************
850 * *
851 * Check RPKI Attributes *
852 * *
853 ****************************************************************************/
854 
855 /* Check attributes for a resource RPKI (RPKI) certificate. This is
856  somewhat ugly in that it entails a number of implicit checks rather
857  than just applying constraints specified in the certificate itself,
858  but then again it's not much different to the range of checks
859  hardcoded into checkCert(), the only real difference is that the latter
860  is specified for all certificates while these are only for RPKI
861  certificates */
862 
863 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
864 static int checkRPKIAttributes( const ATTRIBUTE_PTR *subjectAttributes,
865  const BOOLEAN isCA,
866  const BOOLEAN isSelfSigned,
867  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
868  CRYPT_ATTRIBUTE_TYPE *errorLocus,
869  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
870  CRYPT_ERRTYPE_TYPE *errorType )
871  {
873  void *policyOidPtr;
874  int policyOidLength, value, status;
875 
876  assert( isReadPtr( subjectAttributes, sizeof( CERT_INFO ) ) );
877  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
878  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
879 
880  /* Check that there's a keyUsage present, and that for CA certificates
881  it's the CA usages and for EE certificates it's digital signature
882  (RPKI section 3.9.4) */
883  status = getAttributeFieldValue( subjectAttributes,
885  CRYPT_ATTRIBUTE_NONE, &value );
886  if( cryptStatusError( status ) )
887  {
889  return( CRYPT_ERROR_INVALID );
890  }
891  if( isCA )
892  {
893  if( value != CRYPT_KEYUSAGE_DIGITALSIGNATURE )
894  status = CRYPT_ERROR_INVALID;
895  }
896  else
897  {
898  if( value != ( CRYPT_KEYUSAGE_KEYCERTSIGN | \
900  status = CRYPT_ERROR_INVALID;
901  }
902  if( cryptStatusError( status ) )
903  {
905  return( CRYPT_ERROR_INVALID );
906  }
907 
908  /* If it's a CA, check that there's no extendedKeyUsage (RPKI section
909  3.9.5) and there's a caRepository SIA (RPKI section 3.9.8) */
910  if( isCA )
911  {
912  if( checkAttributePresent( subjectAttributes,
914  {
917  return( CRYPT_ERROR_INVALID );
918  }
919  if( !checkAttributeFieldPresent( subjectAttributes,
921  {
924  return( CRYPT_ERROR_INVALID );
925  }
926  }
927 
928  /* If it's not self-signed (i.e. not a root certificate) check that
929  there's a caIssuers AIA (RPKI section 3.9.7) */
930  if( !isSelfSigned )
931  {
932  if( !checkAttributeFieldPresent( subjectAttributes,
934  {
937  return( CRYPT_ERROR_INVALID );
938  }
939  }
940 
941  /* Check that there's an RPKI policy present (RPKI section 3.9.9) */
942  attributePtr = findAttributeField( subjectAttributes,
945  if( attributePtr == NULL )
946  {
949  return( CRYPT_ERROR_INVALID );
950  }
951  status = getAttributeDataPtr( attributePtr, &policyOidPtr,
952  &policyOidLength );
953  if( cryptStatusError( status ) || \
954  policyOidLength != sizeofOID( OID_RPKI_POLICY ) || \
955  memcmp( policyOidPtr, OID_RPKI_POLICY,
957  {
960  return( CRYPT_ERROR_INVALID );
961  }
962 
963  return( CRYPT_OK );
964  }
965 
966 /****************************************************************************
967 * *
968 * Check a Certificate Object *
969 * *
970 ****************************************************************************/
971 
972 #ifdef USE_CERTREV
973 
974 /* Check the consistency of a CRL against its issuing certificate. Note
975  that this is the reverse of the usual form of checking the certificate
976  against the CRL */
977 
978 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
979 static int checkCrlConsistency( const CERT_INFO *crlInfoPtr,
983  const int complianceLevel,
984  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
985  CRYPT_ATTRIBUTE_TYPE *errorLocus,
986  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
987  CRYPT_ERRTYPE_TYPE *errorType )
988  {
989  int deltaCRLindicator, status;
990 
991  assert( isReadPtr( crlInfoPtr, sizeof( CERT_INFO ) ) );
992  assert( issuerCertInfoPtr == NULL || \
993  isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
994  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
995  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
996 
997  REQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \
998  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );
999 
1000  /* If it's a delta CRL make sure that the CRL numbers make sense (that
1001  is, that the delta CRL was issued after the full CRL) */
1002  status = getAttributeFieldValue( crlInfoPtr->attributes,
1005  &deltaCRLindicator );
1006  if( cryptStatusOK( status ) )
1007  {
1008  int crlNumber;
1009 
1010  status = getAttributeFieldValue( crlInfoPtr->attributes,
1012  CRYPT_ATTRIBUTE_NONE, &crlNumber );
1013  if( cryptStatusOK( status ) && crlNumber >= deltaCRLindicator )
1014  {
1017  return( CRYPT_ERROR_INVALID );
1018  }
1019  }
1020 
1021  /* If it's a standalone CRL entry used purely as a container for
1022  revocation data don't try and perform any issuer-based checking */
1023  if( issuerCertInfoPtr == NULL )
1024  return( CRYPT_OK );
1025 
1026  /* Make sure that the issuer can sign CRLs and that the issuer
1027  certificate in general is in order */
1028  return( checkKeyUsage( issuerCertInfoPtr,
1030  CRYPT_KEYUSAGE_CRLSIGN, complianceLevel,
1031  errorLocus, errorType ) );
1032  }
1033 #endif /* USE_CERTREV */
1034 
1035 /* Perform basic checks on a certificate. Apart from its use as part of the
1036  normal certificate-checking process this is also used to provide a quick
1037  "is this certificate obviously invalid" check without having to check
1038  signatures from issuing certificates and other paraphernalia, for example
1039  when a full certificate check has been performed earlier and all we want
1040  to do is make sure that the certificate hasn't expired or been declared
1041  untrusted in the meantime */
1042 
1043 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1044 int checkCertBasic( INOUT CERT_INFO *certInfoPtr )
1045  {
1046  CRYPT_ATTRIBUTE_TYPE *errorLocus = &certInfoPtr->errorLocus;
1047  CRYPT_ERRTYPE_TYPE *errorType = &certInfoPtr->errorType;
1048  const time_t currentTime = getTime();
1049  int complianceLevel, status;
1050 
1051  assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
1052  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
1053  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
1054 
1055  REQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
1056  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
1057  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
1058 
1059  /* Determine how much checking we need to perform */
1060  status = krnlSendMessage( certInfoPtr->ownerHandle,
1061  IMESSAGE_GETATTRIBUTE, &complianceLevel,
1063  if( cryptStatusError( status ) )
1064  return( status );
1065 
1066  /* There is one universal case in which a certificate is regarded as
1067  invalid and that's when it's explicitly not trusted */
1068  if( certInfoPtr->cCertCert->trustedUsage == 0 )
1069  {
1072  return( CRYPT_ERROR_INVALID );
1073  }
1074 
1075  /* If we're running in oblivious mode, we're done */
1076  if( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )
1077  return( CRYPT_OK );
1078 
1079  /* Check that the validity period is in order. If we're checking an
1080  existing certificate then the start time has to be valid, if we're
1081  creating a new certificate then it doesn't have to be valid since the
1082  certificate could be created for use in the future */
1083  if( currentTime <= MIN_TIME_VALUE )
1084  {
1085  /* Time is broken, we can't reliably check for expiry times */
1087  return( CRYPT_ERROR_INVALID );
1088  }
1089  if( certInfoPtr->startTime >= certInfoPtr->endTime || \
1090  ( certInfoPtr->certificate != NULL && \
1091  currentTime < certInfoPtr->startTime ) )
1092  {
1094  return( CRYPT_ERROR_INVALID );
1095  }
1096  if( currentTime > certInfoPtr->endTime )
1097  {
1099  return( CRYPT_ERROR_INVALID );
1100  }
1101 
1102  return( CRYPT_OK );
1103  }
1104 
1105 /* Check the validity of a subject certificate based on an issuer
1106  certificate with the level of checking performed depending on the
1107  complianceLevel setting. If the shortCircuitCheck flag is set (used for
1108  certificate issuer : subject pairs that may already have been checked)
1109  we skip the constant-result checks if the combination has already been
1110  checked at this compliance level */
1111 
1112 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
1113 int checkCert( INOUT CERT_INFO *subjectCertInfoPtr,
1114  IN_OPT const CERT_INFO *issuerCertInfoPtr,
1115  const BOOLEAN shortCircuitCheck,
1116  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
1117  CRYPT_ATTRIBUTE_TYPE *errorLocus,
1118  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
1119  CRYPT_ERRTYPE_TYPE *errorType )
1120  {
1121  const ATTRIBUTE_PTR *subjectAttributes = subjectCertInfoPtr->attributes;
1122  const ATTRIBUTE_PTR *issuerAttributes = \
1123  ( issuerCertInfoPtr != NULL ) ? \
1124  issuerCertInfoPtr->attributes : NULL;
1125  const ATTRIBUTE_PTR *attributePtr;
1126  const BOOLEAN subjectSelfSigned = \
1127  ( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) ? \
1128  TRUE : FALSE;
1129  BOOLEAN subjectIsCA = FALSE, issuerIsCA = FALSE;
1130  int value, complianceLevel, status;
1131 
1132  assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
1133  assert( issuerCertInfoPtr == NULL || \
1134  isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
1135  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
1136  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
1137 
1138  /* Determine how much checking we need to perform. If this is a
1139  currently-under-construction certificate then we use the maximum
1140  compliance level to ensure that cryptlib never produces broken
1141  certificates */
1142  if( subjectCertInfoPtr->certificate == NULL )
1143  complianceLevel = CRYPT_COMPLIANCELEVEL_PKIX_FULL;
1144  else
1145  {
1146  status = krnlSendMessage( subjectCertInfoPtr->ownerHandle,
1147  IMESSAGE_GETATTRIBUTE, &complianceLevel,
1149  if( cryptStatusError( status ) )
1150  return( status );
1151  }
1152 
1153  /* If it's some form of certificate request or an OCSP object (which
1154  means that it isn't signed by an issuer in the normal sense) then
1155  there's nothing to check (yet) */
1156  switch( subjectCertInfoPtr->type )
1157  {
1161  /* It's an issuer-signed object, there must be an issuer
1162  certificate present */
1163  REQUIRES( issuerCertInfoPtr != NULL );
1164  if( subjectCertInfoPtr->flags & CERT_FLAG_CERTCOLLECTION )
1165  {
1166  /* Certificate collections are pure container objects for
1167  which the base certificate object doesn't correspond to
1168  an actual certificate */
1169  retIntError();
1170  }
1171  break;
1172 
1176  /* These are merely templates submitted to a CA, there's nothing
1177  to check. More specifically, the template could contain
1178  constraints that only make sense once the issuer certificate
1179  is incorporated into a chain or a future-dated validity time
1180  or a CA keyUsage for which the CA provides the appropriate
1181  matching basicConstraints value(s) so we can't really perform
1182  much checking here */
1183  return( CRYPT_OK );
1184 
1185 #ifdef USE_CERTREV
1186  case CRYPT_CERTTYPE_CRL:
1187  /* There must be an issuer certificate present unless we're
1188  checking a standalone CRL entry that acts purely as a
1189  container for revocation data */
1190  assert( issuerCertInfoPtr == NULL || \
1191  isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
1192 
1193  /* CRL checking is handled specially */
1194  return( checkCrlConsistency( subjectCertInfoPtr,
1195  issuerCertInfoPtr, complianceLevel,
1196  errorLocus, errorType ) );
1197 #endif /* USE_CERTREV */
1198 
1201  retIntError();
1202 
1207  /* These aren't normal certificate types, there's nothing to
1208  check - we can't even check the issuer since they're not
1209  normally issued by CAs */
1210  return( CRYPT_OK );
1211 
1212  default:
1213  retIntError();
1214  }
1215  ENSURES( issuerCertInfoPtr != NULL );
1216  ENSURES( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
1217  subjectCertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
1218  subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
1219 
1220  /* Perform a basic check for obvious invalidity issues */
1221  status = checkCertBasic( subjectCertInfoPtr );
1222  if( cryptStatusError( status ) )
1223  return( status );
1224 
1225  /* There is one universal case in which a certificate is regarded as
1226  invalid and that's when the issuing certificate isn't trusted as an
1227  issuer. We perform the check in oblivious mode to ensure that only
1228  the basic trusted usage gets checked at this point */
1229  if( issuerCertInfoPtr->cCertCert->trustedUsage != CRYPT_ERROR )
1230  {
1231  status = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA,
1234  errorLocus, errorType );
1235  if( cryptStatusError( status ) )
1236  return( status );
1237  }
1238 
1239  /* If we're running in oblivious mode, we're done */
1240  if( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )
1241  return( CRYPT_OK );
1242 
1243  /* If it's a self-signed certificate or if we're doing a short-circuit
1244  check of a certificate in a chain that's already been checked and
1245  we've already checked it at the appropriate level then there's no
1246  need to perform any further checks */
1247  if( ( subjectSelfSigned || shortCircuitCheck ) && \
1248  ( subjectCertInfoPtr->cCertCert->maxCheckLevel >= complianceLevel ) )
1249  return( CRYPT_OK );
1250 
1251  /* If the certificate isn't self-signed, check name chaining */
1252  if( !subjectSelfSigned )
1253  {
1254  /* Check that the subject issuer name and issuer subject name chain
1255  properly. If the DNs are present in pre-encoded form we do a
1256  binary comparison, which is faster than calling compareDN() */
1257  if( subjectCertInfoPtr->certificate != NULL )
1258  {
1259  if( subjectCertInfoPtr->issuerDNsize != \
1260  issuerCertInfoPtr->subjectDNsize || \
1261  memcmp( subjectCertInfoPtr->issuerDNptr,
1262  issuerCertInfoPtr->subjectDNptr,
1263  subjectCertInfoPtr->issuerDNsize ) )
1264  {
1267  return( CRYPT_ERROR_INVALID );
1268  }
1269  }
1270  else
1271  {
1272  if( !compareDN( subjectCertInfoPtr->issuerName,
1273  issuerCertInfoPtr->subjectName, FALSE, NULL ) )
1274  {
1277  return( CRYPT_ERROR_INVALID );
1278  }
1279  }
1280  }
1281 
1282  /* Determine whether the subject or issuer are CA certificates */
1283  status = getAttributeFieldValue( subjectAttributes,
1285  CRYPT_ATTRIBUTE_NONE, &value );
1286  if( cryptStatusOK( status ) )
1287  subjectIsCA = ( value > 0 ) ? TRUE : FALSE;
1288  status = getAttributeFieldValue( issuerAttributes,
1290  CRYPT_ATTRIBUTE_NONE, &value );
1291  if( cryptStatusOK( status ) )
1292  issuerIsCA = ( value > 0 ) ? TRUE : FALSE;
1293 
1294  /* If we're doing a reduced level of checking, we're done */
1295  if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )
1296  {
1297  if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
1298  subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
1299  return( CRYPT_OK );
1300  }
1301 
1302  /* Check that the certificate usage flags are present and consistent.
1303  The key usage checking level ranges up to
1304  CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL so we re-do the check even if it's
1305  already been done at a lower level */
1306  if( subjectCertInfoPtr->cCertCert->maxCheckLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \
1307  subjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )
1308  {
1309  status = checkKeyUsage( subjectCertInfoPtr, CHECKKEY_FLAG_GENCHECK,
1310  CRYPT_KEYUSAGE_NONE, complianceLevel,
1311  errorLocus, errorType );
1312  if( cryptStatusError( status ) )
1313  return( status );
1314  }
1315 
1316  /* If the certificate isn't self-signed check that the issuer is a CA */
1317  if( !subjectSelfSigned )
1318  {
1319  status = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA,
1320  CRYPT_KEYUSAGE_KEYCERTSIGN, complianceLevel,
1321  errorLocus, errorType );
1322  if( cryptStatusError( status ) )
1323  {
1324  /* There was a problem with the issuer certificate, convert the
1325  error to an issuer constraint */
1326  *errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
1327  return( status );
1328  }
1329  }
1330 
1331  /* Check all the blob (unrecognised) attributes to see if any are marked
1332  critical. We only do this if it's an existing certificate that we've
1333  imported rather than one that we've just created since applying this
1334  check to the latter would make it impossible to create certificates
1335  with unrecognised critical extensions */
1336  if( subjectCertInfoPtr->certificate != NULL )
1337  {
1338  ATTRIBUTE_ENUM_INFO attrEnumInfo;
1339  int iterationCount;
1340 
1341  for( attributePtr = getFirstAttribute( &attrEnumInfo, subjectAttributes,
1342  ATTRIBUTE_ENUM_BLOB ), \
1343  iterationCount = 0;
1344  attributePtr != NULL && \
1345  iterationCount < FAILSAFE_ITERATIONS_LARGE;
1346  attributePtr = getNextAttribute( &attrEnumInfo ), \
1347  iterationCount++ )
1348  {
1349  /* If we've found an unrecognised critical extension, reject the
1350  certificate (PKIX section 4.2). The one exception to this is
1351  if the attribute was recognised but has been ignored at this
1352  compliance level, in which case it's treated as a blob
1353  attribute */
1354  if( checkAttributeProperty( attributePtr, \
1356  !checkAttributeProperty( attributePtr, \
1358  {
1361  return( CRYPT_ERROR_INVALID );
1362  }
1363  }
1364  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
1365  }
1366 
1367 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
1368  /* If we're not doing at least partial PKIX checking, we're done */
1369  if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
1370  {
1371  if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
1372  subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
1373  return( CRYPT_OK );
1374  }
1375 
1376  /* Constraints can only be present in CA certificates. The issuer may
1377  not be a proper CA if it's a self-signed end entity certificate or
1378  an X.509v1 CA certificate, which is why we also check for
1379  !issuerIsCA */
1380  if( subjectAttributes != NULL )
1381  {
1382  if( !subjectIsCA && invalidAttributesPresent( subjectAttributes, FALSE,
1383  errorLocus, errorType ) )
1384  return( CRYPT_ERROR_INVALID );
1385  if( !issuerIsCA && invalidAttributesPresent( subjectAttributes, TRUE,
1386  errorLocus, errorType ) )
1387  return( CRYPT_ERROR_INVALID );
1388  }
1389 
1390  /* From this point onwards if we're doing a short-circuit check of
1391  certificates in a chain we don't apply constraint checks. This is
1392  because the certificate-chain code has already performed far more
1393  complete checks of the various constraints set by all the
1394  certificates in the chain rather than just the current certificate
1395  issuer : subject pair */
1396 
1397  /* If there's a path length constraint present, apply it */
1398  status = getAttributeFieldValue( issuerAttributes,
1400  CRYPT_ATTRIBUTE_NONE, &value );
1401  if( cryptStatusOK( status ) && !shortCircuitCheck )
1402  {
1403  status = checkPathConstraints( subjectCertInfoPtr, value,
1404  errorLocus, errorType );
1405  if( cryptStatusError( status ) )
1406  return( status );
1407  }
1408 
1409  /* In order to dig itself out of a hole caused by a circular definition,
1410  RFC 3280 added a new extKeyUsage anyExtendedKeyUsage (rather than the
1411  more obvious fix of removing the problematic definition).
1412  Unfortunately this causes more problems than it solves because the exact
1413  semantics of this new usage aren't precisely defined. To fix this
1414  problem we invent some plausible ones ourselves: If the only eKU is
1415  anyKU we treat the overall extKeyUsage as empty, i.e. there are no
1416  particular restrictions on usage. If any other usage is present then
1417  the extension has become self-contradictory so we treat the anyKU as
1418  being absent. See the comment for getExtendedKeyUsageFlags() for how
1419  this is handled */
1420  attributePtr = findAttributeField( subjectAttributes,
1423  if( attributePtr != NULL && \
1424  checkAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_CRITICAL ) )
1425  {
1426  /* If anyKU is present the extension must be non-critical
1427  (PKIX section 4.2.1.13) */
1430  return( CRYPT_ERROR_INVALID );
1431  }
1432 
1433  /* If this is a resource PKI (RPKI) certificate, apply RPKI-specific
1434  checks */
1435  if( checkAttributePresent( subjectAttributes, \
1437  checkAttributePresent( subjectAttributes, \
1439  {
1440  ANALYSER_HINT( subjectAttributes != NULL );
1441 
1442  status = checkRPKIAttributes( subjectAttributes, subjectIsCA,
1443  subjectSelfSigned, errorLocus,
1444  errorType );
1445  if( cryptStatusError( status ) )
1446  return( status );
1447  }
1448 
1449 #ifdef USE_CERTLEVEL_PKIX_FULL
1450  /* If we're not doing full PKIX checking, we're done. In addition since
1451  all of the remaining checks are constraint checks we can exit at this
1452  point if we're doing a short-circuit check */
1453  if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL || \
1454  shortCircuitCheck )
1455  {
1456  if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
1457  subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
1458  return( CRYPT_OK );
1459  }
1460 
1461  /* If the issuing certificate has name constraints and isn't
1462  self-signed make sure that the subject name and altName fall within
1463  the constrained subtrees. Since excluded subtrees override permitted
1464  subtrees we check these first */
1465  if( !subjectSelfSigned )
1466  {
1467  attributePtr = findAttributeField( issuerAttributes,
1470  if( attributePtr != NULL && \
1471  cryptStatusError( \
1472  checkNameConstraints( subjectCertInfoPtr, attributePtr,
1473  TRUE, errorLocus, errorType ) ) )
1474  return( CRYPT_ERROR_INVALID );
1475  attributePtr = findAttributeField( issuerAttributes,
1478  if( attributePtr != NULL && \
1479  cryptStatusError( \
1480  checkNameConstraints( subjectCertInfoPtr, attributePtr,
1481  FALSE, errorLocus, errorType ) ) )
1482  return( CRYPT_ERROR_INVALID );
1483  }
1484 
1485  /* If there's a policy constraint present and the skip count is set to
1486  zero (i.e. the constraint applies to the current certificate) check
1487  the issuer constraints against the subject */
1488  status = getAttributeFieldValue( issuerAttributes,
1490  CRYPT_ATTRIBUTE_NONE, &value );
1491  if( cryptStatusOK( status ) && value <= 0 )
1492  {
1493  POLICY_TYPE policyType = POLICY_SUBJECT;
1494 
1495  /* Check whether use of the the wildcard anyPolicy has been
1496  disallowed */
1497  attributePtr = findAttribute( issuerCertInfoPtr->attributes,
1499  TRUE );
1500  if( attributePtr != NULL && \
1501  cryptStatusOK( getAttributeDataValue( attributePtr, \
1502  &value ) ) && \
1503  value <= 0 )
1504  policyType = POLICY_SUBJECT_SPECIFIC;
1505 
1506  /* Apply the appropriate policy constraint */
1507  status = checkPolicyConstraints( subjectCertInfoPtr,
1508  issuerAttributes, policyType,
1509  NULL, 0, FALSE, errorLocus,
1510  errorType );
1511  if( cryptStatusError( status ) )
1512  return( status );
1513  }
1514 #endif /* USE_CERTLEVEL_PKIX_FULL */
1515 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
1516 
1517  if( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )
1518  subjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;
1519  return( CRYPT_OK );
1520  }
1521 #endif /* USE_CERTIFICATES */