1 /****************************************************************************
2 *																			*
3 *							cryptlib Core Routines							*
4 *						Copyright Peter Gutmann 1992-2008					*
5 *																			*
6 ****************************************************************************/
7 
8 #include "crypt.h"
9 
10 /* Prototypes for functions in init.c.  These should actually be annotated
11    with CHECK_RETVAL_ACQUIRELOCK( MUTEX_LOCKNAME( initialisation ) and
12    RELEASELOCK( MUTEX_LOCKNAME( initialisation ) ) but the mutex locking
13    types aren't visible outside the kernel and in any case the annotation is
14    only required where the functions are defined, so we just annotate them
15    normally here */
16 
17 CHECK_RETVAL \
18 int krnlBeginInit( void );
19 void krnlCompleteInit( void );
20 CHECK_RETVAL \
21 int krnlBeginShutdown( void );
22 RETVAL \
23 int krnlCompleteShutdown( void );
24 
25 /* Temporary kludge for functions that have to be performed mid-startup or
26    mid-shutdown */
27 
28 int destroyObjects( void );
29 CHECK_RETVAL \
30 int testKernel( void );
31 
32 /* Some messages communicate standard data values that are used again and
33    again so we predefine values for these that can be used globally */
34 
35 const int messageValueTrue = TRUE;
36 const int messageValueFalse = FALSE;
37 const int messageValueCryptOK = CRYPT_OK;
38 const int messageValueCryptError = CRYPT_ERROR;
39 const int messageValueCryptUnused = CRYPT_UNUSED;
40 const int messageValueCryptUseDefault = CRYPT_USE_DEFAULT;
41 const int messageValueCursorFirst = CRYPT_CURSOR_FIRST;
42 const int messageValueCursorNext = CRYPT_CURSOR_NEXT;
43 const int messageValueCursorPrevious = CRYPT_CURSOR_PREVIOUS;
44 const int messageValueCursorLast = CRYPT_CURSOR_LAST;
45 
46 /* OS X Snow Leopard broke dlopen(), if it's called from a (sub-)thread then
47    it dies with a SIGTRAP.  Specifically, if you dlopen() a shared library
48    linked with CoreFoundation from a thread and the calling app wasn't
49    linked with CoreFoundation then the function CFInitialize() inside
50    dlopen() checks if the thread is the main thread (specifically
51    CFInitialize is declared with __attribute__ ((constructor))) and if it
52    isn't being called from the main thread it crashes with a SIGTRAP.  The
53    inability to call dlopen() from a thread was apparently a requirement in
54    pre-Snow Leopard versions as well but was never enforced.  One possible
55    workaround for this would be to require that any application that uses
56    cryptlib also link in CoreFoundation, but this will be rather error-
57    prone, so we disable asynchronous driver binding instead */
58 
59 #if defined( __APPLE__ )
60   #undef USE_THREADS
61 #endif /* __APPLE__  */
62 
63 /* If we're fuzzing we also disable threaded init in order to make the
64    startup behaviour deterministic */
65 
66 #if defined( CONFIG_FUZZ )
67   #undef USE_THREADS
68 #endif /* CONFIG_FUZZ */
69 
70 /****************************************************************************
71 *																			*
72 *							Startup/Shutdown Routines						*
73 *																			*
74 ****************************************************************************/
75 
76 /* The initialisation and shutdown actions performed for various object
77    types.  The pre-init actions are used to handle various preparatory
78    actions that are required before the actual init can be performed, for
79    example to create the system device and user object, which are needed by
80    the init routines.  The pre-shutdown actions are used to signal to various
81    subsystems that a shutdown is about to occur, for example to allow the
82    networking subsystem to gracefully exit from any currently occurring
83    network I/O.
84 
85    The certificate init is somewhat special in that it only performs an
86    internal consistency check rather than performing any actual
87    initialisation.  As such it's not performed as part of the asynchronous
88    init since it has the potential to abort the cryptlib startup and as
89    such can't be allowed to come back at a later date an retroactively shut
90    things down after other crypto operations have already occurred.  In fact
91    since it's part of the startup self-test it's done in the pre-init, as a
92    failure to complete the self-test will result in an immediate abort of the
93    init process.
94 
95    The order of the init/shutdown actions is:
96 
97 					Object type		Action
98 					-----------		------
99 	Pre-init:		Cert			Self-test only
100 					Device			Create system object
101 
102 	Init:			User			Create default user object
103 					Keyset			Drivers - keysets			| Done async.
104 					Device			Drivers - devices			| if
105 					Session			Drivers - networking		| available
106 				   [Several]		Kernel self-test
107 
108 	Pre-shutdown:	Session			Networking - signal socket close
109 					Device			System object - signal entropy poll end
110 
111 	Shutdown:		User			Destroy default user object	| Done by
112 					Device			Destroy system object		| kernel
113 					Keyset			Drivers - keysets
114 					Device			Drivers - devices
115 					Session			Drivers - networking
116 
117    The init order is determined by the following object dependencies:
118 
119 	All -> Device
120 			(System object handles many message types).
121 	User -> Keyset, Cert
122 			(Default user object reads config data from the default keyset
123 			 to init drivers for keysets, devices, and networking, and
124 			 trusted certs.  The default keyset isn't read via a loadable
125 			 keyset driver so it doesn't require the keyset driver init).
126 	Self-test -> Several
127 			(Kernel self-test creates several ephemeral objects in order to
128 			 test the kernel mechanisms).
129 
130    The shutdown order is determined by the following dependencies:
131 
132 	Session (Networking needs to shut down to release any objects that are
133 			 blocked waiting on network I/O)
134 	Device (System object needs to shut down ongoing entropy poll)
135 
136    After this the shutdown proper can take place.  The shutdown order is
137    noncritical, provided that the pre-shutdown actions have occurred.
138 
139    In theory the user and system objects are destroyed as part of the
140    standard shutdown, however the kernel prevents these objects from ever
141    being explicitly destroyed so they're destroyed implicitly by the
142    destroyObjects() cleanup call */
143 
144 CHECK_RETVAL \
145 int certManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
146 								const MANAGEMENT_ACTION_TYPE action );
147 CHECK_RETVAL \
148 int deviceManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
149 								const MANAGEMENT_ACTION_TYPE action );
150 CHECK_RETVAL \
151 int keysetManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
152 								const MANAGEMENT_ACTION_TYPE action );
153 CHECK_RETVAL \
154 int sessionManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
155 								const MANAGEMENT_ACTION_TYPE action );
156 CHECK_RETVAL \
157 int userManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
158 								const MANAGEMENT_ACTION_TYPE action );
159 
160 typedef CHECK_RETVAL \
161 		int ( *MANAGEMENT_FUNCTION )( IN_ENUM( MANAGEMENT_ACTION ) \
162 										const MANAGEMENT_ACTION_TYPE action );
163 
164 static const MANAGEMENT_FUNCTION preInitFunctions[] = {
165   #ifdef USE_CERTIFICATES
166 	certManagementFunction,
167   #endif /* USE_CERTIFICATES */
168 	deviceManagementFunction,
169 	NULL, NULL
170 	};
171 static const MANAGEMENT_FUNCTION initFunctions[] = {
172 	userManagementFunction,
173 	NULL, NULL
174 	};
175 static const MANAGEMENT_FUNCTION asyncInitFunctions[] = {
176   #ifdef USE_KEYSETS
177 	keysetManagementFunction,
178   #endif /* USE_KEYSETS */
179 	deviceManagementFunction,
180   #ifdef USE_SESSIONS
181 	sessionManagementFunction,
182   #endif /* USE_SESSIONS */
183 	NULL, NULL
184 	};
185 static const MANAGEMENT_FUNCTION preShutdownFunctions[] = {
186   #ifdef USE_SESSIONS
187 	sessionManagementFunction,
188   #endif /* USE_SESSIONS */
189 	deviceManagementFunction,
190 	NULL, NULL
191 	};
192 static const MANAGEMENT_FUNCTION shutdownFunctions[] = {
193 	/*userManagementFunction,*/ /*deviceManagementFunction,*/
194   #ifdef USE_KEYSETS
195 	keysetManagementFunction,
196   #endif /* USE_KEYSETS */
197 	deviceManagementFunction,
198   #ifdef USE_SESSIONS
199 	sessionManagementFunction,
200   #endif /* USE_SESSIONS */
201 	NULL, NULL
202 	};
203 
204 /* Dispatch a set of management actions */
205 
206 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
dispatchManagementAction(IN_ARRAY (mgmtFunctionCount)const MANAGEMENT_FUNCTION * mgmtFunctions,IN_INT_SHORT const int mgmtFunctionCount,IN_ENUM (MANAGEMENT_ACTION)const MANAGEMENT_ACTION_TYPE action)207 static int dispatchManagementAction( IN_ARRAY( mgmtFunctionCount ) \
208 										const MANAGEMENT_FUNCTION *mgmtFunctions,
209 									 IN_INT_SHORT const int mgmtFunctionCount,
210 									 IN_ENUM( MANAGEMENT_ACTION ) \
211 										const MANAGEMENT_ACTION_TYPE action )
212 	{
213 	int i, status = CRYPT_OK;
214 
215 	assert( isReadPtr( mgmtFunctions, \
216 					   sizeof( MANAGEMENT_FUNCTION ) * mgmtFunctionCount ) );
217 
218 	REQUIRES( mgmtFunctionCount > 0 && \
219 			  mgmtFunctionCount < MAX_INTLENGTH_SHORT );
220 	REQUIRES( action > MANAGEMENT_ACTION_NONE && \
221 			  action < MANAGEMENT_ACTION_LAST );
222 
223 	/* If we're performing a startup and the kernel is shutting down, bail
224 	   out now */
225 	if( ( action == MANAGEMENT_ACTION_INIT ) && krnlIsExiting() )
226 		return( CRYPT_ERROR_PERMISSION );
227 
228 	/* Dispatch each management action in turn */
229 	for( i = 0; i < mgmtFunctionCount && \
230 				mgmtFunctions[ i ] != NULL && \
231 				i < FAILSAFE_ITERATIONS_MED; i++ )
232 		{
233 		const int localStatus = mgmtFunctions[ i ]( action );
234 		if( cryptStatusError( localStatus ) && cryptStatusOK( status ) )
235 			status = localStatus;
236 
237 		/* If we're performing a startup and the kernel is shutting down,
238 		   bail out now */
239 		if( ( action == MANAGEMENT_ACTION_INIT ) && krnlIsExiting() )
240 			return( CRYPT_ERROR_PERMISSION );
241 		}
242 	ENSURES( i < FAILSAFE_ITERATIONS_MED );
243 
244 	return( status );
245 	}
246 
247 /* Under various OSes we bind to a number of drivers at runtime.  We can
248    either do this sychronously or asynchronously depending on the setting of
249    a config option.  By default we use the async init since it speeds up the
250    startup.  Synchronisation is achieved by having the open/init functions
251    in the modules that require the drivers call krnlWaitSemaphore() on the
252    driver binding semaphore, which blocks until the drivers are bound if an
253    async bind is in progress, or returns immediately if no bind is in
254    progress */
255 
256 #ifdef USE_THREADS
257 
threadedBind(const THREAD_PARAMS * threadParams)258 void threadedBind( const THREAD_PARAMS *threadParams )
259 	{
260 	assert( isReadPtr( threadParams, sizeof( THREAD_PARAMS ) ) );
261 
262 	( void ) dispatchManagementAction( asyncInitFunctions,
263 									   FAILSAFE_ARRAYSIZE( asyncInitFunctions, \
264 														   MANAGEMENT_FUNCTION ),
265 									   MANAGEMENT_ACTION_INIT );
266 	}
267 #endif /* USE_THREADS */
268 
269 /* Perform various sanity checks on the build process.  Since this will
270    typically be running on an embedded system there's not much that we can
271    (safely) do in terms of user I/O except to return a special-case return
272    code and hope that the user checks the embedded systems section of the
273    manual for more details, although we do try and produce diagnostic output
274    if this is enabled */
275 
buildSanityCheck(void)276 static BOOLEAN buildSanityCheck( void )
277 	{
278 	FNPTR_DECLARE( void *, testPtr );
279 	void *testPtrResult;
280 
281 	/* If we're using a user-defined endianness override (i.e. it's a cross-
282 	   compile from a difference architecture) perform a sanity check to
283 	   make sure that the endianness was set right.  The crypto self-test that's
284 	   performed a few lines further down will catch this problem as well but
285 	   it's better to do an explicit check here that catches the endianness
286 	   problem rather than just returning a generic self-test fail error */
287 #if defined( CONFIG_DATA_LITTLEENDIAN ) || defined( CONFIG_DATA_BIGENDIAN )
288   #ifdef DATA_LITTLEENDIAN
289 		if( *( ( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" ) < 0 )
290   #else
291 		if( *( ( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" ) >= 0 )
292   #endif /* DATA_LITTLEENDIAN */
293 			{
294 			/* We should probably sound klaxons as well at this point */
295 			DEBUG_PRINT(( "CPU endianness is configured incorrectly, see "
296 						  "the cryptlib manual for details" ));
297 			return( FALSE );
298 			}
299 #endif /* Big/little-endian override check */
300 
301 	/* Make sure that the compiler doesn't use variable-size enums.  This is
302 	   done by, for example, the PalmOS SDK for backwards compatibility with
303 	   architectural decisions made for 68K-based PalmPilots, and at least
304 	   one ARM compiler, as permitted by the ARM AAPCS (section 7.1.3),
305 	   which says that "this ABI delegates a choice of representation of
306 	   enumerated types to a platform ABI", followed by a long discussion of
307 	   all the problems that this causes, after which it's allowed anyway,
308 	   but it can also be optionally enabled for compilers like gcc, so just
309 	   to be safe we check all compilers except the ones that we know never
310 	   do this */
311 #if !defined( _MSC_VER )
312 	if( sizeof( CRYPT_ALGO_TYPE ) != sizeof( int ) || \
313 		sizeof( CRYPT_MODE_TYPE ) != sizeof( int ) ||
314 		sizeof( CRYPT_ATTRIBUTE_TYPE ) != sizeof( int ) )
315 		{
316 		DEBUG_PRINT(( "Compiler uses variable-length enumerated types, see "
317 					  "the cryptlib manual for details" ));
318 		return( FALSE );
319 		}
320 #endif /* Microsoft compilers */
321 
322 	/* Make sure that the handling of safe function pointers is OK */
323 	FNPTR_SET( testPtr, ( void * ) buildSanityCheck );
324 	testPtrResult = FNPTR_GET( testPtr );
325 	if( testPtrResult != buildSanityCheck )
326 		{
327 		DEBUG_PRINT(( "Handling of safe function pointers is broken" ));
328 		return( FALSE );
329 		}
330 
331 	return( TRUE );
332 	}
333 
334 /* Initialise and shut down the system */
335 
336 CHECK_RETVAL \
initCryptlib(void)337 int initCryptlib( void )
338 	{
339 	int initLevel = 0, status;
340 
341 	/* Let the user know that we're in the cryptlib startup code if they're in
342 	   debug mode */
343 	DEBUG_PRINT(( "\n" ));
344 	DEBUG_PRINT(( "***************************\n" ));
345 	DEBUG_PRINT(( "* Beginning cryptlib init *\n" ));
346 	DEBUG_PRINT(( "***************************\n" ));
347 
348 	/* Perform any required sanity checks on the build process.  This would
349 	   be caught by the self-test but sometimes people don't run this so we
350 	   perform a minimal sanity check here to avoid failing in the startup
351 	   self-tests that follow */
352 	if( !buildSanityCheck() )
353 		{
354 		DEBUG_DIAG(( "Build sanity-check failed" ));
355 		retIntError();
356 		}
357 
358 	/* Initiate the kernel startup */
359 	status = krnlBeginInit();
360 	if( cryptStatusError( status ) )
361 		{
362 		DEBUG_DIAG(( "Kernel init failed" ));
363 		return( status );
364 		}
365 
366 	/* Perform OS-specific additional initialisation inside the kernel init
367 	   lock */
368 	status = initSysVars();
369 	if( cryptStatusError( status ) )
370 		{
371 		DEBUG_DIAG(( "OS-specific initialisation failed" ));
372 		assert( DEBUG_WARN );
373 		krnlCompleteShutdown();
374 		return( CRYPT_ERROR_FAILED );
375 		}
376 
377 	/* Perform the multi-phase bootstrap */
378 	status = dispatchManagementAction( preInitFunctions,
379 									   FAILSAFE_ARRAYSIZE( preInitFunctions, \
380 														   MANAGEMENT_FUNCTION ),
381 									   MANAGEMENT_ACTION_PRE_INIT );
382 	assertNoFault( cryptStatusOK( status ) );
383 	if( cryptStatusOK( status ) )
384 		{
385 		initLevel = 1;
386 		status = dispatchManagementAction( initFunctions,
387 										   FAILSAFE_ARRAYSIZE( initFunctions, \
388 															   MANAGEMENT_FUNCTION ),
389 										   MANAGEMENT_ACTION_INIT );
390 		assertNoFault( cryptStatusOK( status ) );
391 		}
392 	if( cryptStatusOK( status ) )
393 		{
394 #ifdef USE_THREADS
395 		BOOLEAN asyncInit = FALSE;
396 #endif /* USE_THREADS */
397 
398 		initLevel = 2;
399 
400 		/* Perform the final init phase asynchronously or synchronously
401 		   depending on the config option setting.  We always send this
402 		   query to the default user object since no other user objects
403 		   exist at this time */
404 #ifdef USE_THREADS
405 		status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
406 								  IMESSAGE_GETATTRIBUTE, &asyncInit,
407 								  CRYPT_OPTION_MISC_ASYNCINIT );
408 		if( cryptStatusOK( status ) && asyncInit )
409 			{
410 			/* We use the kernel's thread storage for this thread, so we
411 			   specify the thread data storage as NULL */
412 			status = krnlDispatchThread( threadedBind, NULL, NULL, 0,
413 										 SEMAPHORE_DRIVERBIND );
414 			if( cryptStatusError( status ) )
415 				{
416 				/* The thread couldn't be started, try again with a
417 				   synchronous init */
418 				asyncInit = FALSE;
419 				}
420 			}
421 		if( !asyncInit )
422 #endif /* USE_THREADS */
423 		status = dispatchManagementAction( asyncInitFunctions,
424 										   FAILSAFE_ARRAYSIZE( asyncInitFunctions, \
425 															   MANAGEMENT_FUNCTION ),
426 										   MANAGEMENT_ACTION_INIT );
427 		assertNoFault( cryptStatusOK( status ) );
428 		}
429 	if( cryptStatusOK( status ) )
430 		{
431 #ifndef CONFIG_FUZZ
432 		/* Everything's set up, verify that the core crypto algorithms and
433 		   kernel security mechanisms are working as required, unless we're
434 		   running a fuzzing build for which we don't want to get held up
435 		   too long in startup */
436 		status = testKernel();
437 		assertNoFault( cryptStatusOK( status ) );
438 #endif /* CONFIG_FUZZ */
439 		}
440 
441 	/* If anything failed, shut down the internal functions and services
442 	   before we exit */
443 	if( cryptStatusError( status ) )
444 		{
445 		if( initLevel >= 1 )
446 			{
447 			/* Shut down any external interfaces */
448 			( void ) dispatchManagementAction( preShutdownFunctions,
449 									FAILSAFE_ARRAYSIZE( preShutdownFunctions, \
450 														MANAGEMENT_FUNCTION ),
451 									MANAGEMENT_ACTION_PRE_SHUTDOWN );
452 			destroyObjects();
453 			( void ) dispatchManagementAction( shutdownFunctions,
454 									FAILSAFE_ARRAYSIZE( shutdownFunctions, \
455 														MANAGEMENT_FUNCTION ),
456 									MANAGEMENT_ACTION_SHUTDOWN );
457 			}
458 		krnlCompleteShutdown();
459 		return( status );
460 		}
461 
462 	/* Complete the kernel startup */
463 	krnlCompleteInit();
464 
465 	/* Let the user know that the cryptlib startup has completed
466 	   successfully if they're in debug mode */
467 	DEBUG_PRINT(( "\n" ));
468 	DEBUG_PRINT(( "***************************\n" ));
469 	DEBUG_PRINT(( "* cryptlib init completed *\n" ));
470 	DEBUG_PRINT(( "***************************\n" ));
471 	DEBUG_PRINT(( "\n" ));
472 
473 	return( CRYPT_OK );
474 	}
475 
476 CHECK_RETVAL \
endCryptlib(void)477 int endCryptlib( void )
478 	{
479 	int status;
480 
481 	/* Initiate the kernel shutdown */
482 	status = krnlBeginShutdown();
483 	if( cryptStatusError( status ) )
484 		return( status );
485 
486 	/* Reverse the process carried out in the multi-phase bootstrap */
487 	( void ) dispatchManagementAction( preShutdownFunctions,
488 							FAILSAFE_ARRAYSIZE( preShutdownFunctions, \
489 												MANAGEMENT_FUNCTION ),
490 							MANAGEMENT_ACTION_PRE_SHUTDOWN );
491 	status = destroyObjects();
492 	( void ) dispatchManagementAction( shutdownFunctions,
493 							FAILSAFE_ARRAYSIZE( shutdownFunctions, \
494 												MANAGEMENT_FUNCTION ),
495 							MANAGEMENT_ACTION_SHUTDOWN );
496 
497 	/* Complete the kernel shutdown */
498 	krnlCompleteShutdown();
499 	return( status );
500 	}
501