1 /****************************************************************************
2 *																			*
3 *							cryptlib Kernel Header File						*
4 *						Copyright Peter Gutmann 1992-2005					*
5 *																			*
6 ****************************************************************************/
7 
8 #ifndef _KERNEL_DEFINED
9 
10 #define _KERNEL_DEFINED
11 
12 #if defined( INC_ALL )
13   #include "thread.h"
14 #else
15   #include "kernel/thread.h"
16 #endif /* Compiler-specific includes */
17 
18 /* RAY and EGON look over code.
19 
20    EGON: The structure of this kernel is exactly like the kind of telemetry
21          tracker that NASA uses to secure dead pulsars in deep space.
22 
23    RAY: All message dispatch mechanisms and callback functions.
24 
25    PETER (to other jailbirds): Everyone getting this so far?  So what?  I
26          guess they just don't make them like they used to.
27 
28    RAY: No!  Nobody ever made them like this!  The architect was either a
29         certified genius or an authentic wacko! */
30 
31 /* "There is a fine line between genius and insanity.
32     I have erased this line" - Oscar Levant
33 	(or "Nullum magnum ingenium sine mixtura dementiae" if you want it in
34 	the usual style) */
35 
36 /****************************************************************************
37 *																			*
38 *							Parameter Checking Macros						*
39 *																			*
40 ****************************************************************************/
41 
42 /* Macros to perform validity checks on objects and handles.  These checks
43    are:
44 
45 	isValidHandle(): Whether a handle is a valid index into the object table.
46 	isValidObject(): Whether a handle refers to an object in the table.
47 	isFreeObject(): Whether a handle refers to an empty entry in the table.
48 	isInternalObject(): Whether an object is an internal object.
49 	isInvalidObjectState(): Whether an object is in an invalid (error) state.
50 	isInUse(): Whether an object is currently in use (processing a message).
51 	isObjectOwner(): If inUse == TRUE, whether this thread is the one using
52 					 the object.
53 	isInHighState(): Whether an object is in the 'high' security state.
54 	isSameOwningObject(): Whether two objects have the same owner.  We also
55 						  have to handle the situation where the first object
56 						  is a user object, in which case it has to be the
57 						  owner of the second object.
58 	isObjectAccessValid(): Internal/external object access check.
59 	isValidMessage(): Whether a message type is valid.
60 	isInternalMessage(): Whether a message is an internal message.
61 	isValidType(): Whether an object type is valid
62 	isValidSubtype(): Whether an object subtype is allowed based on access
63 					  bitflags */
64 
65 #define isValidHandle( handle ) \
66 		( ( handle ) >= 0 && ( handle ) < krnlData->objectTableSize )
67 #define isValidObject( handle ) \
68 		( isValidHandle( handle ) && \
69 		  krnlData->objectTable[ ( handle ) ].objectPtr != NULL )
70 #define isFreeObject( handle ) \
71 		( isValidHandle( handle ) && \
72 		  krnlData->objectTable[ ( handle ) ].objectPtr == NULL )
73 #define isInternalObject( handle ) \
74 		( krnlData->objectTable[ handle ].flags & OBJECT_FLAG_INTERNAL )
75 #define isObjectAccessValid( objectHandle, message ) \
76 		!( isInternalObject( objectHandle ) && \
77 		   !( message & MESSAGE_FLAG_INTERNAL ) )
78 #define isInvalidObjectState( handle ) \
79 		( krnlData->objectTable[ ( handle ) ].flags & OBJECT_FLAGMASK_STATUS )
80 #define isInUse( handle ) \
81 		( krnlData->objectTable[ ( handle ) ].lockCount > 0 )
82 #define isObjectOwner( handle ) \
83 		THREAD_SAME( krnlData->objectTable[ ( handle ) ].lockOwner, THREAD_SELF() )
84 #define isInHighState( handle ) \
85 		( krnlData->objectTable[ ( handle ) ].flags & OBJECT_FLAG_HIGH )
86 #define isSameOwningObject( handle1, handle2 ) \
87 		( krnlData->objectTable[ ( handle1 ) ].owner == CRYPT_UNUSED || \
88 		  krnlData->objectTable[ ( handle2 ) ].owner == CRYPT_UNUSED || \
89 		  ( krnlData->objectTable[ ( handle1 ) ].owner == \
90 							krnlData->objectTable[ ( handle2 ) ].owner ) || \
91 		  ( ( handle1 ) == krnlData->objectTable[ ( handle2 ) ].owner ) )
92 #define isValidMessage( message ) \
93 		( ( message ) > MESSAGE_NONE && ( message ) < MESSAGE_LAST )
94 #define isInternalMessage( message ) \
95 		( ( message ) & MESSAGE_FLAG_INTERNAL )
96 #define isValidType( type ) \
97 		( ( type ) > OBJECT_TYPE_NONE && ( type ) < OBJECT_TYPE_LAST )
98 #define isValidSubtype( subtypeMask, subtype ) \
99 		( ( ( subtypeMask ) & ( subtype ) ) == ( subtype ) )
100 
101 /* The set of object checks is used frequently enough that we combine them
102    into a composite check that performs all of the checks in one place */
103 
104 #define fullObjectCheck( objectHandle, message ) \
105 		( isValidObject( objectHandle ) && \
106 		  isObjectAccessValid( objectHandle, message ) && \
107 		  checkObjectOwnership( objectTable[ objectHandle ] ) )
108 
109 /* Macros to test whether a message falls into a certain class.  These tests
110    are:
111 
112 	isParamMessage(): Whether a message contains an object as a parameter */
113 
114 #define isParamMessage( message ) \
115 		( ( message ) == MESSAGE_CRT_SIGN || \
116 		  ( message ) == MESSAGE_CRT_SIGCHECK )
117 
118 /* Macros to manage object ownership, if the OS supports it */
119 
120 #define checkObjectOwnership( objectPtr ) \
121 		( !( ( objectPtr ).flags & OBJECT_FLAG_OWNED ) || \
122 		  THREAD_SAME( ( objectPtr ).objectOwner, THREAD_SELF() ) )
123 
124 /* A macro to turn an abnormal status indicated in an object's flags into a
125    status code.  The values are prioritised so that notinited > signalled >
126    busy */
127 
128 #define getObjectStatusValue( flags ) \
129 		( ( flags & OBJECT_FLAG_NOTINITED ) ? CRYPT_ERROR_NOTINITED : \
130 		  ( flags & OBJECT_FLAG_SIGNALLED ) ? CRYPT_ERROR_SIGNALLED : CRYPT_OK )
131 
132 /****************************************************************************
133 *																			*
134 *						Object Definitions and Information					*
135 *																			*
136 ****************************************************************************/
137 
138 /* The information maintained by the kernel for each object */
139 
140 typedef struct {
141 	/* Object type and value */
142 	OBJECT_TYPE type;			/* Object type */
143 	OBJECT_SUBTYPE subType;		/* Object subtype */
144 	void *objectPtr;			/* Object data */
145 	int objectSize;				/* Object data size */
146 
147 	/* Object properties */
148 	int flags;					/* Internal-only, locked, etc */
149 	int actionFlags;			/* Permitted actions */
150 	int intRefCount, extRefCount;/* Number of int/ext refs.to this object */
151 	int lockCount;				/* Message-processing lock recursion count */
152 #ifdef USE_THREADS
153 	THREAD_HANDLE lockOwner;	/* Lock owner if lockCount > 0 */
154 #endif /* USE_THREADS */
155 	int uniqueID;				/* Unique ID for this object */
156 /*	time_t lastAccess;			// Last access time */
157 
158 	/* Object security properties */
159 	int forwardCount;			/* Number of times ownership can be transferred */
160 	int usageCount;				/* Number of times obj.can be used */
161 #ifdef USE_THREADS
162 	THREAD_HANDLE objectOwner;	/* The object's owner */
163 #endif /* USE_THREADS */
164 
165 	/* Object methods */
166 	FNPTR_DECLARE( MESSAGE_FUNCTION, messageFunction );
167 								/* The object's message handler */
168 
169 	/* Owning and dependent objects */
170 	CRYPT_USER owner;			/* Owner object handle */
171 	CRYPT_HANDLE dependentObject;	/* Dependent object (context or cert) */
172 	CRYPT_HANDLE dependentDevice;	/* Dependent crypto device */
173 	} OBJECT_INFO;
174 
175 /* The flags that apply to each object in the table */
176 
177 #define OBJECT_FLAG_NONE		0x0000	/* Non-flag */
178 #define OBJECT_FLAG_INTERNAL	0x0001	/* Internal-use only */
179 #define OBJECT_FLAG_NOTINITED	0x0002	/* Still being initialised */
180 #define OBJECT_FLAG_HIGH		0x0004	/* In 'high' security state */
181 #define OBJECT_FLAG_SIGNALLED	0x0008	/* In signalled state */
182 #define OBJECT_FLAG_SECUREMALLOC 0x0010	/* Uses secure memory */
183 #define OBJECT_FLAG_OWNED		0x0020	/* Object is bound to a thread */
184 #define OBJECT_FLAG_ATTRLOCKED	0x0040	/* Security properties can't be modified */
185 
186 /* The flags that convey information about an object's status */
187 
188 #define OBJECT_FLAGMASK_STATUS \
189 		( OBJECT_FLAG_NOTINITED | OBJECT_FLAG_SIGNALLED )
190 
191 /****************************************************************************
192 *																			*
193 *							Kernel Data Structures							*
194 *																			*
195 ****************************************************************************/
196 
197 /* The object allocation state data.  This controls the allocation of
198    handles to newly-created objects.  The first NO_SYSTEM_OBJECTS handles
199    are system objects that exist with fixed handles, the remainder are
200    allocated pseudorandomly under the control of an LFSR */
201 
202 typedef struct {
203 	long lfsrMask, lfsrPoly;	/* LFSR state values */
204 	int objectHandle;			/* Current object handle */
205 	} OBJECT_STATE_INFO;
206 
207 /* A structure to store the details of a message sent to an object, and the
208    size of the message queue.  This defines the maximum nesting depth of
209    messages sent by an object.  Because of the way krnlSendMessage() handles
210    message processing, it's extremely difficult to ever have more than two
211    or three messages in the queue unless an object starts recursively
212    sending itself messages */
213 
214 typedef struct {
215 	int objectHandle;			/* Handle to send message to */
216 	const void *handlingInfoPtr;/* Message handling info */
217 	MESSAGE_TYPE message;
218 	const void *messageDataPtr;
219 	int messageValue;			/* Message parameters */
220 	} MESSAGE_QUEUE_DATA;
221 
222 #define MESSAGE_QUEUE_SIZE	16
223 
224 /* Semaphores are one-shots, so that once set and cleared they can't be
225    reset.  This is handled by enforcing the following state transitions:
226 
227 	Uninited -> Set | Clear
228 	Set -> Set | Clear
229 	Clear -> Clear
230 
231    The handling is complicated somewhat by the fact that on some systems the
232    semaphore has to be explicitly deleted, but only the last thread to use
233    it can safely delete it.  In order to handle this, we reference-count the
234    semaphore and let the last thread out delete it.  In order to do this we
235    introduce an additional state, preClear, which indicates that while the
236    semaphore object is still present, the last thread out should delete it,
237    bringing it to the true clear state */
238 
239 typedef enum {
240 	SEMAPHORE_STATE_UNINITED,
241 	SEMAPHORE_STATE_CLEAR,
242 	SEMAPHORE_STATE_PRECLEAR,
243 	SEMAPHORE_STATE_SET,
244 	SEMAPHORE_STATE_LAST
245 	} SEMAPHORE_STATE;
246 
247 typedef struct {
248 	SEMAPHORE_STATE state;		/* Semaphore state */
249 	MUTEX_HANDLE object;		/* Handle to system synchronisation object */
250 	int refCount;				/* Reference count for handle */
251 	} SEMAPHORE_INFO;
252 
253 /* A structure to store the details of a thread */
254 
255 typedef struct {
256 	FNPTR_DECLARE( THREAD_FUNCTION, threadFunction );
257 									/* Function to call from thread */
258 	THREAD_PARAMS threadParams;		/* Thread function parameters */
259 	SEMAPHORE_TYPE semaphore;		/* Optional semaphore to set */
260 	MUTEX_HANDLE syncHandle;		/* Handle to use for thread sync */
261 	} THREAD_INFO;
262 
263 /* When the kernel starts up and closes down it does so in a multi-stage
264    process that's equivalent to Unix runlevels.  For the startup at the
265    first level the kernel data block and all kernel-level primitive
266    objects like mutexes have been initialised.
267 
268    For the shutdown, at the first level all internal worker threads/tasks
269    must exist.  At the next level all messages to objects except destroy
270    messages fail.  At the final level all kernel-managed primitives such as
271    mutexes and semaphores are no longer available */
272 
273 typedef enum {
274 	INIT_LEVEL_NONE,			/* Uninitialised */
275 	INIT_LEVEL_KRNLDATA,		/* Kernel data block initialised */
276 	INIT_LEVEL_FULL,			/* Full initialisation */
277 	INIT_LEVEL_LAST				/* Last possible init level */
278 	} INIT_LEVEL;
279 
280 typedef enum {
281 	SHUTDOWN_LEVEL_NONE,		/* Normal operation */
282 	SHUTDOWN_LEVEL_THREADS,		/* Internal threads must exit */
283 	SHUTDOWN_LEVEL_MESSAGES,	/* Only destroy messages are valid */
284 	SHUTDOWN_LEVEL_MUTEXES,		/* Kernel objects become invalid */
285 	SHUTDOWN_LEVEL_ALL,			/* Complete shutdown */
286 	SHUTDOWN_LEVEL_LAST			/* Last possible shutdown level */
287 	} SHUTDOWN_LEVEL;
288 
289 /* The kernel data block, containing all variables used by the kernel.  With
290    the exception of the special-case values at the start, all values in this
291    block should be set to use zero/NULL as their ground state (for example a
292    boolean variable should have a ground state of FALSE (zero) rather than
293    TRUE (nonzero)).
294 
295    If the objectTable giant lock (or more strictly speaking monolithic lock,
296    since the kernel's message-handling is designed to be straight-line code
297    and so never blocks for any amount of time like the Linux giant lock can)
298    ever proves to be a problem then the solution would be to use lock
299    striping, dividing the load of the object table across NO_TABLE_LOCKS
300    locks.  This gets a bit tricky because the object table is dynamically
301    resizeable, a basic mod_NO_TABLE_LOCKS strategy where every n-th entry
302    uses the same lock works but then we'd still need a giant lock to check
303    whether the table is being resized.  To avoid this we can use a lock-free
304    implementation that operates by acquiring each lock (to make sure we have
305    complete control of the table), checking whether another thread beat us to
306    it, and if not resizing the table.  The pseudocode for this is as
307    follows:
308 
309 	// Remember the original table size
310 	const int oldSize = krnlData->objectTableSize;
311 
312 	// Acquire each lock
313 	for( i = 0; i < NO_LOCKS; i++ )
314 		THREAD_LOCK( krnlData->locks[ i ] );
315 
316 	// Check whether another thread beat us to the resize while we were
317 	// acquiring locks
318 	if( krnlData->objectTableSize != oldSize )
319 		{
320 		// Unlock all the locks
321 		// ... //
322 		return;
323 		}
324 
325 	// We hold all the locks and therefore have exclusive control of the
326 	// table, resize it
327 	// ... //
328 
329 	// Release each lock again //
330 	for( i = 0; i < NO_LOCKS; i++ )
331 		THREAD_UNLOCK( krnlData->locks[ i ] );
332 
333    This is a conventional lock-free implementation of such an algorithm but
334    is conceptually ugly in that it accesses protected data outside the lock,
335    which will cause concurrency-checking tools to complain.  Until the fast-
336    path through the kernel actually becomes a real bottleneck it's probably
337    best to leave well enough alone */
338 
339 typedef struct {
340 	/* The kernel initialisation state and a lock to protect it.  The
341 	   lock and shutdown level value are handled externally and aren't
342 	   cleared when the kernel data block as a whole is cleared.  Note
343 	   that the shutdown level has to be before the lock so that we can
344 	   statically initialise the data with '{ 0 }', which won't work if
345 	   the lock data is non-scalar */
346 	SHUTDOWN_LEVEL shutdownLevel;		/* Kernel shutdown level */
347 #ifdef USE_THREADS
348 	MUTEX_DECLARE_STORAGE( initialisation );
349 #endif /* USE_THREADS */
350 	/* Everything from this point on is cleared at init and shutdown */
351 	int initLevel;						/* Kernel initialisation level */
352 
353 	/* The kernel object table and object table management info */
354 	OBJECT_INFO *objectTable;			/* Pointer to object table */
355 	int objectTableSize;				/* Current table size */
356 	int objectUniqueID;					/* Unique ID for next object */
357 	OBJECT_STATE_INFO objectStateInfo;	/* Object allocation state */
358 #ifdef USE_THREADS
359 	MUTEX_DECLARE_STORAGE( objectTable );
360 #endif /* USE_THREADS */
361 
362 	/* The kernel message dispatcher queue */
363 	BUFFER( MESSAGE_QUEUE_SIZE, queueEnd ) \
364 	MESSAGE_QUEUE_DATA messageQueue[ MESSAGE_QUEUE_SIZE + 8 ];
365 	int queueEnd;						/* Points past last queue element */
366 
367 	/* The kernel semaphores */
368 	BUFFER_FIXED( SEMAPHORE_LAST ) \
369 	SEMAPHORE_INFO semaphoreInfo[ SEMAPHORE_LAST + 8 ];
370 #ifdef USE_THREADS
371 	MUTEX_DECLARE_STORAGE( semaphore );
372 #endif /* USE_THREADS */
373 
374 	/* The kernel mutexes.  Since mutexes usually aren't scalar values and
375 	   are declared and accessed via macros that manipulate various fields,
376 	   we have to declare a pile of them individually rather than using an
377 	   array of mutexes */
378 #ifdef USE_THREADS
379 	MUTEX_DECLARE_STORAGE( mutex1 );
380 	MUTEX_DECLARE_STORAGE( mutex2 );
381 	MUTEX_DECLARE_STORAGE( mutex3);
382 #endif /* USE_THREADS */
383 
384 	/* The kernel thread data */
385 #ifdef USE_THREADS
386 	THREAD_INFO threadInfo;
387 #endif /* USE_THREADS */
388 
389 	/* The kernel secure memory list and a lock to protect it */
390 	void *allocatedListHead, *allocatedListTail;
391 #ifdef USE_THREADS
392 	MUTEX_DECLARE_STORAGE( allocation );
393 #endif /* USE_THREADS */
394 
395 	/* A marker for the end of the kernel data, used during init/shutdown */
396 	int endMarker;
397 	} KERNEL_DATA;
398 
399 /* When we start up and shut down the kernel, we need to clear the kernel
400    data.  However, the init lock may have been set by an external management
401    function, so we can't clear that part of the kernel data.  In addition,
402    on shutdown the shutdown level value must stay set so that any threads
403    still running will be forced to exit at the earliest possible instance,
404    and remain set after the shutdown has completed.  To handle this, we use
405    the following macro to clear only the appropriate area of the kernel data
406    block */
407 
408 #ifdef __STDC__
409 
410 #include <stddef.h>		/* For offsetof() */
411 
412 #define CLEAR_KERNEL_DATA()     \
413 		zeroise( ( BYTE * ) krnlData + offsetof( KERNEL_DATA, initLevel ), \
414 				 sizeof( KERNEL_DATA ) - offsetof( KERNEL_DATA, initLevel ) )
415 #else
416 
417 #define CLEAR_KERNEL_DATA()     \
418 		assert( &krnlDataBlock.endMarker - \
419 				&krnlDataBlock.initLevel < sizeof( krnlDataBlock ) ); \
420 		zeroise( ( void * ) ( &krnlDataBlock.initLevel ), \
421 				 &krnlDataBlock.endMarker - &krnlDataBlock.initLevel )
422 #endif /* C89 compilers */
423 
424 /****************************************************************************
425 *																			*
426 *								ACL Functions								*
427 *																			*
428 ****************************************************************************/
429 
430 /* Prototypes for functions in certm_acl.c */
431 
432 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
433 int preDispatchCheckCertMgmtAccess( IN_HANDLE const int objectHandle,
434 									IN_MESSAGE const MESSAGE_TYPE message,
435 									IN_BUFFER_C( sizeof( MESSAGE_CERTMGMT_INFO ) ) \
436 										const void *messageDataPtr,
437 									IN_ENUM( CRYPT_CERTACTION ) \
438 										const int messageValue,
439 									STDC_UNUSED const void *dummy );
440 
441 /* Prototypes for functions in key_acl.c */
442 
443 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
444 int preDispatchCheckKeysetAccess( IN_HANDLE const int objectHandle,
445 								  IN_MESSAGE const MESSAGE_TYPE message,
446 								  IN_BUFFER_C( sizeof( MESSAGE_KEYMGMT_INFO ) ) \
447 										const void *messageDataPtr,
448 								  IN_ENUM( KEYMGMT_ITEM ) const int messageValue,
449 								  STDC_UNUSED const void *dummy );
450 
451 /* Prototypes for functions in mech_acl.c */
452 
453 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
454 int preDispatchCheckMechanismWrapAccess( IN_HANDLE const int objectHandle,
455 										 IN_MESSAGE const MESSAGE_TYPE message,
456 										 IN_BUFFER_C( sizeof( MECHANISM_WRAP_INFO ) ) \
457 											TYPECAST( MECHANISM_WRAP_INFO * ) \
458 											const void *messageDataPtr,
459 										 IN_ENUM( MECHANISM ) const int messageValue,
460 										 STDC_UNUSED const void *dummy );
461 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
462 int preDispatchCheckMechanismSignAccess( IN_HANDLE const int objectHandle,
463 										 IN_MESSAGE const MESSAGE_TYPE message,
464 										 IN_BUFFER_C( sizeof( MECHANISM_SIGN_INFO ) ) \
465 											TYPECAST( MECHANISM_SIGN_INFO * ) \
466 											const void *messageDataPtr,
467 										 IN_ENUM( MECHANISM ) const int messageValue,
468 										 STDC_UNUSED const void *dummy );
469 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
470 int preDispatchCheckMechanismDeriveAccess( IN_HANDLE const int objectHandle,
471 										   IN_MESSAGE const MESSAGE_TYPE message,
472 										   IN_BUFFER_C( sizeof( MECHANISM_DERIVE_INFO ) ) \
473 												TYPECAST( MECHANISM_DERIVE_INFO * ) \
474 												const void *messageDataPtr,
475 										   IN_ENUM( MECHANISM ) const int messageValue,
476 										   STDC_UNUSED const void *dummy );
477 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
478 int preDispatchCheckMechanismKDFAccess( IN_HANDLE const int objectHandle,
479 										IN_MESSAGE const MESSAGE_TYPE message,
480 										IN_BUFFER_C( sizeof( MECHANISM_KDF_INFO ) ) \
481 											TYPECAST( MECHANISM_KDF_INFO * ) \
482 											const void *messageDataPtr,
483 										IN_ENUM( MECHANISM ) const int messageValue,
484 										STDC_UNUSED const void *dummy );
485 
486 /* Prototypes for functions in msg_acl.c */
487 
488 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
489 BOOLEAN paramAclConsistent( const PARAM_ACL *paramACL,
490 							const BOOLEAN mustBeEmpty );
491 CHECK_RETVAL \
492 int preDispatchSignalDependentObjects( IN_HANDLE const int objectHandle,
493 									   STDC_UNUSED const MESSAGE_TYPE dummy1,
494 									   STDC_UNUSED const void *dummy2,
495 									   STDC_UNUSED const int dummy3,
496 									   STDC_UNUSED const void *dummy4 );
497 CHECK_RETVAL STDC_NONNULL_ARG( ( 5 ) ) \
498 int preDispatchCheckAttributeAccess( IN_HANDLE const int objectHandle,
499 									 IN_MESSAGE const MESSAGE_TYPE message,
500 									 IN_OPT const void *messageDataPtr,
501 									 IN_ATTRIBUTE const int messageValue,
502 									 IN TYPECAST( ATTRIBUTE_ACL * ) \
503 										const void *auxInfo );
504 CHECK_RETVAL \
505 int preDispatchCheckCompareParam( IN_HANDLE const int objectHandle,
506 								  IN_MESSAGE const MESSAGE_TYPE message,
507 								  const void *messageDataPtr,
508 								  IN_ENUM( MESSAGE_COMPARE ) const int messageValue,
509 								  STDC_UNUSED const void *dummy2 );
510 CHECK_RETVAL \
511 int preDispatchCheckCheckParam( IN_HANDLE const int objectHandle,
512 								IN_MESSAGE const MESSAGE_TYPE message,
513 								STDC_UNUSED const void *dummy1,
514 								IN_ENUM( MESSAGE_CHECK ) const int messageValue,
515 								STDC_UNUSED const void *dummy2 );
516 CHECK_RETVAL \
517 int preDispatchCheckActionAccess( IN_HANDLE const int objectHandle,
518 								  IN_MESSAGE const MESSAGE_TYPE message,
519 								  STDC_UNUSED const void *dummy1,
520 								  STDC_UNUSED const int dummy2,
521 								  STDC_UNUSED const void *dummy3 );
522 CHECK_RETVAL \
523 int preDispatchCheckState( IN_HANDLE const int objectHandle,
524 						   IN_MESSAGE const MESSAGE_TYPE message,
525 						   STDC_UNUSED const void *dummy1,
526 						   STDC_UNUSED const int dummy2,
527 						   STDC_UNUSED const void *dummy3 );
528 CHECK_RETVAL \
529 int preDispatchCheckParamHandleOpt( IN_HANDLE const int objectHandle,
530 									IN_MESSAGE const MESSAGE_TYPE message,
531 									STDC_UNUSED const void *dummy1,
532 									const int messageValue,
533 									IN TYPECAST( MESSAGE_ACL * ) \
534 										const void *auxInfo );
535 CHECK_RETVAL \
536 int preDispatchCheckStateParamHandle( IN_HANDLE const int objectHandle,
537 									  IN_MESSAGE const MESSAGE_TYPE message,
538 									  STDC_UNUSED const void *dummy1,
539 									  const int messageValue,
540 									  IN TYPECAST( MESSAGE_ACL * ) \
541 											const void *auxInfo );
542 CHECK_RETVAL \
543 int preDispatchCheckExportAccess( IN_HANDLE const int objectHandle,
544 								  IN_MESSAGE const MESSAGE_TYPE message,
545 								  const void *messageDataPtr,
546 								  IN_ENUM( CRYPT_CERTFORMAT ) const int messageValue,
547 								  STDC_UNUSED const void *dummy2 );
548 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
549 int preDispatchCheckData( IN_HANDLE const int objectHandle,
550 						  IN_MESSAGE const MESSAGE_TYPE message,
551 						  IN_BUFFER_C( sizeof( MESSAGE_DATA ) ) \
552 								const void *messageDataPtr,
553 						  STDC_UNUSED const int dummy1,
554 						  STDC_UNUSED const void *dummy2 );
555 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
556 int preDispatchCheckCreate( IN_HANDLE const int objectHandle,
557 							IN_MESSAGE const MESSAGE_TYPE message,
558 							IN_BUFFER_C( sizeof( MESSAGE_CREATEOBJECT_INFO ) ) \
559 								const void *messageDataPtr,
560 							IN_ENUM( OBJECT_TYPE ) const int messageValue,
561 							STDC_UNUSED const void *dummy );
562 CHECK_RETVAL \
563 int preDispatchCheckUserMgmtAccess( IN_HANDLE const int objectHandle,
564 									IN_MESSAGE const MESSAGE_TYPE message,
565 									STDC_UNUSED const void *dummy1,
566 									IN_ENUM( MESSAGE_USERMGMT ) const int messageValue,
567 									STDC_UNUSED const void *dummy2 );
568 CHECK_RETVAL \
569 int preDispatchCheckTrustMgmtAccess( IN_HANDLE const int objectHandle,
570 									 IN_MESSAGE const MESSAGE_TYPE message,
571 									 const void *messageDataPtr,
572 									 STDC_UNUSED const int messageValue,
573 									 STDC_UNUSED const void *dummy );
574 CHECK_RETVAL \
575 int postDispatchSignalDependentDevices( IN_HANDLE const int objectHandle,
576 										STDC_UNUSED const MESSAGE_TYPE dummy1,
577 										STDC_UNUSED const void *dummy2,
578 										STDC_UNUSED const int dummy3,
579 										STDC_UNUSED const void *dummy4 );
580 CHECK_RETVAL \
581 int postDispatchMakeObjectExternal( STDC_UNUSED const int dummy,
582 									IN_MESSAGE const MESSAGE_TYPE message,
583 									const void *messageDataPtr,
584 									const int messageValue,
585 									const void *auxInfo );
586 CHECK_RETVAL \
587 int postDispatchForwardToDependentObject( IN_HANDLE const int objectHandle,
588 										  IN_MESSAGE const MESSAGE_TYPE message,
589 										  STDC_UNUSED const void *dummy1,
590 										  IN_ENUM( MESSAGE_CHECK ) const int messageValue,
591 										  STDC_UNUSED const void *dummy2 );
592 CHECK_RETVAL \
593 int postDispatchUpdateUsageCount( IN_HANDLE const int objectHandle,
594 								  STDC_UNUSED const MESSAGE_TYPE dummy1,
595 								  STDC_UNUSED const void *dummy2,
596 								  STDC_UNUSED const int dummy3,
597 								  STDC_UNUSED const void *dummy4 );
598 CHECK_RETVAL \
599 int postDispatchChangeState( IN_HANDLE const int objectHandle,
600 							 STDC_UNUSED const MESSAGE_TYPE dummy1,
601 							 STDC_UNUSED const void *dummy2,
602 							 STDC_UNUSED const int dummy3,
603 							 STDC_UNUSED const void *dummy4 );
604 CHECK_RETVAL \
605 int postDispatchChangeStateOpt( IN_HANDLE const int objectHandle,
606 								STDC_UNUSED const MESSAGE_TYPE dummy1,
607 								STDC_UNUSED const void *dummy2,
608 								const int messageValue,
609 								IN TYPECAST( ATTRIBUTE_ACL * ) const void *auxInfo );
610 CHECK_RETVAL \
611 int postDispatchHandleZeroise( IN_HANDLE const int objectHandle,
612 							   IN_MESSAGE const MESSAGE_TYPE message,
613 							   STDC_UNUSED const void *dummy2,
614 							   IN_ENUM( MESSAGE_USERMGMT ) const int messageValue,
615 							   STDC_UNUSED const void *dummy3 );
616 
617 /****************************************************************************
618 *																			*
619 *								Kernel Functions							*
620 *																			*
621 ****************************************************************************/
622 
623 /* Prototypes for functions in attr_acl.c */
624 
625 CHECK_RETVAL_PTR \
626 const void *findAttributeACL( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
627 							  const BOOLEAN isInternalMessage );
628 
629 /* Prototypes for functions in int_msg.c */
630 
631 CHECK_RETVAL \
632 int convertIntToExtRef( IN_HANDLE const int objectHandle );
633 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
634 int getPropertyAttribute( IN_HANDLE const int objectHandle,
635 						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
636 						  OUT_BUFFER_FIXED_C( sizeof( int ) ) void *messageDataPtr );
637 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
638 int setPropertyAttribute( IN_HANDLE const int objectHandle,
639 						  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
640 						  IN_BUFFER_C( sizeof( int ) ) void *messageDataPtr );
641 CHECK_RETVAL \
642 int incRefCount( IN_HANDLE const int objectHandle,
643 				 STDC_UNUSED const int dummy1,
644 				 STDC_UNUSED const void *dummy2,
645 				 const BOOLEAN isInternal );
646 CHECK_RETVAL \
647 int decRefCount( IN_HANDLE const int objectHandle,
648 				 STDC_UNUSED const int dummy1,
649 				 STDC_UNUSED const void *dummy2,
650 				 const BOOLEAN isInternal );
651 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
652 int getDependentObject( IN_HANDLE const int objectHandle,
653 						const int targetType,
654 						IN_BUFFER_C( sizeof( int ) ) \
655 								const void *messageDataPtr,
656 							/* This is a bit of a lie since we actually
657 							   return the dependent object through this
658 							   pointer, however making it non-const means
659 							   that we'd have to also un-const every other
660 							   use of this parameter in all other functions
661 							   accessed via this function pointer */
662 						STDC_UNUSED const BOOLEAN dummy );
663 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
664 int setDependentObject( IN_HANDLE const int objectHandle,
665 						IN_ENUM( SETDEP_OPTION ) const int option,
666 						IN_BUFFER_C( sizeof( int ) ) \
667 								const void *messageDataPtr,
668 						STDC_UNUSED const BOOLEAN dummy );
669 CHECK_RETVAL \
670 int cloneObject( IN_HANDLE const int objectHandle,
671 				 IN_HANDLE const int clonedObject,
672 				 STDC_UNUSED const void *dummy1,
673 				 STDC_UNUSED const BOOLEAN dummy2 );
674 
675 /* Prototypes for functions in sendmsg.c */
676 
677 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
678 int checkTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle,
679 					 OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,
680 					 const long targets );
681 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
682 int findTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle,
683 					OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,
684 					const long targets );
685 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
686 int waitForObject( IN_HANDLE const int objectHandle,
687 				   OUT_PTR_COND OBJECT_INFO **objectInfoPtrPtr );
688 #ifndef NDEBUG
689 const char *getObjectDescriptionNT( IN_HANDLE const int objectHandle );
690 #endif /* NDEBUG */
691 
692 /* Prototypes for functions in objects.c */
693 
694 CHECK_RETVAL \
695 int destroyObjectData( IN_HANDLE const int objectHandle );
696 CHECK_RETVAL \
697 int destroyObjects( void );
698 
699 /* Prototypes for functions in semaphore.c */
700 
701 void setSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore,
702 				   const MUTEX_HANDLE object );
703 void clearSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore );
704 
705 /* Init/shutdown functions for each kernel module */
706 
707 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
708 int initAllocation( INOUT KERNEL_DATA *krnlDataPtr );
709 void endAllocation( void );
710 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
711 int initAttributeACL( INOUT KERNEL_DATA *krnlDataPtr );
712 void endAttributeACL( void );
713 #if defined( USE_CERTIFICATES ) && defined( USE_KEYSETS )
714 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
715 int initCertMgmtACL( INOUT KERNEL_DATA *krnlDataPtr );
716 void endCertMgmtACL( void );
717 #else
718   #define initCertMgmtACL( krnlDataPtr )	CRYPT_OK
719   #define endCertMgmtACL()
720 #endif /* USE_CERTIFICATES && USE_KEYSETS */
721 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
722 int initInternalMsgs( INOUT KERNEL_DATA *krnlDataPtr );
723 void endInternalMsgs( void );
724 #ifdef USE_KEYSETS
725 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
726 int initKeymgmtACL( INOUT KERNEL_DATA *krnlDataPtr );
727 void endKeymgmtACL( void );
728 #else
729   #define initKeymgmtACL( krnlDataPtr )		CRYPT_OK
730   #define endKeymgmtACL()
731 #endif /* USE_KEYSETS */
732 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
733 int initMechanismACL( INOUT KERNEL_DATA *krnlDataPtr );
734 void endMechanismACL( void );
735 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
736 int initMessageACL( INOUT KERNEL_DATA *krnlDataPtr );
737 void endMessageACL( void );
738 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
739 int initObjects( INOUT KERNEL_DATA *krnlDataPtr );
740 void endObjects( void );
741 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
742 int initObjectAltAccess( INOUT KERNEL_DATA *krnlDataPtr );
743 void endObjectAltAccess( void );
744 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
745 int initSemaphores( INOUT KERNEL_DATA *krnlDataPtr );
746 void endSemaphores( void );
747 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
748 int initSendMessage( INOUT KERNEL_DATA *krnlDataPtr );
749 void endSendMessage( void );
750 
751 #endif /* _KERNEL_DEFINED */
752