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