cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cms_denv.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib De-enveloping Routines *
4 * Copyright Peter Gutmann 1996-2009 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "asn1.h"
10  #include "asn1_ext.h"
11  #include "envelope.h"
12 #else
13  #include "enc_dec/asn1.h"
14  #include "enc_dec/asn1_ext.h"
15  #include "envelope/envelope.h"
16 #endif /* Compiler-specific includes */
17 
18 #ifdef USE_ENVELOPES
19 
20 /* OID information used to read enveloped data */
21 
22 static const CMS_CONTENT_INFO FAR_BSS oidInfoSignedData = { 0, 3 };
23 static const CMS_CONTENT_INFO FAR_BSS oidInfoEnvelopedData = { 0, 4 };
24 static const CMS_CONTENT_INFO FAR_BSS oidInfoDigestedData = { 0, 2 };
25 static const CMS_CONTENT_INFO FAR_BSS oidInfoEncryptedData = { 0, 2 };
26 static const CMS_CONTENT_INFO FAR_BSS oidInfoCompressedData = { 0, 0 };
27 static const CMS_CONTENT_INFO FAR_BSS oidInfoAuthData = { 0, 0 };
28 static const CMS_CONTENT_INFO FAR_BSS oidInfoAuthEnvData = { 0, 0 };
29 
30 static const OID_INFO FAR_BSS envelopeOIDinfo[] = {
32  { OID_CMS_SIGNEDDATA, ACTION_SIGN, &oidInfoSignedData },
33  { OID_CMS_ENVELOPEDDATA, ACTION_KEYEXCHANGE, &oidInfoEnvelopedData },
34  { OID_CMS_DIGESTEDDATA, ACTION_HASH, &oidInfoDigestedData },
35  { OID_CMS_ENCRYPTEDDATA, ACTION_CRYPT, &oidInfoEncryptedData },
36  { OID_CMS_COMPRESSEDDATA, ACTION_COMPRESS, &oidInfoCompressedData },
37  { OID_CMS_AUTHDATA, ACTION_MAC, &oidInfoAuthData },
38  { OID_CMS_AUTHENVDATA, ACTION_xxx, &oidInfoAuthEnvData },
44  { NULL, 0 }, { NULL, 0 }
45  };
46 
47 static const OID_INFO FAR_BSS nestedContentOIDinfo[] = {
60  { NULL, 0 }, { NULL, 0 }
61  };
62 
63 /****************************************************************************
64 * *
65 * Utility Routines *
66 * *
67 ****************************************************************************/
68 
69 /* Sanity-check the envelope state */
70 
72 static BOOLEAN sanityCheck( const ENVELOPE_INFO *envelopeInfoPtr )
73  {
74  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
75 
76  /* Make sure that the general envelope state is in order */
77  if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
78  return( FALSE );
79  if( envelopeInfoPtr->deenvState < DEENVSTATE_NONE || \
80  envelopeInfoPtr->deenvState >= DEENVSTATE_LAST )
81  return( FALSE );
82 
83  /* Make sure that the buffer position is within bounds */
84  if( envelopeInfoPtr->buffer == NULL || \
85  envelopeInfoPtr->bufPos < 0 || \
86  envelopeInfoPtr->bufPos > envelopeInfoPtr->bufSize || \
87  envelopeInfoPtr->bufSize < MIN_BUFFER_SIZE || \
88  envelopeInfoPtr->bufSize >= MAX_INTLENGTH )
89  return( FALSE );
90 
91  return( TRUE );
92  }
93 
94 /****************************************************************************
95 * *
96 * Content-list Processing Routines *
97 * *
98 ****************************************************************************/
99 
100 
101 /* Add information on different object types to a content-list entry */
102 
103 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
104 static int initExternalContentInfo( CONTENT_LIST *contentListItem,
105  IN_ENUM( CONTENT ) \
106  const CONTENT_TYPE contentType,
107  const QUERY_INFO *queryInfo )
108  {
109  CONTENT_ENCR_INFO *encrInfo = &contentListItem->clEncrInfo;
110 
111  assert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );
112  assert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );
113 
114  REQUIRES( contentType == CONTENT_AUTHENC || \
115  contentType == CONTENT_CRYPT );
116 
117  contentListItem->envInfo = CRYPT_ENVINFO_SESSIONKEY;
118 
119  /* If it's authenticated encrypted data, remember the encryption and MAC
120  algorithm parameters */
121  if( contentType == CONTENT_AUTHENC )
122  {
123  CONTENT_AUTHENC_INFO *authEncInfo = &contentListItem->clAuthEncInfo;
124 
125  authEncInfo->authEncAlgo = queryInfo->cryptAlgo;
126  REQUIRES( queryInfo->authEncParamLength > 0 && \
127  queryInfo->authEncParamLength <= 128 );
128  memcpy( authEncInfo->authEncParamData, queryInfo->authEncParamData,
129  queryInfo->authEncParamLength );
130  authEncInfo->authEncParamLength = queryInfo->authEncParamLength;
131  authEncInfo->encParamData = authEncInfo->authEncParamData + \
132  queryInfo->encParamStart;
133  authEncInfo->encParamDataLength = queryInfo->encParamLength;
134  authEncInfo->macParamData = authEncInfo->authEncParamData + \
135  queryInfo->macParamStart;
136  authEncInfo->macParamDataLength = queryInfo->macParamLength;
137 
138  return( CRYPT_OK );
139  }
140 
141  /* It's conventionally encrypted data, remember the encryption algorithm
142  parameters */
143  encrInfo->cryptAlgo = queryInfo->cryptAlgo;
144  encrInfo->cryptMode = queryInfo->cryptMode;
145  if( queryInfo->ivLength > 0 )
146  {
147  REQUIRES( queryInfo->ivLength > 0 && \
148  queryInfo->ivLength <= CRYPT_MAX_IVSIZE );
149  memcpy( encrInfo->saltOrIV, queryInfo->iv, queryInfo->ivLength );
150  encrInfo->saltOrIVsize = queryInfo->ivLength;
151  }
152 
153  return( CRYPT_OK );
154  }
155 
156 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
157 static int initPkcContentInfo( CONTENT_LIST *contentListItem,
158  const QUERY_INFO *queryInfo,
159  IN_BUFFER( objectSize ) const void *object,
160  IN_LENGTH_SHORT const int objectSize )
161  {
162  const BYTE *objectPtr = object; /* For pointer maths */
163 
164  assert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );
165  assert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );
166  assert( isReadPtr( object, objectSize ) );
167 
168  REQUIRES( objectSize > 0 && objectSize < MAX_INTLENGTH_SHORT );
169 
170  /* Remember the details of the enveloping information that we require
171  to continue */
172  if( queryInfo->type == CRYPT_OBJECT_PKCENCRYPTED_KEY )
173  contentListItem->envInfo = CRYPT_ENVINFO_PRIVATEKEY;
174  else
175  {
176  contentListItem->envInfo = CRYPT_ENVINFO_SIGNATURE;
177  contentListItem->clSigInfo.hashAlgo = queryInfo->hashAlgo;
178  }
179  if( queryInfo->formatType == CRYPT_FORMAT_CMS )
180  {
181  REQUIRES( rangeCheck( queryInfo->iAndSStart, queryInfo->iAndSLength,
182  objectSize ) );
183  contentListItem->issuerAndSerialNumber = objectPtr + queryInfo->iAndSStart;
184  contentListItem->issuerAndSerialNumberSize = queryInfo->iAndSLength;
185  }
186  else
187  {
188  REQUIRES( queryInfo->keyIDlength > 0 && \
189  queryInfo->keyIDlength <= CRYPT_MAX_HASHSIZE );
190  memcpy( contentListItem->keyID, queryInfo->keyID,
191  queryInfo->keyIDlength );
192  contentListItem->keyIDsize = queryInfo->keyIDlength;
193  }
194  REQUIRES( rangeCheck( queryInfo->dataStart, queryInfo->dataLength,
195  objectSize ) );
196  contentListItem->payload = objectPtr + queryInfo->dataStart;
197  contentListItem->payloadSize = queryInfo->dataLength;
198  if( queryInfo->type == CRYPT_OBJECT_SIGNATURE && \
199  queryInfo->formatType == CRYPT_FORMAT_CMS && \
200  queryInfo->unauthAttributeStart > 0 )
201  {
202  CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;
203 
205  queryInfo->unauthAttributeLength,
206  objectSize ) );
207  sigInfo->extraData2 = objectPtr + queryInfo->unauthAttributeStart;
208  sigInfo->extraData2Length = queryInfo->unauthAttributeLength;
209  }
210 
211  return( CRYPT_OK );
212  }
213 
214 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
215 static int initEncKeyContentInfo( CONTENT_LIST *contentListItem,
216  const QUERY_INFO *queryInfo,
217  IN_BUFFER( objectSize ) const void *object,
218  IN_LENGTH_SHORT const int objectSize )
219  {
220  CONTENT_ENCR_INFO *encrInfo = &contentListItem->clEncrInfo;
221  const BYTE *objectPtr = object; /* For pointer maths */
222 
223  assert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );
224  assert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );
225  assert( isReadPtr( object, objectSize ) );
226 
227  REQUIRES( objectSize > 0 && objectSize < MAX_INTLENGTH_SHORT );
228 
229  /* Remember the details of the enveloping information that we require
230  to continue */
231  if( queryInfo->keySetupAlgo != CRYPT_ALGO_NONE )
232  {
233  contentListItem->envInfo = CRYPT_ENVINFO_PASSWORD;
234  encrInfo->keySetupAlgo = queryInfo->keySetupAlgo;
235  encrInfo->keySetupIterations = queryInfo->keySetupIterations;
236  if( queryInfo->keySize > 0 )
237  encrInfo->keySize = queryInfo->keySize;
238  if( queryInfo->saltLength > 0 )
239  {
240  REQUIRES( queryInfo->saltLength > 0 && \
241  queryInfo->saltLength <= CRYPT_MAX_HASHSIZE );
242  memcpy( encrInfo->saltOrIV, queryInfo->salt,
243  queryInfo->saltLength );
244  encrInfo->saltOrIVsize = queryInfo->saltLength;
245  }
246  }
247  else
248  contentListItem->envInfo = CRYPT_ENVINFO_KEY;
249  encrInfo->cryptAlgo = queryInfo->cryptAlgo;
250  encrInfo->cryptMode = queryInfo->cryptMode;
251  REQUIRES( rangeCheck( queryInfo->dataStart, queryInfo->dataLength,
252  objectSize ) );
253  contentListItem->payload = objectPtr + queryInfo->dataStart;
254  contentListItem->payloadSize = queryInfo->dataLength;
255 
256  return( CRYPT_OK );
257  }
258 
259 /* Add information about an object to an envelope's content information list.
260  The content information can be supplied in one of two ways, either
261  implicitly via the data in the stream or explicitly via a QUERY_INFO
262  structure */
263 
264 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
265 static int addContentListItem( INOUT ENVELOPE_INFO *envelopeInfoPtr,
267  IN_OPT const QUERY_INFO *externalQueryInfo,
268  OUT_LENGTH_SHORT_Z int *itemSize )
269  {
272  void *contentListObjectPtr = NULL;
273  CONTENT_TYPE contentType;
274  const BOOLEAN infoProvidedExternally = \
275  ( externalQueryInfo != NULL ) ? TRUE : FALSE;
276  int objectSize = 0, status;
277 
278  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
279  assert( ( stream == NULL && \
280  isReadPtr( externalQueryInfo, sizeof( QUERY_INFO ) ) ) || \
281  ( isWritePtr( stream, sizeof( STREAM ) ) && \
282  externalQueryInfo == NULL ) );
283  assert( isWritePtr( itemSize, sizeof( int ) ) );
284 
285  REQUIRES( ( stream == NULL && externalQueryInfo != NULL ) || \
286  ( stream != NULL && externalQueryInfo == NULL ) );
287 
288  /* Clear return values */
289  *itemSize = 0;
290 
291  /* Make sure that there's room to add another list item */
292  if( !moreContentItemsPossible( envelopeInfoPtr->contentList ) )
293  return( CRYPT_ERROR_OVERFLOW );
294 
295  /* Find the size of the object, allocate a buffer for it, and copy it
296  across */
297  if( !infoProvidedExternally )
298  {
299  /* See what we've got. This call verifies that all of the object
300  data is present in the stream so in theory we don't have to check
301  the following reads, but we check them anyway just to be sure */
302  status = queryAsn1Object( stream, &queryInfo );
303  if( cryptStatusError( status ) )
304  return( status );
305  objectSize = ( int ) queryInfo.size;
306 
307  /* If it's a valid but unrecognised object type (a new RecipientInfo
308  type that was added after this version of cryptlib was released),
309  skip it and continue (if there are no recognised RecipientInfo
310  types, the code will automatically fall back to asking the user
311  for a raw session key). Alternatively, we could just add it to
312  the content list as an unrecognised object type, but this would
313  lead to confusion for the caller when non-object-types appear
314  when they query the current component */
315  if( queryInfo.type == CRYPT_OBJECT_NONE )
316  {
317  status = sSkip( stream, objectSize );
318  if( cryptStatusError( status ) )
319  return( status );
320  *itemSize = objectSize;
321 
322  return( CRYPT_OK );
323  }
324 
325  /* Read the object data into memory */
326  if( ( contentListObjectPtr = clAlloc( "addContentListItem", \
327  objectSize ) ) == NULL )
328  return( CRYPT_ERROR_MEMORY );
329  status = sread( stream, contentListObjectPtr, objectSize );
330  if( cryptStatusError( status ) )
331  {
332  clFree( "addContentListItem", contentListObjectPtr );
333  return( status );
334  }
335  }
336  else
337  {
338  /* The query information has been provided externally, use that */
339  memcpy( &queryInfo, externalQueryInfo, sizeof( QUERY_INFO ) );
340  }
341  ENSURES( infoProvidedExternally || \
342  ( queryInfo.size > 0 && \
343  queryInfo.size < MAX_INTLENGTH ) );
344  /* If the query information is supplied externally then it's a
345  template that doesn't correspond to any actual data */
346 
347  /* Determine the type of content that we're working with */
348  if( queryInfo.type == CRYPT_OBJECT_SIGNATURE )
349  contentType = CONTENT_SIGNATURE;
350  else
351  {
352  if( isSpecialAlgo( queryInfo.cryptAlgo ) )
353  contentType = CONTENT_AUTHENC;
354  else
355  contentType = CONTENT_CRYPT;
356  }
357 
358  /* Allocate memory for the new content list item and copy information on
359  the item across */
360  status = createContentListItem( &contentListItem,
361  envelopeInfoPtr->memPoolState, contentType,
362  queryInfo.formatType, contentListObjectPtr,
363  objectSize );
364  if( cryptStatusError( status ) )
365  {
366  if( contentListObjectPtr != NULL )
367  clFree( "addContentListItem", contentListObjectPtr );
368  return( status );
369  }
370  if( infoProvidedExternally )
371  {
372  /* It's externally-supplied encryption algorithm details from an
373  encrypted data header, either standard encrypted data or
374  authenticated encrypted data */
375  status = initExternalContentInfo( contentListItem, contentType,
376  &queryInfo );
377  if( cryptStatusError( status ) )
378  return( status );
379  }
380  else
381  {
382  if( queryInfo.type == CRYPT_OBJECT_PKCENCRYPTED_KEY || \
383  queryInfo.type == CRYPT_OBJECT_SIGNATURE )
384  {
385  /* Remember the details of the enveloping information that we
386  require to continue */
387  status = initPkcContentInfo( contentListItem, &queryInfo,
388  contentListObjectPtr, objectSize );
389  if( cryptStatusError( status ) )
390  return( status );
391  }
392  if( queryInfo.type == CRYPT_OBJECT_ENCRYPTED_KEY )
393  {
394  /* Remember the details of the enveloping information that we
395  require to continue */
396  status = initEncKeyContentInfo( contentListItem, &queryInfo,
397  contentListObjectPtr, objectSize );
398  if( cryptStatusError( status ) )
399  return( status );
400  }
401  }
402  status = appendContentListItem( envelopeInfoPtr, contentListItem );
403  if( cryptStatusError( status ) )
404  {
405  deleteContentList( envelopeInfoPtr->memPoolState,
406  &contentListItem );
407  if( contentListObjectPtr != NULL )
408  clFree( "addContentListItem", contentListObjectPtr );
409  return( status );
410  }
411  *itemSize = ( int ) queryInfo.size;
412 
413  return( CRYPT_OK );
414  }
415 
416 /****************************************************************************
417 * *
418 * Header Processing Routines *
419 * *
420 ****************************************************************************/
421 
422 /* Process the outer CMS envelope header */
423 
424 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
425 static int processEnvelopeHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr,
426  INOUT STREAM *stream,
428  {
429  int status;
430 
431  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
432  assert( isWritePtr( stream, sizeof( STREAM ) ) );
433  assert( isWritePtr( state, sizeof( DEENV_STATE ) ) );
434 
435  /* Clear return value */
436  *state = DEENVSTATE_NONE;
437 
438  /* Read the outer CMS header */
439  status = readCMSheader( stream, envelopeOIDinfo,
440  FAILSAFE_ARRAYSIZE( envelopeOIDinfo, OID_INFO ),
441  &envelopeInfoPtr->payloadSize,
443  if( cryptStatusError( status ) )
444  return( status );
445 
446  /* Determine the next state to continue processing */
447  switch( status )
448  {
449  case ACTION_NONE:
450  /* Since we're going straight to the data payload there's no
451  nested content type so we explicitly set it to "data" */
452  envelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;
453  *state = DEENVSTATE_DATA;
454  break;
455 
456  case ACTION_KEYEXCHANGE:
457  envelopeInfoPtr->usage = ACTION_CRYPT;
458  *state = DEENVSTATE_SET_ENCR;
459  break;
460 
461  case ACTION_xxx:
462  /* Authenticated encryption is a variant of a standard encrypted
463  envelope */
464  envelopeInfoPtr->usage = ACTION_CRYPT;
465  envelopeInfoPtr->flags |= ENVELOPE_AUTHENC;
466  *state = DEENVSTATE_SET_ENCR;
467  break;
468 
469  case ACTION_CRYPT:
470  envelopeInfoPtr->usage = ACTION_CRYPT;
471  *state = DEENVSTATE_ENCRCONTENT;
472  break;
473 
474  case ACTION_MAC:
475  /* MACd envelopes have key exchange information at the start
476  just like ACTION_KEYEXCHANGE but the later processing is
477  different so we treat them as a special case here */
478  envelopeInfoPtr->usage = ACTION_MAC;
479  *state = DEENVSTATE_SET_ENCR;
480  break;
481 
482  case ACTION_COMPRESS:
483  /* With compressed data all that we need to do is check that the
484  fixed AlgorithmIdentifier is present and set up the
485  decompression stream, after which we go straight to the
486  content */
487  status = readGenericAlgoID( stream, OID_ZLIB,
488  sizeofOID( OID_ZLIB ) );
489  if( cryptStatusError( status ) )
490  return( status );
491  envelopeInfoPtr->usage = ACTION_COMPRESS;
492 #ifdef USE_COMPRESSION
493  if( inflateInit( &envelopeInfoPtr->zStream ) != Z_OK )
494  return( CRYPT_ERROR_MEMORY );
495  envelopeInfoPtr->flags |= ENVELOPE_ZSTREAMINITED;
496  *state = DEENVSTATE_CONTENT;
497 #else
498  return( CRYPT_ERROR_NOTAVAIL );
499 #endif /* USE_COMPRESSION */
500  break;
501 
502  case ACTION_SIGN:
503  envelopeInfoPtr->usage = ACTION_SIGN;
504  *state = DEENVSTATE_SET_HASH;
505  break;
506 
507  default:
508  retIntError();
509  }
510 
511  return( CRYPT_OK );
512  }
513 
514 /* Process the encrypted content header */
515 
516 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
517 static int processEncryptionHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr,
518  INOUT STREAM *stream )
519  {
521  int status;
522 
523  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
524  assert( isWritePtr( stream, sizeof( STREAM ) ) );
525 
526  /* Read the encrypted content header */
527  status = readCMSencrHeader( stream, nestedContentOIDinfo,
528  FAILSAFE_ARRAYSIZE( nestedContentOIDinfo, OID_INFO ),
529  NULL, &queryInfo,
530  ( envelopeInfoPtr->flags & ENVELOPE_AUTHENC ) ? \
532  if( cryptStatusError( status ) )
533  return( status );
534  envelopeInfoPtr->contentType = status;
535  envelopeInfoPtr->payloadSize = queryInfo.size;
536 
537  /* We've reached encrypted data, we can't go any further until we can
538  either recover the session key from a key exchange object or are fed
539  the session key directly */
540  if( envelopeInfoPtr->actionList == NULL )
541  {
542  int dummy;
543 
544  /* Since the content can be indefinite-length we clear the size
545  field to give it a sensible setting */
546  queryInfo.size = 0;
547  return( addContentListItem( envelopeInfoPtr, NULL, &queryInfo,
548  &dummy ) );
549  }
550  REQUIRES( envelopeInfoPtr->actionList != NULL && \
551  envelopeInfoPtr->actionList->action == ACTION_CRYPT );
552 
553  /* If the session key was recovered from a key exchange action but we
554  ran out of input data before we could read the encryptedContent
555  information it'll be present in the action list so we use it to set
556  things up for the decryption. This can only happen if the caller
557  pushes in just enough data to get past the key exchange actions but
558  not enough to recover the encryptedContent information and then
559  pushes in a key exchange action in response to the
560  CRYPT_ERROR_UNDERFLOW error */
561  return( initEnvelopeEncryption( envelopeInfoPtr,
562  envelopeInfoPtr->actionList->iCryptHandle,
563  queryInfo.cryptAlgo, queryInfo.cryptMode,
564  queryInfo.iv, queryInfo.ivLength,
565  FALSE ) );
566  }
567 
568 /* Process the hash object header */
569 
570 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
571 static int processHashHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr,
572  INOUT STREAM *stream )
573  {
576  int hashAlgo = DUMMY_INIT, iterationCount, status;
577 
578  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
579  assert( isWritePtr( stream, sizeof( STREAM ) ) );
580 
581  /* Create the hash object from the data */
582  status = readContextAlgoID( stream, &iHashContext, NULL, DEFAULT_TAG,
584  if( cryptStatusOK( status ) )
585  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
586  &hashAlgo, CRYPT_CTXINFO_ALGO );
587  if( cryptStatusError( status ) )
588  return( status );
589 
590  /* Check whether an identical hash action is already present, either
591  through being supplied externally or from a duplicate entry in the
592  set of digest/MAC algorithms in the envelope header */
593  for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
594  actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
595  actionListPtr = actionListPtr->next, iterationCount++ )
596  {
597  int actionHashAlgo;
598 
599  status = krnlSendMessage( actionListPtr->iCryptHandle,
600  IMESSAGE_GETATTRIBUTE, &actionHashAlgo,
602  if( cryptStatusOK( status ) && actionHashAlgo == hashAlgo )
603  {
604  /* There's a duplicate action present, destroy the one that
605  we've just created and continue */
606  krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
607  return( CRYPT_OK );
608  }
609  }
610  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
611 
612  /* We didn't find any duplicates, append the new hash action to the
613  action list and remember that hashing is now active */
614  status = addAction( &envelopeInfoPtr->actionList,
615  envelopeInfoPtr->memPoolState,
616  ( envelopeInfoPtr->usage == ACTION_MAC ) ? \
617  ACTION_MAC : ACTION_HASH, iHashContext );
618  if( cryptStatusError( status ) )
619  return( status );
620  envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;
621 
622  ENSURES( envelopeInfoPtr->actionList != NULL && \
623  ( envelopeInfoPtr->actionList->action == ACTION_HASH || \
624  envelopeInfoPtr->actionList->action == ACTION_MAC ) );
625 
626  return( CRYPT_OK );
627  }
628 
629 /****************************************************************************
630 * *
631 * Trailer Processing Routines *
632 * *
633 ****************************************************************************/
634 
635 /* Process EOCs that separate the payload from the trailer */
636 
637 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
638 static int processPayloadEOCs( INOUT ENVELOPE_INFO *envelopeInfoPtr,
639  INOUT STREAM *stream )
640  {
641  int status;
642 
643  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
644  assert( isWritePtr( stream, sizeof( STREAM ) ) );
645 
646  /* If the payload has an indefinite-length encoding, make sure that the
647  required EOCs are present */
648  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
649  {
650  if( ( status = checkEOC( stream ) ) != TRUE || \
651  ( status = checkEOC( stream ) ) != TRUE )
652  {
653  return( cryptStatusError( status ) ? \
654  status : CRYPT_ERROR_BADDATA );
655  }
656 
657  return( CRYPT_OK );
658  }
659 
660  /* If the data was encoded using a mixture of definite and indefinite
661  encoding there may be EOC's present even though the length is known
662  so we skip them if necessary */
663  if( ( status = checkEOC( stream ) ) == TRUE )
664  status = checkEOC( stream );
665  if( cryptStatusError( status ) )
666  return( status );
667 
668  return( CRYPT_OK );
669  }
670 
671 /* Complete processing of the authenticated payload for hashed, MACd,
672  signed, and authenticated encrypted data */
673 
675 static int completePayloadProcessing( INOUT ENVELOPE_INFO *envelopeInfoPtr )
676  {
677  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
678 
679  /* When we reach this point there may still be unhashed data left in the
680  buffer. It won't have been hashed yet because the hashing is
681  performed when the data is copied out, after unwrapping and
682  deblocking and whatnot, so we hash it before we wrap up the
683  hashing (the exception to this is authenticated encrypted data which
684  is MACd before decryption, but that's handled internally by the data-
685  decoding process) */
686  if( envelopeInfoPtr->dataLeft > 0 )
687  {
688  int status;
689 
690  status = envelopeInfoPtr->processExtraData( envelopeInfoPtr,
691  envelopeInfoPtr->buffer,
692  envelopeInfoPtr->dataLeft );
693  if( cryptStatusError( status ) )
694  return( status );
695  }
696 
697  /* Wrap up the hashing */
698  return( envelopeInfoPtr->processExtraData( envelopeInfoPtr, "", 0 ) );
699  }
700 
701 /* Process the signed data trailer */
702 
703 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
704 static int processSignedTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr,
705  INOUT STREAM *stream,
707  {
708  DEENV_STATE newState;
709  int tag, status;
710 
711  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
712  assert( isWritePtr( stream, sizeof( STREAM ) ) );
713  assert( isWritePtr( state, sizeof( DEENV_STATE ) ) );
714 
715  /* Read the SignedData EOC's if necessary */
716  status = processPayloadEOCs( envelopeInfoPtr, stream );
717  if( cryptStatusError( status ) )
718  return( status );
719 
720  /* Check whether there's a certificate chain to follow */
721  tag = peekTag( stream );
722  if( cryptStatusError( tag ) )
723  return( tag );
724  newState = ( tag == MAKE_CTAG( 0 ) ) ? \
726 
727  /* If we've seen all of the signed data, complete the hashing */
728  if( !( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
729  {
730  status = completePayloadProcessing( envelopeInfoPtr );
731  if( cryptStatusError( status ) )
732  return( status );
733  }
734 
735  /* Move on to the next state */
736  *state = newState;
737  return( CRYPT_OK );
738  }
739 
740 /* Process the MACd data trailer. Note that some data-formatting errors
741  encountered at this level may be converted into an authentication-failure
742  status by the calling code to avoid truncation attacks, see the comment
743  in processPostable() for more details */
744 
745 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
746 static int processMacTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr,
747  INOUT STREAM *stream,
748  OUT_BOOL BOOLEAN *failedMAC )
749  {
752  BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
753  int hashSize, status;
754 
755  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
756  assert( isWritePtr( stream, sizeof( STREAM ) ) );
757  assert( isWritePtr( failedMAC, sizeof( BOOLEAN ) ) );
758 
759  /* Clear return value */
760  *failedMAC = FALSE;
761 
762  /* Read the AuthenticatedData EOCs if necessary */
763  status = processPayloadEOCs( envelopeInfoPtr, stream );
764  if( cryptStatusError( status ) )
765  return( status );
766 
767  /* Read the MAC value that follows the payload */
768  status = readOctetString( stream, hash, &hashSize, 16,
770  if( cryptStatusError( status ) )
771  return( status );
772 
773  /* Complete the payload processing and compare the read MAC value with
774  the calculated one */
775  status = completePayloadProcessing( envelopeInfoPtr );
776  if( cryptStatusError( status ) )
777  return( status );
778  setMessageData( &msgData, hash, hashSize );
779  actionListPtr = findAction( envelopeInfoPtr->actionList, ACTION_MAC );
780  ENSURES( actionListPtr != NULL );
781  status = krnlSendMessage( actionListPtr->iCryptHandle, IMESSAGE_COMPARE,
782  &msgData, MESSAGE_COMPARE_HASH );
783  if( cryptStatusError( status ) )
784  {
785  /* Unlike signatures a failed MAC check (reported as a CRYPT_ERROR
786  comparison result) is detected immediately rather than after the
787  payload processing has completed. However if we bail out now
788  then any later checks of things like signature metadata will fail
789  because the envelope regards processing as still being incomplete
790  so we have to continue processing data until we at least get the
791  envelope to the finished state */
792  assert( status == CRYPT_ERROR );
793  *failedMAC = TRUE;
794  }
795 
796  return( CRYPT_OK );
797  }
798 
799 /* Process any remaining EOCs. This gets a bit complicated because there
800  can be a variable number of EOCs depending on where definite and
801  indefinite encodings were used so we look for at least one EOC and at
802  most a number that depends on the data type being processed */
803 
804 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
805 static int processEOCTrailer( const ENVELOPE_INFO *envelopeInfoPtr,
806  INOUT STREAM *stream )
807  {
808  int noEOCs, i;
809 
810  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
811  assert( isWritePtr( stream, sizeof( STREAM ) ) );
812 
813  /* Consume any EOCs up to the maximum amount possible. In theory we
814  could be rather liberal with trailing EOCs since it's not really
815  necessary for the caller to push in every last one, however if we
816  assume that seeing at least one EOC is enough to signal the end of
817  all content this can lead to problems if adding the EOCs occurs
818  over a pushData boundary. What can happen here is that the code will
819  see the start of the string of EOCs on the first push, record the
820  end-of-data-reached state, and then report a CRYPT_ERROR_COMPLETE
821  when the remainder of the string of EOCs are pushed the next time
822  round. To avoid this problem we have to be pedantic and require
823  that callers push all EOCs */
824  switch( envelopeInfoPtr->usage )
825  {
826  case ACTION_NONE:
827  noEOCs = 2;
828  break;
829 
830  case ACTION_CRYPT:
831  /* Authenticated encryption is a special case since there's a
832  MAC value present after the data, which means that we've
833  already consumed two of the four EOCs present at the end of
834  encrypted data in getting to the MAC value */
835  if( envelopeInfoPtr->flags & ENVELOPE_AUTHENC )
836  noEOCs = 2;
837  else
838  noEOCs = 4;
839  break;
840 
841  case ACTION_SIGN:
842  case ACTION_MAC:
843  noEOCs = 3;
844  break;
845 
846  case ACTION_COMPRESS:
847  noEOCs = 5;
848  break;
849 
850  default:
851  retIntError();
852  }
853  for( i = 0; i < noEOCs; i++ )
854  {
855  const int value = checkEOC( stream );
856  if( cryptStatusError( value ) )
857  return( value );
858  if( value == FALSE )
859  return( CRYPT_ERROR_BADDATA );
860  }
861 
862  return( CRYPT_OK );
863  }
864 
865 /****************************************************************************
866 * *
867 * Process Envelope Preamble/Postamble *
868 * *
869 ****************************************************************************/
870 
871 /* Process the non-data portions of an envelope. This is a complex event-
872  driven state machine, but instead of reading along a (hypothetical
873  Turing-machine) tape someone has taken the tape and cut it into bits and
874  keeps feeding them to us and saying "See what you can do with this" (and
875  occasionally "Where's the bloody spoons?"). The following code implements
876  this state machine.
877 
878  Encr. with key exchange: SET_ENCR -> ENCR -> ENCRCONTENT -> DATA
879  Encr.: ENCRCONTENT -> DATA
880  Signed: SET_HASH -> HASH -> CONTENT -> DATA
881  MACd: SET_ENCR -> ENCR -> HASH -> CONTENT -> DATA */
882 
884 static int processPreamble( INOUT ENVELOPE_INFO *envelopeInfoPtr )
885  {
886  DEENV_STATE state = envelopeInfoPtr->deenvState;
887  STREAM stream;
888  int remainder, streamPos = 0, iterationCount, status = CRYPT_OK;
889 
890  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
891 
892  REQUIRES( sanityCheck( envelopeInfoPtr ) );
893 
894  sMemConnect( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufPos );
895 
896  /* If we haven't started doing anything yet try and read the outer
897  header fields */
898  if( state == DEENVSTATE_NONE )
899  {
900  status = processEnvelopeHeader( envelopeInfoPtr, &stream, &state );
901  if( cryptStatusError( status ) )
902  {
903  sMemDisconnect( &stream );
904  retExt( status,
905  ( status, ENVELOPE_ERRINFO,
906  "Invalid CMS envelope header" ) );
907  }
908 
909  /* Remember how far we got */
910  streamPos = stell( &stream );
911  }
912 
913  /* Keep consuming information until we either run out of input or reach
914  the data payload. Although in theory we should really use
915  FAILSAFE_ITERATIONS_MED for this loop, in practice we have to use
916  FAILSAFE_ITERATIONS_LARGE because it's possible to generate S/MIME
917  messages with large numbers of recipients for mailing lists. This
918  would never occur in any normal usage, but we have to allow for it for
919  mailing-list use */
920  for( iterationCount = 0;
921  state != DEENVSTATE_DONE && \
922  iterationCount < FAILSAFE_ITERATIONS_LARGE;
923  iterationCount++ )
924  {
925  /* Read the start of the SET OF RecipientInfo/SET OF
926  DigestAlgorithmIdentifier */
927  if( state == DEENVSTATE_SET_ENCR )
928  {
929  long setLongLength;
930 
931  /* Read the SET tag and length. We have to read the length as
932  a long value in order to handle cases where there's a large
933  amount of key management data involving a great many
934  recipients */
935  status = readLongSet( &stream, &setLongLength );
936  if( cryptStatusError( status ) )
937  {
939  "Invalid SET OF RecipientInfo header", 35 );
940  break;
941  }
942  envelopeInfoPtr->hdrSetLength = setLongLength;
943 
944  /* Remember where we are and move on to the next state. Some
945  implementations use the indefinite-length encoding for this so
946  if there's no length given (setLength == CRYPT_UNUSED) we
947  have to look for the EOC after each entry read */
948  streamPos = stell( &stream );
949  state = DEENVSTATE_ENCR;
950  }
951  if( state == DEENVSTATE_SET_HASH )
952  {
953  int setLength;
954 
955  /* Read the SET tag and length */
956  status = readSetI( &stream, &setLength );
957  if( cryptStatusError( status ) )
958  {
960  "Invalid SET OF DigestAlgorithmIdentifier "
961  "header", 47 );
962  break;
963  }
964  envelopeInfoPtr->hdrSetLength = setLength;
965 
966  /* Remember where we are and move on to the next state. Some
967  implementations use the indefinite-length encoding for this so
968  if there's no length given (setLength == CRYPT_UNUSED) we
969  have to look for the EOC after each entry read */
970  streamPos = stell( &stream );
971  state = DEENVSTATE_HASH;
972  }
973 
974  /* Read and remember a key exchange object from an EncryptionKeyInfo
975  record */
976  if( state == DEENVSTATE_ENCR )
977  {
978  int contentItemLength;
979 
980  /* Add the object to the content information list */
981  status = addContentListItem( envelopeInfoPtr, &stream, NULL,
982  &contentItemLength );
983  if( cryptStatusError( status ) )
984  {
986  "Invalid EncryptionKeyInfo key exchange "
987  "record", 45 );
988  break;
989  }
990 
991  /* Remember where we are and move on to the next state if
992  necessary */
993  streamPos = stell( &stream );
994  if( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )
995  {
996  if( contentItemLength > envelopeInfoPtr->hdrSetLength )
997  {
998  status = CRYPT_ERROR_BADDATA;
999  break;
1000  }
1001  envelopeInfoPtr->hdrSetLength -= contentItemLength;
1002  if( envelopeInfoPtr->hdrSetLength <= 0 )
1003  {
1004  state = ( envelopeInfoPtr->usage == ACTION_MAC ) ? \
1006  }
1007  }
1008  else
1009  {
1010  const int value = checkEOC( &stream );
1011  if( cryptStatusError( value ) )
1012  {
1013  status = value;
1014  break;
1015  }
1016  if( value == TRUE )
1017  {
1018  state = ( envelopeInfoPtr->usage == ACTION_MAC ) ? \
1020  }
1021  }
1022  }
1023 
1024  /* Read the encrypted content information */
1025  if( state == DEENVSTATE_ENCRCONTENT )
1026  {
1027  status = processEncryptionHeader( envelopeInfoPtr, &stream );
1028  if( cryptStatusError( status ) )
1029  {
1030  /* We may get non-data-related errors like
1031  CRYPT_ERROR_WRONGKEY so we only set extended error
1032  information if it's a data-related error */
1033  if( isDataError( status ) )
1034  {
1036  "Invalid encrypted content header", 32 );
1037  }
1038  break;
1039  }
1040 
1041  /* Remember where we are and move on to the next state */
1042  streamPos = stell( &stream );
1043  state = DEENVSTATE_DATA;
1044  if( envelopeInfoPtr->actionList == NULL )
1045  {
1046  /* If we haven't got a session key to decrypt the data that
1047  follows we can't go beyond this point */
1048  status = CRYPT_ENVELOPE_RESOURCE;
1049  break;
1050  }
1051  }
1052 
1053  /* Read and remember a MAC object from a MACAlgorithmIdentifier
1054  record */
1055  if( state == DEENVSTATE_HASH && \
1056  envelopeInfoPtr->usage == ACTION_MAC )
1057  {
1058  status = processHashHeader( envelopeInfoPtr, &stream );
1059  if( cryptStatusError( status ) )
1060  {
1062  "Invalid MACd content header", 27 );
1063  break;
1064  }
1065 
1066  /* Remember where we are and move on to the next state */
1067  streamPos = stell( &stream );
1068  state = DEENVSTATE_CONTENT;
1069  }
1070 
1071  /* Read and remember a hash object from a DigestAlgorithmIdentifier
1072  record */
1073  if( state == DEENVSTATE_HASH )
1074  {
1075  status = processHashHeader( envelopeInfoPtr, &stream );
1076  if( cryptStatusError( status ) )
1077  {
1079  "Invalid hashed content header", 29 );
1080  break;
1081  }
1082 
1083  /* Remember where we are and move on to the next state if
1084  necessary */
1085  if( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )
1086  {
1087  const int hashInfoLength = stell( &stream ) - streamPos;
1088  if( hashInfoLength < 0 || \
1089  hashInfoLength > envelopeInfoPtr->hdrSetLength )
1090  {
1091  status = CRYPT_ERROR_BADDATA;
1092  break;
1093  }
1094  envelopeInfoPtr->hdrSetLength -= hashInfoLength;
1095  streamPos = stell( &stream );
1096  if( envelopeInfoPtr->hdrSetLength <= 0 )
1097  state = DEENVSTATE_CONTENT;
1098  }
1099  else
1100  {
1101  const int value = checkEOC( &stream );
1102  if( cryptStatusError( value ) )
1103  {
1104  status = value;
1105  break;
1106  }
1107  if( value == TRUE )
1108  state = DEENVSTATE_CONTENT;
1109  }
1110  }
1111 
1112  /* Read the encapsulated content header */
1113  if( state == DEENVSTATE_CONTENT )
1114  {
1115  int contentType;
1116 
1117  status = contentType = \
1118  readCMSheader( &stream, nestedContentOIDinfo,
1119  FAILSAFE_ARRAYSIZE( nestedContentOIDinfo, OID_INFO ),
1120  &envelopeInfoPtr->payloadSize,
1122  if( cryptStatusError( status ) )
1123  {
1125  "Invalid encapsulated content header", 35 );
1126  break;
1127  }
1128  envelopeInfoPtr->contentType = contentType;
1129 
1130  /* If there's no content included and it's not an attributes-only
1131  message then this is a detached signature with the content
1132  supplied anderswhere */
1133  if( envelopeInfoPtr->payloadSize == 0 && \
1134  !( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY ) )
1135  envelopeInfoPtr->flags |= ENVELOPE_DETACHED_SIG;
1136 
1137  /* Remember where we are and move on to the next state */
1138  streamPos = stell( &stream );
1139  state = ( envelopeInfoPtr->payloadSize == 0 && \
1140  ( envelopeInfoPtr->flags & ( ENVELOPE_DETACHED_SIG | \
1141  ENVELOPE_ATTRONLY ) ) ) ? \
1143 
1144  /* If this is MACd data and we haven't loaded a key to MAC the
1145  data that follows we can't go beyond this point */
1146  if( envelopeInfoPtr->usage == ACTION_MAC )
1147  {
1148  if( envelopeInfoPtr->actionList == NULL )
1149  {
1150  status = CRYPT_ENVELOPE_RESOURCE;
1151  break;
1152  }
1153  REQUIRES( envelopeInfoPtr->actionList->action == ACTION_MAC );
1154  status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle,
1155  IMESSAGE_CHECK, NULL,
1157  if( cryptStatusError( status ) )
1158  {
1159  status = CRYPT_ENVELOPE_RESOURCE;
1160  break;
1161  }
1162  }
1163  }
1164 
1165  /* Start the decryption process if necessary */
1166  if( state == DEENVSTATE_DATA )
1167  {
1168  /* Synchronise the data stream processing to the start of the
1169  encrypted data and move back to the start of the data
1170  stream */
1171  status = envelopeInfoPtr->syncDeenvelopeData( envelopeInfoPtr,
1172  &stream );
1173  if( cryptStatusError( status ) )
1174  {
1176  "Couldn't synchronise envelope state prior "
1177  "to data payload processing", 68 );
1178  break;
1179  }
1180 
1181  /* The data has now been resynchronised with the start of
1182  stream, and we're done */
1183  streamPos = 0;
1184  state = DEENVSTATE_DONE;
1185 
1186  ENSURES( checkActions( envelopeInfoPtr ) );
1187  }
1188  }
1189  sMemDisconnect( &stream );
1190  if( iterationCount >= FAILSAFE_ITERATIONS_LARGE )
1191  {
1192  /* Technically this would be an overflow but that's a recoverable
1193  error so we make it a BADDATA, which is really what it is */
1194  return( CRYPT_ERROR_BADDATA );
1195  }
1196  envelopeInfoPtr->deenvState = state;
1197 
1198  ENSURES( streamPos >= 0 && streamPos < MAX_INTLENGTH && \
1199  envelopeInfoPtr->bufPos - streamPos >= 0 );
1200 
1201  /* Consume the input that we've processed so far by moving everything
1202  past the current position down to the start of the envelope buffer */
1203  remainder = envelopeInfoPtr->bufPos - streamPos;
1204  REQUIRES( remainder >= 0 && remainder < MAX_INTLENGTH && \
1205  streamPos + remainder <= envelopeInfoPtr->bufSize );
1206  if( remainder > 0 && streamPos > 0 )
1207  {
1208  REQUIRES( rangeCheck( streamPos, remainder,
1209  envelopeInfoPtr->bufSize ) );
1210  memmove( envelopeInfoPtr->buffer, envelopeInfoPtr->buffer + streamPos,
1211  remainder );
1212  }
1213  envelopeInfoPtr->bufPos = remainder;
1214  ENSURES( sanityCheck( envelopeInfoPtr ) );
1215  if( cryptStatusError( status ) )
1216  return( status );
1217 
1218  /* If all went OK but we're still not out of the header information,
1219  return an underflow error */
1220  return( ( state != DEENVSTATE_DONE ) ? \
1222  }
1223 
1225 static int processPostamble( INOUT ENVELOPE_INFO *envelopeInfoPtr,
1226  const BOOLEAN isFlush )
1227  {
1228  DEENV_STATE state = envelopeInfoPtr->deenvState;
1229  STREAM stream;
1230  BOOLEAN failedMAC = FALSE;
1231  int remainder, streamPos = 0, iterationCount, status = CRYPT_OK;
1232 
1233  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1234 
1235  REQUIRES( sanityCheck( envelopeInfoPtr ) );
1236 
1237  /* If that's all that there is, return */
1238  if( state == DEENVSTATE_NONE && \
1239  !( envelopeInfoPtr->usage == ACTION_SIGN || \
1240  envelopeInfoPtr->usage == ACTION_MAC || \
1241  ( envelopeInfoPtr->usage == ACTION_CRYPT && \
1242  envelopeInfoPtr->flags & ENVELOPE_AUTHENC ) ) && \
1243  envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
1244  {
1245  /* Definite-length data with no trailer, there's nothing left to
1246  process */
1247  envelopeInfoPtr->deenvState = DEENVSTATE_DONE;
1248  return( CRYPT_OK );
1249  }
1250 
1251  /* If there's not enough data left in the stream to do anything, don't
1252  try and go any further */
1253  if( envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft < 2 )
1254  return( CRYPT_ERROR_UNDERFLOW );
1255 
1256  /* Start reading the trailer data from the end of the payload */
1257  sMemConnect( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,
1258  envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft );
1259 
1260  /* If we haven't started doing anything yet figure out what we should be
1261  looking for */
1262  if( state == DEENVSTATE_NONE )
1263  {
1264  switch( envelopeInfoPtr->usage )
1265  {
1266  case ACTION_SIGN:
1267  status = processSignedTrailer( envelopeInfoPtr, &stream,
1268  &state );
1269  break;
1270 
1271  case ACTION_CRYPT:
1272  /* If it's conventional encrypted data, just look for EOCs */
1273  if( !( envelopeInfoPtr->flags & ENVELOPE_AUTHENC ) )
1274  {
1275  state = DEENVSTATE_EOC;
1276  break;
1277  }
1278 
1279  /* It's authenticated encrypted data, fall through */
1280 
1281  case ACTION_MAC:
1282  /* The error handling here gets a bit tricky in that an
1283  attacker could truncate the data and turn a fatal
1284  CRYPT_ERROR_SIGNATURE into a more benign
1285  CRYPT_ERROR_UNDERFLOW, which may be ignored by the caller
1286  if all of the payload data was successfully recovered.
1287  On the other hand this could be a genuine underflow with
1288  the caller still to push in the MAC trailer data, so we
1289  can't just unconditionally convert an underflow error
1290  into a CRYPT_ERROR_SIGNATURE. At best we can convert a
1291  CRYPT_ERROR_BADDATA or an underflow (or indeed any kind
1292  of error) on an explicit flush into a signature error,
1293  but unfortunately have to leave the CRYPT_ERROR_UNDERFLOW
1294  on a non-flush because we don't know whether the caller
1295  has more data to push. Note that this differs from the
1296  failedMAC == TRUE behaviour in that we return the
1297  signature error immediately, since we can't go any
1298  further as we could for a pure MAC failure with the data-
1299  processing state still OK */
1300  status = processMacTrailer( envelopeInfoPtr, &stream,
1301  &failedMAC );
1302  if( cryptStatusError( status ) )
1303  {
1304  if( isFlush || status == CRYPT_ERROR_BADDATA )
1305  status = CRYPT_ERROR_SIGNATURE;
1306  }
1307  else
1308  {
1309  state = \
1310  ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \
1312  }
1313  break;
1314 
1315  default:
1316  /* Just look for EOCs */
1317  state = DEENVSTATE_EOC;
1318  break;
1319  }
1320  if( cryptStatusError( status ) )
1321  {
1322  sMemDisconnect( &stream );
1323  retExt( status,
1324  ( status, ENVELOPE_ERRINFO,
1325  "Invalid CMS signed/MACd data trailer" ) );
1326  }
1327 
1328  /* Remember how far we got */
1329  streamPos = stell( &stream );
1330  }
1331 
1332  /* Keep consuming information until we run out of input or reach the end
1333  of the data */
1334  for( iterationCount = 0;
1335  state != DEENVSTATE_DONE && iterationCount < FAILSAFE_ITERATIONS_MED;
1336  iterationCount++ )
1337  {
1338  /* Read the certificate chain */
1339  if( state == DEENVSTATE_CERTSET )
1340  {
1341  int certSetLength;
1342 
1343  /* Read the certificate chain into the auxiliary buffer. We
1344  can't import it yet at this point because we need the
1345  SignerInfo to definitively identify the leaf certificate.
1346  Usually there's only one leaf but there will be more than one
1347  if there are multiple signatures present or if the sending
1348  application decides to shovel in assorted (non-relevant)
1349  certificates */
1350  status = getStreamObjectLength( &stream, &certSetLength );
1351  if( cryptStatusError( status ) )
1352  {
1354  "Invalid signing certificate chain header",
1355  40 );
1356  break;
1357  }
1358  if( envelopeInfoPtr->auxBuffer == NULL )
1359  {
1360  /* Allocate a buffer for the certificate chain if necessary.
1361  This may already be allocated if the previous attempt to
1362  read the chain failed due to there being insufficient
1363  data in the envelope buffer, so we make it conditional on
1364  the buffer being NULL */
1365  if( ( envelopeInfoPtr->auxBuffer = \
1366  clAlloc( "processPostamble", certSetLength ) ) == NULL )
1367  {
1368  status = CRYPT_ERROR_MEMORY;
1369  break;
1370  }
1371  envelopeInfoPtr->auxBufSize = certSetLength;
1372  }
1373  ENSURES( envelopeInfoPtr->auxBufSize == certSetLength );
1374  status = sread( &stream, envelopeInfoPtr->auxBuffer,
1375  envelopeInfoPtr->auxBufSize );
1376  if( cryptStatusError( status ) )
1377  break;
1378 
1379  /* Remember where we are and move on to the next state */
1380  streamPos = stell( &stream );
1381  state = DEENVSTATE_SET_SIG;
1382  }
1383 
1384  /* Read the start of the SET OF Signature */
1385  if( state == DEENVSTATE_SET_SIG )
1386  {
1387  int setLength;
1388 
1389  /* Read the SET tag and length */
1390  status = readSetI( &stream, &setLength );
1391  if( cryptStatusError( status ) )
1392  {
1394  "Invalid SET OF Signature header", 31 );
1395  break;
1396  }
1397  envelopeInfoPtr->hdrSetLength = setLength;
1398 
1399  /* Remember where we are and move on to the next state. Some
1400  implementations use the indefinite-length encoding for this so
1401  if there's no length given we have to look for the EOC after
1402  each entry read */
1403  streamPos = stell( &stream );
1404  state = DEENVSTATE_SIG;
1405  }
1406 
1407  /* Read and remember a signature object from a Signature record */
1408  if( state == DEENVSTATE_SIG )
1409  {
1410  int contentItemLength;
1411 
1412  /* Add the object to the content information list */
1413  status = addContentListItem( envelopeInfoPtr, &stream, NULL,
1414  &contentItemLength );
1415  if( cryptStatusError( status ) )
1416  {
1418  "Invalid CMS signature record", 28 );
1419  break;
1420  }
1421 
1422  /* Remember where we are and move on to the next state if
1423  necessary */
1424  streamPos = stell( &stream );
1425  if( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )
1426  {
1427  if( contentItemLength < 0 || \
1428  contentItemLength > envelopeInfoPtr->hdrSetLength )
1429  {
1430  status = CRYPT_ERROR_BADDATA;
1431  break;
1432  }
1433  envelopeInfoPtr->hdrSetLength -= contentItemLength;
1434  if( envelopeInfoPtr->hdrSetLength <= 0 )
1435  {
1436  state = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \
1438  }
1439  }
1440  else
1441  {
1442  const int value = checkEOC( &stream );
1443  if( cryptStatusError( value ) )
1444  {
1445  status = value;
1446  break;
1447  }
1448  if( value == TRUE )
1449  {
1450  state = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \
1452  }
1453  }
1454  }
1455 
1456  /* Handle end-of-contents octets */
1457  if( state == DEENVSTATE_EOC )
1458  {
1459  status = processEOCTrailer( envelopeInfoPtr, &stream );
1460  if( cryptStatusError( status ) )
1461  {
1463  "Invalid CMS EOC trailer", 23 );
1464  break;
1465  }
1466 
1467  /* We're done */
1468  streamPos = stell( &stream );
1469  state = DEENVSTATE_DONE;
1470  break;
1471  }
1472  }
1473  sMemDisconnect( &stream );
1474  if( iterationCount >= FAILSAFE_ITERATIONS_MED )
1475  {
1476  /* We can only go once through the loop on a MAC check so we
1477  shouldn't get here with a failed MAC */
1478  ENSURES( !failedMAC );
1479 
1480  /* Technically this would be an overflow but that's a recoverable
1481  error so we make it a BADDATA, which is really what it is */
1482  return( CRYPT_ERROR_BADDATA );
1483  }
1484  envelopeInfoPtr->deenvState = state;
1485  ENSURES( streamPos >= 0 && streamPos < MAX_INTLENGTH );
1486 
1487  /* Consume the input that we've processed so far by moving everything
1488  past the current position down to the start of the memory buffer:
1489 
1490  bufPos
1491  | bufSize
1492  v v
1493  +-----------+-------+-----------+---+
1494  | dataLeft | | | |
1495  +-----------+-------+-----------+---+
1496  |<--+-->|<-- rem -->|
1497  |
1498  streamPos */
1499  remainder = envelopeInfoPtr->bufPos - \
1500  ( envelopeInfoPtr->dataLeft + streamPos );
1501  REQUIRES( remainder >= 0 && remainder < MAX_INTLENGTH && \
1502  envelopeInfoPtr->dataLeft + streamPos + \
1503  remainder <= envelopeInfoPtr->bufPos );
1504  if( remainder > 0 && streamPos > 0 )
1505  {
1506  REQUIRES( rangeCheck( envelopeInfoPtr->dataLeft + streamPos,
1507  remainder, envelopeInfoPtr->bufPos ) );
1508  memmove( envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,
1509  envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft + streamPos,
1510  remainder );
1511  }
1512  envelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft + remainder;
1513  ENSURES( sanityCheck( envelopeInfoPtr ) );
1514  if( failedMAC )
1515  {
1516  /* If the MAC check failed then this overrides any other status */
1517  return( CRYPT_ERROR_SIGNATURE );
1518  }
1519  if( cryptStatusError( status ) )
1520  {
1521  /* If we got an underflow error but there's payload data left to be
1522  copied out, convert the status to OK since the caller can still
1523  continue before they need to copy in more data. Since there's
1524  more data left to process we return OK_SPECIAL to tell the
1525  calling function not to perform any cleanup */
1526  if( status == CRYPT_ERROR_UNDERFLOW && envelopeInfoPtr->dataLeft > 0 )
1527  return( OK_SPECIAL );
1528 
1529  return( status );
1530  }
1531 
1532  /* If all went OK but we're still not out of the header information,
1533  return an underflow error */
1534  return( ( state != DEENVSTATE_DONE ) ? CRYPT_ERROR_UNDERFLOW : CRYPT_OK );
1535  }
1536 
1537 /****************************************************************************
1538 * *
1539 * Envelope Access Routines *
1540 * *
1541 ****************************************************************************/
1542 
1543 STDC_NONNULL_ARG( ( 1 ) ) \
1544 void initCMSDeenveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr )
1545  {
1546  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1547 
1548  REQUIRES_V( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE );
1549 
1550  /* Set the access method pointers */
1551  envelopeInfoPtr->processPreambleFunction = processPreamble;
1552  envelopeInfoPtr->processPostambleFunction = processPostamble;
1553  envelopeInfoPtr->checkAlgo = cmsCheckAlgo;
1554 
1555  /* Set up the processing state information */
1556  envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
1557  }
1558 #endif /* USE_ENVELOPES */