1 /****************************************************************************
2 *																			*
3 *							Kernel Message Dispatcher						*
4 *						Copyright Peter Gutmann 1997-2012					*
5 *																			*
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9   #include "crypt.h"
10   #include "acl.h"
11   #include "kernel.h"
12 #else
13   #include "crypt.h"
14   #include "kernel/acl.h"
15   #include "kernel/kernel.h"
16 #endif /* Compiler-specific includes */
17 
18 /* A pointer to the kernel data block */
19 
20 static KERNEL_DATA *krnlData = NULL;
21 
22 /* The ACL used to check objects passed as message parameters, in this case
23    for certificate sign/sig-check messages */
24 
25 static const MESSAGE_ACL FAR_BSS messageParamACLTbl[] = {
26 	/* Certificates can only be signed by (private-key) PKC contexts */
27 	{ MESSAGE_CRT_SIGN,
28 	  { ST_CTX_PKC,
29 		ST_NONE, ST_NONE } },
30 
31 	/* Signatures can be checked with a raw PKC context or a certificate
32 	   (but specifically not a certificate chain, see the long discussion
33 	   in certs/certschk.c for details on this).  The object being checked
34 	   can also be checked against a CRL or CRL-equivalent like an RTCS or
35 	   OCSP response, against revocation data in a certificate store, or
36 	   against an RTCS or OCSP responder */
37 	{ MESSAGE_CRT_SIGCHECK,
38 	  { ST_CTX_PKC | MKTYPE_CERTIFICATES( ST_CERT_CERT ) | \
39 			MKTYPE_CERTREV( ST_CERT_CRL ) | MKTYPE_CERTVAL( ST_CERT_RTCS_RESP ) | \
40 			MKTYPE_CERTREV( ST_CERT_OCSP_RESP ),
41 	    MKTYPE_DBMS( ST_KEYSET_DBMS ) | MKTYPE_DBMS( ST_KEYSET_DBMS_STORE ),
42 		MKTYPE_RTCS( ST_SESS_RTCS ) | MKTYPE_OCSP( ST_SESS_OCSP ) } },
43 
44 	/* End-of-ACL marker */
45 	{ MESSAGE_NONE, { ST_NONE, ST_NONE, ST_NONE } },
46 	{ MESSAGE_NONE, { ST_NONE, ST_NONE, ST_NONE } }
47 	};
48 
49 /****************************************************************************
50 *																			*
51 *								Utility Functions							*
52 *																			*
53 ****************************************************************************/
54 
55 /* Sometimes a message is explicitly non-routable (i.e. it has to be sent
56    directly to the appropriate target object).  The following function checks
57    that the target object is one of the required types */
58 
59 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
checkTargetType(IN_HANDLE const CRYPT_HANDLE originalObjectHandle,OUT_HANDLE_OPT CRYPT_HANDLE * targetObjectHandle,const long targets)60 int checkTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle,
61 					 OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,
62 					 const long targets )
63 	{
64 	const OBJECT_TYPE target = targets & 0xFF;
65 	const OBJECT_TYPE altTarget = targets >> 8;
66 	OBJECT_INFO *objectTable = krnlData->objectTable;
67 
68 	/* Precondition: Source is a valid object, destination(s) are valid
69 	   target(s) */
70 	REQUIRES( isValidObject( originalObjectHandle ) );
71 	REQUIRES( isValidType( target ) );
72 	REQUIRES( altTarget == OBJECT_TYPE_NONE || isValidType( altTarget ) );
73 
74 	/* Clear return value */
75 	*targetObjectHandle = CRYPT_ERROR;
76 
77 	/* Check whether the object matches the required type.  We don't have to
78 	   check whether the alternative target has a value or not since the
79 	   object can never be a OBJECT_TYPE_NONE */
80 	if( !isValidObject( originalObjectHandle ) || \
81 		( objectTable[ originalObjectHandle ].type != target && \
82 		  objectTable[ originalObjectHandle ].type != altTarget ) )
83 		return( CRYPT_ERROR );
84 
85 	/* Postcondition */
86 	ENSURES( objectTable[ originalObjectHandle ].type == target || \
87 			 objectTable[ originalObjectHandle ].type == altTarget );
88 
89 	*targetObjectHandle = originalObjectHandle;
90 	return( CRYPT_OK );
91 	}
92 
93 /* Find the ACL for a parameter object */
94 
95 CHECK_RETVAL_PTR \
findParamACL(IN_MESSAGE const MESSAGE_TYPE message)96 static const MESSAGE_ACL *findParamACL( IN_MESSAGE const MESSAGE_TYPE message )
97 	{
98 	int i;
99 
100 	/* Precondition: It's a message that takes an object parameter */
101 	REQUIRES_N( isParamMessage( message ) );
102 
103 	/* Find the ACL entry for this message type.  There's no need to
104 	   explicitly handle the internal-error condition since any loop
105 	   exit is treated as an error */
106 	for( i = 0; messageParamACLTbl[ i ].type != MESSAGE_NONE && \
107 				i < FAILSAFE_ARRAYSIZE( messageParamACLTbl, MESSAGE_ACL );
108 		 i++ )
109 		{
110 		if( messageParamACLTbl[ i ].type == message )
111 			return( &messageParamACLTbl[ i ] );
112 		}
113 
114 	retIntError_Null();
115 	}
116 
117 /* Wait for an object to become available so that we can use it, with a
118    timeout for blocked objects (dulcis et alta quies placidaeque similima
119    morti).  We spin for WAITCOUNT_SLEEP_THRESHOLD turns, then sleep (see
120    the comment in waitForObject() for more on this), and finally bail out
121    once MAX_WAITCOUNT is reached.
122 
123    This is an internal function that's used when mapping an object handle to
124    object data, and is never called directly.
125 
126    As an aid in identifying objects acting as bottlenecks, we provide a
127    function to warn about excessive waiting, along with information on the
128    object that was waited on, in debug mode.  A wait count threshold of
129    100 is generally high enough to avoid false positives caused by (for
130    example) network subsystem delays */
131 
132 #define WAITCOUNT_SLEEP_THRESHOLD		100
133 #define WAITCOUNT_WARN_THRESHOLD		100
134 #define MAX_WAITCOUNT					1000
135 
136 #if !defined( NDEBUG )
137 
138 /* Get a text description of an object associated with a given object
139    handle */
140 
getObjectDescription(IN_HANDLE const int objectHandle,OUT char * description)141 static void getObjectDescription( IN_HANDLE const int objectHandle,
142 								  OUT char *description )
143 	{
144 	static const char *objectTypeNames[] = {
145 		"none", "context", "keyset", "envelope", "certificate", "device",
146 		"session", "user", "none", "none"
147 		};
148 	typedef struct {
149 		const OBJECT_SUBTYPE subType;
150 		const char *description;
151 		} OBJECT_DESCRIPTION_MAP;
152 	static const OBJECT_DESCRIPTION_MAP descriptionMap[] = {
153 		{ SUBTYPE_CTX_CONV, "conventional encryption" },
154 		{ SUBTYPE_CTX_PKC, "public-key encryption" },
155 		{ SUBTYPE_CTX_HASH, "hash" },
156 		{ SUBTYPE_CTX_MAC, "MAC" },
157 		{ SUBTYPE_CTX_GENERIC, "generic" },
158 		{ SUBTYPE_CERT_CERT, "certificate" },
159 		{ SUBTYPE_CERT_CERTREQ, "PKCS #10 cert.request" },
160 		{ SUBTYPE_CERT_REQ_CERT, "CRMF cert.request" },
161 		{ SUBTYPE_CERT_REQ_REV, "CRMF rev.request" },
162 		{ SUBTYPE_CERT_CERTCHAIN, "cert.chain" },
163 		{ SUBTYPE_CERT_ATTRCERT, "attribute cert." },
164 		{ SUBTYPE_CERT_CRL, "CRK" },
165 		{ SUBTYPE_CERT_CMSATTR, "CMS attributes" },
166 		{ SUBTYPE_CERT_RTCS_REQ, "RTCS request" },
167 		{ SUBTYPE_CERT_RTCS_RESP, "RTCS response" },
168 		{ SUBTYPE_CERT_OCSP_REQ, "OCSP request" },
169 		{ SUBTYPE_CERT_OCSP_RESP, "OCSP response" },
170 		{ SUBTYPE_CERT_PKIUSER, "PKI user" },
171 		{ SUBTYPE_ENV_ENV, "PKCS #7/CMS envelope" },
172 		{ SUBTYPE_ENV_ENV_PGP, "PGP envelope" },
173 		{ SUBTYPE_ENV_DEENV, "de-envelope" },
174 		{ SUBTYPE_KEYSET_FILE, "file" },
175 		{ SUBTYPE_KEYSET_FILE_PARTIAL, "file (partial)" },
176 		{ SUBTYPE_KEYSET_FILE_READONLY, "file (readonly)" },
177 		{ SUBTYPE_KEYSET_DBMS, "database" },
178 		{ SUBTYPE_KEYSET_DBMS_STORE, "database store" },
179 		{ SUBTYPE_KEYSET_HTTP, "HTTP" },
180 		{ SUBTYPE_KEYSET_LDAP, "LDAP" },
181 		{ SUBTYPE_DEV_SYSTEM, "system" },
182 		{ SUBTYPE_DEV_PKCS11, "PKCS #11" },
183 		{ SUBTYPE_DEV_CRYPTOAPI, "CryptoAPI" },
184 		{ SUBTYPE_DEV_HARDWARE, "hardware" },
185 		{ SUBTYPE_SESSION_SSH, "SSH" },
186 		{ SUBTYPE_SESSION_SSH_SVR, "SSH server" },
187 		{ SUBTYPE_SESSION_SSL, "SSL" },
188 		{ SUBTYPE_SESSION_SSL_SVR, "SSL server" },
189 		{ SUBTYPE_SESSION_RTCS, "RTCS" },
190 		{ SUBTYPE_SESSION_RTCS_SVR, "RTCS server" },
191 		{ SUBTYPE_SESSION_OCSP, "OCSP" },
192 		{ SUBTYPE_SESSION_OCSP_SVR, "OCSP server" },
193 		{ SUBTYPE_SESSION_TSP, "TSP" },
194 		{ SUBTYPE_SESSION_TSP_SVR, "TSP server" },
195 		{ SUBTYPE_SESSION_CMP, "CMP" },
196 		{ SUBTYPE_SESSION_CMP_SVR, "CMP server" },
197 		{ SUBTYPE_SESSION_SCEP, "SCEP" },
198 		{ SUBTYPE_SESSION_SCEP_SVR, "SCEP server" },
199 		{ SUBTYPE_SESSION_CERT_SVR, "cerificate store" },
200 		{ SUBTYPE_USER_SO, "SO user" },
201 		{ SUBTYPE_USER_NORMAL, "standard user" },
202 		{ SUBTYPE_USER_CA, "CA user" },
203 		{ SUBTYPE_NONE, "NONE" }, { SUBTYPE_NONE, "NONE" },
204 		};
205 	const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
206 	int i;
207 
208 	assert( isValidObject( objectHandle ) );
209 
210 	REQUIRES_V( isValidType( objectInfoPtr->type ) );
211 
212 	if( objectHandle == SYSTEM_OBJECT_HANDLE )
213 		{
214 		strlcpy_s( description, 128, "system object" );
215 		return;
216 		}
217 	if( objectHandle == DEFAULTUSER_OBJECT_HANDLE )
218 		{
219 		strlcpy_s( description, 128, "default user object" );
220 		return;
221 		}
222 	for( i = 0; descriptionMap[ i ].subType != objectInfoPtr->subType && \
223 				descriptionMap[ i ].subType != SUBTYPE_NONE; i++ );
224 	sprintf_s( description, 128, "object %d (%s/%s)", objectHandle,
225 			   objectTypeNames[ objectInfoPtr->type ],
226 			   descriptionMap[ i ].description );
227 	}
228 
229 /* Non thread-safe version of the above that can be used directly in
230    printf() statements.  This isn't really that bad, firstly it's mostly
231    only called for diagnostics during startup/shutdown where there's
232    guaranteed to be only one thread active, and secondly it uses TLS
233    where possible which means that it'll only really be non-thread-safe on
234    systems that don't have threading anyway (embedded systems that use
235    the tasking model where there's typically only one task) */
236 
237 #if defined( _MSC_VER )
238   #define THREAD_STORAGE_STATIC		__declspec( thread ) static
239 #elif defined( __GNUC__ ) || defined( __clang__ ) || \
240 	  defined( __SUNPRO_C ) || defined( __xlc__ )
241   #define THREAD_STORAGE_STATIC		static __thread
242 #else
243   #define THREAD_STORAGE_STATIC		static
244 #endif /* Compiler-specific TLS */
245 #if defined( __APPLE__ )
246   #undef THREAD_STORAGE_STATIC
247   #define THREAD_STORAGE_STATIC		static
248 #endif /* OS X */
249 
getObjectDescriptionNT(IN_HANDLE const int objectHandle)250 const char *getObjectDescriptionNT( IN_HANDLE const int objectHandle )
251 	{
252 	THREAD_STORAGE_STATIC char buffer[ 128 ];
253 
254 	getObjectDescription( objectHandle, buffer );
255 	return( buffer );
256 	}
257 
258 /* Warn about an excessive wait for an object to become available */
259 
waitWarn(IN_HANDLE const int objectHandle,IN_INT const int waitCount)260 static void waitWarn( IN_HANDLE const int objectHandle,
261 					  IN_INT const int waitCount )
262 	{
263 	char description[ 128 + 8 ];
264 
265 	assert( isValidObject( objectHandle ) );
266 	assert( waitCount > WAITCOUNT_WARN_THRESHOLD && \
267 			waitCount <= MAX_WAITCOUNT );
268 
269 	getObjectDescription( objectHandle, description );
270 	DEBUG_PRINT(( "\nWarning: Thread %lX waited %d iteration%s for %s.\n",
271 				  ( unsigned long ) THREAD_SELF(), waitCount,
272 				  ( waitCount == 1 ) ? "" : "s", description ));
273 	}
274 #endif /* Debug mode only */
275 
276 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
waitForObject(IN_HANDLE const int objectHandle,OUT_PTR_COND OBJECT_INFO ** objectInfoPtrPtr)277 int waitForObject( IN_HANDLE const int objectHandle,
278 				   OUT_PTR_COND OBJECT_INFO **objectInfoPtrPtr )
279 	{
280 	OBJECT_INFO *objectTable = krnlData->objectTable;
281 	const int uniqueID = objectTable[ objectHandle ].uniqueID;
282 	int waitCount = 0;
283 
284 	/* Preconditions: The object is in use by another thread */
285 	REQUIRES( isValidObject( objectHandle ) );
286 	REQUIRES( isInUse( objectHandle ) && !isObjectOwner( objectHandle ) );
287 
288 	/* Clear return value */
289 	*objectInfoPtrPtr = NULL;
290 
291 	/* While the object is busy, put the thread to sleep (Pauzele lungi si
292 	   dese; Cheia marilor succese).  This is the only really portable way
293 	   to wait on the resource, which gives up this thread's timeslice to
294 	   allow other threads (including the one using the object) to run.
295 	   Somewhat better methods methods such as mutexes with timers are
296 	   difficult to manage portably across different platforms.
297 
298 	   Even this can cause problems in some circumstances.  The idea behind
299 	   the mechanism below is that by yielding the CPU, whichever thread
300 	   currently holds the object gets to finish with it and then the
301 	   current thread resumes.  However if there's a thundering-herd
302 	   situation where a dozen other threads are waiting on the lock and
303 	   they've voluntarily yielded the CPU and the scheduler prioritises
304 	   them above other threads because of this then they'll all fight for
305 	   the lock and so the thread that holds the object that they're waiting
306 	   on never gets to run.
307 
308 	   This seems somewhat unlikely, but it's cropped up on multicore
309 	   hyperthreaded Linux machines running large numbers of threads,
310 	   probably because of the thread-scheduling pecularities of HT CPUs
311 	   combined with the thread-scheduling peculiarities of Linux (it
312 	   doesn't occur on the same systems running Windows or other OSes).
313 	   The problem seems to be that if a thread yields on a CPU other than
314 	   the one that holds the resource and no other threads are waiting to
315 	   run then it's immediately re-scheduled, because the yield only
316 	   applies to threads on the same CPU.
317 
318 	   To deal with this we turn the basic thread-timeslice-yield into a
319 	   more aggressive thread-sleep (which really does yield the CPU, even
320 	   with the thread-scheduling described above) if
321 	   WAITCOUNT_SLEEP_THRESHOLD yields are exceeded */
322 	while( isValidObject( objectHandle ) && \
323 		   objectTable[ objectHandle ].uniqueID == uniqueID && \
324 		   isInUse( objectHandle ) && waitCount < MAX_WAITCOUNT && \
325 		   krnlData->shutdownLevel < SHUTDOWN_LEVEL_MESSAGES )
326 		{
327 		objectTable = NULL;
328 		MUTEX_UNLOCK( objectTable );
329 		waitCount++;
330 		THREAD_YIELD();
331 		if( waitCount > WAITCOUNT_SLEEP_THRESHOLD )
332 			{
333 			/* We've waited for over WAITCOUNT_SLEEP_THRESHOLD thread
334 			   timeslices, explicitly put the thread to sleep rather than
335 			   just yielding its timeslice */
336 			THREAD_SLEEP( 1 );
337 			}
338 		MUTEX_LOCK( objectTable );
339 		objectTable = krnlData->objectTable;
340 		}
341 #if !defined( NDEBUG ) && !defined( __WIN16__ )
342 	if( waitCount > WAITCOUNT_WARN_THRESHOLD )
343 		{
344 		/* If we waited more than WAITCOUNT_WARN_THRESHOLD iterations for
345 		   something this could be a sign of a resource usage bottleneck
346 		   (typically caused by users who don't understand threading), warn
347 		   the user that there's a potential problem */
348 		waitWarn( objectHandle, waitCount );
349 		}
350 #endif /* NDEBUG on systems with stdio */
351 
352 	/* If cryptlib is shutting down, exit */
353 	if( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES )
354 		return( CRYPT_ERROR_PERMISSION );
355 
356 	/* If we timed out waiting for the object, return a timeout error */
357 	if( waitCount >= MAX_WAITCOUNT )
358 		{
359 		DEBUG_DIAG(( "Object wait exceeded %d iterations", MAX_WAITCOUNT ));
360 		assert( DEBUG_WARN );
361 		return( CRYPT_ERROR_TIMEOUT );
362 		}
363 
364 	/* Make sure that nothing happened to the object while we were waiting
365 	   on it */
366 	if( !isValidObject( objectHandle ) || \
367 		objectTable[ objectHandle ].uniqueID != uniqueID )
368 		return( CRYPT_ERROR_SIGNALLED );
369 
370 	/* Update the object info pointer in case the object table was updated
371 	   while we had yielded control */
372 	*objectInfoPtrPtr = &objectTable[ objectHandle ];
373 
374 	/* Postconditions: The object is available for use */
375 	ENSURES( isValidObject( objectHandle ) );
376 	ENSURES( !isInUse( objectHandle ) );
377 
378 	return( CRYPT_OK );
379 	}
380 
381 /****************************************************************************
382 *																			*
383 *									Message Routing							*
384 *																			*
385 ****************************************************************************/
386 
387 /* Find the ultimate target of an object attribute manipulation message by
388    walking down the chain of controlling -> dependent objects.  For example
389    a message targeted at a device and sent to a certificate would be routed
390    to the certificate's dependent object (which would typically be a
391    context).  The device message targeted at the context would in turn be
392    routed to the context's dependent device, which is its final destination */
393 
394 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
findTargetType(IN_HANDLE const CRYPT_HANDLE originalObjectHandle,OUT_HANDLE_OPT CRYPT_HANDLE * targetObjectHandle,const long targets)395 int findTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle,
396 					OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,
397 					const long targets )
398 	{
399 	const OBJECT_TYPE target = targets & 0xFF;
400 	const OBJECT_TYPE altTarget1 = ( targets >> 8 ) & 0xFF;
401 	const OBJECT_TYPE altTarget2 = ( targets >> 16 ) & 0xFF;
402 	OBJECT_INFO *objectTable = krnlData->objectTable;
403 	OBJECT_TYPE type = objectTable[ originalObjectHandle ].type;
404 	int objectHandle = originalObjectHandle, iterations;
405 
406 	/* Preconditions: Source is a valid object, destination(s) are valid
407 	   target(s) */
408 	REQUIRES( isValidObject( objectHandle ) );
409 	REQUIRES( isValidType( target ) );
410 	REQUIRES( altTarget1 == OBJECT_TYPE_NONE || isValidType( altTarget1 ) );
411 	REQUIRES( altTarget2 == OBJECT_TYPE_NONE || isValidType( altTarget2 ) );
412 
413 	/* Clear return value */
414 	*targetObjectHandle = CRYPT_ERROR;
415 
416 	/* Route the request through any dependent objects as required until we
417 	   reach the required target object type.  "And thou shalt make
418 	   loops..." -- Exodus 26:4 */
419 	for( iterations = 0; \
420 		 iterations < 3 && isValidObject( objectHandle ) && \
421 		   !( target == type || \
422 			  ( altTarget1 != OBJECT_TYPE_NONE && altTarget1 == type ) || \
423 			  ( altTarget2 != OBJECT_TYPE_NONE && altTarget2 == type ) ); \
424 		 iterations++ )
425 		{
426 		/* Loop invariants.  "Fifty loops thou shalt make" -- Exodus 26:5
427 		   (some of the OT verses shouldn't be taken too literally,
428 		   apparently the 50 used here merely means "many" as in "more than
429 		   one or two" in the same way that "40 days and nights" is now
430 		   generally taken as meaning "Lots, but that's as far as we're
431 		   prepared to count") */
432 		ENSURES( isValidObject( objectHandle ) );
433 		ENSURES( iterations < 3 );
434 
435 		/* Find the next potential target object */
436 		if( target == OBJECT_TYPE_DEVICE && \
437 			objectTable[ objectHandle ].dependentDevice != CRYPT_ERROR )
438 			objectHandle = objectTable[ objectHandle ].dependentDevice;
439 		else
440 			{
441 			if( target == OBJECT_TYPE_USER )
442 				{
443 				/* If we've reached the system object (the parent of all
444 				   other objects) we can't go any further */
445 				objectHandle = ( objectHandle != SYSTEM_OBJECT_HANDLE ) ? \
446 							   objectTable[ objectHandle ].owner : CRYPT_ERROR;
447 				}
448 			else
449 				objectHandle = objectTable[ objectHandle ].dependentObject;
450 			}
451 		if( isValidObject( objectHandle ) )
452 			type = objectTable[ objectHandle ].type;
453 
454 		/* If we've got a new object, it has the same owner as the original
455 		   target candidate */
456 		ENSURES( !isValidObject( objectHandle ) || \
457 				 isSameOwningObject( originalObjectHandle, objectHandle ) || \
458 				 objectTable[ originalObjectHandle ].owner == objectHandle );
459 		}
460 	ENSURES( iterations < 3 );
461 	if( !isValidObject( objectHandle ) )
462 		return( CRYPT_ARGERROR_OBJECT );
463 
464 	/* Postcondition: We've reached the target object */
465 	ENSURES( isValidObject( objectHandle ) && \
466 			 ( isSameOwningObject( originalObjectHandle, objectHandle ) || \
467 			   objectTable[ originalObjectHandle ].owner == objectHandle ) && \
468 			 ( target == type || \
469 			   ( altTarget1 != OBJECT_TYPE_NONE && altTarget1 == type ) || \
470 			   ( altTarget2 != OBJECT_TYPE_NONE && altTarget2 == type ) ) );
471 
472 
473 	*targetObjectHandle = objectHandle;
474 	return( CRYPT_OK );
475 	}
476 
477 /* Find the ultimate target of a compare message by walking down the chain
478    of controlling -> dependent objects.  For example a message targeted at a
479    device and sent to a certificate would be routed to the certificate's
480    dependent object (which would typically be a context).  The device
481    message targeted at the context would be routed to the context's
482    dependent device, which is its final destination */
483 
484 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
routeCompareMessageTarget(IN_HANDLE const CRYPT_HANDLE originalObjectHandle,OUT_HANDLE_OPT CRYPT_HANDLE * targetObjectHandle,IN_ENUM (MESSAGE_COMPARE)const long messageValue)485 static int routeCompareMessageTarget( IN_HANDLE const CRYPT_HANDLE originalObjectHandle,
486 									  OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,
487 									  IN_ENUM( MESSAGE_COMPARE ) \
488 											const long messageValue )
489 	{
490 	OBJECT_TYPE targetType = OBJECT_TYPE_NONE;
491 	int status;
492 
493 	/* Preconditions */
494 	REQUIRES( isValidObject( originalObjectHandle ) );
495 	REQUIRES( messageValue == MESSAGE_COMPARE_HASH || \
496 			  messageValue == MESSAGE_COMPARE_ICV || \
497 			  messageValue == MESSAGE_COMPARE_KEYID || \
498 			  messageValue == MESSAGE_COMPARE_KEYID_PGP || \
499 			  messageValue == MESSAGE_COMPARE_KEYID_OPENPGP || \
500 			  messageValue == MESSAGE_COMPARE_SUBJECT || \
501 			  messageValue == MESSAGE_COMPARE_ISSUERANDSERIALNUMBER || \
502 			  messageValue == MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER || \
503 			  messageValue == MESSAGE_COMPARE_FINGERPRINT_SHA1 || \
504 			  messageValue == MESSAGE_COMPARE_FINGERPRINT_SHA2 || \
505 			  messageValue == MESSAGE_COMPARE_FINGERPRINT_SHAng || \
506 			  messageValue == MESSAGE_COMPARE_CERTOBJ );
507 
508 	/* Clear return value */
509 	*targetObjectHandle = CRYPT_ERROR;
510 
511 	/* Determine the ultimate target type for the message.  We don't check for
512 	   keysets, envelopes and sessions as dependent objects since this never
513 	   occurs */
514 	switch( messageValue )
515 		{
516 		case MESSAGE_COMPARE_HASH:
517 		case MESSAGE_COMPARE_ICV:
518 		case MESSAGE_COMPARE_KEYID:
519 		case MESSAGE_COMPARE_KEYID_PGP:
520 		case MESSAGE_COMPARE_KEYID_OPENPGP:
521 			targetType = OBJECT_TYPE_CONTEXT;
522 			break;
523 
524 		case MESSAGE_COMPARE_SUBJECT:
525 		case MESSAGE_COMPARE_ISSUERANDSERIALNUMBER:
526 		case MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER:
527 		case MESSAGE_COMPARE_FINGERPRINT_SHA1:
528 		case MESSAGE_COMPARE_FINGERPRINT_SHA2:
529 		case MESSAGE_COMPARE_FINGERPRINT_SHAng:
530 		case MESSAGE_COMPARE_CERTOBJ:
531 			targetType = OBJECT_TYPE_CERTIFICATE;
532 			break;
533 
534 		default:
535 			retIntError();
536 		}
537 
538 	/* Route the message through to the appropriate object */
539 	status = findTargetType( originalObjectHandle, targetObjectHandle,
540 							 targetType );
541 	if( cryptStatusError( status ) )
542 		return( CRYPT_ARGERROR_OBJECT );
543 
544 	/* Postcondition: We've found a valid target object */
545 	ENSURES( isValidObject( *targetObjectHandle ) && \
546 			 isSameOwningObject( originalObjectHandle, \
547 								 *targetObjectHandle ) );
548 
549 	return( CRYPT_OK );
550 	}
551 
552 /****************************************************************************
553 *																			*
554 *							Message Dispatch ACL							*
555 *																			*
556 ****************************************************************************/
557 
558 /* Each message type has certain properties such as whether it's routable,
559    which object types it applies to, what checks are performed on it, whether
560    it's processed by the kernel or dispatched to an object, etc etc.  These
561    are all defined in the following table.
562 
563    In addition to the usual checks, we also make various assertions about the
564    parameters we're passed.  Note that these don't check user data (that's
565    checked programmatically and an error code returned) but values passed by
566    cryptlib code */
567 
568 typedef enum {
569 	PARAMTYPE_NONE_NONE,	/* Data = 0, value = 0 */
570 		PARAMTYPE_NONE = PARAMTYPE_NONE_NONE,/* For code analyser */
571 	PARAMTYPE_NONE_ANY,		/* Data = 0, value = any */
572 	PARAMTYPE_NONE_BOOLEAN,	/* Data = 0, value = boolean */
573 	PARAMTYPE_NONE_CHECKTYPE,/* Data = 0, value = check type */
574 	PARAMTYPE_DATA_NONE,	/* Data, value = 0 */
575 	PARAMTYPE_DATA_ANY,		/* Data, value = any */
576 	PARAMTYPE_DATA_ATTRIBUTE,/* Data, value = attribute type */
577 	PARAMTYPE_DATA_LENGTH,	/* Data, value >= 0 */
578 	PARAMTYPE_DATA_OBJTYPE,	/* Data, value = object type */
579 	PARAMTYPE_DATA_MECHTYPE,/* Data, value = mechanism type */
580 	PARAMTYPE_DATA_ITEMTYPE,/* Data, value = keymgmt.item type */
581 	PARAMTYPE_DATA_FORMATTYPE,/* Data, value = cert format type */
582 	PARAMTYPE_DATA_COMPARETYPE,/* Data, value = compare type */
583 	PARAMTYPE_DATA_SETDEPTYPE,/* Data, value = setdep.option type */
584 	PARAMTYPE_DATA_CERTMGMTTYPE,/* Data, value = cert.mgmt.type */
585 	PARAMTYPE_ANY_USERMGMTTYPE,/* Data = any, value = user mgmt.type */
586 	PARAMTYPE_ANY_TRUSTMGMTTYPE,/* Data = any, value = trust mgmt.type */
587 	PARAMTYPE_LAST			/* Last possible parameter check type */
588 	} PARAMCHECK_TYPE;
589 
590 /* Symbolic defines for message handling types, used to make it clearer
591    what's going on
592 
593 	PRE_DISPATCH	- Action before message is dispatched
594 	POST_DISPATCH	- Action after message is dispatched
595 	HANDLE_INTERNAL	- Message handled by the kernel */
596 
597 #define PRE_DISPATCH( function )	preDispatch##function, NULL
598 #define POST_DISPATCH( function )	NULL, postDispatch##function
599 #define PRE_POST_DISPATCH( preFunction, postFunction ) \
600 		preDispatch##preFunction, postDispatch##postFunction
601 #define HANDLE_INTERNAL( function )	NULL, NULL, MESSAGE_HANDLING_FLAG_INTERNAL, function
602 
603 /* Flags to indicate (potential) special-case handling for a message.  These
604    are:
605 
606 	FLAG_INTERNAL: The message is handled internally by the kernel rather
607 			than being sent to an external handler.
608 
609 	FLAG_MAYUNLOCK: The message handler may unlock the object (via
610 			krnlReleaseObject()) to allow other threads access.  In this
611 			case the first parameter to the handler function should be a
612 			MESSAGE_FUNCTION_EXTINFO structure to contain unlocking
613 			information */
614 
615 #define MESSAGE_HANDLING_FLAG_NONE		0	/* No special handling */
616 #define MESSAGE_HANDLING_FLAG_MAYUNLOCK	1	/* Handler may unlock object */
617 #define MESSAGE_HANDLING_FLAG_INTERNAL	2	/* Message handle by kernel */
618 
619 /* The handling information, declared in the order in which it's applied */
620 
621 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
622 		int ( *PREDISPATCH_FUNCTION )( IN_HANDLE const int objectHandle,
623 									   IN_MESSAGE const MESSAGE_TYPE message,
624 									   const void *messageDataPtr,
625 									   const int messageValue, const void *auxInfo );
626 typedef CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
627 		int ( *POSTDISPATCH_FUNCTION )( IN_HANDLE const int objectHandle,
628 										IN_MESSAGE const MESSAGE_TYPE message,
629 										const void *messageDataPtr,
630 										const int messageValue, const void *auxInfo );
631 typedef CHECK_RETVAL \
632 		int ( *INTERNALHANDLER_FUNCTION )( IN_HANDLE const int objectHandle,
633 										   const int arg1, const void *arg2,
634 										   const BOOLEAN isInternal );
635 
636 typedef struct {
637 	/* The message type, used for consistency checking */
638 	const MESSAGE_TYPE messageType;
639 
640 	/* Message routing information if the message is routable.  If the target
641 	   is implicitly determined via the message value, the routing target is
642 	   OBJECT_TYPE_NONE; if the target is explicitly determined, the routing
643 	   target is identified in the target.  If the routing function is null,
644 	   the message isn't routed */
645 	const long routingTarget;			/* Target type if routable */
646 	ROUTING_FUNCTION routingFunction;
647 
648 	/* Object type checking information: Object subtypes for which this
649 	   message is valid (for object-type-specific message) */
650 	const OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;
651 										/* Object subtype for which msg.valid */
652 
653 	/* Message type checking information used to assertion-check the function
654 	   preconditions */
655 	const PARAMCHECK_TYPE paramCheck;	/* Parameter check assertion type */
656 
657 	/* Pre- and post-message-dispatch handlers.  These perform any additional
658 	   checking and processing that may be necessary before and after a
659 	   message is dispatched to an object */
660 	PREDISPATCH_FUNCTION preDispatchFunction;
661 	POSTDISPATCH_FUNCTION postDispatchFunction;
662 
663 	/* Flags to indicate (potential) special-case handling for this message,
664 	   and the (optional) internal handler function that's used if the
665 	   message is handled directly by the kernel */
666 	int flags;							/* Special-case handling flags */
667 	INTERNALHANDLER_FUNCTION internalHandlerFunction;
668 	} MESSAGE_HANDLING_INFO;
669 
670 static const MESSAGE_HANDLING_INFO FAR_BSS messageHandlingInfo[] = {
671 	{ MESSAGE_NONE, ROUTE_NONE, 0, 0, 0, PARAMTYPE_NONE_NONE },
672 
673 	/* Control messages.  These messages aren't routed, are valid for all
674 	   object types and subtypes, take no (or minimal) parameters, and are
675 	   handled by the kernel */
676 	{ MESSAGE_DESTROY,				/* Destroy the object */
677 	  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,
678 	  PARAMTYPE_NONE_NONE,
679 	  PRE_POST_DISPATCH( SignalDependentObjects, SignalDependentDevices ) },
680 	{ MESSAGE_INCREFCOUNT,			/* Increment object ref.count */
681 	  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,
682 	  PARAMTYPE_NONE_NONE,
683 	  HANDLE_INTERNAL( incRefCount ) },
684 	{ MESSAGE_DECREFCOUNT,			/* Decrement object ref.count */
685 	  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,
686 	  PARAMTYPE_NONE_NONE,
687 	  HANDLE_INTERNAL( decRefCount ) },
688 	{ MESSAGE_GETDEPENDENT,			/* Get dependent object */
689 	  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,
690 	  PARAMTYPE_DATA_OBJTYPE,
691 	  HANDLE_INTERNAL( getDependentObject ) },
692 	{ MESSAGE_SETDEPENDENT,			/* Set dependent object (e.g. ctx->dev) */
693 	  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,
694 	  PARAMTYPE_DATA_SETDEPTYPE,
695 	  HANDLE_INTERNAL( setDependentObject ) },
696 	{ MESSAGE_CLONE,				/* Clone the object (only valid for ctxs) */
697 	  ROUTE_FIXED( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_HASH, ST_NONE, ST_NONE,
698 	  PARAMTYPE_NONE_ANY,
699 	  HANDLE_INTERNAL( cloneObject ) },
700 
701 	/* Attribute messages.  These messages are implicitly routed by attribute
702 	   type, more specific checking is performed using the attribute ACL's */
703 	{ MESSAGE_GETATTRIBUTE,			/* Get numeric object attribute */
704 	  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C,
705 	  PARAMTYPE_DATA_ATTRIBUTE,
706 	  PRE_POST_DISPATCH( CheckAttributeAccess, MakeObjectExternal ) },
707 	{ MESSAGE_GETATTRIBUTE_S,		/* Get string object attribute */
708 	  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C,
709 	  PARAMTYPE_DATA_ATTRIBUTE,
710 	  PRE_DISPATCH( CheckAttributeAccess ) },
711 	{ MESSAGE_SETATTRIBUTE,			/* Set numeric object attribute */
712 	  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C,
713 	  PARAMTYPE_DATA_ATTRIBUTE,
714 	  PRE_POST_DISPATCH( CheckAttributeAccess, ChangeStateOpt ) },
715 	{ MESSAGE_SETATTRIBUTE_S,		/* Set string object attribute */
716 	  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C,
717 	  PARAMTYPE_DATA_ATTRIBUTE,
718 	  PRE_POST_DISPATCH( CheckAttributeAccess, ChangeStateOpt ) },
719 	{ MESSAGE_DELETEATTRIBUTE,		/* Delete object attribute */
720 	  ROUTE_IMPLICIT, ST_CTX_ANY | ST_CERT_ANY, ST_NONE, ST_SESS_ANY | ST_USER_NORMAL | ST_USER_SO,
721 	  PARAMTYPE_NONE_ANY,
722 	  PRE_DISPATCH( CheckAttributeAccess ) },
723 
724 	/* General messages to objects */
725 	{ MESSAGE_COMPARE,				/* Compare objs.or obj.properties */
726 	  ROUTE_SPECIAL( CompareMessageTarget ), ST_CTX_ANY | ST_CERT_ANY, ST_NONE, ST_NONE,
727 	  PARAMTYPE_DATA_COMPARETYPE,
728 	  PRE_DISPATCH( CheckCompareParam ) },
729 	{ MESSAGE_CHECK,				/* Check object info */
730 	  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,
731 	  PARAMTYPE_NONE_CHECKTYPE,
732 	  PRE_POST_DISPATCH( CheckCheckParam, ForwardToDependentObject ) },
733 	{ MESSAGE_SELFTEST,				/* Perform a self-test */
734 	  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_SYSTEM, ST_NONE,
735 	  PARAMTYPE_NONE_NONE,
736 	  NULL, NULL,
737 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
738 
739 	/* Messages sent from the kernel to object message handlers.  These
740 	   messages are sent directly to the object from inside the kernel in
741 	   response to a control message, so we set the checking to disallow
742 	   everything to catch any that arrive from outside */
743 	{ MESSAGE_CHANGENOTIFY,			/* Notification of obj.status chge.*/
744 	  ROUTE_NONE, ST_NONE, ST_NONE, ST_NONE, PARAMTYPE_NONE_NONE },
745 
746 	/* Object-type-specific messages: Contexts */
747 	{ MESSAGE_CTX_ENCRYPT,			/* Context: Action = encrypt */
748 	  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC, ST_NONE, ST_NONE,
749 	  PARAMTYPE_DATA_LENGTH,
750 	  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
751 	{ MESSAGE_CTX_DECRYPT,			/* Context: Action = decrypt */
752 	  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC, ST_NONE, ST_NONE,
753 	  PARAMTYPE_DATA_LENGTH,
754 	  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
755 	{ MESSAGE_CTX_SIGN,				/* Context: Action = sign */
756 	  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_PKC, ST_NONE, ST_NONE,
757 	  PARAMTYPE_DATA_LENGTH,
758 	  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
759 	{ MESSAGE_CTX_SIGCHECK,			/* Context: Action = sigcheck */
760 	  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_PKC, ST_NONE, ST_NONE,
761 	  PARAMTYPE_DATA_LENGTH,
762 	  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
763 	{ MESSAGE_CTX_HASH,				/* Context: Action = hash */
764 	  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_HASH | ST_CTX_MAC, ST_NONE, ST_NONE,
765 	  PARAMTYPE_DATA_LENGTH,
766 	  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
767 	{ MESSAGE_CTX_GENKEY,			/* Context: Generate a key */
768 	  ROUTE( OBJECT_TYPE_CONTEXT ),
769 		ST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE,
770 	  PARAMTYPE_NONE_NONE,
771 	  PRE_POST_DISPATCH( CheckState, ChangeState ) },
772 	{ MESSAGE_CTX_GENIV,			/* Context: Generate an IV */
773 	  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV, ST_NONE, ST_NONE,
774 	  PARAMTYPE_NONE_NONE },
775 
776 	/* Object-type-specific messages: Certificates */
777 	{ MESSAGE_CRT_SIGN,				/* Cert: Action = sign certificate */
778 	  ROUTE( OBJECT_TYPE_CERTIFICATE ),
779 		ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \
780 		ST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE,
781 	  PARAMTYPE_NONE_ANY,
782 	  PRE_POST_DISPATCH( CheckStateParamHandle, ChangeState ) },
783 	{ MESSAGE_CRT_SIGCHECK,			/* Cert: Action = check/verify certificate */
784 	  ROUTE( OBJECT_TYPE_CERTIFICATE ),
785 		ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \
786 		ST_CERT_RTCS_RESP | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE,
787 	  PARAMTYPE_NONE_ANY,
788 	  PRE_DISPATCH( CheckParamHandleOpt ) },
789 	{ MESSAGE_CRT_EXPORT,			/* Cert: Export encoded certificate data */
790 	  ROUTE( OBJECT_TYPE_CERTIFICATE ), ST_CERT_ANY, ST_NONE, ST_NONE,
791 	  PARAMTYPE_DATA_FORMATTYPE,
792 	  PRE_DISPATCH( CheckExportAccess ) },
793 
794 	/* Object-type-specific messages: Devices */
795 	{ MESSAGE_DEV_QUERYCAPABILITY,	/* Device: Query capability */
796 	  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
797 	  PARAMTYPE_DATA_ANY },
798 	{ MESSAGE_DEV_EXPORT,			/* Device: Action = export key */
799 	  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
800 	  PARAMTYPE_DATA_MECHTYPE,
801 	  PRE_DISPATCH( CheckMechanismWrapAccess ),
802 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
803 	{ MESSAGE_DEV_IMPORT,			/* Device: Action = import key */
804 	  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
805 	  PARAMTYPE_DATA_MECHTYPE,
806 	  PRE_DISPATCH( CheckMechanismWrapAccess ),
807 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
808 	{ MESSAGE_DEV_SIGN,				/* Device: Action = sign */
809 	  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
810 	  PARAMTYPE_DATA_MECHTYPE,
811 	  PRE_DISPATCH( CheckMechanismSignAccess ),
812 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
813 	{ MESSAGE_DEV_SIGCHECK,			/* Device: Action = sig.check */
814 	  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
815 	  PARAMTYPE_DATA_MECHTYPE,
816 	  PRE_DISPATCH( CheckMechanismSignAccess ),
817 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
818 	{ MESSAGE_DEV_DERIVE,			/* Device: Action = derive key */
819 	  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
820 	  PARAMTYPE_DATA_MECHTYPE,
821 	  PRE_DISPATCH( CheckMechanismDeriveAccess ),
822 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
823 	{ MESSAGE_DEV_KDF,				/* Device: Action = KDF key */
824 	  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
825 	  PARAMTYPE_DATA_MECHTYPE,
826 	  PRE_DISPATCH( CheckMechanismKDFAccess ),
827 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
828 	{ MESSAGE_DEV_CREATEOBJECT,		/* Device: Create object */
829 	  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
830 	  PARAMTYPE_DATA_OBJTYPE,
831 	  PRE_POST_DISPATCH( CheckCreate, MakeObjectExternal ),
832 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
833 	{ MESSAGE_DEV_CREATEOBJECT_INDIRECT,/* Device: Create obj.from data */
834 	  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE,
835 	  PARAMTYPE_DATA_OBJTYPE,
836 	  PRE_POST_DISPATCH( CheckCreate, MakeObjectExternal ),
837 	  MESSAGE_HANDLING_FLAG_MAYUNLOCK },
838 
839 	/* Object-type-specific messages: Envelopes */
840 	{ MESSAGE_ENV_PUSHDATA,			/* Envelope: Push data */
841 	  ROUTE_FIXED_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),
842 		ST_NONE, ST_ENV_ANY, ST_SESS_ANY_DATA,
843 	  PARAMTYPE_DATA_NONE,
844 	  PRE_DISPATCH( CheckData ) },
845 	{ MESSAGE_ENV_POPDATA,			/* Envelope: Pop data */
846 	  ROUTE_FIXED_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),
847 		ST_NONE, ST_ENV_ANY, ST_SESS_ANY_DATA,
848 	  PARAMTYPE_DATA_NONE,
849 	  PRE_DISPATCH( CheckData ) },
850 
851 	/* Object-type-specific messages: Keysets */
852 	{ MESSAGE_KEY_GETKEY,			/* Keyset: Instantiate ctx/certificate */
853 	  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
854 		ST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
855 	  PARAMTYPE_DATA_ITEMTYPE,
856 	  PRE_POST_DISPATCH( CheckKeysetAccess, MakeObjectExternal ) },
857 	{ MESSAGE_KEY_SETKEY,			/* Keyset: Add ctx/certificate */
858 	  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
859 		ST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
860 	  PARAMTYPE_DATA_ITEMTYPE,
861 	  PRE_DISPATCH( CheckKeysetAccess ) },
862 	{ MESSAGE_KEY_DELETEKEY,		/* Keyset: Delete key */
863 	  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
864 		ST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
865 	  PARAMTYPE_DATA_ITEMTYPE,
866 	  PRE_DISPATCH( CheckKeysetAccess ) },
867 	{ MESSAGE_KEY_GETFIRSTCERT,		/* Keyset: Get first cert in sequence */
868 	  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
869 		ST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
870 	  PARAMTYPE_DATA_ITEMTYPE,
871 	  PRE_DISPATCH( CheckKeysetAccess ) },
872 	{ MESSAGE_KEY_GETNEXTCERT,		/* Keyset: Get next cert in sequence */
873 	  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
874 		ST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
875 	  PARAMTYPE_DATA_ITEMTYPE,
876 	  PRE_POST_DISPATCH( CheckKeysetAccess, MakeObjectExternal ) },
877 	{ MESSAGE_KEY_CERTMGMT,			/* Keyset: Certificate management */
878 	  ROUTE_FIXED( OBJECT_TYPE_KEYSET ),
879 		ST_NONE, ST_KEYSET_DBMS_STORE, ST_NONE,
880 	  PARAMTYPE_DATA_CERTMGMTTYPE,
881 	  PRE_POST_DISPATCH( CheckCertMgmtAccess, MakeObjectExternal ) },
882 
883 	/* Object-type-specific messages: Users */
884 	{ MESSAGE_USER_USERMGMT,		/* User: User management */
885 	  ROUTE_FIXED( OBJECT_TYPE_USER ), ST_NONE, ST_NONE, ST_USER_SO,
886 	  PARAMTYPE_ANY_USERMGMTTYPE,
887 	  PRE_POST_DISPATCH( CheckUserMgmtAccess, HandleZeroise ) },
888 	{ MESSAGE_USER_TRUSTMGMT,		/* User: Trust management */
889 	  ROUTE_FIXED( OBJECT_TYPE_USER ), ST_NONE, ST_NONE, ST_USER_SO,
890 	  PARAMTYPE_ANY_TRUSTMGMTTYPE,
891 	  PRE_DISPATCH( CheckTrustMgmtAccess ) },
892 
893 	/* End-of-ACL marker */
894 	{ MESSAGE_NONE, ROUTE_NONE, 0, PARAMTYPE_NONE_NONE },
895 	{ MESSAGE_NONE, ROUTE_NONE, 0, PARAMTYPE_NONE_NONE }
896 	};
897 
898 /* Check the basic validity of message parameters.  Note that this only
899    checks for coding errors (krnlSendMessage() having been called
900    correctly), it doesn't perform parameter validation, which is the
901    job of the full ACL checks */
902 
903 CHECK_RETVAL_BOOL
checkParams(IN_ENUM (PARAMTYPE)const PARAMCHECK_TYPE paramCheck,const void * messageDataPtr,const int messageValue)904 static BOOLEAN checkParams( IN_ENUM( PARAMTYPE ) \
905 								const PARAMCHECK_TYPE paramCheck,
906 							const void *messageDataPtr,
907 							const int messageValue )
908 	{
909 	REQUIRES_B( paramCheck >= PARAMTYPE_NONE_NONE && \
910 				paramCheck < PARAMTYPE_LAST );
911 
912 	switch( paramCheck )
913 		{
914 		case PARAMTYPE_NONE_NONE:
915 			return( messageDataPtr == NULL && messageValue == 0 );
916 
917 		case PARAMTYPE_NONE_ANY:
918 			return( messageDataPtr == NULL );
919 
920 		case PARAMTYPE_NONE_BOOLEAN:
921 			return( messageDataPtr == NULL && \
922 					( messageValue == FALSE || messageValue == TRUE ) );
923 
924 		case PARAMTYPE_NONE_CHECKTYPE:
925 			return( messageDataPtr == NULL && \
926 					( messageValue > MESSAGE_CHECK_NONE && \
927 					  messageValue < MESSAGE_CHECK_LAST ) );
928 
929 		case PARAMTYPE_DATA_NONE:
930 			return( messageDataPtr != NULL && messageValue == 0 );
931 
932 		case PARAMTYPE_DATA_ANY:
933 			return( messageDataPtr != NULL );
934 
935 		case PARAMTYPE_DATA_ATTRIBUTE:
936 			return( messageDataPtr != NULL && \
937 					( ( messageValue > CRYPT_ATTRIBUTE_NONE && \
938 						messageValue < CRYPT_ATTRIBUTE_LAST ) || \
939 					  ( messageValue > CRYPT_IATTRIBUTE_FIRST && \
940 					    messageValue < CRYPT_IATTRIBUTE_LAST ) ) );
941 
942 		case PARAMTYPE_DATA_LENGTH:
943 			return( messageDataPtr != NULL && messageValue >= 0 );
944 
945 		case PARAMTYPE_DATA_OBJTYPE:
946 			return( messageDataPtr != NULL && \
947 					( messageValue > OBJECT_TYPE_NONE && \
948 					  messageValue < OBJECT_TYPE_LAST ) );
949 
950 		case PARAMTYPE_DATA_MECHTYPE:
951 			return( messageDataPtr != NULL && \
952 					( messageValue > MECHANISM_NONE && \
953 					  messageValue < MECHANISM_LAST ) );
954 
955 		case PARAMTYPE_DATA_ITEMTYPE:
956 			return( messageDataPtr != NULL && \
957 					( messageValue > KEYMGMT_ITEM_NONE && \
958 					  messageValue < KEYMGMT_ITEM_LAST ) );
959 
960 		case PARAMTYPE_DATA_FORMATTYPE:
961 			return( messageDataPtr != NULL && \
962 					( messageValue > CRYPT_CERTFORMAT_NONE && \
963 					  messageValue < CRYPT_CERTFORMAT_LAST ) );
964 
965 		case PARAMTYPE_DATA_COMPARETYPE:
966 			return( messageDataPtr != NULL && \
967 					( messageValue > MESSAGE_COMPARE_NONE && \
968 					  messageValue < MESSAGE_COMPARE_LAST ) );
969 
970 		case PARAMTYPE_DATA_SETDEPTYPE:
971 			return( messageDataPtr != NULL && \
972 					messageValue > SETDEP_OPTION_NONE && \
973 					messageValue < SETDEP_OPTION_LAST );
974 
975 		case PARAMTYPE_DATA_CERTMGMTTYPE:
976 			return( messageDataPtr != NULL && \
977 					messageValue > CRYPT_CERTACTION_NONE && \
978 					messageValue < CRYPT_CERTACTION_LAST );
979 
980 		case PARAMTYPE_ANY_USERMGMTTYPE:
981 			return( messageValue > MESSAGE_USERMGMT_NONE && \
982 					messageValue < MESSAGE_USERMGMT_LAST );
983 
984 		case PARAMTYPE_ANY_TRUSTMGMTTYPE:
985 			return( messageValue > MESSAGE_TRUSTMGMT_NONE && \
986 					messageValue < MESSAGE_TRUSTMGMT_LAST );
987 
988 		default:
989 			retIntError_Boolean();
990 		}
991 
992 	retIntError_Boolean();
993 	}
994 
995 /****************************************************************************
996 *																			*
997 *							Init/Shutdown Functions							*
998 *																			*
999 ****************************************************************************/
1000 
1001 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initSendMessage(INOUT KERNEL_DATA * krnlDataPtr)1002 int initSendMessage( INOUT KERNEL_DATA *krnlDataPtr )
1003 	{
1004 	int i;
1005 
1006 	assert( isWritePtr( krnlDataPtr, sizeof( KERNEL_DATA ) ) );
1007 
1008 	/* If we're running a fuzzing build, skip the lengthy self-checks */
1009 #ifdef CONFIG_FUZZ
1010 	krnlData = krnlDataPtr;
1011 	return( CRYPT_OK );
1012 #endif /* CONFIG_FUZZ */
1013 
1014 	/* Perform a consistency check on various things that need to be set
1015 	   up in a certain way for things to work properly */
1016 	static_assert( MESSAGE_CTX_DECRYPT == MESSAGE_CTX_ENCRYPT + 1, \
1017 				   "Message value" );
1018 	static_assert( MESSAGE_CTX_SIGN == MESSAGE_CTX_DECRYPT + 1, \
1019 				   "Message value" );
1020 	static_assert( MESSAGE_CTX_SIGCHECK == MESSAGE_CTX_SIGN + 1, \
1021 				   "Message value" );
1022 	static_assert( MESSAGE_CTX_HASH == MESSAGE_CTX_SIGCHECK + 1, \
1023 				   "Message value" );
1024 	static_assert( MESSAGE_CTX_GENKEY == MESSAGE_CTX_HASH + 1, \
1025 				   "Message value" );
1026 	static_assert( MESSAGE_GETATTRIBUTE_S == MESSAGE_GETATTRIBUTE + 1, \
1027 				   "Message value" );
1028 	static_assert( MESSAGE_SETATTRIBUTE == MESSAGE_GETATTRIBUTE_S + 1, \
1029 				   "Message value" );
1030 	static_assert( MESSAGE_SETATTRIBUTE_S == MESSAGE_SETATTRIBUTE + 1, \
1031 				   "Message value" );
1032 	static_assert( MESSAGE_DELETEATTRIBUTE == MESSAGE_SETATTRIBUTE_S + 1, \
1033 				   "Message value" );
1034 
1035 	/* Perform a consistency check on various internal values and constants */
1036 	assert( ACTION_PERM_COUNT == 6 );
1037 
1038 	/* Perform a consistency check on the parameter ACL */
1039 	for( i = 0; messageParamACLTbl[ i ].type != MESSAGE_NONE && \
1040 				i < FAILSAFE_ARRAYSIZE( messageParamACLTbl, MESSAGE_ACL );
1041 		 i++ )
1042 		{
1043 		const MESSAGE_ACL *messageParamACL = &messageParamACLTbl[ i ];
1044 
1045 		ENSURES( isParamMessage( messageParamACL->type ) && \
1046 				 !( messageParamACL->objectACL.subTypeA & ( SUBTYPE_CLASS_B | \
1047 															SUBTYPE_CLASS_C ) ) && \
1048 				 !( messageParamACL->objectACL.subTypeB & ( SUBTYPE_CLASS_A | \
1049 															SUBTYPE_CLASS_C ) ) && \
1050 				 !( messageParamACL->objectACL.subTypeC & ( SUBTYPE_CLASS_A | \
1051 															SUBTYPE_CLASS_B ) ) );
1052 		}
1053 	ENSURES( i < FAILSAFE_ARRAYSIZE( messageParamACLTbl, MESSAGE_ACL ) );
1054 
1055 	/* Perform a consistency check on the message handling information */
1056 	for( i = MESSAGE_NONE + 1; i < MESSAGE_LAST; i++ )
1057 		{
1058 		const MESSAGE_HANDLING_INFO *messageInfo = &messageHandlingInfo[ i ];
1059 
1060 		ENSURES( messageInfo->messageType == i && \
1061 				 messageInfo->paramCheck >= PARAMTYPE_NONE_NONE && \
1062 				 messageInfo->paramCheck < PARAMTYPE_LAST );
1063 		ENSURES( ( messageInfo->messageType >= MESSAGE_ENV_PUSHDATA && \
1064 				   messageInfo->messageType <= MESSAGE_KEY_GETNEXTCERT ) || \
1065 				 ( messageInfo->routingTarget >= OBJECT_TYPE_NONE && \
1066 				   messageInfo->routingTarget <= OBJECT_TYPE_LAST ) );
1067 		ENSURES( messageInfo->messageType == MESSAGE_CLONE || \
1068 				 messageInfo->messageType == MESSAGE_COMPARE || \
1069 				 ( messageInfo->routingTarget == OBJECT_TYPE_NONE && \
1070 				   messageInfo->routingFunction == NULL ) || \
1071 				 ( messageInfo->routingTarget != OBJECT_TYPE_NONE && \
1072 				   messageInfo->routingFunction != NULL ) );
1073 		ENSURES( !( messageInfo->subTypeA & ( SUBTYPE_CLASS_B | \
1074 											  SUBTYPE_CLASS_C ) ) && \
1075 				 !( messageInfo->subTypeB & ( SUBTYPE_CLASS_A | \
1076 											  SUBTYPE_CLASS_C ) ) && \
1077 				 !( messageInfo->subTypeC & ( SUBTYPE_CLASS_A | \
1078 											  SUBTYPE_CLASS_B ) ) );
1079 		ENSURES( ( messageInfo->flags & MESSAGE_HANDLING_FLAG_INTERNAL ) || \
1080 				 messageInfo->messageType == MESSAGE_SELFTEST || \
1081 				 messageInfo->messageType == MESSAGE_CHANGENOTIFY || \
1082 				 messageInfo->messageType == MESSAGE_CTX_GENIV || \
1083 				 messageInfo->messageType == MESSAGE_DEV_QUERYCAPABILITY || \
1084 				 messageInfo->preDispatchFunction != NULL );
1085 		ENSURES( messageInfo->messageType == MESSAGE_SELFTEST || \
1086 				 messageInfo->messageType == MESSAGE_CHANGENOTIFY || \
1087 				 messageInfo->messageType == MESSAGE_CTX_GENIV || \
1088 				 messageInfo->messageType == MESSAGE_DEV_QUERYCAPABILITY || \
1089 				 ( messageInfo->preDispatchFunction != NULL || \
1090 				   messageInfo->postDispatchFunction != NULL || \
1091 				   messageInfo->internalHandlerFunction != NULL ) );
1092 		ENSURES( ( ( messageInfo->flags & MESSAGE_HANDLING_FLAG_INTERNAL ) && \
1093 					 messageInfo->internalHandlerFunction != NULL ) || \
1094 				 ( !( messageInfo->flags & MESSAGE_HANDLING_FLAG_INTERNAL ) && \
1095 					  messageInfo->internalHandlerFunction == NULL ) );
1096 		}
1097 
1098 	/* Set up the reference to the kernel data block */
1099 	krnlData = krnlDataPtr;
1100 
1101 	return( CRYPT_OK );
1102 	}
1103 
endSendMessage(void)1104 void endSendMessage( void )
1105 	{
1106 	krnlData = NULL;
1107 	}
1108 
1109 /****************************************************************************
1110 *																			*
1111 *								Message Queue								*
1112 *																			*
1113 ****************************************************************************/
1114 
1115 /* Enqueue a message */
1116 
1117 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
enqueueMessage(IN_HANDLE const int objectHandle,const MESSAGE_HANDLING_INFO * handlingInfoPtr,IN_MESSAGE const MESSAGE_TYPE message,IN_OPT const void * messageDataPtr,const int messageValue)1118 static int enqueueMessage( IN_HANDLE const int objectHandle,
1119 						   const MESSAGE_HANDLING_INFO *handlingInfoPtr,
1120 						   IN_MESSAGE const MESSAGE_TYPE message,
1121 						   IN_OPT const void *messageDataPtr,
1122 						   const int messageValue )
1123 	{
1124 	MESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;
1125 	int queuePos, i, iterationCount;
1126 	ORIGINAL_INT_VAR( queueEnd, krnlData->queueEnd );
1127 
1128 	assert( isReadPtr( handlingInfoPtr, sizeof( MESSAGE_HANDLING_INFO ) ) );
1129 
1130 	/* Precondition: It's a valid message being sent to a valid object */
1131 	REQUIRES( isValidObject( objectHandle ) );
1132 	REQUIRES( isValidMessage( message & MESSAGE_MASK ) );
1133 
1134 	/* Sanity-check the state/make sure that we don't overflow the queue
1135 	   (this object is not responding to messages... now all we need is
1136 	   GPF's).  We return a timeout error on overflow to indicate that there
1137 	   are too many messages queued for this (or other) objects */
1138 	if( krnlData->queueEnd < 0 || \
1139 		krnlData->queueEnd >= MESSAGE_QUEUE_SIZE - 1 )
1140 		{
1141 		ENSURES( krnlData->queueEnd >= 0 );
1142 		DEBUG_DIAG(( "Invalid kernel message queue state" ));
1143 		assert( DEBUG_WARN );
1144 		return( CRYPT_ERROR_TIMEOUT );
1145 		}
1146 
1147 	/* Precondition: There's room to enqueue the message */
1148 	REQUIRES( krnlData->queueEnd >= 0 && \
1149 			  krnlData->queueEnd < MESSAGE_QUEUE_SIZE - 1 );
1150 
1151 	/* Check whether a message to this object is already present in the
1152 	   queue */
1153 	for( queuePos = krnlData->queueEnd - 1, iterationCount = 0;
1154 		 queuePos >= 0 && iterationCount++ < MESSAGE_QUEUE_SIZE; queuePos-- )
1155 		{
1156 		if( messageQueue[ queuePos ].objectHandle == objectHandle )
1157 			break;
1158 		}
1159 	ENSURES( iterationCount < MESSAGE_QUEUE_SIZE );
1160 
1161 	/* Postcondition: queuePos = -1 if not present, position in queue if
1162 	   present */
1163 	ENSURES( queuePos == -1 || \
1164 			 ( queuePos >= 0 && queuePos < krnlData->queueEnd ) );
1165 
1166 	/* Sanity-check the queue positioning */
1167 	ENSURES( queuePos >= -1 && queuePos < krnlData->queueEnd );
1168 
1169 	/* Enqueue the message:
1170 
1171 		+---------------+		+---------------+
1172 		|.|.|x|x|y|z|   |	->	|.|.|x|x|#|y|z| |
1173 		+---------------+		+---------------+
1174 			   ^	 ^					 ^	   ^
1175 			  qPos	qEnd				qPos  qEnd */
1176 	queuePos++;		/* Insert after current position */
1177 	for( i = krnlData->queueEnd - 1, iterationCount = 0;
1178 		 i >= queuePos && iterationCount < MESSAGE_QUEUE_SIZE;
1179 		 i--, iterationCount++ )
1180 		messageQueue[ i + 1 ] = messageQueue[ i ];
1181 	ENSURES( iterationCount < MESSAGE_QUEUE_SIZE );
1182 	memset( &messageQueue[ queuePos ], 0, sizeof( MESSAGE_QUEUE_DATA ) );
1183 	messageQueue[ queuePos ].objectHandle = objectHandle;
1184 	messageQueue[ queuePos ].handlingInfoPtr = handlingInfoPtr;
1185 	messageQueue[ queuePos ].message = message;
1186 	messageQueue[ queuePos ].messageDataPtr = messageDataPtr;
1187 	messageQueue[ queuePos ].messageValue = messageValue;
1188 	krnlData->queueEnd++;
1189 
1190 	/* Postcondition: The queue is within bounds and has grown by one
1191 	   element */
1192 	ENSURES( krnlData->queueEnd > 0 && \
1193 			 krnlData->queueEnd <= MESSAGE_QUEUE_SIZE - 1 );
1194 	ENSURES( krnlData->queueEnd == ORIGINAL_VALUE( queueEnd ) + 1 );
1195 
1196 	/* If a message for this object is already present tell the caller to
1197 	   defer processing */
1198 	if( queuePos > 0 )
1199 		return( OK_SPECIAL );
1200 
1201 	return( CRYPT_OK );
1202 	}
1203 
1204 /* Dequeue a message */
1205 
1206 CHECK_RETVAL \
1207 static int dequeueMessage( IN_RANGE( 0, MESSAGE_QUEUE_SIZE ) \
1208 								const int messagePosition )
1209 	{
1210 	MESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;
1211 	int i, iterationCount;
1212 	ORIGINAL_INT_VAR( queueEnd, krnlData->queueEnd );
1213 
1214 	/* Precondition: We're deleting a valid queue position */
1215 	REQUIRES( messagePosition >= 0 && \
1216 			  messagePosition < krnlData->queueEnd );
1217 	REQUIRES( krnlData->queueEnd > 0 && \
1218 			  krnlData->queueEnd < MESSAGE_QUEUE_SIZE );
1219 
1220 	/* Move the remaining messages down and clear the last entry */
1221 	for( i = messagePosition, iterationCount = 0;
1222 		 i < krnlData->queueEnd - 1 && \
1223 			iterationCount++ < MESSAGE_QUEUE_SIZE; i++ )
1224 		messageQueue[ i ] = messageQueue[ i + 1 ];
1225 	ENSURES( iterationCount < MESSAGE_QUEUE_SIZE );
1226 	zeroise( &messageQueue[ krnlData->queueEnd - 1 ],
1227 			 sizeof( MESSAGE_QUEUE_DATA ) );
1228 	krnlData->queueEnd--;
1229 
1230 	/* Postcondition: the queue is one element shorter, all queue entries
1231 	   are valid, and all non-queue entries are empty */
1232 	ENSURES( krnlData->queueEnd == ORIGINAL_VALUE( queueEnd ) - 1 );
1233 	ENSURES( krnlData->queueEnd >= 0 && \
1234 			 krnlData->queueEnd < MESSAGE_QUEUE_SIZE - 1 );
1235 	FORALL( i, 0, krnlData->queueEnd,
1236 			messageQueue[ i ].handlingInfoPtr != NULL );
1237 	FORALL( i, krnlData->queueEnd, MESSAGE_QUEUE_SIZE,
1238 			messageQueue[ i ].handlingInfoPtr == NULL );
1239 
1240 	return( CRYPT_OK );
1241 	}
1242 
1243 /* Get the next message in the queue */
1244 
1245 CHECK_RETVAL_BOOL \
getNextMessage(IN_HANDLE const int objectHandle,OUT_OPT MESSAGE_QUEUE_DATA * messageQueueInfo)1246 static BOOLEAN getNextMessage( IN_HANDLE const int objectHandle,
1247 							   OUT_OPT MESSAGE_QUEUE_DATA *messageQueueInfo )
1248 	{
1249 	MESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;
1250 	int i;
1251 
1252 	assert( messageQueueInfo == NULL || \
1253 			isWritePtr( messageQueueInfo, sizeof( MESSAGE_QUEUE_DATA ) ) );
1254 
1255 	/* Preconditions: It's a valid object table entry.  It's not necessarily
1256 	   a valid object since we may be de-queueing messages for it because
1257 	   it's just been destroyed */
1258 	REQUIRES_B( objectHandle == SYSTEM_OBJECT_HANDLE || \
1259 				objectHandle == DEFAULTUSER_OBJECT_HANDLE || \
1260 				isHandleRangeValid( objectHandle ) );
1261 
1262 	/* Clear return value */
1263 	if( messageQueueInfo != NULL )
1264 		memset( messageQueueInfo, 0, sizeof( MESSAGE_QUEUE_DATA ) );
1265 
1266 	/* Sanity-check the state */
1267 	ENSURES_B( krnlData->queueEnd >= 0 && \
1268 			   krnlData->queueEnd < MESSAGE_QUEUE_SIZE );
1269 
1270 	/* Find the next message for this object.  Since other messages can have
1271 	   come and gone in the meantime, we have to scan from the start each
1272 	   time */
1273 	for( i = 0; i < krnlData->queueEnd && i < MESSAGE_QUEUE_SIZE; i++ )
1274 		{
1275 		if( messageQueue[ i ].objectHandle == objectHandle )
1276 			{
1277 			int status;
1278 
1279 			if( messageQueueInfo != NULL )
1280 				*messageQueueInfo = messageQueue[ i ];
1281 			status = dequeueMessage( i );
1282 			if( cryptStatusError( status ) )
1283 				return( FALSE );
1284 
1285 			return( TRUE );
1286 			}
1287 		}
1288 	ENSURES_B( i < MESSAGE_QUEUE_SIZE );
1289 
1290 	/* Postcondition: There are no more messages for this object present in
1291 	   the queue */
1292 	FORALL( i, 0, krnlData->queueEnd,
1293 			messageQueue[ i ].objectHandle != objectHandle );
1294 
1295 	return( FALSE );
1296 	}
1297 
1298 /* Dequeue all messages for an object in the queue */
1299 
dequeueAllMessages(IN_HANDLE const int objectHandle)1300 static void dequeueAllMessages( IN_HANDLE const int objectHandle )
1301 	{
1302 	int iterationCount;
1303 
1304 	/* Preconditions: It's a valid object table entry.  It's not necessarily
1305 	   a valid object since we may be de-queueing messages for it because
1306 	   it's just been destroyed */
1307 	REQUIRES_V( objectHandle == SYSTEM_OBJECT_HANDLE || \
1308 				objectHandle == DEFAULTUSER_OBJECT_HANDLE || \
1309 				isHandleRangeValid( objectHandle ) );
1310 
1311 	/* Dequeue all messages for a given object */
1312 	for( iterationCount = 0;
1313 		 getNextMessage( objectHandle, NULL ) && \
1314 			iterationCount < MESSAGE_QUEUE_SIZE;
1315 		 iterationCount++ );
1316 	ENSURES_V( iterationCount < MESSAGE_QUEUE_SIZE );
1317 
1318 	/* Postcondition: There are no more messages for this object present in
1319 	   the queue */
1320 	FORALL( i, 0, krnlData->queueEnd,
1321 			krnlData->messageQueue[ i ].objectHandle != objectHandle );
1322 	}
1323 
1324 /****************************************************************************
1325 *																			*
1326 *							Message Dispatcher								*
1327 *																			*
1328 ****************************************************************************/
1329 
1330 /* Process a message that's handled internally by the kernel, for example
1331    one that accesses an object's kernel attributes */
1332 
1333 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
processInternalMessage(IN_HANDLE const int localObjectHandle,const MESSAGE_HANDLING_INFO * handlingInfoPtr,IN_MESSAGE const MESSAGE_TYPE message,IN_OPT void * messageDataPtr,const int messageValue,IN_OPT const void * aclPtr)1334 static int processInternalMessage( IN_HANDLE const int localObjectHandle,
1335 								   const MESSAGE_HANDLING_INFO *handlingInfoPtr,
1336 								   IN_MESSAGE const MESSAGE_TYPE message,
1337 								   IN_OPT void *messageDataPtr,
1338 								   const int messageValue,
1339 								   IN_OPT const void *aclPtr )
1340 	{
1341 	int status;
1342 
1343 	assert( isReadPtr( handlingInfoPtr, sizeof( MESSAGE_HANDLING_INFO ) ) );
1344 
1345 	/* Precondition: It's a valid message being sent to a valid object */
1346 	REQUIRES( isValidObject( localObjectHandle ) );
1347 	REQUIRES( isValidMessage( message & MESSAGE_MASK ) );
1348 
1349 	/* If there's a pre-dispatch handler, invoke it */
1350 	if( handlingInfoPtr->preDispatchFunction != NULL )
1351 		{
1352 		status = handlingInfoPtr->preDispatchFunction( localObjectHandle,
1353 									message, messageDataPtr, messageValue,
1354 									aclPtr );
1355 		if( cryptStatusError( status ) )
1356 			return( status );
1357 		}
1358 
1359 	/* Inner precondition: Either the message as a whole is internally
1360 	   handled or it's a property attribute */
1361 	REQUIRES( handlingInfoPtr->internalHandlerFunction != NULL || \
1362 			  isAttributeMessage( message & MESSAGE_MASK ) );
1363 
1364 	/* If it's an object property attribute (which is handled by the kernel),
1365 	   get or set its value */
1366 	if( handlingInfoPtr->internalHandlerFunction == NULL )
1367 		{
1368 		/* Precondition: Object properties are always numeric attributes,
1369 		   and there's always a message value present */
1370 		REQUIRES( handlingInfoPtr->messageType == MESSAGE_GETATTRIBUTE || \
1371 				  handlingInfoPtr->messageType == MESSAGE_SETATTRIBUTE );
1372 		REQUIRES( messageDataPtr != NULL );
1373 
1374 		if( handlingInfoPtr->messageType == MESSAGE_GETATTRIBUTE )
1375 			status = getPropertyAttribute( localObjectHandle, messageValue,
1376 										   messageDataPtr );
1377 		else
1378 			status = setPropertyAttribute( localObjectHandle, messageValue,
1379 										   messageDataPtr );
1380 		}
1381 	else
1382 		{
1383 		/* It's a kernel-handled message, process it */
1384 		status = handlingInfoPtr->internalHandlerFunction( localObjectHandle,
1385 												messageValue, messageDataPtr,
1386 												isInternalMessage( message ) );
1387 		}
1388 	if( cryptStatusError( status ) )
1389 		{
1390 		/* Postcondition: It's a genuine error, or a special-case condition
1391 		   such as the object creation being aborted, which produces an
1392 		   OK_SPECIAL status to tell the caller to convert the message that
1393 		   triggered this into a MESSAGE_DESTROY */
1394 		ENSURES( cryptStatusError( status ) || status == OK_SPECIAL );
1395 
1396 		return( status );
1397 		}
1398 
1399 	/* If there's a post-dispatch handler, invoke it */
1400 	if( handlingInfoPtr->postDispatchFunction != NULL )
1401 		{
1402 		status = handlingInfoPtr->postDispatchFunction( localObjectHandle,
1403 									message, messageDataPtr, messageValue,
1404 									aclPtr );
1405 		if( cryptStatusError( status ) )
1406 			return( status );
1407 		}
1408 
1409 	return( CRYPT_OK );
1410 	}
1411 
1412 /* Dispatch a message to an object */
1413 
1414 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \
dispatchMessage(IN_HANDLE const int localObjectHandle,const MESSAGE_QUEUE_DATA * messageQueueData,INOUT OBJECT_INFO * objectInfoPtr,IN_OPT const void * aclPtr)1415 static int dispatchMessage( IN_HANDLE const int localObjectHandle,
1416 							const MESSAGE_QUEUE_DATA *messageQueueData,
1417 							INOUT OBJECT_INFO *objectInfoPtr,
1418 							IN_OPT const void *aclPtr )
1419 	{
1420 	const MESSAGE_HANDLING_INFO *handlingInfoPtr = \
1421 						messageQueueData->handlingInfoPtr;
1422 	const MESSAGE_FUNCTION messageFunction = \
1423 						FNPTR_GET( objectInfoPtr->messageFunction );
1424 	const MESSAGE_TYPE localMessage = \
1425 						messageQueueData->message & MESSAGE_MASK;
1426 	MESSAGE_FUNCTION_EXTINFO messageExtInfo;
1427 	void *objectPtr = objectInfoPtr->objectPtr;
1428 	BOOLEAN mayUnlock = FALSE;
1429 	int status;
1430 	ORIGINAL_INT_VAR( lockCount, objectInfoPtr->lockCount );
1431 
1432 	assert( isReadPtr( messageQueueData, sizeof( MESSAGE_QUEUE_DATA ) ) );
1433 	assert( isWritePtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );
1434 
1435 	REQUIRES( isValidObject( localObjectHandle ) );
1436 	REQUIRES( !isInUse( localObjectHandle ) || \
1437 			  isObjectOwner( localObjectHandle ) );
1438 	ENSURES( messageFunction != NULL );
1439 
1440 	/* If there's a pre-dispatch handler present, apply it */
1441 	if( handlingInfoPtr->preDispatchFunction != NULL )
1442 		{
1443 		status = handlingInfoPtr->preDispatchFunction( localObjectHandle,
1444 										messageQueueData->message,
1445 										messageQueueData->messageDataPtr,
1446 										messageQueueData->messageValue,
1447 										aclPtr );
1448 		if( cryptStatusError( status ) )
1449 			return( status );
1450 		}
1451 
1452 	/* Some objects (generally the system object and to a lesser extent other
1453 	   devices and the default user object) may unlock themselves while
1454 	   processing a message when they forward the message elsewhere or perform
1455 	   non-object-specific processing.  If this may be the case then we pass
1456 	   in an extended message structure to record this information */
1457 	initMessageExtInfo( &messageExtInfo, objectPtr );
1458 	if( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) || \
1459 		( handlingInfoPtr->flags & MESSAGE_HANDLING_FLAG_MAYUNLOCK ) )
1460 		{
1461 		mayUnlock = TRUE;
1462 		objectPtr = &messageExtInfo;
1463 		}
1464 
1465 	/* Mark the object as busy so that we have it available for our
1466 	   exclusive use and further messages to it will be enqueued, dispatch
1467 	   the message with the object table unlocked, and mark the object as
1468 	   non-busy again */
1469 	objectInfoPtr->lockCount++;
1470 #ifdef USE_THREADS
1471 	objectInfoPtr->lockOwner = THREAD_SELF();
1472 #endif /* USE_THREADS */
1473 	MUTEX_UNLOCK( objectTable );
1474 	status = messageFunction( objectPtr, localMessage,
1475 							  ( MESSAGE_CAST ) messageQueueData->messageDataPtr,
1476 							  messageQueueData->messageValue );
1477 	MUTEX_LOCK( objectTable );
1478 	objectInfoPtr = &krnlData->objectTable[ localObjectHandle ];
1479 	if( !isValidType( objectInfoPtr->type ) )
1480 		retIntError();	/* Something catastrophic happened while unlocked */
1481 	if( !( mayUnlock && isMessageObjectUnlocked( &messageExtInfo ) ) )
1482 		objectInfoPtr->lockCount--;
1483 
1484 	/* Postcondition: The lock count is non-negative and, if it's not the
1485 	   system object, has been reset to its previous value */
1486 	ENSURES( objectInfoPtr->lockCount >= 0 && \
1487 			 ( localObjectHandle == SYSTEM_OBJECT_HANDLE ||
1488 			   objectInfoPtr->lockCount == ORIGINAL_VALUE( lockCount ) ) );
1489 
1490 	/* If there's a post-dispatch handler present, apply it.  Since a
1491 	   destroy object message always succeeds but can return an error code
1492 	   (typically CRYPT_ERROR_INCOMPLETE), we don't treat an error return as
1493 	   a real error status for the purposes of further processing */
1494 	if( ( cryptStatusOK( status ) || localMessage == MESSAGE_DESTROY ) && \
1495 		handlingInfoPtr->postDispatchFunction != NULL )
1496 		{
1497 		const BOOLEAN isIncomplete = ( localMessage == MESSAGE_DESTROY && \
1498 									   status == CRYPT_ERROR_INCOMPLETE ) ? \
1499 									 TRUE : FALSE;
1500 
1501 		status = handlingInfoPtr->postDispatchFunction( localObjectHandle,
1502 												messageQueueData->message,
1503 												messageQueueData->messageDataPtr,
1504 												messageQueueData->messageValue,
1505 												aclPtr );
1506 		if( isIncomplete )
1507 			{
1508 			/* Normally we don't call the post-dispatch handler on error,
1509 			   however if it's a destroy message then we have to call it
1510 			   in order to handle any additional cleanup operations since
1511 			   the object is about to be destroyed, so if the destroy
1512 			   message to the object returned an incomplete error a we
1513 			   override any post-dispatch status with the original error
1514 			   status */
1515 			status = CRYPT_ERROR_INCOMPLETE;
1516 			}
1517 		}
1518 	return( status );
1519 	}
1520 
1521 /* Send a message to an object */
1522 
1523 RETVAL \
1524 PARAMCHECK_MESSAGE( MESSAGE_DESTROY, PARAM_NULL, PARAM_IS( 0 ) ) \
1525 PARAMCHECK_MESSAGE( MESSAGE_INCREFCOUNT, PARAM_NULL, PARAM_IS( 0 ) ) \
1526 PARAMCHECK_MESSAGE( MESSAGE_DECREFCOUNT, PARAM_NULL, PARAM_IS( 0 ) ) \
PARAMCHECK_MESSAGE(MESSAGE_GETDEPENDENT,OUT,IN_ENUM (OBJECT_TYPE))1527 PARAMCHECK_MESSAGE( MESSAGE_GETDEPENDENT, OUT, IN_ENUM( OBJECT_TYPE ) ) \
1528 PARAMCHECK_MESSAGE( MESSAGE_SETDEPENDENT, IN, IN ) \
1529 PARAMCHECK_MESSAGE( MESSAGE_CLONE, PARAM_NULL, IN_HANDLE ) \
1530 PARAMCHECK_MESSAGE( MESSAGE_GETATTRIBUTE, OUT, IN_ATTRIBUTE ) \
1531 PARAMCHECK_MESSAGE( MESSAGE_GETATTRIBUTE_S, INOUT, IN_ATTRIBUTE ) \
1532 PARAMCHECK_MESSAGE( MESSAGE_SETATTRIBUTE, IN, IN_ATTRIBUTE ) \
1533 PARAMCHECK_MESSAGE( MESSAGE_SETATTRIBUTE_S, IN, IN_ATTRIBUTE ) \
1534 PARAMCHECK_MESSAGE( MESSAGE_DELETEATTRIBUTE, PARAM_NULL, IN_ATTRIBUTE ) \
1535 PARAMCHECK_MESSAGE( MESSAGE_COMPARE, IN, IN_ENUM( MESSAGE_COMPARE ) ) \
1536 PARAMCHECK_MESSAGE( MESSAGE_CHECK, PARAM_NULL, IN_ENUM( MESSAGE_CHECK ) ) \
1537 PARAMCHECK_MESSAGE( MESSAGE_SELFTEST, PARAM_NULL, PARAM_IS( 0 ) ) \
1538 PARAMCHECK_MESSAGE( MESSAGE_CHANGENOTIFY, PARAM_NULL, PARAM_IS( 0 ) ) \
1539 PARAMCHECK_MESSAGE( MESSAGE_CTX_ENCRYPT, INOUT, IN_LENGTH ) \
1540 PARAMCHECK_MESSAGE( MESSAGE_CTX_DECRYPT, INOUT, IN_LENGTH ) \
1541 PARAMCHECK_MESSAGE( MESSAGE_CTX_SIGN, IN, IN_LENGTH ) \
1542 PARAMCHECK_MESSAGE( MESSAGE_CTX_SIGCHECK, IN, IN_LENGTH ) \
1543 PARAMCHECK_MESSAGE( MESSAGE_CTX_HASH, IN, IN_LENGTH_Z ) \
1544 PARAMCHECK_MESSAGE( MESSAGE_CTX_GENKEY, PARAM_NULL, PARAM_IS( 0 ) ) \
1545 PARAMCHECK_MESSAGE( MESSAGE_CTX_GENIV, PARAM_NULL, PARAM_IS( 0 ) ) \
1546 PARAMCHECK_MESSAGE( MESSAGE_CRT_SIGN, PARAM_NULL, IN_HANDLE ) \
1547 PARAMCHECK_MESSAGE( MESSAGE_CRT_SIGCHECK, PARAM_NULL, IN_HANDLE_OPT ) \
1548 PARAMCHECK_MESSAGE( MESSAGE_CRT_EXPORT, INOUT, IN_ENUM( CRYPT_CERTFORMAT ) ) \
1549 PARAMCHECK_MESSAGE( MESSAGE_DEV_QUERYCAPABILITY, OUT, IN_ALGO ) \
1550 PARAMCHECK_MESSAGE( MESSAGE_DEV_EXPORT, INOUT, IN_ENUM( MECHANISM ) ) \
1551 PARAMCHECK_MESSAGE( MESSAGE_DEV_IMPORT, INOUT, IN_ENUM( MECHANISM ) ) \
1552 PARAMCHECK_MESSAGE( MESSAGE_DEV_SIGN, INOUT, IN_ENUM( MECHANISM ) ) \
1553 PARAMCHECK_MESSAGE( MESSAGE_DEV_SIGCHECK, INOUT, IN_ENUM( MECHANISM ) ) \
1554 PARAMCHECK_MESSAGE( MESSAGE_DEV_DERIVE, INOUT, IN_ENUM( MECHANISM ) ) \
1555 PARAMCHECK_MESSAGE( MESSAGE_DEV_KDF, INOUT, IN_ENUM( MECHANISM ) ) \
1556 PARAMCHECK_MESSAGE( MESSAGE_DEV_CREATEOBJECT, INOUT, IN_ENUM( OBJECT_TYPE ) ) \
1557 PARAMCHECK_MESSAGE( MESSAGE_DEV_CREATEOBJECT_INDIRECT, INOUT, IN_ENUM( OBJECT_TYPE ) ) \
1558 PARAMCHECK_MESSAGE( MESSAGE_ENV_PUSHDATA, INOUT, PARAM_IS( 0 ) ) \
1559 PARAMCHECK_MESSAGE( MESSAGE_ENV_POPDATA, INOUT, PARAM_IS( 0 ) ) \
1560 PARAMCHECK_MESSAGE( MESSAGE_KEY_GETKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \
1561 PARAMCHECK_MESSAGE( MESSAGE_KEY_SETKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \
1562 PARAMCHECK_MESSAGE( MESSAGE_KEY_DELETEKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \
1563 PARAMCHECK_MESSAGE( MESSAGE_KEY_GETFIRSTCERT, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \
1564 PARAMCHECK_MESSAGE( MESSAGE_KEY_GETNEXTCERT, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \
1565 PARAMCHECK_MESSAGE( MESSAGE_KEY_CERTMGMT, INOUT, IN_ENUM( CRYPT_CERTACTION ) ) \
1566 PARAMCHECK_MESSAGE( MESSAGE_USER_USERMGMT, INOUT, IN_ENUM( MESSAGE_USERMGMT ) ) \
1567 PARAMCHECK_MESSAGE( MESSAGE_USER_TRUSTMGMT, IN, IN_ENUM( MESSAGE_TRUSTMGMT ) ) \
1568 					/* Actually INOUT for MESSAGE_TRUSTMGMT_GETISSUER, but too \
1569 					   complex to annotate */ \
1570 int krnlSendMessage( IN_HANDLE const int objectHandle,
1571 					 IN_MESSAGE const MESSAGE_TYPE message,
1572 					 void *messageDataPtr, const int messageValue )
1573 	{
1574 	const ATTRIBUTE_ACL *attributeACL = NULL;
1575 	const MESSAGE_HANDLING_INFO *handlingInfoPtr;
1576 	OBJECT_INFO *objectTable, *objectInfoPtr;
1577 	MESSAGE_QUEUE_DATA enqueuedMessageData;
1578 	const BOOLEAN isInternalMessage = isInternalMessage( message ) ? \
1579 									  TRUE : FALSE;
1580 	const void *aclPtr = NULL;
1581 	MESSAGE_TYPE localMessage = message & MESSAGE_MASK;
1582 	int localObjectHandle = objectHandle, iterationCount;
1583 	int status = CRYPT_OK;
1584 
1585 	assert( isWritePtr( krnlData, sizeof( KERNEL_DATA ) ) );
1586 
1587 	/* Preconditions.  For external messages we don't provide any assertions
1588 	   at this point since they're coming straight from the user and could
1589 	   contain any values, and for internal messages we only trap on
1590 	   programming errors (thus for example isValidHandle() vs.
1591 	   isValidObject(), since this would trap if a message is sent to a
1592 	   destroyed object) */
1593 	REQUIRES( isValidMessage( localMessage ) );
1594 	REQUIRES( !isInternalMessage || isValidHandle( objectHandle ) );
1595 
1596 	/* Get the information that we need to handle this message */
1597 	handlingInfoPtr = &messageHandlingInfo[ localMessage ];
1598 
1599 	/* Inner preconditions now that we have the handling information: Message
1600 	   parameters must be within the allowed range */
1601 	REQUIRES( checkParams( handlingInfoPtr->paramCheck, messageDataPtr,
1602 						   messageValue ) );
1603 
1604 	/* If it's an object-manipulation message get the attribute's mandatory
1605 	   ACL; if it's an object-parameter message get the parameter's mandatory
1606 	   ACL.  Since these doesn't require access to any object information, we
1607 	   can do it before we lock the object table */
1608 	if( isAttributeMessage( localMessage ) )
1609 		{
1610 		attributeACL = findAttributeACL( messageValue, isInternalMessage );
1611 		if( attributeACL == NULL )
1612 			return( CRYPT_ARGERROR_VALUE );
1613 		aclPtr = attributeACL;
1614 
1615 		/* Because cryptlib can be called through a variety of different
1616 		   language bindings it's not guaranteed that the values of TRUE and
1617 		   FALSE (as supplied by the caller) will always be 1 and 0.  For
1618 		   example Visual Basic uses the value -1 for TRUE because of
1619 		   obscure backwards-compatibility and implementation issues with
1620 		   16-bit versions of VB.  In order to avoid complaints from various
1621 		   checks at lower levels of cryptlib, we replace any boolean values
1622 		   with a setting other than FALSE with the explicit boolean value
1623 		   TRUE.  This is a bit of an ugly kludge but it avoids having to
1624 		   special-case these values at all sorts of other locations in the
1625 		   code */
1626 		if( localMessage == MESSAGE_SETATTRIBUTE && \
1627 			attributeACL->valueType == ATTRIBUTE_VALUE_BOOLEAN )
1628 			{
1629 			REQUIRES( messageDataPtr != NULL );
1630 
1631 			if( *( ( BOOLEAN * ) messageDataPtr ) )
1632 				messageDataPtr = MESSAGE_VALUE_TRUE;
1633 			}
1634 		}
1635 	if( isParamMessage( localMessage ) )
1636 		{
1637 		aclPtr = findParamACL( localMessage );
1638 		ENSURES( aclPtr != NULL );
1639 		}
1640 
1641 	/* Inner precondition: If it's an attribute-manipulation message, we have
1642 	   a valid ACL for the attribute present */
1643 	REQUIRES( !isAttributeMessage( localMessage ) || attributeACL != NULL );
1644 
1645 	/* If we're in the middle of a shutdown, don't allow any further
1646 	   messages except ones related to object destruction (the status read
1647 	   is needed for objects capable of performing async ops, since the
1648 	   shutdown code needs to determine whether they're currently busy).
1649 	   The check outside the object-table lock is done in order to have any
1650 	   remaining active objects exit quickly without tying up the object
1651 	   table, since we don't want them to block the shutdown.  In addition
1652 	   if the thread is a leftover/long-running thread that's still active
1653 	   after the shutdown has occurred, we can't access the object table
1654 	   lock since it'll have been deleted */
1655 	if( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES && \
1656 		!( localMessage == MESSAGE_DESTROY || \
1657 		   localMessage == MESSAGE_DECREFCOUNT || \
1658 		   ( localMessage == MESSAGE_GETATTRIBUTE && \
1659 			 messageValue == CRYPT_IATTRIBUTE_STATUS ) ) )
1660 		{
1661 		/* Exit without even trying to acquire the object table lock */
1662 		return( CRYPT_ERROR_PERMISSION );
1663 		}
1664 
1665 	/* Lock the object table to ensure that other threads don't try to
1666 	   access it */
1667 	MUTEX_LOCK( objectTable );
1668 	objectTable = krnlData->objectTable;
1669 
1670 	/* The first line of defence: Make sure that the message is being sent
1671 	   to a valid object and that the object is externally visible and
1672 	   accessible to the caller if required by the message.  The checks
1673 	   performed are:
1674 
1675 		if( handle does not correspond to an object )
1676 			error;
1677 		if( message is external )
1678 			{
1679 			if( object is internal )
1680 				error;
1681 			if( object isn't owned by calling thread )
1682 				error;
1683 			}
1684 
1685 	   This is equivalent to the shorter form fullObjectCheck() that used
1686 	   elsewhere.  The error condition reported in all of these cases is
1687 	   that the object handle isn't valid */
1688 	if( !isValidObject( objectHandle ) )
1689 		status = CRYPT_ARGERROR_OBJECT;
1690 	else
1691 		{
1692 		if( !isInternalMessage && \
1693 			( isInternalObject( objectHandle ) || \
1694 			  !checkObjectOwnership( objectTable[ objectHandle ] ) ) )
1695 			status = CRYPT_ARGERROR_OBJECT;
1696 		}
1697 	if( cryptStatusError( status ) )
1698 		{
1699 		MUTEX_UNLOCK( objectTable );
1700 		return( status );
1701 		}
1702 
1703 	/* Inner precondition now that the outer check has been passed: It's a
1704 	   valid, accessible object and not a system object that can never be
1705 	   explicitly destroyed or have its refCount altered */
1706 	REQUIRES_MUTEX( isValidObject( objectHandle ), objectTable );
1707 	REQUIRES_MUTEX( isInternalMessage || ( !isInternalObject( objectHandle ) && \
1708 					checkObjectOwnership( objectTable[ objectHandle ] ) ), \
1709 					objectTable );
1710 	REQUIRES_MUTEX( fullObjectCheck( objectHandle, message ), objectTable );
1711 	REQUIRES_MUTEX( objectHandle >= NO_SYSTEM_OBJECTS || \
1712 					( localMessage != MESSAGE_DESTROY && \
1713 					  localMessage != MESSAGE_DECREFCOUNT && \
1714 					  localMessage != MESSAGE_INCREFCOUNT ), objectTable );
1715 
1716 	/* If this message is routable, find its target object */
1717 	if( handlingInfoPtr->routingFunction != NULL )
1718 		{
1719 		/* If it's implicitly routed, route it based on the attribute type */
1720 		if( isImplicitRouting( handlingInfoPtr->routingTarget ) )
1721 			{
1722 			REQUIRES_MUTEX( attributeACL != NULL, objectTable );
1723 
1724 			if( attributeACL->routingFunction != NULL )
1725 				{
1726 				status = attributeACL->routingFunction( objectHandle,
1727 											&localObjectHandle,
1728 											attributeACL->routingTarget );
1729 				}
1730 			}
1731 		else
1732 			{
1733 			/* It's explicitly or directly routed, route it based on the
1734 			   message type or fixed-target type */
1735 			status = handlingInfoPtr->routingFunction( objectHandle,
1736 											&localObjectHandle,
1737 						isExplicitRouting( handlingInfoPtr->routingTarget ) ? \
1738 						messageValue : handlingInfoPtr->routingTarget );
1739 			}
1740 		if( cryptStatusError( status ) )
1741 			{
1742 			MUTEX_UNLOCK( objectTable );
1743 			return( CRYPT_ARGERROR_OBJECT );
1744 			}
1745 		}
1746 
1747 	/* Inner precodition: It's a valid destination object */
1748 	REQUIRES_MUTEX( isValidObject( localObjectHandle ), objectTable );
1749 
1750 	/* Sanity-check the message routing */
1751 	if( !isValidObject( localObjectHandle ) )
1752 		{
1753 		MUTEX_UNLOCK( objectTable );
1754 		retIntError();
1755 		}
1756 
1757 	/* It's a valid object, get its info */
1758 	objectInfoPtr = &objectTable[ localObjectHandle ];
1759 
1760 	/* Now that the message has been routed to its intended target, make sure
1761 	   that it's valid for the target object subtype */
1762 	if( !isValidSubtype( handlingInfoPtr->subTypeA, objectInfoPtr->subType ) && \
1763 		!isValidSubtype( handlingInfoPtr->subTypeB, objectInfoPtr->subType ) && \
1764 		!isValidSubtype( handlingInfoPtr->subTypeC, objectInfoPtr->subType ) )
1765 		{
1766 		MUTEX_UNLOCK( objectTable );
1767 		return( CRYPT_ARGERROR_OBJECT );
1768 		}
1769 
1770 	/* Inner precondition: The message is valid for this object subtype */
1771 	REQUIRES_MUTEX( isValidSubtype( handlingInfoPtr->subTypeA, \
1772 									objectInfoPtr->subType ) || \
1773 					isValidSubtype( handlingInfoPtr->subTypeB, \
1774 									objectInfoPtr->subType ) || \
1775 					isValidSubtype( handlingInfoPtr->subTypeC, \
1776 									objectInfoPtr->subType ), \
1777 					objectTable );
1778 
1779 	/* If this message is processed internally, handle it now.  These
1780 	   messages aren't affected by the object's state so they're always
1781 	   processed */
1782 	if( handlingInfoPtr->internalHandlerFunction != NULL || \
1783 		( attributeACL != NULL && \
1784 		  attributeACL->flags & ATTRIBUTE_FLAG_PROPERTY ) )
1785 		{
1786 		status = processInternalMessage( localObjectHandle, handlingInfoPtr,
1787 										 message, messageDataPtr,
1788 										 messageValue, aclPtr );
1789 		if( status != OK_SPECIAL )
1790 			{
1791 			/* The message was processed normally, exit */
1792 			MUTEX_UNLOCK( objectTable );
1793 			return( status );
1794 			}
1795 
1796 		/* The object has entered an invalid state (for example it was
1797 		   signalled while it was being initialised) and can't be used any
1798 		   more, destroy it, convert the (local copy of the) message into a
1799 		   destroy object message */
1800 		localMessage = MESSAGE_DESTROY;
1801 		status = CRYPT_OK;
1802 		}
1803 
1804 	/* If the object isn't already processing a message and the message isn't
1805 	   a special type such as MESSAGE_DESTROY, dispatch it immediately rather
1806 	   than enqueueing it for later dispatch.  This scoreboard mechanism
1807 	   greatly reduces the load on the queue */
1808 	if( !isInUse( localObjectHandle ) && localMessage != MESSAGE_DESTROY )
1809 		{
1810 		CONST_INIT_STRUCT_5( MESSAGE_QUEUE_DATA messageQueueData, \
1811 							 localObjectHandle, handlingInfoPtr, message, \
1812 							 messageDataPtr, messageValue );
1813 
1814 		CONST_SET_STRUCT( messageQueueData.objectHandle = localObjectHandle; \
1815 						  messageQueueData.handlingInfoPtr = handlingInfoPtr; \
1816 						  messageQueueData.message = message; \
1817 						  messageQueueData.messageDataPtr = messageDataPtr; \
1818 						  messageQueueData.messageValue = messageValue );
1819 
1820 		/* If the object isn't in a valid state, we can't do anything with it.
1821 		   There are no messages that can be sent to it at this point, get/
1822 		   set property messages have already been handled earlier and the
1823 		   destroy message isn't handled here */
1824 		if( isInvalidObjectState( localObjectHandle ) )
1825 			{
1826 			status = getObjectStatusValue( objectInfoPtr->flags );
1827 			MUTEX_UNLOCK( objectTable );
1828 			return( status );
1829 			}
1830 
1831 		/* In case a shutdown was signalled while we were performing other
1832 		   processing, exit now before we try and do anything with the
1833 		   object.  It's safe to perform the check at this point since no
1834 		   message sent during shutdown will get here */
1835 		if( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES )
1836 			{
1837 			MUTEX_UNLOCK( objectTable );
1838 			return( CRYPT_ERROR_PERMISSION );
1839 			}
1840 
1841 		/* Inner precondition: The object is in a valid state */
1842 		REQUIRES_MUTEX( !isInvalidObjectState( localObjectHandle ), \
1843 						objectTable );
1844 
1845 		/* Dispatch the message to the object */
1846 		status = dispatchMessage( localObjectHandle, &messageQueueData,
1847 								  objectInfoPtr, aclPtr );
1848 		MUTEX_UNLOCK( objectTable );
1849 
1850 		/* If it's a zeroise, perform a kernel shutdown.  In theory we could
1851 		   do this from the post-dispatch handler, but we need to make sure
1852 		   that there are no further kernel actions to be taken before we
1853 		   perform the shutdown, so we do it at this level instead */
1854 		if( cryptStatusOK( status ) && \
1855 			( messageQueueData.message & MESSAGE_MASK ) == MESSAGE_USER_USERMGMT && \
1856 			messageQueueData.messageValue == MESSAGE_USERMGMT_ZEROISE )
1857 			{
1858 			/* Since it's a zeroise we return the status of the overall
1859 			   zeroise operation rather than any possible non-OK status from
1860 			   shutting down the kernel at the end of the zeroise */
1861 			( void ) endCryptlib();
1862 			}
1863 
1864 		/* Postcondition: The return status is valid */
1865 		ENSURES( cryptStandardError( status ) || \
1866 				 cryptArgError( status ) || status == OK_SPECIAL );
1867 
1868 		return( status );
1869 		}
1870 
1871 	/* Inner precondition: The object is in use or it's a destroy object
1872 	   message, we have to enqueue it */
1873 	REQUIRES_MUTEX( isInUse( localObjectHandle ) || \
1874 					localMessage == MESSAGE_DESTROY, \
1875 					objectTable );
1876 
1877 	/* If we're stuck in a loop processing recursive messages, bail out.
1878 	   This would happen automatically anyway once we fill the message queue,
1879 	   but this early-out mechanism prevents a single object from filling the
1880 	   queue to the detriment of other objects */
1881 	if( objectInfoPtr->lockCount > MESSAGE_QUEUE_SIZE / 2 )
1882 		{
1883 		MUTEX_UNLOCK( objectTable );
1884 		DEBUG_DIAG(( "Invalid kernel message queue state" ));
1885 		assert( DEBUG_WARN );
1886 		return( CRYPT_ERROR_TIMEOUT );
1887 		}
1888 
1889 	/* If the object is in use by another thread, wait for it to become
1890 	   available */
1891 	if( isInUse( localObjectHandle ) && !isObjectOwner( localObjectHandle ) )
1892 		{
1893 		status = waitForObject( localObjectHandle, &objectInfoPtr );
1894 #if !defined( NDEBUG ) && defined( USE_THREADS )
1895 		if( cryptStatusOK( status ) && isInUse( localObjectHandle ) )
1896 			{
1897 			/* dispatchMessage() expects us to be the lock owner if the
1898 			   object is in use, however if the object has been */
1899 			objectInfoPtr->lockOwner = THREAD_SELF();
1900 			}
1901 #endif /* !NDEBUG && USE_THREADS */
1902 		}
1903 	if( cryptStatusError( status ) )
1904 		{
1905 		MUTEX_UNLOCK( objectTable );
1906 		return( status );
1907 		}
1908 	assert( !isInUse( localObjectHandle ) || \
1909 			isObjectOwner( localObjectHandle ) );
1910 
1911 	/* Enqueue the message */
1912 	if( ( message & MESSAGE_MASK ) != localMessage )
1913 		{
1914 		/* The message was converted during processing, this can only happen
1915 		   when a message sent to an invalid-state object is converted into
1916 		   a destroy-object message.  What we therefore enqueue is a
1917 		   destroy-object message, but with the messageValue parameter set
1918 		   to TRUE to indicate that it's a converted destroy message */
1919 		REQUIRES_MUTEX( localMessage == MESSAGE_DESTROY, objectTable );
1920 
1921 		status = enqueueMessage( localObjectHandle,
1922 								 &messageHandlingInfo[ MESSAGE_DESTROY ],
1923 								 MESSAGE_DESTROY, messageDataPtr, TRUE );
1924 		}
1925 	else
1926 		{
1927 		status = enqueueMessage( localObjectHandle, handlingInfoPtr, message,
1928 								 messageDataPtr, messageValue );
1929 		}
1930 	if( cryptStatusError( status ) )
1931 		{
1932 		/* A message for this object is already present in the queue, defer
1933 		   processing until later */
1934 		MUTEX_UNLOCK( objectTable );
1935 		return( ( status == OK_SPECIAL ) ? CRYPT_OK : status );
1936 		}
1937 	assert( !isInUse( localObjectHandle ) || \
1938 			isObjectOwner( localObjectHandle ) );
1939 
1940 	/* While there are more messages for this object present, dequeue them
1941 	   and dispatch them.  Since messages will only be enqueued if
1942 	   krnlSendMessage() is called recursively, we only dequeue messages for
1943 	   the current object in this loop.  Queued messages for other objects
1944 	   will be handled at a different level of recursion.
1945 
1946 	   Bounding this loop is a bit tricky because new messages can arrive as
1947 	   the existing ones are dequeued, so that in theory the arrival rate
1948 	   could match the dispatch rate.  However in practice a situation like
1949 	   this would be extremely unusual, so we bound the loop at
1950 	   FAILSAFE_ITERATIONS_LARGE */
1951 	for( iterationCount = 0;
1952 		 getNextMessage( localObjectHandle, &enqueuedMessageData ) && \
1953 			iterationCount < FAILSAFE_ITERATIONS_LARGE;
1954 		 iterationCount++ )
1955 		{
1956 		const BOOLEAN isDestroy = \
1957 			( enqueuedMessageData.message & MESSAGE_MASK ) == MESSAGE_DESTROY;
1958 		const BOOLEAN isZeroise = \
1959 			( enqueuedMessageData.message & MESSAGE_MASK ) == MESSAGE_USER_USERMGMT && \
1960 			enqueuedMessageData.messageValue == MESSAGE_USERMGMT_ZEROISE;
1961 
1962 		/* If there's a problem with the object, initiate special processing.
1963 		   The exception to this is a destroy message that started out as a
1964 		   different type of message (that is, it was converted into a
1965 		   destroy object message due to the object being in an invalid
1966 		   state, indicated by the messageValue parameter being set to TRUE
1967 		   when it's normally zero for a destroy message), which is let
1968 		   through */
1969 		if( isInvalidObjectState( localObjectHandle ) && \
1970 			!( isDestroy && ( enqueuedMessageData.messageValue == TRUE ) ) )
1971 			{
1972 			/* If it's a destroy object message being sent to an object in
1973 			   the process of being created, set the state to signalled and
1974 			   continue.  The object will be destroyed when the caller
1975 			   notifies the kernel that the init is complete */
1976 			if( isDestroy && ( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED ) )
1977 				{
1978 				objectInfoPtr->flags |= OBJECT_FLAG_SIGNALLED;
1979 				status = CRYPT_OK;
1980 				}
1981 			else
1982 				{
1983 				/* Remove all further messages for this object and return
1984 				   to the caller */
1985 				dequeueAllMessages( localObjectHandle );
1986 				status = getObjectStatusValue( objectInfoPtr->flags );
1987 				}
1988 			continue;
1989 			}
1990 		assert( !isInUse( localObjectHandle ) || \
1991 				isObjectOwner( localObjectHandle ) );
1992 
1993 		/* Inner precondition: The object is in a valid state or it's a
1994 		   destroy message that was converted from a different message
1995 		   type */
1996 		REQUIRES_MUTEX( !isInvalidObjectState( localObjectHandle ) || \
1997 						( isDestroy && ( enqueuedMessageData.messageValue == TRUE ) ), \
1998 						objectTable );
1999 
2000 		/* Dispatch the message to the object */
2001 		status = dispatchMessage( localObjectHandle, &enqueuedMessageData,
2002 								  objectInfoPtr, aclPtr );
2003 
2004 		/* If the message is a destroy object message, we have to explicitly
2005 		   remove it from the object table and dequeue all further messages
2006 		   for it since the object's message handler can't do this itself.
2007 		   Since a destroy object message always succeeds but can return an
2008 		   error code (typically CRYPT_ERROR_INCOMPLETE), we don't treat an
2009 		   error return as a real error status for the purposes of further
2010 		   processing */
2011 		if( isDestroy )
2012 			{
2013 			int destroyStatus;	/* Preserve original status value */
2014 
2015 			destroyStatus = destroyObjectData( localObjectHandle );
2016 			ENSURES_MUTEX( cryptStatusOK( destroyStatus ), objectTable );
2017 			dequeueAllMessages( localObjectHandle );
2018 			}
2019 		else
2020 			{
2021 			/* If we ran into a problem or this is a zeroise (i.e. a
2022 			   localised shutdown), dequeue all further messages for this
2023 			   object.  This causes getNextMessage() to fail and we drop out
2024 			   of the loop */
2025 			if( cryptStatusError( status ) || \
2026 				( cryptStatusOK( status ) && isZeroise ) )
2027 				{
2028 				dequeueAllMessages( localObjectHandle );
2029 				}
2030 			}
2031 		}
2032 	ENSURES_MUTEX( iterationCount < FAILSAFE_ITERATIONS_LARGE, \
2033 				   objectTable );
2034 
2035 	/* Unlock the object table to allow access by other threads */
2036 	MUTEX_UNLOCK( objectTable );
2037 
2038 	/* If it's a zeroise, perform a kernel shutdown.  In theory we could do
2039 	   this from the post-dispatch handler, but we need to make sure that
2040 	   there are no further kernel actions to be taken before we perform the
2041 	   shutdown, so we do it at this level instead */
2042 	if( cryptStatusOK( status ) && localMessage == MESSAGE_USER_USERMGMT && \
2043 		messageValue == MESSAGE_USERMGMT_ZEROISE )
2044 		{
2045 		/* Since it's a zeroise we return the status of the overall zeroise
2046 		   operation rather than any possible non-OK status from shutting
2047 		   down the kernel at the end of the zeroise */
2048 		( void ) endCryptlib();
2049 		}
2050 
2051 	/* Postcondition: The return status is valid */
2052 	ENSURES( cryptStandardError( status ) || cryptArgError( status ) || \
2053 			 status == OK_SPECIAL );
2054 
2055 	return( status );
2056 	}
2057