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