cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs11.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #11 Routines *
4 * Copyright Peter Gutmann 1998-2005 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "context.h"
11  #include "device.h"
12  #include "pkcs11_api.h"
13  #include "dev_mech.h"
14  #include "asn1.h"
15 #else
16  #include "crypt.h"
17  #include "context/context.h"
18  #include "device/device.h"
19  #include "device/pkcs11_api.h"
20  #include "enc_dec/asn1.h"
21  #include "mechs/dev_mech.h"
22 #endif /* Compiler-specific includes */
23 
24 /* Define the following to generate conventional/MAC keys inside the PKCS
25  #11 device rather than in cryptlib. Note that this imposes a number of
26  restrictions on the use of encryption keys, see the note for
27  cipherGenerateKey() for more details */
28 
29 #define USE_HW_KEYGEN
30 
31 #ifdef USE_PKCS11
32 
33 /* The max. number of drivers we can work with and the max.number of slots
34  per driver */
35 
36 #define MAX_PKCS11_DRIVERS 5
37 #define MAX_PKCS11_SLOTS 16
38 
39 /****************************************************************************
40 * *
41 * Utility Routines *
42 * *
43 ****************************************************************************/
44 
45 /* Map a PKCS #11-specific error to a cryptlib error */
46 
47 CHECK_RETVAL \
48 int pkcs11MapError( const CK_RV errorCode,
49  IN_STATUS const int defaultError )
50  {
51  REQUIRES( cryptStatusError( defaultError ) );
52 
53  switch( ( int ) errorCode )
54  {
55  case CKR_OK:
56  return( CRYPT_OK );
57 
58  case CKR_HOST_MEMORY:
59  case CKR_DEVICE_MEMORY:
60  return( CRYPT_ERROR_MEMORY );
61 
62  case CKR_DEVICE_ERROR:
63  case CKR_DEVICE_REMOVED:
65  return( CRYPT_ERROR_SIGNALLED );
66 
67  case CKR_PIN_INCORRECT:
68  case CKR_PIN_INVALID:
69  case CKR_PIN_LEN_RANGE:
70  case CKR_PIN_EXPIRED:
71  case CKR_PIN_LOCKED:
72  return( CRYPT_ERROR_WRONGKEY );
73 
74  case CKR_DATA_INVALID:
77  return( CRYPT_ERROR_BADDATA );
78 
80  return( CRYPT_ERROR_SIGNATURE );
81 
86  return( CRYPT_ERROR_PERMISSION );
87 
88  case CKR_DATA_LEN_RANGE:
94  return( CRYPT_ERROR_OVERFLOW );
95 
96  case CKR_SESSION_EXISTS:
102  return( CRYPT_ERROR_INITED );
103 
107  return( CRYPT_ERROR_NOTINITED );
108 
109  case CKR_RANDOM_NO_RNG:
110  return( CRYPT_ERROR_RANDOM );
111 
113  return( CRYPT_ERROR_TIMEOUT );
114 
116  return( CRYPT_ERROR_NOTFOUND );
117  }
118 
119  return( defaultError );
120  }
121 
122 /* Extract the time from a PKCS #11 tokenInfo structure */
123 
124 STDC_NONNULL_ARG( ( 1 ) ) \
125 time_t getTokenTime( const CK_TOKEN_INFO *tokenInfo )
126  {
127  STREAM stream;
128  BYTE buffer[ 32 + 8 ];
129  time_t theTime = MIN_TIME_VALUE + 1;
130  int length = DUMMY_INIT, status;
131 
132  assert( isReadPtr( tokenInfo, sizeof( CK_TOKEN_INFO ) ) );
133 
134  /* Convert the token time to an ASN.1 time string that we can read using
135  the standard ASN.1 routines by writing a dummy time value and inserting
136  the token's time string in its place */
137  sMemOpen( &stream, buffer, 32 );
138  status = writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );
139  if( cryptStatusOK( status ) )
140  length = stell( &stream );
141  sMemDisconnect( &stream );
142  if( cryptStatusError( status ) )
143  return( 0 );
144  memcpy( buffer + 2, tokenInfo->utcTime, 14 );
145  sMemConnect( &stream, buffer, length );
146  status = readGeneralizedTime( &stream, &theTime );
147  sMemDisconnect( &stream );
148 
149  return( ( cryptStatusOK( status ) ) ? theTime : 0 );
150  }
151 
152 /* Get access to the PKCS #11 device associated with a context */
153 
154 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \
155 int getContextDeviceInfo( IN_HANDLE const CRYPT_HANDLE iCryptContext,
156  OUT_HANDLE_OPT CRYPT_DEVICE *iCryptDevice,
157  OUT_OPT_PTR PKCS11_INFO **pkcs11InfoPtrPtr )
158  {
159  CRYPT_DEVICE iLocalDevice;
160  DEVICE_INFO *deviceInfo;
161  int cryptStatus;
162 
163  assert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) );
164  assert( isWritePtr( pkcs11InfoPtrPtr, sizeof( PKCS11_INFO * ) ) );
165 
166  REQUIRES( isHandleRangeValid( iCryptContext ) );
167 
168  /* Clear return values */
169  *iCryptDevice = CRYPT_ERROR;
170  *pkcs11InfoPtrPtr = NULL;
171 
172  /* Get the the device associated with this context */
173  cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT,
174  &iLocalDevice, OBJECT_TYPE_DEVICE );
175  if( cryptStatusError( cryptStatus ) )
176  return( cryptStatus );
177 
178  /* Get the PKCS #11 information from the device information */
179  cryptStatus = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE,
180  ( void ** ) &deviceInfo,
182  if( cryptStatusError( cryptStatus ) )
183  return( cryptStatus );
184  *iCryptDevice = iLocalDevice;
185  *pkcs11InfoPtrPtr = deviceInfo->devicePKCS11;
186 
187  return( CRYPT_OK );
188  }
189 
190 /* Create and try and use a dummy object to check for various PKCS #11
191  driver bugs */
192 
194 static int checkDriverBugs( const PKCS11_INFO *pkcs11Info )
195  {
196  static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
197  const CK_KEY_TYPE type = CKK_DES;
198  static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
199  const CK_ATTRIBUTE keyTemplate[] = {
200  { CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
201  { CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
202  { CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
203  { CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
204  { CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
205  { CKA_VALUE, "12345678", 8 } /* Dummy key value */
206  };
207  const CK_MECHANISM mechanism = { CKM_DES_ECB, NULL, 0 };
208  CK_OBJECT_HANDLE hObject;
209  CK_RV status;
210 
211  assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
212 
213  /* Try and create the sort of object that'd normally require a login.
214  This can fail for reasons other than driver bugs (for example DES
215  isn't supported for this token type) so we only check for the
216  specific error code returned by a login bug */
217  status = C_CreateObject( pkcs11Info->hSession,
218  ( CK_ATTRIBUTE_PTR ) keyTemplate, 6, &hObject );
219  if( status == CKR_USER_NOT_LOGGED_IN )
220  {
221  DEBUG_DIAG(( "PKCS #11 driver bug detected, attempt to log in to "
222  "the device apparently succeeded but logged-on "
223  "operation failed with CKR_USER_NOT_LOGGED_IN" ));
224  assert( DEBUG_WARN );
225  return( CRYPT_ERROR_NOTINITED );
226  }
227  ENSURES( hObject != CK_OBJECT_NONE );
228 
229  /* Try and use the object to encrypt data (or at least call the pre-
230  encrypt call, which should be enough to shake out most bugs) */
231  status = C_EncryptInit( pkcs11Info->hSession,
232  ( CK_MECHANISM_PTR ) &mechanism, hObject );
233  C_DestroyObject( pkcs11Info->hSession, hObject );
234  if( status != CKR_OK )
235  {
236  DEBUG_DIAG(( "PKCS #11 driver bug detected, attempt to use object "
237  "in logged-in device failed, this can happen when "
238  "using C_InitToken() rather than the proprietary "
239  "vendor-supplied utility to initialise the device" ));
240  assert( DEBUG_WARN );
241  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
242  }
243 
244  return( CRYPT_OK );
245  }
246 
247 /****************************************************************************
248 * *
249 * Device Init/Shutdown/Device Control Routines *
250 * *
251 ****************************************************************************/
252 
253 /* Handle device control functions */
254 
256 static int controlFunction( INOUT DEVICE_INFO *deviceInfo,
258  IN_BUFFER_OPT( dataLength ) void *data,
259  IN_LENGTH_SHORT_Z const int dataLength,
261  {
262  CK_RV status;
263  PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
264 
265  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
266  assert( isAttribute( type ) || isInternalAttribute( type ) );
267 
268  /* Handle token present/active checks */
269  if( type == CRYPT_DEVINFO_LOGGEDIN )
270  {
271  CK_TOKEN_INFO tokenInfo;
272  CK_SLOT_INFO slotInfo;
273 
274  /* Check whether the user is still logged in. This is rather
275  problematic because some devices can't detect a token removal,
276  and if they do they often can't report it to the driver. It's
277  also possible in some devices to remove the token and re-insert
278  it later without that being regarded as logging out (or you can
279  remove the smart card and insert your frequent flyer card and
280  it's still regarded as a card present). In addition if the
281  reader supports its own authentication mechanisms (even if it
282  forces a logout if the token is removed) it's possible for the
283  user to reinsert the token and reauthenticate themselves and it
284  appears as if they never logged out. In fact the only totally
285  foolproof way to detect a token removal/change is to try and use
286  the token to perform a crypto operation, which is a rather
287  suboptimal detection mechanism.
288 
289  Because of this, the best that we can do here is check the token-
290  present flag and report a token-changed error if it's not set.
291  In addition since some devices only do a minimal check with
292  C_GetSlotInfo() (e.g. checking whether a microswitch is held
293  open by something in the slot, see above) we first call
294  C_GetTokenInfo(), which has a greater chance of actually trying
295  to access the token, before we call C_GetSlotInfo().
296 
297  If there's a problem reported, we don't perform an implicit
298  shutdown since the user may choose to re-authenticate to the
299  device or perform some other action that we have no control over
300  in response to the token-removed notification */
301  status = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );
302  if( status != CKR_OK )
303  return( pkcs11MapError( status, CRYPT_ERROR_SIGNALLED ) );
304  status = C_GetSlotInfo( pkcs11Info->slotID, &slotInfo );
305  if( status != CKR_OK )
306  return( pkcs11MapError( status, CRYPT_ERROR_SIGNALLED ) );
307  if( !( slotInfo.flags & CKF_TOKEN_PRESENT ) )
308  return( CRYPT_ERROR_SIGNALLED );
309 
310  return( CRYPT_OK );
311  }
312 
313  /* Handle user authorisation */
314  if( type == CRYPT_DEVINFO_AUTHENT_USER || \
316  {
317  /* Make sure that the PIN is within range */
318  if( dataLength < pkcs11Info->minPinSize || \
319  dataLength > pkcs11Info->maxPinSize )
320  return( CRYPT_ARGERROR_NUM1 );
321 
322  /* If the user is already logged in, log them out before we try
323  logging in with a new authentication value */
324  if( deviceInfo->flags & DEVICE_LOGGEDIN )
325  {
326  C_Logout( pkcs11Info->hSession );
327  deviceInfo->flags &= ~DEVICE_LOGGEDIN;
328  }
329 
330  /* Authenticate the user to the device */
331  status = C_Login( pkcs11Info->hSession,
332  ( type == CRYPT_DEVINFO_AUTHENT_USER ) ? \
333  CKU_USER : CKU_SO, ( CK_CHAR_PTR ) data,
334  ( CK_ULONG ) dataLength );
335  if( status != CKR_OK )
336  {
337  int cryptStatus;
338 
339  /* The check for CKR_USER_ALREADY_LOGGED_IN is logical since we
340  may already be logged in from another session, however
341  several buggy drivers return CKR_USER_ALREADY_LOGGED_IN
342  without actually logging the user in so that all further
343  operations fail with CKR_USER_NOT_LOGGED_IN. To try and
344  detect this, if we get a CKR_USER_ALREADY_LOGGED_IN we try
345  and create the sort of object that's likely to require a
346  login and use that to see whether we're really logged in or
347  not */
348  if( status != CKR_USER_ALREADY_LOGGED_IN )
349  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
350  cryptStatus = checkDriverBugs( pkcs11Info );
351  return( cryptStatusError( cryptStatus ) ? \
352  cryptStatus : CRYPT_ERROR_FAILED );
353  }
354 
355  /* The device is now ready for use */
356  deviceInfo->flags |= DEVICE_LOGGEDIN;
357  return( CRYPT_OK );
358  }
359 
360  /* Handle authorisation value changes. The initialise SO/user PIN
361  functionality is a bit awkward in that it has to fill the gap between
362  C_InitToken() (which usually sets the SSO PIN but may also take an
363  initialisation PIN and leave the token in a state where the only valid
364  operation is to set the SSO PIN) and C_SetPIN() (which can only set the
365  SSO PIN for the SSO or the user PIN for the user). Setting the user
366  PIN by the SSO, which is usually required to perform any useful (non-
367  administrative) function with the token, requires the special-case
368  C_InitPIN(). In addition we can't speculatively set the user PIN to
369  be the same as the SSO PIN (which would be useful because in most
370  cases the user *is* the SSO, thus ensuring that the device behaves as
371  expected when the user isn't even aware that there are SSO and user
372  roles) because devices that implement an FSM for initialisation will
373  move into an undesired state once the SSO -> user change is triggered.
374 
375  The FSM for initialisation on devices that perform a multi-stage
376  bootstrap and require all of the various intialisation functions to
377  be used one after the other (e.g. Fortezza) is:
378 
379  uninitialised/zeroised
380  v
381  C_InitToken (enter init or SSO PIN)
382  v
383  initialised
384  v
385  C_SetPIN (change init PIN -> SSO PIN)
386  v
387  SSO initialised
388  v
389  C_InitPIN (set user PIN)
390  v
391  user initialised
392  v
393  C_Logout
394  C_Login (move from SO -> user state)
395 
396  The final logout/login is only needed with some tokens, in others
397  the move to user state is automatic once the user PIN is set by the
398  SO */
400  {
401  /* Make sure that the PIN is within range */
402  if( dataLength < pkcs11Info->minPinSize || \
403  dataLength > pkcs11Info->maxPinSize )
404  return( CRYPT_ARGERROR_NUM1 );
405 
406  /* Make sure that there's an SSO PIN present from a previous device
407  initialisation */
408  if( pkcs11Info->defaultSSOPinLen <= 0 )
409  {
412  return( CRYPT_ERROR_NOTINITED );
413  }
414 
415  /* Change the SSO PIN from the initialisation PIN. Once we've done
416  this we clear the initial SSO PIN, since it's no longer valid in
417  the new state */
418  status = C_SetPIN( pkcs11Info->hSession, pkcs11Info->defaultSSOPin,
419  pkcs11Info->defaultSSOPinLen,
420  ( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );
421  zeroise( pkcs11Info->defaultSSOPin, CRYPT_MAX_TEXTSIZE );
422  pkcs11Info->defaultSSOPinLen = 0;
423  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
424  }
425  if( type == CRYPT_DEVINFO_SET_AUTHENT_USER )
426  {
427  /* Make sure that the PIN is within range */
428  if( dataLength < pkcs11Info->minPinSize || \
429  dataLength > pkcs11Info->maxPinSize )
430  return( CRYPT_ARGERROR_NUM1 );
431 
432  status = C_InitPIN( pkcs11Info->hSession, ( CK_CHAR_PTR ) data,
433  ( CK_ULONG ) dataLength );
434  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
435  }
436 
437  /* Handle initialisation and zeroisation */
438  if( type == CRYPT_DEVINFO_INITIALISE || \
439  type == CRYPT_DEVINFO_ZEROISE )
440  {
441  CK_SESSION_HANDLE hSession;
442  CK_CHAR label[ 32 + 8 ];
443  int cryptStatus;
444 
445  /* Make sure that the PIN is within range */
446  if( dataLength < pkcs11Info->minPinSize || \
447  dataLength > pkcs11Info->maxPinSize )
448  return( CRYPT_ARGERROR_NUM1 );
449 
450  /* If there's a session active with the device, log out and terminate
451  the session, since the token initialisation will reset this */
452  if( pkcs11Info->hSession != CK_OBJECT_NONE )
453  {
454  C_Logout( pkcs11Info->hSession );
455  C_CloseSession( pkcs11Info->hSession );
456  pkcs11Info->hSession = CK_OBJECT_NONE;
457  }
458 
459  /* Initialise/clear the device, setting the initial SSO PIN */
460  memset( label, ' ', 32 );
461  status = C_InitToken( pkcs11Info->slotID,
462  ( CK_CHAR_PTR ) data,
463  ( CK_ULONG ) dataLength, label );
464  if( status != CKR_OK )
465  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
466 
467  /* Reopen the session with the device */
468  status = C_OpenSession( pkcs11Info->slotID,
470  NULL_PTR, NULL_PTR, &hSession );
471  if( status != CKR_OK )
472  return( pkcs11MapError( status, CRYPT_ERROR_OPEN ) );
473  ENSURES( hSession != CK_OBJECT_NONE );
474  pkcs11Info->hSession = hSession;
475 
476  /* If it's a straight zeroise, we're done */
477  if( type == CRYPT_DEVINFO_ZEROISE )
478  return( CRYPT_OK );
479 
480  /* We're initialising it, log in as supervisor. In theory we could
481  also set the initial user PIN to the same as the SSO PIN at this
482  point because the user usually won't be aware of the presence of
483  an SSO role or the need to set a PIN for it, but this can run into
484  problems with tokens that only allow the user PIN to be modified
485  by the SSO after they've set it for the first time, so if the user
486  *is* aware of the existence of an SSO role then once they log in
487  as SSO they can no longer set the user PIN */
488  status = C_Login( pkcs11Info->hSession, CKU_SO,
489  ( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );
490  if( status != CKR_OK )
491  {
492  C_Logout( pkcs11Info->hSession );
493  C_CloseSession( pkcs11Info->hSession );
494  pkcs11Info->hSession = CK_OBJECT_NONE;
495  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
496  }
497 
498  /* Remember the default SSO PIN for use with a future C_SetPIN() */
499  memcpy( pkcs11Info->defaultSSOPin, data, dataLength );
500  pkcs11Info->defaultSSOPinLen = dataLength;
501 
502  /* A number of PKCS #11 devices can't actually be initialised
503  through C_InitToken() but require a vendor-supplied proprietary
504  application to do this, apparently succeeding with C_InitToken()
505  but then failing in various strange and unpredictable ways later
506  on. We try and detect this situation here by creating a dummy
507  object in the device and trying to use it */
508  cryptStatus = checkDriverBugs( pkcs11Info );
509  if( cryptStatusError( cryptStatus ) )
510  return( cryptStatus );
511 
512  /* We're logged in and ready to go */
513  deviceInfo->flags |= DEVICE_LOGGEDIN;
514  return( CRYPT_OK );
515  }
516 
517  /* Handle high-reliability time */
518  if( type == CRYPT_IATTRIBUTE_TIME )
519  {
520  CK_TOKEN_INFO tokenInfo;
521  time_t *timePtr = ( time_t * ) data, theTime;
522 
523  /* Get the token's time, returned as part of the token information
524  structure */
525  status = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );
526  if( status != CKR_OK )
527  return( pkcs11MapError( status, CRYPT_ERROR_SIGNALLED ) );
528  if( ( theTime = getTokenTime( &tokenInfo ) ) <= MIN_TIME_VALUE )
529  return( CRYPT_ERROR_NOTAVAIL );
530  *timePtr = theTime;
531  return( CRYPT_OK );
532  }
533 
534  retIntError();
535  }
536 
537 /****************************************************************************
538 * *
539 * Capability Interface Routines *
540 * *
541 ****************************************************************************/
542 
543 /* Encrypt, decrypt */
544 
545 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
546 static int genericEncrypt( const PKCS11_INFO *pkcs11Info,
548  const CK_MECHANISM *pMechanism,
549  INOUT_BUFFER_FIXED( length ) void *buffer,
550  IN_LENGTH const int length,
551  IN_LENGTH const int outLength )
552  {
553  CK_ULONG resultLen = outLength;
554  CK_RV status;
555 
556  assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
557  assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
558  assert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );
559  assert( isWritePtr( buffer, length ) );
560 
561  REQUIRES( length > 0 && length < MAX_INTLENGTH );
562  REQUIRES( length == outLength );
563 
564  status = C_EncryptInit( pkcs11Info->hSession,
565  ( CK_MECHANISM_PTR ) pMechanism,
566  contextInfoPtr->deviceObject );
567  if( status == CKR_OK )
568  status = C_Encrypt( pkcs11Info->hSession, buffer, length,
569  buffer, &resultLen );
570  if( status != CKR_OK )
571  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
572  return( CRYPT_OK );
573  }
574 
575 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
576 static int genericDecrypt( const PKCS11_INFO *pkcs11Info,
577  const CONTEXT_INFO *contextInfoPtr,
578  const CK_MECHANISM *pMechanism,
579  INOUT_BUFFER_FIXED( length ) void *buffer,
580  IN_LENGTH const int length )
581  {
582  CK_ULONG resultLen = length;
583  CK_RV status;
584 
585  assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
586  assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
587  assert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );
588  assert( isWritePtr( buffer, length ) );
589 
590  REQUIRES( length > 0 && length < MAX_INTLENGTH );
591 
592  status = C_DecryptInit( pkcs11Info->hSession,
593  ( CK_MECHANISM_PTR ) pMechanism,
594  contextInfoPtr->deviceObject );
595  if( status == CKR_OK )
596  status = C_Decrypt( pkcs11Info->hSession, buffer, length,
597  buffer, &resultLen );
598  if( status != CKR_OK )
599  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
600  return( CRYPT_OK );
601  }
602 
603 /* Clean up the object associated with a context */
604 
605 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
606 int genericEndFunction( const CONTEXT_INFO *contextInfoPtr )
607  {
608  CRYPT_DEVICE iCryptDevice;
609  PKCS11_INFO *pkcs11Info;
610  int cryptStatus;
611 
612  assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
613 
614  /* Since the device object that corresponds to the cryptlib object is
615  created on-demand, it may not exist yet if the action that triggers
616  the on-demand creation hasn't been taken yet. If no device object
617  exists, we're done */
618  if( contextInfoPtr->deviceObject == CRYPT_ERROR )
619  return( CRYPT_OK );
620 
621  /* Get the information for the device associated with this context */
622  cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
623  &iCryptDevice, &pkcs11Info );
624  if( cryptStatusError( cryptStatus ) )
625  return( cryptStatus );
626 
627  /* If we're deleting an object that's in the middle of a multi-stage
628  operation, record the fact that the operation has now ended. We
629  have to perform this tracking explicitly since PKCS #11 only allows
630  one multi-stage operation per session */
631  if( pkcs11Info->hActiveSignObject == contextInfoPtr->deviceObject )
632  pkcs11Info->hActiveSignObject = CK_OBJECT_NONE;
633 
634  /* If this is a persistent object, we can't destroy it. This is a bit
635  problematic since PKCS #11 doesn't differentiate between releasing
636  an object handle and destroying (deleting) it, which means that
637  repeatedly instantiating a persistent object (via getItemFunction())
638  and then destroying it leaks a PKCS #11 handle each time.
639  Unfortunately there's nothing that we can do about this since the
640  problem lies at the PKCS #11 level */
641  if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
642  {
643  krnlReleaseObject( iCryptDevice );
644  return( CRYPT_OK );
645  }
646 
647  /* Destroy the object */
648  C_DestroyObject( pkcs11Info->hSession, contextInfoPtr->deviceObject );
649  if( contextInfoPtr->altDeviceObject != CK_OBJECT_NONE )
650  {
651  C_DestroyObject( pkcs11Info->hSession,
652  contextInfoPtr->altDeviceObject );
653  }
654  krnlReleaseObject( iCryptDevice );
655 
656  return( CRYPT_OK );
657  }
658 
659 /****************************************************************************
660 * *
661 * Conventional Crypto/MAC Key Load Functions *
662 * *
663 ****************************************************************************/
664 
665 /* Get a PKCS #11 mechanism corresponding to a cryptlib algorithm and
666  optional mode */
667 
668 typedef enum { MECH_NONE, MECH_CONV, MECH_MAC, MECH_CONV_KEYGEN,
669  MECH_MAC_KEYGEN, MECH_LAST } GETMECH_TYPE;
670 
671 static CK_MECHANISM_TYPE getMechanism( const GETMECH_TYPE mechType,
674 
675 /* Set up a key template and context information in preparation for creating
676  a device object */
677 
678 STDC_NONNULL_ARG( ( 1 ) ) \
679 static void adjustKeyParity( INOUT_BUFFER_FIXED( length ) BYTE *key,
680  IN_LENGTH_SHORT const int length )
681  {
682  int i;
683 
684  assert( isWritePtr( key, length ) );
685 
686  REQUIRES_V( length > 0 && length < MAX_INTLENGTH_SHORT );
687 
688  /* Adjust a key to have odd parity, needed for DES keys */
689  for( i = 0; i < length; i++ )
690  {
691  int ch = byteToInt( key[ i ] );
692 
693  ch = ( ch & 0x55 ) + ( ( ch >> 1 ) & 0x55 );
694  ch = ( ch & 0x33 ) + ( ( ch >> 2 ) & 0x33 );
695  if( !( ( ch + ( ch >> 4 ) ) & 0x01 ) )
696  key[ i ] ^= 1;
697  }
698  }
699 
700 /* Load a key into a device object */
701 
702 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
703 static int initKey( INOUT CONTEXT_INFO *contextInfoPtr,
704  INOUT_ARRAY( templateCount ) \
705  CK_ATTRIBUTE *keyTemplate,
706  IN_RANGE( 4, 10 ) const int templateCount,
707  IN_BUFFER( keyLength ) const void *key,
708  IN_LENGTH_SHORT const int keyLength )
709  {
710  CRYPT_DEVICE iCryptDevice;
711  const CRYPT_ALGO_TYPE cryptAlgo = \
712  contextInfoPtr->capabilityInfo->cryptAlgo;
713  PKCS11_INFO *pkcs11Info;
714  CK_OBJECT_HANDLE hObject;
715  CK_RV status;
716  BYTE *contextKeyPtr;
717  int *contextKeyLenPtr;
718  int keySize = \
719  ( cryptAlgo == CRYPT_ALGO_DES || cryptAlgo == CRYPT_ALGO_3DES ) ? \
720  contextInfoPtr->capabilityInfo->keySize : keyLength;
721  int cryptStatus;
722 
723  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
724  assert( isWritePtr( keyTemplate, \
725  templateCount * sizeof( CK_ATTRIBUTE ) ) );
726  assert( isReadPtr( key, keyLength ) );
727 
728  REQUIRES( templateCount >= 4 && templateCount <= 10 );
729  REQUIRES( keyLength > 0 && keyLength < MAX_INTLENGTH_SHORT );
730 
731  /* Get the information for the device associated with this context */
732  cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
733  &iCryptDevice, &pkcs11Info );
734  if( cryptStatusError( cryptStatus ) )
735  return( cryptStatus );
736 
737  /* Set up pointers to the appropriate object sub-type data */
738  if( contextInfoPtr->type == CONTEXT_CONV )
739  {
740  contextKeyPtr = contextInfoPtr->ctxConv->userKey;
741  contextKeyLenPtr = &contextInfoPtr->ctxConv->userKeyLength;
742  }
743  else
744  {
745  REQUIRES( contextInfoPtr->type == CONTEXT_MAC );
746 
747  contextKeyPtr = contextInfoPtr->ctxMAC->userKey;
748  contextKeyLenPtr = &contextInfoPtr->ctxMAC->userKeyLength;
749  }
750 
751  /* Copy the key to internal storage */
752  if( contextKeyPtr != key )
753  memcpy( contextKeyPtr, key, keyLength );
754  *contextKeyLenPtr = keyLength;
755 
756  /* Special-case handling for 2-key vs.3-key 3DES */
757  if( cryptAlgo == CRYPT_ALGO_3DES )
758  {
759  /* If the supplied key contains only two DES keys, adjust the key to
760  make it the equivalent of 3-key 3DES. In addition since the
761  nominal keysize is for 2-key 3DES, we have to make the actual
762  size the maximum size, corresponding to 3-key 3DES */
763  if( keyLength <= bitsToBytes( 64 * 2 ) )
764  memcpy( contextKeyPtr + bitsToBytes( 64 * 2 ),
765  contextKeyPtr, bitsToBytes( 64 ) );
766  keySize = contextInfoPtr->capabilityInfo->maxKeySize;
767  }
768 
769  /* If we're using DES we have to adjust the key parity because the spec
770  says so, almost all implementations do this anyway but there's always
771  the odd one out that we have to cater for */
772  if( cryptAlgo == CRYPT_ALGO_DES || cryptAlgo == CRYPT_ALGO_3DES )
773  adjustKeyParity( contextKeyPtr, keySize );
774 
775  /* Set up the key values. Since the key passed in by the user may be
776  smaller than the keysize required by algorithms that use fixed-size
777  keys, we use the (optionally) zero-padded key of the correct length
778  held in the context rather than the variable-length user-supplied
779  one */
780  REQUIRES( keyTemplate[ 7 ].type == CKA_VALUE );
781  keyTemplate[ 7 ].pValue = contextKeyPtr;
782  keyTemplate[ 7 ].ulValueLen = keySize;
783 
784  /* Load the key into the token */
785  status = C_CreateObject( pkcs11Info->hSession, keyTemplate,
786  templateCount, &hObject );
787  cryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );
788  if( cryptStatusOK( cryptStatus ) )
789  {
790  ENSURES( hObject != CK_OBJECT_NONE );
791 
792  contextInfoPtr->deviceObject = hObject;
793  }
794  else
795  {
796  zeroise( contextInfoPtr->ctxConv->userKey, keyLength );
797  contextInfoPtr->ctxConv->userKeyLength = 0;
798  }
799  zeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );
800  krnlReleaseObject( iCryptDevice );
801  return( cryptStatus );
802  }
803 
804 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
805 static int cipherInitKey( INOUT CONTEXT_INFO *contextInfoPtr,
806  IN_BUFFER( keyLength ) const void *key,
807  IN_LENGTH_SHORT const int keyLength )
808  {
809  static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
810  static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
811  const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
812  CK_ATTRIBUTE keyTemplate[] = {
813  /* General-purpose fields */
814  { CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
815  { CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
816  { CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
817  { CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
818  { CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
819  { CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
820  { CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
821  { CKA_VALUE, NULL_PTR, 0 },
822  /* Persistent-object only fields */
823  { CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
824  };
825  const int templateCount = \
826  ( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;
827 
828  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
829  assert( isReadPtr( key, keyLength ) );
830 
831  REQUIRES( keyLength > 0 && keyLength < MAX_INTLENGTH_SHORT );
832 
833  /* If this is meant to be a persistent object, modify the template to
834  make it a persistent token object and adjust the template entry count
835  to include the object label */
836  if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
837  keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;
838 
839  return( initKey( contextInfoPtr, keyTemplate, templateCount,
840  key, keyLength ) );
841  }
842 
843 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
844 static int hmacInitKey( INOUT CONTEXT_INFO *contextInfoPtr,
845  IN_BUFFER( keyLength ) const void *key,
846  IN_LENGTH_SHORT const int keyLength )
847  {
848  static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
849  static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
850  const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
851  CK_ATTRIBUTE keyTemplate[] = {
852  /* General-purpose fields */
853  { CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
854  { CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
855  { CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
856  { CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
857  { CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
858  { CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
859  { CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
860  { CKA_VALUE, NULL_PTR, 0 },
861  /* Persistent-object only fields */
862  { CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
863  };
864  const int templateCount = \
865  ( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;
866 
867  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
868  assert( isReadPtr( key, keyLength ) );
869 
870  REQUIRES( keyLength > 0 && keyLength < MAX_INTLENGTH_SHORT );
871 
872  /* If this is meant to be a persistent object, modify the template to
873  make it a persistent token object and adjust the template entry count
874  to include the object label */
875  if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
876  keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;
877 
878  return( initKey( contextInfoPtr, keyTemplate, templateCount,
879  key, keyLength ) );
880  }
881 
882 /* Generate a key into a device object. Normally we generate keys inside
883  cryptlib and load them into the device object (so a keygen becomes a
884  keygen inside cryptlib followed by a cipherInitKey()) in order to make
885  sure that the key data is accessible from the context. If we didn't do
886  this, the user would have to be very careful to perform all key wrap/
887  unwrap operations only via device objects. This is particularly
888  problematic with public-key operations since cryptlib always instantiates
889  public-key objects as cryptlib native objects since they're so much
890  quicker in that form. So for example importing a certificate and then
891  using it to wrap a conventional encryption key that's been generated in
892  a device is impossible because the key to wrap isn't accessible to the
893  public-key context tied to the certificate. Because of this,
894  USE_HW_KEYGEN should be used with great care */
895 
896 #ifdef USE_HW_KEYGEN
897 
898 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
899 static int generateKey( INOUT CONTEXT_INFO *contextInfoPtr,
900  INOUT_ARRAY( templateCount ) \
901  CK_ATTRIBUTE *keyTemplate,
902  IN_RANGE( 4, 10 ) const int templateCount,
903  const BOOLEAN isMAC )
904  {
905  CRYPT_DEVICE iCryptDevice;
906  PKCS11_INFO *pkcs11Info;
907  CK_MECHANISM mechanism = { contextInfoPtr->capabilityInfo->paramKeyGen,
908  NULL_PTR, 0 };
909  CK_OBJECT_HANDLE hObject;
910  CK_RV status;
911  int cryptStatus;
912 
913  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
914  assert( isWritePtr( keyTemplate, \
915  templateCount * sizeof( CK_ATTRIBUTE ) ) );
916 
917  REQUIRES( templateCount >= 4 && templateCount <= 10 );
918 
919  /* Get the information for the device associated with this context */
920  cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
921  &iCryptDevice, &pkcs11Info );
922  if( cryptStatusError( cryptStatus ) )
923  return( cryptStatus );
924 
925  /* Generate the key into the token */
926  status = C_GenerateKey( pkcs11Info->hSession, &mechanism,
927  keyTemplate, templateCount, &hObject );
928  cryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );
929  if( cryptStatusOK( cryptStatus ) )
930  {
931  ENSURES( hObject != CK_OBJECT_NONE );
932 
933  contextInfoPtr->deviceObject = hObject;
934  }
935  zeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );
936  krnlReleaseObject( iCryptDevice );
937  return( cryptStatus );
938  }
939 
941 static int cipherGenerateKey( INOUT CONTEXT_INFO *contextInfoPtr,
944  const int keySizeBits )
945  {
946  static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
947  static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
948  const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
949  const CK_ULONG length = bitsToBytes( keySizeBits );
950  CK_ATTRIBUTE keyTemplate[] = {
951  /* General-purpose fields */
952  { CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
953  { CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
954  { CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
955  { CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
956  { CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
957  { CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
958  { CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
959  { CKA_VALUE_LEN, ( CK_VOID_PTR ) &length, sizeof( CK_ULONG ) },
960  /* Persistent-object only fields */
961  { CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
962  };
963  const int templateCount = \
964  ( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;
965 
966  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
967 
968  REQUIRES( keySizeBits >= bytesToBits( MIN_KEYSIZE ) && \
969  keySizeBits <= bytesToBits( CRYPT_MAX_KEYSIZE ) );
970 
971  /* If this is meant to be a persistent object, modify the template to
972  make it a persistent token object and adjust the template entry count
973  to include the object label */
974  if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
975  keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;
976 
977  return( generateKey( contextInfoPtr, keyTemplate, templateCount, FALSE ) );
978  }
979 
981 static int hmacGenerateKey( INOUT CONTEXT_INFO *contextInfoPtr,
984  const int keySizeBits )
985  {
986  static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
987  static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
988  const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
989  const CK_ULONG length = bitsToBytes( keySizeBits );
990  CK_ATTRIBUTE keyTemplate[] = {
991  /* General-purpose fields */
992  { CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
993  { CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
994  { CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
995  { CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
996  { CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
997  { CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
998  { CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
999  { CKA_VALUE_LEN, ( CK_VOID_PTR ) &length, sizeof( CK_ULONG ) },
1000  /* Persistent-object only fields */
1001  { CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
1002  };
1003  const int templateCount = \
1004  ( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;
1005 
1006  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1007 
1008  REQUIRES( keySizeBits >= bytesToBits( MIN_KEYSIZE ) && \
1009  keySizeBits <= bytesToBits( CRYPT_MAX_KEYSIZE ) );
1010 
1011  /* If this is meant to be a persistent object, modify the template to
1012  make it a persistent token object and adjust the template entry count
1013  to include the object label */
1014  if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
1015  keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;
1016 
1017  return( generateKey( contextInfoPtr, keyTemplate, templateCount, TRUE ) );
1018  }
1019 #else
1020 
1021 #define cipherGenerateKey NULL
1022 #define hmacGenerateKey NULL
1023 
1024 #endif /* USE_HW_KEYGEN */
1025 
1026 /****************************************************************************
1027 * *
1028 * Conventional Crypto Mapping Functions *
1029 * *
1030 ****************************************************************************/
1031 
1032 /* Set up algorithm-specific encryption parameters */
1033 
1034 CHECK_RETVAL_RANGE( 0, 64 ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
1035 static int initCryptParams( const CONTEXT_INFO *contextInfoPtr,
1036  INOUT void *paramData )
1037  {
1038  const int ivSize = contextInfoPtr->capabilityInfo->blockSize;
1039 
1040  assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1041  assert( isWritePtr( paramData, sizeof( int ) ) );
1042  /* Minimum writable size is integer */
1043 
1044  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RC2 )
1045  {
1046  if( contextInfoPtr->ctxConv->mode == CRYPT_MODE_ECB )
1047  {
1048  CK_RC2_PARAMS_PTR rc2params = ( CK_RC2_PARAMS_PTR ) paramData;
1049 
1050  *rc2params = 128;
1051  return( sizeof( CK_RC2_PARAMS ) );
1052  }
1053  else
1054  {
1055  CK_RC2_CBC_PARAMS_PTR rc2params = ( CK_RC2_CBC_PARAMS_PTR ) paramData;
1056 
1057  rc2params->ulEffectiveBits = 128;
1058  memcpy( rc2params->iv, contextInfoPtr->ctxConv->currentIV, ivSize );
1059  return( sizeof( CK_RC2_CBC_PARAMS ) );
1060  }
1061  }
1062  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RC5 )
1063  {
1064  if( contextInfoPtr->ctxConv->mode == CRYPT_MODE_ECB )
1065  {
1066  CK_RC5_PARAMS_PTR rc5params = ( CK_RC5_PARAMS_PTR ) paramData;
1067 
1068  rc5params->ulWordsize = 4; /* Word size in bytes = blocksize/2 */
1069  rc5params->ulRounds = 12;
1070  return( sizeof( CK_RC5_PARAMS ) );
1071  }
1072  else
1073  {
1074  CK_RC5_CBC_PARAMS_PTR rc5params = ( CK_RC5_CBC_PARAMS_PTR ) paramData;
1075 
1076  rc5params->ulWordsize = 4; /* Word size in bytes = blocksize/2 */
1077  rc5params->ulRounds = 12;
1078  rc5params->pIv = contextInfoPtr->ctxConv->currentIV;
1079  rc5params->ulIvLen = ivSize;
1080  return( sizeof( CK_RC5_CBC_PARAMS ) );
1081  }
1082  }
1083 
1084  return( 0 );
1085  }
1086 
1087 /* Encrypt/decrypt data */
1088 
1089 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1090 static int cipherEncrypt( INOUT CONTEXT_INFO *contextInfoPtr,
1091  INOUT_BUFFER_FIXED( length ) void *buffer,
1092  IN_LENGTH const int length,
1093  const CK_MECHANISM_TYPE mechanismType )
1094  {
1095  CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
1096  CRYPT_DEVICE iCryptDevice;
1097  PKCS11_INFO *pkcs11Info;
1098  BYTE paramDataBuffer[ 64 + 8 ];
1099  const int ivSize = contextInfoPtr->capabilityInfo->blockSize;
1100  int paramSize, cryptStatus;
1101 
1102  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1103  assert( isWritePtr( buffer, length ) );
1104 
1105  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1106 
1107  /* Set up algorithm and mode-specific parameters */
1108  paramSize = initCryptParams( contextInfoPtr, &paramDataBuffer );
1109  if( paramSize > 0 )
1110  {
1111  mechanism.pParameter = paramDataBuffer;
1112  mechanism.ulParameterLen = paramSize;
1113  }
1114  else
1115  {
1116  /* Even if there are no algorithm-specific parameters, there may
1117  still be a mode-specific IV parameter */
1118  if( needsIV( contextInfoPtr->ctxConv->mode ) && \
1119  !isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
1120  {
1121  mechanism.pParameter = contextInfoPtr->ctxConv->currentIV;
1122  mechanism.ulParameterLen = ivSize;
1123  }
1124  }
1125 
1126  /* Get the information for the device associated with this context */
1127  cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
1128  &iCryptDevice, &pkcs11Info );
1129  if( cryptStatusError( cryptStatus ) )
1130  return( cryptStatus );
1131 
1132  cryptStatus = genericEncrypt( pkcs11Info, contextInfoPtr, &mechanism, buffer,
1133  length, length );
1134  if( cryptStatusOK( cryptStatus ) )
1135  {
1136  if( needsIV( contextInfoPtr->ctxConv->mode ) && \
1137  !isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
1138  {
1139  /* Since PKCS #11 assumes that either all data is encrypted at
1140  once or that a given mechanism is devoted entirely to a single
1141  operation, we have to preserve the state (the IV) across
1142  calls */
1143  memcpy( contextInfoPtr->ctxConv->currentIV, \
1144  ( BYTE * ) buffer + length - ivSize, ivSize );
1145  }
1146  }
1147  krnlReleaseObject( iCryptDevice );
1148 
1149  return( cryptStatus );
1150  }
1151 
1152 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1153 static int cipherDecrypt( INOUT CONTEXT_INFO *contextInfoPtr,
1154  INOUT_BUFFER_FIXED( length ) void *buffer,
1155  IN_LENGTH const int length,
1156  const CK_MECHANISM_TYPE mechanismType )
1157  {
1158  CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
1159  CRYPT_DEVICE iCryptDevice;
1160  PKCS11_INFO *pkcs11Info;
1161  BYTE paramDataBuffer[ 64 + 8 ], ivBuffer[ CRYPT_MAX_IVSIZE + 8 ];
1162  const int ivSize = contextInfoPtr->capabilityInfo->blockSize;
1163  int paramSize, cryptStatus;
1164 
1165  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1166  assert( isWritePtr( buffer, length ) );
1167 
1168  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1169 
1170  /* Set up algorithm and mode-specific parameters */
1171  paramSize = initCryptParams( contextInfoPtr, &paramDataBuffer );
1172  if( paramSize > 0 )
1173  {
1174  mechanism.pParameter = paramDataBuffer;
1175  mechanism.ulParameterLen = paramSize;
1176  }
1177  else
1178  /* Even if there are no algorithm-specific parameters, there may
1179  still be a mode-specific IV parameter. In addition we have to
1180  save the end of the ciphertext as the IV for the next block if
1181  this is required */
1182  if( needsIV( contextInfoPtr->ctxConv->mode ) && \
1183  !isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
1184  {
1185  mechanism.pParameter = contextInfoPtr->ctxConv->currentIV;
1186  mechanism.ulParameterLen = ivSize;
1187  }
1188  if( needsIV( contextInfoPtr->ctxConv->mode ) && \
1189  !isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
1190  memcpy( ivBuffer, ( BYTE * ) buffer + length - ivSize, ivSize );
1191 
1192  /* Get the information for the device associated with this context */
1193  cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
1194  &iCryptDevice, &pkcs11Info );
1195  if( cryptStatusError( cryptStatus ) )
1196  return( cryptStatus );
1197 
1198  cryptStatus = genericDecrypt( pkcs11Info, contextInfoPtr, &mechanism, buffer,
1199  length );
1200  if( cryptStatusOK( cryptStatus ) )
1201  {
1202  if( needsIV( contextInfoPtr->ctxConv->mode ) && \
1203  !isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
1204  {
1205  /* Since PKCS #11 assumes that either all data is encrypted at
1206  once or that a given mechanism is devoted entirely to a single
1207  operation, we have to preserve the state (the IV) across
1208  calls */
1209  memcpy( contextInfoPtr->ctxConv->currentIV, ivBuffer, ivSize );
1210  }
1211  }
1212  krnlReleaseObject( iCryptDevice );
1213  return( cryptStatus );
1214  }
1215 
1216 /* Map a cryptlib algorithm and mode to a PKCS #11 mechanism type, with
1217  shortcuts for the most frequently-used algorithm(s) */
1218 
1219 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1220 static int cipherEncryptECB( INOUT CONTEXT_INFO *contextInfoPtr,
1221  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1222  IN_LENGTH int length )
1223  {
1224  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1225  assert( isWritePtr( buffer, length ) );
1226 
1227  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1228 
1229  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_3DES )
1230  return( cipherEncrypt( contextInfoPtr, buffer, length, CKM_DES3_ECB ) );
1231  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_AES )
1232  return( cipherEncrypt( contextInfoPtr, buffer, length, CKM_AES_ECB ) );
1233  return( cipherEncrypt( contextInfoPtr, buffer, length,
1234  getMechanism( MECH_CONV, contextInfoPtr->capabilityInfo->cryptAlgo,
1235  CRYPT_MODE_ECB ) ) );
1236  }
1237 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1238 static int cipherEncryptCBC( INOUT CONTEXT_INFO *contextInfoPtr,
1239  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1240  IN_LENGTH int length )
1241  {
1242  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1243  assert( isWritePtr( buffer, length ) );
1244 
1245  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1246 
1247  return( cipherEncrypt( contextInfoPtr, buffer, length,
1248  contextInfoPtr->capabilityInfo->paramDefaultMech ) );
1249  }
1250 #if defined( USE_RC4 )
1251 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1252 static int cipherEncryptOFB( INOUT CONTEXT_INFO *contextInfoPtr,
1253  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1254  IN_LENGTH int length )
1255  {
1256  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1257  assert( isWritePtr( buffer, length ) );
1258 
1259  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1260 
1261  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RC4 )
1262  return( cipherEncrypt( contextInfoPtr, buffer, length, CKM_RC4 ) );
1263  return( cipherEncrypt( contextInfoPtr, buffer, length,
1264  getMechanism( MECH_CONV, contextInfoPtr->capabilityInfo->cryptAlgo,
1265  CRYPT_MODE_OFB ) ) );
1266  }
1267 #endif /* USE_RC4 */
1268 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1269 static int cipherDecryptECB( INOUT CONTEXT_INFO *contextInfoPtr,
1270  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1271  IN_LENGTH int length )
1272  {
1273  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1274  assert( isWritePtr( buffer, length ) );
1275 
1276  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1277 
1278  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_3DES )
1279  return( cipherDecrypt( contextInfoPtr, buffer, length, CKM_DES3_ECB ) );
1280  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_AES )
1281  return( cipherDecrypt( contextInfoPtr, buffer, length, CKM_AES_ECB ) );
1282  return( cipherDecrypt( contextInfoPtr, buffer, length,
1283  getMechanism( MECH_CONV, contextInfoPtr->capabilityInfo->cryptAlgo,
1284  CRYPT_MODE_ECB ) ) );
1285  }
1286 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1287 static int cipherDecryptCBC( INOUT CONTEXT_INFO *contextInfoPtr,
1288  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1289  IN_LENGTH int length )
1290  {
1291  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1292  assert( isWritePtr( buffer, length ) );
1293 
1294  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1295 
1296  return( cipherDecrypt( contextInfoPtr, buffer, length,
1297  contextInfoPtr->capabilityInfo->paramDefaultMech ) );
1298  }
1299 #if defined( USE_RC4 )
1300 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1301 static int cipherDecryptOFB( INOUT CONTEXT_INFO *contextInfoPtr,
1302  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1303  IN_LENGTH int length )
1304  {
1305  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1306  assert( isWritePtr( buffer, length ) );
1307 
1308  REQUIRES( length > 0 && length < MAX_INTLENGTH );
1309 
1310  if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RC4 )
1311  return( cipherDecrypt( contextInfoPtr, buffer, length, CKM_RC4 ) );
1312  return( cipherDecrypt( contextInfoPtr, buffer, length,
1313  getMechanism( MECH_CONV, contextInfoPtr->capabilityInfo->cryptAlgo,
1314  CRYPT_MODE_OFB ) ) );
1315  }
1316 #endif /* USE_RC4 */
1317 
1318 /****************************************************************************
1319 * *
1320 * MAC Mapping Functions *
1321 * *
1322 ****************************************************************************/
1323 
1324 /* MAC data. The PKCS #11 way of handling this is rather problematic since
1325  the HMAC operation is associated with a session and not with the the HMAC
1326  object. This means that we can only have a single HMAC operation in
1327  effect at any one time. To protect against users starting a second
1328  HMAC/sign operation, we record the device object handle of the currently
1329  active signing object and don't allow any further signature operations to
1330  be initiated if there's an object currently in use */
1331 
1332 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1333 static int hmac( INOUT CONTEXT_INFO *contextInfoPtr,
1334  INOUT_BUFFER_FIXED( length ) BYTE *buffer,
1335  IN_LENGTH_Z int length )
1336  {
1337  CK_MECHANISM mechanism = { contextInfoPtr->capabilityInfo->paramDefaultMech,
1338  NULL_PTR, 0 };
1339  CRYPT_DEVICE iCryptDevice;
1340  PKCS11_INFO *pkcs11Info;
1341  CK_RV status;
1342  int cryptStatus;
1343 
1344  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
1345  assert( ( length == 0 ) || isWritePtr( buffer, length ) );
1346 
1347  REQUIRES( length >= 0 && length < MAX_INTLENGTH );
1348 
1349  /* Get the information for the device associated with this context */
1350  cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
1351  &iCryptDevice, &pkcs11Info );
1352  if( cryptStatusError( cryptStatus ) )
1353  return( cryptStatus );
1354 
1355  /* If we're currently in the middle of a multi-stage sign operation we
1356  can't start a new one. We have to perform this tracking explicitly
1357  since PKCS #11 only allows one multi-stage operation per session */
1358  if( pkcs11Info->hActiveSignObject != CK_OBJECT_NONE && \
1359  pkcs11Info->hActiveSignObject != contextInfoPtr->deviceObject )
1360  {
1361  krnlReleaseObject( iCryptDevice );
1362  return( CRYPT_ERROR_INCOMPLETE );
1363  }
1364 
1365  /* If we haven't initialised the MAC operation yet, start it now */
1366  if( !( contextInfoPtr->flags & CONTEXT_FLAG_HASH_INITED ) )
1367  {
1368  status = C_SignInit( pkcs11Info->hSession, &mechanism,
1369  contextInfoPtr->deviceObject );
1370  if( status != CKR_OK )
1371  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
1372  contextInfoPtr->flags |= CONTEXT_FLAG_HASH_INITED;
1373  pkcs11Info->hActiveSignObject = contextInfoPtr->deviceObject;
1374  }
1375 
1376  if( length > 0 )
1377  status = C_SignUpdate( pkcs11Info->hSession, buffer, length );
1378  else
1379  {
1380  CK_ULONG dummy;
1381 
1382  status = C_SignFinal( pkcs11Info->hSession,
1383  contextInfoPtr->ctxMAC->mac, &dummy );
1384  pkcs11Info->hActiveSignObject = CK_OBJECT_NONE;
1385  }
1386  if( status != CKR_OK )
1387  return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
1388 
1389  krnlReleaseObject( iCryptDevice );
1390  return( cryptStatus );
1391  }
1392 
1393 /****************************************************************************
1394 * *
1395 * Device Capability Routines *
1396 * *
1397 ****************************************************************************/
1398 
1399 /* Conventional encryption and MAC mechanism information */
1400 
1401 static const PKCS11_MECHANISM_INFO mechanismInfoConv[] = {
1402  /* Conventional encryption mechanisms */
1404  genericEndFunction, cipherInitKey, cipherGenerateKey,
1405  cipherEncryptECB, cipherDecryptECB, NULL, NULL },
1407  genericEndFunction, cipherInitKey, cipherGenerateKey,
1408  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },
1410  genericEndFunction, cipherInitKey, cipherGenerateKey,
1411  cipherEncryptECB, cipherDecryptECB, NULL, NULL },
1413  genericEndFunction, cipherInitKey, cipherGenerateKey,
1414  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },
1415 #ifdef USE_RC2
1417  genericEndFunction, cipherInitKey, cipherGenerateKey,
1418  cipherEncryptECB, cipherDecryptECB, NULL, NULL },
1420  genericEndFunction, cipherInitKey, cipherGenerateKey,
1421  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },
1422 #endif /* USE_RC2 */
1423 #ifdef USE_RC4
1425  genericEndFunction, cipherInitKey, cipherGenerateKey,
1426  cipherEncryptOFB, cipherDecryptOFB, NULL, NULL },
1427 #endif /* USE_RC4 */
1428 #ifdef USE_RC5
1430  genericEndFunction, cipherInitKey, cipherGenerateKey,
1431  cipherEncryptECB, cipherDecryptECB, NULL, NULL },
1433  genericEndFunction, cipherInitKey, cipherGenerateKey,
1434  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },
1435 #endif /* USE_RC5 */
1437  genericEndFunction, cipherInitKey, cipherGenerateKey,
1438  cipherEncryptECB, cipherDecryptECB, NULL, NULL },
1440  genericEndFunction, cipherInitKey, cipherGenerateKey,
1441  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },
1442 #ifdef USE_BLOWFISH
1444  genericEndFunction, cipherInitKey, cipherGenerateKey,
1445  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },
1446 #endif /* USE_BLOWFISH */
1447 
1448  /* MAC mechanisms. The positioning of the encrypt/decrypt functions is
1449  a bit odd because cryptlib treats hashing as an encrypt/decrypt
1450  operation while PKCS #11 treats it as a sign/verify operation, the
1451  function names correspond to the PKCS #11 usage but the position is
1452  for cryptlib usage. In addition there aren't any HMAC key types so
1453  it's necessary to use CKK_GENERIC_SECRET (there's actually a bug in
1454  the standard around this because CKK_GENERIC_SECRET keys can't be
1455  used for en/decryption or sign/verify, at the moment some
1456  implementations allow them to be used with HMAC and some don't). In
1457  order to allow for implementations that define their own HMAC keygen
1458  and key types, we use macros for CKM_x_HMAC_KEY_GEN and CKK_x_HMAC
1459  that expand either to the vendor-specific type or the generic CKM/CKK
1460  types */
1461 #ifdef USE_HMAC_MD5
1462  { CKM_MD5_HMAC, CKM_MD5_HMAC_KEY_GEN, CKM_MD5_HMAC, CRYPT_ALGO_HMAC_MD5, CRYPT_MODE_NONE, CKK_MD5_HMAC,
1463  genericEndFunction, hmacInitKey, hmacGenerateKey,
1464  hmac, hmac, NULL, NULL },
1465 #endif /* USE_HMAC_MD5 */
1466  { CKM_SHA_1_HMAC, CKM_SHA_1_HMAC_KEY_GEN, CKM_SHA_1_HMAC, CRYPT_ALGO_HMAC_SHA1, CRYPT_MODE_NONE, CKK_SHA_1_HMAC,
1467  genericEndFunction, hmacInitKey, hmacGenerateKey,
1468  hmac, hmac, NULL, NULL },
1469 #ifdef USE_HMAC_RIPEMD160
1470  { CKM_RIPEMD160_HMAC, CKM_RIPEMD160_HMAC_KEY_GEN, CKM_RIPEMD160_HMAC, CRYPT_ALGO_HMAC_RIPEMD160, CRYPT_MODE_NONE, CKK_RIPEMD160_HMAC,
1471  genericEndFunction, hmacInitKey, hmacGenerateKey,
1472  hmac, hmac, NULL, NULL },
1473 #endif /* USE_HMAC_RIPEMD160 */
1474 #ifdef USE_HMAC_SHA2
1475  { CKM_SHA256_HMAC, CKM_SHA256_HMAC_KEY_GEN, CKM_SHA256_HMAC, CRYPT_ALGO_HMAC_SHA2, CRYPT_MODE_NONE, CKK_SHA256_HMAC,
1476  genericEndFunction, hmacInitKey, hmacGenerateKey,
1477  hmac, hmac, NULL, NULL },
1478 #endif /* USE_HMAC_SHA2 */
1479 
1480  { CKM_NONE, CKM_NONE, CKM_NONE, CRYPT_ERROR, CRYPT_ERROR },
1481  { CKM_NONE, CKM_NONE, CKM_NONE, CRYPT_ERROR, CRYPT_ERROR }
1482  };
1483 
1484 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1485 const PKCS11_MECHANISM_INFO *getMechanismInfoConv( OUT_LENGTH_SHORT int *mechanismInfoSize )
1486  {
1487  assert( isWritePtr( mechanismInfoSize, sizeof( int ) ) );
1488 
1489  *mechanismInfoSize = FAILSAFE_ARRAYSIZE( mechanismInfoConv, \
1490  PKCS11_MECHANISM_INFO );
1491  return( mechanismInfoConv );
1492  }
1493 
1494 /* Map a cryptlib conventional-encryption algorithm and mode to a PKCS #11
1495  mechanism */
1496 
1497 static CK_MECHANISM_TYPE getMechanism( const GETMECH_TYPE mechType,
1498  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
1500  {
1501  int i;
1502 
1503  REQUIRES_EXT( ( ( mechType == MECH_CONV && \
1504  isConvAlgo( cryptAlgo ) && \
1505  cryptMode > CRYPT_MODE_NONE && \
1506  cryptMode < CRYPT_MODE_LAST ) ||
1507  ( mechType == MECH_CONV_KEYGEN && \
1508  isConvAlgo( cryptAlgo ) && \
1509  cryptMode == CRYPT_MODE_NONE ) ||
1510  ( ( mechType == MECH_MAC || \
1511  mechType == MECH_MAC_KEYGEN ) && \
1512  isMacAlgo( cryptAlgo ) && \
1513  cryptMode == CRYPT_MODE_NONE ) ), CKM_NONE );
1514 
1515  /* Find a match for the algorithm type. If it's a MAC algorithm or
1516  keygen mechanism, we're done */
1517  for( i = 0; mechanismInfoConv[ i ].cryptAlgo != cryptAlgo && \
1518  mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR && \
1519  i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO );
1520  i++ );
1521  ENSURES_EXT( ( i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ) ),
1522  CKM_NONE );
1523  ENSURES_EXT( ( i < sizeof( mechanismInfoConv ) / sizeof( PKCS11_MECHANISM_INFO ) && \
1524  mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR ), CKM_NONE );
1525  if( mechType == MECH_MAC )
1526  return( mechanismInfoConv[ i ].mechanism );
1527  if( mechType == MECH_CONV_KEYGEN || mechType == MECH_MAC_KEYGEN )
1528  return( mechanismInfoConv[ i ].keygenMechanism );
1529 
1530  /* It's a conventional-encryption mechanism, we have to match the
1531  encryption mode as well */
1532  ENSURES_EXT( mechType == MECH_CONV, CKM_NONE );
1533  while( mechanismInfoConv[ i ].cryptMode != cryptMode && \
1534  mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR && \
1535  i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ) )
1536  i++;
1537  ENSURES_EXT( ( i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ) ),
1538  CKM_NONE );
1539  ENSURES_EXT( ( i < sizeof( mechanismInfoConv ) / sizeof( PKCS11_MECHANISM_INFO ) && \
1540  mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR ), CKM_NONE );
1541 
1542  return( mechanismInfoConv[ i ].mechanism );
1543  }
1544 
1545 /****************************************************************************
1546 * *
1547 * Device Access Routines *
1548 * *
1549 ****************************************************************************/
1550 
1551 /* Mechanisms supported by PKCS #11 devices. These are actually cryptlib
1552  native mechanisms (support of the various mechanisms in devices is too
1553  patchy to rely on, see for example the comments about PKCS vs.raw RSA
1554  mechanisms elsewhere), but not the full set supported by the system
1555  device since functions like private key export aren't available. The
1556  list is sorted in order of frequency of use in order to make lookups a
1557  bit faster */
1558 
1559 static const FAR_BSS MECHANISM_FUNCTION_INFO mechanismFunctions[] = {
1560  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },
1561  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },
1562  { MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },
1563  { MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },
1564  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },
1565  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },
1566 #ifdef USE_PGP
1567  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },
1568  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },
1569 #endif /* USE_PGP */
1570  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },
1571  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },
1572  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS5, ( MECHANISM_FUNCTION ) derivePKCS5 },
1573 #if defined( USE_PGP ) || defined( USE_PGPKEYS )
1574  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },
1575 #endif /* USE_PGP || USE_PGPKEYS */
1576 #ifdef USE_SSL
1577  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveSSL },
1578  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveTLS },
1579  { MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },
1580  { MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },
1581 #endif /* USE_SSL */
1582 #ifdef USE_CMP
1583  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },
1584 #endif /* USE_CMP */
1585 #ifdef USE_PKCS12
1586  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },
1587 #endif /* USE_PKCS12 */
1589  };
1590 
1591 /* Set up the function pointers to the device methods */
1592 
1593 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1594 int setDevicePKCS11( INOUT DEVICE_INFO *deviceInfo,
1595  IN_BUFFER( nameLength ) const char *name,
1596  IN_LENGTH_ATTRIBUTE const int nameLength )
1597  {
1598  int status;
1599 
1600  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
1601  assert( isReadPtr( name, nameLength ) );
1602 
1603  REQUIRES( nameLength > 0 && nameLength < MAX_ATTRIBUTE_SIZE );
1604 
1605  status = initPKCS11Init( deviceInfo, name, nameLength );
1606  if( cryptStatusError( status ) )
1607  return( status );
1608  deviceInfo->controlFunction = controlFunction;
1609  initPKCS11Read( deviceInfo );
1610  initPKCS11Write( deviceInfo );
1611  deviceInfo->mechanismFunctions = mechanismFunctions;
1612  deviceInfo->mechanismFunctionCount = \
1613  FAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );
1614 
1615  return( CRYPT_OK );
1616  }
1617 #endif /* USE_PKCS11 */