cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs15_get.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #15 Get-item 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 "keyset.h"
12  #include "pkcs15.h"
13 #else
14  #include "crypt.h"
15  #include "enc_dec/asn1.h"
16  #include "keyset/keyset.h"
17  #include "keyset/pkcs15.h"
18 #endif /* Compiler-specific includes */
19 
20 #ifdef USE_PKCS15
21 
22 /****************************************************************************
23 * *
24 * Utility Functions *
25 * *
26 ****************************************************************************/
27 
28 /* Set any optional attributes that may be associated with a key */
29 
31 static int setKeyAttributes( IN_HANDLE const CRYPT_HANDLE iCryptHandle,
33  IN_FLAGS_Z( ACTION_PERM ) const int actionFlags )
34  {
35  int status;
36 
37  assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
38 
39  REQUIRES( isHandleRangeValid( iCryptHandle ) );
40  REQUIRES( actionFlags >= ACTION_PERM_FLAG_NONE && \
41  actionFlags < ACTION_PERM_FLAG_MAX );
42  /* This check is a bit odd because normally an action flag
43  value of ACTION_PERM_FLAG_NONE would indicate that the
44  object can't be used, but setting it to CRYPT_UNUSED would
45  create a value outside the normal allowed range so we use
46  _NONE to indicate a don't-care value */
47 
48  if( actionFlags != 0 )
49  {
50  status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
51  ( MESSAGE_CAST ) &actionFlags,
52  CRYPT_IATTRIBUTE_ACTIONPERMS );
53  if( cryptStatusError( status ) )
54  return( status );
55  }
56  if( pkcs15infoPtr->openPGPKeyIDlength > 0 )
57  {
59 
60  setMessageData( &msgData, ( MESSAGE_CAST ) pkcs15infoPtr->openPGPKeyID,
61  pkcs15infoPtr->openPGPKeyIDlength );
62  status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
63  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
64  if( cryptStatusError( status ) )
65  return( status );
66  }
67  if( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )
68  {
70 
71  /* This isn't really used for anything but is required to generate
72  the OpenPGP keyID, which includes the key creation time in the
73  ID-generation process */
74  setMessageData( &msgData, ( MESSAGE_CAST ) &pkcs15infoPtr->validFrom,
75  sizeof( time_t ) );
76  status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
77  &msgData, CRYPT_IATTRIBUTE_PGPVALIDITY );
78  if( cryptStatusError( status ) )
79  return( status );
80  }
81 
82  return( CRYPT_OK );
83  }
84 
85 /* Get an encoded trusted certificate */
86 
87 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
89  const PKCS15_INFO *pkcs15info,
92  IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength,
94  const BOOLEAN resetCertIndex )
95  {
96  static int trustedCertIndex;
98  int certStartOffset, certDataTotalSize;
99 
100  assert( isReadPtr( pkcs15info, \
101  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
102  assert( isWritePtr( data, dataMaxLength ) );
103  assert( isWritePtr( dataLength, sizeof( int ) ) );
104 
105  REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
106  REQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );
107 
108  /* Clear return values */
109  memset( data, 0, min( 16, dataMaxLength ) );
110  *dataLength = 0;
111 
112  /* If this is the first certificate, reset the index value. This is
113  pretty ugly since this sort of state-information value should be
114  stored with the caller, however there's no way to pass this back and
115  forth in a MESSAGE_DATA without resorting to an even uglier hack and
116  it's safe since this attribute is only ever read by the init thread
117  when it reads the configuration data at startup */
118  if( resetCertIndex )
119  trustedCertIndex = 0;
120  else
121  {
122  /* Move on to the next certificate */
123  if( trustedCertIndex >= noPkcs15objects - 1 )
124  return( CRYPT_ERROR_NOTFOUND );
125  trustedCertIndex++;
126  }
127 
128  /* Find the next trusted certificate */
129  for( pkcs15infoPtr = NULL;
130  trustedCertIndex < noPkcs15objects && \
131  trustedCertIndex < FAILSAFE_ITERATIONS_MED; trustedCertIndex++ )
132  {
133  if( pkcs15info[ trustedCertIndex ].implicitTrust )
134  {
135  pkcs15infoPtr = &pkcs15info[ trustedCertIndex ];
136  break;
137  }
138  }
139  ENSURES( trustedCertIndex < FAILSAFE_ITERATIONS_MED );
140  if( pkcs15infoPtr == NULL )
141  return( CRYPT_ERROR_NOTFOUND );
142  certStartOffset = pkcs15infoPtr->certOffset;
143  certDataTotalSize = pkcs15infoPtr->certDataSize;
144 
145  /* Return the data to the caller */
146  REQUIRES( rangeCheck( certStartOffset,
147  certDataTotalSize - certStartOffset,
148  certDataTotalSize ) );
149  return( attributeCopyParams( data, dataMaxLength, dataLength,
150  ( BYTE * ) pkcs15infoPtr->certData + certStartOffset,
151  certDataTotalSize - certStartOffset ) );
152  }
153 
154 /* Get an encoded configuration item */
155 
156 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
157 static int getConfigItem( IN_ARRAY( noPkcs15objects ) \
158  const PKCS15_INFO *pkcs15info,
159  IN_LENGTH_SHORT const int noPkcs15objects,
161  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) void *data,
162  IN_LENGTH_SHORT_Z const int dataMaxLength,
163  OUT_LENGTH_SHORT_Z int *dataLength )
164  {
165  const PKCS15_INFO *pkcs15infoPtr;
166  int dataStartOffset, dataTotalSize, i;
167 
168  assert( isReadPtr( pkcs15info, \
169  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
170  assert( ( data == NULL && dataMaxLength == 0 ) || \
171  isWritePtr( data, dataMaxLength ) );
172  assert( isWritePtr( dataLength, sizeof( int ) ) );
173 
174  REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
175  REQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
176  dataType == CRYPT_IATTRIBUTE_USERINDEX || \
177  dataType == CRYPT_IATTRIBUTE_USERINFO );
178  REQUIRES( ( data == NULL && dataMaxLength == 0 ) || \
179  ( data != NULL && \
180  dataMaxLength >= 16 && \
181  dataMaxLength < MAX_INTLENGTH_SHORT ) );
182 
183  /* Clear return values */
184  *dataLength = 0;
185  if( data != NULL )
186  memset( data, 0, min( 16, dataMaxLength ) );
187 
188  /* Find the particular data type that we're looking for */
189  for( pkcs15infoPtr = NULL, i = 0;
190  i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
191  {
192  if( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_DATA && \
193  pkcs15info[ i ].dataType == dataType ) )
194  {
195  pkcs15infoPtr = &pkcs15info[ i ];
196  break;
197  }
198  }
199  ENSURES( i < FAILSAFE_ITERATIONS_MED );
200  if( pkcs15infoPtr == NULL )
201  return( CRYPT_ERROR_NOTFOUND );
202  dataStartOffset = pkcs15infoPtr->dataOffset;
203  dataTotalSize = pkcs15infoPtr->dataDataSize;
204 
205  /* If it's just a length check, we're done */
206  if( data == NULL )
207  {
208  *dataLength = dataTotalSize - dataStartOffset;
209  return( CRYPT_OK );
210  }
211 
212  /* Return the data to the caller */
213  REQUIRES( rangeCheck( dataStartOffset,
214  dataTotalSize - dataStartOffset,
215  dataTotalSize ) );
216  return( attributeCopyParams( data, dataMaxLength, dataLength,
217  ( BYTE * ) pkcs15infoPtr->dataData + dataStartOffset,
218  dataTotalSize - dataStartOffset ) );
219  }
220 
221 /****************************************************************************
222 * *
223 * Get a Key *
224 * *
225 ****************************************************************************/
226 
227 /* Read key data from a PKCS #15 collection */
228 
229 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
230 static int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
231  OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
232  IN_ENUM( KEYMGMT_ITEM ) \
233  const KEYMGMT_ITEM_TYPE itemType,
235  IN_BUFFER( keyIDlength ) const void *keyID,
236  IN_LENGTH_KEYID const int keyIDlength,
237  IN_OPT void *auxInfo,
239  IN_FLAGS_Z( KEYMGMT ) const int flags )
240  {
241  CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
243  const PKCS15_INFO *pkcs15infoPtr;
245  const BOOLEAN publicComponentsOnly = \
246  ( itemType != KEYMGMT_ITEM_PRIVATEKEY ) ? TRUE : FALSE;
247  const BOOLEAN isStorageObject = \
248  ( keysetInfoPtr->keysetFile->iHardwareDevice != CRYPT_UNUSED ) ? \
249  TRUE : FALSE;
250  const int auxInfoMaxLength = *auxInfoLength;
251  int pubkeyActionFlags = 0, privkeyActionFlags = 0, status;
252 
253  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
254  assert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );
255  assert( isReadPtr( keyID, keyIDlength ) );
256  assert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \
257  isReadPtr( auxInfo, auxInfoMaxLength ) );
258 
259  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
260  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
261  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
262  itemType == KEYMGMT_ITEM_PRIVATEKEY );
263  REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
264  keyIDtype == CRYPT_KEYID_URI || \
265  keyIDtype == CRYPT_IKEYID_KEYID || \
266  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
267  keyIDtype == CRYPT_IKEYID_ISSUERID );
268  REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
269  keyIDlength < MAX_ATTRIBUTE_SIZE );
270  REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
271  ( auxInfo != NULL && \
272  *auxInfoLength > 0 && \
273  *auxInfoLength < MAX_INTLENGTH_SHORT ) );
274  REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
275 
276  /* Clear return values */
277  *iCryptHandle = CRYPT_ERROR;
278 
279  /* Locate the appropriate object in the PKCS #15 collection and make
280  sure that the components that we need are present: Either a public
281  key or a certificate for any type of read, and a private key as well
282  for a private-key read */
283  pkcs15infoPtr = findEntry( keysetInfoPtr->keyData,
284  keysetInfoPtr->keyDataNoObjects, keyIDtype,
285  keyID, keyIDlength, flags );
286  if( pkcs15infoPtr == NULL )
287  {
290  "No information present for this ID" ) );
291  }
292  if( pkcs15infoPtr->pubKeyData == NULL && \
293  pkcs15infoPtr->certData == NULL )
294  {
295  /* There's not enough information present to get a public key or the
296  public portions of a private key */
299  "No public key or certificate data present for this ID" ) );
300  }
301  if( !publicComponentsOnly && pkcs15infoPtr->privKeyData == NULL )
302  {
303  /* There's not enough information present to get a private key */
306  "No private key data present for this ID" ) );
307  }
308 
309  /* If we're just checking whether an object exists, return now. If all
310  that we want is the key label, copy it back to the caller and exit */
311  if( flags & KEYMGMT_FLAG_CHECK_ONLY )
312  return( CRYPT_OK );
313  if( flags & KEYMGMT_FLAG_LABEL_ONLY )
314  {
315  return( attributeCopyParams( auxInfo, auxInfoMaxLength,
316  auxInfoLength, pkcs15infoPtr->label,
317  pkcs15infoPtr->labelLength ) );
318  }
319 
320  /* If we're reading the private key and this isn't a PKCS #15 object
321  store (which only contains metadata for private keys), make sure that
322  the user has supplied a password. This is checked by the kernel but
323  we perform another check here just to be safe*/
324  if( !publicComponentsOnly && !isStorageObject && auxInfo == NULL )
325  return( CRYPT_ERROR_WRONGKEY );
326 
327  /* Read the public components */
328  status = readPublicKeyComponents( pkcs15infoPtr, keysetInfoPtr->objectHandle,
329  keyIDtype, keyID, keyIDlength,
330  publicComponentsOnly,
331  isStorageObject ? \
332  keysetInfoPtr->keysetFile->iHardwareDevice : \
334  &iCryptContext, &iDataCert,
335  &pubkeyActionFlags,
336  &privkeyActionFlags, KEYSET_ERRINFO );
337  if( cryptStatusError( status ) )
338  return( status );
339 
340  /* If we're only interested in the public components, set the key
341  permissions and exit */
342  if( publicComponentsOnly )
343  {
344  status = setKeyAttributes( iCryptContext, pkcs15infoPtr,
345  ( pkcs15infoPtr->pubKeyData != NULL ) ? \
346  pubkeyActionFlags : 0 );
347  if( cryptStatusError( status ) )
348  {
349  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
350  retExt( status,
351  ( status, KEYSET_ERRINFO,
352  "Couldn't set PKCS #15 permitted action flags for "
353  "the key" ) );
354  }
355  *iCryptHandle = iCryptContext;
356 
357  return( CRYPT_OK );
358  }
359 
360  REQUIRES( ( pkcs15infoPtr->pubKeyData != NULL || \
361  pkcs15infoPtr->certData != NULL ) && \
362  pkcs15infoPtr->privKeyData != NULL );
363 
364  /* Set the key label and read the private key components. We have to
365  set the label before we load the key or the key load will be blocked
366  by the kernel. In addition if this keyset is a device object store
367  we have to set the label as a CRYPT_IATTRIBUTE_EXISTINGLABEL
368  otherwise the existing item's label will be erroneously reported as
369  a duplicate */
370  if( pkcs15infoPtr->labelLength > 0 )
371  { setMessageData( &msgData, ( MESSAGE_CAST ) pkcs15infoPtr->label,
372  min( pkcs15infoPtr->labelLength, \
373  CRYPT_MAX_TEXTSIZE ) ); }
374  else
375  { setMessageData( &msgData, ( MESSAGE_CAST ) "Dummy label", 11 ); }
376  status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
377  &msgData, isStorageObject ? \
378  CRYPT_IATTRIBUTE_EXISTINGLABEL : \
380  if( cryptStatusOK( status ) )
381  {
382  status = readPrivateKeyComponents( pkcs15infoPtr, iCryptContext,
383  auxInfo, *auxInfoLength, isStorageObject,
384  KEYSET_ERRINFO );
385  }
386  if( cryptStatusError( status ) )
387  {
388  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
389  if( iDataCert != CRYPT_ERROR )
391  return( status );
392  }
393 
394  /* Connect the data-only certificate object to the context if it exists.
395  This is an internal object used only by the context so we tell the
396  kernel to mark it as owned by the context only */
397  if( iDataCert != CRYPT_ERROR )
398  {
399  status = krnlSendMessage( iCryptContext, IMESSAGE_SETDEPENDENT,
400  &iDataCert, SETDEP_OPTION_NOINCREF );
401  if( cryptStatusError( status ) )
402  {
403  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
405  retExt( status,
406  ( status, KEYSET_ERRINFO,
407  "Couldn't attach certificate to key" ) );
408  }
409  }
410 
411  /* Set the permitted action flags */
412  status = setKeyAttributes( iCryptContext, pkcs15infoPtr,
413  privkeyActionFlags );
414  if( cryptStatusError( status ) )
415  {
416  krnlSendNotifier( iCryptContext, MESSAGE_DECREFCOUNT );
417  retExt( status,
418  ( status, KEYSET_ERRINFO,
419  "Couldn't set PKCS #15 permitted action flags for the "
420  "key" ) );
421  }
422 
423  *iCryptHandle = iCryptContext;
424  return( CRYPT_OK );
425  }
426 
427 /* Read special data from a PKCS #15 collection */
428 
429 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
430 static int getSpecialItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
431  IN_ATTRIBUTE \
432  const CRYPT_ATTRIBUTE_TYPE dataType,
433  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \
434  void *data,
435  IN_LENGTH_SHORT_Z const int dataMaxLength,
436  OUT_LENGTH_SHORT_Z int *dataLength )
437  {
438  assert( ( data == NULL && dataMaxLength == 0 ) || \
439  isWritePtr( data, dataMaxLength ) );
440  assert( isWritePtr( dataLength, sizeof( int ) ) );
441 
442  REQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
443  dataType == CRYPT_IATTRIBUTE_USERINDEX || \
444  dataType == CRYPT_IATTRIBUTE_USERINFO || \
445  dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT || \
446  dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );
447  REQUIRES( ( data == NULL && dataMaxLength == 0 ) || \
448  ( data != NULL && \
449  dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT ) );
450  REQUIRES( ( dataType != CRYPT_IATTRIBUTE_TRUSTEDCERT && \
451  dataType != CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT ) || \
452  data != NULL );
453 
454  /* Clear return values */
455  if( data != NULL )
456  memset( data, 0, min( 16, dataMaxLength ) );
457  *dataLength = 0;
458 
459  /* If we're being asked for pre-encoded trusted certificate data, return
460  it to the caller */
461  if( dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT || \
462  dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT )
463  {
464  return( getTrustedCert( keysetInfoPtr->keyData,
465  keysetInfoPtr->keyDataNoObjects,
466  data, dataMaxLength, dataLength,
467  ( dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT ) ? \
468  TRUE : FALSE ) );
469  }
470 
471  /* Return a configuration data item */
472  return( getConfigItem( keysetInfoPtr->keyData,
473  keysetInfoPtr->keyDataNoObjects, dataType,
474  data, dataMaxLength, dataLength ) );
475  }
476 
477 /* Fetch a sequence of certificates. These functions are called indirectly
478  by the certificate code to fetch the first and subsequent certificates in
479  a certificate chain. The 'stateInfo' value is handled as an OUT parameter
480  rather than the more obvious INOUT since the state is managed explicitly
481  by the caller, who uses it to pass in a next-key-ID reference instead of
482  a current-key-ID one */
483 
484 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 10 ) ) \
485 static int getItem( INOUT_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info,
486  IN_LENGTH_SHORT const int noPkcs15objects,
488  OUT int *stateInfo,
489  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
490  IN_BUFFER( keyIDlength ) const void *keyID,
491  IN_LENGTH_KEYID const int keyIDlength,
492  IN_ENUM( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType,
493  IN_FLAGS_Z( KEYMGMT ) const int options,
495  {
496  MESSAGE_CREATEOBJECT_INFO createInfo;
497  const PKCS15_INFO *pkcs15infoPtr;
498  BYTE *certDataPtr;
499  int certStartOffset, certDataTotalSize, tag, status;
500 
501  assert( isWritePtr( pkcs15info, \
502  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
503  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
504  assert( isReadPtr( stateInfo, sizeof( int ) ) );
505  assert( isReadPtr( keyID, keyIDlength ) );
506 
507  REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
508  REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
509  keyIDtype == CRYPT_KEYID_URI || \
510  keyIDtype == CRYPT_IKEYID_KEYID || \
511  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
512  keyIDtype == CRYPT_IKEYID_ISSUERID || \
513  keyIDtype == CRYPT_KEYIDEX_SUBJECTNAMEID );
514  REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
515  keyIDlength < MAX_ATTRIBUTE_SIZE );
516  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );
517  REQUIRES( options >= KEYMGMT_FLAG_NONE && \
518  options < KEYMGMT_FLAG_MAX );
519  REQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \
520  KEYMGMT_MASK_USAGEOPTIONS );
521  REQUIRES( errorInfo != NULL );
522 
523  /* Clear return values */
524  *iCertificate = CRYPT_ERROR;
525  *stateInfo = CRYPT_ERROR;
526 
527  /* Find the appropriate entry based on the ID */
528  pkcs15infoPtr = findEntry( pkcs15info, noPkcs15objects, keyIDtype,
529  keyID, keyIDlength, options );
530  if( pkcs15infoPtr == NULL )
531  return( CRYPT_ERROR_NOTFOUND );
532  *stateInfo = pkcs15infoPtr->index;
533 
534  /* Import the certificate. This gets somewhat ugly because early drafts
535  of PKCS #15 wrote the certificate as is while the final version
536  wrapped it up in a [0] IMPLICIT tag so we can run into both the
537  original untagged SEQUENCE form and the newer [0] IMPLICIT SEQUENCE.
538  To handle this we dynamically replace the tag with the standard
539  SEQUENCE tag and reinstate the original afterwards, this is easier
540  than trying to pass the special-case decoding requirement down
541  through the kernel call */
542  certDataPtr = ( BYTE * ) pkcs15infoPtr->certData + \
543  pkcs15infoPtr->certOffset;
544  certStartOffset = pkcs15infoPtr->certOffset;
545  certDataTotalSize = pkcs15infoPtr->certDataSize;
546  tag = *certDataPtr;
547  *certDataPtr = BER_SEQUENCE;
548  REQUIRES( rangeCheck( certStartOffset,
549  certDataTotalSize - certStartOffset,
550  certDataTotalSize ) );
551  setMessageCreateObjectIndirectInfo( &createInfo, certDataPtr,
552  certDataTotalSize - certStartOffset,
553  ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
554  CRYPT_ICERTTYPE_DATAONLY : \
558  &createInfo, OBJECT_TYPE_CERTIFICATE );
559  *certDataPtr = intToByte( tag );
560  if( cryptStatusError( status ) )
561  {
562  retExt( status,
563  ( status, errorInfo,
564  "Couldn't create certificate from stored certificate "
565  "data" ) );
566  }
567  *iCertificate = createInfo.cryptHandle;
568  if( pkcs15infoPtr->validFrom <= MIN_TIME_VALUE )
569  {
570  /* Perform an opportunistic update of the validity information if
571  this hasn't already been set. Since this is a purely
572  opportunistic update we ignore any return value */
573  ( void ) getValidityInfo( pkcs15info, createInfo.cryptHandle );
574  }
575  return( CRYPT_OK );
576  }
577 
578 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \
579 static int getFirstItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
580  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
581  OUT int *stateInfo,
582  IN_ENUM( KEYMGMT_ITEM ) \
583  const KEYMGMT_ITEM_TYPE itemType,
584  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
585  IN_BUFFER( keyIDlength ) const void *keyID,
586  IN_LENGTH_KEYID const int keyIDlength,
587  IN_FLAGS_Z( KEYMGMT ) const int options )
588  {
589  PKCS15_INFO *pkcs15info = keysetInfoPtr->keyData;
590  const int noPkcs15objects = keysetInfoPtr->keyDataNoObjects;
591 
592  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
593  assert( isWritePtr( pkcs15info, \
594  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
595  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
596  assert( isReadPtr( stateInfo, sizeof( int ) ) );
597  assert( isReadPtr( keyID, keyIDlength ) );
598 
599  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
600  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
601  REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
602  keyIDtype == CRYPT_KEYID_URI || \
603  keyIDtype == CRYPT_IKEYID_KEYID || \
604  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
605  keyIDtype == CRYPT_IKEYID_ISSUERID );
606  REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
607  keyIDlength < MAX_ATTRIBUTE_SIZE );
608  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );
609  REQUIRES( options >= KEYMGMT_FLAG_NONE && \
610  options < KEYMGMT_FLAG_MAX );
611  REQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \
612  KEYMGMT_MASK_USAGEOPTIONS );
613 
614  /* Clear return values */
615  *iCertificate = CRYPT_ERROR;
616  *stateInfo = CRYPT_ERROR;
617 
618  return( getItem( pkcs15info, noPkcs15objects, iCertificate, stateInfo,
619  keyIDtype, keyID, keyIDlength, itemType, options,
620  KEYSET_ERRINFO ) );
621  }
622 
623 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
624 static int getNextItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
625  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
626  INOUT int *stateInfo,
627  IN_FLAGS_Z( KEYMGMT ) const int options )
628  {
629  PKCS15_INFO *pkcs15info = keysetInfoPtr->keyData;
630  const int noPkcs15objects = keysetInfoPtr->keyDataNoObjects;
631  const int lastEntry = *stateInfo;
632  int status;
633 
634  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
635  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
636  assert( isWritePtr( stateInfo, sizeof( int ) ) );
637  assert( isWritePtr( pkcs15info, \
638  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
639 
640  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
641  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
642  REQUIRES( options >= KEYMGMT_FLAG_NONE && options < KEYMGMT_FLAG_MAX && \
643  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );
644  REQUIRES( ( lastEntry >= 0 && lastEntry < noPkcs15objects ) || \
645  lastEntry == CRYPT_ERROR );
646 
647  /* Clear return values */
648  *iCertificate = CRYPT_ERROR;
649  *stateInfo = CRYPT_ERROR;
650 
651  /* If the previous certificate was the last one, there's nothing left to
652  fetch */
653  if( lastEntry == CRYPT_ERROR )
654  {
657  "No more items present" ) );
658  }
659  ENSURES( lastEntry >= 0 && lastEntry < noPkcs15objects );
660 
661  /* If there's no index information present to locate other certificates,
662  we can't go any further */
663  if( pkcs15info[ lastEntry ].issuerNameIDlength <= 0 )
664  {
667  "No index information available to locate other "
668  "certificates" ) );
669  }
670 
671  /* Find the certificate for which the subjectNameID matches this
672  certificate's issuerNameID */
673  status = getItem( pkcs15info, noPkcs15objects, iCertificate, stateInfo,
675  pkcs15info[ lastEntry ].issuerNameID,
676  pkcs15info[ lastEntry ].issuerNameIDlength,
678  if( cryptStatusError( status ) )
679  return( status );
680  ENSURES( lastEntry != *stateInfo ); /* Loop detection */
681 
682  return( CRYPT_OK );
683  }
684 
685 /****************************************************************************
686 * *
687 * Keyset Access Routines *
688 * *
689 ****************************************************************************/
690 
692 int initPKCS15get( KEYSET_INFO *keysetInfoPtr )
693  {
694  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
695 
696  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
697  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
698 
699  /* Set the access method pointers */
700  keysetInfoPtr->getItemFunction = getItemFunction;
701  keysetInfoPtr->getSpecialItemFunction = getSpecialItemFunction;
702  keysetInfoPtr->getFirstItemFunction = getFirstItemFunction;
703  keysetInfoPtr->getNextItemFunction = getNextItemFunction;
704 
705  return( CRYPT_OK );
706  }
707 #endif /* USE_PKCS15 */