cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs11_wr.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #11 Item Write 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 #ifdef USE_PKCS11
23 
24 /****************************************************************************
25 * *
26 * Utility Routines *
27 * *
28 ****************************************************************************/
29 
30 /* Convert a time_t to a PKCS #11 CK_DATE */
31 
32 STDC_NONNULL_ARG( ( 1 ) ) \
33 static void convertDate( OUT CK_DATE *date, const time_t theTime )
34  {
35  STREAM stream;
36  BYTE dateBuffer[ 32 + 8 ];
37  int cryptStatus;
38 
39  assert( isWritePtr( date, sizeof( CK_DATE ) ) );
40 
41  /* Clear return value */
42  memset( date, 0, sizeof( CK_DATE ) );
43 
44  /* Convert the time_t value to an ASN.1 time string that we can use to
45  populate the CK_DATE fields, which are stored as ASCII text strings */
46  sMemOpen( &stream, dateBuffer, 32 );
47  cryptStatus = writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );
48  sMemDisconnect( &stream );
49  ENSURES_V( cryptStatusOK( cryptStatus ) );
50  memcpy( &date->year, dateBuffer + 2, 4 );
51  memcpy( &date->month, dateBuffer + 6, 2 );
52  memcpy( &date->day, dateBuffer + 8, 2 );
53  }
54 
55 /****************************************************************************
56 * *
57 * Certificate R/W Routines *
58 * *
59 ****************************************************************************/
60 
61 /* Set up certificate information and load it into the device */
62 
63 #define addTemplateValue( certTemplatePtr, valueType, valuePtr, valueLen ) \
64  { \
65  ( certTemplatePtr ).type = valueType; \
66  ( certTemplatePtr ).pValue = valuePtr; \
67  ( certTemplatePtr ).ulValueLen = valueLen; \
68  }
69 
71 static int updateCertificate( INOUT PKCS11_INFO *pkcs11Info,
73  const BOOLEAN isLeafCert )
74  {
75  static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
76  static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
77  static const CK_BBOOL bTrue = TRUE;
78  CK_DATE startDate, endDate;
79  CK_ATTRIBUTE certTemplate[] = {
80  { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
81  { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
82  { CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
83  { CKA_ID, NULL_PTR, 0 },
84  { CKA_SUBJECT, NULL_PTR, 0 },
85  { CKA_ISSUER, NULL_PTR, 0 },
86  { CKA_SERIAL_NUMBER, NULL_PTR, 0 },
87  { CKA_VALUE, NULL_PTR, 0 },
88  /* Optional fields, filled in if required and the driver supports this */
89  { CKA_NONE, NULL_PTR, 0 }, /* 8 */
90  { CKA_NONE, NULL_PTR, 0 }, /* 9 */
91  { CKA_NONE, NULL_PTR, 0 }, /* 10 */
92  { CKA_NONE, NULL_PTR, 0 }, /* 11 */
93  };
94  CK_OBJECT_HANDLE hObject;
95  CK_RV status;
97  DYNBUF subjectDB, iAndSDB, certDB;
99  BOOLEAN hasURL = FALSE;
100  time_t theTime;
101  char label[ CRYPT_MAX_TEXTSIZE + 8 ], uri[ MAX_URL_SIZE + 8 ];
102  int templateCount = 8, cryptStatus;
103 
104  assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
105 
106  REQUIRES( isHandleRangeValid( iCryptHandle ) );
107 
108  /* Get the keyID from the certificate */
109  setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
110  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
111  &msgData, CRYPT_IATTRIBUTE_KEYID );
112  if( cryptStatusError( cryptStatus ) )
113  return( CRYPT_ARGERROR_NUM1 );
114  certTemplate[ 3 ].pValue = msgData.data;
115  certTemplate[ 3 ].ulValueLen = msgData.length;
116 
117  /* If it's a leaf certificate, use the keyID to locate the corresponding
118  public or private key object. This is used as a check to ensure that
119  the certificate corresponds to a key in the device. In theory this
120  would allow us to read the label from the key so that we can reuse it
121  for the certificate, but there doesn't seem to be any good reason for
122  this and it could lead to problems with multiple certificates with the
123  same labels so we don't do it */
124  if( isLeafCert )
125  {
126  static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
127  static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
128  CK_ATTRIBUTE keyTemplate[] = {
129  { CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
130  { CKA_ID, NULL_PTR, 0 }
131  };
132 
133  keyTemplate[ 1 ].pValue = certTemplate[ 3 ].pValue;
134  keyTemplate[ 1 ].ulValueLen = certTemplate[ 3 ].ulValueLen;
135  cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
136  if( cryptStatusError( cryptStatus ) )
137  {
138  /* Couldn't find a private key with this ID, try for a public key */
139  keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &pubkeyClass;
140  cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
141  }
142  if( cryptStatusError( cryptStatus ) )
143  return( CRYPT_ARGERROR_NUM1 );
144  }
145 
146  /* Get the validFrom and validTo dates. These aren't currently used for
147  anything, but could be used in the future to handle superceded
148  certificates in the same way that it's done for PKCS #15 keysets */
149  setMessageData( &msgData, &theTime, sizeof( time_t ) );
150  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
151  &msgData, CRYPT_CERTINFO_VALIDFROM );
152  if( cryptStatusOK( cryptStatus ) )
153  {
154  convertDate( &startDate, theTime );
155  setMessageData( &msgData, &theTime, sizeof( time_t ) );
156  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
157  &msgData, CRYPT_CERTINFO_VALIDTO );
158  }
159  if( cryptStatusError( cryptStatus ) )
160  return( cryptStatus );
161  convertDate( &endDate, theTime );
162 
163  /* Get the subjectName and issuerAndSerialNumber from the certificate */
164  cryptStatus = dynCreate( &subjectDB, iCryptHandle,
165  CRYPT_IATTRIBUTE_SUBJECT );
166  if( cryptStatusError( cryptStatus ) )
167  return( cryptStatus );
168  cryptStatus = dynCreate( &iAndSDB, iCryptHandle,
169  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
170  if( cryptStatusError( cryptStatus ) )
171  {
172  dynDestroy( &subjectDB );
173  return( cryptStatus );
174  }
175  certTemplate[ 4 ].pValue = dynData( subjectDB );
176  certTemplate[ 4 ].ulValueLen = dynLength( subjectDB );
177  cryptStatus = addIAndSToTemplate( &certTemplate[ 5 ], dynData( iAndSDB ),
178  dynLength( iAndSDB ) );
179  if( cryptStatusError( cryptStatus ) )
180  {
181  dynDestroy( &subjectDB );
182  dynDestroy( &iAndSDB );
183  return( cryptStatus );
184  }
185 
186  /* Get the certificate data */
187  cryptStatus = dynCreateCert( &certDB, iCryptHandle,
189  if( cryptStatusError( cryptStatus ) )
190  {
191  dynDestroy( &subjectDB );
192  dynDestroy( &iAndSDB );
193  return( cryptStatus );
194  }
195  certTemplate[ 7 ].pValue = dynData( certDB );
196  certTemplate[ 7 ].ulValueLen = dynLength( certDB );
197 
198  /* Get the certificate holder name (label) from the certificate if
199  available */
200  setMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );
201  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
202  &msgData, CRYPT_IATTRIBUTE_HOLDERNAME );
203  if( cryptStatusOK( cryptStatus ) )
204  {
205  /* We've found a holder name, use it as the certificate object
206  label */
207  addTemplateValue( certTemplate[ templateCount ],
208  CKA_LABEL, msgData.data, msgData.length );
209  templateCount++;
210  }
211 
212  /* Add the certificate dates. These have to be located between the
213  label and the URI so that we can selectively back out the attributes
214  that don't work for this driver, see the comments further down for
215  more details */
216  addTemplateValue( certTemplate[ templateCount ],
217  CKA_START_DATE, ( CK_VOID_PTR ) &startDate, sizeof( CK_DATE ) );
218  templateCount++;
219  addTemplateValue( certTemplate[ templateCount ],
220  CKA_END_DATE, ( CK_VOID_PTR ) &endDate, sizeof( CK_DATE ) );
221  templateCount++;
222 
223  /* Get the URI from the certificate if available */
224  setMessageData( &msgData, uri, MAX_URL_SIZE );
225  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,
226  &msgData, CRYPT_IATTRIBUTE_HOLDERURI );
227  if( cryptStatusOK( cryptStatus ) )
228  {
229  /* We've found a holder URI, use it as the certificate object URL */
230  addTemplateValue( certTemplate[ templateCount ],
231  CKA_URL, msgData.data, msgData.length );
232  templateCount++;
233  hasURL = TRUE;
234  }
235 
236  /* Reset the status value, which may contain error values due to not
237  finding various object attributes above */
238  cryptStatus = CRYPT_OK;
239 
240  /* We've finally got everything available, try and update the device with
241  the certificate data. In theory we should also set CKA_PRIVATE = FALSE
242  but the Dallas iButton driver doesn't allow this so we have to rely on
243  drivers doing the right thing with the default setting */
244  status = C_CreateObject( pkcs11Info->hSession,
245  ( CK_ATTRIBUTE_PTR ) certTemplate, templateCount,
246  &hObject );
247  if( hasURL && ( status == CKR_TEMPLATE_INCONSISTENT || \
248  status == CKR_ATTRIBUTE_TYPE_INVALID ) )
249  {
250  /* Support for the PKCS #11 v2.20 attribute CKA_URL is pretty hit-
251  and-miss, some drivers from ca.2000 support it but others from
252  ca.2007 still don't so if we get a CKR_ATTRIBUTE_TYPE_INVALID
253  return code we try again without the CKA_URL */
254  templateCount--;
255  status = C_CreateObject( pkcs11Info->hSession,
256  ( CK_ATTRIBUTE_PTR ) certTemplate,
257  templateCount, &hObject );
258  }
259  if( status == CKR_TEMPLATE_INCONSISTENT || \
260  status == CKR_ATTRIBUTE_TYPE_INVALID )
261  {
262  /* Even support for dates is hit-and-miss so if we're still getting
263  CKR_ATTRIBUTE_TYPE_INVALID we try again without the
264  CKA_START_DATE/CKA_END_DATE */
265  templateCount -= 2;
266  status = C_CreateObject( pkcs11Info->hSession,
267  ( CK_ATTRIBUTE_PTR ) certTemplate,
268  templateCount, &hObject );
269  }
270  if( status != CKR_OK )
271  cryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );
272 
273  /* Clean up */
274  dynDestroy( &subjectDB );
275  dynDestroy( &iAndSDB );
276  dynDestroy( &certDB );
277  return( cryptStatus );
278  }
279 
280 /* Update a device using the certificates in a certificate chain */
281 
283 static int updateCertChain( INOUT PKCS11_INFO *pkcs11Info,
285  {
286  static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
287  static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
288  CK_ATTRIBUTE certTemplate[] = {
289  { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
290  { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
291  { CKA_ISSUER, NULL_PTR, 0 },
292  { CKA_SERIAL_NUMBER, NULL_PTR, 0 },
293  };
294  BOOLEAN isLeafCert = TRUE, seenNonDuplicate = FALSE;
295  int value, iterationCount, cryptStatus;
296 
297  assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
298 
299  REQUIRES( isHandleRangeValid( iCryptCert ) );
300 
301  /* If we've been passed a standalone certificate, check whether it's
302  implicitly trusted, which allows it to be added without requiring the
303  presence of a corresponding public/private key in the device */
304  cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value,
306  if( cryptStatusError( cryptStatus ) )
307  {
308  return( ( cryptStatus == CRYPT_ARGERROR_OBJECT ) ? \
309  CRYPT_ARGERROR_NUM1 : cryptStatus );
310  }
311  if( value == CRYPT_CERTTYPE_CERTIFICATE )
312  {
313  cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
314  &value,
316  if( cryptStatusError( cryptStatus ) )
317  return( CRYPT_ARGERROR_NUM1 );
318 
319  /* If the certificate is implicitly trusted we indicate that it's
320  (effectively) a non-leaf certificate so that it can be added even
321  if there's no corresponding key already in the device */
322  if( value )
323  isLeafCert = FALSE;
324  }
325 
326  /* Add each certificate in the chain to the device */
327  for( iterationCount = 0; iterationCount < FAILSAFE_ITERATIONS_MED;
328  iterationCount++ )
329  {
330  CK_OBJECT_HANDLE hObject;
331  DYNBUF iAndSDB;
332 
333  /* If the certificate is already present, don't do anything */
334  cryptStatus = dynCreate( &iAndSDB, iCryptCert,
335  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
336  if( cryptStatusError( cryptStatus ) )
337  return( cryptStatus );
338  cryptStatus = addIAndSToTemplate( &certTemplate[ 2 ],
339  dynData( iAndSDB ),
340  dynLength( iAndSDB ) );
341  if( cryptStatusError( cryptStatus ) )
342  {
343  /* In theory we could simply skip any certificates for which we
344  can't decode the iAndS, but in practice it's probably better
345  to fail and warn the user than to continue with only some
346  certificates added */
347  dynDestroy( &iAndSDB );
348  return( cryptStatus );
349  }
350  cryptStatus = findObject( pkcs11Info, &hObject, certTemplate, 4 );
351  dynDestroy( &iAndSDB );
352  if( cryptStatusError( cryptStatus ) )
353  {
354  /* The certificate isn't already present, write it */
355  cryptStatus = updateCertificate( pkcs11Info, iCryptCert,
356  isLeafCert );
357  if( cryptStatusError( cryptStatus ) )
358  return( cryptStatus );
359  isLeafCert = FALSE;
360  seenNonDuplicate = TRUE;
361  }
362 
363  /* Try and move to the next certificate */
364  cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
367  if( cryptStatusError( cryptStatus ) )
368  break;
369  }
370  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
371 
372  return( seenNonDuplicate ? CRYPT_OK : CRYPT_ERROR_DUPLICATE );
373  }
374 
375 /****************************************************************************
376 * *
377 * Write an Item to a Device *
378 * *
379 ****************************************************************************/
380 
381 /* Update a device with a certificate */
382 
384 static int setItemFunction( INOUT DEVICE_INFO *deviceInfo,
385  IN_HANDLE const CRYPT_HANDLE iCryptHandle )
386  {
388  PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
389  int value, cryptStatus;
390 
391  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
392 
393  REQUIRES( isHandleRangeValid( iCryptHandle ) );
394 
395  /* If the certificate isn't signed then we can't store it in this
396  state */
397  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
398  &value, CRYPT_CERTINFO_IMMUTABLE );
399  if( cryptStatusError( cryptStatus ) || !value )
400  return( CRYPT_ERROR_NOTINITED );
401 
402  /* Lock the certificate for our exclusive use (in case it's a
403  certificate chain we also select the first certificate in the
404  chain), update the device with the certificate, and unlock it to
405  allow others access */
406  cryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT,
407  &iCryptCert, OBJECT_TYPE_CERTIFICATE );
408  if( cryptStatusOK( cryptStatus ) )
409  cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
411  CRYPT_IATTRIBUTE_LOCKED );
412  if( cryptStatusError( cryptStatus ) )
413  return( cryptStatus );
414  cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
417  if( cryptStatusOK( cryptStatus ) )
418  cryptStatus = updateCertChain( pkcs11Info, iCryptCert );
419  ( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
420  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
421 
422  return( cryptStatus );
423  }
424 
425 /****************************************************************************
426 * *
427 * Delete an Item from a Device *
428 * *
429 ****************************************************************************/
430 
431 /* Delete an object in a device */
432 
433 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
434 static int deleteItemFunction( INOUT DEVICE_INFO *deviceInfo,
435  IN_ENUM( KEYMGMT_ITEM ) \
436  const KEYMGMT_ITEM_TYPE itemType,
438  IN_BUFFER( keyIDlength ) const void *keyID,
439  IN_LENGTH_KEYID const int keyIDlength )
440  {
441  static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
442  static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
443  static const CK_OBJECT_CLASS secKeyClass = CKO_SECRET_KEY;
444  static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
445  static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
446  CK_ATTRIBUTE certTemplate[] = {
447  { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
448  { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
449  { CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
450  };
451  CK_ATTRIBUTE keyTemplate[] = {
452  { CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },
453  { CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
454  };
455  CK_OBJECT_HANDLE hPrivkey = CK_OBJECT_NONE, hCertificate = CK_OBJECT_NONE;
456  CK_OBJECT_HANDLE hPubkey = CK_OBJECT_NONE, hSecretKey = CK_OBJECT_NONE;
457  CK_RV status;
458  PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
459  int cryptStatus;
460 
461  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
462  assert( isReadPtr( keyID, keyIDlength ) );
463 
464  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
465  itemType == KEYMGMT_ITEM_PRIVATEKEY || \
466  itemType == KEYMGMT_ITEM_SECRETKEY );
467  REQUIRES( keyIDtype == CRYPT_KEYID_NAME );
468  REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
469  keyIDlength < MAX_ATTRIBUTE_SIZE );
470 
471  /* Find the object to delete based on the label. Since we can have
472  multiple related objects (e.g. a key and a certificate) with the same
473  label, a straight search for all objects with a given label could
474  return CRYPT_ERROR_DUPLICATE so we search for the objects by type as
475  well as label. In addition even a search for specific objects can
476  return CRYPT_ERROR_DUPLICATE so we use the -Ex version of findObject()
477  to make sure we don't get an error if multiple objects exist.
478  Although cryptlib won't allow more than one object with a given label
479  to be created, other applications might create duplicate labels. The
480  correct behaviour in these circumstances is uncertain, what we do for
481  now is delete the first object we find that matches the label.
482 
483  First we try for a certificate and use that to find associated keys */
484  cryptStatus = findObjectEx( pkcs11Info, &hCertificate, certTemplate, 3 );
485  if( cryptStatusOK( cryptStatus ) )
486  {
487  /* We got a certificate, if there are associated keys delete them as
488  well */
489  cryptStatus = findObjectFromObject( pkcs11Info, hCertificate,
490  CKO_PUBLIC_KEY, &hPubkey );
491  if( cryptStatusError( cryptStatus ) )
492  hPubkey = CK_OBJECT_NONE;
493  cryptStatus = findObjectFromObject( pkcs11Info, hCertificate,
494  CKO_PRIVATE_KEY, &hPrivkey );
495  if( cryptStatusError( cryptStatus ) )
496  hPrivkey = CK_OBJECT_NONE;
497  }
498  else
499  {
500  /* We didn't find a certificate with the given label, try for
501  public, private, and secret keys */
502  cryptStatus = findObjectEx( pkcs11Info, &hPubkey, keyTemplate, 2 );
503  if( cryptStatusError( cryptStatus ) )
504  hPubkey = CK_OBJECT_NONE;
505  keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
506  cryptStatus = findObjectEx( pkcs11Info, &hPrivkey, keyTemplate, 2 );
507  if( cryptStatusError( cryptStatus ) )
508  hPrivkey = CK_OBJECT_NONE;
509  keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &secKeyClass;
510  cryptStatus = findObjectEx( pkcs11Info, &hSecretKey, keyTemplate, 2 );
511  if( cryptStatusError( cryptStatus ) )
512  hSecretKey = CK_OBJECT_NONE;
513 
514  /* There may be an unlabelled certificate present, try and find it
515  by looking for a certificate matching the key ID */
516  if( hPubkey != CK_OBJECT_NONE || hPrivkey != CK_OBJECT_NONE )
517  {
518  cryptStatus = findObjectFromObject( pkcs11Info,
519  ( hPrivkey != CK_OBJECT_NONE ) ? hPrivkey : hPubkey,
520  CKO_CERTIFICATE, &hCertificate );
521  if( cryptStatusError( cryptStatus ) )
522  hCertificate = CK_OBJECT_NONE;
523  }
524  }
525 
526  /* If we found a public key with a given label but no private key, try
527  and find a matching private key by ID, and vice versa */
528  if( hPubkey != CK_OBJECT_NONE && hPrivkey == CK_OBJECT_NONE )
529  {
530  cryptStatus = findObjectFromObject( pkcs11Info, hPubkey,
531  CKO_PRIVATE_KEY, &hPrivkey );
532  if( cryptStatusError( cryptStatus ) )
533  hPrivkey = CK_OBJECT_NONE;
534  }
535  if( hPrivkey != CK_OBJECT_NONE && hPubkey == CK_OBJECT_NONE )
536  {
537  cryptStatus = findObjectFromObject( pkcs11Info, hPrivkey,
538  CKO_PUBLIC_KEY, &hPubkey );
539  if( cryptStatusError( cryptStatus ) )
540  hPubkey = CK_OBJECT_NONE;
541  }
542  if( hPrivkey == CK_OBJECT_NONE && hPubkey == CK_OBJECT_NONE && \
543  hSecretKey == CK_OBJECT_NONE && hCertificate == CK_OBJECT_NONE )
544  return( CRYPT_ERROR_NOTFOUND );
545 
546  /* Reset the status values, which may contain error values due to not
547  finding various objects to delete above */
548  cryptStatus = CRYPT_OK;
549  status = CKR_OK;
550 
551  /* Delete the objects */
552  if( hCertificate != CK_OBJECT_NONE )
553  status = C_DestroyObject( pkcs11Info->hSession, hCertificate );
554  if( hPubkey != CK_OBJECT_NONE )
555  {
556  int status2;
557 
558  status2 = C_DestroyObject( pkcs11Info->hSession, hPubkey );
559  if( status2 != CKR_OK && status == CKR_OK )
560  status = status2;
561  }
562  if( hPrivkey != CK_OBJECT_NONE )
563  {
564  int status2;
565 
566  status2 = C_DestroyObject( pkcs11Info->hSession, hPrivkey );
567  if( status2 != CKR_OK && status == CKR_OK )
568  status = status2;
569  }
570  if( hSecretKey != CK_OBJECT_NONE )
571  {
572  int status2;
573 
574  status2 = C_DestroyObject( pkcs11Info->hSession, hSecretKey );
575  if( status2 != CKR_OK && status == CKR_OK )
576  status = status2;
577  }
578  if( status != CKR_OK )
579  cryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );
580  return( cryptStatus );
581  }
582 
583 /****************************************************************************
584 * *
585 * Device Access Routines *
586 * *
587 ****************************************************************************/
588 
589 /* Set up the function pointers to the write methods */
590 
591 STDC_NONNULL_ARG( ( 1 ) ) \
592 void initPKCS11Write( INOUT DEVICE_INFO *deviceInfo )
593  {
594  assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
595 
596  deviceInfo->setItemFunction = setItemFunction;
597  deviceInfo->deleteItemFunction = deleteItemFunction;
598  }
599 #endif /* USE_PKCS11 */