1 /****************************************************************************
2 * *
3 * Certificate Signature Checking Routines *
4 * Copyright Peter Gutmann 1997-2013 *
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 * Utility Routines *
19 * *
20 ****************************************************************************/
21
22 #if defined( USE_CERTREV ) || defined( USE_CERTVAL )
23
24 /* Generate an issuerID, a SHA-1 hash of the issuerAndSerialNumber needed
25 when storing/retrieving a certificate to/from a database keyset, which
26 can't handle the awkward heirarchical IDs usually used in certificates.
27 This is created by encoding the DN and serial number */
28
29 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
generateCertID(IN_BUFFER (dnLength)const void * dn,IN_LENGTH_SHORT const int dnLength,IN_BUFFER (serialNumberLength)const void * serialNumber,IN_LENGTH_SHORT const int serialNumberLength,OUT_BUFFER_FIXED_C (KEYID_SIZE)BYTE * certID,IN_LENGTH_FIXED (KEYID_SIZE)const int certIdLength)30 static int generateCertID( IN_BUFFER( dnLength ) const void *dn,
31 IN_LENGTH_SHORT const int dnLength,
32 IN_BUFFER( serialNumberLength ) \
33 const void *serialNumber,
34 IN_LENGTH_SHORT const int serialNumberLength,
35 OUT_BUFFER_FIXED_C( KEYID_SIZE ) BYTE *certID,
36 IN_LENGTH_FIXED( KEYID_SIZE ) const int certIdLength )
37 {
38 HASH_FUNCTION hashFunction;
39 HASHINFO hashInfo;
40 STREAM stream;
41 BYTE buffer[ MAX_SERIALNO_SIZE + 8 + 8 ];
42 int status;
43
44 assert( isReadPtr( dn, dnLength ) );
45 assert( isReadPtr( serialNumber, serialNumberLength ) && \
46 serialNumberLength > 0 && \
47 serialNumberLength <= MAX_SERIALNO_SIZE );
48 assert( isWritePtr( certID, certIdLength ) );
49
50 REQUIRES( serialNumberLength > 0 && \
51 serialNumberLength <= MAX_SERIALNO_SIZE );
52 REQUIRES( certIdLength == KEYID_SIZE );
53
54 /* Clear return value */
55 memset( certID, 0, min( 16, certIdLength ) );
56
57 /* Get the hash algorithm information */
58 getHashParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, NULL );
59
60 /* Write the relevant information to a buffer and hash the data to get
61 the ID:
62
63 SEQUENCE {
64 issuer DN,
65 serial INTEGER
66 } */
67 sMemOpen( &stream, buffer, MAX_SERIALNO_SIZE + 8 );
68 status = writeSequence( &stream,
69 dnLength + sizeofInteger( serialNumber, \
70 serialNumberLength ) );
71 if( cryptStatusError( status ) )
72 {
73 sMemClose( &stream );
74 return( status );
75 }
76 hashFunction( hashInfo, NULL, 0, buffer, stell( &stream ),
77 HASH_STATE_START );
78 hashFunction( hashInfo, NULL, 0, dn, dnLength, HASH_STATE_CONTINUE );
79 sseek( &stream, 0 );
80 status = writeInteger( &stream, serialNumber, serialNumberLength,
81 DEFAULT_TAG );
82 if( cryptStatusOK( status ) )
83 {
84 hashFunction( hashInfo, certID, certIdLength, buffer,
85 stell( &stream ), HASH_STATE_END );
86 }
87 sMemClose( &stream );
88
89 return( status );
90 }
91 #endif /* USE_CERTREV || USE_CERTVAL */
92
93 /****************************************************************************
94 * *
95 * Validity/Revocation Checking *
96 * *
97 ****************************************************************************/
98
99 #if defined( USE_CERTREV ) || defined( USE_CERTVAL )
100
101 /* Check a certificate using an RTCS or OCSP responder */
102
103 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkResponder(INOUT CERT_INFO * certInfoPtr,IN_HANDLE const CRYPT_SESSION iCryptSession)104 static int checkResponder( INOUT CERT_INFO *certInfoPtr,
105 IN_HANDLE const CRYPT_SESSION iCryptSession )
106 {
107 CRYPT_CERTIFICATE cryptResponse DUMMY_INIT;
108 MESSAGE_CREATEOBJECT_INFO createInfo;
109 int sessionType, status;
110
111 assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
112
113 REQUIRES( isHandleRangeValid( iCryptSession) );
114
115 status = krnlSendMessage( iCryptSession, IMESSAGE_GETATTRIBUTE,
116 &sessionType, CRYPT_IATTRIBUTE_SUBTYPE );
117 if( cryptStatusError( status ) )
118 return( status );
119
120 REQUIRES( ( sessionType == SUBTYPE_SESSION_RTCS ) || \
121 ( sessionType == SUBTYPE_SESSION_OCSP ) );
122
123 /* Create the request, add the certificate, and add the request to the
124 session */
125 setMessageCreateObjectInfo( &createInfo,
126 ( sessionType == SUBTYPE_SESSION_RTCS ) ? \
127 CRYPT_CERTTYPE_RTCS_REQUEST : \
128 CRYPT_CERTTYPE_OCSP_REQUEST );
129 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
130 &createInfo, OBJECT_TYPE_CERTIFICATE );
131 if( cryptStatusError( status ) )
132 return( status );
133 status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
134 &certInfoPtr->objectHandle, CRYPT_CERTINFO_CERTIFICATE );
135 if( cryptStatusOK( status ) )
136 status = krnlSendMessage( iCryptSession, IMESSAGE_SETATTRIBUTE,
137 &createInfo.cryptHandle, CRYPT_SESSINFO_REQUEST );
138 krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
139 if( cryptStatusError( status ) )
140 return( status );
141
142 /* Activate the session and get the response information */
143 status = krnlSendMessage( iCryptSession, IMESSAGE_SETATTRIBUTE,
144 MESSAGE_VALUE_TRUE, CRYPT_SESSINFO_ACTIVE );
145 if( cryptStatusOK( status ) )
146 status = krnlSendMessage( iCryptSession, IMESSAGE_GETATTRIBUTE,
147 &cryptResponse, CRYPT_SESSINFO_RESPONSE );
148 if( cryptStatusError( status ) )
149 return( status );
150 if( sessionType == SUBTYPE_SESSION_RTCS )
151 {
152 int certStatus;
153
154 status = krnlSendMessage( cryptResponse, IMESSAGE_GETATTRIBUTE,
155 &certStatus, CRYPT_CERTINFO_CERTSTATUS );
156 if( cryptStatusOK( status ) && \
157 ( certStatus != CRYPT_CERTSTATUS_VALID ) )
158 status = CRYPT_ERROR_INVALID;
159 }
160 else
161 {
162 int revocationStatus;
163
164 status = krnlSendMessage( cryptResponse, IMESSAGE_GETATTRIBUTE,
165 &revocationStatus,
166 CRYPT_CERTINFO_REVOCATIONSTATUS );
167 if( cryptStatusOK( status ) && \
168 ( revocationStatus != CRYPT_OCSPSTATUS_NOTREVOKED ) )
169 status = CRYPT_ERROR_INVALID;
170 }
171 krnlSendNotifier( cryptResponse, IMESSAGE_DECREFCOUNT );
172
173 return( status );
174 }
175
176 /* Check a certificate against a CRL stored in a keyset */
177
178 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkKeyset(INOUT CERT_INFO * certInfoPtr,IN_HANDLE const CRYPT_SESSION iCryptKeyset)179 static int checkKeyset( INOUT CERT_INFO *certInfoPtr,
180 IN_HANDLE const CRYPT_SESSION iCryptKeyset )
181 {
182 MESSAGE_KEYMGMT_INFO getkeyInfo;
183 BYTE issuerID[ KEYID_SIZE + 8 ];
184 int status;
185
186 assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
187
188 REQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
189 certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
190 certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
191 REQUIRES( isHandleRangeValid( iCryptKeyset ) );
192
193 /* Generate the issuerID for the certificate */
194 status = generateCertID( certInfoPtr->issuerDNptr,
195 certInfoPtr->issuerDNsize,
196 certInfoPtr->cCertCert->serialNumber,
197 certInfoPtr->cCertCert->serialNumberLength,
198 issuerID, KEYID_SIZE );
199 if( cryptStatusError( status ) )
200 return( status );
201
202 /* Check whether the object with this issuerID is present in the CRL.
203 Since all that we're interested in is a yes/no answer we tell the
204 keyset to perform a check only */
205 setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_ISSUERID, issuerID,
206 KEYID_SIZE, NULL, 0, KEYMGMT_FLAG_CHECK_ONLY );
207 status = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_GETKEY,
208 &getkeyInfo, KEYMGMT_ITEM_REVOCATIONINFO );
209 if( cryptStatusOK( status ) )
210 {
211 /* The certificate is present in the blacklist so it's an invalid
212 certificate */
213 return( CRYPT_ERROR_INVALID );
214 }
215 if( status == CRYPT_ERROR_NOTFOUND )
216 {
217 /* The certificate isn't present in the blacklist so it's not
218 revoked (although not necessarily valid either) */
219 return( CRYPT_OK );
220 }
221
222 /* Some other type of error occurred */
223 return( status );
224 }
225 #endif /* USE_CERTREV || USE_CERTVAL */
226
227 /****************************************************************************
228 * *
229 * Signature Checking Functions *
230 * *
231 ****************************************************************************/
232
233 /* Check a certificate object against a signing certificate object,
234 typically a certificate against an issuer certificate but also a self-
235 signed object like a certificate request against itself.
236
237 The trustAnchorCheck flag is used when we're checking an explicit trust
238 anchor, for which we only need to check the signature if it's self-signed.
239 The shortCircuitCheck flag is used when checking subject:issuer pairs
240 inside certificate chains, which have already been checked by the chain-
241 handling code so a full (re-)check isn't necessary any more. The
242 basicCheckDone flag is used if checkCertBasic() has already been done by
243 the caller (if we're coming from the certificate-chain code then we're
244 processing a certificate in the middle of the chain and it hasn't been
245 done yet, if we're coming from the standalone certificate-checking code
246 then it's already been done) */
247
248 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 8, 9 ) ) \
checkCertDetails(INOUT CERT_INFO * subjectCertInfoPtr,INOUT_OPT CERT_INFO * issuerCertInfoPtr,IN_HANDLE_OPT const CRYPT_CONTEXT iIssuerPubKey,IN_OPT const X509SIG_FORMATINFO * formatInfo,const BOOLEAN trustAnchorCheck,const BOOLEAN shortCircuitCheck,const BOOLEAN basicCheckDone,OUT_ENUM_OPT (CRYPT_ATTRIBUTE)CRYPT_ATTRIBUTE_TYPE * errorLocus,OUT_ENUM_OPT (CRYPT_ERRTYPE)CRYPT_ERRTYPE_TYPE * errorType)249 int checkCertDetails( INOUT CERT_INFO *subjectCertInfoPtr,
250 INOUT_OPT CERT_INFO *issuerCertInfoPtr,
251 IN_HANDLE_OPT const CRYPT_CONTEXT iIssuerPubKey,
252 IN_OPT const X509SIG_FORMATINFO *formatInfo,
253 const BOOLEAN trustAnchorCheck,
254 const BOOLEAN shortCircuitCheck,
255 const BOOLEAN basicCheckDone,
256 OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
257 CRYPT_ATTRIBUTE_TYPE *errorLocus,
258 OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
259 CRYPT_ERRTYPE_TYPE *errorType )
260 {
261 int status;
262
263 assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
264 assert( issuerCertInfoPtr == NULL || \
265 isWritePtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
266 assert( formatInfo == NULL || \
267 isReadPtr( formatInfo, sizeof( X509SIG_FORMATINFO ) ) );
268 assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
269 assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
270
271 REQUIRES( iIssuerPubKey == CRYPT_UNUSED || \
272 isHandleRangeValid( iIssuerPubKey ) );
273
274 /* Clear return values */
275 *errorLocus = CRYPT_ATTRIBUTE_NONE;
276 *errorType = CRYPT_ERRTYPE_NONE;
277
278 /* Perform a basic check for obvious invalidity issues if required */
279 if( !basicCheckDone && \
280 ( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
281 subjectCertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
282 subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) )
283 {
284 status = checkCertBasic( subjectCertInfoPtr );
285 if( cryptStatusError( status ) )
286 return( status );
287 }
288
289 /* If there's an issuer certificate present check the validity of the
290 subject certificate based on it. If it's not present all that we can
291 do is perform a pure signature check with the context */
292 if( issuerCertInfoPtr != NULL )
293 {
294 status = checkCert( subjectCertInfoPtr, issuerCertInfoPtr,
295 shortCircuitCheck, errorLocus, errorType );
296 if( cryptStatusError( status ) )
297 return( status );
298 }
299
300 /* If the signature has already been checked or there's no signature-
301 check key present we're done. The latter can occur when we're
302 checking a data-only certificate in a certificate chain. This is
303 safe because these certificates can only occur when we're reading
304 them from an (implicitly trusted) private key store */
305 if( ( subjectCertInfoPtr->flags & CERT_FLAG_SIGCHECKED ) || \
306 iIssuerPubKey == CRYPT_UNUSED )
307 return( CRYPT_OK );
308
309 /* If we're checking an explicit trust anchor and the certificate isn't
310 self-signed there's nothing further left to check */
311 if( trustAnchorCheck && issuerCertInfoPtr != NULL && \
312 !( issuerCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
313 return( CRYPT_OK );
314
315 /* If we're performing a standard check and it's an explicitly-trusted
316 certificate we're done. If we're performing a check of a certificate
317 chain then the chain-handling code will have performed its own
318 handling of trusted certificates/trust anchors so we don't peform a
319 second check here */
320 if( !shortCircuitCheck )
321 {
322 status = krnlSendMessage( subjectCertInfoPtr->ownerHandle,
323 IMESSAGE_USER_TRUSTMGMT,
324 &subjectCertInfoPtr->objectHandle,
325 MESSAGE_TRUSTMGMT_CHECK );
326 if( cryptStatusOK( status ) )
327 return( CRYPT_OK );
328 }
329
330 /* Check the signature on the certificate. If there's a problem with
331 the issuer's public key it'll be reported as a CRYPT_ARGERROR_NUM1,
332 which the caller has to convert into an appropriate error code */
333 status = checkX509signature( subjectCertInfoPtr->certificate,
334 subjectCertInfoPtr->certificateSize,
335 iIssuerPubKey, formatInfo );
336 if( cryptStatusError( status ) )
337 {
338 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
339 MESSAGE_DATA msgData;
340 BYTE subjectIssuerID[ CRYPT_MAX_HASHSIZE + 8 ];
341 BYTE issuerSubjectID[ CRYPT_MAX_HASHSIZE + 8 ];
342 int subjectIDlength, issuerIDlength;
343 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
344
345 /* There's one special-case situation in which we can get a
346 signature-check failure that looks like data corruption and
347 that's when a CA quietly changes its issuing key without changing
348 anything else so that the certificates chain but the signature
349 check produces garbage as output due to the use of the incorrect
350 key. Although it could be argued that a CA that does this is
351 broken, we try and accomodate it by performing a backup check
352 using keyIDs if the signature check produces garbled output.
353 Because of the complete chaos present in keyIDs we can't do this
354 by default (it would result in far too many false positives) but
355 it's safe as a fallback at this point since we're about to report
356 an error anyway and the worst that can happen is that we return
357 a slightly inappropriate error message.
358
359 If there's no issuer certificate provided we also have to exit at
360 this point because we can't go any further without it */
361 if( status != CRYPT_ERROR_BADDATA || issuerCertInfoPtr == NULL )
362 return( status );
363
364 #ifdef USE_CERTLEVEL_PKIX_PARTIAL
365 /* Get the subject certificate's issuerID and the issuer
366 certificate's subjectID. We don't bother with the alternative
367 awkward DN-based ID since what we're really interested in is the
368 ID of the signing key and it's not worth the extra pain of dealing
369 with these awkward cert IDs just to try and fix up a slight
370 difference in error codes. Since the overall error status at this
371 point is CRYPT_ERROR_BADDATA we return that instead of any
372 ephemeral status values returned from further function calls */
373 setMessageData( &msgData, subjectIssuerID, CRYPT_MAX_HASHSIZE );
374 status = krnlSendMessage( subjectCertInfoPtr->objectHandle,
375 IMESSAGE_GETATTRIBUTE_S, &msgData,
376 CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER );
377 if( cryptStatusError( status ) )
378 return( CRYPT_ERROR_BADDATA );
379 issuerIDlength = msgData.length;
380 setMessageData( &msgData, issuerSubjectID, CRYPT_MAX_HASHSIZE );
381 status = krnlSendMessage( issuerCertInfoPtr->objectHandle,
382 IMESSAGE_GETATTRIBUTE_S, &msgData,
383 CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
384 if( cryptStatusError( status ) )
385 return( CRYPT_ERROR_BADDATA );
386 subjectIDlength = msgData.length;
387
388 /* If the keyIDs don't match then it's a signature error due to
389 false-positive chaining rather than a data corruption error */
390 return( ( ( issuerIDlength != subjectIDlength ) || \
391 memcmp( subjectIssuerID, issuerSubjectID, \
392 issuerIDlength ) ) ? \
393 CRYPT_ERROR_SIGNATURE : CRYPT_ERROR_BADDATA );
394 #else
395 return( status );
396 #endif /* USE_CERTLEVEL_PKIX_PARTIAL */
397 }
398
399 /* The signature is OK, we don't need to check it again. There is a
400 theoretical situation where this can lead to a false positive which
401 requires first checking the certificate using the correct issuing CA
402 (which will set the CERT_FLAG_SIGCHECKED flag) and then checking it
403 again using a second CA certificate identical to the first but with a
404 different key. In other words the issuer DN chains correctly but the
405 issuer key is different. The appropriate behaviour here is somewhat
406 unclear, it could be argued that a CA that uses two otherwise
407 identical certificates but with different keys is broken and therefore
408 behaviour in this situation is undefined. However we need to do
409 something and returning the result of the check with the correct CA
410 certificate even if we're later passed a second incorrect certificate
411 from the CA seems to be the most appropriate action since it has in
412 the past been validated by a certificate from the same CA. If we want
413 to force the check to be done with a specific CA key (rather than just
414 the issuing CA's certificate in general) we could store the
415 fingerprint of the signing key alongside the CERT_FLAG_SIGCHECKED
416 flag */
417 subjectCertInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
418
419 return( CRYPT_OK );
420 }
421
422 /* Check a self-signed certificate object like a certificate request or a
423 self-signed certificate */
424
425 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkSelfSignedCert(INOUT CERT_INFO * certInfoPtr,IN_OPT const X509SIG_FORMATINFO * formatInfo)426 static int checkSelfSignedCert( INOUT CERT_INFO *certInfoPtr,
427 IN_OPT const X509SIG_FORMATINFO *formatInfo )
428 {
429 CRYPT_CONTEXT iCryptContext = CRYPT_UNUSED;
430 CERT_INFO *issuerCertInfoPtr;
431 BOOLEAN trustedCertAcquired = FALSE;
432 int status;
433
434 assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
435 assert( formatInfo == NULL || \
436 isReadPtr( formatInfo, sizeof( X509SIG_FORMATINFO ) ) );
437
438 /* Perform a basic check for obvious invalidity issues */
439 if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
440 certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
441 certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
442 {
443 status = checkCertBasic( certInfoPtr );
444 if( cryptStatusError( status ) )
445 return( status );
446 }
447
448 /* Since there's no signer certificate provided it has to be either
449 explicitly self-signed or signed by a trusted certificate */
450 if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
451 {
452 if( certInfoPtr->iPubkeyContext != CRYPT_ERROR )
453 iCryptContext = certInfoPtr->iPubkeyContext;
454 issuerCertInfoPtr = certInfoPtr;
455 }
456 else
457 {
458 CRYPT_CERTIFICATE iCryptCert = certInfoPtr->objectHandle;
459
460 /* If it's a certificate it may be implicitly trusted */
461 if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
462 certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )
463 {
464 if( cryptStatusOK( \
465 krnlSendMessage( certInfoPtr->ownerHandle,
466 IMESSAGE_USER_TRUSTMGMT, &iCryptCert,
467 MESSAGE_TRUSTMGMT_CHECK ) ) )
468 {
469 /* The certificate is implicitly trusted, we're done */
470 return( CRYPT_OK );
471 }
472 }
473
474 /* If it's not self-signed it has to be signed by a trusted
475 certificate, try and get the trusted certificate */
476 status = krnlSendMessage( certInfoPtr->ownerHandle,
477 IMESSAGE_USER_TRUSTMGMT, &iCryptCert,
478 MESSAGE_TRUSTMGMT_GETISSUER );
479 if( cryptStatusError( status ) )
480 {
481 /* There's no trusted signer present, indicate that we need
482 something to check the certificate with */
483 return( CRYPT_ARGERROR_VALUE );
484 }
485 status = krnlAcquireObject( iCryptCert, OBJECT_TYPE_CERTIFICATE,
486 ( void ** ) &issuerCertInfoPtr,
487 CRYPT_ERROR_SIGNALLED );
488 if( cryptStatusError( status ) )
489 return( status );
490 ANALYSER_HINT( issuerCertInfoPtr != NULL );
491 iCryptContext = iCryptCert;
492 trustedCertAcquired = TRUE;
493 }
494
495 /* Check the certificate against the issuing certificate */
496 status = checkCertDetails( certInfoPtr, issuerCertInfoPtr,
497 iCryptContext, formatInfo, FALSE, FALSE,
498 TRUE, &certInfoPtr->errorLocus,
499 &certInfoPtr->errorType );
500 if( trustedCertAcquired )
501 krnlReleaseObject( issuerCertInfoPtr->objectHandle );
502 return( cryptArgError( status ) ? CRYPT_ARGERROR_OBJECT : status );
503 }
504
505 /****************************************************************************
506 * *
507 * General Certificate Validity Checking Functions *
508 * *
509 ****************************************************************************/
510
511 /* Check the validity of a certificate object against another object,
512 typically an issuing key or certificate but also a CRL or RTCS/OCSP
513 session.
514
515 Working with certificate chains is different from working with any other
516 type of certificate object because of the presence of multiple
517 certificates in both the item to be checked (the left-hand argument) and
518 the item to use for the checking (the right-hand argument). Consider the
519 following combinations of objects that we could encounter in terms of
520 verification:
521
522 Left Right Allowed Configuration
523 ---- ----- ------- -------------
524 Leaf Issuer Y L: A
525 R: B
526
527 Chain - Y L: A - B - C
528 R: -
529
530 Chain Root Y L: A - B - C
531 R: C
532
533 Leaf Chain N L: A
534 R: A - B - C
535
536 Leaf Chain - Lf. N L: A
537 R: B - C
538
539 Chain - Rt. Root Y L: A - B
540 R: C
541
542 Chain - Rt. Chain - Lf. N L: A - B
543 R: B - C
544
545 In the worst case we could run into something like:
546
547 L: A - B - C - D
548 R: X - Y - C - Z
549
550 Now although some of the certificates on the left and the right appear to
551 be identical, all this means is that the DNs and keys (and optionally
552 keyIDs) match, they could otherwise be completely different certificates
553 (different key usage, policies, altNames, and so on). Because of this we
554 can't use one chain to verify another chain since although they may
555 logically verify, the principle of least surprise (to the user) indicates
556 that we shouldn't make any security statement about it. For example in
557 the case of the A - B chain verified by the X - Y chain above, if we
558 report a successful verification then the user could be quite justified
559 in thinking that A - B - C - D was verified rather than A - B - C - Z, or
560 even that both the A - B and the X - Y chains are valid.
561
562 An informal survey of users indicated that no-one was really sure what a
563 success (or failure) status would indicate in this case, or more
564 specifically that everyone had some sort of guess but there was little
565 overlap between them, and people changed their views when questioned
566 about individual details.
567
568 Because of this issue of virtually-guaranteed unexpected results from the
569 user's point of view we don't allow a certificate chain as a right-hand
570 argument for checking any kind of certificate object. In addition we
571 don't allow any overlap between the certificates on the left and the
572 certificates on the right, for example if the left-hand argument is a
573 chain from leaf to root and the right-hand argument is another copy of
574 the root */
575
576 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkCertValidity(INOUT CERT_INFO * certInfoPtr,IN_HANDLE_OPT const CRYPT_HANDLE iSigCheckObject)577 int checkCertValidity( INOUT CERT_INFO *certInfoPtr,
578 IN_HANDLE_OPT const CRYPT_HANDLE iSigCheckObject )
579 {
580 CRYPT_CONTEXT iCryptContext;
581 CERT_INFO *issuerCertInfoPtr = NULL;
582 X509SIG_FORMATINFO formatInfo, *formatInfoPtr = NULL;
583 BOOLEAN issuerCertAcquired = FALSE;
584 int checkObjectType, checkObjectSubtype = CRYPT_CERTTYPE_NONE;
585 int status;
586
587 assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
588
589 REQUIRES( certInfoPtr->certificate != NULL || \
590 certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
591 certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );
592 REQUIRES( iSigCheckObject == CRYPT_UNUSED || \
593 isHandleRangeValid( iSigCheckObject ) );
594
595 /* CRMF and OCSP use a b0rken signature format (the authors couldn't
596 quite manage a cut & paste of two lines of text) so if it's one of
597 these we have to use nonstandard formatting */
598 if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
599 {
600 /* [1] SEQUENCE */
601 setX509FormatInfo( &formatInfo, 1, FALSE );
602 formatInfoPtr = &formatInfo;
603 }
604 else
605 {
606 if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
607 {
608 /* [0] EXPLICIT SEQUENCE */
609 setX509FormatInfo( &formatInfo, 0, TRUE );
610 formatInfoPtr = &formatInfo;
611 }
612 }
613
614 /* If there's no signature checking key supplied then the certificate
615 must be self-signed, either an implicitly self-signed object like a
616 certificate chain or an explicitly self-signed object like a
617 certificate request or self-signed certificate */
618 if( iSigCheckObject == CRYPT_UNUSED )
619 {
620 /* If it's a certificate chain it's a (complex) self-signed object
621 containing more than one certificate so we need a special
622 function to check the entire chain */
623 if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
624 return( checkCertChain( certInfoPtr ) );
625
626 /* It's an explicitly self-signed object */
627 return( checkSelfSignedCert( certInfoPtr, formatInfoPtr ) );
628 }
629
630 /* Find out what the signature check object is */
631 status = krnlSendMessage( iSigCheckObject, IMESSAGE_GETATTRIBUTE,
632 &checkObjectType, CRYPT_IATTRIBUTE_TYPE );
633 if( cryptStatusOK( status ) )
634 {
635 status = krnlSendMessage( iSigCheckObject, IMESSAGE_GETATTRIBUTE,
636 &checkObjectSubtype,
637 CRYPT_IATTRIBUTE_SUBTYPE );
638 }
639 if( cryptStatusError( status ) )
640 return( cryptArgError( status ) ? CRYPT_ARGERROR_VALUE : status );
641
642 /* Perform a general validity check on the object being checked and the
643 associated verification object. This is somewhat more strict than
644 the kernel checks since the kernel only knows about valid subtypes
645 but not that some subtypes are only valid in combination with some
646 types of object being checked */
647 switch( checkObjectType )
648 {
649 case OBJECT_TYPE_CERTIFICATE:
650 REQUIRES( checkObjectSubtype == SUBTYPE_CERT_CERT || \
651 checkObjectSubtype == SUBTYPE_CERT_CRL || \
652 checkObjectSubtype == SUBTYPE_CERT_RTCS_RESP || \
653 checkObjectSubtype == SUBTYPE_CERT_OCSP_RESP );
654 break;
655
656 case OBJECT_TYPE_CONTEXT:
657 REQUIRES( checkObjectSubtype == SUBTYPE_CTX_PKC );
658 break;
659
660 case OBJECT_TYPE_KEYSET:
661 /* A keyset can only be used as a source of revocation
662 information for checking a certificate or to populate the
663 status fields of an RTCS/OCSP response */
664 REQUIRES( checkObjectSubtype == SUBTYPE_KEYSET_DBMS || \
665 checkObjectSubtype == SUBTYPE_KEYSET_DBMS_STORE );
666 if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
667 certInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \
668 certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \
669 certInfoPtr->type != CRYPT_CERTTYPE_RTCS_RESPONSE && \
670 certInfoPtr->type != CRYPT_CERTTYPE_OCSP_RESPONSE )
671 return( CRYPT_ARGERROR_VALUE );
672 break;
673
674 case OBJECT_TYPE_SESSION:
675 /* An (RTCS or OCSP) session can only be used as a source of
676 validity/revocation information for checking a certificate */
677 REQUIRES( checkObjectSubtype == SUBTYPE_SESSION_RTCS || \
678 checkObjectSubtype == SUBTYPE_SESSION_OCSP );
679 if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
680 certInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \
681 certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )
682 return( CRYPT_ARGERROR_VALUE );
683 break;
684
685 default:
686 return( CRYPT_ARGERROR_VALUE );
687 }
688
689 /* There's one special-case situation in which we don't perform a
690 standard check and that's when the object to be checked is a
691 certificate chain. Normally the checking object would be
692 CRYPT_UNUSED, but the caller may also pass in a root certificate
693 as the checking object for a chain that's missing the root */
694 if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
695 {
696 CERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;
697
698 /* If we're checking a certificate chain then the only type of
699 checking object that's valid is a certificate. This isn't
700 strictly true since the CRL-checking code will check every
701 certificate in the chain against the CRL, but the code for OCSP,
702 RTCS, and keysets doesn't yet do this so until someone requests
703 it we don't allow entire chains to be checked in this manner */
704 if( checkObjectType != OBJECT_TYPE_CERTIFICATE || \
705 checkObjectSubtype != SUBTYPE_CERT_CERT )
706 return( CRYPT_ARGERROR_VALUE );
707
708 /* At this point things get a bit deceptive (for the caller), the
709 only way in which the check that's being performed here can
710 succeed is if the certificate being used as the checking object
711 is a trusted CA certificate that's at the top of the chain. In
712 this case there's no need to explicitly make it part of the check
713 since it'll already be present in the trust store, however for
714 consistency we verify that it's a CA certificate, that it's
715 trusted, and that it chains up from the certificate at the top of
716 the chain. Once this check has passed we call checkCertChain()
717 as if the checking object had been specified as CRYPT_UNUSED */
718 status = krnlSendMessage( iSigCheckObject, IMESSAGE_CHECK, NULL,
719 MESSAGE_CHECK_CA );
720 if( cryptStatusError( status ) )
721 return( CRYPT_ARGERROR_VALUE );
722 status = krnlSendMessage( certInfoPtr->ownerHandle,
723 IMESSAGE_USER_TRUSTMGMT,
724 ( MESSAGE_CAST ) &iSigCheckObject,
725 MESSAGE_TRUSTMGMT_CHECK );
726 if( cryptStatusError( status ) )
727 return( CRYPT_ARGERROR_VALUE );
728 REQUIRES( certChainInfo->chainEnd > 0 && \
729 certChainInfo->chainEnd <= MAX_CHAINLENGTH );
730 status = krnlSendMessage( certChainInfo->chain[ certChainInfo->chainEnd - 1 ],
731 IMESSAGE_CRT_SIGCHECK, NULL,
732 iSigCheckObject );
733 if( cryptStatusError( status ) )
734 return( CRYPT_ARGERROR_VALUE );
735
736 /* The checking object is a trusted CA certificate that connects to
737 the top of the chain, check the rest of the chain with the
738 implicitly-present trusted certificate as the root */
739 return( checkCertChain( certInfoPtr ) );
740 }
741
742 /* Perform a basic check for obvious invalidity issues */
743 if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
744 certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
745 certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
746 {
747 status = checkCertBasic( certInfoPtr );
748 if( cryptStatusError( status ) )
749 return( status );
750 }
751
752 /* If the checking object is a CRL or CRL-equivalent like an RTCS or
753 OCSP response, a keyset that may contain a CRL, or an RTCS or OCSP
754 session then this is a validity/revocation check that works rather
755 differently from a straight signature check */
756 #if defined( USE_CERTREV ) || defined( USE_CERTVAL )
757 if( checkObjectType == OBJECT_TYPE_CERTIFICATE )
758 {
759 #if defined( USE_CERTREV )
760 if( checkObjectSubtype == SUBTYPE_CERT_CRL || \
761 checkObjectSubtype == SUBTYPE_CERT_OCSP_RESP )
762 {
763 return( checkCRL( certInfoPtr, iSigCheckObject ) );
764 }
765 #endif /* USE_CERTREV */
766 #if defined( USE_CERTVAL )
767 if( checkObjectSubtype == SUBTYPE_CERT_RTCS_RESP )
768 {
769 /* This functionality isn't enabled yet, since RTCS is a
770 straight go/no go protocol it seems unlikely that it'll
771 ever be needed, and no-one's ever requested it in more
772 than a decade of use */
773 retIntError();
774 }
775 #endif /* USE_CERTVAL */
776 }
777 #endif /* USE_CERTREV || USE_CERTVAL */
778 if( checkObjectType == OBJECT_TYPE_KEYSET )
779 {
780 /* If it's an RTCS or OCSP response use the certificate store to fill
781 in the status information fields */
782 #if defined( USE_CERTVAL )
783 if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )
784 return( checkRTCSResponse( certInfoPtr, iSigCheckObject ) );
785 #endif /* USE_CERTVAL */
786 #if defined( USE_CERTREV )
787 if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
788 return( checkOCSPResponse( certInfoPtr, iSigCheckObject ) );
789
790 /* It's a keyset, check the certificate against the CRL blacklist in
791 the keyset */
792 return( checkKeyset( certInfoPtr, iSigCheckObject ) );
793 #else
794 return( CRYPT_ARGERROR_VALUE );
795 #endif /* USE_CERTREV */
796 }
797 #if defined( USE_CERTREV ) || defined( USE_CERTVAL )
798 if( checkObjectType == OBJECT_TYPE_SESSION )
799 return( checkResponder( certInfoPtr, iSigCheckObject ) );
800 #endif /* USE_CERTREV || USE_CERTVAL */
801
802 /* If we've been given a self-signed certificate make sure that the
803 signature check key is the same as the certificate's key. To test
804 this we have to compare both the signing key and if the signature
805 check object is a certificate, the certificate */
806 if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
807 {
808 MESSAGE_DATA msgData;
809 BYTE keyID[ KEYID_SIZE + 8 ];
810
811 /* Check that the key in the certificate and the key in the
812 signature check object are identical */
813 setMessageData( &msgData, keyID, KEYID_SIZE );
814 status = krnlSendMessage( iSigCheckObject, IMESSAGE_GETATTRIBUTE_S,
815 &msgData, CRYPT_IATTRIBUTE_KEYID );
816 if( cryptStatusOK( status ) )
817 status = krnlSendMessage( certInfoPtr->objectHandle,
818 IMESSAGE_COMPARE, &msgData,
819 MESSAGE_COMPARE_KEYID );
820 if( cryptStatusError( status ) )
821 return( CRYPT_ARGERROR_VALUE );
822
823 /* If the signature check object is a certificate (even though
824 what's being checked is already a self-signed certificate) check
825 that it's identical to the certificate being checked (which it
826 must be if the certificate is self-signed). This may be somewhat
827 stricter than required but it'll weed out technically valid but
828 questionable combinations like a certificate request being used
829 to validate a certificate and misleading ones such as one
830 certificate chain being used to check a second chain */
831 if( checkObjectType == OBJECT_TYPE_CERTIFICATE )
832 {
833 status = krnlSendMessage( certInfoPtr->objectHandle,
834 IMESSAGE_COMPARE,
835 ( MESSAGE_CAST ) &iSigCheckObject,
836 MESSAGE_COMPARE_CERTOBJ );
837 if( cryptStatusError( status ) )
838 return( CRYPT_ARGERROR_VALUE );
839 }
840
841 /* If it's a certificate chain it's a (complex) self-signed object
842 containing more than one certificate so we need a special
843 function to check the entire chain */
844 if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
845 return( checkCertChain( certInfoPtr ) );
846
847 return( checkSelfSignedCert( certInfoPtr, formatInfoPtr ) );
848 }
849
850 /* The signature check key may be a certificate or a context. If it's
851 a certificate we get the issuer certificate information and extract
852 the context from it before continuing */
853 if( checkObjectType == OBJECT_TYPE_CERTIFICATE )
854 {
855 /* Get the context from the issuer certificate */
856 status = krnlSendMessage( iSigCheckObject, IMESSAGE_GETDEPENDENT,
857 &iCryptContext, OBJECT_TYPE_CONTEXT );
858 if( cryptStatusError( status ) )
859 return( cryptArgError( status ) ? CRYPT_ARGERROR_VALUE : status );
860
861 /* Get the issuer certificate information */
862 status = krnlAcquireObject( iSigCheckObject, OBJECT_TYPE_CERTIFICATE,
863 ( void ** ) &issuerCertInfoPtr,
864 CRYPT_ARGERROR_VALUE );
865 if( cryptStatusError( status ) )
866 return( status );
867 ANALYSER_HINT( issuerCertInfoPtr != NULL );
868 issuerCertAcquired = TRUE;
869 }
870 else
871 {
872 CRYPT_CERTIFICATE localCert;
873
874 iCryptContext = iSigCheckObject;
875
876 /* It's a context, we may have a certificate present with it so we
877 try to extract that and use it as the issuer certificate if
878 possible. If the issuer certificate isn't present this isn't an
879 error since it could be just a raw context */
880 status = krnlSendMessage( iSigCheckObject, IMESSAGE_GETDEPENDENT,
881 &localCert, OBJECT_TYPE_CERTIFICATE );
882 if( cryptStatusOK( status ) )
883 {
884 status = krnlAcquireObject( localCert, OBJECT_TYPE_CERTIFICATE,
885 ( void ** ) &issuerCertInfoPtr,
886 CRYPT_ARGERROR_VALUE );
887 if( cryptStatusError( status ) )
888 return( status );
889 ANALYSER_HINT( issuerCertInfoPtr != NULL );
890 issuerCertAcquired = TRUE;
891 }
892 }
893
894 /* Check the certificate against the issuing certificate */
895 status = checkCertDetails( certInfoPtr, issuerCertAcquired ? \
896 issuerCertInfoPtr : NULL,
897 iCryptContext, formatInfoPtr, FALSE, FALSE,
898 TRUE, &certInfoPtr->errorLocus,
899 &certInfoPtr->errorType );
900 if( issuerCertAcquired )
901 krnlReleaseObject( issuerCertInfoPtr->objectHandle );
902 return( cryptArgError( status ) ? CRYPT_ARGERROR_VALUE : status );
903 }
904 #endif /* USE_CERTIFICATES */
905