cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs12_rd.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #12 Read Routines *
4 * Copyright Peter Gutmann 1997-2010 *
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 "pkcs12.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/pkcs12.h"
20 #endif /* Compiler-specific includes */
21 
22 #ifdef USE_PKCS12
23 
24 /* OID information used to read a PKCS #12 keyset */
25 
26 static const CMS_CONTENT_INFO FAR_BSS oidInfoEncryptedData = { 0, 2 };
27 
28 static const FAR_BSS OID_INFO keyDataOIDinfo[] = {
29  { OID_CMS_ENCRYPTEDDATA, TRUE, &oidInfoEncryptedData },
30  { OID_CMS_DATA, FALSE },
31  { NULL, 0 }, { NULL, 0 }
32  };
33 
34 /* OID information used to read decrypted PKCS #12 objects */
35 
36 static const FAR_BSS OID_INFO certBagOIDinfo[] = {
37  { OID_PKCS12_CERTBAG, 0 },
38  { NULL, 0 }, { NULL, 0 }
39  };
40 static const FAR_BSS OID_INFO certOIDinfo[] = {
42  { NULL, 0 }, { NULL, 0 }
43  };
44 
45 /****************************************************************************
46 * *
47 * Utility Functions *
48 * *
49 ****************************************************************************/
50 
51 /* Copy PKCS #12 object information. If there's already content present in
52  the destination information then we copy in additional information, for
53  example to augment existing private-key data with an associated
54  certificate or vice-versa */
55 
56 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
57 static void copyObjectInfo( INOUT PKCS12_INFO *destPkcs12Info,
58  const PKCS12_INFO *srcPkcs12Info,
59  const BOOLEAN isCertificate )
60  {
61  assert( isWritePtr( destPkcs12Info, sizeof( PKCS12_INFO ) ) );
62  assert( isReadPtr( srcPkcs12Info, sizeof( PKCS12_INFO ) ) );
63 
64  destPkcs12Info->flags |= srcPkcs12Info->flags;
65  if( isCertificate )
66  {
67  memcpy( &destPkcs12Info->certInfo, &srcPkcs12Info->certInfo,
68  sizeof( PKCS12_OBJECT_INFO ) );
69  }
70  else
71  {
72  memcpy( &destPkcs12Info->keyInfo, &srcPkcs12Info->keyInfo,
73  sizeof( PKCS12_OBJECT_INFO ) );
74  }
75  if( destPkcs12Info->labelLength <= 0 && \
76  srcPkcs12Info->labelLength > 0 )
77  {
78  memcpy( destPkcs12Info->label, srcPkcs12Info->label,
79  srcPkcs12Info->labelLength );
80  destPkcs12Info->labelLength = srcPkcs12Info->labelLength;
81  }
82  if( destPkcs12Info->idLength <= 0 && \
83  srcPkcs12Info->idLength > 0 )
84  {
85  memcpy( destPkcs12Info->id, srcPkcs12Info->id,
86  srcPkcs12Info->idLength );
87  destPkcs12Info->idLength = srcPkcs12Info->idLength;
88  }
89  }
90 
91 /* PKCS #12's lack of useful indexing information makes it extremely
92  difficult to reliably track and match up object types like private keys
93  and certificates. The PKCS #15 code simply does a findEntry() to find
94  the entry that matches a newly-read object and attaches it to whatever's
95  already present for an existing entry if required (so for example it'd
96  attach a certificate to a previously-read private key), however with PKCS
97  #12 there's no reliable way to do this since entries may or may not have
98  ID information attached, which makes it impossible to reliably attach
99  keys to certificates.
100 
101  To deal with this as best we can, we apply the following strategy:
102 
103  1. For the first item read, we save it as is in the zero-th position
104  (the item may or may not have an ID attached, typically if it's an
105  encrypted certificate then it won't, if it's a private key then it
106  will).
107 
108  2. For subsequent items read, if there's no ID information present then
109  we assume that it's attached to the previously-read first entry
110  provided that it's compatible with it, for example an ID-less
111  encrypted certificate attached to an encrypted key. The "no ID
112  information present" can mean either that the currently-read item has
113  no ID information or that the first item has no ID information.
114 
115  3. If there's ID information attached, we handle it as we would for a
116  PKCS #15 item */
117 
118 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
119 static int findObjectEntryLocation( OUT_PTR PKCS12_INFO **pkcs12infoPtrPtr,
121  const PKCS12_INFO *pkcs12info,
123  IN_BUFFER_OPT( idLength ) const void *id,
124  IN_LENGTH_KEYID_Z const int idLength,
125  IN_FLAGS( PKCS12 ) const int flags )
126 
127  {
128  const PKCS12_INFO *pkcs12firstItem = &pkcs12info[ 0 ];
129  const PKCS12_INFO *pkcs12infoPtr;
130  int index;
131 
132  assert( isReadPtr( pkcs12infoPtrPtr, sizeof( PKCS12_INFO * ) ) );
133  assert( isReadPtr( pkcs12info, sizeof( PKCS12_INFO ) * \
134  maxNoPkcs12objects ) );
135  assert( ( id == NULL && idLength == 0 ) || \
136  isReadPtr( id, idLength ) );
137 
138  REQUIRES( maxNoPkcs12objects >= 1 && \
139  maxNoPkcs12objects < MAX_INTLENGTH_SHORT );
140  REQUIRES( ( id == NULL && idLength == 0 ) || \
141  ( id != NULL && \
142  idLength > 0 && idLength < MAX_ATTRIBUTE_SIZE ) );
143 
144  /* Clear return value */
145  *pkcs12infoPtrPtr = NULL;
146 
147  /* If this is the first entry being added, just add it as is */
148  if( pkcs12FindFreeEntry( pkcs12info, maxNoPkcs12objects, \
149  &index ) != NULL && index == 0 )
150  {
151  *pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12firstItem;
152 
153  return( CRYPT_OK );
154  }
155 
156  /* If there's no ID information present, try and find an appropriate
157  existing item to attach it to. This can occur in two variations,
158  either the existing entry is EncryptedData containing a certificate
159  with no ID information and the newly-read item is a private key, or
160  the existing item is a private key with ID information and the newly-
161  read item is EncryptedData containing a certificate with no ID
162  information */
163  if( ( pkcs12firstItem->labelLength == 0 && \
164  pkcs12firstItem->idLength == 0 ) || id == NULL )
165  {
166  int i;
167 
168  /* If the combination of items isn't an encrypted certificate (which
169  has no ID data associated with it since it's EncryptedData) rather
170  than a non-encrypted certificate or a private key (which is Data
171  and should have ID data associated with it) then we can't process
172  it */
173  if( !( ( pkcs12firstItem->flags == PKCS12_FLAG_ENCCERT && \
174  flags == PKCS12_FLAG_PRIVKEY ) || \
175  ( pkcs12firstItem->flags == PKCS12_FLAG_PRIVKEY && \
176  flags == PKCS12_FLAG_ENCCERT ) ) )
177  return( CRYPT_ERROR_BADDATA );
178 
179  pkcs12infoPtr = NULL;
180  for( i = 0; i < maxNoPkcs12objects && \
181  i < FAILSAFE_ITERATIONS_MED; i++ )
182  {
183  /* If this entry isn't in use, continue */
184  if( pkcs12info[ i ].flags == PKCS12_FLAG_NONE )
185  continue;
186 
187  /* If we've already found a matching entry then finding a second
188  one is ambiguous since we don't know know which one to
189  associate the newly-read no-ID entry with */
190  if( pkcs12infoPtr != NULL )
191  return( CRYPT_ERROR_DUPLICATE );
192 
193  /* We've found a potential location to add the ID-less entry */
194  pkcs12infoPtr = &pkcs12info[ i ];
195  }
196  ENSURES( i < FAILSAFE_ITERATIONS_MED );
197  ENSURES( pkcs12infoPtr != NULL )
198  /* There's always a zero-th entry present to act as the
199  known elephant in Cairo */
200 
201  *pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12infoPtr;
202 
203  return( CRYPT_OK );
204  }
205 
206  /* There's an ID present, try and find a matching existing entry for
207  it */
208  pkcs12infoPtr = pkcs12FindEntry( pkcs12info, maxNoPkcs12objects,
209  CRYPT_IKEYID_KEYID, id, idLength );
210  if( pkcs12infoPtr != NULL )
211  {
212  *pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12infoPtr;
213 
214  return( CRYPT_OK );
215  }
216 
217  /* This personality isn't present yet, find out where we can add the
218  object data */
219  pkcs12infoPtr = pkcs12FindFreeEntry( pkcs12info, maxNoPkcs12objects,
220  NULL );
221  if( pkcs12infoPtr == NULL )
222  return( CRYPT_ERROR_OVERFLOW );
223  *pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12infoPtr;
224 
225  return( CRYPT_OK );
226  }
227 
228 /****************************************************************************
229 * *
230 * Import Keys/Certificates *
231 * *
232 ****************************************************************************/
233 
234 /* Unwrap and import an encrypted certificate */
235 
236 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 7 ) ) \
237 static int importCertificate( const PKCS12_OBJECT_INFO *certObjectInfo,
239  IN_BUFFER( passwordLen ) const void *password,
240  IN_LENGTH_NAME const int passwordLen,
241  INOUT_BUFFER_FIXED( certObjectDataLen ) \
242  void *certObjectData,
243  IN_LENGTH_SHORT const int certObjectDataLen,
244  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iDataCert )
245  {
246  CRYPT_CONTEXT iWrapContext;
247  STREAM stream;
248  long length;
249  int certDataSize, status;
250 
251  assert( isReadPtr( certObjectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );
252  assert( isReadPtr( password, passwordLen ) );
253  assert( isWritePtr( certObjectData, certObjectDataLen ) );
254  assert( isWritePtr( iDataCert, sizeof( CRYPT_CERTIFICATE ) ) );
255 
256  REQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
257  isHandleRangeValid( cryptOwner ) );
258  REQUIRES( passwordLen >= MIN_NAME_LENGTH && \
259  passwordLen <= CRYPT_MAX_TEXTSIZE );
260  REQUIRES( certObjectDataLen > MIN_OBJECT_SIZE && \
261  certObjectDataLen < MAX_INTLENGTH_SHORT );
262 
263  /* Clear return value */
264  *iDataCert = CRYPT_ERROR;
265 
266  /* Create the wrap context used to decrypt the public certificate data */
267  status = createPkcs12KeyWrapContext( ( PKCS12_OBJECT_INFO * ) certObjectInfo,
268  cryptOwner, password, passwordLen,
269  &iWrapContext, FALSE );
270  if( cryptStatusError( status ) )
271  return( status );
272 
273  /* Decrypt the certificate */
274  status = krnlSendMessage( iWrapContext, IMESSAGE_CTX_DECRYPT,
275  certObjectData, certObjectDataLen );
276  krnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );
277  if( cryptStatusError( status ) )
278  return( status );
279 
280  /* Make sure that the decryption succeeded. We have to be a bit careful
281  here because there are so many garbled certificates used with the
282  equally-garbled PKCS #12 format that an invalid object doesn't
283  necessarily imply that an incorrect decryption key was used. To
284  avoid false positives, if we get an invalid encoding we try and read
285  the outer layer of wrapping around the certificate object, and if
286  that succeeds then it's a valid decrypt of a garbled certificate
287  rather than an invalid key leading to an invalid certificate */
288  status = length = checkObjectEncoding( certObjectData,
289  certObjectDataLen );
290  if( cryptStatusError( status ) )
291  {
292  sMemConnect( &stream, certObjectData, certObjectDataLen );
293  readSequence( &stream, NULL );
294  status = readSequence( &stream, NULL );
295  sMemDisconnect( &stream );
296  return( cryptStatusError( status ) ? \
298  }
299  certDataSize = length;
300 
301  /* Import the certificate as a data-only certificate. At this point we
302  have two redundant CMS headers, one within the other, with the nested
303  inner header of the outer CMS header being the start of the inner CMS
304  header. To handle this we read the outer CMS header with the
305  READCMS_FLAG_WRAPPERONLY flag set to avoid reading the start of the
306  inner header, which is then read by the second readCMSheader()
307  call */
308  sMemConnect( &stream, certObjectData, certDataSize );
309  readSequence( &stream, NULL );
310  status = readCMSheader( &stream, certBagOIDinfo,
311  FAILSAFE_ARRAYSIZE( certBagOIDinfo, OID_INFO ),
312  NULL, READCMS_FLAG_WRAPPERONLY );
313  if( cryptStatusOK( status ) )
314  {
315  status = readCMSheader( &stream, certOIDinfo,
316  FAILSAFE_ARRAYSIZE( certOIDinfo, OID_INFO ),
317  &length, READCMS_FLAG_INNERHEADER | \
319  }
320  if( cryptStatusOK( status ) && \
321  ( length < MIN_OBJECT_SIZE || length > MAX_INTLENGTH_SHORT ) )
322  status = CRYPT_ERROR_BADDATA;
323  if( cryptStatusError( status ) )
324  {
325  sMemDisconnect( &stream );
326  return( status );
327  }
328  status = importCertFromStream( &stream, iDataCert, cryptOwner,
329  CRYPT_ICERTTYPE_DATAONLY,
330  ( int ) length );
331  sMemDisconnect( &stream );
332 
333  return( status );
334  }
335 
336 /* Import an encrypted private key */
337 
338 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 10 ) ) \
339 static int importPrivateKey( const PKCS12_OBJECT_INFO *keyObjectInfo,
340  IN_HANDLE const CRYPT_USER cryptOwner,
341  IN_BUFFER( passwordLen ) const void *password,
342  IN_LENGTH_NAME const int passwordLen,
343  IN_BUFFER( keyObjectDataLen ) const void *keyObjectData,
344  IN_LENGTH_SHORT const int keyObjectDataLen,
346  IN_BUFFER_OPT( labelLength ) const void *label,
347  IN_LENGTH_SHORT_Z const int labelLength,
349  {
350  CRYPT_CONTEXT iCryptContext, iWrapContext;
351  MESSAGE_CREATEOBJECT_INFO createInfo;
354  int status;
355 
356  assert( isReadPtr( keyObjectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );
357  assert( isReadPtr( password, passwordLen ) );
358  assert( isReadPtr( keyObjectData, keyObjectDataLen) );
359  assert( ( label == NULL && labelLength == 0 ) || \
360  isReadPtr( label, labelLength ) );
361  assert( isWritePtr( iPrivKeyContext, sizeof( CRYPT_CERTIFICATE ) ) );
362 
363  REQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
364  isHandleRangeValid( cryptOwner ) );
365  REQUIRES( passwordLen >= MIN_NAME_LENGTH && \
366  passwordLen <= CRYPT_MAX_TEXTSIZE );
367  REQUIRES( keyObjectDataLen > MIN_OBJECT_SIZE && \
368  keyObjectDataLen < MAX_INTLENGTH_SHORT );
369  REQUIRES( ( label == NULL && labelLength == 0 ) || \
370  ( label != NULL && \
371  labelLength > 0 && labelLength < MAX_INTLENGTH_SHORT ) );
372  REQUIRES( isPkcAlgo( cryptAlgo ) );
373 
374  /* Clear return value */
375  *iPrivKeyContext = CRYPT_ERROR;
376 
377  /* Create the wrap context used to unwrap the private key */
378  status = createPkcs12KeyWrapContext( ( PKCS12_OBJECT_INFO * ) keyObjectInfo,
379  cryptOwner, password, passwordLen,
380  &iWrapContext, FALSE );
381  if( cryptStatusError( status ) )
382  return( status );
383 
384  /* Create the private-key object that we'll be importing the key data
385  into and set the key label. We have to set the label before we load
386  the key or the key load will be blocked by the kernel */
387  setMessageCreateObjectInfo( &createInfo, cryptAlgo );
389  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
391  if( cryptStatusError( status ) )
392  {
393  krnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );
394  return( status );
395  }
396  iCryptContext = createInfo.cryptHandle;
397  if( label != NULL )
398  {
399  setMessageData( &msgData, ( MESSAGE_CAST ) label, \
400  min( labelLength, CRYPT_MAX_TEXTSIZE ) );
401  }
402  else
403  {
404  setMessageData( &msgData, ( MESSAGE_CAST ) "Dummy label", 11 );
405  }
406  status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
407  &msgData, CRYPT_CTXINFO_LABEL );
408  if( cryptStatusError( status ) )
409  {
410  krnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );
411  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
412  return( status );
413  }
414 
415  /* Import the encrypted private key into the PKC context */
416  setMechanismWrapInfo( &mechanismInfo, ( MESSAGE_CAST * ) keyObjectData,
417  keyObjectDataLen, NULL, 0, iCryptContext,
418  iWrapContext );
420  &mechanismInfo,
422  clearMechanismInfo( &mechanismInfo );
423  krnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );
424  if( cryptStatusError( status ) )
425  {
426  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
427  return( status );
428  }
429  *iPrivKeyContext = iCryptContext;
430 
431  return( CRYPT_OK );
432  }
433 
434 /****************************************************************************
435 * *
436 * Read PKCS #12 Keys *
437 * *
438 ****************************************************************************/
439 
440 /* Read a set of objects in a keyset */
441 
442 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6 ) ) \
443 static int readObjects( INOUT STREAM *stream,
444  OUT_ARRAY( maxNoPkcs12objects ) PKCS12_INFO *pkcs12info,
445  IN_LENGTH_SHORT const int maxNoPkcs12objects,
446  IN_LENGTH_MIN( 32 ) const long endPos,
447  const BOOLEAN isEncryptedCert,
449  {
450  int iterationCount, status;
451 
452  assert( isWritePtr( stream, sizeof( STREAM ) ) );
453  assert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) * \
454  maxNoPkcs12objects ) );
455 
456  REQUIRES( maxNoPkcs12objects >= 1 && \
457  maxNoPkcs12objects < MAX_INTLENGTH_SHORT );
458  REQUIRES( endPos >= 32 && endPos < MAX_INTLENGTH );
459  REQUIRES( errorInfo != NULL );
460 
461  /* Read each object in the current collection */
462  for( iterationCount = 0;
463  stell( stream ) < endPos && iterationCount < FAILSAFE_ITERATIONS_MED;
464  iterationCount++ )
465  {
466  PKCS12_INFO localPkcs12Info, *pkcs12infoPtr;
467  PKCS12_OBJECT_INFO *pkcs12ObjectInfoPtr;
468  BOOLEAN isCertificate = FALSE;
469 
470  /* Read one object */
471  status = pkcs12ReadObject( stream, &localPkcs12Info,
472  isEncryptedCert, errorInfo );
473  if( cryptStatusError( status ) )
474  return( status );
475  if( localPkcs12Info.flags & ( PKCS12_FLAG_CERT | \
477  isCertificate = TRUE;
478 
479  /* Find the location where we'll copy over the new object data */
480  status = findObjectEntryLocation( &pkcs12infoPtr, pkcs12info,
481  maxNoPkcs12objects,
482  localPkcs12Info.idLength <= 0 ? \
483  NULL : localPkcs12Info.id,
484  localPkcs12Info.idLength,
485  localPkcs12Info.flags );
486  if( cryptStatusError( status ) )
487  {
488  pkcs12freeObjectEntry( isCertificate ? \
489  &localPkcs12Info.certInfo : &localPkcs12Info.keyInfo );
490  if( status == CRYPT_ERROR_OVERFLOW )
491  {
493  ( CRYPT_ERROR_OVERFLOW, errorInfo,
494  "No more room in keyset data to add further "
495  "PKCS #12 items" ) );
496  }
497  retExt( status,
498  ( status, errorInfo,
499  "Couldn't reconcile ID-less object with existing "
500  "PKCS #12 objects" ) );
501  }
502 
503  /* Copy the newly-read PKCS #12 object information into the PKCS #12
504  keyset info */
505  pkcs12ObjectInfoPtr = isCertificate ? &pkcs12infoPtr->certInfo : \
506  &pkcs12infoPtr->keyInfo;
507  if( pkcs12ObjectInfoPtr->data != NULL )
508  {
509  pkcs12freeObjectEntry( isCertificate ? \
510  &localPkcs12Info.certInfo : &localPkcs12Info.keyInfo );
512  ( CRYPT_ERROR_BADDATA, errorInfo,
513  "Multiple conflicting %s found in keyset",
514  isCertificate ? "certificates" : "keys" ) );
515  }
516  copyObjectInfo( pkcs12infoPtr, &localPkcs12Info, isCertificate );
517  }
518 
519  return( CRYPT_OK );
520  }
521 
522 /* Read an entire keyset */
523 
524 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
525 int pkcs12ReadKeyset( INOUT STREAM *stream,
526  OUT_ARRAY( maxNoPkcs12objects ) PKCS12_INFO *pkcs12info,
527  IN_LENGTH_SHORT const int maxNoPkcs12objects,
528  IN_LENGTH const long endPos,
529  INOUT ERROR_INFO *errorInfo )
530  {
531  int iterationCount, status;
532 
533  assert( isWritePtr( stream, sizeof( STREAM ) ) );
534  assert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) * \
535  maxNoPkcs12objects ) );
536  assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
537 
538  REQUIRES( maxNoPkcs12objects >= 1 && \
539  maxNoPkcs12objects < MAX_INTLENGTH_SHORT );
540  REQUIRES( endPos > 0 && endPos > stell( stream ) && \
541  endPos < MAX_INTLENGTH );
542 
543  /* Clear return value */
544  memset( pkcs12info, 0, sizeof( PKCS12_INFO ) * maxNoPkcs12objects );
545 
546  /* Scan all of the objects in the keyset. This gets quite complicated
547  because there are multiple points at which we can have a SET/SEQUENCE
548  OF and depending on the implementation multiple objects may be stored
549  at any of these points, so we have to handle multiple nesting points
550  at which we can find more than one of an object */
551  for( status = CRYPT_OK, iterationCount = 0;
552  cryptStatusOK( status ) && stell( stream ) < endPos && \
553  iterationCount < FAILSAFE_ITERATIONS_MED; iterationCount++ )
554  {
555  long length, innerEndPos = CRYPT_ERROR;
556  int isEncrypted, noEOCs = 0;
557 
558  /* Read the CMS header encapsulation for the object. At this point
559  we get to more PKCS #12 stupidity, if we hit CMS EncryptedData
560  (isEncrypted == TRUE) then it's actually a certificate (that
561  doesn't need to be encrypted), and if we hit CMS Data
562  (isEncrypted == FALSE) then it's usually a private key wrapped
563  within a bizarre reinvention of CMS EncryptedData that's nested
564  within the CMS Data, although in some rare cases it may be a
565  SEQUENCE OF certificates and/or private key data that doesn't
566  correspond to either of the above. The combinations are:
567 
568  Data
569  SEQUENCE OF
570  ShroundedKeyBag | CertBag
571 
572  EncryptedData
573  Data (= Certificate)
574 
575  So if we find EncryptedData then we know that it's definitely a
576  certificate (so far nothing has tried to put private keys in
577  EncryptedData, although the spec allows it). If we find Data
578  then it could be anything, and we have to keep looking at a lower
579  level */
580  status = isEncrypted = \
581  readCMSheader( stream, keyDataOIDinfo,
582  FAILSAFE_ARRAYSIZE( keyDataOIDinfo, OID_INFO ),
583  &length, READCMS_FLAG_NONE );
584  if( cryptStatusError( status ) )
585  {
587  ( CRYPT_ERROR_BADDATA, errorInfo,
588  "Invalid PKCS #12 object header" ) );
589  }
590 
591  /* Find out where the collection of PKCS #12 objects in the current
592  set of objects ends. There may be only one, or many, and they
593  may or may not be of the same type */
594  if( length != CRYPT_UNUSED )
595  innerEndPos = stell( stream ) + length;
596  else
597  {
598  /* In order to get to this point without finding a length we
599  need to have encountered three indefinite-length wrappers,
600  which means that we need to skip three EOCs at the end */
601  noEOCs = 3;
602  }
603  if( !isEncrypted )
604  {
605  int innerLength;
606 
607  /* Skip the SET OF PKCS12Bag encapsulation */
608  status = readSequenceI( stream, &innerLength );
609  if( cryptStatusError( status ) )
610  return( status );
611  if( length == CRYPT_UNUSED && innerLength != CRYPT_UNUSED )
612  innerEndPos = stell( stream ) + innerLength;
613  }
614  if( innerEndPos == CRYPT_ERROR )
615  {
616  int innerLength;
617 
618  /* We still haven't got any length information, at this point
619  the best that we can do is assume that there's a single
620  encapsulated object present (which, in the rare situations
621  where this case arises, always seems to be the case) and
622  explicitly find its length before we can continue */
623  status = getStreamObjectLength( stream, &innerLength );
624  if( cryptStatusError( status ) )
625  return( status );
626  innerEndPos = stell( stream ) + innerLength;
627 
628  /* In practice it's not quite this simple. Firstly, this
629  approach is somewhat risky because we're calling
630  getStreamObjectLength() on a stream that could in theory be
631  non-seekable (although in practice file streams are always
632  seekable so this is more a theoretical than an actual
633  problem). In addition PKCS #12 files usually contain a
634  single object that fits easily within the stream buffer,
635  so even if the stream was non-seekable the call would
636  usually work.
637 
638  Secondly, and more critically, readObjects() calls
639  pkcs12ReadObject() which calls readRawObjectAlloc(), which
640  needs a definite length, again because it's dealing with a
641  non-seekable stream (and in this case it really may be a non-
642  seekable stream). Since we're dealing with an indefinite
643  length, readRawObjectAlloc() can't continue.
644 
645  A kludge workaround for this would be to pass the innerLength
646  value in to readObjects() as a length hint and to tell it to
647  bypass the call to readRawObjectAlloc() in favour of a direct
648  malloc() and fixed-length read, duplicating part of
649  readRawObjectAlloc(). For now we'll leave this until there's
650  an actual demand for it */
652  ( CRYPT_ERROR_BADDATA, errorInfo,
653  "Couldn't get PKCS #12 object length information" ) );
654 
655  }
656 
657  /* Read the set of objects */
658  status = readObjects( stream, pkcs12info, maxNoPkcs12objects,
659  innerEndPos, isEncrypted, errorInfo );
660  if( cryptStatusError( status ) )
661  return( status );
662 
663  /* Skip any EOCs that may be present. In the simplest case where
664  the data was encoded using all indefinte-length encoding we know
665  how many EOCs are present and skip them all */
666  if( noEOCs > 0 )
667  {
668  int i;
669 
670  for( i = 0; i < noEOCs; i++ )
671  {
672  const int value = checkEOC( stream );
673  if( cryptStatusError( value ) )
674  return( value );
675  if( value == FALSE )
676  return( CRYPT_ERROR_BADDATA );
677  }
678  }
679  else
680  {
681  /* If the data was encoded using a mixture of definite and
682  indefinite encoding there may be EOC's present even though
683  the length is known so we skip them if necessary. We have to
684  make the reads speculative since the indefinite-length values
685  were processed inside readCMSheader(), so we don't know how
686  many there were */
687  if( ( status = checkEOC( stream ) ) == TRUE )
688  status = checkEOC( stream );
689  if( cryptStatusError( status ) )
690  return( status );
691  status = CRYPT_OK; /* checkEOC() returns TRUE/FALSE */
692  }
693  }
694 
695  return( CRYPT_OK );
696  }
697 
698 /****************************************************************************
699 * *
700 * Get a Key *
701 * *
702 ****************************************************************************/
703 
704 #if 0 /* Crack an RC2-40 key. Call as 'keyCrack( certData, certDataSize )'
705  before the 'importCertificate()' call. A more efficient version
706  of this is in ctx_rc2.c, the following code is really only
707  present for testing the process with known-key data */
708 
709 #pragma message( "#############################" )
710 #pragma message( "Building PKCS #12 key-cracker" )
711 #pragma message( "#############################" )
712 
713 static int keyCrack( const void *encData, const int length )
714  {
716  MESSAGE_CREATEOBJECT_INFO createInfo;
718  BYTE data[ 32 ], key[ 32 ], *keyPtr = key + 14;
719  int i, status;
720 
721  /* Test file: IV = 17 17 F1 B0 94 E8 EE F8 encData + 0
722  PT = 06 0B 2A 86 48 86 F7 0D
723  -----------------------
724  XOR: 11 1C DB 36 DC 6E 19 F5
725 
726  So encr. above = CT block 2.
727  = 9C 4E 66 8A C7 6B 97 F5 encData + 8
728 
729  Actual: IV = 6F A0 7E A5 65 00 65 6C encData + 0
730  PT = 06 0B 2A 86 48 86 F7 0D
731  -----------------------
732  XOR: 69 AB 54 23 2D 86 92 61
733 
734  So encr. above = CT block 2.
735  = 34 AA F1 83 BD 9C C0 15 encData + 8 */
736 
737 // memcpy( data, "\x17\x17\xF1\xB0\x94\xE8\xEE\xF8", 8 );
738  memcpy( data, "\x6F\xA0\x7E\xA5\x65\x00\x65\x6C", 8 );
739  for( i = 0; i < 8; i++ )
740  data[ i ] ^= i[ "\x06\x0B\x2A\x86\x48\x86\xF7\x0D" ];
741 
742  memcpy( key, "PKCS#12PKCS#12", 14 );
743  memset( key + 14, 0, 5 );
744 
745 // memcpy( keyPtr, "\x13\x25\x0c\x1a\x60", 5 ); // Test PKCS #12 file, file #1.
746 // memcpy( keyPtr, "\x2C\x28\x14\xC4\x01", 5 ); // "Tellus" PKCS #12 file, file #2
747 
748  for( i = 0; i < 256; i++ )
749  {
750  int keyIndex;
751 
752  printf( "Trying keys %02X xx.\n", i );
753  fflush( stdout );
754  while( keyPtr[ 0 ] == i )
755  {
758  &createInfo, OBJECT_TYPE_CONTEXT );
759  if( cryptStatusError( status ) )
760  return( status );
761  cryptContext = createInfo.cryptHandle;
762  setMessageData( &msgData, key, 19 );
763  status = krnlSendMessage( cryptContext, IMESSAGE_SETATTRIBUTE_S,
764  &msgData, CRYPT_CTXINFO_KEY );
765  if( cryptStatusOK( status ) )
766  {
767  setMessageData( &msgData, ( MESSAGE_CAST ) encData, 8 );
768  status = krnlSendMessage( cryptContext, IMESSAGE_SETATTRIBUTE_S,
769  &msgData, CRYPT_CTXINFO_IV );
770  }
771  if( cryptStatusOK( status ) )
772  {
773 #if 0 /* For key-crack */
774  memcpy( data, ( const BYTE * ) encData + 8, 8 );
775  status = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT,
776  data, 8 );
777 #else /* For full decrypt */
778  status = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT,
779  ( MESSAGE_CAST ) \
780  ( ( const BYTE * ) encData + 8 ),
781  length - 8 );
782  DEBUG_DUMP( "crack_result", ( const BYTE * ) encData + 8,
783  length - 8 );
784 #endif /* 0 */
785  }
786  krnlSendNotifier( cryptContext, IMESSAGE_DECREFCOUNT );
787  if( cryptStatusError( status ) )
788  return( status );
789  if( data[ 0 ] == 0x06 && \
790  !memcmp( data, "\x06\x0B\x2A\x86\x48\x86\xF7\x0D", 8 ) )
791  {
792  printf( "Found at %02X %02X %02X %02X %02X.\n",
793  keyPtr[ 0 ], keyPtr[ 1 ], keyPtr[ 2 ],
794  keyPtr[ 3 ], keyPtr[ 4 ] );
795  fflush( stdout );
796  return( CRYPT_OK );
797  }
798  for( keyIndex = 4; keyIndex >= 0; keyIndex++ )
799  {
800  keyPtr[ keyIndex ]++;
801  if( keyPtr[ keyIndex ] > 0 )
802  break;
803  }
804  if( keyIndex == 1 )
805  {
806  printf( "Trying keys %02X %02X.\n",
807  keyPtr[ 0 ], keyPtr[ 1 ] );
808  fflush( stdout );
809  }
810  }
811  }
812 
813  return( CRYPT_OK );
814  }
815 #endif /* 0 */
816 
817 /* Get a key from a PKCS #12 keyset. This gets pretty ugly both because
818  PKCS #12 keysets contain no effective indexing information (making it
819  impossible to look up objects within them) and because in most cases all
820  data, including public keys and certificates, is encrypted. To handle
821  this we only allow private-key reads, and treat whatever's in the keyset
822  as being a match for any request, since without indexing information
823  there's no way to tell whether it really is a match or not */
824 
825 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
826 static int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
828  IN_ENUM( KEYMGMT_ITEM ) \
829  const KEYMGMT_ITEM_TYPE itemType,
831  IN_BUFFER( keyIDlength ) const void *keyID,
832  IN_LENGTH_KEYID const int keyIDlength,
833  IN_OPT void *auxInfo,
835  IN_FLAGS_Z( KEYMGMT ) const int flags )
836  {
837 #ifdef USE_CERTIFICATES
838  CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
839 #endif /* USE_CERTIFICATES */
841  CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_RSA;
842  const PKCS12_INFO *pkcs12infoPtr;
843  const int auxInfoMaxLength = *auxInfoLength;
844  int status;
845 
846  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
847  assert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );
848  assert( isReadPtr( keyID, keyIDlength ) );
849  assert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \
850  isReadPtr( auxInfo, auxInfoMaxLength ) );
851 
852  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
853  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );
854  REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
855  itemType == KEYMGMT_ITEM_PRIVATEKEY );
856  REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
857  keyIDtype == CRYPT_KEYID_URI || \
858  keyIDtype == CRYPT_IKEYID_KEYID || \
859  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
860  keyIDtype == CRYPT_IKEYID_ISSUERID );
861  REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
862  keyIDlength < MAX_ATTRIBUTE_SIZE );
863  REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
864  ( auxInfo != NULL && \
865  *auxInfoLength > 0 && \
866  *auxInfoLength < MAX_INTLENGTH_SHORT ) );
867  REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
868 
869  /* Clear return values */
870  *iCryptHandle = CRYPT_ERROR;
871 
872  /* Only private-key reads are possible */
873  if( itemType != KEYMGMT_ITEM_PRIVATEKEY )
874  {
877  "PKCS #12 keysets only support private-key reads" ) );
878  }
879 
880  /* PKCS #12 doesn't provide any useful indexing information that we
881  can use to look up a key apart from an optional label, so if we get
882  a key ID type that we can't do anything with or we're matching on
883  the special-case key ID "[none]" we perform a fetch of the first
884  matching key on the basis that most PKCS #12 keysets only contain a
885  single key of interest */
886  if( keyIDtype == CRYPT_IKEYID_KEYID || \
887  keyIDtype == CRYPT_IKEYID_PGPKEYID || \
888  keyIDtype == CRYPT_IKEYID_ISSUERID || \
889  ( keyIDlength == 6 && !strCompare( keyID, "[none]", 6 ) ) )
890  {
891  pkcs12infoPtr = pkcs12FindEntry( keysetInfoPtr->keyData,
892  keysetInfoPtr->keyDataNoObjects,
893  CRYPT_KEYID_NAME, NULL, 0 );
894  }
895  else
896  {
897  /* Find a private-key entry */
898  pkcs12infoPtr = pkcs12FindEntry( keysetInfoPtr->keyData,
899  keysetInfoPtr->keyDataNoObjects,
900  keyIDtype, keyID, keyIDlength );
901  }
902  if( pkcs12infoPtr == NULL )
903  {
906  "No information present for this ID" ) );
907  }
908  if( pkcs12infoPtr->keyInfo.data == NULL )
909  {
910  /* There's not enough information present to get a private key */
913  "No private key data present for this ID" ) );
914  }
915 
916  /* If we're just checking whether an object exists, return now. If all
917  that we want is the key label, copy it back to the caller and exit */
918  if( flags & KEYMGMT_FLAG_CHECK_ONLY )
919  return( CRYPT_OK );
920  if( flags & KEYMGMT_FLAG_LABEL_ONLY )
921  {
922  return( attributeCopyParams( auxInfo, auxInfoMaxLength,
923  auxInfoLength, pkcs12infoPtr->label,
924  pkcs12infoPtr->labelLength ) );
925  }
926 
927  /* Make sure that the user has supplied a password */
928  if( auxInfo == NULL )
929  return( CRYPT_ERROR_WRONGKEY );
930 
931  /* If there's a certificate present with the private key, import it as a
932  data-only certificate object to be attached to the private key */
933 #ifdef USE_CERTIFICATES
934  if( pkcs12infoPtr->certInfo.data != NULL )
935  {
936  const PKCS12_OBJECT_INFO *certObjectInfo = &pkcs12infoPtr->certInfo;
937  const int certDataSize = certObjectInfo->payloadSize;
938  int value;
939 
940  /* If it's an unencrypted certificate then we can import it
941  directly */
942  if( pkcs12infoPtr->flags & PKCS12_FLAG_CERT )
943  {
944  STREAM stream;
945 
946  sMemConnect( &stream,
947  ( BYTE * ) certObjectInfo->data + \
948  certObjectInfo->payloadOffset,
949  certDataSize );
950  status = importCertFromStream( &stream, &iDataCert,
951  keysetInfoPtr->ownerHandle,
952  CRYPT_ICERTTYPE_DATAONLY,
953  certDataSize );
954  sMemDisconnect( &stream );
955  }
956  else
957  {
958  BYTE certDataBuffer[ 2048 + 8 ], *certData = certDataBuffer;
959 
960  REQUIRES( pkcs12infoPtr->flags & PKCS12_FLAG_ENCCERT );
961 
962  /* It's an encrypted certificate, we need to decrypt it before
963  we can import it. First we set up a buffer to decrypt the
964  certificate data */
965  if( certDataSize > 2048 )
966  {
967  if( certDataSize >= MAX_INTLENGTH_SHORT )
968  return( CRYPT_ERROR_OVERFLOW );
969  if( ( certData = clAlloc( "getItemFunction", \
970  certDataSize ) ) == NULL )
971  return( CRYPT_ERROR_MEMORY );
972  }
973  memcpy( certData,
974  ( BYTE * ) certObjectInfo->data + \
975  certObjectInfo->payloadOffset, certDataSize );
976 
977  /* Decrypt and import the certificate */
978  status = importCertificate( certObjectInfo,
979  keysetInfoPtr->ownerHandle,
980  auxInfo, *auxInfoLength, certData,
981  certDataSize, &iDataCert );
982  zeroise( certData, certDataSize );
983  if( certData != certDataBuffer )
984  clFree( "getItemFunction", certData );
985  }
986  if( cryptStatusError( status ) )
987  {
988  retExt( status,
989  ( status, KEYSET_ERRINFO,
990  "Couldn't recreate certificate from stored certificate "
991  "data" ) );
992  }
993 
994  /* In yet another piece of design brilliance, the PKC algorithm
995  that's needed to create the public/private-key context is stored
996  inside the encrypted key data, so we can't create a context to
997  import the key data into until we've already imported the key
998  data. To get around this we read the PKC algorithm from the
999  certificate that corresponds to the key. If there's no
1000  certificate present we default to CRYPT_ALGO_RSA, which is almost
1001  always the case anyway */
1002  status = krnlSendMessage( iDataCert, IMESSAGE_GETATTRIBUTE, &value,
1003  CRYPT_IATTRIBUTE_CERTKEYALGO );
1004  if( cryptStatusOK( status ) )
1005  cryptAlgo = value;
1006  }
1007 #endif /* USE_CERTIFICATES */
1008 
1009  /* Import the wrapped private key */
1010  status = importPrivateKey( &pkcs12infoPtr->keyInfo,
1011  keysetInfoPtr->ownerHandle, auxInfo, *auxInfoLength,
1012  ( const BYTE * ) pkcs12infoPtr->keyInfo.data + \
1013  pkcs12infoPtr->keyInfo.payloadOffset,
1014  pkcs12infoPtr->keyInfo.payloadSize, cryptAlgo,
1015  ( pkcs12infoPtr->labelLength > 0 ) ? \
1016  pkcs12infoPtr->label : NULL,
1017  pkcs12infoPtr->labelLength, &iCryptContext );
1018  if( cryptStatusError( status ) )
1019  {
1020  if( iDataCert != CRYPT_ERROR )
1021  krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
1022  retExt( status,
1023  ( status, KEYSET_ERRINFO,
1024  "Couldn't unwrap and import private key" ) );
1025  }
1026 
1027 #ifdef USE_CERTIFICATES
1028  /* Connect the data-only certificate object to the private-key context
1029  if necessary. This is an internal object used only by the context so
1030  we tell the kernel to mark it as owned by the context only */
1031  if( iDataCert != CRYPT_ERROR )
1032  {
1033  status = krnlSendMessage( iCryptContext, IMESSAGE_SETDEPENDENT,
1034  &iDataCert, SETDEP_OPTION_NOINCREF );
1035  if( cryptStatusError( status ) )
1036  {
1037  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
1038  krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
1039  retExt( status,
1040  ( status, KEYSET_ERRINFO,
1041  "Couldn't attach certificate to key" ) );
1042  }
1043  }
1044 #endif /* USE_CERTIFICATES */
1045  *iCryptHandle = iCryptContext;
1046 
1047  return( CRYPT_OK );
1048  }
1049 
1050 /****************************************************************************
1051 * *
1052 * Keyset Access Routines *
1053 * *
1054 ****************************************************************************/
1055 
1056 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1057 int initPKCS12get( INOUT KEYSET_INFO *keysetInfoPtr )
1058  {
1059  assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
1060 
1061  REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
1062  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );
1063 
1064  /* Set the access method pointers */
1065  keysetInfoPtr->getItemFunction = getItemFunction;
1066 
1067  return( CRYPT_OK );
1068  }
1069 #endif /* USE_PKCS12 */