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