cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
hardware.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Generic Crypto HW Routines *
4 * Copyright Peter Gutmann 1998-2009 *
5 * *
6 ****************************************************************************/
7 
8 #define PKC_CONTEXT /* Indicate that we're working with PKC contexts */
9 #if defined( INC_ALL )
10  #include "crypt.h"
11  #include "context.h"
12  #include "device.h"
13  #include "hardware.h"
14  #include "dev_mech.h"
15 #else
16  #include "crypt.h"
17  #include "context/context.h"
18  #include "device/device.h"
19  #include "device/hardware.h"
20  #include "mechs/dev_mech.h"
21 #endif /* Compiler-specific includes */
22 
23 #ifdef USE_HARDWARE
24 
25 /****************************************************************************
26 * *
27 * Utility Routines *
28 * *
29 ****************************************************************************/
30 
31 /* Get access to the hardware device associated with a context */
32 
33 static int getContextDeviceInfo( const CRYPT_HANDLE iCryptContext,
34  CRYPT_DEVICE *iCryptDevice,
35  HARDWARE_INFO **hwInfoPtrPtr )
36  {
37  CRYPT_DEVICE iLocalDevice;
39  int status;
40 
41  assert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) );
42  assert( isWritePtr( hwInfoPtrPtr, sizeof( HARDWARE_INFO * ) ) );
43 
44  REQUIRES( isHandleRangeValid( iCryptContext ) );
45 
46  /* Clear return values */
47  *iCryptDevice = CRYPT_ERROR;
48  *hwInfoPtrPtr = NULL;
49 
50  /* Get the the device associated with this context */
51  status = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT,
52  &iLocalDevice, OBJECT_TYPE_DEVICE );
53  if( cryptStatusError( status ) )
54  return( status );
55 
56  /* Get the hardware information from the device information */
57  status = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE,
58  ( void ** ) &deviceInfo,
60  if( cryptStatusError( status ) )
61  return( status );
62  *iCryptDevice = iLocalDevice;
63  *hwInfoPtrPtr = deviceInfo->deviceHardware;
64 
65  return( CRYPT_OK );
66  }
67 
68 /* Get a reference to the cryptographic hardware object that underlies a
69  cryptlib object. This is used to connect a template object from a
70  PKCS #15 storage object to the corresponding hardware object via the
71  storageID that's recorded in the storage object */
72 
73 static int getHardwareReference( const CRYPT_CONTEXT iCryptContext,
74  int *keyHandle )
75  {
77  BYTE storageID[ KEYID_SIZE + 8 ];
78  int status;
79 
80  assert( isWritePtr( keyHandle, sizeof( int ) ) );
81 
82  REQUIRES( isHandleRangeValid( iCryptContext ) );
83 
84  setMessageData( &msgData, storageID, KEYID_SIZE );
85  status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
86  &msgData, CRYPT_IATTRIBUTE_DEVICESTORAGEID );
87  if( cryptStatusOK( status ) )
88  status = hwLookupItem( storageID, KEYID_SIZE, keyHandle );
89  if( cryptStatusError( status ) )
90  {
91  /* In theory this is an internal error but in practice we shouldn't
92  treat this as too fatal, what it really means is that the crypto
93  hardware (which we don't control and therefore can't do too much
94  about) is out of sync with the PKCS #15 storage object. This can
95  happen for example during the development process when the
96  hardware is reinitialised but the storage object isn't, or from
97  any one of a number of other circumstances beyond our control.
98  To deal with this we return a standard notfound error but also
99  output a diagnostic message for developers to let them know that
100  they need to check hardware/storage object synchronisation */
101  DEBUG_PRINT(( "Object held in PKCS #15 object store doesn't "
102  "correspond to anything known to the crypto "
103  "hardware HAL" ));
104  return( CRYPT_ERROR_NOTFOUND );
105  }
106 
107  return( CRYPT_OK );
108  }
109 
110 /* Open the PKCS #15 storage object associated with this device */
111 
112 static int openStorageObject( CRYPT_KEYSET *iCryptKeyset,
114  const CRYPT_DEVICE iCryptDevice )
115  {
116  MESSAGE_CREATEOBJECT_INFO createInfo;
117  char storageFilePath[ MAX_PATH_LENGTH + 8 ];
118  int storageFilePathLen, status;
119 
120  assert( isWritePtr( iCryptKeyset, sizeof( CRYPT_KEYSET ) ) );
121 
122  REQUIRES( options == CRYPT_KEYOPT_NONE || \
123  options == CRYPT_KEYOPT_CREATE );
124  REQUIRES( isHandleRangeValid( iCryptDevice ) );
125 
126  /* Clear return value */
127  *iCryptKeyset = CRYPT_ERROR;
128 
129  /* Try and open/create the PKCS #15 storage object */
130  status = fileBuildCryptlibPath( storageFilePath, MAX_PATH_LENGTH,
131  &storageFilePathLen, "CLKEYS", 6,
133  if( cryptStatusError( status ) )
134  return( status );
136  if( options != CRYPT_KEYOPT_NONE )
137  createInfo.arg2 = options;
138  createInfo.strArg1 = storageFilePath;
139  createInfo.strArgLen1 = storageFilePathLen;
141  &createInfo, OBJECT_TYPE_KEYSET );
142  if( cryptStatusError( status ) )
143  return( status );
144 
145  /* Now that we've got the storage object we have to perform a somewhat
146  awkward double-linked-list update of the keyset to give it the handle
147  of the owning device since we need to create any contexts for keys
148  fetched from the storage object via the hardware device rather than
149  the default system device. In theory we could also do this via a new
150  get-owning-object message but we still need to signal to the keyset
151  that it's a storage object rather than a standard keyset so this
152  action serves a second purpose anyway and we may as well use it to
153  explicitly set the owning-device handle at the same time.
154 
155  Note that we don't set the storage object as a dependent object of
156  the device because it's not necessarily constant across device
157  sessions. In particular if we initialise or zeroise the device then
158  the storage object will be reset, but there's no way to switch
159  dependent objects without destroying and recreating the parent. In
160  addition it's not certain whether the storage-object keyset should
161  really be a dependent object or not, in theory it's nice because it
162  allows keyset-specific messages/accesses to be sent to the device and
163  automatically routed to the keyset (standard accesses will still go
164  to the device, so for example a getItem() will be handled as a
165  device-get rather than a keyset-get) but such unmediated access to
166  the underlying keyset probably isn't a good idea anyway */
167  status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
168  ( MESSAGE_CAST ) &iCryptDevice,
169  CRYPT_IATTRIBUTE_HWSTORAGE );
170  if( cryptStatusError( status ) )
171  {
173  return( status );
174  }
175  *iCryptKeyset = createInfo.cryptHandle;
176 
177  return( CRYPT_OK );
178  }
179 
180 /****************************************************************************
181 * *
182 * Init/Shutdown Routines *
183 * *
184 ****************************************************************************/
185 
186 /* Initialise the capability information */
187 
188 #define MAX_DEVICE_CAPABILITIES 32
189 
190 static CAPABILITY_INFO_LIST capabilityInfoList[ MAX_DEVICE_CAPABILITIES ];
191 
192 /* Initialise the cryptographic hardware and its crypto capability
193  interface */
194 
195 int deviceInitHardware( void )
196  {
197  CAPABILITY_INFO *capabilityInfo;
198  static BOOLEAN initCalled = FALSE;
199  int noCapabilities, i, status;
200 
201  /* If we've previously tried to initialise the hardware, don't try it
202  again */
203  if( initCalled )
204  return( CRYPT_OK );
205  initCalled = TRUE;
206 
207  /* Get the hardware capability information */
208  status = hwGetCapabilities( &capabilityInfo, &noCapabilities );
209  if( cryptStatusError( status ) )
210  return( status );
211  ENSURES( noCapabilities > 0 && \
212  noCapabilities < MAX_DEVICE_CAPABILITIES );
213 
214  /* Build the list of available capabilities */
215  memset( capabilityInfoList, 0,
216  sizeof( CAPABILITY_INFO_LIST ) * MAX_DEVICE_CAPABILITIES );
217  for( i = 0; i < noCapabilities && \
218  capabilityInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE; i++ )
219  {
220  REQUIRES( sanityCheckCapability( &capabilityInfo[ i ], FALSE ) );
221 
222  capabilityInfoList[ i ].info = &capabilityInfo[ i ];
223  capabilityInfoList[ i ].next = NULL;
224  if( i > 0 )
225  capabilityInfoList[ i - 1 ].next = &capabilityInfoList[ i ];
226  }
227  ENSURES( i < noCapabilities );
228 
229  return( CRYPT_OK );
230  }
231 
232 void deviceEndHardware( void )
233  {
234  }
235 
236 /****************************************************************************
237 * *
238 * Device Init/Shutdown/Device Control Routines *
239 * *
240 ****************************************************************************/
241 
242 /* Close a previously-opened session with the device. We have to have this
243  before the initialisation function since it may be called by it if the
244  initialisation process fails */
245 
246 static void shutdownFunction( DEVICE_INFO *deviceInfo )
247  {
248  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
249 
250  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
251 
252  /* Shut down access to the storage object */
253  if( hardwareInfo->iCryptKeyset != CRYPT_ERROR )
254  {
256  hardwareInfo->iCryptKeyset = CRYPT_ERROR;
257  }
258  deviceInfo->flags &= ~( DEVICE_ACTIVE | DEVICE_LOGGEDIN );
259  }
260 
261 /* Open a session with the device */
262 
263 static int initFunction( DEVICE_INFO *deviceInfo, const char *name,
264  const int nameLength )
265  {
267  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
268  int status;
269 
270  UNUSED_ARG( name );
271 
272  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
273 
274  /* Set up any internal objects to contain invalid handles */
275  hardwareInfo->iCryptKeyset = CRYPT_ERROR;
276 
277  /* Set up the device ID information */
278  memcpy( hardwareInfo->label, "Cryptographic hardware device", 29 );
279  hardwareInfo->labelLen = 29;
280  deviceInfo->label = hardwareInfo->label;
281  deviceInfo->labelLen = hardwareInfo->labelLen;
282 
283  /* Since this is a built-in hardware device it's always present and
284  available */
285  deviceInfo->flags |= DEVICE_ACTIVE | DEVICE_LOGGEDIN;
286 
287  /* Try and open the PKCS #15 storage object. If we can't open it it
288  means that either it doesn't exist (i.e. persistent key storage
289  isn't supported) or the device hasn't been initialised yet. This
290  isn't a fatal error, although it does mean that public-key
291  operations will be severely restricted since these depend on storing
292  key metadata in the storage object */
293  status = openStorageObject( &iCryptKeyset, CRYPT_KEYOPT_NONE,
294  deviceInfo->objectHandle );
295  if( cryptStatusError( status ) )
296  return( CRYPT_OK ); /* Storage object not available */
297  hardwareInfo->iCryptKeyset = iCryptKeyset;
298 
299  return( CRYPT_OK );
300  }
301 
302 /* Handle device control functions */
303 
304 static int controlFunction( DEVICE_INFO *deviceInfo,
306  const void *data, const int dataLength,
308  {
309  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
310  int status;
311 
312  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
313 
314  REQUIRES( isAttribute( type ) || isInternalAttribute( type ) );
315 
316  UNUSED_ARG( hardwareInfo );
317  UNUSED_ARG( messageExtInfo );
318 
319  /* Handle user authorisation. Since this is a built-in hardware device
320  it's always available for use so these are just dummy routines,
321  although they can be expanded to call down into the HAL for actual
322  authentication if any hardware with such a facility is ever used */
323  if( type == CRYPT_DEVINFO_AUTHENT_USER || \
325  {
326  /* Authenticate the user */
327  /* ... */
328 
329  /* The device is now ready for use */
330  deviceInfo->flags |= DEVICE_LOGGEDIN;
332  MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
333  return( CRYPT_OK );
334  }
335 
336  /* Handle authorisation value change */
338  {
339  /* Set SO PIN */
340  /* ... */
341 
342  return( CRYPT_OK );
343  }
344  if( type == CRYPT_DEVINFO_SET_AUTHENT_USER )
345  {
346  /* Set user PIN */
347  /* ... */
348 
349  return( CRYPT_OK );
350  }
351 
352  /* Handle initialisation and zeroisation */
353  if( type == CRYPT_DEVINFO_INITIALISE || \
354  type == CRYPT_DEVINFO_ZEROISE )
355  {
357 
358  /* Shut down any existing state if necessary in preparation for the
359  zeroise/initialise. Since this clears all state we manually
360  reset the device-active flag since we're still active, just with
361  all information cleared */
362  if( hardwareInfo->iCryptKeyset != CRYPT_ERROR )
363  shutdownFunction( deviceInfo );
364  hwInitialise();
365  deviceInfo->flags |= DEVICE_ACTIVE;
366 
367  /* The only real difference between a zeroise and an initialise is
368  that the zeroise only clears existing state and exits while the
369  initialise resets the state with the device ready to be used
370  again */
371  if( type == CRYPT_DEVINFO_ZEROISE )
372  {
373  char storageFilePath[ MAX_PATH_LENGTH + 1 + 8 ];
374  int storageFilePathLen;
375 
376  /* Zeroise the device */
377  status = fileBuildCryptlibPath( storageFilePath, MAX_PATH_LENGTH,
378  &storageFilePathLen, "CLKEYS", 6,
380  if( cryptStatusOK( status ) )
381  {
382  storageFilePath[ storageFilePathLen ] = '\0';
383  fileErase( storageFilePath );
384  }
385  deviceInfo->flags &= ~DEVICE_LOGGEDIN;
386  return( status );
387  }
388 
389  /* Initialise the device. In theory we're already in the logged-in
390  state but if the initialise was preceded by a zeroise then this
391  will have been cleared, so we explicitly re-set it */
392  status = openStorageObject( &iCryptKeyset, CRYPT_KEYOPT_CREATE,
393  deviceInfo->objectHandle );
394  if( cryptStatusError( status ) )
395  return( status );
396  hardwareInfo->iCryptKeyset = iCryptKeyset;
397  deviceInfo->flags |= DEVICE_LOGGEDIN;
398 
399  return( CRYPT_OK );
400  }
401 
402  /* Handle high-reliability time */
403  if( type == CRYPT_IATTRIBUTE_TIME )
404  {
405  time_t *timePtr = ( time_t * ) data;
406 
407  UNUSED_ARG( timePtr );
408 
409  return( CRYPT_ERROR_NOTAVAIL );
410  }
411 
412  retIntError();
413  }
414 
415 /* Get random data from the device. The messageExtInfo parameter is used
416  to handle recursive messages sent to the system device during the
417  randomness-polling process and isn't used here */
418 
419 static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
420  const int length,
421  MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
422  {
423  UNUSED_ARG( messageExtInfo );
424 
425  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
426  assert( isWritePtr( buffer, length ) );
427 
428  REQUIRES( length > 0 && length < MAX_INTLENGTH );
429 
430  /* Fill the buffer with random data */
431  return( hwGetRandom( buffer, length ) );
432  }
433 
434 /****************************************************************************
435 * *
436 * Get/Set/Delete Item Routines *
437 * *
438 ****************************************************************************/
439 
440 /* Instantiate an object in a device. This works like the create context
441  function but instantiates a cryptlib object using data already contained
442  in the device (for example a stored private key or certificate). If the
443  value being read is a public key and there's a certificate attached then
444  the instantiated object is a native cryptlib object rather than a device
445  object with a native certificate object attached because there doesn't
446  appear to be any good reason to create the public-key object in the
447  device, and the cryptlib native object will probably be faster anyway */
448 
449 static int getItemFunction( DEVICE_INFO *deviceInfo,
450  CRYPT_CONTEXT *iCryptContext,
451  const KEYMGMT_ITEM_TYPE itemType,
453  const void *keyID, const int keyIDlength,
454  void *auxInfo, int *auxInfoLength,
455  const int flags )
456  {
457 #if 0
458  const CRYPT_DEVICE cryptDevice = deviceInfo->objectHandle;
461  HW_KEYINFO keyInfo;
463  const int extraFlags = ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
465  int keyHandle, p15status, status;
466 #endif
467  CRYPT_CONTEXT iLocalContext;
468  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
469  MESSAGE_KEYMGMT_INFO getkeyInfo;
470  int keyHandle, status;
471 
472  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
473  assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
474  assert( isReadPtr( keyID, keyIDlength ) );
475 
476  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
477  itemType == KEYMGMT_ITEM_PRIVATEKEY );
478  REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
479  keyIDtype == CRYPT_KEYID_URI || \
480  keyIDtype == CRYPT_IKEYID_KEYID || \
481  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
482  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
483  REQUIRES( auxInfo == NULL && *auxInfoLength == 0 );
484  REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
485 
486 #if 1
487  /* Redirect the fetch down to the PKCS #15 storage object, which will
488  create either a dummy context that we have to connect to the actual
489  hardware for a private-key object or a native public-key/certificate
490  object if it's a non-private-key item */
491  if( hardwareInfo->iCryptKeyset == CRYPT_ERROR )
492  return( CRYPT_ERROR_NOTINITED );
493  setMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDlength,
494  NULL, 0, flags );
495  status = krnlSendMessage( hardwareInfo->iCryptKeyset,
496  IMESSAGE_KEY_GETKEY, &getkeyInfo,
497  itemType );
498  if( cryptStatusError( status ) )
499  return( status );
500  iLocalContext = getkeyInfo.cryptHandle;
501 
502  /* If it's a public-key fetch, we've created a native object and we're
503  done */
504  if( itemType != KEYMGMT_ITEM_PRIVATEKEY )
505  {
506  *iCryptContext = iLocalContext;
507  return( CRYPT_OK );
508  }
509 
510  /* It was a private-key fetch, we need to connect the dummy context that
511  was created with the underlying hardware. When this final step
512  has been completed we can move the context to the initialised state */
513  status = getHardwareReference( iLocalContext, &keyHandle );
514  if( cryptStatusError( status ) )
515  {
516  krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
517  return( status );
518  }
519  status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
520  &keyHandle, CRYPT_IATTRIBUTE_DEVICEOBJECT );
521  if( cryptStatusOK( status ) )
522  {
523  status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
525  CRYPT_IATTRIBUTE_INITIALISED );
526  }
527  if( cryptStatusError( status ) )
528  {
529  krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
530  return( status );
531  }
532 #else
533  /* As a first step we redirect the fetch down to the PKCS #15 storage
534  object to get any certificate that may be associated with the item.
535  We always do this because if we're fetching a public key then this
536  is all that we need and if we're fetching a private key then we'll
537  associate the certificate with it if it's present */
538  if( hardwareInfo->iCryptKeyset == CRYPT_ERROR )
539  return( CRYPT_ERROR_NOTINITED );
540  setMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDlength,
541  NULL, 0, flags | extraFlags );
542  p15status = krnlSendMessage( hardwareInfo->iCryptKeyset,
543  IMESSAGE_KEY_GETKEY, &getkeyInfo,
545  if( cryptStatusOK( p15status ) )
546  {
547  iCryptCert = getkeyInfo.cryptHandle;
548 
549  /* If we were after a public key, we're done */
550  if( itemType == KEYMGMT_ITEM_PUBLICKEY )
551  {
552  *iCryptContext = iCryptCert;
553  return( CRYPT_OK );
554  }
555 
556  /* If we were after a private key and the keyID is one that isn't
557  stored locally, extract it from the returned private key */
558  // This won't work, there's no CRYPT_IKEYID_KEYID or
559  // CRYPT_IKEYID_PGPKEYID with the cert, only an
560  // CRYPT_IKEYID_ISSUERANDSERIALNUMBER
561  }
562 
563  /* Look up the private key, which we may use directly or simply extract
564  the public-key components from. If there's an error then we
565  preferentially return the error code from the storage object, which
566  is likely to be more informative than a generic CRYPT_ERROR_NOTFOUND
567  from the hardware lookup */
568  status = hwLookupItemInfo( keyIDtype, keyID, keyIDlength, &keyHandle,
569  &keyInfo );
570  if( cryptStatusError( status ) )
571  return( cryptStatusError( p15status ) ? p15status : status );
572  if( itemType == KEYMGMT_ITEM_PUBLICKEY )
573  {
574  MESSAGE_CREATEOBJECT_INFO createInfo;
575 
576  /* There's no certificate present but we do have private-key
577  components from which we can extract the public-key portion to
578  create a native context instead of a device one. This solves a
579  variety of problems including the fact that performing public-key
580  operations natively is often much faster than the time it takes
581  to marshall the data and get it to the crypto hardware, and that
582  if we do it ourselves we can defend against a variety of RSA
583  padding and timing attacks that have come up since the device
584  firmware was done */
585  setMessageCreateObjectInfo( &createInfo, keyInfo.cryptAlgo );
587  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
589  if( cryptStatusError( status ) )
590  return( status );
591  iLocalContext = createInfo.cryptHandle;
592 
593  /* Send the keying information to the context. We don't set the
594  action flags because there are none recorded at the hardware
595  level */
596  status = setPublicComponents( createInfo.cryptHandle,
597  keyInfo.cryptAlgo,
598  &keyInfo.publicKeyInfo );
599  if( cryptStatusError( status ) )
600  {
601  krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
602  return( status );
603  }
604  *iCryptContext = iLocalContext;
605  return( CRYPT_OK );
606  }
607 
608  /* It's a private key, create a dummy context for the device object,
609  remember the device that it's contained in, and record the handle for
610  the device-internal key */
611  capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfoList,
612  keyInfo.cryptAlgo );
613  if( capabilityInfoPtr == NULL )
614  return( CRYPT_ERROR_NOTAVAIL );
615  status = createContextFromCapability( &iLocalContext, cryptDevice,
616  capabilityInfoPtr,
619  if( cryptStatusError( status ) )
620  {
621  if( iCryptCert != CRYPT_UNUSED )
622  krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
623  return( status );
624  }
625  status = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,
626  ( MESSAGE_CAST ) &cryptDevice,
628  if( cryptStatusOK( status ) )
629  status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
630  ( MESSAGE_CAST ) &keyHandle,
631  CRYPT_IATTRIBUTE_DEVICEOBJECT );
632  if( cryptStatusError( status ) )
633  {
634  krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
635  if( iCryptCert != CRYPT_UNUSED )
636  krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
637  return( status );
638  }
639 
640  /* Set the object's label, send the keying information to the context,
641  and mark it as initialised (i.e. with a key loaded). Setting the
642  label requires special care because the label that we're setting
643  matches that of an existing object, so trying to set it as a standard
644  CRYPT_CTXINFO_LABEL will return a CRYPT_ERROR_DUPLICATE error when
645  the context code checks for the existence of an existing label. To
646  handle this, we use the attribute CRYPT_IATTRIBUTE_EXISTINGLABEL to
647  indicate that we're setting a label that matches an existing object
648  in the device */
649  if( keyInfo.labelLength <= 0 )
650  {
651  /* If there's no label present, use a dummy value */
652  strlcpy_s( keyInfo.label, CRYPT_MAX_TEXTSIZE, "Label-less private key" );
653  keyInfo.labelLength = 22;
654  }
655  setMessageData( &msgData, keyInfo.label, keyInfo.labelLength );
656  status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,
657  &msgData, CRYPT_IATTRIBUTE_EXISTINGLABEL );
658  if( cryptStatusOK( status ) )
659  status = setPublicComponents( iLocalContext, keyInfo.cryptAlgo,
660  &keyInfo.publicKeyInfo );
661  if( cryptStatusOK( status ) )
662  status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
664  CRYPT_IATTRIBUTE_INITIALISED );
665  if( cryptStatusOK( status ) && ( iCryptCert != CRYPT_UNUSED ) )
666  {
667  /* If there's a certificate present, attach it to the context. The
668  certificate is an internal object used only by the context so we
669  tell the kernel to mark it as owned by the context only */
670  status = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,
671  ( MESSAGE_CAST ) &iCryptCert,
673  }
674  if( cryptStatusError( status ) )
675  {
676  krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
677  if( iCryptCert != CRYPT_UNUSED )
678  krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
679  }
680 #endif /* 1 */
681 
682  *iCryptContext = iLocalContext;
683  return( CRYPT_OK );
684  }
685 
686 /* Add an object to a device. This can only ever add a certificate
687  (enforced by the kernel ACLs) so we don't have to perform any
688  special-case handling */
689 
690 static int setItemFunction( DEVICE_INFO *deviceInfo,
691  const CRYPT_HANDLE iCryptHandle )
692  {
693  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
694  MESSAGE_KEYMGMT_INFO setkeyInfo;
695 
696  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
697 
698  REQUIRES( isHandleRangeValid( iCryptHandle ) );
699 
700  /* Redirect the add down to the PKCS #15 storage object */
701  if( hardwareInfo->iCryptKeyset == CRYPT_ERROR )
702  return( CRYPT_ERROR_NOTINITED );
703  setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,
704  NULL, 0, KEYMGMT_FLAG_NONE );
705  setkeyInfo.cryptHandle = iCryptHandle;
706  return( krnlSendMessage( hardwareInfo->iCryptKeyset,
707  IMESSAGE_KEY_SETKEY, &setkeyInfo,
709  }
710 
711 /* Delete an object in a device */
712 
713 static int deleteItemFunction( DEVICE_INFO *deviceInfo,
714  const KEYMGMT_ITEM_TYPE itemType,
715  const CRYPT_KEYID_TYPE keyIDtype,
716  const void *keyID, const int keyIDlength )
717  {
718  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
719  MESSAGE_KEYMGMT_INFO getkeyInfo, deletekeyInfo;
720  int status;
721 
722  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
723  assert( isReadPtr( keyID, keyIDlength ) );
724 
725  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
726  itemType == KEYMGMT_ITEM_PRIVATEKEY );
727  REQUIRES( keyIDtype == CRYPT_KEYID_NAME );
728  REQUIRES( keyIDlength > 0 && keyIDlength <= CRYPT_MAX_TEXTSIZE );
729 
730  /* Perform the delete both from the PKCS #15 storage object and the
731  native storage. This gets a bit complicated because in order to
732  find the hardware object we have to extract the storageID, and in
733  order to get that we have to instantiate a dummy private-key object
734  to contain it. In addition if the object that's stored isn't a
735  private-key object then there's no associated cryptographic
736  hardware object. To handle this we try and instantiate a dummy
737  private-key object in order to get the storageID. If this succeeds,
738  we locate the underlying hardware object and delete it. Finally, we
739  delete the PKCS #15 object, either a pure public-key/certificate
740  object or the private-key metadata for the cryptographic hardware
741  object */
742  if( hardwareInfo->iCryptKeyset == CRYPT_ERROR )
743  return( CRYPT_ERROR_NOTINITED );
744  setMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDlength,
745  NULL, 0, KEYMGMT_FLAG_NONE );
746  status = krnlSendMessage( hardwareInfo->iCryptKeyset,
747  IMESSAGE_KEY_GETKEY, &getkeyInfo,
749  if( cryptStatusOK( status ) )
750  {
751  int keyHandle;
752 
753  /* It's a private-key object, get its hardware reference and delete
754  it. If this fails we continue anyway because we know that
755  there's also a PKCS #15 object to delete */
756  status = getHardwareReference( getkeyInfo.cryptHandle, &keyHandle );
757  if( cryptStatusOK( status ) )
758  ( void ) hwDeleteItem( keyHandle );
760  }
761  setMessageKeymgmtInfo( &deletekeyInfo, keyIDtype, keyID, keyIDlength,
762  NULL, 0, KEYMGMT_FLAG_NONE );
763  return( krnlSendMessage( hardwareInfo->iCryptKeyset,
764  IMESSAGE_KEY_DELETEKEY, &deletekeyInfo,
765  itemType ) );
766  }
767 
768 /* Get the sequence of certificates in a chain from a device. Since these
769  functions operate only on certificates we can redirect them straight down
770  to the underlying storage object */
771 
772 static int getFirstItemFunction( DEVICE_INFO *deviceInfo,
774  int *stateInfo,
775  const CRYPT_KEYID_TYPE keyIDtype,
776  const void *keyID, const int keyIDlength,
777  const KEYMGMT_ITEM_TYPE itemType,
778  const int options )
779  {
780  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
781  MESSAGE_KEYMGMT_INFO getnextcertInfo;
782 
783  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
784  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
785  assert( isReadPtr( keyID, keyIDlength ) );
786  assert( isWritePtr( stateInfo, sizeof( int ) ) );
787 
788  REQUIRES( keyIDtype == CRYPT_IKEYID_KEYID );
789  REQUIRES( keyIDlength > 4 && keyIDlength < MAX_INTLENGTH_SHORT );
790  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );
791 
792  /* Clear return values */
793  *iCertificate = CRYPT_ERROR;
794  *stateInfo = CRYPT_ERROR;
795 
796  /* Get the first certificate */
797  setMessageKeymgmtInfo( &getnextcertInfo, keyIDtype, keyID, keyIDlength,
798  stateInfo, sizeof( int ), options );
799  return( krnlSendMessage( hardwareInfo->iCryptKeyset,
800  IMESSAGE_KEY_GETFIRSTCERT, &getnextcertInfo,
802  }
803 
804 static int getNextItemFunction( DEVICE_INFO *deviceInfo,
805  CRYPT_CERTIFICATE *iCertificate,
806  int *stateInfo, const int options )
807  {
808  HARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;
809  MESSAGE_KEYMGMT_INFO getnextcertInfo;
810 
811  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
812  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
813  assert( isWritePtr( stateInfo, sizeof( int ) ) );
814 
815  REQUIRES( isHandleRangeValid( *stateInfo ) || \
816  *stateInfo == CRYPT_ERROR );
817 
818  UNUSED_ARG( hardwareInfo );
819 
820  /* Clear return value */
821  *iCertificate = CRYPT_ERROR;
822 
823  /* If the previous certificate was the last one, there's nothing left to
824  fetch */
825  if( *stateInfo == CRYPT_ERROR )
826  return( CRYPT_ERROR_NOTFOUND );
827 
828  /* Get the next certificate */
829  setMessageKeymgmtInfo( &getnextcertInfo, CRYPT_KEYID_NONE, NULL, 0,
830  stateInfo, sizeof( int ), options );
831  return( krnlSendMessage( hardwareInfo->iCryptKeyset,
832  IMESSAGE_KEY_GETNEXTCERT, &getnextcertInfo,
834  }
835 
836 /****************************************************************************
837 * *
838 * Cryptographic HAL Assist Routines *
839 * *
840 ****************************************************************************/
841 
842 /* The following helper routines provide common functionality needed by most
843  cryptographic HALs, which avoids having to reimplement the same code in
844  each HAL module. These are called from the HAL to provide services such
845  as keygen assist and various context-management functions */
846 
847 /* Set up a mapping from a context to its associated information in the
848  underlying hardware. This generates a storageID for the information and
849  records it and the hardware handle in the context. The caller has to
850  record the storageID alongside the crypto information held by the
851  hardware for later use to look up the information */
852 
853 int setPersonalityMapping( CONTEXT_INFO *contextInfoPtr, const int keyHandle,
854  void *storageID, const int storageIDlength )
855  {
856  CRYPT_DEVICE iCryptDevice;
858  MESSAGE_KEYMGMT_INFO setkeyInfo;
860  BYTE buffer[ KEYID_SIZE + 8 ];
861  int status;
862 
863  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
864  assert( isWritePtr( storageID, storageIDlength ) );
865 
866  REQUIRES( keyHandle >= 0 && keyHandle < INT_MAX );
867  REQUIRES( storageIDlength >= 4 && storageIDlength <= KEYID_SIZE );
868 
869  /* Set up the mapping information in the context */
870  status = hwGetRandom( buffer, KEYID_SIZE );
871  if( cryptStatusError( status ) )
872  return( status );
873  setMessageData( &msgData, buffer, KEYID_SIZE );
874  status = krnlSendMessage( contextInfoPtr->objectHandle,
875  IMESSAGE_SETATTRIBUTE_S, &msgData,
876  CRYPT_IATTRIBUTE_DEVICESTORAGEID );
877  if( cryptStatusOK( status ) )
878  {
879  status = krnlSendMessage( contextInfoPtr->objectHandle,
881  ( MESSAGE_CAST ) &keyHandle,
882  CRYPT_IATTRIBUTE_DEVICEOBJECT );
883  }
884  if( cryptStatusError( status ) )
885  return( status );
886 
887  /* Copy the storageID back to the caller */
888  memcpy( storageID, buffer, storageIDlength );
889 
890  /* If it's a non-PKC context then there's nothing further to do */
891  if( contextInfoPtr->type != CONTEXT_PKC )
892  return( CRYPT_OK );
893 
894  /* As a variation of the above, if it's a public-key context then we
895  don't want to persist it to the storage object because public-key
896  contexts a bit of an anomaly, when generating our own keys we always
897  have full private keys and when obtaining public keys from an
898  external source they'll be in the form of certificates so there isn't
899  really much need for persistent raw public keys. At the moment the
900  only time they're used is for the self-test, and potentially
901  polluting the (typically quite limited) crypto hardware storage with
902  unneeded public keys doesn't seem like a good idea */
903  if( contextInfoPtr->flags & CONTEXT_FLAG_ISPUBLICKEY )
904  return( CRYPT_OK );
905 
906  /* It's a PKC context, prepare to persist the key metadata to the
907  underlying PKCS #15 object store */
908  status = getContextDeviceInfo( contextInfoPtr->objectHandle,
909  &iCryptDevice, &hardwareInfo );
910  if( cryptStatusError( status ) )
911  return( status );
912  if( hardwareInfo->iCryptKeyset == CRYPT_ERROR )
913  {
914  krnlReleaseObject( iCryptDevice );
915  return( CRYPT_ERROR_NOTINITED );
916  }
917 
918  /* Since this is a dummy context that contains no actual keying
919  information (the key data is held in hardware) we set it as
920  KEYMGMT_ITEM_KEYMETADATA */
921  setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, NULL, 0,
923  setkeyInfo.cryptHandle = contextInfoPtr->objectHandle;
924  status = krnlSendMessage( hardwareInfo->iCryptKeyset,
925  IMESSAGE_KEY_SETKEY, &setkeyInfo,
927  krnlReleaseObject( iCryptDevice );
928 
929  return( status );
930  }
931 
932 /* Many hardware devices have no native public/private key generation
933  support or can only generate something like the DLP x value, which is
934  just a raw string of random bits, but can't generate a full set of
935  public/private key parameters since these require complex bignum
936  operations not supported by the underlying cryptologic. To handle this
937  we provide supplementary software support routines that generate the
938  key parameters using native contexts and bignum code and then pass them
939  back to the crypto HAL to load into the cryptlogic */
940 
941 static int generateKeyComponents( CONTEXT_INFO *staticContextInfo,
942  PKC_INFO *contextData,
943  const CAPABILITY_INFO *capabilityInfoPtr,
944  const int keySizeBits )
945  {
946  int status;
947 
948  assert( isWritePtr( staticContextInfo, sizeof( CONTEXT_INFO ) ) );
949  assert( isWritePtr( contextData, sizeof( PKC_INFO ) ) );
950  assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );
951 
952  REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \
953  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
954 
955  /* Initialise a static context to generate the key into */
956  status = staticInitContext( staticContextInfo, CONTEXT_PKC,
957  capabilityInfoPtr, contextData,
958  sizeof( PKC_INFO ), NULL );
959  if( cryptStatusError( status ) )
960  return( status );
961 
962  /* Generate a key into the static context */
963  status = capabilityInfoPtr->generateKeyFunction( staticContextInfo,
964  keySizeBits );
965  if( cryptStatusError( status ) )
966  {
967  staticDestroyContext( staticContextInfo );
968  return( status );
969  }
970 
971  return( CRYPT_OK );
972  }
973 
974 static int rsaGenerateComponents( CRYPT_PKCINFO_RSA *rsaKeyInfo,
975  const int keySizeBits )
976  {
977  CONTEXT_INFO staticContextInfo;
978  PKC_INFO contextData, *pkcInfo = &contextData;
979  int status;
980 
981  assert( isWritePtr( rsaKeyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) );
982 
983  REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \
984  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
985 
986  /* Clear return value */
987  cryptInitComponents( rsaKeyInfo, FALSE );
988 
989  /* Generate the key components */
990  status = generateKeyComponents( &staticContextInfo, &contextData,
991  getRSACapability(), keySizeBits );
992  if( cryptStatusError( status ) )
993  return( status );
994 
995  /* Extract the newly-generated key components for the caller to use */
996  BN_bn2bin( &pkcInfo->rsaParam_n, rsaKeyInfo->n );
997  rsaKeyInfo->nLen = BN_num_bits( &pkcInfo->rsaParam_n );
998  BN_bn2bin( &pkcInfo->rsaParam_e, rsaKeyInfo->e );
999  rsaKeyInfo->eLen = BN_num_bits( &pkcInfo->rsaParam_e );
1000  BN_bn2bin( &pkcInfo->rsaParam_p, rsaKeyInfo->p );
1001  rsaKeyInfo->pLen = BN_num_bits( &pkcInfo->rsaParam_p );
1002  BN_bn2bin( &pkcInfo->rsaParam_q, rsaKeyInfo->q );
1003  rsaKeyInfo->qLen = BN_num_bits( &pkcInfo->rsaParam_q );
1004  BN_bn2bin( &pkcInfo->rsaParam_exponent1, rsaKeyInfo->e1 );
1005  rsaKeyInfo->e1Len = BN_num_bits( &pkcInfo->rsaParam_exponent1 );
1006  BN_bn2bin( &pkcInfo->rsaParam_exponent2, rsaKeyInfo->e2 );
1007  rsaKeyInfo->e2Len = BN_num_bits( &pkcInfo->rsaParam_exponent2 );
1008  BN_bn2bin( &pkcInfo->rsaParam_u, rsaKeyInfo->u );
1009  rsaKeyInfo->uLen = BN_num_bits( &pkcInfo->rsaParam_u );
1010  staticDestroyContext( &staticContextInfo );
1011 
1012  return( status );
1013  }
1014 
1015 #if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL )
1016 
1017 static int dlpGenerateComponents( CRYPT_PKCINFO_DLP *dlpKeyInfo,
1018  const int keySizeBits,
1019  const CRYPT_ALGO_TYPE cryptAlgo )
1020  {
1021  CONTEXT_INFO staticContextInfo;
1022  PKC_INFO contextData, *pkcInfo = &contextData;
1023  int status;
1024 
1025  assert( isWritePtr( dlpKeyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) );
1026 
1027  REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \
1028  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
1029  REQUIRES( cryptAlgo == CRYPT_ALGO_DH || \
1030  cryptAlgo == CRYPT_ALGO_DSA || \
1031  cryptAlgo == CRYPT_ALGO_ELGAMAL );
1032 
1033  /* Clear return value */
1034  cryptInitComponents( dlpKeyInfo, FALSE );
1035 
1036  /* Generate the key components */
1037  switch( cryptAlgo )
1038  {
1039 #ifdef USE_DH
1040  case CRYPT_ALGO_DH:
1041  status = generateKeyComponents( &staticContextInfo, &contextData,
1042  getDHCapability(), keySizeBits );
1043  break;
1044 #endif /* USE_DH */
1045 
1046 #ifdef USE_DSA
1047  case CRYPT_ALGO_DSA:
1048  status = generateKeyComponents( &staticContextInfo, &contextData,
1049  getDSACapability(), keySizeBits );
1050  break;
1051 #endif /* USE_DSA */
1052 
1053 #ifdef USE_ELGAMAL
1054  case CRYPT_ALGO_ELGAMAL:
1055  status = generateKeyComponents( &staticContextInfo, &contextData,
1056  getElgamalCapability(), keySizeBits );
1057  break;
1058 #endif /* USE_ELGAMAL */
1059 
1060  default:
1061  retIntError();
1062  }
1063  if( cryptStatusError( status ) )
1064  return( status );
1065 
1066  /* Extract the newly-generated key components for the caller to use */
1067  BN_bn2bin( &pkcInfo->dlpParam_p, dlpKeyInfo->p );
1068  dlpKeyInfo->pLen = BN_num_bits( &pkcInfo->dlpParam_p );
1069  BN_bn2bin( &pkcInfo->dlpParam_g, dlpKeyInfo->g );
1070  dlpKeyInfo->gLen = BN_num_bits( &pkcInfo->dlpParam_g );
1071  BN_bn2bin( &pkcInfo->dlpParam_q, dlpKeyInfo->q );
1072  dlpKeyInfo->qLen = BN_num_bits( &pkcInfo->dlpParam_q );
1073  BN_bn2bin( &pkcInfo->dlpParam_y, dlpKeyInfo->y );
1074  dlpKeyInfo->yLen = BN_num_bits( &pkcInfo->dlpParam_y );
1075  BN_bn2bin( &pkcInfo->dlpParam_x, dlpKeyInfo->x );
1076  dlpKeyInfo->xLen = BN_num_bits( &pkcInfo->dlpParam_x );
1077  staticDestroyContext( &staticContextInfo );
1078 
1079  return( status );
1080  }
1081 #endif /* USE_DH || USE_DSA || USE_ELGAMAL */
1082 
1083 int generatePKCcomponents( CONTEXT_INFO *contextInfoPtr,
1084  void *keyInfo, const int keySizeBits )
1085  {
1086  const CRYPT_ALGO_TYPE cryptAlgo = \
1087  contextInfoPtr->capabilityInfo->cryptAlgo;
1088  int status;
1089 
1090  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1091 
1092  REQUIRES( keyInfo != NULL );
1093  REQUIRES( cryptAlgo == CRYPT_ALGO_DH || \
1094  cryptAlgo == CRYPT_ALGO_RSA || \
1095  cryptAlgo == CRYPT_ALGO_DSA || \
1096  cryptAlgo == CRYPT_ALGO_ELGAMAL );
1097  REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \
1098  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
1099 
1100  switch( cryptAlgo )
1101  {
1102  case CRYPT_ALGO_RSA:
1103  status = rsaGenerateComponents( keyInfo, keySizeBits );
1104  break;
1105 
1106 #if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL )
1107  case CRYPT_ALGO_DH:
1108  case CRYPT_ALGO_DSA:
1109  case CRYPT_ALGO_ELGAMAL:
1110  status = dlpGenerateComponents( keyInfo, keySizeBits, cryptAlgo );
1111  break;
1112 #endif /* USE_DH || USE_DSA || USE_ELGAMAL */
1113 
1114  default:
1115  return( CRYPT_ERROR_NOTAVAIL );
1116  }
1117  if( cryptStatusError( status ) )
1118  return( status );
1119 
1120  /* Send the public-key data (needed for certificates and the like) to
1121  the context */
1122  return( setPKCinfo( contextInfoPtr, cryptAlgo, keyInfo ) );
1123  }
1124 
1125 /* Send public-key data to the context for use with certificate objects */
1126 
1127 int setPKCinfo( CONTEXT_INFO *contextInfoPtr,
1128  const CRYPT_ALGO_TYPE cryptAlgo, const void *keyInfo )
1129  {
1130  BYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 4 ) + 8 ];
1132  int keyDataSize, status;
1133 
1134  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1135  assert( ( cryptAlgo == CRYPT_ALGO_RSA && \
1136  isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) ) || \
1137  ( cryptAlgo != CRYPT_ALGO_RSA && \
1138  isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) ) );
1139 
1140  REQUIRES( cryptAlgo == CRYPT_ALGO_DH || \
1141  cryptAlgo == CRYPT_ALGO_RSA || \
1142  cryptAlgo == CRYPT_ALGO_DSA || \
1143  cryptAlgo == CRYPT_ALGO_ELGAMAL );
1144 
1145  /* Send the public key data to the context. We send the keying
1146  information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than
1147  CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context
1148  into the high state. We don't want to do this because we're already
1149  in the middle of processing a message that does this on completion,
1150  all that we're doing here is sending in encoded public key data for
1151  use by objects such as certificates */
1152  switch( cryptAlgo )
1153  {
1154  case CRYPT_ALGO_RSA:
1155  {
1156  const CRYPT_PKCINFO_RSA *rsaKeyInfo = \
1157  ( CRYPT_PKCINFO_RSA * ) keyInfo;
1158 
1159  if( rsaKeyInfo->isPublicKey )
1160  contextInfoPtr->flags |= CONTEXT_FLAG_ISPUBLICKEY;
1161  else
1162  contextInfoPtr->flags |= CONTEXT_FLAG_PERSISTENT;
1163  status = writeFlatPublicKey( keyDataBuffer,
1164  CRYPT_MAX_PKCSIZE * 4,
1165  &keyDataSize, CRYPT_ALGO_RSA,
1166  rsaKeyInfo->n,
1167  bitsToBytes( rsaKeyInfo->nLen ),
1168  rsaKeyInfo->e,
1169  bitsToBytes( rsaKeyInfo->eLen ),
1170  NULL, 0, NULL, 0 );
1171  break;
1172  }
1173 
1174  case CRYPT_ALGO_DH:
1175  case CRYPT_ALGO_DSA:
1176  case CRYPT_ALGO_ELGAMAL:
1177  {
1178  const CRYPT_PKCINFO_DLP *dlpKeyInfo = \
1179  ( CRYPT_PKCINFO_DLP * ) keyInfo;
1180 
1181  if( dlpKeyInfo->isPublicKey )
1182  contextInfoPtr->flags |= CONTEXT_FLAG_ISPUBLICKEY;
1183  else
1184  contextInfoPtr->flags |= CONTEXT_FLAG_PERSISTENT;
1185  status = writeFlatPublicKey( keyDataBuffer,
1186  CRYPT_MAX_PKCSIZE * 4,
1187  &keyDataSize, cryptAlgo,
1188  dlpKeyInfo->p,
1189  bitsToBytes( dlpKeyInfo->pLen ),
1190  dlpKeyInfo->q,
1191  bitsToBytes( dlpKeyInfo->qLen ),
1192  dlpKeyInfo->g,
1193  bitsToBytes( dlpKeyInfo->gLen ),
1194  dlpKeyInfo->y,
1195  bitsToBytes( dlpKeyInfo->yLen ) );
1196  break;
1197  }
1198 
1199  default:
1200  retIntError();
1201  }
1202  if( cryptStatusError( status ) )
1203  return( status );
1204  setMessageData( &msgData, keyDataBuffer, keyDataSize );
1205  return( krnlSendMessage( contextInfoPtr->objectHandle,
1206  IMESSAGE_SETATTRIBUTE_S, &msgData,
1207  CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL ) );
1208  }
1209 
1210 /* Send encryption/MAC keying metadata to the context */
1211 
1212 int setConvInfo( const CRYPT_CONTEXT iCryptContext, const int keySize )
1213  {
1214  assert( isHandleRangeValid( iCryptContext ) );
1215 
1216  REQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_KEYSIZE );
1217 
1218  return( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
1219  ( MESSAGE_CAST ) &keySize,
1220  CRYPT_IATTRIBUTE_KEYSIZE ) );
1221  }
1222 
1223 /* The default cleanup function, which simply frees the context-related data
1224  used by the cryptographic hardware if it's an ephemeral key */
1225 
1226 int cleanupHardwareContext( const CONTEXT_INFO *contextInfoPtr )
1227  {
1228  assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1229 
1230  /* If this is non-ephemeral context data then we leave it intact when
1231  the corresponding context is destroyed, the only way to delete it is
1232  with an explicit deleteItem() */
1233  if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
1234  return( CRYPT_OK );
1235 
1236  /* We have to be careful about deleting the context data since it may
1237  not have been set up yet, for example if we're called due to a
1238  failure in the complete-creation/initialisation step of setting up a
1239  context */
1240  if( contextInfoPtr->deviceObject != CRYPT_ERROR )
1241  hwDeleteItem( contextInfoPtr->deviceObject );
1242 
1243  return( CRYPT_OK );
1244  }
1245 
1246 /****************************************************************************
1247 * *
1248 * Device Access Routines *
1249 * *
1250 ****************************************************************************/
1251 
1252 /* Mechanisms supported by the hardware. These are actually cryptlib native
1253  mechanisms, but not the full set supported by the system device since
1254  functions like private key export aren't available. The list is sorted
1255  in order of frequency of use in order to make lookups a bit faster */
1256 
1258  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },
1259  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },
1260  { MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },
1261  { MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },
1262  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },
1263  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },
1264 #ifdef USE_PGP
1265  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },
1266  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },
1267 #endif /* USE_PGP */
1268  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },
1269  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },
1270  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS5, ( MECHANISM_FUNCTION ) derivePKCS5 },
1271 #if defined( USE_PGP ) || defined( USE_PGPKEYS )
1272  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },
1273 #endif /* USE_PGP || USE_PGPKEYS */
1274 #ifdef USE_SSL
1275  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveSSL },
1276  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveTLS },
1277  { MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },
1278  { MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },
1279 #endif /* USE_SSL */
1280 #ifdef USE_CMP
1281  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },
1282 #endif /* USE_CMP */
1283 #ifdef USE_PKCS12
1284  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },
1285 #endif /* USE_PKCS12 */
1287  };
1288 
1289 /* Set up the function pointers to the device methods */
1290 
1291 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1292 int setDeviceHardware( INOUT DEVICE_INFO *deviceInfo )
1293  {
1294  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
1295 
1296  deviceInfo->initFunction = initFunction;
1297  deviceInfo->shutdownFunction = shutdownFunction;
1298  deviceInfo->controlFunction = controlFunction;
1299  deviceInfo->getItemFunction = getItemFunction;
1300  deviceInfo->setItemFunction = setItemFunction;
1301  deviceInfo->deleteItemFunction = deleteItemFunction;
1302  deviceInfo->getFirstItemFunction = getFirstItemFunction;
1303  deviceInfo->getNextItemFunction = getNextItemFunction;
1304  deviceInfo->getRandomFunction = getRandomFunction;
1305  deviceInfo->capabilityInfoList = capabilityInfoList;
1306  deviceInfo->mechanismFunctions = mechanismFunctions;
1307  deviceInfo->mechanismFunctionCount = \
1308  FAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );
1309 
1310  return( CRYPT_OK );
1311  }
1312 #endif /* USE_HARDWARE */