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