cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
chk_use.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Certificate Usage Checking Routines *
4 * Copyright Peter Gutmann 1997-2008 *
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 #ifdef USE_CERTIFICATES
15 
16 /****************************************************************************
17 * *
18 * ExtKeyUsage to Key Usage Routines *
19 * *
20 ****************************************************************************/
21 
22 /* The following keyUsage settings are used based on extendedKeyUsage and
23  Netscape key usage extensions. In the following 'Y' = required, 'w' =
24  written but apparently not required, 'S' = for signature keys only, 'E' =
25  for encryption keys only, 'KA' = for key agreement keys only.
26 
27  dig non key dat key cer crl enc dec
28  sig rep enc enc agt sig sig onl onl
29  PKIX: -----------------------------------
30  serverAuth S E KA [1]
31  clientAuth S
32  codeSign Y
33  email Y Y E
34  ipsecEndSys S E KA
35  ipsecTunnel S E KA
36  ipsecUser S E KA
37  timeStamping Y Y
38  ocsp Y
39  directoryService ?
40  MS: -----------------------------------
41  individualCodeSign Y
42  commercialCodeSign Y
43  ctlSign Y
44  tsa Y
45  sgc E
46  encryptedFS E
47  NS: -----------------------------------
48  sgc E
49  NS extensions: -----------------------------------
50  sslClient Y
51  sslServer S E [1]
52  sMime S E
53  objectSign Y
54  sslCA Y w
55  sMimeCA Y w
56  objectSignCA Y w
57  Verisign: -----------------------------------
58  sgcCA Y w
59  -----------------------------------
60  dig non key dat key cer crl enc dec
61  sig rep enc enc agt sig sig onl onl
62 
63  [1] These keys need to potentially perform both decryption for RSA key
64  transport and signing for authenticating DH key agreement */
65 
66 /* Mask for key usage types that we don't check for consistency against
67  extended key usages. The two CA usages don't occur in extended key usage,
68  and no-one can agree on what non-repudiation is supposed to mean */
69 
70 #define USAGE_MASK_NONRELEVANT ( CRYPT_KEYUSAGE_NONREPUDIATION | \
71  CRYPT_KEYUSAGE_KEYCERTSIGN | \
72  CRYPT_KEYUSAGE_CRLSIGN )
73 
74 /* Flags to denote the algorithm type */
75 
76 #define ALGO_TYPE_NONE 0
77 #define ALGO_TYPE_SIGN 1
78 #define ALGO_TYPE_CRYPT 2
79 #define ALGO_TYPE_KEYAGREEMENT 4
80 #define ALGO_TYPE_FLAG_NONE 0 /* Defines for range checking */
81 #define ALGO_TYPE_FLAG_MAX 0x07
82 
83 /* Table mapping extended key usage values to key usage flags */
84 
85 typedef struct {
86  const CRYPT_ATTRIBUTE_TYPE usageType;
87  const int keyUsageFlags;
88  } EXT_USAGE_INFO;
89 
90 static const EXT_USAGE_INFO FAR_BSS extendedUsageInfo[] = {
91  { CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING,/* individualCodeSigning */
93  { CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING,/* commercialCodeSigning */
95  { CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING,/* certTrustListSigning */
97  { CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING, /* timeStampSigning */
99  { CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO, /* serverGatedCrypto */
101  { CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM, /* encrypedFileSystem */
103  { CRYPT_CERTINFO_EXTKEY_SERVERAUTH, /* serverAuth */
105  { CRYPT_CERTINFO_EXTKEY_CLIENTAUTH, /* clientAuth */
107  { CRYPT_CERTINFO_EXTKEY_CODESIGNING, /* codeSigning */
109  { CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION, /* emailProtection */
110  KEYUSAGE_SIGN },
111  { CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM, /* ipsecEndSystem */
113  { CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL, /* ipsecTunnel */
115  { CRYPT_CERTINFO_EXTKEY_IPSECUSER, /* ipsecUser */
117  { CRYPT_CERTINFO_EXTKEY_TIMESTAMPING, /* timeStamping */
118  KEYUSAGE_SIGN },
119  { CRYPT_CERTINFO_EXTKEY_OCSPSIGNING, /* ocspSigning */
121  { CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE, /* directoryService */
123  { CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO, /* serverGatedCrypto */
125  { CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA,/* serverGatedCrypto CA */
126  KEYUSAGE_CA },
128  };
129 
130 #ifdef USE_CERT_OBSOLETE
131 
132 /* Table mapping Netscape certificate-type flags to extended key usage
133  flags */
134 
135 typedef struct {
136  const int certType;
137  const int keyUsageFlags;
138  } NS_CERT_TYPE_INFO;
139 
140 static const NS_CERT_TYPE_INFO FAR_BSS nsCertTypeInfo[] = {
151  KEYUSAGE_CA },
153  KEYUSAGE_CA },
155  KEYUSAGE_CA },
156  { 0, 0 }, { 0, 0 }
157  };
158 #endif /* USE_CERT_OBSOLETE */
159 
160 /* Build up key usage flags consistent with the extended key usage purpose.
161  We don't have to perform any special-case handling for
162  anyExtendedKeyUsage (added in RFC 3280, section 4.2.1.13) since it's a
163  no-op extension whose presence is the equivalent of adding "|| TRUE" to
164  an expression */
165 
166 CHECK_RETVAL_RANGE( MAX_ERROR, CRYPT_KEYUSAGE_MAX ) STDC_NONNULL_ARG( ( 1, 3 ) ) \
167 static int getExtendedKeyUsageFlags( const ATTRIBUTE_PTR *attributes,
168  IN_FLAGS( ALGO_TYPE ) const int algorithmType,
169  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
170  CRYPT_ATTRIBUTE_TYPE *errorLocus )
171  {
172  int keyUsage = 0, i;
173 
174  assert( isReadPtr( attributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
175  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
176 
177  REQUIRES( algorithmType > ALGO_TYPE_FLAG_NONE && \
178  algorithmType < ALGO_TYPE_FLAG_MAX );
179 
180  /* Most certificates don't contain an extendedKeyUsage extension so
181  rather than iterating through a long list of non-present attribute
182  fields we perform an early-out check to see whether there's actually
183  anything to do */
185  return( 0 );
186 
187  /* There's an extendedKeyUsage extension present, build up the key usage
188  flags for it */
189  for( i = 0; extendedUsageInfo[ i ].usageType != CRYPT_ATTRIBUTE_NONE && \
190  i < FAILSAFE_ARRAYSIZE( extendedUsageInfo, EXT_USAGE_INFO );
191  i++ )
192  {
193  int extendedUsage = 0;
194 
195  /* If this usage isn't present, continue */
196  if( !checkAttributeFieldPresent( attributes,
197  extendedUsageInfo[ i ].usageType ) )
198  continue;
199 
200  /* If the usage is consistent with the algorithm type, add it */
201  if( algorithmType & ALGO_TYPE_SIGN )
202  {
203  extendedUsage |= \
204  extendedUsageInfo[ i ].keyUsageFlags & ( KEYUSAGE_SIGN | \
205  KEYUSAGE_CA );
206  }
207  if( algorithmType & ALGO_TYPE_CRYPT )
208  {
209  extendedUsage |= \
210  extendedUsageInfo[ i ].keyUsageFlags & KEYUSAGE_CRYPT;
211  }
212  if( algorithmType & ALGO_TYPE_KEYAGREEMENT )
213  {
214  extendedUsage |= \
215  extendedUsageInfo[ i ].keyUsageFlags & KEYUSAGE_KEYAGREEMENT;
216  }
217 
218  /* If there's no key usage consistent with the extended usage and the
219  extended usage isn't some special-case usage, return an error */
220  if( extendedUsage == 0 && extendedUsageInfo[ i ].keyUsageFlags != 0 )
221  {
222  *errorLocus = extendedUsageInfo[ i ].usageType;
223  return( CRYPT_ERROR_INVALID );
224  }
225 
226  keyUsage |= extendedUsage;
227  }
228  ENSURES( i < FAILSAFE_ARRAYSIZE( extendedUsageInfo, EXT_USAGE_INFO ) );
229 
230  return( keyUsage );
231  }
232 
233 #ifdef USE_CERT_OBSOLETE
234 
235 /* Build up key usage flags consistent with the Netscape certificate-type
236  purpose */
237 
238 CHECK_RETVAL_RANGE( MAX_ERROR, CRYPT_KEYUSAGE_MAX ) STDC_NONNULL_ARG( ( 1, 3 ) ) \
239 static int getNetscapeCertTypeFlags( const ATTRIBUTE_PTR *attributes,
240  IN_FLAGS( ALGO_TYPE ) const int algorithmType,
241  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
242  CRYPT_ATTRIBUTE_TYPE *errorLocus )
243  {
244  int nsCertType, keyUsage = 0, i, status;
245 
246  assert( isReadPtr( attributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );
247  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
248 
249  REQUIRES( algorithmType > ALGO_TYPE_FLAG_NONE && \
250  algorithmType < ALGO_TYPE_FLAG_MAX );
251 
252  /* If there isn't a Netscape certificate-type extension present, exit */
253  status = getAttributeFieldValue( attributes, CRYPT_CERTINFO_NS_CERTTYPE,
254  CRYPT_ATTRIBUTE_NONE, &nsCertType );
255  if( cryptStatusError( status ) )
256  return( 0 );
257 
258  /* The Netscape certificate-type value is a bitfield containing the
259  different certificate types. For each certificate-type flag that's
260  set we set the corresponding keyUsage flags */
261  for( i = 0; nsCertTypeInfo[ i ].certType && \
262  i < FAILSAFE_ARRAYSIZE( nsCertTypeInfo, NS_CERT_TYPE_INFO ); i++ )
263  {
264  int nsUsage = 0;
265 
266  /* If this isn't the currently-selected certificate type, continue */
267  if( !( nsCertType & nsCertTypeInfo[ i ].certType ) )
268  continue;
269 
270  /* If the usage is consistent with the algorithm type, add it */
271  if( algorithmType & ALGO_TYPE_SIGN )
272  nsUsage |= nsCertTypeInfo[ i ].keyUsageFlags & ( KEYUSAGE_SIGN | \
273  KEYUSAGE_CA );
274  if( algorithmType & ALGO_TYPE_CRYPT )
275  nsUsage |= nsCertTypeInfo[ i ].keyUsageFlags & KEYUSAGE_CRYPT;
276  if( algorithmType & ALGO_TYPE_KEYAGREEMENT )
277  nsUsage |= nsCertTypeInfo[ i ].keyUsageFlags & KEYUSAGE_KEYAGREEMENT;
278 
279  /* If there's no key usage consistent with the Netscape
280  certificate-type, return an error */
281  if( nsUsage == 0 )
282  {
283  *errorLocus = CRYPT_CERTINFO_NS_CERTTYPE;
284  return( CRYPT_ERROR_INVALID );
285  }
286 
287  keyUsage |= nsUsage;
288  }
289  ENSURES( i < FAILSAFE_ARRAYSIZE( nsCertTypeInfo, NS_CERT_TYPE_INFO ) );
290 
291  return( keyUsage );
292  }
293 #endif /* USE_CERT_OBSOLETE */
294 
295 /* Get key usage flags for a certificate based on its extended key
296  usage/Netscape cert-type. Returns 0 if no extKeyUsage/cert-type values
297  present */
298 
299 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
300 int getKeyUsageFromExtKeyUsage( const CERT_INFO *certInfoPtr,
301  OUT_FLAGS_Z( CRYPT_KEYUSAGE ) int *keyUsage,
302  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
303  CRYPT_ATTRIBUTE_TYPE *errorLocus,
304  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
305  CRYPT_ERRTYPE_TYPE *errorType )
306  {
307  int algorithmType = ALGO_TYPE_NONE, localKeyUsage;
308 
309  assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
310  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
311  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
312 
313  /* Clear return value */
314  *keyUsage = CRYPT_KEYUSAGE_NONE;
315 
316  /* If there are no attributes present there's nothing to do */
317  if( certInfoPtr->attributes == NULL )
318  return( CRYPT_OK );
319 
320  /* Determine the possible algorithm usage type(s) */
321  if( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )
322  algorithmType |= ALGO_TYPE_CRYPT;
323  if( isSigAlgo( certInfoPtr->publicKeyAlgo ) )
324  algorithmType |= ALGO_TYPE_SIGN;
325  if( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )
326  algorithmType |= ALGO_TYPE_KEYAGREEMENT;
327  ENSURES( algorithmType != ALGO_TYPE_NONE );
328 
329  /* Get the key usage flags for the given extended/Netscape usage type(s)
330  and algorithm type */
331  localKeyUsage = getExtendedKeyUsageFlags( certInfoPtr->attributes,
332  algorithmType, errorLocus );
333 #ifdef USE_CERT_OBSOLETE
334  localKeyUsage |= getNetscapeCertTypeFlags( certInfoPtr->attributes,
335  algorithmType, errorLocus );
336 #endif /* USE_CERT_OBSOLETE */
337  if( cryptStatusError( localKeyUsage ) )
338  {
339  /* We only have to set the error type at this point since the error
340  locus was set when we got the key usage flags */
341  *errorType = CRYPT_ERRTYPE_CONSTRAINT;
342  return( CRYPT_ERROR_INVALID );
343  }
344  *keyUsage = localKeyUsage;
345 
346  return( CRYPT_OK );
347  }
348 
349 /****************************************************************************
350 * *
351 * Check Key/Certificate Usage *
352 * *
353 ****************************************************************************/
354 
355 /* Check that a certificate/key is valid for a particular purpose. This
356  function is used in one of two ways:
357 
358  1. Check that a key can be used for a particular purpose, regardless of
359  whether the certificate extensions that define the usage make any
360  sense or not. This is used when performing an object usage check
361  such as whether a key can be used for signing or encryption.
362 
363  2. Check that the key usage is consistent. This is used when performing
364  a general certificate validity check, indicated by setting the
365  CHECKKEY_FLAG_GENCHECK check flag.
366 
367  Processing is done in three phases:
368 
369  1. Fix up usage flags at lower compliance levels if necessary.
370  2. Check for strict usability even if the flags don't make sense.
371  3. Check consistency as per the PKIX and X.509 specs */
372 
373 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5, 6 ) ) \
374 int checkKeyUsage( const CERT_INFO *certInfoPtr,
375  IN_FLAGS_Z( CHECKKEY ) const int flags,
376  IN_FLAGS_Z( CRYPT_KEYUSAGE ) const int specificUsage,
379  const int complianceLevel,
380  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
381  CRYPT_ATTRIBUTE_TYPE *errorLocus,
382  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
383  CRYPT_ERRTYPE_TYPE *errorType )
384  {
386  const BOOLEAN isGeneralCheck = ( flags & CHECKKEY_FLAG_GENCHECK ) ? \
387  TRUE : FALSE;
388  BOOLEAN keyUsageCritical = 0, isCA = FALSE;
389  const int trustedUsage = \
390  ( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
392  certInfoPtr->cCertCert->trustedUsage : CRYPT_UNUSED;
393  int keyUsage, rawKeyUsage, extKeyUsage, rawExtKeyUsage, caKeyUsage;
394  int value, status;
395 
396  assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
397  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
398  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
399 
400  REQUIRES( flags >= CHECKKEY_FLAG_NONE && \
401  flags < CHECKKEY_FLAG_MAX );
402  REQUIRES( specificUsage >= CRYPT_KEYUSAGE_FLAG_NONE && \
403  specificUsage < CRYPT_KEYUSAGE_FLAG_MAX );
404  REQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \
405  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );
406  REQUIRES( ( ( flags & CHECKKEY_FLAG_CA ) && \
407  ( specificUsage & ( CRYPT_KEYUSAGE_KEYCERTSIGN | \
408  CRYPT_KEYUSAGE_CRLSIGN ) ) ) || \
409  ( !( flags & CHECKKEY_FLAG_CA ) && \
410  ( ( specificUsage & ( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
413  ( specificUsage == CRYPT_KEYUSAGE_NONE ) ) ) );
414 
415  /* There is one universal case in which a key is regarded as invalid for
416  the requested use and that's when it's explicitly not trusted for the
417  purpose. Note that this check (in oblivious mode) differs slightly
418  from the later check (in reduced mode or higher) in that in oblivious
419  mode we ignore the certificate's actual key usage and check only the
420  requested against trusted usage */
421  if( specificUsage != CRYPT_KEYUSAGE_NONE && \
422  trustedUsage != CRYPT_UNUSED && !( trustedUsage & specificUsage ) )
423  {
424  /* The issuer is explicitly not trusted to perform the requested
425  operation */
428  return( CRYPT_ERROR_INVALID );
429  }
430 
431  /* If we're running in oblivious mode there's nothing else to check */
432  if( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )
433  return( CRYPT_OK );
434 
435  /* Phase 1: Fix up values if required */
436 
437  /* Obtain assorted certificate information */
438  status = getAttributeFieldValue( certInfoPtr->attributes,
440  CRYPT_ATTRIBUTE_NONE, &value );
441  if( cryptStatusOK( status ) && value > 0 )
442  isCA = TRUE;
443  status = getKeyUsageFromExtKeyUsage( certInfoPtr, &extKeyUsage,
444  errorLocus, errorType );
445  if( cryptStatusError( status ) )
446  return( status );
447 
448  /* If it's a v1 self-signed certificate then the CA status and key usage
449  are implicit/undefined */
450  if( certInfoPtr->version == 1 && \
451  ( certInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
452  {
453  /* If it's claiming to be a CA certificate by virtue of being a v1
454  self-signed certificate then there can't be any v3 CA attributes
455  (or any v3 attributes for that matter) present. Unfortunately we
456  can't just check for the complete non-presence of attributes
457  because the certificate-import code will have converted an email
458  address in the DN into the appropriate altName component,
459  creating at least one valid (in this case) attribute */
460  if( isGeneralCheck && \
461  ( checkAttributePresent( certInfoPtr->attributes,
463  checkAttributePresent( certInfoPtr->attributes,
465  extKeyUsage != 0 ) )
466  {
469  return( CRYPT_ERROR_INVALID );
470  }
471 
472  /* It's a v1 self-signed certificate with no keyUsage present, don't
473  perform any usage-specific checks */
474  return( CRYPT_OK );
475  }
476 
477  /* Get the certificate's keyUsage. If we're running at a reduced
478  compliance level and the CA flag is set and keyUsage isn't or vice
479  versa we synthesise the required value from the other value in order
480  to pass the checks that follow */
481  attributePtr = findAttributeField( certInfoPtr->attributes,
484  if( attributePtr != NULL )
485  {
486  status = getAttributeDataValue( attributePtr, &keyUsage );
487  if( cryptStatusError( status ) )
488  return( status );
489  keyUsageCritical = \
490  checkAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_CRITICAL );
491 
492  /* If the CA key usages are set make sure that the CA flag is set in
493  an appropriate manner */
494  if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD && \
495  ( keyUsage & specificUsage & KEYUSAGE_CA ) && !isCA )
496  isCA = TRUE;
497  }
498  else
499  {
500  /* There's no keyUsage information present, start with no usage
501  available */
502  keyUsage = 0;
503 
504  /* If the CA flag is set make sure that the keyUsage is set in an
505  appropriate manner */
506  if( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && isCA )
507  keyUsage = KEYUSAGE_CA;
508 
509  /* Some broken certificates don't have any keyUsage present, which
510  is meant to imply that the certificate can be used for any usage
511  that the key is capable of modulo the magic usages keyCertSign
512  and crlSign. To handle this we map the algorithm type to the
513  matching usage types. In theory the usage may be further
514  modified by the certificate policy, extKeyUsage, and who knows
515  what else but in the presence of a certificate like that it's up
516  to the user to sort out what they want to do with it.
517 
518  Some even more broken certificates indicate their usage via a
519  Netscape key usage (even though they use X.509 flags everywhere
520  else - insanes numquam moriuntur) which means that we fail them
521  if we're strictly applying the PKIX requirements at a higher
522  compliance level. At this lower level fixAttributes() will have
523  mapped the Netscape usage to the equivalent X.509 usage so
524  there's always a keyUsage present */
525  if( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )
526  keyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;
527  if( isSigAlgo( certInfoPtr->publicKeyAlgo ) )
528  keyUsage |= KEYUSAGE_SIGN;
529  if( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )
530  keyUsage |= CRYPT_KEYUSAGE_KEYAGREEMENT;
531  }
532  caKeyUsage = keyUsage & KEYUSAGE_CA;
533 
534  /* Apply the trusted-usage restrictions if necessary */
535  rawKeyUsage = keyUsage;
536  rawExtKeyUsage = extKeyUsage;
537  if( trustedUsage != CRYPT_UNUSED )
538  {
539  keyUsage &= trustedUsage;
540  extKeyUsage &= trustedUsage;
541  }
542 
543  /* Phase 2: Strict usability check */
544 
545  /* If we're looking for a CA certificate make sure that the
546  basicConstraints CA flag is set and the keyUsage indicates a CA usage
547  (PKIX sections 4.2.1.3 and 4.2.1.10). RFC 2459 left this open, it
548  was made explicit in RFC 3280. If we're running at a reduced
549  compliance level then the settings will have been adjusted as
550  required earlier on */
551  if( flags & CHECKKEY_FLAG_CA )
552  {
553  if( !isCA )
554  {
556  return( CRYPT_ERROR_INVALID );
557  }
558  if( !( caKeyUsage & specificUsage ) )
559  {
562  return( CRYPT_ERROR_INVALID );
563  }
564  }
565 
566  /* There is one universal case in which a key is regarded as invalid for
567  the requested use and that's when it's explicitly not trusted for the
568  purpose */
569  if( specificUsage != CRYPT_KEYUSAGE_NONE && \
570  trustedUsage != CRYPT_UNUSED && !( specificUsage & keyUsage ) )
571  {
574  return( CRYPT_ERROR_INVALID );
575  }
576 
577  /* If we're doing a reduced level of checking, we're done */
578  if( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )
579  return( CRYPT_OK );
580 
581  /* If we're just performing a key-usability check rather than a general
582  check that the key usage is in order, we're done */
583  if( !isGeneralCheck )
584  return( CRYPT_OK );
585 
586  /* Phase 3: Consistency check */
587 
588  /* If the CA flag is set make sure that there's a keyUsage with one of
589  the CA usages present. Conversely if there are CA key usages
590  present make sure that the CA flag is set. In other words this
591  check tests for an XOR relation, ( CA && kU ) || ( !CA && !kU ).
592 
593  The CA flag is actually a leftover from an early v3 certificate
594  concept and is made entirely redundant by the keyUsage flags but we
595  have to check it regardless (PKIX sections 4.2.1.3 and 4.2.1.10).
596  RFC 2459 left this open, it was made explicit in RFC 3280 */
597  if( isCA )
598  {
599  /* It's a CA certificate, make sure that a CA keyUsage is set */
600  if( !( caKeyUsage | extKeyUsage ) )
601  {
604  return( CRYPT_ERROR_INVALID );
605  }
606  }
607  else
608  {
609  /* It's a non-CA certificate, make sure that no CA keyUsage is set */
610  if( ( caKeyUsage | extKeyUsage ) & KEYUSAGE_CA )
611  {
613  return( CRYPT_ERROR_INVALID );
614  }
615  }
616 
617  /* Check and enforce the keyUsage if required (PKIX section 4.2.1.3).
618  RFC 2459 included some waffly text about critical vs. non-critical
619  usage, RFC 3280 made this explicit regardless of criticality */
620  if( specificUsage != CRYPT_KEYUSAGE_NONE )
621  {
622  BOOLEAN usageOK = FALSE;
623 
624  /* If it's a key agreement usage the checking gets a bit complex
625  (PKIX-ALGS section 2.3.3), we have to make sure that it's both a
626  permitted usage and not an excluded usage */
627  if( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \
628  ( specificUsage & ( CRYPT_KEYUSAGE_ENCIPHERONLY | \
630  {
631  const int excludedUsage = \
632  ( specificUsage & CRYPT_KEYUSAGE_ENCIPHERONLY ) ? \
634 
635  if( ( keyUsage & specificUsage ) && !( keyUsage & excludedUsage ) )
636  usageOK = TRUE;
637  }
638  else
639  {
640  /* Conventional usage flag, do a straight check */
641  if( keyUsage & specificUsage )
642  usageOK = TRUE;
643  }
644  if( !usageOK )
645  {
646  setErrorValues( ( rawKeyUsage & specificUsage ) ? \
650  return( CRYPT_ERROR_INVALID );
651  }
652  }
653 
654  /* Switch back to the original usage values (before adjustment by
655  trusted-usage values) because after this point we're performing
656  consistency checks on the values and need to check all of the bits */
657  keyUsage = rawKeyUsage;
658  extKeyUsage = rawExtKeyUsage;
659 
660  /* Make sure that mutually exclusive flags aren't set (RFC 3279 section
661  2.3.3) */
662  if( ( keyUsage & CRYPT_KEYUSAGE_ENCIPHERONLY ) && \
663  ( keyUsage & CRYPT_KEYUSAGE_DECIPHERONLY ) )
664  {
666  return( CRYPT_ERROR_INVALID );
667  }
668 
669  /* Make sure that the keyUsage flags represent capabilities that the
670  algorithm is actually capable of. RFC 2459 included some waffly text
671  about critical vs. non-critical usage, RFC 3280 made this explicit
672  regardless of criticality, although the details were actually moved
673  into RFC 3279, which specifies the algorithms used in PKIX */
674  if( ( ( ( keyUsage & KEYUSAGE_CRYPT ) && \
675  !isCryptAlgo( certInfoPtr->publicKeyAlgo ) ) || \
676  ( ( keyUsage & ( KEYUSAGE_SIGN | KEYUSAGE_CA ) ) && \
677  !isSigAlgo( certInfoPtr->publicKeyAlgo ) ) || \
678  ( ( keyUsage & KEYUSAGE_KEYAGREEMENT ) && \
679  !isKeyxAlgo( certInfoPtr->publicKeyAlgo ) ) ) )
680  {
682  return( CRYPT_ERROR_INVALID );
683  }
684 
685  /* Mask out any non-relevant usages (e.g. certificate signing, which
686  doesn't occur in extended key usages and has already been checked
687  above) */
688  keyUsage &= ~USAGE_MASK_NONRELEVANT;
689  extKeyUsage &= ~USAGE_MASK_NONRELEVANT;
690 
691 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
692  /* If we're being asked to check for private-key constraints, check and
693  enforce the privateKeyUsage attribute if there's one present */
694  if( ( flags & CHECKKEY_FLAG_PRIVATEKEY ) && \
695  checkAttributePresent( certInfoPtr->attributes,
697  {
698  const time_t currentTime = getTime();
699  time_t certTime;
700 
701  if( currentTime <= MIN_TIME_VALUE )
702  {
703  /* Time is broken, we can't reliably check for expiry times */
706  return( CRYPT_ERROR_INVALID );
707  }
708  status = getAttributeFieldTime( certInfoPtr->attributes,
710  CRYPT_ATTRIBUTE_NONE, &certTime );
711  if( cryptStatusOK( status ) && currentTime < certTime )
712  {
715  return( CRYPT_ERROR_INVALID );
716  }
717  status = getAttributeFieldTime( certInfoPtr->attributes,
719  CRYPT_ATTRIBUTE_NONE, &certTime );
720  if( cryptStatusOK( status ) && currentTime > certTime )
721  {
724  return( CRYPT_ERROR_INVALID );
725  }
726  }
727 
728  /* If there's no key usage based on extended key usage present or we're
729  not doing at least partial PKIX checking, there's nothing further to
730  check */
731  if( !extKeyUsage || complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
732  return( CRYPT_OK );
733 
734  /* If the CA key usages are set then an encryption key usage shouldn't
735  be set (RFC 3279 section 2.3.1) */
736  if( isCA && ( keyUsage & extKeyUsage & KEYUSAGE_CRYPT ) )
737  {
739  return( CRYPT_ERROR_INVALID );
740  }
741 
742  /* If the usage and extended usage are critical (but only if both are
743  critical, because PKIX says so) make sure that the given usage is
744  consistent with the required usage (PKIX section 4.2.1.13). To
745  perform this check we first check for situations where we *don't*
746  have to perform the check and only if none of these occur do we
747  perform the actual check.
748 
749  Checking whether the extended usage is critical is a bit nontrivial,
750  we have to check each possible extended usage since only one of them
751  may be present so we check the criticality of the basic key usage
752  first to allow quick short-circuit evaluation.
753 
754  In addition to the explicit criticality checks we also perform an
755  implicit check based on whether this is a freshly-generated, as-yet-
756  unsigned cryptlib certificate. This is done for two reasons, firstly
757  because an unsigned certificate won't have had the criticality flag
758  set by the signing/encoding process so the extension always appears
759  non-critical and secondly because we don't want cryptlib to generate
760  inconsistent certificates, whether the extensions are marked critical
761  or not (cryptlib always makes the keyUsage critical so at least for
762  key usage it's no change from the standard behaviour) */
763  if( certInfoPtr->certificate != NULL )
764  {
765  int attributeID;
766 
767  /* If there's no critical key usage present we can exit without
768  performing further checks */
769  if( !keyUsageCritical )
770  return( CRYPT_OK );
771 
772  /* If we find an extended key usage and it's non-critical (which
773  means that all extended usages are non-critical since they're
774  all in the same extension), return */
775  for( attributeID = CRYPT_CERTINFO_EXTKEYUSAGE + 1;
776  attributeID < CRYPT_CERTINFO_NS_CERTTYPE; attributeID++ )
777  {
778  attributePtr = findAttributeField( certInfoPtr->attributes,
779  attributeID, CRYPT_ATTRIBUTE_NONE );
780  if( attributePtr != NULL && \
781  !checkAttributeProperty( attributePtr,
783  return( CRYPT_OK );
784  }
785  }
786 
787  /* Make sure that the extended key usage-based key usage is consistent
788  with the actual key usage */
789  if( ( keyUsage & extKeyUsage ) != extKeyUsage )
790  {
792  return( CRYPT_ERROR_INVALID );
793  }
794 
795  /* If the encipherOnly or decipherOnly bits are set then the
796  keyAgreement bit most also be set (PKIX section 4.2.1.3). Actually
797  the spec merely says "undefined" but we interpret this to mean that
798  they should be consistent. This situation occurs because the
799  encipher/decipher-only usages were tacked on as modifiers long after
800  keyAgreement was defined and make it entirely redundant, in the same
801  way that the CA keyUsages make the basicConstraints CA flag
802  redundant */
803  if( ( keyUsage & ( CRYPT_KEYUSAGE_ENCIPHERONLY | \
804  CRYPT_KEYUSAGE_DECIPHERONLY ) ) && \
805  !( keyUsage & CRYPT_KEYUSAGE_KEYAGREEMENT ) )
806  {
808  return( CRYPT_ERROR_INVALID );
809  }
810 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
811 
812  return( CRYPT_OK );
813  }
814 #endif /* USE_CERTIFICATES */