1 /****************************************************************************
2 * *
3 * cryptlib PKCS #11 Item Read Routines *
4 * Copyright Peter Gutmann 1998-2012 *
5 * *
6 ****************************************************************************/
7
8 #define PKC_CONTEXT /* Tell context.h that we're working with PKC contexts */
9 #if defined( INC_ALL )
10 #include "crypt.h"
11 #include "context.h"
12 #include "device.h"
13 #include "pkcs11_api.h"
14 #include "asn1.h"
15 #if defined( USE_ECDH ) || defined( USE_ECDSA )
16 #include "asn1_ext.h"
17 #endif /* USE_ECDH || USE_ECDSA */
18 #else
19 #include "crypt.h"
20 #include "context/context.h"
21 #include "device/device.h"
22 #include "device/pkcs11_api.h"
23 #include "enc_dec/asn1.h"
24 #if defined( USE_ECDH ) || defined( USE_ECDSA )
25 #include "enc_dec/asn1_ext.h"
26 #endif /* USE_ECDH || USE_ECDSA */
27 #endif /* Compiler-specific includes */
28
29 /* In some rare situations only incomplete PKCS #11 support is available in
30 the underlying device, for example with a token that's been initialised
31 via CryptoAPI (which doesn't populate all the PKCS #11 fields) but which
32 is now being accessed through a PKCS #11 driver. Define the following
33 to have cryptlib perform an object search by enumerating every object of
34 the required type in the token and matching by the requested ID
35 information */
36
37 #define PKCS11_FIND_VIA_CRYPTLIB
38
39 /* We sometimes need to read things into local memory from a device in a
40 manner that can't be handled by a dynBuf since the data is coming from a
41 device rather than a cryptlib object. The following value defines the
42 maximum size of the on-stack buffer, if the data is larger than this then
43 we dynamically allocate the buffer (this almost never occurs) */
44
45 #define MAX_STACK_BUFFER_SIZE 1024
46
47 #ifdef USE_PKCS11
48
49 /****************************************************************************
50 * *
51 * Utility Routines *
52 * *
53 ****************************************************************************/
54
55 /* Get a PKCS #11 attribute value. If the passed-in buffer is large enough
56 to contain the value (it almost always is) then we use that, otherwise
57 we dynamically allocate the storage for it, which is why the caller has
58 to call an explicit cleanup function when they're finished with the
59 data */
60
61 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5, 6 ) ) \
62 static int getAttributeValue( INOUT PKCS11_INFO *pkcs11Info,
63 const CK_OBJECT_HANDLE hObject,
64 const CK_ATTRIBUTE_TYPE type,
65 OUT_BUFFER_ALLOC_OPT( *valueLength ) void **value,
66 OUT_LENGTH_SHORT_Z int *valueLength,
67 OUT_BUFFER( valueBufLength, *valueLength ) \
68 void *valueBuffer,
69 IN_LENGTH_SHORT_MIN( 16 ) const int valueBufLength )
70 {
71 CK_ATTRIBUTE valueTemplate = \
72 { type, NULL_PTR, 0 };
73 CK_RV status;
74
75 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
76 assert( isWritePtr( value, sizeof( void * ) ) );
77 assert( isWritePtr( valueLength, sizeof( int ) ) );
78 assert( isWritePtr( valueBuffer, valueBufLength ) );
79
80 REQUIRES( valueBufLength >= 16 && valueBufLength < MAX_INTLENGTH_SHORT );
81
82 /* Clear return values */
83 *value = NULL;
84 memset( valueBuffer, 0, min( 16, valueBufLength ) );
85 *valueLength = 0;
86
87 /* Find out how big the attribute value is */
88 status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
89 &valueTemplate, 1 );
90 if( status != CKR_OK )
91 return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
92
93 /* If it's larger than the supplied buffer, allocate the storage
94 dynamically */
95 if( valueTemplate.ulValueLen > valueBufLength )
96 {
97 if( valueTemplate.ulValueLen >= MAX_INTLENGTH_SHORT )
98 return( CRYPT_ERROR_OVERFLOW );
99 if( ( valueTemplate.pValue = clAlloc( "getAttributeValue", \
100 ( size_t ) ( valueTemplate.ulValueLen ) ) ) == NULL )
101 return( CRYPT_ERROR_MEMORY );
102 }
103 else
104 valueTemplate.pValue = valueBuffer;
105
106 /* Get the attribute value */
107 status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
108 &valueTemplate, 1 );
109 if( status != CKR_OK )
110 {
111 if( valueTemplate.pValue != valueBuffer )
112 clFree( "getAttributeValue", valueTemplate.pValue );
113 return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
114 }
115 *value = valueTemplate.pValue;
116 *valueLength = valueTemplate.ulValueLen;
117
118 return( CRYPT_OK );
119 }
120
121 STDC_NONNULL_ARG( ( 1, 2 ) ) \
getAttributeValueEnd(IN void * value,const void * valueBuffer)122 static void getAttributeValueEnd( IN void *value,
123 const void *valueBuffer )
124 {
125 assert( isReadPtr( value, 16 ) );
126 assert( isReadPtr( valueBuffer, 16 ) );
127
128 if( value != valueBuffer )
129 clFree( "getAttributeValueEnd", value );
130 }
131
132 /* Get the label for an object, truncating overly long labels if required.
133 We can't use a dynBuf for this because it's a PKCS #11 attribute rather
134 than a cryptlib attribute */
135
136 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
137 static int getObjectLabel( INOUT PKCS11_INFO *pkcs11Info,
138 const CK_OBJECT_HANDLE hObject,
139 OUT_BUFFER( maxLabelSize, *labelLength ) \
140 char *label,
141 IN_LENGTH_SHORT_MIN( 16 ) \
142 const int maxLabelSize,
143 OUT_LENGTH_BOUNDED_Z( maxLabelSize ) \
144 int *labelLength )
145 {
146 char labelBuffer[ CRYPT_MAX_TEXTSIZE + 8 ], *localLabel;
147 int localLabelLength, cryptStatus;
148
149 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
150 assert( isWritePtr( label, maxLabelSize ) );
151 assert( isWritePtr( labelLength, sizeof( int ) ) );
152
153 REQUIRES( maxLabelSize >= 16 && maxLabelSize < MAX_INTLENGTH_SHORT );
154
155 /* Clear return values */
156 memset( label, 0, maxLabelSize );
157 *labelLength = 0;
158
159 cryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_LABEL,
160 &localLabel, &localLabelLength,
161 labelBuffer, CRYPT_MAX_TEXTSIZE );
162 if( cryptStatusError( cryptStatus ) )
163 return( cryptStatus );
164 *labelLength = min( localLabelLength, maxLabelSize );
165 REQUIRES( *labelLength > 0 && *labelLength < MAX_INTLENGTH_SHORT );
166 memcpy( label, localLabel, *labelLength );
167 getAttributeValueEnd( localLabel, labelBuffer );
168
169 return( CRYPT_OK );
170 }
171
172 /* Read a flag for an object. An absent value is treated as FALSE */
173
174 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
readFlag(const PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hObject,const CK_ATTRIBUTE_TYPE flagType)175 static BOOLEAN readFlag( const PKCS11_INFO *pkcs11Info,
176 const CK_OBJECT_HANDLE hObject,
177 const CK_ATTRIBUTE_TYPE flagType )
178 {
179 CK_BBOOL bFlag = FALSE;
180 CK_ATTRIBUTE flagTemplate = { flagType, &bFlag, sizeof( CK_BBOOL ) };
181
182 assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
183
184 /* Some buggy implementations return CKR_OK but forget to set the
185 data value in the template (!!!) so we have to initialise bFlag
186 to a default of FALSE to handle this */
187 return( ( C_GetAttributeValue( pkcs11Info->hSession, hObject,
188 &flagTemplate, 1 ) == CKR_OK && bFlag ) ? \
189 TRUE : FALSE );
190 }
191
192 /* Get the permitted-action flags for an object */
193
CHECK_RETVAL_RANGE(ACTION_PERM_FLAG_NONE,ACTION_PERM_FLAG_MAX)194 CHECK_RETVAL_RANGE( ACTION_PERM_FLAG_NONE, ACTION_PERM_FLAG_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \
195 int getActionFlags( INOUT PKCS11_INFO *pkcs11Info,
196 const CK_OBJECT_HANDLE hObject,
197 IN_ENUM( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType,
198 IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
199 {
200 const BOOLEAN checkSign = ( isSigAlgo( cryptAlgo ) || \
201 isMacAlgo( cryptAlgo ) ) ? \
202 TRUE : FALSE;
203 const BOOLEAN checkCrypt = ( isCryptAlgo( cryptAlgo ) || \
204 isConvAlgo( cryptAlgo ) ) ? \
205 TRUE : FALSE;
206 const BOOLEAN checkWrap = isCryptAlgo( cryptAlgo );
207 BOOLEAN cryptAllowed = FALSE, sigAllowed = FALSE;
208 int actionFlags = 0;
209
210 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
211
212 REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
213 itemType == KEYMGMT_ITEM_PRIVATEKEY || \
214 itemType == KEYMGMT_ITEM_SECRETKEY );
215 REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
216 cryptAlgo <= CRYPT_ALGO_LAST_MAC );
217
218 /* Get the permitted actions for the object. Some devices report bogus
219 capabilities (for example encrypt for a MAC object) so we restrict
220 the actions that we check for to try and weed out false positives.
221 The kernel won't allow the setting of an invalid action anyway, but
222 it's better to be safe here.
223
224 We also have to provide special translation for the sign and sig-
225 check action flags, PKCS #11 treats the MAC operation as a member
226 of the signature family while cryptlib treats it as a member of the
227 hash family so if we get a sign/sigcheck permitted action for a MAC
228 object we map it to a hash permitted action */
229 if( ( checkCrypt && readFlag( pkcs11Info, hObject, CKA_ENCRYPT ) ) || \
230 ( checkWrap && readFlag( pkcs11Info, hObject, CKA_WRAP ) ) )
231 {
232 actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
233 cryptAllowed = TRUE;
234 }
235 if( ( checkCrypt && itemType != KEYMGMT_ITEM_PUBLICKEY && \
236 readFlag( pkcs11Info, hObject, CKA_DECRYPT ) ) || \
237 ( checkWrap && itemType == KEYMGMT_ITEM_PRIVATEKEY && \
238 readFlag( pkcs11Info, hObject, CKA_UNWRAP ) ) )
239 {
240 actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
241 cryptAllowed = TRUE;
242 }
243 if( checkSign && itemType != KEYMGMT_ITEM_PUBLICKEY && \
244 readFlag( pkcs11Info, hObject, CKA_SIGN ) )
245 {
246 if( isMacAlgo( cryptAlgo ) )
247 actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );
248 else
249 actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
250 sigAllowed = TRUE;
251 }
252 if( checkSign && readFlag( pkcs11Info, hObject, CKA_VERIFY ) )
253 {
254 if( isMacAlgo( cryptAlgo ) )
255 actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );
256 else
257 actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
258 sigAllowed = TRUE;
259 }
260 if( cryptAlgo == CRYPT_ALGO_RSA )
261 {
262 /* If there are any restrictions on the key usage then we have to
263 make it internal-only because of RSA's signature/encryption
264 duality */
265 if( !( cryptAllowed && sigAllowed ) )
266 actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
267 }
268 else
269 {
270 if( isDlpAlgo( cryptAlgo ) || isEccAlgo( cryptAlgo ) )
271 {
272 /* Because of the special-case data formatting requirements for
273 DLP/ECDLP algorithms we make the usage internal-only */
274 actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
275 }
276 }
277
278 return( actionFlags );
279 }
280
281 /* Get cryptlib algorithm and capability information for a PKCS #11 object */
282
283 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \
getMechanismInfo(const PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hObject,const void * capabilityInfoList,const BOOLEAN isPKC,const CAPABILITY_INFO ** capabilityInfoPtrPtr,OUT_ALGO_Z CRYPT_ALGO_TYPE * cryptAlgo)284 static int getMechanismInfo( const PKCS11_INFO *pkcs11Info,
285 const CK_OBJECT_HANDLE hObject,
286 const void *capabilityInfoList,
287 const BOOLEAN isPKC,
288 const CAPABILITY_INFO **capabilityInfoPtrPtr,
289 OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo )
290 {
291 CK_KEY_TYPE keyType DUMMY_INIT;
292 CK_ATTRIBUTE keyTypeTemplate = \
293 { CKA_KEY_TYPE, ( CK_VOID_PTR ) &keyType, sizeof( CK_KEY_TYPE ) };
294 CK_RV status;
295 const CAPABILITY_INFO *capabilityInfoPtr;
296 const PKCS11_MECHANISM_INFO *mechanismInfoPtr;
297 int mechanismInfoSize, i;
298
299 assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
300 assert( isReadPtr( capabilityInfoPtrPtr, sizeof( CAPABILITY_INFO ) ) );
301 assert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
302
303 REQUIRES( capabilityInfoList != NULL );
304
305 /* Clear return values */
306 *capabilityInfoPtrPtr = NULL;
307 *cryptAlgo = CRYPT_ALGO_NONE;
308
309 /* Get the key type (equivalent to the cryptlib algoID) for this
310 object */
311 status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
312 &keyTypeTemplate, 1 );
313 if( status != CKR_OK )
314 {
315 DEBUG_DIAG(( "Couldn't read CKA_KEY_TYPE" ));
316 assert( DEBUG_WARN );
317 return( CRYPT_ERROR_FAILED );
318 }
319
320 /* Hack for PKCS #11's broken HMAC "support", PKCS #11 has no HMAC
321 object types so if we find a generic secret key object we assume that
322 it's an HMAC-SHA1 object, the most common type */
323 if( keyType == CKK_GENERIC_SECRET )
324 {
325 *cryptAlgo = CRYPT_ALGO_HMAC_SHA1;
326 capabilityInfoPtr = findCapabilityInfo( capabilityInfoList,
327 *cryptAlgo );
328 if( capabilityInfoPtr == NULL )
329 return( CRYPT_ERROR_NOTAVAIL );
330 *capabilityInfoPtrPtr = capabilityInfoPtr;
331
332 return( CRYPT_OK );
333 }
334
335 /* Get the equivalent cryptlib algorithm type and use that to get the
336 capability information for the algorithm */
337 if( isPKC )
338 mechanismInfoPtr = getMechanismInfoPKC( &mechanismInfoSize );
339 else
340 mechanismInfoPtr = getMechanismInfoConv( &mechanismInfoSize );
341 for( i = 0; i < mechanismInfoSize && \
342 mechanismInfoPtr[ i ].keyType != keyType; i++ );
343 if( i >= mechanismInfoSize )
344 {
345 /* If we can't find a match for the PKCS #11 algorithm type in the
346 list of mechanisms then we're trying to instantiate an object
347 that uses an unsupported algorithm type */
348 DEBUG_DIAG(( "Tried to read object with unsupported PKCS #11 "
349 "algorithm type %d", keyType ));
350 return( CRYPT_ERROR_NOTAVAIL );
351 }
352 mechanismInfoPtr = &mechanismInfoPtr[ i ];
353 *cryptAlgo = mechanismInfoPtr->cryptAlgo;
354 capabilityInfoPtr = findCapabilityInfo( capabilityInfoList, *cryptAlgo );
355 if( capabilityInfoPtr == NULL )
356 return( CRYPT_ERROR_NOTAVAIL );
357 *capabilityInfoPtrPtr = capabilityInfoPtr;
358
359 return( CRYPT_OK );
360 }
361
362 #if defined( USE_ECDH ) || defined( USE_ECDSA )
363
364 /* Get the named curve type for an ECC object */
365
366 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
getEccCurveType(INOUT PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hObject,OUT_ENUM_OPT (CRYPT_ECCCURVE)CRYPT_ECCCURVE_TYPE * curveType)367 int getEccCurveType( INOUT PKCS11_INFO *pkcs11Info,
368 const CK_OBJECT_HANDLE hObject,
369 OUT_ENUM_OPT( CRYPT_ECCCURVE ) \
370 CRYPT_ECCCURVE_TYPE *curveType )
371 {
372 CRYPT_ECCCURVE_TYPE curve;
373 STREAM stream;
374 BYTE ecOidBuffer[ MAX_OID_SIZE + 8 ], *ecOid;
375 int ecOidLength, cryptStatus;
376
377 assert( isWritePtr( curveType, sizeof( CRYPT_ECCCURVE_TYPE ) ) );
378
379 /* Clear return value */
380 *curveType = CRYPT_ECCCURVE_NONE;
381
382 /* ECC algorithms are a serious pain, the only parameter that we have
383 available for them is CKA_EC_PARAMS, an OID for the curve that's
384 being used. In order to get the curve type from that we have to read
385 the OID and then convert it to the named-curve type */
386 cryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_EC_PARAMS,
387 &ecOid, &ecOidLength, ecOidBuffer,
388 MAX_OID_SIZE );
389 if( cryptStatusError( cryptStatus ) )
390 return( cryptStatus );
391 sMemConnect( &stream, ecOid, ecOidLength );
392 cryptStatus = readECCOID( &stream, &curve );
393 sMemDisconnect( &stream );
394 getAttributeValueEnd( ecOid, ecOidBuffer );
395 if( cryptStatusOK( cryptStatus ) )
396 *curveType = curve;
397
398 return( cryptStatus );
399 }
400 #endif /* USE_ECDH || USE_ECDSA */
401
402 /****************************************************************************
403 * *
404 * Template Manipulation Routines *
405 * *
406 ****************************************************************************/
407
408 /* Add the components of an issuerAndSerialnumber to a certificate
409 template */
410
411 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readIAndS(INOUT STREAM * stream,INOUT CK_ATTRIBUTE * certTemplateI,INOUT CK_ATTRIBUTE * certTemplateS)412 static int readIAndS( INOUT STREAM *stream,
413 INOUT CK_ATTRIBUTE *certTemplateI,
414 INOUT CK_ATTRIBUTE *certTemplateS )
415 {
416 void *dataPtr DUMMY_INIT_PTR;
417 int length, cryptStatus;
418
419 assert( isWritePtr( stream, sizeof( STREAM ) ) );
420 assert( isWritePtr( certTemplateI, sizeof( CK_ATTRIBUTE ) ) );
421 assert( isWritePtr( certTemplateS, sizeof( CK_ATTRIBUTE ) ) );
422
423 /* We don't clear the return values since these have already been
424 partially initialised with attribute information by the caller */
425
426 /* Read the wrapper tag */
427 cryptStatus = readSequence( stream, NULL );
428 if( cryptStatusError( cryptStatus ) )
429 return( cryptStatus );
430
431 /* Read the issuer DN and add it to the template */
432 cryptStatus = getStreamObjectLength( stream, &length );
433 if( cryptStatusOK( cryptStatus ) )
434 {
435 certTemplateI->ulValueLen = length;
436 cryptStatus = sMemGetDataBlock( stream, &dataPtr, length );
437 }
438 if( cryptStatusOK( cryptStatus ) )
439 {
440 certTemplateI->pValue = dataPtr;
441 cryptStatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );
442 }
443 if( cryptStatusError( cryptStatus ) )
444 return( cryptStatus );
445
446 /* Read the serial number and add it to the template */
447 cryptStatus = getStreamObjectLength( stream, &length );
448 if( cryptStatusOK( cryptStatus ) )
449 {
450 certTemplateS->ulValueLen = length;
451 cryptStatus = sMemGetDataBlock( stream, &dataPtr, length );
452 }
453 if( cryptStatusOK( cryptStatus ) )
454 {
455 certTemplateS->pValue = dataPtr;
456 cryptStatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );
457 }
458 return( cryptStatus );
459 }
460
461 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
462 int addIAndSToTemplate( INOUT_ARRAY_C( 2 ) CK_ATTRIBUTE *certTemplate,
463 IN_BUFFER( iAndSLength ) const void *iAndSPtr,
464 IN_LENGTH_SHORT const int iAndSLength )
465 {
466 STREAM stream;
467 int cryptStatus;
468
469 assert( isWritePtr( certTemplate, sizeof( CK_ATTRIBUTE ) * 2 ) );
470 assert( isReadPtr( iAndSPtr, iAndSLength ) );
471
472 REQUIRES( iAndSLength > 0 && iAndSLength < MAX_INTLENGTH_SHORT );
473
474 /* We don't clear the return value since this has already been
475 partially initialised with attribute information by the caller */
476
477 /* Parse the iAndS data and add it to the template */
478 sMemConnect( &stream, iAndSPtr, iAndSLength );
479 cryptStatus = readIAndS( &stream, &certTemplate[ 0 ],
480 &certTemplate[ 1 ] );
481 sMemDisconnect( &stream );
482 return( cryptStatus );
483 }
484
485 /* Set up a search template for an issuerAndSerialNumber. Because Netscape
486 incorrectly used the raw serial number instead of the DER-encoded form
487 and other applications copied this, we also set up an alternative
488 template with the serial number in this alternative form that we fall
489 back to if a search using the correct form fails */
490
491 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
492 static int initIAndSTemplate( OUT_ARRAY_C( 4 ) CK_ATTRIBUTE *iAndSTemplate,
493 OUT_ARRAY_C( 4 ) CK_ATTRIBUTE *iAndSTemplateAlt,
494 IN_BUFFER( keyIDlength ) const void *keyID,
495 IN_LENGTH_KEYID const int keyIDlength )
496 {
497 static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
498 static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
499 static const CK_ATTRIBUTE initTemplate[] = {
500 { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
501 { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
502 { CKA_ISSUER, NULL_PTR, 0 },
503 { CKA_SERIAL_NUMBER, NULL_PTR, 0 }
504 };
505 STREAM stream;
506 int offset DUMMY_INIT, length, cryptStatus;
507
508 assert( isWritePtr( iAndSTemplate, 4 * sizeof( CK_ATTRIBUTE ) ) );
509 assert( isWritePtr( iAndSTemplateAlt, 4 * sizeof( CK_ATTRIBUTE ) ) );
510 assert( isReadPtr( keyID, keyIDlength ) );
511
512 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
513 keyIDlength < MAX_ATTRIBUTE_SIZE );
514
515 /* Set up the issuerAndSerialNumber template */
516 memcpy( iAndSTemplate, initTemplate, 4 * sizeof( CK_ATTRIBUTE ) );
517 cryptStatus = addIAndSToTemplate( &iAndSTemplate[ 2 ], keyID,
518 keyIDlength );
519 if( cryptStatusError( cryptStatus ) )
520 return( cryptStatus );
521
522 /* Set up the alternate template to the same as the main template, but
523 with the tag and length stripped from the serial number */
524 memcpy( iAndSTemplateAlt, iAndSTemplate, 4 * sizeof( CK_ATTRIBUTE ) );
525 sMemConnect( &stream, iAndSTemplateAlt[ 3 ].pValue,
526 iAndSTemplateAlt[ 3 ].ulValueLen );
527 cryptStatus = readGenericHole( &stream, &length, 1, BER_INTEGER );
528 if( cryptStatusOK( cryptStatus ) )
529 offset = stell( &stream );
530 sMemDisconnect( &stream );
531 if( cryptStatusError( cryptStatus ) )
532 return( cryptStatus );
533 iAndSTemplateAlt[ 3 ].pValue = \
534 ( BYTE * ) iAndSTemplateAlt[ 3 ].pValue + offset;
535 iAndSTemplateAlt[ 3 ].ulValueLen = length;
536
537 return( CRYPT_OK );
538 }
539
540 /****************************************************************************
541 * *
542 * Certificate Import Routines *
543 * *
544 ****************************************************************************/
545
546 /* Instantiate a certificate object from a PKCS #11 object handle */
547
548 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
instantiateCert(INOUT PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hCertificate,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,const BOOLEAN createContext)549 static int instantiateCert( INOUT PKCS11_INFO *pkcs11Info,
550 const CK_OBJECT_HANDLE hCertificate,
551 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
552 const BOOLEAN createContext )
553 {
554 MESSAGE_CREATEOBJECT_INFO createInfo;
555 BYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;
556 int length, cryptStatus;
557
558 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
559 assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );
560
561 /* Clear return value */
562 *iCryptCert = CRYPT_ERROR;
563
564 /* Fetch the certificate data into local memory. We can't use a dynBuf
565 for this because it's a PKCS #11 attribute rather than a cryptlib
566 attribute */
567 cryptStatus = getAttributeValue( pkcs11Info, hCertificate, CKA_VALUE,
568 &bufPtr, &length, buffer,
569 MAX_STACK_BUFFER_SIZE );
570 if( cryptStatusError( cryptStatus ) )
571 return( cryptStatus );
572
573 /* Import the certificate as a cryptlib object */
574 setMessageCreateObjectIndirectInfoEx( &createInfo, bufPtr, length,
575 CRYPT_CERTTYPE_CERTIFICATE, !createContext ? \
576 KEYMGMT_FLAG_DATAONLY_CERT : KEYMGMT_FLAG_NONE );
577 cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
578 IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
579 &createInfo, OBJECT_TYPE_CERTIFICATE );
580 getAttributeValueEnd( bufPtr, buffer );
581 if( cryptStatusOK( cryptStatus ) )
582 *iCryptCert = createInfo.cryptHandle;
583 return( cryptStatus );
584 }
585
586 /* Get a certificate chain from a device */
587
588 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
getCertChain(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,const CK_OBJECT_HANDLE hCertificate,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,const BOOLEAN createContext)589 static int getCertChain( INOUT PKCS11_INFO *pkcs11Info,
590 IN_HANDLE const CRYPT_DEVICE iCertSource,
591 const CK_OBJECT_HANDLE hCertificate,
592 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
593 const BOOLEAN createContext )
594 {
595 CK_ATTRIBUTE idTemplate = \
596 { CKA_ID, NULL_PTR, 0 };
597 CK_RV status;
598 BYTE keyID[ MAX_STACK_BUFFER_SIZE + 8 ];
599
600 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
601 assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );
602
603 REQUIRES( isHandleRangeValid( iCertSource ) );
604
605 /* Clear return value */
606 *iCryptCert = CRYPT_ERROR;
607
608 /* Find the ID for this certificate */
609 status = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,
610 &idTemplate, 1 );
611 if( status == CKR_OK && idTemplate.ulValueLen <= MAX_STACK_BUFFER_SIZE )
612 {
613 idTemplate.pValue = keyID;
614 status = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,
615 &idTemplate, 1 );
616 }
617 if( status != CKR_OK || idTemplate.ulValueLen > MAX_STACK_BUFFER_SIZE )
618 {
619 /* We couldn't get the ID to build the chain or it's too large to be
620 usable, we can at least still return the individual certificate */
621 return( instantiateCert( pkcs11Info, hCertificate, iCryptCert,
622 createContext ) );
623 }
624
625 /* Create the certificate chain via an indirect import */
626 return( iCryptImportCertIndirect( iCryptCert, iCertSource,
627 CRYPT_IKEYID_KEYID, keyID, idTemplate.ulValueLen,
628 createContext ? KEYMGMT_FLAG_DATAONLY_CERT : 0 ) );
629 }
630
631 /****************************************************************************
632 * *
633 * Find-Item Routines *
634 * *
635 ****************************************************************************/
636
637 /* Find an object based on a given template. There are two variations of
638 this, one that finds one and only one object and the other that returns
639 the first object that it finds without treating the presence of multiple
640 objects as an error.
641
642 The way in which this call works has special significance, there are PKCS
643 #11 implementations that don't allow any other calls during the init/find/
644 final sequence so the code is structured to always call them one after
645 the other without any intervening calls. In addition some drivers are
646 confused over whether they're 1.x or 2.x and may or may not implement
647 C_FindObjectsFinal(). Because of this we call it if it exists, if it
648 doesn't then we assume that the driver can handle cleanup itself (this
649 situation shouldn't occur because we've checked for 1.x drivers earlier,
650 but there are one or two drivers where it does happen) */
651
652 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
653 static int findDeviceObjects( INOUT PKCS11_INFO *pkcs11Info,
654 OUT CK_OBJECT_HANDLE *hObject,
655 IN_ARRAY( templateCount ) \
656 const CK_ATTRIBUTE *objectTemplate,
657 IN_RANGE( 1, 64 ) const CK_ULONG templateCount,
658 const BOOLEAN onlyOne )
659 {
660 CK_OBJECT_HANDLE hObjectArray[ 2 + 8 ];
661 CK_ULONG ulObjectCount;
662 CK_RV status;
663
664 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
665 assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
666 assert( isReadPtr( objectTemplate, \
667 sizeof( CK_ATTRIBUTE ) * templateCount ) );
668
669 REQUIRES( templateCount >= 1 && templateCount <= 64 );
670
671 /* Clear return value */
672 *hObject = CK_OBJECT_NONE;
673
674 status = C_FindObjectsInit( pkcs11Info->hSession,
675 ( CK_ATTRIBUTE_PTR ) objectTemplate,
676 templateCount );
677 if( status != CKR_OK )
678 return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
679 status = C_FindObjects( pkcs11Info->hSession, hObjectArray, 2,
680 &ulObjectCount );
681 if( C_FindObjectsFinal != NULL )
682 C_FindObjectsFinal( pkcs11Info->hSession );
683 if( status != CKR_OK )
684 return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
685 if( ulObjectCount <= 0 )
686 return( CRYPT_ERROR_NOTFOUND );
687 if( ulObjectCount > 1 && onlyOne )
688 return( CRYPT_ERROR_DUPLICATE );
689 *hObject = hObjectArray[ 0 ];
690
691 return( CRYPT_OK );
692 }
693
694 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
695 int findObject( INOUT PKCS11_INFO *pkcs11Info,
696 OUT CK_OBJECT_HANDLE *hObject,
697 IN_ARRAY( templateCount ) \
698 const CK_ATTRIBUTE *objectTemplate,
699 IN_RANGE( 1, 64 ) const CK_ULONG templateCount )
700 {
701 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
702 assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
703 assert( isReadPtr( objectTemplate, \
704 sizeof( CK_ATTRIBUTE ) * templateCount ) );
705
706 REQUIRES( templateCount >= 1 && templateCount <= 64 );
707
708 return( findDeviceObjects( pkcs11Info, hObject,
709 objectTemplate, templateCount, TRUE ) );
710 }
711
712 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
713 int findObjectEx( INOUT PKCS11_INFO *pkcs11Info,
714 OUT CK_OBJECT_HANDLE *hObject,
715 IN_ARRAY( templateCount ) \
716 const CK_ATTRIBUTE *objectTemplate,
717 IN_RANGE( 1, 64 ) const CK_ULONG templateCount )
718 {
719 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
720 assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
721 assert( isReadPtr( objectTemplate, \
722 sizeof( CK_ATTRIBUTE ) * templateCount ) );
723
724 REQUIRES( templateCount >= 1 && templateCount <= 64 );
725
726 return( findDeviceObjects( pkcs11Info, hObject,
727 objectTemplate, templateCount, FALSE ) );
728 }
729
730 /* Find an object from a source object by matching IDs. This is used to
731 find a key matching a certificate, a public key matching a private key,
732 or other objects with similar relationships */
733
734 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
findObjectFromObject(INOUT PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hSourceObject,const CK_OBJECT_CLASS objectClass,OUT CK_OBJECT_HANDLE * hObject)735 int findObjectFromObject( INOUT PKCS11_INFO *pkcs11Info,
736 const CK_OBJECT_HANDLE hSourceObject,
737 const CK_OBJECT_CLASS objectClass,
738 OUT CK_OBJECT_HANDLE *hObject )
739 {
740 CK_ATTRIBUTE keyTemplate[] = {
741 { CKA_CLASS, ( CK_VOID_PTR ) &objectClass, sizeof( CK_OBJECT_CLASS ) },
742 { CKA_ID, NULL_PTR, 0 }
743 };
744 BYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;
745 int length, cryptStatus;
746
747 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
748 assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
749
750 /* Clear return value */
751 *hObject = CK_OBJECT_NONE;
752
753 /* We're looking for a key whose ID matches that of the source object,
754 read its certificate ID. We can't use a dynBuf for this because it's
755 a PKCS #11 attribute rather than a cryptlib attribute */
756 cryptStatus = getAttributeValue( pkcs11Info, hSourceObject, CKA_ID,
757 &bufPtr, &length, buffer,
758 MAX_STACK_BUFFER_SIZE );
759 if( cryptStatusError( cryptStatus ) )
760 return( cryptStatus );
761
762 /* Find the key object with the given ID */
763 keyTemplate[ 1 ].pValue = bufPtr;
764 keyTemplate[ 1 ].ulValueLen = length;
765 cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
766 getAttributeValueEnd( bufPtr, buffer );
767
768 return( cryptStatus );
769 }
770
771 /* Find a certificate object based on various search criteria:
772
773 - Find a certificate matching a supplied template - certFromTemplate()
774 - Find a certificate matching a given label - certFromLabel()
775 - Find a certificate matching a given ID - certFromID()
776 - Find a certificate matching the ID of an object hObject - certFromObject()
777 - Find any X.509 certificate - certFromLabel(), no label supplied.
778
779 These are general-purpose functions whose behaviour can be modified through
780 the following action codes */
781
782 typedef enum {
783 FINDCERT_NONE, /* No find-cert flag */
784 FINDCERT_NORMAL, /* Instantiate standard a certificate+context */
785 FINDCERT_DATAONLY, /* Instantiate data-only certificate */
786 FINDCERT_P11OBJECT, /* Return handle to PKCS #11 object */
787 FINDCERT_LAST /* Maximum possible flag value */
788 } FINDCERT_ACTION_TYPE;
789
790 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
791 static int findCertFromTemplate( INOUT PKCS11_INFO *pkcs11Info,
792 IN_HANDLE const CRYPT_DEVICE iCertSource,
793 IN_ARRAY( templateCount ) \
794 const CK_ATTRIBUTE *findTemplate,
795 IN_RANGE( 1, 64 ) const int templateCount,
796 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
797 OUT_OPT CK_OBJECT_HANDLE *hCertificate,
798 IN_ENUM( FINDCERT ) \
799 const FINDCERT_ACTION_TYPE findAction )
800 {
801 CK_OBJECT_HANDLE hFindCertificate;
802 int cryptStatus;
803
804 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
805 assert( isReadPtr( findTemplate, \
806 sizeof( CK_ATTRIBUTE ) * templateCount ) );
807 assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
808 hCertificate == NULL ) || \
809 ( iCryptCert == NULL && \
810 isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
811
812 REQUIRES( isHandleRangeValid( iCertSource ) );
813 REQUIRES( templateCount >= 1 && templateCount <= 64 );
814 REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
815 ( iCryptCert == NULL && hCertificate != NULL ) );
816 REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
817
818 /* Clear return values */
819 if( iCryptCert != NULL )
820 *iCryptCert = CRYPT_ERROR;
821 if( hCertificate != NULL )
822 *hCertificate = CK_OBJECT_NONE;
823
824 /* Try and find the certificate from the given template */
825 cryptStatus = findObject( pkcs11Info, &hFindCertificate, findTemplate,
826 templateCount );
827 if( cryptStatusError( cryptStatus ) )
828 return( cryptStatus );
829 if( findAction == FINDCERT_P11OBJECT )
830 {
831 *hCertificate = hFindCertificate;
832 return( CRYPT_OK );
833 }
834
835 return( getCertChain( pkcs11Info, iCertSource, hFindCertificate, iCryptCert,
836 ( findAction == FINDCERT_NORMAL ) ? TRUE : FALSE ) );
837 }
838
839 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
findCertFromLabel(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,const CK_ATTRIBUTE_TYPE labelType,IN_BUFFER_OPT (labelLength)const char * label,IN_LENGTH_SHORT_Z const int labelLength,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hCertificate,IN_ENUM (FINDCERT)const FINDCERT_ACTION_TYPE findAction)840 static int findCertFromLabel( INOUT PKCS11_INFO *pkcs11Info,
841 IN_HANDLE const CRYPT_DEVICE iCertSource,
842 const CK_ATTRIBUTE_TYPE labelType,
843 IN_BUFFER_OPT( labelLength ) const char *label,
844 IN_LENGTH_SHORT_Z const int labelLength,
845 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
846 OUT_OPT CK_OBJECT_HANDLE *hCertificate,
847 IN_ENUM( FINDCERT ) \
848 const FINDCERT_ACTION_TYPE findAction )
849 {
850 static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
851 static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
852 CK_ATTRIBUTE certTemplate[] = {
853 { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
854 { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
855 { CKA_LABEL, NULL, 0 }
856 };
857
858 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
859 assert( ( label == NULL && labelLength == 0 ) || \
860 isReadPtr( label, labelLength ) );
861 assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
862 hCertificate == NULL ) || \
863 ( iCryptCert == NULL && \
864 isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
865
866 REQUIRES( isHandleRangeValid( iCertSource ) );
867 REQUIRES( ( label == NULL && labelLength == 0 ) || \
868 ( label != NULL && \
869 labelLength > 0 && labelLength < MAX_INTLENGTH_SHORT ) );
870 REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
871 ( iCryptCert == NULL && hCertificate != NULL ) );
872 REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
873
874 /* Clear return values */
875 if( iCryptCert != NULL )
876 *iCryptCert = CRYPT_ERROR;
877 if( hCertificate != NULL )
878 *hCertificate = CK_OBJECT_NONE;
879
880 /* Try and find the certificate with the given label if there's one
881 supplied. Usually this is the CKA_LABEL but it can also be something
882 like a CKA_URL */
883 if( label != NULL )
884 {
885 certTemplate[ 2 ].type = labelType;
886 certTemplate[ 2 ].pValue = ( CK_VOID_PTR ) label;
887 certTemplate[ 2 ].ulValueLen = labelLength;
888 }
889 return( findCertFromTemplate( pkcs11Info, iCertSource, certTemplate,
890 ( label == NULL ) ? 2 : 3, iCryptCert,
891 hCertificate, findAction ) );
892 }
893
894 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
findCertFromID(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,IN_BUFFER (certIDlength)const void * certID,IN_LENGTH_SHORT const int certIDlength,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hCertificate,IN_ENUM (FINDCERT)const FINDCERT_ACTION_TYPE findAction)895 static int findCertFromID( INOUT PKCS11_INFO *pkcs11Info,
896 IN_HANDLE const CRYPT_DEVICE iCertSource,
897 IN_BUFFER( certIDlength ) const void *certID,
898 IN_LENGTH_SHORT const int certIDlength,
899 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
900 OUT_OPT CK_OBJECT_HANDLE *hCertificate,
901 IN_ENUM( FINDCERT ) \
902 const FINDCERT_ACTION_TYPE findAction )
903 {
904 static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
905 static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
906 CK_ATTRIBUTE certTemplate[] = {
907 { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
908 { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
909 { CKA_ID, ( CK_VOID_PTR ) certID, certIDlength }
910 };
911
912 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
913 assert( isReadPtr( certID, certIDlength ) );
914 assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
915 hCertificate == NULL ) || \
916 ( iCryptCert == NULL && \
917 isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
918
919 REQUIRES( isHandleRangeValid( iCertSource ) );
920 REQUIRES( certIDlength > 0 && certIDlength < MAX_INTLENGTH_SHORT );
921 REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
922 ( iCryptCert == NULL && hCertificate != NULL ) );
923 REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
924
925 /* Clear return values */
926 if( iCryptCert != NULL )
927 *iCryptCert = CRYPT_ERROR;
928 if( hCertificate != NULL )
929 *hCertificate = CK_OBJECT_NONE;
930
931 /* Try and find the certificate with the given ID */
932 return( findCertFromTemplate( pkcs11Info, iCertSource, certTemplate, 3,
933 iCryptCert, hCertificate, findAction ) );
934 }
935
936 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
findCertFromObject(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,const CK_OBJECT_HANDLE hObject,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,IN_ENUM (FINDCERT)const FINDCERT_ACTION_TYPE findAction)937 static int findCertFromObject( INOUT PKCS11_INFO *pkcs11Info,
938 IN_HANDLE const CRYPT_DEVICE iCertSource,
939 const CK_OBJECT_HANDLE hObject,
940 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
941 IN_ENUM( FINDCERT ) \
942 const FINDCERT_ACTION_TYPE findAction )
943 {
944 BYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;
945 int length, cryptStatus;
946
947 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
948 assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );
949
950 REQUIRES( isHandleRangeValid( iCertSource ) );
951 REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
952
953 /* Clear return value */
954 *iCryptCert = CRYPT_ERROR;
955
956 /* We're looking for a certificate whose ID matches the object, read the
957 key ID from the device. We can't use a dynBuf for this because it's a
958 PKCS #11 attribute rather than a cryptlib attribute */
959 cryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_ID, &bufPtr,
960 &length, buffer, MAX_STACK_BUFFER_SIZE );
961 if( cryptStatusError( cryptStatus ) )
962 return( cryptStatus );
963
964 /* Look for a certificate with the same ID as the key */
965 cryptStatus = findCertFromID( pkcs11Info, iCertSource, bufPtr, length,
966 iCryptCert, NULL, findAction );
967 getAttributeValueEnd( bufPtr, buffer );
968 return( cryptStatus );
969 }
970
971 /* Find an object using a non-PKCS #11 ID. This is a special-case function
972 that's used in rare situations where only incomplete PKCS #11 format
973 support is available in the underlying device, for example with a token
974 that's been initialised via CryptoAPI (which doesn't populate all of the
975 PKCS #11 fields) but which is now being accessed through a PKCS #11
976 driver. It works by enumerating every object (of the required type,
977 which in this case is only certificates) in the token, creating a
978 cryptlib native object from them, and matching by the ID information
979 provided by cryptlib.
980
981 Since this complex search function is used by both findCert() (which
982 always tries to return a complete certificate chain) and getFirst()/
983 getNext() (which are called indirectly by findCert() and which only
984 require a PKCS #11 certificate object handle to turn into a single
985 standalone certificate) we have to provide a dual-purpose interface,
986 one that returns a certificate chain when called from findCert() and a
987 second one that returns a PKCS #11 certificate object handle when called
988 from getFirst()/getNext() as called by findCert() */
989
990 #ifdef PKCS11_FIND_VIA_CRYPTLIB
991
992 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
matchID(IN_HANDLE CRYPT_CERTIFICATE iCryptCert,IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength)993 static int matchID( IN_HANDLE CRYPT_CERTIFICATE iCryptCert,
994 IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,
995 IN_BUFFER( keyIDlength ) const void *keyID,
996 IN_LENGTH_KEYID const int keyIDlength )
997 {
998 MESSAGE_DATA msgData;
999 char buffer[ MAX_ATTRIBUTE_SIZE + 8 ];
1000 int cryptStatus;
1001
1002 assert( isReadPtr( keyID, keyIDlength ) );
1003
1004 REQUIRES( isHandleRangeValid( iCryptCert ) );
1005 REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1006 keyIDtype == CRYPT_KEYID_URI || \
1007 keyIDtype == CRYPT_IKEYID_KEYID || \
1008 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER || \
1009 keyIDtype == CRYPT_KEYID_NONE );
1010 /* _NONE is by subject DN, i.e. child.issuerDN */
1011 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1012 keyIDlength < MAX_ATTRIBUTE_SIZE );
1013
1014 switch( keyIDtype )
1015 {
1016 case CRYPT_KEYID_NAME:
1017 /* This identifier is usually an arbitrary user-defined label
1018 attached to the object, in the absence of this we use the
1019 certificate CN (or equivalent) as the item to match on. This
1020 is consistent with the use in updateCertificate(), which sets
1021 the holder name as the PKCS #11 label when a new certificate
1022 is added (only explicitly-created public- or private-key
1023 objects have user-defined labels) */
1024 setMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE );
1025 cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
1026 &msgData,
1027 CRYPT_IATTRIBUTE_HOLDERNAME );
1028 if( cryptStatusError( cryptStatus ) )
1029 return( cryptStatus );
1030 if( msgData.length != keyIDlength || \
1031 strCompare( msgData.data, keyID, keyIDlength ) )
1032 return( CRYPT_ERROR_NOTFOUND );
1033 return( CRYPT_OK );
1034
1035 case CRYPT_KEYID_URI:
1036 setMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE );
1037 cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
1038 &msgData,
1039 CRYPT_IATTRIBUTE_HOLDERURI );
1040 if( cryptStatusError( cryptStatus ) )
1041 return( cryptStatus );
1042 if( msgData.length != keyIDlength || \
1043 strCompare( msgData.data, keyID, keyIDlength ) )
1044 return( CRYPT_ERROR_NOTFOUND );
1045 return( CRYPT_OK );
1046
1047 case CRYPT_IKEYID_KEYID:
1048 setMessageData( &msgData, ( void * ) keyID, keyIDlength );
1049 return( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,
1050 MESSAGE_COMPARE_KEYID ) );
1051
1052 case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
1053 setMessageData( &msgData, ( void * ) keyID, keyIDlength );
1054 return( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,
1055 MESSAGE_COMPARE_ISSUERANDSERIALNUMBER ) );
1056
1057 case CRYPT_KEYID_NONE:
1058 /* This is a special-case code to used denote a match of the
1059 subject name, specifically the issuer DN of the child
1060 certificate (which is the next certificate's subject DN) when
1061 chain building */
1062 setMessageData( &msgData, ( void * ) keyID, keyIDlength );
1063 return( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,
1064 MESSAGE_COMPARE_SUBJECT ) );
1065
1066 default:
1067 retIntError();
1068 }
1069 retIntError();
1070 }
1071
1072 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
searchDeviceObjects(INOUT PKCS11_INFO * pkcs11Info,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hObject,IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,const BOOLEAN onlyOne)1073 static int searchDeviceObjects( INOUT PKCS11_INFO *pkcs11Info,
1074 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
1075 OUT_OPT CK_OBJECT_HANDLE *hObject,
1076 IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,
1077 IN_BUFFER( keyIDlength ) const void *keyID,
1078 IN_LENGTH_KEYID const int keyIDlength,
1079 const BOOLEAN onlyOne )
1080 {
1081 static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1082 static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
1083 CK_ATTRIBUTE certTemplate[] = {
1084 { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
1085 { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
1086 };
1087 CK_OBJECT_HANDLE hMatchedObject = CK_OBJECT_NONE;
1088 CK_ULONG ulObjectCount;
1089 CK_RV status;
1090 CRYPT_CERTIFICATE iMatchedCert = CRYPT_ERROR;
1091 BOOLEAN foundMatch = FALSE;
1092 int i, cryptStatus = CRYPT_ERROR_NOTFOUND;
1093
1094 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1095 assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
1096 hObject == NULL ) || \
1097 ( iCryptCert == NULL && \
1098 isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) ) );
1099 assert( isReadPtr( keyID, keyIDlength ) );
1100
1101 REQUIRES( ( iCryptCert != NULL && hObject == NULL ) || \
1102 ( iCryptCert == NULL && hObject != NULL ) );
1103 REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1104 keyIDtype == CRYPT_KEYID_URI || \
1105 keyIDtype == CRYPT_IKEYID_KEYID || \
1106 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER || \
1107 keyIDtype == CRYPT_KEYID_NONE );
1108 /* _NONE is by subject DN, i.e. child.issuerDN */
1109 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1110 keyIDlength < MAX_ATTRIBUTE_SIZE );
1111
1112 /* Clear return values */
1113 if( iCryptCert != NULL )
1114 *iCryptCert = CRYPT_ERROR;
1115 if( hObject != NULL )
1116 *hObject = CK_OBJECT_NONE;
1117
1118 status = C_FindObjectsInit( pkcs11Info->hSession,
1119 ( CK_ATTRIBUTE_PTR ) &certTemplate, 2 );
1120 if( status != CKR_OK )
1121 return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
1122 for( i = 0; i < FAILSAFE_ITERATIONS_LARGE; i++ )
1123 {
1124 CK_OBJECT_HANDLE hMatchObject;
1125 CRYPT_CERTIFICATE iMatchCert;
1126
1127 /* Try and get the next object of the requested type */
1128 status = C_FindObjects( pkcs11Info->hSession, &hMatchObject, 1,
1129 &ulObjectCount );
1130 if( status != CKR_OK )
1131 {
1132 cryptStatus = pkcs11MapError( status, CRYPT_ERROR_NOTFOUND );
1133 break;
1134 }
1135 if( ulObjectCount <= 0 )
1136 {
1137 cryptStatus = CRYPT_ERROR_NOTFOUND;
1138 break;
1139 }
1140
1141 /* Check whether this certificate meets the match criteria. If
1142 we're matching on keyID we have to create the context associated
1143 with the certificate in order to calculate the keyID, otherwise
1144 we use a data-only certificate */
1145 cryptStatus = instantiateCert( pkcs11Info, hMatchObject, &iMatchCert,
1146 ( keyIDtype == CRYPT_IKEYID_KEYID ) ? \
1147 TRUE : FALSE );
1148 if( cryptStatusError( cryptStatus ) )
1149 {
1150 /* We couldn't create a certificate from the stored data, this
1151 is a non-fatal error since there may be more objects present
1152 so we move on to those */
1153 continue;
1154 }
1155 cryptStatus = matchID( iMatchCert, keyIDtype, keyID, keyIDlength );
1156 if( cryptStatusOK( cryptStatus ) && !foundMatch )
1157 {
1158 /* We've found a matching certificate, remember it for later */
1159 hMatchedObject = hMatchObject;
1160 iMatchedCert = iMatchCert;
1161 }
1162 else
1163 krnlSendNotifier( iMatchCert, IMESSAGE_DECREFCOUNT );
1164 if( cryptStatusError( cryptStatus ) )
1165 continue;
1166
1167 /* We've found a matching certificate, if we're looking for a first-
1168 match then we're done */
1169 if( !onlyOne )
1170 break;
1171
1172 /* We're only looking for one matching certificate, if we've found a
1173 second match then this is an error */
1174 if( foundMatch )
1175 {
1176 krnlSendNotifier( iMatchedCert, IMESSAGE_DECREFCOUNT );
1177 iMatchedCert = CRYPT_ERROR;
1178 hMatchedObject = CK_OBJECT_NONE;
1179 cryptStatus = CRYPT_ERROR_DUPLICATE;
1180 break;
1181 }
1182 foundMatch = TRUE;
1183 }
1184 ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
1185 if( C_FindObjectsFinal != NULL )
1186 C_FindObjectsFinal( pkcs11Info->hSession );
1187
1188 /* If we found a matching certificate, return it to the caller. We
1189 can't directly return the status code since the last one encountered
1190 may have been a CRYPT_ERROR_NOTFOUND if we're checking for the
1191 existence of only a single certificate by enumerating all
1192 certificates present */
1193 if( iMatchedCert != CRYPT_ERROR )
1194 {
1195 if( iCryptCert != NULL )
1196 *iCryptCert = iMatchedCert;
1197 else
1198 {
1199 krnlSendNotifier( iMatchedCert, IMESSAGE_DECREFCOUNT );
1200 *hObject = hMatchedObject;
1201 }
1202 return( CRYPT_OK );
1203 }
1204 return( cryptStatus );
1205 }
1206 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1207
1208 /* Umbrella find-a-certificate function */
1209
1210 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
findCert(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hCertificate)1211 static int findCert( INOUT PKCS11_INFO *pkcs11Info,
1212 IN_HANDLE const CRYPT_DEVICE iCertSource,
1213 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1214 IN_BUFFER( keyIDlength ) const void *keyID,
1215 IN_LENGTH_KEYID const int keyIDlength,
1216 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
1217 OUT_OPT CK_OBJECT_HANDLE *hCertificate )
1218 {
1219 CK_ATTRIBUTE iAndSTemplate[ 4 + 8 ], iAndSTemplateAlt[ 4 + 8 ];
1220 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1221 CK_OBJECT_HANDLE hFindCertificate;
1222 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1223 const FINDCERT_ACTION_TYPE findAction = \
1224 ( hCertificate != NULL ) ? FINDCERT_P11OBJECT : FINDCERT_NORMAL;
1225 int cryptStatus;
1226
1227 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1228 assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
1229 hCertificate == NULL ) || \
1230 ( iCryptCert == NULL && \
1231 isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
1232
1233 REQUIRES( isHandleRangeValid( iCertSource ) );
1234 REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1235 keyIDtype == CRYPT_KEYID_URI || \
1236 keyIDtype == CRYPT_IKEYID_KEYID || \
1237 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
1238 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1239 keyIDlength < MAX_ATTRIBUTE_SIZE );
1240 REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
1241 ( iCryptCert == NULL && hCertificate != NULL ) );
1242
1243 /* Clear return values */
1244 if( iCryptCert != NULL )
1245 *iCryptCert = CRYPT_ERROR;
1246 if( hCertificate != NULL )
1247 *hCertificate = CK_OBJECT_NONE;
1248
1249 switch( keyIDtype )
1250 {
1251 case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
1252 cryptStatus = initIAndSTemplate( iAndSTemplate,
1253 iAndSTemplateAlt,
1254 keyID, keyIDlength );
1255 if( cryptStatusError( cryptStatus ) )
1256 return( cryptStatus );
1257 cryptStatus = findCertFromTemplate( pkcs11Info, iCertSource,
1258 iAndSTemplate, 4, iCryptCert,
1259 NULL, findAction );
1260 if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1261 cryptStatus = findCertFromTemplate( pkcs11Info, iCertSource,
1262 iAndSTemplateAlt, 4, iCryptCert,
1263 NULL, findAction );
1264 if( cryptStatusOK( cryptStatus ) )
1265 return( cryptStatus );
1266 break;
1267
1268 case CRYPT_IKEYID_KEYID:
1269 cryptStatus = findCertFromID( pkcs11Info, iCertSource,
1270 keyID, keyIDlength, iCryptCert,
1271 hCertificate, findAction );
1272 if( cryptStatusOK( cryptStatus ) )
1273 return( cryptStatus );
1274 break;
1275
1276 case CRYPT_KEYID_NAME:
1277 case CRYPT_KEYID_URI:
1278 cryptStatus = findCertFromLabel( pkcs11Info, iCertSource,
1279 ( keyIDtype == CRYPT_KEYID_NAME ) ? \
1280 CKA_LABEL : CKA_URL,
1281 keyID, keyIDlength, iCryptCert,
1282 hCertificate, findAction );
1283 if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1284 {
1285 /* Some devices use the iD in place of the label, if a
1286 search by label fails we try again with the label as the
1287 iD */
1288 cryptStatus = findCertFromID( pkcs11Info, iCertSource,
1289 keyID, keyIDlength, iCryptCert,
1290 hCertificate, findAction );
1291 }
1292 if( cryptStatusOK( cryptStatus ) )
1293 return( cryptStatus );
1294 break;
1295
1296 default:
1297 retIntError();
1298 }
1299
1300 /* A standard search has failed, this may be because the necessary PKCS
1301 #11 ID information isn't present in the token, in which case we
1302 optionally try again by performing the search ourselves */
1303 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1304 cryptStatus = searchDeviceObjects( pkcs11Info, NULL, &hFindCertificate,
1305 keyIDtype, keyID, keyIDlength,
1306 TRUE );
1307 if( cryptStatusOK( cryptStatus ) )
1308 {
1309 return( getCertChain( pkcs11Info, iCertSource, hFindCertificate,
1310 iCryptCert,
1311 ( findAction == FINDCERT_NORMAL ) ? \
1312 TRUE : FALSE ) );
1313 }
1314 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1315
1316 return( cryptStatus );
1317 }
1318
1319 /* Find a public- or private-key object. Alongside the standard cryptlib
1320 status code we return an extended information code to handle the
1321 convoluted search strategy required in getItemFunction(), see the
1322 comments inline for the reason for the extra codes */
1323
1324 typedef enum {
1325 FIND_PUBPRIV_NONE, /* No find-cert flag */
1326 FIND_PUBPRIV_CERTVIAKEY,/* Key found via certificate */
1327 FIND_PUBPRIV_KEYVIACERT,/* Certificate found via key */
1328 FIND_PUBPRIV_LAST /* Maximum possible flag value */
1329 } FIND_PUBPRIV_TYPE;
1330
1331 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \
findPubPrivKey(INOUT PKCS11_INFO * pkcs11Info,OUT CK_OBJECT_HANDLE * hObject,OUT CK_OBJECT_HANDLE * hCertificate,OUT_ENUM_OPT (FIND_PUBPRIV)FIND_PUBPRIV_TYPE * findType,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER_OPT (keyIDlength)const void * keyID,IN_LENGTH_KEYID_Z const int keyIDlength,const BOOLEAN isPublicKey)1332 static int findPubPrivKey( INOUT PKCS11_INFO *pkcs11Info,
1333 OUT CK_OBJECT_HANDLE *hObject,
1334 OUT CK_OBJECT_HANDLE *hCertificate,
1335 OUT_ENUM_OPT( FIND_PUBPRIV ) \
1336 FIND_PUBPRIV_TYPE *findType,
1337 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1338 IN_BUFFER_OPT( keyIDlength ) const void *keyID,
1339 IN_LENGTH_KEYID_Z const int keyIDlength,
1340 const BOOLEAN isPublicKey )
1341 {
1342 static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
1343 static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
1344 CK_ATTRIBUTE keyTemplate[] = {
1345 { CKA_CLASS, ( CK_VOID_PTR ) \
1346 ( isPublicKey ? &pubkeyClass : &privkeyClass ),
1347 sizeof( CK_OBJECT_CLASS ) },
1348 { CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
1349 };
1350 int cryptStatus;
1351
1352 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1353 assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
1354 assert( isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) );
1355 assert( isWritePtr( findType, sizeof( FIND_PUBPRIV_TYPE ) ) );
1356 assert( isReadPtr( keyID, keyIDlength ) );
1357
1358 REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1359 keyIDtype == CRYPT_KEYID_URI || \
1360 keyIDtype == CRYPT_IKEYID_KEYID );
1361 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1362 keyIDlength < MAX_ATTRIBUTE_SIZE );
1363
1364 /* Clear return values */
1365 *hObject = CK_OBJECT_NONE;
1366 *hCertificate = CK_OBJECT_NONE;
1367 *findType = FIND_PUBPRIV_NONE;
1368
1369 /* Try and find the object with the given label/ID, or the first object
1370 of the given class if no ID is given */
1371 if( keyIDtype == CRYPT_IKEYID_KEYID )
1372 keyTemplate[ 1 ].type = CKA_ID;
1373 cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
1374 if( cryptStatus != CRYPT_ERROR_NOTFOUND )
1375 return( cryptStatus );
1376
1377 /* Some devices use the iD in place of the label, if we're doing a
1378 search by label and it fails then we try again with the label as
1379 the iD */
1380 if( keyIDtype == CRYPT_KEYID_NAME )
1381 {
1382 keyTemplate[ 1 ].type = CKA_ID;
1383 cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
1384 keyTemplate[ 1 ].type = CKA_LABEL;
1385 if( cryptStatus != CRYPT_ERROR_NOTFOUND )
1386 return( cryptStatus );
1387 }
1388
1389 /* Some devices may only contain private key objects with associated
1390 certificates that can't be picked out of the other cruft that's
1391 present without going via the private key, so if we're looking for a
1392 public key and don't find one we try again for a private key whose
1393 sole function is to point to an associated certificate */
1394 if( isPublicKey )
1395 {
1396 keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
1397 cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
1398 if( cryptStatusError( cryptStatus ) )
1399 return( cryptStatus );
1400
1401 /* Tell the caller that although we've got a private key object we
1402 only need it to find the associated certificate and not finding
1403 an associated certificate is an error */
1404 *findType = FIND_PUBPRIV_CERTVIAKEY;
1405
1406 return( CRYPT_OK );
1407 }
1408
1409 /* A standard search has failed, this may be because the necessary PKCS
1410 #11 ID information isn't present in the token, in which case we
1411 optionally try again by performing the search ourselves */
1412 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1413 cryptStatus = searchDeviceObjects( pkcs11Info, NULL, hCertificate,
1414 keyIDtype, keyID, keyIDlength, TRUE );
1415 if( cryptStatusError( cryptStatus ) )
1416 return( cryptStatus );
1417
1418 /* We've found the identified certificate, use it to find the
1419 corresponding private key */
1420 cryptStatus = findObjectFromObject( pkcs11Info, *hCertificate,
1421 CKO_PRIVATE_KEY, hObject );
1422 if( cryptStatusError( cryptStatus ) )
1423 return( cryptStatus );
1424
1425 /* Tell the caller that we've already got a certificate to attach to
1426 the private key */
1427 *findType = FIND_PUBPRIV_KEYVIACERT;
1428
1429 return( CRYPT_OK );
1430 #else
1431 return( CRYPT_ERROR_NOTFOUND );
1432 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1433 }
1434
1435 /****************************************************************************
1436 * *
1437 * Read an Item from a Device *
1438 * *
1439 ****************************************************************************/
1440
1441 /* Set public-key information (in the form of the SubjectPublicKeyInfo) for
1442 a native object */
1443
1444 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setPublicComponents(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_CONTEXT iCryptContext,const CK_OBJECT_HANDLE hObject,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,const BOOLEAN isPrivateKey,const BOOLEAN nativeContext)1445 static int setPublicComponents( INOUT PKCS11_INFO *pkcs11Info,
1446 IN_HANDLE const CRYPT_CONTEXT iCryptContext,
1447 const CK_OBJECT_HANDLE hObject,
1448 IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
1449 const BOOLEAN isPrivateKey,
1450 const BOOLEAN nativeContext )
1451 {
1452 CK_OBJECT_HANDLE hPubKeyObject DUMMY_INIT;
1453 int cryptStatus;
1454
1455 /* If it's an RSA object then we can set the public components from it
1456 directly */
1457 if( cryptAlgo == CRYPT_ALGO_RSA )
1458 return( rsaSetPublicComponents( pkcs11Info, iCryptContext, hObject,
1459 nativeContext ) );
1460
1461 /* If we're creating a private-key object then we need to be able to set
1462 the SubjectPublicKeyInfo for it. Only RSA allows us to access the
1463 public-key components from a private-key object, for everything else
1464 we need to locate a corresponding public-key object in order to get
1465 the public-key components */
1466 if( isPrivateKey )
1467 {
1468 cryptStatus = findObjectFromObject( pkcs11Info, hObject,
1469 CKO_PUBLIC_KEY, &hPubKeyObject );
1470 if( cryptStatusError( cryptStatus ) )
1471 return( cryptStatus );
1472 }
1473
1474 /* Send the SubjectPublicKey information to the context */
1475 switch( cryptAlgo )
1476 {
1477 case CRYPT_ALGO_DSA:
1478 return( dsaSetPublicComponents( pkcs11Info, iCryptContext,
1479 hPubKeyObject,
1480 nativeContext ) );
1481
1482 #if defined( USE_ECDSA )
1483 case CRYPT_ALGO_ECDSA:
1484 return( ecdsaSetPublicComponents( pkcs11Info, iCryptContext,
1485 hPubKeyObject,
1486 nativeContext ) );
1487 #endif /* USE_ECDSA */
1488 }
1489
1490 return( CRYPT_ERROR_NOTAVAIL );
1491 }
1492
1493 /* Instantiate an object in a device. This works like the create context
1494 function but instantiates a cryptlib object using data already contained
1495 in the device (for example public-key components stored with a private
1496 key or a stored certificate) */
1497
1498 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
createNativeObject(INOUT PKCS11_INFO * pkcs11Info,OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,const CK_OBJECT_HANDLE hObject,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo)1499 static int createNativeObject( INOUT PKCS11_INFO *pkcs11Info,
1500 OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
1501 const CK_OBJECT_HANDLE hObject,
1502 IN_ENUM( KEYMGMT_ITEM ) \
1503 const KEYMGMT_ITEM_TYPE itemType,
1504 IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
1505 {
1506 CRYPT_CONTEXT iLocalContext;
1507 MESSAGE_CREATEOBJECT_INFO createInfo;
1508 int actionFlags, cryptStatus;
1509
1510 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1511 assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
1512
1513 REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1514 itemType == KEYMGMT_ITEM_PRIVATEKEY || \
1515 itemType == KEYMGMT_ITEM_SECRETKEY );
1516 REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
1517 cryptAlgo <= CRYPT_ALGO_LAST_MAC );
1518
1519 /* Clear return value */
1520 *iCryptContext = CRYPT_ERROR;
1521
1522 /* Get the permitted-action flags for the object. If no usage is
1523 allowed then we can't do anything with the object so we don't even
1524 try and create it */
1525 actionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );
1526 if( actionFlags <= 0 )
1527 return( CRYPT_ERROR_PERMISSION );
1528
1529 /* We're creating a public-key context, make it a native context instead
1530 of a device one. This solves a variety of problems including the
1531 fact that some devices (which function purely as key stores coupled
1532 to modexp accelerators) only support private-key operations, that
1533 performing public-key operations natively is much, much faster than
1534 on any token, and finally that if we do it ourselves we can defend
1535 against a variety of RSA padding and timing attacks that have come up
1536 since the device firmware was done */
1537 setMessageCreateObjectInfo( &createInfo, cryptAlgo );
1538 cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
1539 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
1540 OBJECT_TYPE_CONTEXT );
1541 if( cryptStatusError( cryptStatus ) )
1542 return( cryptStatus );
1543 iLocalContext = createInfo.cryptHandle;
1544
1545 /* Send the SubjectPublicKeyInfo and action permissions for the
1546 context */
1547 cryptStatus = setPublicComponents( pkcs11Info, iLocalContext, hObject,
1548 cryptAlgo,
1549 ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
1550 TRUE : FALSE, TRUE );
1551 if( cryptStatusOK( cryptStatus ) )
1552 {
1553 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1554 &actionFlags,
1555 CRYPT_IATTRIBUTE_ACTIONPERMS );
1556 }
1557 if( cryptStatusError( cryptStatus ) )
1558 {
1559 krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1560 return( cryptStatus );
1561 }
1562 *iCryptContext = iLocalContext;
1563
1564 return( CRYPT_OK );
1565 }
1566
1567 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 7 ) ) \
createDeviceObject(INOUT PKCS11_INFO * pkcs11Info,OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,const CK_OBJECT_HANDLE hObject,IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,IN_HANDLE const CRYPT_USER iOwnerHandle,IN_HANDLE const CRYPT_DEVICE iDeviceHandle,const CAPABILITY_INFO * capabilityInfoPtr,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,IN_RANGE (MIN_KEYSIZE,CRYPT_MAX_PKCSIZE)const int keySize)1568 static int createDeviceObject( INOUT PKCS11_INFO *pkcs11Info,
1569 OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
1570 const CK_OBJECT_HANDLE hObject,
1571 IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,
1572 IN_HANDLE const CRYPT_USER iOwnerHandle,
1573 IN_HANDLE const CRYPT_DEVICE iDeviceHandle,
1574 const CAPABILITY_INFO *capabilityInfoPtr,
1575 IN_ENUM( KEYMGMT_ITEM ) \
1576 const KEYMGMT_ITEM_TYPE itemType,
1577 IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
1578 IN_RANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) \
1579 const int keySize )
1580 {
1581 CRYPT_CONTEXT iLocalContext;
1582 MESSAGE_DATA msgData;
1583 char label[ CRYPT_MAX_TEXTSIZE + 8 ];
1584 int createFlags = CREATEOBJECT_FLAG_DUMMY;
1585 int actionFlags, labelLength, cryptStatus;
1586
1587 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1588 assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
1589 assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );
1590
1591 REQUIRES( ( iCryptCert == CRYPT_UNUSED ) || \
1592 isHandleRangeValid( iCryptCert ) );
1593 REQUIRES( iOwnerHandle == DEFAULTUSER_OBJECT_HANDLE || \
1594 isHandleRangeValid( iOwnerHandle ) );
1595 REQUIRES( isHandleRangeValid( iDeviceHandle ) );
1596 REQUIRES( itemType == KEYMGMT_ITEM_PRIVATEKEY || \
1597 itemType == KEYMGMT_ITEM_SECRETKEY );
1598 REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
1599 cryptAlgo <= CRYPT_ALGO_LAST_MAC );
1600 REQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_PKCSIZE );
1601
1602 /* Clear return value */
1603 *iCryptContext = CRYPT_ERROR;
1604
1605 /* Check whether this is a persistent object */
1606 if( readFlag( pkcs11Info, hObject, CKA_TOKEN ) )
1607 createFlags |= CREATEOBJECT_FLAG_PERSISTENT;
1608
1609 /* Get the permitted-action flags for the object */
1610 actionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );
1611 if( actionFlags <= 0 )
1612 {
1613 /* If no usage is allowed then we can't do anything with the object
1614 so we don't even try to create it */
1615 return( CRYPT_ERROR_PERMISSION );
1616 }
1617
1618 /* Create a dummy context for the key and remember the device that it's
1619 contained in */
1620 cryptStatus = getObjectLabel( pkcs11Info, hObject, label,
1621 CRYPT_MAX_TEXTSIZE, &labelLength );
1622 if( cryptStatusError( cryptStatus ) )
1623 return( cryptStatus );
1624 if( labelLength <= 0 )
1625 {
1626 /* If there's no label present, use a dummy value */
1627 strlcpy_s( label, CRYPT_MAX_TEXTSIZE, "Label-less PKCS #11 key" );
1628 labelLength = 23;
1629 }
1630 cryptStatus = createContextFromCapability( &iLocalContext,
1631 iOwnerHandle, capabilityInfoPtr,
1632 createFlags | CREATEOBJECT_FLAG_PERSISTENT );
1633 if( cryptStatusError( cryptStatus ) )
1634 return( cryptStatus );
1635 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,
1636 ( MESSAGE_CAST ) &iDeviceHandle,
1637 SETDEP_OPTION_INCREF );
1638 if( cryptStatusOK( cryptStatus ) )
1639 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1640 &actionFlags,
1641 CRYPT_IATTRIBUTE_ACTIONPERMS );
1642 if( cryptStatusError( cryptStatus ) )
1643 {
1644 krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1645 return( cryptStatus );
1646 }
1647
1648 /* Set the object's label. This requires special care because the label
1649 that we're setting matches that of an existing object so trying to
1650 set it as a standard CRYPT_CTXINFO_LABEL will return a
1651 CRYPT_ERROR_DUPLICATE error when the context code checks for the
1652 existence of an existing label. To handle this we use the attribute
1653 CRYPT_IATTRIBUTE_EXISTINGLABEL to indicate that we're setting a label
1654 that matches an existing object in the device */
1655 setMessageData( &msgData, label, min( labelLength, CRYPT_MAX_TEXTSIZE ) );
1656 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,
1657 &msgData, CRYPT_IATTRIBUTE_EXISTINGLABEL );
1658 if( cryptStatusError( cryptStatus ) )
1659 {
1660 krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1661 return( cryptStatus );
1662 }
1663
1664 /* Send the keying information to the context. For non-PKC contexts we
1665 only need to set the key length to let the user query the key size,
1666 for PKC contexts we also have to set the key components so that they
1667 can be written into certificates */
1668 if( isPkcAlgo( cryptAlgo ) )
1669 {
1670 cryptStatus = setPublicComponents( pkcs11Info, iLocalContext,
1671 hObject, cryptAlgo, TRUE, FALSE );
1672 }
1673 else
1674 {
1675 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1676 ( MESSAGE_CAST ) &keySize,
1677 CRYPT_IATTRIBUTE_KEYSIZE );
1678 }
1679 if( cryptStatusError( cryptStatus ) )
1680 {
1681 krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1682 return( cryptStatus );
1683 }
1684
1685 /* Finally, record the handle for the device-internal key and mark it as
1686 initialised (i.e. with a key loaded) */
1687 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1688 ( MESSAGE_CAST ) &hObject,
1689 CRYPT_IATTRIBUTE_DEVICEOBJECT );
1690 if( cryptStatusOK( cryptStatus ) )
1691 {
1692 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1693 MESSAGE_VALUE_UNUSED,
1694 CRYPT_IATTRIBUTE_INITIALISED );
1695 }
1696 if( cryptStatusOK( cryptStatus ) && ( iCryptCert != CRYPT_UNUSED ) )
1697 {
1698 /* If it's a public key and there's a certificate present attach it
1699 to the context. The certificate is an internal object used only
1700 by the context so we tell the kernel to mark it as owned by the
1701 context only */
1702 cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,
1703 ( MESSAGE_CAST ) &iCryptCert,
1704 SETDEP_OPTION_NOINCREF );
1705 }
1706 if( cryptStatusError( cryptStatus ) )
1707 {
1708 krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1709 return( cryptStatus );
1710 }
1711 *iCryptContext = iLocalContext;
1712
1713 return( CRYPT_OK );
1714 }
1715
1716 /* Get an item from a device and instantiate either a native or a device
1717 object from it */
1718
1719 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
getSecretKey(INOUT DEVICE_INFO * deviceInfo,INOUT PKCS11_INFO * pkcs11Info,OUT_HANDLE_OPT CRYPT_HANDLE * iCryptHandle,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,IN_FLAGS_Z (KEYMGMT)const int flags)1720 static int getSecretKey( INOUT DEVICE_INFO *deviceInfo,
1721 INOUT PKCS11_INFO *pkcs11Info,
1722 OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
1723 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1724 IN_BUFFER( keyIDlength ) const void *keyID,
1725 IN_LENGTH_KEYID const int keyIDlength,
1726 IN_FLAGS_Z( KEYMGMT ) const int flags )
1727 {
1728 static const CK_OBJECT_CLASS secKeyClass = CKO_SECRET_KEY;
1729 const CAPABILITY_INFO *capabilityInfoPtr;
1730 CK_ULONG secKeySize DUMMY_INIT;
1731 CK_ATTRIBUTE keyTemplate[] = {
1732 { CKA_CLASS, ( CK_VOID_PTR ) &secKeyClass, sizeof( CK_OBJECT_CLASS ) },
1733 { CKA_LABEL, NULL_PTR, 0 }
1734 };
1735 CK_ATTRIBUTE secKeySizeTemplate = \
1736 { CKA_VALUE_LEN, &secKeySize, sizeof( CK_ULONG ) };
1737 CK_OBJECT_HANDLE hObject = CK_OBJECT_NONE;
1738 CRYPT_ALGO_TYPE cryptAlgo;
1739 int status, cryptStatus;
1740
1741 assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
1742 assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1743 assert( isWritePtr( iCryptHandle, sizeof( CRYPT_CONTEXT ) ) );
1744 assert( isReadPtr( keyID, keyIDlength ) );
1745
1746 REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1747 keyIDtype == CRYPT_IKEYID_KEYID );
1748 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1749 keyIDlength < MAX_ATTRIBUTE_SIZE );
1750 REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
1751
1752 /* Clear return value */
1753 *iCryptHandle = CRYPT_ERROR;
1754
1755 /* Try and find the object with the given label/ID */
1756 if( keyIDtype == CRYPT_IKEYID_KEYID )
1757 keyTemplate[ 1 ].type = CKA_ID;
1758 keyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;
1759 keyTemplate[ 1 ].ulValueLen = keyIDlength;
1760 cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
1761 if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1762 {
1763 /* Some devices use the iD in place of the label, if a search by
1764 label fails we try again with the label as the iD */
1765 keyTemplate[ 1 ].type = CKA_ID;
1766 cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
1767 }
1768 if( cryptStatusError( cryptStatus ) )
1769 return( cryptStatus );
1770
1771 /* If it's just an existence check, return now */
1772 if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1773 return( CRYPT_OK );
1774
1775 /* We found something, map the key type to a cryptlib algorithm ID and
1776 find its capabilities */
1777 cryptStatus = getMechanismInfo( pkcs11Info, hObject,
1778 deviceInfo->capabilityInfoList,
1779 FALSE, &capabilityInfoPtr,
1780 &cryptAlgo );
1781 if( cryptStatusError( cryptStatus ) )
1782 return( cryptStatus );
1783 status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
1784 &secKeySizeTemplate, 1 );
1785 if( status != CKR_OK )
1786 return( pkcs11MapError( status, CRYPT_ERROR_NOTINITED ) );
1787 ENSURES( secKeySize >= MIN_KEYSIZE && \
1788 secKeySize <= CRYPT_MAX_KEYSIZE );
1789
1790 /* Create the object as a device object */
1791 return( createDeviceObject( pkcs11Info, iCryptHandle, hObject,
1792 CRYPT_UNUSED, deviceInfo->ownerHandle,
1793 deviceInfo->objectHandle, capabilityInfoPtr,
1794 KEYMGMT_ITEM_SECRETKEY, cryptAlgo,
1795 secKeySize ) );
1796 }
1797
1798 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 8 ) ) \
getItemFunction(INOUT DEVICE_INFO * deviceInfo,OUT_HANDLE_OPT CRYPT_HANDLE * iCryptHandle,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,IN_OPT void * auxInfo,INOUT_LENGTH_SHORT_Z int * auxInfoLength,IN_FLAGS_Z (KEYMGMT)const int flags)1799 static int getItemFunction( INOUT DEVICE_INFO *deviceInfo,
1800 OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
1801 IN_ENUM( KEYMGMT_ITEM ) \
1802 const KEYMGMT_ITEM_TYPE itemType,
1803 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1804 IN_BUFFER( keyIDlength ) const void *keyID,
1805 IN_LENGTH_KEYID const int keyIDlength,
1806 IN_OPT void *auxInfo,
1807 INOUT_LENGTH_SHORT_Z int *auxInfoLength,
1808 IN_FLAGS_Z( KEYMGMT ) const int flags )
1809 {
1810 static const MAP_TABLE keySizeMapTbl[] = {
1811 { CRYPT_ALGO_RSA, CKA_MODULUS },
1812 { CRYPT_ALGO_DSA, CKA_PRIME },
1813 { CRYPT_ALGO_DH, CKA_PRIME },
1814 { CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
1815 };
1816 const CAPABILITY_INFO *capabilityInfoPtr;
1817 CK_ATTRIBUTE keySizeTemplate = { 0, NULL, 0 };
1818 CK_OBJECT_HANDLE hObject = CK_OBJECT_NONE, hCertificate = CK_OBJECT_NONE;
1819 CK_RV status;
1820 CRYPT_CERTIFICATE iCryptCert DUMMY_INIT;
1821 CRYPT_ALGO_TYPE cryptAlgo;
1822 PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
1823 BOOLEAN certViaPrivateKey = FALSE, privateKeyViaCert = FALSE;
1824 BOOLEAN certPresent = FALSE;
1825 int keySize DUMMY_INIT, cryptStatus;
1826
1827 assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
1828 assert( isWritePtr( iCryptHandle, sizeof( CRYPT_CONTEXT ) ) );
1829 assert( isReadPtr( keyID, keyIDlength ) );
1830 assert( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
1831 isReadPtr( auxInfo, *auxInfoLength ) );
1832
1833 REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1834 itemType == KEYMGMT_ITEM_PRIVATEKEY || \
1835 itemType == KEYMGMT_ITEM_SECRETKEY );
1836 REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1837 keyIDtype == CRYPT_KEYID_URI || \
1838 keyIDtype == CRYPT_IKEYID_KEYID || \
1839 keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
1840 REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1841 keyIDlength < MAX_ATTRIBUTE_SIZE );
1842 REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
1843 ( auxInfo != NULL && \
1844 *auxInfoLength > 0 && \
1845 *auxInfoLength < MAX_INTLENGTH_SHORT ) );
1846 REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
1847
1848 /* Clear return value */
1849 *iCryptHandle = CRYPT_ERROR;
1850
1851 /* If we're looking for a secret key then it's fairly straightforward */
1852 if( itemType == KEYMGMT_ITEM_SECRETKEY )
1853 {
1854 return( getSecretKey( deviceInfo, pkcs11Info, iCryptHandle,
1855 keyIDtype, keyID, keyIDlength, flags ) );
1856 }
1857
1858 /* If we're looking for a public key, try for a certificate first. Some
1859 non-crypto-capable devices don't have an explicit CKO_PUBLIC_KEY but
1860 only a CKO_CERTIFICATE and some apps delete the public key since it's
1861 redundant, so we try to create a certificate object before we try
1862 anything else. If the keyID type is an ID or label then this won't
1863 necessarily locate the certificate since it could be unlabelled or
1864 have a different label/ID, so if this fails we try again by going via
1865 the private key with the given label/ID */
1866 if( itemType == KEYMGMT_ITEM_PUBLICKEY )
1867 {
1868 CK_OBJECT_HANDLE hCertificateLabelObject DUMMY_INIT;
1869
1870 if( flags & ( KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY ) )
1871 {
1872 cryptStatus = findCert( pkcs11Info, deviceInfo->objectHandle,
1873 keyIDtype, keyID, keyIDlength, NULL,
1874 &hCertificateLabelObject );
1875 }
1876 else
1877 {
1878 cryptStatus = findCert( pkcs11Info, deviceInfo->objectHandle,
1879 keyIDtype, keyID, keyIDlength,
1880 &iCryptCert, NULL );
1881 }
1882 if( cryptStatusOK( cryptStatus ) )
1883 {
1884 /* If we're just checking whether an object exists, return now.
1885 If all we want is the key label, copy it back to the caller
1886 and exit */
1887 if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1888 return( CRYPT_OK );
1889 if( flags & KEYMGMT_FLAG_LABEL_ONLY )
1890 {
1891 return( getObjectLabel( pkcs11Info, hCertificateLabelObject,
1892 auxInfo, *auxInfoLength,
1893 auxInfoLength ) );
1894 }
1895 *iCryptHandle = iCryptCert;
1896
1897 return( CRYPT_OK );
1898 }
1899
1900 /* If we're looking for a specific match on a certificate (rather
1901 than just a general public key) and we don't find anything, exit
1902 now */
1903 if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
1904 return( cryptStatus );
1905 }
1906
1907 /* Either there were no certificates found or we're looking for a
1908 private key (or, somewhat unusually, a raw public key). At this
1909 point we can approach the problem from one of two sides, if we've
1910 got an issuerAndSerialNumber we have to find the matching certificate
1911 and get the key from that, otherwise we find the key and get the
1912 certificate from that */
1913 if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
1914 {
1915 CK_ATTRIBUTE iAndSTemplate[ 4 + 8 ], iAndSTemplateAlt[ 4 + 8 ];
1916
1917 /* Try and find the certificate from the given template. Note that
1918 we can't use findCert() for this because it returns a cryptlib
1919 certificate and not a PKCS #11 object handle */
1920 cryptStatus = initIAndSTemplate( iAndSTemplate, iAndSTemplateAlt,
1921 keyID, keyIDlength );
1922 if( cryptStatusError( cryptStatus ) )
1923 return( cryptStatus );
1924 cryptStatus = findObject( pkcs11Info, &hCertificate,
1925 iAndSTemplate, 4 );
1926 if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1927 cryptStatus = findObject( pkcs11Info, &hCertificate,
1928 iAndSTemplateAlt, 4 );
1929 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1930 if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1931 {
1932 cryptStatus = searchDeviceObjects( pkcs11Info, NULL,
1933 &hCertificate, keyIDtype,
1934 keyID, keyIDlength, TRUE );
1935 }
1936 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1937 if( cryptStatusOK( cryptStatus ) )
1938 {
1939 /* We've found the identified certificate, use it to find the
1940 corresponding private key */
1941 cryptStatus = findObjectFromObject( pkcs11Info, hCertificate,
1942 CKO_PRIVATE_KEY, &hObject );
1943 if( cryptStatusError( cryptStatus ) )
1944 return( cryptStatus );
1945
1946 /* Remember that we've already got a certificate to attach to
1947 the private key */
1948 privateKeyViaCert = TRUE;
1949 }
1950 else
1951 {
1952 /* If we didn't find anything it may be because whoever set up
1953 the token didn't set the iAndS rather than because there's no
1954 key there so we only bail out if we got some unexpected type
1955 of error */
1956 if( cryptStatus != CRYPT_ERROR_NOTFOUND )
1957 return( cryptStatus );
1958 }
1959 }
1960 else
1961 {
1962 FIND_PUBPRIV_TYPE findType;
1963
1964 cryptStatus = findPubPrivKey( pkcs11Info, &hObject, &hCertificate,
1965 &findType, keyIDtype, keyID, keyIDlength,
1966 ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
1967 TRUE : FALSE );
1968 if( cryptStatusError( cryptStatus ) )
1969 return( cryptStatus );
1970 switch( findType )
1971 {
1972 case FIND_PUBPRIV_NONE:
1973 /* No special handling */
1974 break;
1975
1976 case FIND_PUBPRIV_CERTVIAKEY:
1977 /* Remember that although we've got a private key object, we
1978 only need it to find the associated certificate and not
1979 finding an associated certificate is an error */
1980 certViaPrivateKey = TRUE;
1981 break;
1982
1983 case FIND_PUBPRIV_KEYVIACERT:
1984 /* Remember that we've already got a certificate to attach
1985 to the private key */
1986 privateKeyViaCert = TRUE;
1987 break;
1988
1989 default:
1990 retIntError();
1991 }
1992 }
1993
1994 /* If we're looking for any kind of private key and we either have an
1995 explicit certificate ID but couldn't find a certificate for it or we
1996 don't have a proper ID to search on and a generic search found more
1997 than one matching object, chances are that we're after a generic
1998 decrypt key. The former only occurs in misconfigured or limited-
1999 memory tokens, the latter only in rare tokens that store more than
2000 one private key, typically one for signing and one for verification.
2001
2002 If either of these cases occur then we try again looking specifically
2003 for a decryption key. Even this doesn't always work, there are some
2004 >1-key tokens that mark a signing key as a decryption key so we still
2005 get a CRYPT_ERROR_DUPLICATE error.
2006
2007 Finally, if we can't find a decryption key either, we look for an
2008 unwrapping key. This may or may not work depending on whether we
2009 have a decryption key marked as valid for unwrapping but not
2010 decryption or a key that's genuinely only valid for unwrapping, but
2011 at this point we're ready to try anything */
2012 if( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
2013 ( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
2014 cryptStatus == CRYPT_ERROR_NOTFOUND ) || \
2015 ( cryptStatus == CRYPT_ERROR_DUPLICATE ) )
2016 {
2017 static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
2018 static const CK_BBOOL bTrue = TRUE;
2019 CK_ATTRIBUTE decryptKeyTemplate[] = {
2020 { CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
2021 { CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }
2022 };
2023
2024 cryptStatus = findObject( pkcs11Info, &hObject,
2025 decryptKeyTemplate, 2 );
2026 if( cryptStatusError( cryptStatus ) && \
2027 cryptStatus != CRYPT_ERROR_DUPLICATE )
2028 {
2029 decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
2030 cryptStatus = findObject( pkcs11Info, &hObject,
2031 decryptKeyTemplate, 2 );
2032 }
2033 }
2034 if( cryptStatusError( cryptStatus ) )
2035 return( cryptStatus );
2036
2037 /* Sanity check that we actually found something */
2038 ENSURES( hObject != CK_OBJECT_NONE );
2039
2040 /* If we're just checking whether an object exists, return now. If all
2041 we want is the key label, copy it back to the caller and exit */
2042 if( flags & KEYMGMT_FLAG_CHECK_ONLY )
2043 return( CRYPT_OK );
2044 if( flags & KEYMGMT_FLAG_LABEL_ONLY )
2045 return( getObjectLabel( pkcs11Info, hObject, auxInfo, *auxInfoLength,
2046 auxInfoLength ) );
2047
2048 /* We found something, map the key type to a cryptlib algorithm ID,
2049 determine the key size, and find its capabilities */
2050 cryptStatus = getMechanismInfo( pkcs11Info, hObject,
2051 deviceInfo->capabilityInfoList,
2052 TRUE, &capabilityInfoPtr, &cryptAlgo );
2053 if( cryptStatusError( cryptStatus ) )
2054 return( cryptStatus );
2055 #if defined( USE_ECDH ) || defined( USE_ECDSA )
2056 if( isEccAlgo( cryptAlgo ) )
2057 {
2058 CRYPT_ECCCURVE_TYPE curveType;
2059
2060 /* Get the field size for the named curve */
2061 cryptStatus = getEccCurveType( pkcs11Info, hObject, &curveType );
2062 if( cryptStatusOK( cryptStatus ) )
2063 cryptStatus = getECCFieldSize( curveType, &keySize, FALSE );
2064 if( cryptStatusError( cryptStatus ) )
2065 return( cryptStatus );
2066 }
2067 else
2068 #endif /* USE_ECDH || USE_ECDSA */
2069 {
2070 cryptStatus = mapValue( cryptAlgo, &keySize, keySizeMapTbl,
2071 FAILSAFE_ARRAYSIZE( keySizeMapTbl, MAP_TABLE ) );
2072 if( cryptStatusError( cryptStatus ) )
2073 {
2074 /* This can happen if the object that we're fetching uses an
2075 unknown or non-PKC algorithm */
2076 return( cryptStatus );
2077 }
2078 keySizeTemplate.type = keySize; /* For int vs. enum */
2079 status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
2080 &keySizeTemplate, 1 );
2081 if( status != CKR_OK )
2082 return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
2083 keySize = keySizeTemplate.ulValueLen;
2084 }
2085 ENSURES( keySize >= MIN_PKCSIZE_ECC && \
2086 keySize <= CRYPT_MAX_PKCSIZE );
2087
2088 /* Try and find a certificate that matches the key. The process is as
2089 follows:
2090
2091 if certificate object found in issuerAndSerialNumber search
2092 -- Implies key == private key
2093 create native data-only certificate object
2094 attach certificate object to key
2095 else
2096 {
2097 if public key read
2098 {
2099 if certificate
2100 create native certificate (+context) object
2101 else
2102 create context object
2103 }
2104 else
2105 {
2106 create device privkey object, mark as "key loaded"
2107 if certificate
2108 create native data-only certificate object
2109 attach certificate object to key
2110 }
2111 }
2112
2113 The reason for doing things this way is given in the comments earlier
2114 on in this function */
2115 if( privateKeyViaCert )
2116 {
2117 /* Sanity check that we actually found a certificate */
2118 REQUIRES( hCertificate != CK_OBJECT_NONE );
2119
2120 /* We've already got the certificate object handle, instantiate a
2121 native data-only certificate from it */
2122 cryptStatus = getCertChain( pkcs11Info, deviceInfo->objectHandle,
2123 hCertificate, &iCryptCert, FALSE );
2124 if( cryptStatusError( cryptStatus ) )
2125 return( cryptStatus );
2126 certPresent = TRUE;
2127 }
2128 else
2129 {
2130 cryptStatus = findCertFromObject( pkcs11Info, deviceInfo->objectHandle,
2131 hObject, &iCryptCert,
2132 ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
2133 FINDCERT_NORMAL : FINDCERT_DATAONLY );
2134 if( cryptStatusError( cryptStatus ) )
2135 {
2136 /* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means
2137 that there's no certificate present, however anything else is
2138 an error. In addition if we've got a private key whose only
2139 function is to point to an associated certificate then not
2140 finding anything is also an error */
2141 if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
2142 return( cryptStatus );
2143 }
2144 else
2145 {
2146 /* We got the certificate, if we're being asked for a public key
2147 then we've created a native object to contain it so we return
2148 that */
2149 certPresent = TRUE;
2150 if( itemType == KEYMGMT_ITEM_PUBLICKEY )
2151 {
2152 *iCryptHandle = iCryptCert;
2153 return( CRYPT_OK );
2154 }
2155 }
2156 }
2157
2158 /* Create the object. If it's a public-key object we create a native
2159 object for the reasons given in createNativeObject(), otherwise we
2160 create a device object */
2161 if( itemType == KEYMGMT_ITEM_PUBLICKEY )
2162 {
2163 return( createNativeObject( pkcs11Info, iCryptHandle, hObject,
2164 KEYMGMT_ITEM_PUBLICKEY, cryptAlgo ) );
2165 }
2166 cryptStatus = createDeviceObject( pkcs11Info, iCryptHandle, hObject,
2167 certPresent ? iCryptCert : CRYPT_UNUSED,
2168 deviceInfo->ownerHandle,
2169 deviceInfo->objectHandle,
2170 capabilityInfoPtr,
2171 KEYMGMT_ITEM_PRIVATEKEY, cryptAlgo,
2172 keySize );
2173 if( cryptStatusError( cryptStatus ) && certPresent )
2174 krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
2175 return( cryptStatus );
2176 }
2177
2178 /* Get the sequence of certificates in a chain from a device */
2179
2180 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
getFirstItemFunction(INOUT DEVICE_INFO * deviceInfo,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCertificate,OUT int * stateInfo,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_FLAGS_Z (KEYMGMT)const int options)2181 static int getFirstItemFunction( INOUT DEVICE_INFO *deviceInfo,
2182 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
2183 OUT int *stateInfo,
2184 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
2185 IN_BUFFER( keyIDlength ) const void *keyID,
2186 IN_LENGTH_KEYID const int keyIDlength,
2187 IN_ENUM( KEYMGMT_ITEM ) \
2188 const KEYMGMT_ITEM_TYPE itemType,
2189 IN_FLAGS_Z( KEYMGMT ) const int options )
2190 {
2191 static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
2192 static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
2193 CK_ATTRIBUTE certTemplate[] = {
2194 { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
2195 { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
2196 { CKA_ID, ( CK_VOID_PTR ) keyID, keyIDlength }
2197 };
2198 CK_OBJECT_HANDLE hCertificate;
2199 PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
2200 int cryptStatus;
2201
2202 assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
2203 assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2204 assert( isReadPtr( keyID, keyIDlength ) );
2205 assert( isWritePtr( stateInfo, sizeof( int ) ) );
2206
2207 REQUIRES( keyIDtype == CRYPT_IKEYID_KEYID );
2208 REQUIRES( keyIDlength >= 1 && keyIDlength < MAX_ATTRIBUTE_SIZE );
2209 /* The keyID can be as little as a single byte when coming
2210 from a non-cryptlib source */
2211 REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );
2212 REQUIRES( options >= KEYMGMT_FLAG_NONE && \
2213 options < KEYMGMT_FLAG_MAX );
2214
2215 /* Clear return values */
2216 *iCertificate = CRYPT_ERROR;
2217 *stateInfo = CRYPT_ERROR;
2218
2219 /* Try and find the certificate with the given ID. This should work
2220 because we've just read the ID for the indirect-import that lead to
2221 the getFirst() call. Note that we can't use findCert() for this
2222 because it uses getCertChain() to build the full chain of
2223 certificates from the leaf, which would end up calling back to
2224 here */
2225 cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );
2226 ENSURES( cryptStatusOK( cryptStatus ) );
2227
2228 /* Instantiate the certificate from the device */
2229 cryptStatus = instantiateCert( pkcs11Info, hCertificate, iCertificate,
2230 ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
2231 TRUE : FALSE );
2232 if( cryptStatusError( cryptStatus ) )
2233 return( cryptStatus );
2234 *stateInfo = *iCertificate;
2235 return( CRYPT_OK );
2236 }
2237
2238 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
getNextItemFunction(INOUT DEVICE_INFO * deviceInfo,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCertificate,INOUT int * stateInfo,IN_FLAGS_Z (KEYMGMT)const int options)2239 static int getNextItemFunction( INOUT DEVICE_INFO *deviceInfo,
2240 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
2241 INOUT int *stateInfo,
2242 IN_FLAGS_Z( KEYMGMT ) const int options )
2243 {
2244 static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
2245 static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
2246 CK_ATTRIBUTE certTemplate[] = {
2247 { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
2248 { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
2249 { CKA_SUBJECT, NULL, 0 }
2250 };
2251 CK_OBJECT_HANDLE hCertificate;
2252 PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
2253 DYNBUF subjectDB;
2254 int cryptStatus;
2255
2256 assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
2257 assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2258 assert( isWritePtr( stateInfo, sizeof( int ) ) );
2259
2260 REQUIRES( isHandleRangeValid( *stateInfo ) || *stateInfo == CRYPT_ERROR );
2261 REQUIRES( options >= KEYMGMT_FLAG_NONE && options < KEYMGMT_FLAG_MAX );
2262
2263 /* Clear return value */
2264 *iCertificate = CRYPT_ERROR;
2265
2266 /* If the previous certificate was the last one, there's nothing left to
2267 fetch */
2268 if( *stateInfo == CRYPT_ERROR )
2269 return( CRYPT_ERROR_NOTFOUND );
2270
2271 /* Get the issuerName of the previous certificate, which is the
2272 subjectName of the certificate that we want */
2273 cryptStatus = dynCreate( &subjectDB, *stateInfo,
2274 CRYPT_IATTRIBUTE_ISSUER );
2275 if( cryptStatusError( cryptStatus ) )
2276 return( cryptStatus );
2277 certTemplate[ 2 ].pValue = dynData( subjectDB );
2278 certTemplate[ 2 ].ulValueLen = dynLength( subjectDB );
2279
2280 /* Get the certificate with the subject's issuer DN. Note that we
2281 can't use findCert() for this because it uses getCertChain() to
2282 build the full chain of certificates from the leaf, which would end
2283 up calling back to here */
2284 cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );
2285 if( cryptStatusOK( cryptStatus ) )
2286 {
2287 cryptStatus = instantiateCert( pkcs11Info, hCertificate, iCertificate,
2288 ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
2289 TRUE : FALSE );
2290 }
2291 #ifdef PKCS11_FIND_VIA_CRYPTLIB
2292 else
2293 {
2294 cryptStatus = searchDeviceObjects( pkcs11Info, iCertificate, NULL,
2295 CRYPT_KEYID_NONE,
2296 dynData( subjectDB ),
2297 dynLength( subjectDB ), TRUE );
2298 }
2299 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
2300 dynDestroy( &subjectDB );
2301 if( cryptStatusError( cryptStatus ) )
2302 {
2303 *stateInfo = CRYPT_ERROR;
2304 return( cryptStatus );
2305 }
2306 *stateInfo = *iCertificate;
2307 return( CRYPT_OK );
2308 }
2309
2310 /****************************************************************************
2311 * *
2312 * Device Access Routines *
2313 * *
2314 ****************************************************************************/
2315
2316 /* Set up the function pointers to the read methods */
2317
2318 STDC_NONNULL_ARG( ( 1 ) ) \
initPKCS11Read(INOUT DEVICE_INFO * deviceInfo)2319 void initPKCS11Read( INOUT DEVICE_INFO *deviceInfo )
2320 {
2321 assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
2322
2323 deviceInfo->getItemFunction = getItemFunction;
2324 deviceInfo->getFirstItemFunction = getFirstItemFunction;
2325 deviceInfo->getNextItemFunction = getNextItemFunction;
2326 }
2327 #endif /* USE_PKCS11 */
2328