cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cryptdev.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Crypto Device Routines *
4 * Copyright Peter Gutmann 1997-2007 *
5 * *
6 ****************************************************************************/
7 
8 #include "crypt.h"
9 #ifdef INC_ALL
10  #include "capabil.h"
11  #include "device.h"
12 #else
13  #include "device/capabil.h"
14  #include "device/device.h"
15 #endif /* Compiler-specific includes */
16 
17 /****************************************************************************
18 * *
19 * Utility Routines *
20 * *
21 ****************************************************************************/
22 
23 /* Process a crypto mechanism message */
24 
26 static int processMechanismMessage( INOUT DEVICE_INFO *deviceInfoPtr,
27  IN_MESSAGE const MESSAGE_TYPE action,
28  IN_ENUM( MECHANISM ) \
29  const MECHANISM_TYPE mechanism,
30  INOUT void *mechanismInfo,
32  {
33  CRYPT_DEVICE localCryptDevice = deviceInfoPtr->objectHandle;
34  MECHANISM_FUNCTION mechanismFunction = NULL;
35  int refCount, i, status;
36 
37  assert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );
38  assert( isWritePtr( messageExtInfo, sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );
39 
41  REQUIRES( mechanism > MECHANISM_NONE && mechanism < MECHANISM_LAST );
42  REQUIRES( mechanismInfo != NULL );
43 
44  /* Find the function to handle this action and mechanism */
45  if( deviceInfoPtr->mechanismFunctions != NULL )
46  {
47  for( i = 0;
48  i < deviceInfoPtr->mechanismFunctionCount && \
49  deviceInfoPtr->mechanismFunctions[ i ].action != MESSAGE_NONE && \
51  i++ )
52  {
53  if( deviceInfoPtr->mechanismFunctions[ i ].action == action && \
54  deviceInfoPtr->mechanismFunctions[ i ].mechanism == mechanism )
55  {
56  mechanismFunction = \
57  deviceInfoPtr->mechanismFunctions[ i ].function;
58  break;
59  }
60  }
61  ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
62  ENSURES( i < deviceInfoPtr->mechanismFunctionCount );
63  }
64  if( mechanismFunction == NULL && \
65  localCryptDevice != SYSTEM_OBJECT_HANDLE )
66  {
67  /* This isn't the system object, fall back to the system object and
68  see if it can handle the mechanism. We do it this way rather
69  than sending the message through the kernel a second time because
70  all the kernel checking of message parameters has already been
71  done, this saves the overhead of a second, redundant kernel pass.
72  This code was only ever used with Fortezza devices, with PKCS #11
73  devices the support for various mechanisms is too patchy to allow
74  us to rely on it so we always use system mechanisms which we know
75  will get it right. Because it should never be used in normal
76  use, we throw an exception if we get here inadvertently (if this
77  doesn't stop execution then the krnlAcquireObject() will since it
78  will refuse to allocate the system object) */
79  assert( INTERNAL_ERROR );
80  setMessageObjectUnlocked( messageExtInfo );
81  status = krnlSuspendObject( deviceInfoPtr->objectHandle, &refCount );
82  ENSURES( cryptStatusOK( status ) );
83  localCryptDevice = SYSTEM_OBJECT_HANDLE;
84  status = krnlAcquireObject( SYSTEM_OBJECT_HANDLE, /* Will always fail */
86  ( void ** ) &deviceInfoPtr,
88  if( cryptStatusError( status ) )
89  return( status );
90  REQUIRES( deviceInfoPtr->mechanismFunctions != NULL );
91  for( i = 0;
92  i < deviceInfoPtr->mechanismFunctionCount && \
93  deviceInfoPtr->mechanismFunctions[ i ].action != MESSAGE_NONE && \
95  i++ )
96  {
97  if( deviceInfoPtr->mechanismFunctions[ i ].action == action && \
98  deviceInfoPtr->mechanismFunctions[ i ].mechanism == mechanism )
99  {
100  mechanismFunction = \
101  deviceInfoPtr->mechanismFunctions[ i ].function;
102  break;
103  }
104  }
105  ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
106  ENSURES( i < deviceInfoPtr->mechanismFunctionCount );
107  }
108  if( mechanismFunction == NULL )
109  return( CRYPT_ERROR_NOTAVAIL );
110 
111  /* If the message has been sent to the system object, unlock it to allow
112  it to be used by others and dispatch the message */
113  if( localCryptDevice == SYSTEM_OBJECT_HANDLE )
114  {
115  setMessageObjectUnlocked( messageExtInfo );
116  status = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );
117  ENSURES( cryptStatusOK( status ) );
118  assert( ( action == MESSAGE_DEV_DERIVE &&
119  mechanism >= MECHANISM_DERIVE_PKCS5 && \
120  mechanism <= MECHANISM_DERIVE_PGP && \
121  refCount <= 2 ) || \
122  refCount == 1 );
123  /* The system object can send itself a derive mechanism
124  message during the self-test */
125  return( mechanismFunction( NULL, mechanismInfo ) );
126  }
127 
128  /* Send the message to the device */
129  return( mechanismFunction( deviceInfoPtr, mechanismInfo ) );
130  }
131 
132 /****************************************************************************
133 * *
134 * Device API Functions *
135 * *
136 ****************************************************************************/
137 
138 /* Default object creation routines used when the device code doesn't set
139  anything up */
140 
141 static const CREATEOBJECT_FUNCTION_INFO defaultCreateFunctions[] = {
142  { OBJECT_TYPE_CONTEXT, createContext },
143  { OBJECT_TYPE_NONE, NULL }
144  };
145 
146 /* Handle a message sent to a device object */
147 
149 static int deviceMessageFunction( INOUT TYPECAST( MESSAGE_FUNCTION_EXTINFO * ) \
150  void *objectInfoPtr,
152  void *messageDataPtr,
153  IN_INT_SHORT_Z const int messageValue )
154  {
156  ( MESSAGE_FUNCTION_EXTINFO * ) objectInfoPtr;
157  DEVICE_INFO *deviceInfoPtr = \
158  ( DEVICE_INFO * ) messageExtInfo->objectInfoPtr;
159  int status;
160 
161  assert( isWritePtr( objectInfoPtr, sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );
162  assert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );
163 
164  REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
165  REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH_SHORT );
166 
167  /* Process the destroy object message */
168  if( message == MESSAGE_DESTROY )
169  {
170  /* Shut down the device if required */
171  if( deviceInfoPtr->flags & DEVICE_ACTIVE && \
172  deviceInfoPtr->shutdownFunction != NULL )
173  deviceInfoPtr->shutdownFunction( deviceInfoPtr );
174 
175  return( CRYPT_OK );
176  }
177 
178  /* Process attribute get/set/delete messages */
179  if( isAttributeMessage( message ) )
180  {
181  REQUIRES( message == MESSAGE_GETATTRIBUTE || \
182  message == MESSAGE_GETATTRIBUTE_S || \
183  message == MESSAGE_SETATTRIBUTE || \
184  message == MESSAGE_SETATTRIBUTE_S );
185  REQUIRES( isAttribute( messageValue ) || \
186  isInternalAttribute( messageValue ) );
187 
188  if( message == MESSAGE_GETATTRIBUTE )
189  return( getDeviceAttribute( deviceInfoPtr,
190  ( int * ) messageDataPtr,
191  messageValue, messageExtInfo ) );
192  if( message == MESSAGE_GETATTRIBUTE_S )
193  return( getDeviceAttributeS( deviceInfoPtr,
194  ( MESSAGE_DATA * ) messageDataPtr,
195  messageValue, messageExtInfo ) );
196  if( message == MESSAGE_SETATTRIBUTE )
197  {
198  /* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message
199  with no parameters so we don't pass it down to the attribute-
200  handling code */
201  if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
202  return( CRYPT_OK );
203 
204  return( setDeviceAttribute( deviceInfoPtr,
205  *( ( int * ) messageDataPtr ),
206  messageValue, messageExtInfo ) );
207  }
208  if( message == MESSAGE_SETATTRIBUTE_S )
209  {
210  const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
211 
212  return( setDeviceAttributeS( deviceInfoPtr, msgData->data,
213  msgData->length, messageValue,
214  messageExtInfo ) );
215  }
216 
217  retIntError();
218  }
219 
220  /* Process action messages */
221  if( isMechanismActionMessage( message ) )
222  {
223  return( processMechanismMessage( deviceInfoPtr, message,
224  messageValue, messageDataPtr,
225  messageExtInfo ) );
226  }
227 
228  /* Process messages that check a device */
229  if( message == MESSAGE_CHECK )
230  {
231  /* The check for whether this device type can contain an object that
232  can perform the requested operation has already been performed by
233  the kernel so there's nothing further to do here */
234  REQUIRES( ( messageValue == MESSAGE_CHECK_PKC_ENCRYPT_AVAIL || \
235  messageValue == MESSAGE_CHECK_PKC_DECRYPT_AVAIL || \
236  messageValue == MESSAGE_CHECK_PKC_SIGCHECK_AVAIL || \
237  messageValue == MESSAGE_CHECK_PKC_SIGN_AVAIL ) && \
238  ( deviceInfoPtr->type == CRYPT_DEVICE_PKCS11 || \
239  deviceInfoPtr->type == CRYPT_DEVICE_CRYPTOAPI || \
240  deviceInfoPtr->type == CRYPT_DEVICE_HARDWARE ) );
241 
242  return( CRYPT_OK );
243  }
244 
245  /* Process object-specific messages */
246  if( message == MESSAGE_SELFTEST )
247  {
248  /* If the device doesn't have a self-test capability then there's
249  not much that we can do */
250  if( deviceInfoPtr->selftestFunction == NULL )
251  return( CRYPT_OK );
252 
253  return( deviceInfoPtr->selftestFunction( deviceInfoPtr,
254  messageExtInfo ) );
255  }
256  if( message == MESSAGE_KEY_GETKEY )
257  {
258  MESSAGE_KEYMGMT_INFO *getkeyInfo = \
259  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
260 
261  REQUIRES( deviceInfoPtr->getItemFunction != NULL );
262 
263  /* Create a context via an object in the device */
264  return( deviceInfoPtr->getItemFunction( deviceInfoPtr,
265  &getkeyInfo->cryptHandle, messageValue,
266  getkeyInfo->keyIDtype, getkeyInfo->keyID,
267  getkeyInfo->keyIDlength, getkeyInfo->auxInfo,
268  &getkeyInfo->auxInfoLength,
269  getkeyInfo->flags ) );
270  }
271  if( message == MESSAGE_KEY_SETKEY )
272  {
273  MESSAGE_KEYMGMT_INFO *setkeyInfo = \
274  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
275 
276  REQUIRES( deviceInfoPtr->setItemFunction != NULL );
277 
278  /* Update the device with the cert */
279  return( deviceInfoPtr->setItemFunction( deviceInfoPtr,
280  setkeyInfo->cryptHandle ) );
281  }
282  if( message == MESSAGE_KEY_DELETEKEY )
283  {
284  MESSAGE_KEYMGMT_INFO *deletekeyInfo = \
285  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
286 
287  REQUIRES( deviceInfoPtr->deleteItemFunction != NULL );
288 
289  /* Delete an object in the device */
290  return( deviceInfoPtr->deleteItemFunction( deviceInfoPtr,
291  messageValue, deletekeyInfo->keyIDtype,
292  deletekeyInfo->keyID, deletekeyInfo->keyIDlength ) );
293  }
294  if( message == MESSAGE_KEY_GETFIRSTCERT )
295  {
296  MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
297  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
298 
299  REQUIRES( deviceInfoPtr->getFirstItemFunction != NULL );
300  REQUIRES( getnextcertInfo->auxInfoLength == sizeof( int ) );
301  REQUIRES( messageValue == KEYMGMT_ITEM_PUBLICKEY );
302 
303  /* Fetch a cert in a cert chain from the device */
304  return( deviceInfoPtr->getFirstItemFunction( deviceInfoPtr,
305  &getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,
306  getnextcertInfo->keyIDtype, getnextcertInfo->keyID,
307  getnextcertInfo->keyIDlength, messageValue,
308  getnextcertInfo->flags ) );
309  }
310  if( message == MESSAGE_KEY_GETNEXTCERT )
311  {
312  MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
313  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
314 
315  REQUIRES( deviceInfoPtr->getNextItemFunction != NULL );
316  REQUIRES( getnextcertInfo->auxInfoLength == sizeof( int ) );
317 
318  /* Fetch a cert in a cert chain from the device */
319  return( deviceInfoPtr->getNextItemFunction( deviceInfoPtr,
320  &getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,
321  getnextcertInfo->flags ) );
322  }
323  if( message == MESSAGE_DEV_QUERYCAPABILITY )
324  {
325  const void FAR_BSS *capabilityInfoPtr;
326  CRYPT_QUERY_INFO *queryInfo = ( CRYPT_QUERY_INFO * ) messageDataPtr;
327 
328  /* Find the information for this algorithm and return the appropriate
329  information */
330  capabilityInfoPtr = findCapabilityInfo( deviceInfoPtr->capabilityInfoList,
331  messageValue );
332  if( capabilityInfoPtr == NULL )
333  return( CRYPT_ERROR_NOTAVAIL );
334  getCapabilityInfo( queryInfo, capabilityInfoPtr );
335 
336  return( CRYPT_OK );
337  }
338  if( message == MESSAGE_DEV_CREATEOBJECT )
339  {
340  CRYPT_DEVICE iCryptDevice = deviceInfoPtr->objectHandle;
341  CREATEOBJECT_FUNCTION createObjectFunction = NULL;
342  const void *auxInfo = NULL;
343 
344  REQUIRES( messageValue > OBJECT_TYPE_NONE && \
345  messageValue < OBJECT_TYPE_LAST );
346 
347  /* If the device can't have objects created within it, complain */
348  if( deviceInfoPtr->flags & DEVICE_READONLY )
349  return( CRYPT_ERROR_PERMISSION );
350 
351  /* Find the function to handle this object */
352  if( deviceInfoPtr->createObjectFunctions != NULL )
353  {
354  int i;
355 
356  for( i = 0;
357  i < deviceInfoPtr->createObjectFunctionCount && \
358  deviceInfoPtr->createObjectFunctions[ i ].type != OBJECT_TYPE_NONE && \
359  i < FAILSAFE_ITERATIONS_MED; i++ )
360  {
361  if( deviceInfoPtr->createObjectFunctions[ i ].type == messageValue )
362  {
363  createObjectFunction = \
364  deviceInfoPtr->createObjectFunctions[ i ].function;
365  break;
366  }
367  }
368  ENSURES( i < FAILSAFE_ITERATIONS_MED );
369  ENSURES( i < deviceInfoPtr->createObjectFunctionCount );
370  }
371  if( createObjectFunction == NULL )
372  return( CRYPT_ERROR_NOTAVAIL );
373 
374  /* Get any auxiliary info that we may need to create the object */
375  if( messageValue == OBJECT_TYPE_CONTEXT )
376  auxInfo = deviceInfoPtr->capabilityInfoList;
377 
378  /* If the message has been sent to the system object, unlock it to
379  allow it to be used by others and dispatch the message. This is
380  safe because the auxInfo for the system device is in a static,
381  read-only segment and persists even if the system device is
382  destroyed */
383  if( deviceInfoPtr->objectHandle == SYSTEM_OBJECT_HANDLE )
384  {
385  int refCount;
386 
387  setMessageObjectUnlocked( messageExtInfo );
388  status = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );
390  assert( refCount == 1 );
391  status = createObjectFunction( messageDataPtr, auxInfo,
393  }
394  else
395  {
396  /* Create a dummy object, with all details handled by the device.
397  Unlike the system device we don't unlock the device info
398  before we call the create object function because there may be
399  auxiliary info held in the device object that we need in order
400  to create the object. This is OK since we're not tying up the
401  system device but only some auxiliary crypto device */
402  status = createObjectFunction( messageDataPtr, auxInfo,
404  }
405  if( cryptStatusError( status ) )
406  return( status );
407 
408  /* Make the newly-created object a dependent object of the device */
409  return( krnlSendMessage( \
410  ( ( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr )->cryptHandle,
411  IMESSAGE_SETDEPENDENT, ( MESSAGE_CAST ) &iCryptDevice,
413  }
414  if( message == MESSAGE_DEV_CREATEOBJECT_INDIRECT )
415  {
417  const CRYPT_DEVICE iCryptDevice = deviceInfoPtr->objectHandle;
418  int value, refCount;
419 
420  /* At the moment the only objects where can be created in this manner
421  are certificates */
422  REQUIRES( messageValue == OBJECT_TYPE_CERTIFICATE );
423  REQUIRES( deviceInfoPtr->objectHandle == SYSTEM_OBJECT_HANDLE );
424 
425  /* Unlock the system object to allow it to be used by others and
426  dispatch the message */
427  setMessageObjectUnlocked( messageExtInfo );
428  status = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );
430  assert( refCount == 1 );
431  status = createCertificateIndirect( messageDataPtr, NULL, 0 );
432  if( cryptStatusError( status ) )
433  return( status );
434  iCryptHandle = \
435  ( ( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr )->cryptHandle;
436 
437  /* Make the newly-created object a dependent object of the device.
438  There's one special-case situation where we don't do this and
439  that's when we're importing a certificate chain, which is a
440  collection of individual certificate objects each of which have
441  already been made dependent on the device. We could detect this
442  in one of two ways, either implicitly by reading the
443  CRYPT_IATTRIBUTE_SUBTYPE attribute and assuming that if it's a
444  SUBTYPE_CERT_CERTCHAIN that the owner will have been set, or
445  simply by reading the depending user object. Explcitly checking
446  for ownership seems to be the best approach, although it may
447  pass through a case in which we've inadvertently set the owner
448  without intending do, in which case a backup check of the
449  subtype could be used to catch this */
451  &value, OBJECT_TYPE_USER );
452  if( cryptStatusOK( status ) )
453  {
454  /* The object is already owned, don't try and set an owner */
455  return( CRYPT_OK );
456  }
457  return( krnlSendMessage( iCryptHandle, IMESSAGE_SETDEPENDENT,
458  ( MESSAGE_CAST ) &iCryptDevice,
460  }
461 
462  retIntError();
463  }
464 
465 /* Open a device. This is a common function called to create both the
466  internal system device object and general devices */
467 
469 static int openDevice( OUT_HANDLE_OPT CRYPT_DEVICE *iCryptDevice,
472  IN_BUFFER_OPT( nameLength ) const char *name,
473  IN_LENGTH_SHORT_Z const int nameLength,
474  OUT_PTR DEVICE_INFO **deviceInfoPtrPtr )
475  {
476  DEVICE_INFO *deviceInfoPtr;
477  OBJECT_SUBTYPE subType;
478  static const MAP_TABLE subtypeMapTbl[] = {
484  };
485  int value, storageSize, status;
486 
487  assert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) );
488  assert( ( name == NULL && nameLength == 0 ) || \
489  ( isReadPtr( name, nameLength ) ) );
490  assert( isWritePtr( deviceInfoPtrPtr, sizeof( DEVICE_INFO * ) ) );
491 
492  REQUIRES( ( deviceType == CRYPT_DEVICE_NONE && \
493  iCryptOwner == CRYPT_UNUSED ) || \
494  ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
495  isHandleRangeValid( iCryptOwner ) );
496  REQUIRES( deviceType >= CRYPT_DEVICE_NONE && \
497  deviceType < CRYPT_DEVICE_LAST );
498  REQUIRES( ( name == NULL && nameLength == 0 ) || \
499  ( name != NULL && \
500  nameLength >= MIN_NAME_LENGTH && \
501  nameLength <= CRYPT_MAX_TEXTSIZE ) );
502 
503  /* Clear return values */
504  *iCryptDevice = CRYPT_ERROR;
505  *deviceInfoPtrPtr = NULL;
506 
507  /* Fortezza support was removed as of cryptlib 3.4.0 so we add a special-
508  case check to make sure that we don't try and use it */
509  if( deviceType == CRYPT_DEVICE_FORTEZZA )
510  return( CRYPT_ERROR_NOTAVAIL );
511 
512  /* Set up subtype-specific information */
513  status = mapValue( deviceType, &value, subtypeMapTbl,
514  FAILSAFE_ARRAYSIZE( subtypeMapTbl, MAP_TABLE ) );
515  ENSURES( cryptStatusOK( status ) );
516  subType = value;
517  switch( deviceType )
518  {
519  case CRYPT_DEVICE_NONE:
520  storageSize = sizeof( SYSTEMDEV_INFO );
521  break;
522 
523  case CRYPT_DEVICE_PKCS11:
524  storageSize = sizeof( PKCS11_INFO );
525  break;
526 
528  storageSize = sizeof( CRYPTOAPI_INFO );
529  break;
530 
532  storageSize = sizeof( HARDWARE_INFO );
533  break;
534 
535  default:
536  retIntError();
537  }
538 
539  /* Create the device object and connect it to the device */
540  status = krnlCreateObject( iCryptDevice, ( void ** ) &deviceInfoPtr,
541  sizeof( DEVICE_INFO ) + storageSize,
542  OBJECT_TYPE_DEVICE, subType,
543  CREATEOBJECT_FLAG_NONE, iCryptOwner,
544  ACTION_PERM_NONE_ALL, deviceMessageFunction );
545  if( cryptStatusError( status ) )
546  return( status );
547  ANALYSER_HINT( deviceInfoPtr != NULL );
548  *deviceInfoPtrPtr = deviceInfoPtr;
549  deviceInfoPtr->objectHandle = *iCryptDevice;
550  deviceInfoPtr->ownerHandle = iCryptOwner;
551  deviceInfoPtr->type = deviceType;
552  switch( deviceType )
553  {
554  case CRYPT_DEVICE_NONE:
555  deviceInfoPtr->deviceSystem = \
556  ( SYSTEMDEV_INFO * ) deviceInfoPtr->storage;
557  break;
558 
559  case CRYPT_DEVICE_PKCS11:
560  deviceInfoPtr->devicePKCS11 = \
561  ( PKCS11_INFO * ) deviceInfoPtr->storage;
562  break;
563 
565  deviceInfoPtr->deviceCryptoAPI = \
566  ( CRYPTOAPI_INFO * ) deviceInfoPtr->storage;
567  break;
568 
570  deviceInfoPtr->deviceHardware = \
571  ( HARDWARE_INFO * ) deviceInfoPtr->storage;
572  break;
573 
574  default:
575  retIntError();
576  }
577  deviceInfoPtr->storageSize = storageSize;
578 
579  /* Set up the access information for the device and connect to it */
580  switch( deviceType )
581  {
582  case CRYPT_DEVICE_NONE:
583  status = setDeviceSystem( deviceInfoPtr );
584  break;
585 
586  case CRYPT_DEVICE_PKCS11:
587  status = setDevicePKCS11( deviceInfoPtr, name, nameLength );
588  break;
589 
591  status = setDeviceCryptoAPI( deviceInfoPtr );
592  break;
593 
595  status = setDeviceHardware( deviceInfoPtr );
596  break;
597 
598  default:
599  retIntError();
600  }
601  if( cryptStatusOK( status ) )
602  status = deviceInfoPtr->initFunction( deviceInfoPtr, name,
603  nameLength );
604  if( cryptStatusOK( status ) && \
605  deviceInfoPtr->createObjectFunctions == NULL )
606  {
607  /* The device-specific code hasn't set up anything, use the default
608  create-object functions, which just create encryption contexts
609  using the device capability information */
610  deviceInfoPtr->createObjectFunctions = defaultCreateFunctions;
611  deviceInfoPtr->createObjectFunctionCount = \
612  FAILSAFE_ARRAYSIZE( defaultCreateFunctions, CREATEOBJECT_FUNCTION_INFO );
613  }
614  return( status );
615  }
616 
617 /* Create a (non-system) device object */
618 
620 int createDevice( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
621  STDC_UNUSED const void *auxDataPtr,
622  STDC_UNUSED const int auxValue )
623  {
624  CRYPT_DEVICE iCryptDevice;
625  DEVICE_INFO *deviceInfoPtr = NULL;
626  int initStatus, status;
627 
628  assert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );
629 
630  REQUIRES( auxDataPtr == NULL && auxValue == 0 );
631  REQUIRES( createInfo->arg1 > CRYPT_DEVICE_NONE && \
632  createInfo->arg1 < CRYPT_DEVICE_LAST );
633  REQUIRES( ( createInfo->arg1 != CRYPT_DEVICE_PKCS11 && \
634  createInfo->arg1 != CRYPT_DEVICE_CRYPTOAPI ) || \
635  ( createInfo->strArgLen1 >= MIN_NAME_LENGTH && \
636  createInfo->strArgLen1 <= CRYPT_MAX_TEXTSIZE ) );
637 
638  /* Wait for any async device driver binding to complete */
640  {
641  /* The kernel is shutting down, bail out */
642  DEBUG_DIAG(( "Exiting due to kernel shutdown" ));
643  assert( DEBUG_WARN );
644  return( CRYPT_ERROR_PERMISSION );
645  }
646 
647  /* Pass the call on to the lower-level open function */
648  initStatus = openDevice( &iCryptDevice, createInfo->cryptOwner,
649  createInfo->arg1, createInfo->strArg1,
650  createInfo->strArgLen1, &deviceInfoPtr );
651  if( cryptStatusError( initStatus ) )
652  {
653  /* If the create object failed, return immediately */
654  if( deviceInfoPtr == NULL )
655  return( initStatus );
656 
657  /* The init failed, make sure that the object gets destroyed when we
658  notify the kernel that the setup process is complete */
659  krnlSendNotifier( iCryptDevice, IMESSAGE_DESTROY );
660  }
661 
662  /* We've finished setting up the object-type-specific info, tell the
663  kernel that the object is ready for use */
664  status = krnlSendMessage( iCryptDevice, IMESSAGE_SETATTRIBUTE,
665  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
666  if( cryptStatusOK( status ) && \
667  createInfo->arg1 == CRYPT_DEVICE_CRYPTOAPI )
668  {
669  /* If it's a device that doesn't require an explicit login, move it
670  into the initialised state */
671  status = krnlSendMessage( iCryptDevice, IMESSAGE_SETATTRIBUTE,
673  CRYPT_IATTRIBUTE_INITIALISED );
674  if( cryptStatusError( status ) )
675  krnlSendNotifier( iCryptDevice, IMESSAGE_DESTROY );
676  }
677  if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
678  return( cryptStatusError( initStatus ) ? initStatus : status );
679  createInfo->cryptHandle = iCryptDevice;
680 
681  return( CRYPT_OK );
682  }
683 
684 /* Create the internal system device object. This is somewhat special in
685  that it can't be destroyed through a normal message (it can only be done
686  from one place in the kernel) so if the open fails we don't use the normal
687  signalling mechanism to destroy it but simply return an error code to the
688  caller (the cryptlib init process). This causes the init to fail and
689  destroys the object when the kernel shuts down */
690 
691 CHECK_RETVAL \
692 static int createSystemDeviceObject( void )
693  {
694  CRYPT_DEVICE iSystemObject;
695  DEVICE_INFO *deviceInfoPtr;
696  int initStatus, status;
697 
698  /* Pass the call on to the lower-level open function. This device is
699  unique and has no owner or type.
700 
701  Normally if an object init fails we tell the kernel to destroy it by
702  sending it a destroy message, which is processed after the object's
703  status has been set to normal. However we don't have the privileges
704  to do this for the system object (or the default user object) so we
705  just pass the error code back to the caller, which causes the
706  cryptlib init to fail.
707 
708  In addition the init can fail in one of two ways the object isn't
709  even created (deviceInfoPtr == NULL, nothing to clean up) in which
710  case we bail out immediately, or the object is created but wasn't set
711  up properly (deviceInfoPtr is allocated, but the object can't be
712  used) in which case we bail out after we update its status.
713 
714  A failure at this point is a bit problematic because it's not
715  possible to inform the caller that the system object was successfully
716  created but something went wrong after that. That is, it's assumed
717  that create-object operations are atomic so that a failure status
718  indicates that all allocations and whatnot were rolled back, but
719  since the system object can only be destroyed from within the kernel
720  once it's been created there's no way to roll back the creation of an
721  incomplete system object. In fact it's not even clear what *could*
722  cause a failure at this point apart from "circumstances beyond our
723  control" (memory corruption, a coding error, or something similar).
724  Because this is a can't-occur situation the best course of action for
725  backing out of having a partially-initialised system object that's
726  created at and exists at a level below what the standard system
727  cleanup routines can handle is uncertain.
728 
729  At the moment we just exit and (potentialy) leak the memory, if this
730  situation ever occurs then presumably the calling application will
731  exit and the OS will release the memory for us. This is somewhat
732  ugly, but it's not really clear what other action we can take in the
733  error handler for a can-never-occur error */
734  initStatus = openDevice( &iSystemObject, CRYPT_UNUSED, CRYPT_DEVICE_NONE,
735  NULL, 0, &deviceInfoPtr );
736  if( deviceInfoPtr == NULL )
737  return( initStatus ); /* Create object failed, return immediately */
738  ENSURES( iSystemObject == SYSTEM_OBJECT_HANDLE );
739 
740  /* We've finished setting up the object-type-specific info, tell the
741  kernel that the object is ready for use */
742  status = krnlSendMessage( iSystemObject, IMESSAGE_SETATTRIBUTE,
743  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
744  if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
745  return( cryptStatusError( initStatus ) ? initStatus : status );
746 
747  /* The object has been initialised, move it into the initialised state */
748  return( krnlSendMessage( iSystemObject, IMESSAGE_SETATTRIBUTE,
750  CRYPT_IATTRIBUTE_INITIALISED ) );
751  }
752 
753 /* Generic management function for this class of object. Unlike the usual
754  multilevel init process which is followed for other objects, the devices
755  have an OR rather than an AND relationship since the devices are
756  logically independent so we set a flag for each device type that's
757  successfully initialised rather than recording an init level */
758 
759 typedef CHECK_RETVAL_FNPTR int ( *DEVICEINIT_FUNCTION )( void );
760 typedef void ( *DEVICEND_FUNCTION )( void );
761 typedef struct {
764  const int initFlag;
765  } DEVICEINIT_INFO;
766 
767 #define DEV_NONE_INITED 0x00
768 #define DEV_PKCS11_INITED 0x01
769 #define DEV_CRYPTOAPI_INITED 0x02
770 #define DEV_HARDWARE_INITED 0x04
771 
772 CHECK_RETVAL \
773 int deviceManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \
774  const MANAGEMENT_ACTION_TYPE action )
775  {
776  DEVICEINIT_INFO deviceInitTbl[] = {
777 #ifdef USE_PKCS11
779 #endif /* USE_PKCS11 */
780 #ifdef USE_CRYPTOAPI
782 #endif /* USE_CRYPTOAPI */
783 #ifdef USE_HARDWARE
785 #endif /* USE_HARDWARE */
786  { NULL, 0 }, { NULL, 0 }
787  };
788  static int initFlags = DEV_NONE_INITED;
789  int i, status;
790 
791  REQUIRES( action == MANAGEMENT_ACTION_PRE_INIT || \
792  action == MANAGEMENT_ACTION_INIT || \
793  action == MANAGEMENT_ACTION_PRE_SHUTDOWN || \
794  action == MANAGEMENT_ACTION_SHUTDOWN );
795 
796  switch( action )
797  {
799  status = createSystemDeviceObject();
800  if( cryptStatusError( status ) )
801  {
802  DEBUG_DIAG(( "System object creation failed" ));
803  }
804  return( status );
805 
807  for( i = 0; deviceInitTbl[ i ].deviceInitFunction != NULL && \
808  i < FAILSAFE_ARRAYSIZE( deviceInitTbl, \
810  i++ )
811  {
812  if( krnlIsExiting() )
813  {
814  /* The kernel is shutting down, exit */
815  return( CRYPT_ERROR_PERMISSION );
816  }
817  status = deviceInitTbl[ i ].deviceInitFunction();
818  if( cryptStatusOK( status ) )
819  initFlags |= deviceInitTbl[ i ].initFlag;
820  }
821  ENSURES( i < FAILSAFE_ARRAYSIZE( deviceInitTbl, \
823  return( CRYPT_OK );
824 
826  /* In theory we could signal the background entropy poll to
827  start wrapping up at this point, however if the background
828  polling is being performed in a thread or task then the
829  shutdown is already signalled via the kernel shutdown flag.
830  If it's performed by forking off a process, as it is on Unix
831  systems, there's no easy way to communicate with this process
832  so the shutdown function just kill()s it. Because of this we
833  don't try and do anything here, although this call is left in
834  place as a no-op in case it's needed in the future */
835  return( CRYPT_OK );
836 
838  for( i = 0; deviceInitTbl[ i ].deviceEndFunction != NULL && \
839  i < FAILSAFE_ARRAYSIZE( deviceInitTbl, \
841  i++ )
842  {
843  if( initFlags & deviceInitTbl[ i ].initFlag )
844  deviceInitTbl[ i ].deviceEndFunction();
845  }
846  ENSURES( i < FAILSAFE_ARRAYSIZE( deviceInitTbl, \
848  return( CRYPT_OK );
849  }
850 
851  retIntError();
852  }