cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs15.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #15 Routines *
4 * Copyright Peter Gutmann 1996-2007 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "asn1.h"
11  #include "asn1_ext.h"
12  #include "keyset.h"
13  #include "pkcs15.h"
14 #else
15  #include "crypt.h"
16  #include "enc_dec/asn1.h"
17  #include "enc_dec/asn1_ext.h"
18  #include "keyset/keyset.h"
19  #include "keyset/pkcs15.h"
20 #endif /* Compiler-specific includes */
21 
22 /* Each PKCS #15 keyset can contain information for multiple personalities
23  (although it's extremely unlikely to contain more than one or two), we
24  allow a maximum of MAX_PKCS15_OBJECTS per keyset in order to discourage
25  them from being used as general-purpose public-key keysets, which they're
26  not supposed to be. A setting of 16 objects consumes ~2K of memory
27  (16 x ~128) and seems like a sensible upper bound so we choose that as
28  the limit */
29 
30 #ifdef CONFIG_CONSERVE_MEMORY
31  #define MAX_PKCS15_OBJECTS 8
32 #else
33  #define MAX_PKCS15_OBJECTS 16
34 #endif /* CONFIG_CONSERVE_MEMORY */
35 
36 #ifdef USE_PKCS15
37 
38 /* OID information used to read the header of a PKCS #15 keyset. Since the
39  PKCS #15 content can be further wrapped in CMS AuthData we have to check
40  for both types of content. If we find AuthData we retry the read, this
41  time allowing only PKCS #15 content. In addition since this is inner
42  content in an EncapsulatedContentInfo structure we don't specify any
43  version information because the additional OCTET STRING encapsulation
44  used with EncapsulatedContentInfo means that we need to dig down further
45  before we can find this field */
46 
47 static const CMS_CONTENT_INFO FAR_BSS oidInfoPkcs15Data = { 0, 0 };
48 
49 static const OID_INFO FAR_BSS keyFileOIDinfo[] = {
50  { OID_PKCS15_CONTENTTYPE, TRUE, &oidInfoPkcs15Data },
51  { OID_CMS_AUTHDATA, FALSE, &oidInfoPkcs15Data },
52  { NULL, 0 }, { NULL, 0 }
53  };
54 static const OID_INFO FAR_BSS keyFilePKCS15OIDinfo[] = {
56  { NULL, 0 }, { NULL, 0 }
57  };
58 
59 /****************************************************************************
60 * *
61 * Utility Functions *
62 * *
63 ****************************************************************************/
64 
65 /* Get the hash of various certificate name fields */
66 
67 CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \
68 int getCertID( IN_HANDLE const CRYPT_HANDLE iCryptHandle,
70  OUT_BUFFER( nameIdMaxLen, *nameIdLen ) BYTE *nameID,
71  IN_LENGTH_SHORT_MIN( KEYID_SIZE ) const int nameIdMaxLen,
73  {
74  HASHFUNCTION_ATOMIC hashFunctionAtomic;
75  DYNBUF idDB;
76  int status;
77 
78  assert( isWritePtr( nameID, nameIdMaxLen ) );
79  assert( isWritePtr( nameIdLen, sizeof( int ) ) );
80 
81  REQUIRES( isHandleRangeValid( iCryptHandle ) );
82  REQUIRES( nameType == CRYPT_IATTRIBUTE_SPKI || \
83  nameType == CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER || \
84  nameType == CRYPT_IATTRIBUTE_SUBJECT || \
85  nameType == CRYPT_IATTRIBUTE_ISSUER );
86  REQUIRES( nameIdMaxLen >= KEYID_SIZE && \
87  nameIdMaxLen < MAX_INTLENGTH_SHORT );
88 
89  /* Clear return value */
90  *nameIdLen = 0;
91 
92  /* Get the attribute data and hash algorithm information and hash the
93  attribute to get the ID */
94  status = dynCreate( &idDB, iCryptHandle, nameType );
95  if( cryptStatusError( status ) )
96  return( status );
97  getHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );
98  hashFunctionAtomic( nameID, nameIdMaxLen, dynData( idDB ),
99  dynLength( idDB ) );
100  dynDestroy( &idDB );
101  *nameIdLen = nameIdMaxLen;
102 
103  return( CRYPT_OK );
104  }
105 
106 /* Locate a PKCS #15 object based on an ID */
107 
108 #define matchID( src, srcLen, dest, destLen ) \
109  ( ( srcLen ) > 0 && ( srcLen ) == ( destLen ) && \
110  !memcmp( ( src ), ( dest ), ( destLen ) ) )
111 
113 PKCS15_INFO *findEntry( IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info,
116  IN_BUFFER_OPT( keyIDlength ) const void *keyID,
117  IN_LENGTH_KEYID_Z const int keyIDlength,
118  IN_FLAGS_Z( KEYMGMT ) const int requestedUsage )
119  {
120  int i;
121 
122  assert( isReadPtr( pkcs15info, \
123  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
124  assert( ( keyID == NULL && keyIDlength == 0 ) || \
125  isReadPtr( keyID, keyIDlength ) );
126 
127  REQUIRES_N( noPkcs15objects >= 1 && \
128  noPkcs15objects < MAX_INTLENGTH_SHORT );
129  REQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \
130  keyIDtype == CRYPT_KEYID_URI || \
131  keyIDtype == CRYPT_IKEYID_KEYID || \
132  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
133  keyIDtype == CRYPT_IKEYID_ISSUERID || \
134  keyIDtype == CRYPT_KEYIDEX_ID || \
135  keyIDtype == CRYPT_KEYIDEX_SUBJECTNAMEID );
136  REQUIRES_N( ( keyID == NULL && keyIDlength == 0 ) || \
137  ( keyID != NULL && \
138  keyIDlength >= MIN_NAME_LENGTH && \
139  keyIDlength < MAX_ATTRIBUTE_SIZE ) );
140  REQUIRES_N( requestedUsage >= KEYMGMT_FLAG_NONE && \
141  requestedUsage < KEYMGMT_FLAG_MAX );
142  REQUIRES_N( ( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS ) != \
143  KEYMGMT_MASK_USAGEOPTIONS );
144 
145  /* If there's no ID to search on, don't try and do anything. This can
146  occur when we're trying to build a chain and the necessary chaining
147  data isn't present */
148  if( keyID == NULL || keyIDlength <= 0 )
149  return( NULL );
150 
151  /* Try and locate the appropriate object in the PKCS #15 collection */
152  for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
153  {
154  const PKCS15_INFO *pkcs15infoPtr = &pkcs15info[ i ];
155  const int compositeUsage = pkcs15infoPtr->pubKeyUsage | \
156  pkcs15infoPtr->privKeyUsage;
157 
158  /* If there's no entry at this position, continue */
159  if( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )
160  continue;
161 
162  /* If there's an explicit usage requested, make sure that the key
163  usage matches this. This can get slightly complex because the
164  advertised usage isn't necessarily the same as the usage
165  permitted by the associated certificate (PKCS #11 apps are
166  particularly good at setting bogus usage types) and the overall
167  result can be further influenced by trusted usage settings, so
168  all that we check for here is an indicated usage for the key
169  matching the requested usage */
170  if( ( requestedUsage & KEYMGMT_FLAG_USAGE_CRYPT ) && \
171  !( compositeUsage & ENCR_USAGE_MASK ) )
172  continue;
173  if( ( requestedUsage & KEYMGMT_FLAG_USAGE_SIGN ) && \
174  !( compositeUsage & SIGN_USAGE_MASK ) )
175  continue;
176 
177  /* Check for a match based on the ID type */
178  switch( keyIDtype )
179  {
180  case CRYPT_KEYID_NAME:
181  case CRYPT_KEYID_URI:
182  if( matchID( pkcs15infoPtr->label, pkcs15infoPtr->labelLength,
183  keyID, keyIDlength ) )
184  return( ( PKCS15_INFO * ) pkcs15infoPtr );
185  break;
186 
187  case CRYPT_IKEYID_KEYID:
188  if( matchID( pkcs15infoPtr->keyID, pkcs15infoPtr->keyIDlength,
189  keyID, keyIDlength ) )
190  return( ( PKCS15_INFO * ) pkcs15infoPtr );
191  break;
192 
193  case CRYPT_IKEYID_PGPKEYID:
194  /* For the PGP keyID we compare both IDs for the reasons
195  given in the PGP keyset read code */
196  if( matchID( pkcs15infoPtr->pgp2KeyID,
197  pkcs15infoPtr->pgp2KeyIDlength, keyID,
198  keyIDlength ) || \
199  matchID( pkcs15infoPtr->openPGPKeyID,
200  pkcs15infoPtr->openPGPKeyIDlength, keyID,
201  keyIDlength ) )
202  return( ( PKCS15_INFO * ) pkcs15infoPtr );
203  break;
204 
205  case CRYPT_IKEYID_ISSUERID:
206  if( matchID( pkcs15infoPtr->iAndSID,
207  pkcs15infoPtr->iAndSIDlength, keyID,
208  keyIDlength ) )
209  return( ( PKCS15_INFO * ) pkcs15infoPtr );
210  break;
211 
212  case CRYPT_KEYIDEX_ID:
213  if( matchID( pkcs15infoPtr->iD, pkcs15infoPtr->iDlength,
214  keyID, keyIDlength ) )
215  return( ( PKCS15_INFO * ) pkcs15infoPtr );
216  break;
217 
219  if( matchID( pkcs15infoPtr->subjectNameID,
220  pkcs15infoPtr->subjectNameIDlength, keyID,
221  keyIDlength ) )
222  return( ( PKCS15_INFO * ) pkcs15infoPtr );
223  break;
224 
225  default:
227  }
228  }
229  ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
230 
231  /* If we're trying to match on the PGP key ID and didn't find anything,
232  retry it using the first PGP_KEYID_SIZE bytes of the object ID. This
233  is necessary because calculation of the OpenPGP ID requires the
234  presence of data that may not be present in non-PGP keys so we can't
235  calculate a real OpenPGP ID but have to use the next-best thing
236  (sol lucet omnibus) */
237  if( keyIDtype == CRYPT_IKEYID_PGPKEYID )
238  {
239  for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
240  {
241  const PKCS15_INFO *pkcs15infoPtr = &pkcs15info[ i ];
242 
243  if( pkcs15infoPtr->type != PKCS15_SUBTYPE_NONE && \
244  pkcs15infoPtr->iDlength >= PGP_KEYID_SIZE && \
245  !memcmp( keyID, pkcs15infoPtr->iD, PGP_KEYID_SIZE ) )
246  return( ( PKCS15_INFO * ) pkcs15infoPtr );
247  }
248  ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
249  }
250 
251  return( NULL );
252  }
253 
254 /* Find a free PKCS #15 entry */
255 
257 PKCS15_INFO *findFreeEntry( IN_ARRAY( noPkcs15objects ) \
258  const PKCS15_INFO *pkcs15info,
259  IN_LENGTH_SHORT const int noPkcs15objects,
261  {
262  int i;
263 
264  assert( isReadPtr( pkcs15info, \
265  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
266  assert( ( index == NULL ) || isWritePtr( index, sizeof( int ) ) );
267 
268  REQUIRES_N( noPkcs15objects >= 1 && \
269  noPkcs15objects < MAX_INTLENGTH_SHORT );
270 
271  /* Clear return value */
272  if( index != NULL )
273  *index = CRYPT_ERROR;
274 
275  for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
276  {
277  if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
278  break;
279  }
280  ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
281  if( i >= noPkcs15objects )
282  return( NULL );
283 
284  /* Remember the index value (used for enumerating PKCS #15 entries) for
285  this entry if required */
286  if( index != NULL )
287  *index = i;
288 
289  return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
290  }
291 
292 /* Free object entries */
293 
294 STDC_NONNULL_ARG( ( 1 ) ) \
295 void pkcs15freeEntry( INOUT PKCS15_INFO *pkcs15info )
296  {
297  assert( isWritePtr( pkcs15info, sizeof( PKCS15_INFO ) ) );
298 
299  if( pkcs15info->pubKeyData != NULL )
300  {
301  zeroise( pkcs15info->pubKeyData, pkcs15info->pubKeyDataSize );
302  clFree( "pkcs15freeEntry", pkcs15info->pubKeyData );
303  }
304  if( pkcs15info->privKeyData != NULL )
305  {
306  zeroise( pkcs15info->privKeyData, pkcs15info->privKeyDataSize );
307  clFree( "pkcs15freeEntry", pkcs15info->privKeyData );
308  }
309  if( pkcs15info->certData != NULL )
310  {
311  zeroise( pkcs15info->certData, pkcs15info->certDataSize );
312  clFree( "pkcs15freeEntry", pkcs15info->certData );
313  }
314  if( pkcs15info->dataData != NULL )
315  {
316  zeroise( pkcs15info->dataData, pkcs15info->dataDataSize );
317  clFree( "pkcs15freeEntry", pkcs15info->dataData );
318  }
319  zeroise( pkcs15info, sizeof( PKCS15_INFO ) );
320  }
321 
322 STDC_NONNULL_ARG( ( 1 ) ) \
323 static void pkcs15Free( INOUT_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info,
324  IN_RANGE( 1, MAX_PKCS15_OBJECTS ) const int noPkcs15objects )
325  {
326  int i;
327 
328  assert( isWritePtr( pkcs15info, \
329  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
330 
331  REQUIRES_V( noPkcs15objects >= 1 && \
332  noPkcs15objects <= MAX_PKCS15_OBJECTS );
333 
334  for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
335  pkcs15freeEntry( &pkcs15info[ i ] );
336  ENSURES_V( i < FAILSAFE_ITERATIONS_MED );
337  zeroise( pkcs15info, sizeof( PKCS15_INFO ) * noPkcs15objects );
338  }
339 
340 /* Get the PKCS #15 validity information from a certificate */
341 
343 int getValidityInfo( INOUT PKCS15_INFO *pkcs15info,
345  {
347  time_t validFrom, validTo;
348  int status;
349 
350  assert( isWritePtr( pkcs15info, sizeof( PKCS15_INFO ) ) );
351 
352  REQUIRES( isHandleRangeValid( cryptHandle ) );
353 
354  /* Remember the validity information for later. We always update the
355  validity (even if it's already set) since we may be replacing an
356  older certificate with a newer one */
357  setMessageData( &msgData, &validFrom, sizeof( time_t ) );
358  status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
359  &msgData, CRYPT_CERTINFO_VALIDFROM );
360  if( cryptStatusError( status ) )
361  return( status );
362  setMessageData( &msgData, &validTo, sizeof( time_t ) );
363  status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
364  &msgData, CRYPT_CERTINFO_VALIDTO );
365  if( cryptStatusError( status ) )
366  return( status );
367  if( pkcs15info->validTo > validTo )
368  {
369  /* There's an existing, newer certificate already present, make sure
370  that we don't try and add the new one */
371  return( CRYPT_ERROR_DUPLICATE );
372  }
373  pkcs15info->validFrom = validFrom;
374  pkcs15info->validTo = validTo;
375 
376  return( CRYPT_OK );
377  }
378 
379 /* Read the header of a PKCS #15 keyset */
380 
381 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
382 static int readPkcs15EncapsHeader( INOUT STREAM *stream,
383  OUT long *endPosPtr )
384  {
385  long length;
386  int tag, innerLength, status;
387 
388  assert( isWritePtr( stream, sizeof( STREAM ) ) );
389  assert( isWritePtr( endPosPtr, sizeof( long ) ) );
390 
391  /* Clear return value */
392  *endPosPtr = 0;
393 
394  /* The outer header was a CMS AuthData wrapper, try again for an inner
395  PKCS #15 header. First we skip the AuthData SET OF RECIPIENTINFO,
396  macAlgorithm AlgorithmIdentifier, and optional digestAlgorithm
397  AlgorithmIdentifier */
398  readUniversal( stream );
399  status = readUniversal( stream );
400  if( cryptStatusError( status ) )
401  return( status );
402  status = tag = peekTag( stream );
403  if( !cryptStatusError( status ) && tag == MAKE_CTAG( 1 ) )
404  status = readUniversal( stream );
405  if( cryptStatusError( status ) )
406  return( status );
407 
408  /* We've made our way past the AuthData information, try again for
409  encapsulated PKCS #15 content */
410  status = readCMSheader( stream, keyFilePKCS15OIDinfo,
411  FAILSAFE_ARRAYSIZE( keyFilePKCS15OIDinfo, OID_INFO ),
412  &length, READCMS_FLAG_INNERHEADER );
413  if( cryptStatusError( status ) )
414  return( status );
415 
416  /* Since this is EncapsulatedContentInfo the version information doesn't
417  immediately follow the header but is encapsulated inside an OCTET
418  STRING, so we have to skip an additional layer of wrapping and
419  manually read the version information. In addition the OCTET STRING
420  could be indefinite-length, in which case it acts as a constructed
421  value containing an inner OCTET STRING, so we have to skip the inner
422  OCTET STRING before we get to the actual content */
423  if( length == CRYPT_UNUSED )
424  {
425  /* It's an indefinite-length OCTET STRING, skip the inner OCTET
426  STRING wrapper */
427  readOctetStringHole( stream, NULL, 16, DEFAULT_TAG );
428  }
429  status = readSequence( stream, &innerLength );
430  if( cryptStatusOK( status ) )
431  {
432  long value;
433 
434  *endPosPtr = innerLength;
435  status = readShortInteger( stream, &value );
436  if( cryptStatusOK( status ) && value != 0 )
437  status = CRYPT_ERROR_BADDATA;
438  }
439 
440  return( status );
441  }
442 
443 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
444 static int readPkcs15header( INOUT STREAM *stream,
445  OUT_INT_Z long *endPosPtr,
447  {
448  long endPos, currentPos;
449  int value, status;
450 
451  assert( isWritePtr( stream, sizeof( STREAM ) ) );
452  assert( isWritePtr( endPosPtr, sizeof( long ) ) );
453  assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
454 
455  /* Clear return value */
456  *endPosPtr = 0;
457 
458  /* Read the outer header and make sure that the length information is
459  valid */
460  status = value = readCMSheader( stream, keyFileOIDinfo,
461  FAILSAFE_ARRAYSIZE( keyFileOIDinfo, OID_INFO ),
463  if( cryptStatusError( status ) )
464  {
466  ( CRYPT_ERROR_BADDATA, errorInfo,
467  "Invalid PKCS #15 keyset header" ) );
468  }
469  if( value == FALSE )
470  {
471  /* The outer header was a CMS AuthData wrapper, try again for an
472  inner PKCS #15 header */
473  status = readPkcs15EncapsHeader( stream, &endPos );
474  if( cryptStatusError( status ) )
475  {
477  ( CRYPT_ERROR_BADDATA, errorInfo,
478  "Invalid PKCS #15 content wrapped in AuthData" ) );
479  }
480  }
481 
482  /* If it's indefinite-length data, don't try and go any further (the
483  general length check below will also catch this, but we make the
484  check explicit here) */
485  if( endPos == CRYPT_UNUSED )
486  {
488  ( CRYPT_ERROR_BADDATA, errorInfo,
489  "Can't process indefinite-length PKCS #15 content" ) );
490  }
491 
492  /* Make sure that the length information is sensible. readCMSheader()
493  reads the version number field at the start of the content so we have
494  to adjust the stream position for this when we calculate the data end
495  position */
496  currentPos = stell( stream ) - sizeofShortInteger( 0 );
497  if( endPos < 16 + MIN_OBJECT_SIZE || \
498  currentPos + endPos >= MAX_INTLENGTH )
499  {
501  ( CRYPT_ERROR_BADDATA, errorInfo,
502  "Invalid PKCS #15 keyset length information" ) );
503  }
504  *endPosPtr = currentPos + endPos;
505 
506  /* Skip the key management information if there is any and read the
507  inner wrapper */
508  status = value = peekTag( stream );
509  if( cryptStatusError( status ) )
510  return( status );
511  if( value == MAKE_CTAG( 0 ) )
512  readUniversal( stream );
513  return( readLongSequence( stream, NULL ) );
514  }
515 
516 /****************************************************************************
517 * *
518 * Init/Shutdown Functions *
519 * *
520 ****************************************************************************/
521 
522 /* A PKCS #15 keyset can contain multiple keys and whatnot, so when we open
523  it we parse the contents into memory for later use */
524 
526 static int initFunction( INOUT KEYSET_INFO *keysetInfoPtr,
527  STDC_UNUSED const char *name,
528  STDC_UNUSED const int nameLength,
529  IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )
530  {
531  PKCS15_INFO *pkcs15info;
532  STREAM *stream = &keysetInfoPtr->keysetFile->stream;
533  long endPos = DUMMY_INIT;
534  int status;
535 
536  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
537 
538  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
539  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
540  REQUIRES( name == NULL && nameLength == 0 );
541  REQUIRES( options >= CRYPT_KEYOPT_NONE && options < CRYPT_KEYOPT_LAST );
542 
543  /* If we're opening an existing keyset skip the outer header, optional
544  keyManagementInfo, and inner header. We do this before we perform any
545  setup operations to weed out potential problem keysets */
546  if( options != CRYPT_KEYOPT_CREATE )
547  {
548  status = readPkcs15header( stream, &endPos, KEYSET_ERRINFO );
549  if( cryptStatusError( status ) )
550  return( status );
551  }
552 
553  /* Allocate the PKCS #15 object information */
554  if( ( pkcs15info = clAlloc( "initFunction", \
555  sizeof( PKCS15_INFO ) * \
556  MAX_PKCS15_OBJECTS ) ) == NULL )
557  {
558  if( options != CRYPT_KEYOPT_CREATE )
559  {
560  /* Reset the stream position to account for the header
561  information that we've already read */
562  sseek( stream, 0 ) ;
563  }
564  return( CRYPT_ERROR_MEMORY );
565  }
566  memset( pkcs15info, 0, sizeof( PKCS15_INFO ) * MAX_PKCS15_OBJECTS );
567  keysetInfoPtr->keyData = pkcs15info;
568  keysetInfoPtr->keyDataSize = sizeof( PKCS15_INFO ) * MAX_PKCS15_OBJECTS;
569  keysetInfoPtr->keyDataNoObjects = MAX_PKCS15_OBJECTS;
570 
571  /* If this is a newly-created keyset, there's nothing left to do */
572  if( options == CRYPT_KEYOPT_CREATE )
573  return( CRYPT_OK );
574 
575  /* Read all of the keys in the keyset */
576  status = readPkcs15Keyset( &keysetInfoPtr->keysetFile->stream,
577  pkcs15info, MAX_PKCS15_OBJECTS, endPos,
578  KEYSET_ERRINFO );
579  if( cryptStatusError( status ) )
580  {
581  pkcs15Free( pkcs15info, MAX_PKCS15_OBJECTS );
582  clFree( "initFunction", keysetInfoPtr->keyData );
583  keysetInfoPtr->keyData = NULL;
584  keysetInfoPtr->keyDataSize = 0;
585  if( options != CRYPT_KEYOPT_CREATE )
586  {
587  /* Reset the stream position to account for the header
588  information that we've already read */
589  sseek( stream, 0 ) ;
590  }
591  return( status );
592  }
593 
594  return( CRYPT_OK );
595  }
596 
597 /* Shut down the PKCS #15 state, flushing information to disk if necessary */
598 
599 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
600 static int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )
601  {
602  int status = CRYPT_OK;
603 
604  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
605 
606  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
607  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
608 
609  /* If the contents have been changed, allocate a working I/O buffer for
610  the duration of the flush and commit the changes to disk */
611  if( keysetInfoPtr->flags & KEYSET_DIRTY )
612  {
613  STREAM *stream = &keysetInfoPtr->keysetFile->stream;
614  BYTE buffer[ STREAM_BUFSIZE + 8 ];
615 
616  sseek( stream, 0 );
617  sioctlSetString( stream, STREAM_IOCTL_IOBUFFER, buffer,
618  STREAM_BUFSIZE );
619  status = pkcs15Flush( stream, keysetInfoPtr->keyData,
620  keysetInfoPtr->keyDataNoObjects );
621  sioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );
622  if( status == OK_SPECIAL )
623  {
624  keysetInfoPtr->flags |= KEYSET_EMPTY;
625  status = CRYPT_OK;
626  }
627  }
628 
629  /* Free the PKCS #15 object information */
630  if( keysetInfoPtr->keyData != NULL )
631  {
632  pkcs15Free( keysetInfoPtr->keyData, keysetInfoPtr->keyDataNoObjects );
633  zeroise( keysetInfoPtr->keyData, keysetInfoPtr->keyDataSize );
634  clFree( "shutdownFunction", keysetInfoPtr->keyData );
635  }
636 
637  if( cryptStatusError( status ) )
638  {
639  retExt( status,
640  ( status, KEYSET_ERRINFO,
641  "Couldn't send PKCS #15 data to persistent storage" ) );
642  }
643 
644  return( CRYPT_OK );
645  }
646 
647 /****************************************************************************
648 * *
649 * Keyset Access Routines *
650 * *
651 ****************************************************************************/
652 
654 int setAccessMethodPKCS15( INOUT KEYSET_INFO *keysetInfoPtr )
655  {
656  int status;
657 
658  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
659 
660  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
661  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
662 
663  /* Set the access method pointers */
664  keysetInfoPtr->initFunction = initFunction;
665  keysetInfoPtr->shutdownFunction = shutdownFunction;
666  status = initPKCS15get( keysetInfoPtr );
667  if( cryptStatusOK( status ) )
668  status = initPKCS15set( keysetInfoPtr );
669  return( status );
670  }
671 #endif /* USE_PKCS15 */