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