cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
init.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Kernel Initialisation *
4 * Copyright Peter Gutmann 1997-2005 *
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 /* The kernel data block. All other kernel modules maintain a pointer to
19  this data */
20 
21 static KERNEL_DATA krnlDataBlock = { 0 }, *krnlData;
22 
23 /****************************************************************************
24 * *
25 * Thread Functions *
26 * *
27 ****************************************************************************/
28 
29 /* Execute a function in a background thread. This takes a pointer to the
30  function to execute in the background thread, a set of parameters to pass
31  to the function, and an optional semaphore ID to set once the thread is
32  started. A function is run via a background thread as follows:
33 
34  void threadFunction( const THREAD_FUNCTION_PARAMS *threadParams )
35  {
36  }
37 
38  initThreadParams( &threadParams, ptrParam, intParam );
39  krnlDispatchThread( threadFunction, &threadParams, SEMAPHORE_ID ) */
40 
41 #ifdef USE_THREADS
42 
43 /* The function that's run as a thread. This calls the user-supplied
44  service function with the user-supplied parameters */
45 
46 THREADFUNC_DEFINE( threadServiceFunction, threadInfoPtr )
47  {
48  const THREAD_INFO *threadInfo = ( THREAD_INFO * ) threadInfoPtr;
50  ORIGINAL_INT_VAR( semaphore, threadInfo->semaphore );
51 
52  assert( isReadPtr( threadInfoPtr, sizeof( THREAD_INFO ) ) );
53  assert( threadServiceFunction != NULL );
54  /* We can't use a REQUIRES() because of the polymorphic return
55  type */
56 
57  /* We're running as a thread, call the thread service function and clear
58  the associated semaphore (if there is one) when we're done. We check
59  to make sure that the thread params are unchanged to catch erroneous
60  use of stack-based storage for the parameter data */
61  threadInfo->threadFunction( &threadInfo->threadParams );
62  assert( threadInfo->threadParams.intParam == ORIGINAL_VALUE( intParam ) );
63  assert( threadInfo->semaphore == ORIGINAL_VALUE( semaphore ) );
64  if( threadInfo->semaphore != SEMAPHORE_NONE )
65  clearSemaphore( threadInfo->semaphore );
66  THREAD_EXIT( threadInfo->syncHandle );
67  }
68 
69 /* Dispatch a function in a background thread. If the threadParams value
70  is NULL we use the kernel's thread data storage, otherwise we use the
71  caller-provided storage */
72 
74 int krnlDispatchThread( THREAD_FUNCTION threadFunction,
76  const int intParam, const SEMAPHORE_TYPE semaphore )
77  {
78  THREAD_INFO *threadInfo = \
79  ( threadState == NULL ) ? &krnlData->threadInfo : \
82  int status;
83 
84  assert( threadState == NULL || \
85  isWritePtr( threadState, sizeof( THREAD_STATE ) ) );
86 
87  static_assert( sizeof( THREAD_STATE ) >= sizeof( THREAD_INFO ), \
88  "Thread storage size" );
89 
90  /* Preconditions: The parameters appear valid, and it's a valid
91  semaphore (SEMAPHORE_NONE is valid since it indicates that the caller
92  doesn't want a semaphore set) */
93  REQUIRES( threadFunction != NULL );
94  REQUIRES( semaphore >= SEMAPHORE_NONE && semaphore < SEMAPHORE_LAST );
95 
96  /* Initialise the thread parameters */
97  memset( threadInfo, 0, sizeof( THREAD_INFO ) );
98  threadInfo->threadFunction = threadFunction;
99  threadInfo->threadParams.ptrParam = ptrParam;
100  threadInfo->threadParams.intParam = intParam;
101  threadInfo->semaphore = semaphore;
102 
103  /* Fire up the thread and set the associated semaphore if required.
104  There's no problem with the thread exiting before we set the
105  semaphore because it's a one-shot, so if the thread gets there first
106  the attempt to set the semaphore below is ignored */
107  THREAD_CREATE( threadServiceFunction, threadInfo, dummy,
108  threadInfo->syncHandle, status );
109  if( cryptStatusOK( status ) && semaphore != SEMAPHORE_NONE )
110  setSemaphore( semaphore, threadInfo->syncHandle );
111  return( status );
112  }
113 #endif /* USE_THREADS */
114 
115 /****************************************************************************
116 * *
117 * Pre-initialisation Functions *
118 * *
119 ****************************************************************************/
120 
121 /* Correct initialisation of the kernel is handled by having the object
122  management functions check the state of the initialisation flag before
123  they do anything and returning CRYPT_ERROR_NOTINITED if cryptlib hasn't
124  been initialised. Since everything in cryptlib depends on the creation
125  of objects, any attempt to use cryptlib without it being properly
126  initialised are caught.
127 
128  Reading the initialisation flag presents something of a chicken-and-egg
129  problem since the read should be protected by the intialisation mutex,
130  but we can't try and grab it unless the mutex has been initialised. If
131  we just read the flag directly and rely on the object map mutex to
132  protect access we run into a potential race condition on shutdown:
133 
134  thread1 thread2
135 
136  inited = T read inited = T
137  inited = F, destroy objects
138  lock objects, die
139 
140  The usual way to avoid this is to perform an interlocked mutex lock, but
141  this isn't possible here since the initialisation mutex may not be
142  initialised.
143 
144  If possible we use dynamic initialisation of the kernel to resolve this,
145  taking advantage of stubs that the compiler inserts into the code to
146  perform initialisation functions when cryptlib is loaded. If the
147  compiler doesn't support this, we have to use static initialisation.
148  This has a slight potential race condition if two threads call the init
149  function at the same time, but in practice the only thing that can happen
150  is that the initialisation mutex gets initialised twice, leading to a
151  small resource leak when cryptlib shuts down */
152 
153 #if defined( __WIN32__ ) || defined( __WINCE__ )
154  /* Windows supports dynamic initialisation by allowing the init/shutdown
155  functions to be called from DllMain(), however if we're building a
156  static library there won't be a DllMain() so we have to do a static
157  init */
158  #ifdef STATIC_LIB
159  #define STATIC_INIT
160  #endif /* STATIC_LIB */
161 #elif defined( __GNUC__ ) && defined( __PIC__ ) && defined( USE_THREADS )
162  /* If we're being built as a shared library with gcc, we can use
163  constructor and destructor functions to automatically perform pre-init
164  and post-shutdown functions in a thread-safe manner. By telling gcc
165  to put the preInit() and postShutdown() functions in the __CTOR_LIST__
166  and __DTOR_LIST__, they're called automatically before dlopen/dlclose
167  return */
168  void preInit( void ) __attribute__ ((constructor));
169  void postShutdown( void ) __attribute__ ((destructor));
170 #elif defined( __SUNPRO_C ) && ( __SUNPRO_C >= 0x570 )
171  /* The value of __SUNPRO_C bears no relation whatsoever to the actual
172  version number of the compiler and even Sun's docs give different
173  values in different places for the same compiler version, but 0x570
174  seems to work */
175  #pragma init ( preInit )
176  #pragma fini ( postShutdown )
177 #elif defined( __PALMOS__ )
178  /* PalmOS supports dynamic initialisation by allowing the init/shutdown
179  functions to be called from PilotMain */
180 #else
181  #define STATIC_INIT
182 #endif /* Systems not supporting dynamic initialisation */
183 
184 /* Before we can begin and end the initialisation process, we need to
185  initialise the initialisation lock. This gets a bit complex, and is
186  handled in the following order of preference:
187 
188  A. Systems where the OS contacts a module to tell it to initialise itself
189  before it's called directly for the first time.
190 
191  B. Systems where statically initialising the lock to an all-zero value is
192  equivalent to intialising it at runtime.
193 
194  C. Systems where the lock must be statically initialised at runtime.
195 
196  A and B are thread-safe, C isn't thread-safe but unlikely to be a problem
197  except in highly unusual situations (two different threads entering
198  krnlBeginInit() at the same time) and not something that we can fix
199  without OS support.
200 
201  To handle this pre-initialisation, we provide the following functions for
202  use with case A, statically initialise the lock to handle case B, and
203  initialise it if required in krnlBeginInit() to handle case C */
204 
205 #ifndef STATIC_INIT
206 
207 void preInit( void )
208  {
209  int status;
210 
211  krnlData = &krnlDataBlock;
212  memset( krnlData, 0, sizeof( KERNEL_DATA ) );
213  MUTEX_CREATE( initialisation, status );
214  if( cryptStatusError( status ) )
215  {
216  /* Error handling at this point gets a bit complicated since these
217  functions are called before the main() is called or dlopen()
218  returns, so there's no way to react to an error status. Even
219  the debug exception thrown by retIntError() may be dangerous,
220  but it's only used in the debug version when (presumably) some
221  sort of debugging support is present. In any case if the mutex
222  create fails at this point (a) something is seriously wrong and
223  (b) presumably successive mutex creations will fail as well, at
224  which point they can be detected */
226  }
227  }
228 
229 void postShutdown( void )
230  {
231  MUTEX_DESTROY( initialisation );
232  memset( krnlData, 0, sizeof( KERNEL_DATA ) );
233  }
234 #endif /* !STATIC_INIT */
235 
236 /****************************************************************************
237 * *
238 * Initialisation Functions *
239 * *
240 ****************************************************************************/
241 
242 /* Begin and complete the kernel initialisation, leaving the initialisation
243  mutex locked between the two calls to allow external initialisation of
244  further, non-kernel-related items */
245 
246 CHECK_RETVAL \
247 int krnlBeginInit( void )
248  {
249  int status;
250 
251 #ifdef STATIC_INIT
252  /* If the krnlData hasn't been set up yet, set it up now */
253  if( krnlDataBlock.initLevel <= INIT_LEVEL_NONE )
254  {
255  /* We're starting up, set up the initialisation lock */
256  krnlData = &krnlDataBlock;
257  memset( krnlData, 0, sizeof( KERNEL_DATA ) );
258  MUTEX_CREATE( initialisation, status );
259  ENSURES( cryptStatusOK( status ) );
260  }
261 #endif /* STATIC_INIT */
262 
263  /* Lock the initialisation mutex to make sure that other threads don't
264  try to access it */
265  MUTEX_LOCK( initialisation );
266 
267  /* If we're already initialised, don't to anything */
268  if( krnlData->initLevel > INIT_LEVEL_NONE )
269  {
270  MUTEX_UNLOCK( initialisation );
271  return( CRYPT_ERROR_INITED );
272  }
273 
274 #ifndef USE_EMBEDDED_OS
275  /* If the time is screwed up we can't safely do much since so many
276  protocols and operations depend on it, however since embedded
277  systems may not have RTCs or if they have them they're inevitably
278  not set right, we don't perform this sanity-check if it's an
279  embedded build */
280  if( getTime() <= MIN_TIME_VALUE )
281  {
282  MUTEX_UNLOCK( initialisation );
283  DEBUG_PRINT(( "System time is severely messed up, cannot continue "
284  "without a correctly set system clock" ));
285  retIntError();
286  }
287 #endif /* USE_EMBEDDED_OS */
288 
289  /* Initialise the ephemeral portions of the kernel data block. Since
290  the shutdown level value is non-ephemeral (it has to persist across
291  shutdowns to handle threads that may still be active inside cryptlib
292  when a shutdown occurs), we have to clear this explicitly */
295 
296  /* Initialise all of the kernel modules. Except for the allocation of
297  the kernel object table this is all straight static initialistion
298  and self-checking, so we should never fail at this stage */
299  status = initAllocation( krnlData );
300  if( cryptStatusOK( status ) )
301  status = initAttributeACL( krnlData );
302  if( cryptStatusOK( status ) )
303  status = initCertMgmtACL( krnlData );
304  if( cryptStatusOK( status ) )
305  status = initInternalMsgs( krnlData );
306  if( cryptStatusOK( status ) )
307  status = initKeymgmtACL( krnlData );
308  if( cryptStatusOK( status ) )
309  status = initMechanismACL( krnlData );
310  if( cryptStatusOK( status ) )
311  status = initMessageACL( krnlData );
312  if( cryptStatusOK( status ) )
313  status = initObjects( krnlData );
314  if( cryptStatusOK( status ) )
315  status = initObjectAltAccess( krnlData );
316  if( cryptStatusOK( status ) )
317  status = initSemaphores( krnlData );
318  if( cryptStatusOK( status ) )
319  status = initSendMessage( krnlData );
320  if( cryptStatusError( status ) )
321  {
322  MUTEX_UNLOCK( initialisation );
323  retIntError();
324  }
325 
326  /* The kernel data block has been initialised */
327  krnlData->initLevel = INIT_LEVEL_KRNLDATA;
328 
329  return( TRUE );
330  }
331 
332 void krnlCompleteInit( void )
333  {
334  /* We've completed the initialisation process */
335  krnlData->initLevel = INIT_LEVEL_FULL;
336 
337  MUTEX_UNLOCK( initialisation );
338  }
339 
340 /* Begin and complete the kernel shutdown, leaving the initialisation
341  mutex locked between the two calls to allow external shutdown of
342  further, non-kernel-related items. The shutdown proceeds as follows:
343 
344  lock initialisation mutex;
345  signal internal worker threads (async.init, randomness poll)
346  to exit (shutdownLevel = SHUTDOWN_LEVEL_THREADS);
347  signal all non-destroy messages to fail
348  (shutdownLevel = SHUTDOWN_LEVEL_MESSAGES in destroyObjects());
349  destroy objects (via destroyObjects());
350  shut down kernel modules;
351  shut down kernel mechanisms (semaphores, messages)
352  (shutdownLevel = SHUTDOWN_LEVEL_MUTEXES);
353  clear kernel data; */
354 
355 CHECK_RETVAL \
356 int krnlBeginShutdown( void )
357  {
358  /* Lock the initialisation mutex to make sure that other threads don't
359  try to access it */
360  MUTEX_LOCK( initialisation );
361 
362  /* We can only begin a shutdown if we're fully initialised */
363  REQUIRES( krnlData->initLevel == INIT_LEVEL_FULL );
364 
365  /* If we're already shut down, don't to anything */
366  if( krnlData->initLevel <= INIT_LEVEL_NONE )
367  {
368  MUTEX_UNLOCK( initialisation );
369  return( CRYPT_ERROR_NOTINITED );
370  }
371  krnlData->initLevel = INIT_LEVEL_KRNLDATA;
372 
373  /* Signal all remaining internal threads to exit (dum differtur, vita
374  transcurrit) */
376 
377  return( CRYPT_OK );
378  }
379 
381  {
382 #if 0 /* The object destruction has to be performed between two phases of
383  the external shutdown, so we can't currently do it here */
384  destroyObjects();
385 #endif /* 0 */
386 
387  /* Once the kernel objects have been destroyed, we're in the closing-down
388  state in which no more messages are processed. There are a few
389  special-case situations such as a shutdown that occurs because of a
390  failure to initialise that we also need to handle */
391  REQUIRES( ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \
392  krnlData->shutdownLevel == SHUTDOWN_LEVEL_NONE ) || \
393  ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \
394  krnlData->shutdownLevel == SHUTDOWN_LEVEL_MESSAGES ) || \
395  ( krnlData->initLevel == INIT_LEVEL_FULL && \
396  krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES ) );
397 
398  /* Shut down all of the kernel modules */
399  endAllocation();
400  endAttributeACL();
401  endCertMgmtACL();
402  endInternalMsgs();
403  endKeymgmtACL();
404  endMechanismACL();
405  endMessageACL();
406  endObjects();
408  endSemaphores();
409  endSendMessage();
410 
411  /* At this point all kernel services have been shut down */
413 
414  /* Turn off the lights on the way out. Note that the kernel data-
415  clearing operation leaves the shutdown level set to handle any
416  threads that may still be active */
418  krnlData->shutdownLevel = SHUTDOWN_LEVEL_ALL;
419  MUTEX_UNLOCK( initialisation );
420 
421 #ifdef STATIC_INIT
422  /* We're shutting down, destroy the initialisation lock */
423  MUTEX_DESTROY( initialisation );
424  memset( krnlData, 0, sizeof( KERNEL_DATA ) );
425 #endif /* STATIC_INIT */
426 
427  return( CRYPT_OK );
428  }
429 
430 /* Indicate to a cryptlib-internal worker thread that the kernel is shutting
431  down and the thread should exit as quickly as possible. We don't protect
432  this check with a mutex since it can be called after the kernel mutexes
433  have been destroyed. This lack of mutex protection for the flag isn't a
434  serious problem, it's checked at regular intervals by worker threads so
435  if the thread misses the flag update it'll bve caught at the next check */
436 
437 CHECK_RETVAL_BOOL \
438 BOOLEAN krnlIsExiting( void )
439  {
440  return( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_THREADS );
441  }
442 
443 /****************************************************************************
444 * *
445 * Extended Self-test Functions *
446 * *
447 ****************************************************************************/
448 
449 /* Self-test code for several general crypto algorithms that are used
450  internally all over cryptlib: MD5, SHA-1, and 3DES (and by extension
451  DES) */
452 
453 #if defined( INC_ALL )
454  #include "capabil.h"
455 #else
456  #include "device/capabil.h"
457 #endif /* Compiler-specific includes */
458 
459 CHECK_RETVAL_BOOL \
460 static BOOLEAN testGeneralAlgorithms( void )
461  {
462  const CAPABILITY_INFO *capabilityInfo;
463  int status;
464 
465  /* Test the MD5 functionality */
466 #ifdef USE_MD5
467  capabilityInfo = getMD5Capability();
468  status = capabilityInfo->selfTestFunction();
469  if( cryptStatusError( status ) )
470  {
471  DEBUG_DIAG(( "MD5 self-test failed" ));
472  return( FALSE );
473  }
474 #endif /* USE_MD5 */
475 
476  /* Test the SHA-1 functionality */
477  capabilityInfo = getSHA1Capability();
478  status = capabilityInfo->selfTestFunction();
479  if( cryptStatusError( status ) )
480  {
481  DEBUG_DIAG(( "SHA-1 self-test failed" ));
482  return( FALSE );
483  }
484 
485  /* Test the 3DES (and DES) functionality */
486  capabilityInfo = get3DESCapability();
487  status = capabilityInfo->selfTestFunction();
488  if( cryptStatusError( status ) )
489  {
490  DEBUG_DIAG(( "3DES self-test failed" ));
491  return( FALSE );
492  }
493 
494  return( TRUE );
495  }
496 
497 /* Test the kernel mechanisms to make sure that everything's working as
498  expected. This performs the following tests:
499 
500  General:
501 
502  Object creation.
503 
504  Access checks:
505 
506  Inability to access internal object or attribute via external message.
507  Inability to perform an internal-only action externally, ability to
508  perform an internal-only action internally
509 
510  Attribute checks:
511 
512  Attribute range checking for numeric, string, boolean, and time
513  attributes.
514  Inability to write a read-only attribute, read a write-only attribute,
515  or delete a non-deletable attribute.
516 
517  Object state checks:
518 
519  Ability to perform standard operation on object, ability to transition a
520  state = low object to state = high.
521  Inability to perform state = high operation on state = low object,
522  inability to perform state = low operation on state = high object.
523 
524  Object property checks:
525 
526  Ability to use an object with a finite usage count, inability to
527  increment the count, ability to decrement the count, inability to
528  exceed the usage count.
529  Ability to lock an object, inability to change security parameters once
530  it's locked */
531 
532 CHECK_RETVAL_BOOL \
533 static BOOLEAN checkNumericRange( IN_HANDLE const CRYPT_CONTEXT iCryptContext )
534  {
535  int value;
536 
537  REQUIRES_B( isHandleRangeValid( iCryptContext ) );
538 
539  /* Verify kernel range checking of numeric values */
540  value = -10; /* Below (negative) */
541  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
543  return( FALSE );
544  value = 0; /* Lower bound fencepost error */
545  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
547  return( FALSE );
548  value = 1; /* Lower bound */
549  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
551  return( FALSE );
552  value = 10000; /* Mid-range */
553  krnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,
555  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
557  return( FALSE );
558  value = 20000; /* Upper bound */
559  krnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,
561  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
563  return( FALSE );
564  value = 20001; /* Upper bound fencepost error */
565  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
567  return( FALSE );
568  value = 32767; /* High */
569  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
571  return( FALSE );
572 
573  return( TRUE );
574  }
575 
576 CHECK_RETVAL_BOOL \
577 static BOOLEAN checkStringRange( IN_HANDLE const CRYPT_CONTEXT iCryptContext )
578  {
580  BYTE buffer[ CRYPT_MAX_HASHSIZE + 1 + 8 ];
581 
582  REQUIRES_B( isHandleRangeValid( iCryptContext ) );
583 
584  /* Verify kernel range checking of string values. We have to disable
585  the more outrageous out-of-bounds values in the debug version since
586  they'll cause the debug kernel to throw an exception if it sees
587  them. In addition for internal messages this results in an internal-
588  error status rather than a argument-error status since the values are
589  so far out of their allowed range that it's reported as a problem
590  with the caller rather than with the parameters used */
591  memset( buffer, '*', CRYPT_MAX_HASHSIZE + 1 );
592 #ifdef NDEBUG
593  /* Below (negative) */
594  setMessageData( &msgData, buffer, -10 );
595  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
597  return( FALSE );
598 #endif /* NDEBUG */
599  /* Lower bound fencepost error */
600  setMessageData( &msgData, buffer, 7 );
601  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
603  return( FALSE );
604  /* Lower bound */
605  setMessageData( &msgData, buffer, 8 );
606  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
608  return( FALSE );
609  /* Mid-range */
610  setMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE / 2 );
611  krnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,
613  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
615  return( FALSE );
616  /* Upper bound */
617  setMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE );
618  krnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,
620  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
622  return( FALSE );
623  /* Upper bound fencepost error */
624  setMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE + 1 );
625  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
627  return( FALSE );
628 #ifdef NDEBUG
629  /* High */
630  setMessageData( &msgData, buffer, 32767 );
631  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
633  return( FALSE );
634 #endif /* NDEBUG */
635 
636  return( TRUE );
637  }
638 
639 CHECK_RETVAL_BOOL \
640 static BOOLEAN checkUsageCount( IN_HANDLE const CRYPT_CONTEXT iCryptContext )
641  {
642  BYTE buffer[ 16 + 8 ];
643  int value;
644 
645  REQUIRES_B( isHandleRangeValid( iCryptContext ) );
646 
647  /* Verify the ability to use an object with a finite usage count, the
648  inability to increment the count, the ability to decrement the count,
649  and the inability to exceed the usage count */
650  value = 10;
651  memset( buffer, 0, 16 );
652  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
654  return( FALSE );
655  if( krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,
656  buffer, 8 ) != CRYPT_OK )
657  return( FALSE );
658  value = 20;
659  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
661  return( FALSE );
662  value = 1;
663  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
665  return( FALSE );
666  if( krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,
667  buffer, 8 ) != CRYPT_OK || \
668  krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,
669  buffer, 8 ) != CRYPT_ERROR_PERMISSION )
670  return( FALSE );
671 
672  return( TRUE );
673  }
674 
675 CHECK_RETVAL_BOOL \
676 static BOOLEAN checkLocking( IN_HANDLE const CRYPT_CONTEXT iCryptContext )
677  {
678  int value;
679 
680  REQUIRES_B( isHandleRangeValid( iCryptContext ) );
681 
682  /* Verify the ability to lock an object and the inability to change
683  security parameters once it's locked */
684  value = 5;
685  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
687  krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
690  return( FALSE );
691  if( krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value,
693  value != TRUE || \
694  krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value,
696  {
697  /* Object should be locked, forwardcount should be inaccessible */
698  return( FALSE );
699  }
700  value = 1;
701  if( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,
703  {
704  /* Security parameters shouldn't be writeable */
705  return( FALSE );
706  }
707 
708  return( TRUE );
709  }
710 
711 #ifdef USE_CERTIFICATES
712 
713 CHECK_RETVAL_BOOL \
714 static BOOLEAN checkBooleanRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )
715  {
716  int value;
717 
718  REQUIRES_B( isHandleRangeValid( iCryptCertificate ) );
719 
720  /* Verify functioning of the kernel range checking, phase 3: Boolean
721  values. Any value should be OK, with conversion to TRUE/FALSE */
722  value = 0; /* FALSE */
723  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
725  return( FALSE );
726  if( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,
728  value != FALSE )
729  return( FALSE );
730  value = 1; /* TRUE */
731  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
733  return( FALSE );
734  if( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,
736  value != TRUE )
737  return( FALSE );
738  value = 10000; /* Positive true-equivalent */
739  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
741  return( FALSE );
742  if( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,
744  value != TRUE )
745  return( FALSE );
746  value = -1; /* Negative true-equivalent */
747  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
749  return( FALSE );
750  if( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,
752  value != TRUE )
753  return( FALSE );
754 
755  return( TRUE );
756  }
757 
758 CHECK_RETVAL_BOOL \
759 static BOOLEAN checkTimeRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )
760  {
762  time_t timeVal;
763 
764  REQUIRES_B( isHandleRangeValid( iCryptCertificate ) );
765 
766  /* Verify kernel range checking of time values. Any value above the
767  initial cutoff date should be OK */
768  setMessageData( &msgData, &timeVal, sizeof( time_t ) );
769  timeVal = 10; /* Below */
770  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
772  return( FALSE );
773  timeVal = MIN_TIME_VALUE; /* Lower bound fencepost error */
774  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
776  return( FALSE );
777  timeVal = MIN_TIME_VALUE + 1; /* Lower bound */
778  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
780  return( FALSE );
781  timeVal = roundUp( timeVal, 0x10000000L ); /* Mid-range */
782  krnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,
784  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
786  return( FALSE );
787 
788  return( TRUE );
789  }
790 
791 CHECK_RETVAL_BOOL \
792 static BOOLEAN checkAllowedValuesRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )
793  {
795  BYTE buffer[ 16 + 8 ];
796  int value;
797 
798  REQUIRES_B( isHandleRangeValid( iCryptCertificate ) );
799 
800  /* Verify kernel range checking of special-case allowed values. Valid
801  values are either a 4-byte IPv4 address or a 16-byte IPv6 address */
803  memset( buffer, 0, 16 );
804  setMessageData( &msgData, buffer, 3 ); /* Below, allowed value 1 */
805  krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
807  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
809  return( FALSE );
810  setMessageData( &msgData, buffer, 4 ); /* Equal, allowed value 1 */
811  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
813  return( FALSE );
814  krnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,
816  krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
818  setMessageData( &msgData, buffer, 5 ); /* Above, allowed value 1 */
819  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
821  return( FALSE );
822  setMessageData( &msgData, buffer, 15 ); /* Below, allowed value 2 */
823  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
825  return( FALSE );
826  setMessageData( &msgData, buffer, 16 ); /* Equal, allowed value 2 */
827  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
829  return( FALSE );
830  krnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,
832  krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
834  setMessageData( &msgData, buffer, 17 ); /* Above, allowed value 2 */
835  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,
837  return( FALSE );
838 
839  return( TRUE );
840  }
841 
842 CHECK_RETVAL_BOOL \
843 static BOOLEAN checkSubrangeRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )
844  {
845  int value;
846 
847  REQUIRES_B( isHandleRangeValid( iCryptCertificate ) );
848 
849  /* Verify kernel range checking of special-case subranges. Valid values
850  are either CRYPT_CURSOR_FIRST ... CRYPT_CURSOR_LAST or an extension
851  ID. Since the cursor movement codes are negative values an out-of-
852  bounds value is MIN + 1 or MAX - 1, not the other way round */
853  value = CRYPT_CURSOR_FIRST + 1; /* Below, subrange 1 */
854  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
856  return( FALSE );
857  value = CRYPT_CURSOR_FIRST; /* Low bound, subrange 1 */
858  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
860  return( FALSE );
861  value = CRYPT_CURSOR_LAST; /* High bound, subrange 1 */
862  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
864  return( FALSE );
865  value = CRYPT_CURSOR_LAST - 1; /* Above, subrange 1 */
866  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
868  return( FALSE );
869  value = CRYPT_CERTINFO_FIRST_EXTENSION - 1; /* Below, subrange 2 */
870  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
872  return( FALSE );
873  value = CRYPT_CERTINFO_FIRST_EXTENSION; /* Low bound, subrange 2 */
874  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
876  return( FALSE );
877  value = CRYPT_CERTINFO_LAST_EXTENSION; /* High bound, subrange 2 */
878  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
880  return( FALSE );
881  value = CRYPT_CERTINFO_LAST_EXTENSION + 1; /* Above, subrange 2 */
882  if( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,
884  return( FALSE );
885 
886  return( TRUE );
887  }
888 #endif /* USE_CERTIFICATES */
889 
890 CHECK_RETVAL \
891 static BOOLEAN testKernelMechanisms( void )
892  {
893  MESSAGE_CREATEOBJECT_INFO createInfo;
896  static const BYTE FAR_BSS key[] = { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 };
897  BYTE buffer[ 128 + 8 ];
898  int value, status;
899 
900  /* Verify object creation */
903  &createInfo, OBJECT_TYPE_CONTEXT );
904  if( cryptStatusError( status ) )
905  {
906  DEBUG_DIAG(( "Object creation self-test failed" ));
907  return( FALSE );
908  }
909  iCryptHandle = createInfo.cryptHandle;
910 
911  /* Verify the inability to access an internal object or attribute using
912  an external message. The attribute access will be stopped by the
913  object access check before it even gets to the attribute access check,
914  so we also re-do the check further on when the object is made
915  externally visible to verify the attribute-level checks as well */
916  if( krnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &value,
918  krnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &value,
919  CRYPT_IATTRIBUTE_TYPE ) != CRYPT_ARGERROR_VALUE )
920  {
921  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
922  DEBUG_DIAG(( "Object internal/external self-test failed" ));
923  return( FALSE );
924  }
925 
926  /* Verify the ability to perform standard operations and the inability
927  to perform a state = high operation on a state = low object */
928  setMessageData( &msgData, ( MESSAGE_CAST ) key, 8 );
929  memset( buffer, 0, 16 );
930  if( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
931  CRYPT_CTXINFO_IV ) != CRYPT_OK || \
932  krnlSendMessage( iCryptHandle, IMESSAGE_CTX_ENCRYPT,
933  buffer, 8 ) != CRYPT_ERROR_NOTINITED )
934  {
935  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
936  DEBUG_DIAG(( "Object low/high state self-test failed" ));
937  return( FALSE );
938  }
939 
940  /* Verify the functioning of kernel range checking, phase 1: Numeric
941  values */
942  if( !checkNumericRange( iCryptHandle ) )
943  {
944  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
945  DEBUG_DIAG(( "Kernel numeric range checking self-test failed" ));
946  return( FALSE );
947  }
948 
949  /* Verify the functioning of kernel range checking, phase 2: String
950  values */
951  if( !checkStringRange( iCryptHandle ) )
952  {
953  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
954  DEBUG_DIAG(( "Kernel string range checking self-test failed" ));
955  return( FALSE );
956  }
957 
958  /* Verify the ability to transition a state = low object to state =
959  high */
960  setMessageData( &msgData, ( MESSAGE_CAST ) key, 8 );
961  if( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
963  {
964  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
965  DEBUG_DIAG(( "Object state transition self-test failed" ));
966  return( FALSE );
967  }
968 
969  /* Verify the inability to write a read-only attribute, read a write-
970  only attribute, or delete a non-deletable attribute */
971  value = CRYPT_MODE_CBC;
972  setMessageData( &msgData, NULL, 0 );
973  if( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, &value,
975  krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData,
977  krnlSendMessage( iCryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,
979  {
980  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
981  DEBUG_DIAG(( "Attribute read/write self-test failed" ));
982  return( FALSE );
983  }
984 
985  /* Verify the inability to perform state = low operations on a state =
986  high object */
987  setMessageData( &msgData, ( MESSAGE_CAST ) key, 8 );
988  if( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
990  krnlSendNotifier( iCryptHandle,
992  {
993  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
994  DEBUG_DIAG(( "Object state access self-test failed" ));
995  return( FALSE );
996  }
997 
998  /* Verify the inability to perform an internal-only action externally
999  but still perform it internally. We also repeat the internal-only
1000  attribute test from earlier on, this access is now stopped at the
1001  attribute check level rather than the object-check level.
1002 
1003  The object will become very briefly visible externally at this point,
1004  but there's nothing that can be done with it because of the
1005  permission settings */
1006  value = \
1007  MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
1009  memset( buffer, 0, 16 );
1010  krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, &value,
1011  CRYPT_IATTRIBUTE_ACTIONPERMS );
1012  krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
1013  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
1014  if( krnlSendMessage( iCryptHandle, MESSAGE_CTX_ENCRYPT,
1015  buffer, 8 ) != CRYPT_ERROR_PERMISSION || \
1016  krnlSendMessage( iCryptHandle, IMESSAGE_CTX_ENCRYPT,
1017  buffer, 8 ) != CRYPT_OK )
1018  {
1019  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1020  DEBUG_DIAG(( "Object internal/external action self-test failed" ));
1021  return( FALSE );
1022  }
1023  if( krnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &value,
1024  CRYPT_IATTRIBUTE_TYPE ) != CRYPT_ARGERROR_VALUE )
1025  {
1026  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1027  DEBUG_DIAG(( "Object internal/external action self-test failed" ));
1028  return( FALSE );
1029  }
1030  krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
1031  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_INTERNAL );
1032 
1033  /* Verify the ability to use an object with a finite usage count, the
1034  inability to increment the count, the ability to decrement the count,
1035  and the inability to exceed the usage count */
1036  if( !checkUsageCount( iCryptHandle ) )
1037  {
1038  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1039  DEBUG_DIAG(( "Object usage-count self-test failed" ));
1040  return( FALSE );
1041  }
1042 
1043  /* Verify the ability to lock an object and the inability to change
1044  security parameters once it's locked */
1045  if( !checkLocking( iCryptHandle ) )
1046  {
1047  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1048  DEBUG_DIAG(( "Object locking self-test failed" ));
1049  return( FALSE );
1050  }
1051  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1052 
1053  /* The following checks require that use of certificates be enabled in
1054  order to perform them. This is because these attribute types are
1055  only valid for certificates (or, by extension, certificate-using
1056  object types like envelopes and sessions). So although these
1057  attribute ACLs won't be tested if certificates aren't enabled, they
1058  also won't be used if certificates aren't enabled */
1059 #ifdef USE_CERTIFICATES
1060 
1061  /* Create a cert object for the remaining kernel range checks */
1064  &createInfo, OBJECT_TYPE_CERTIFICATE );
1065  if( cryptStatusError( status ) )
1066  {
1067  DEBUG_DIAG(( "Certificate object creation self-test failed" ));
1068  return( FALSE );
1069  }
1070  iCryptHandle = createInfo.cryptHandle;
1071 
1072  /* Verify functioning of the kernel range checking, phase 3: Boolean
1073  values */
1074  if( !checkBooleanRange( iCryptHandle ) )
1075  {
1076  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1077  DEBUG_DIAG(( "Kernel boolean range checking self-test failed" ));
1078  return( FALSE );
1079  }
1080 
1081  /* Verify functioning of the kernel range checking, phase 4: Time
1082  values */
1083  if( !checkTimeRange( iCryptHandle ) )
1084  {
1085  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1086  DEBUG_DIAG(( "Kernel time range checking self-test failed" ));
1087  return( FALSE );
1088  }
1089 
1090  /* Verify functioning of kernel range-checking, phase 6: Special-case
1091  checks, allowed values */
1092  if( !checkAllowedValuesRange( iCryptHandle ) )
1093  {
1094  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1095  DEBUG_DIAG(( "Kernel allowed-values range checking self-test failed" ));
1096  return( FALSE );
1097  }
1098 
1099  /* Verify functioning of kernel range-checking, phase 6: Special-case
1100  checks, subranges */
1101  if( !checkSubrangeRange( iCryptHandle ) )
1102  {
1103  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1104  DEBUG_DIAG(( "Kernel subranges range checking self-test failed" ));
1105  return( FALSE );
1106  }
1107  krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
1108 #endif /* USE_CERTIFICATES */
1109 
1110  return( TRUE );
1111  }
1112 
1113 CHECK_RETVAL \
1114 int testKernel( void )
1115  {
1116  ENSURES( testGeneralAlgorithms() );
1117  ENSURES( testKernelMechanisms() );
1118 
1119  return( CRYPT_OK );
1120  }