cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cms_env.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib CMS Enveloping Routines *
4 * Copyright Peter Gutmann 1996-2010 *
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 /****************************************************************************
21 * *
22 * Utility Functions *
23 * *
24 ****************************************************************************/
25 
26 /* Sanity-check the envelope state */
27 
29 static BOOLEAN sanityCheck( const ENVELOPE_INFO *envelopeInfoPtr )
30  {
31  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
32 
33  /* Make sure that general envelope state is in order */
34  if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
35  return( FALSE );
36  if( envelopeInfoPtr->envState < ENVSTATE_NONE || \
37  envelopeInfoPtr->envState >= ENVSTATE_LAST )
38  return( FALSE );
39 
40  /* Make sure that the buffer position is within bounds */
41  if( envelopeInfoPtr->buffer == NULL || \
42  envelopeInfoPtr->bufPos < 0 || \
43  envelopeInfoPtr->bufPos > envelopeInfoPtr->bufSize || \
44  envelopeInfoPtr->bufSize < MIN_BUFFER_SIZE || \
45  envelopeInfoPtr->bufSize >= MAX_INTLENGTH )
46  return( FALSE );
47 
48  /* If the auxBuffer isn't being used, make sure that all values related
49  to it are clear */
50  if( envelopeInfoPtr->auxBuffer == NULL )
51  {
52  if( envelopeInfoPtr->auxBufPos != 0 || \
53  envelopeInfoPtr->auxBufSize != 0 )
54  return( FALSE );
55 
56  return( TRUE );
57  }
58 
59  /* Make sure that the auxBuffer position is within bounds */
60  if( envelopeInfoPtr->auxBufPos < 0 || \
61  envelopeInfoPtr->auxBufPos > envelopeInfoPtr->auxBufSize || \
62  envelopeInfoPtr->auxBufSize < 0 || \
63  envelopeInfoPtr->auxBufSize >= MAX_INTLENGTH )
64  return( FALSE );
65 
66  return( TRUE );
67  }
68 
69 /* Check that a requested algorithm type is valid with enveloped data */
70 
71 CHECK_RETVAL_BOOL \
74  {
75  REQUIRES_B( cryptAlgo > CRYPT_ALGO_NONE && \
76  cryptAlgo < CRYPT_ALGO_LAST_EXTERNAL );
77  REQUIRES_B( ( cryptMode == CRYPT_MODE_NONE ) || \
78  ( cryptMode > CRYPT_MODE_NONE && \
79  cryptMode < CRYPT_MODE_LAST ) );
80 
81  return( checkAlgoID( cryptAlgo, cryptMode ) );
82  }
83 
84 /* Retrieve the principal context type from the envelope's action list */
85 
86 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
87 static int getActionContext( const ENVELOPE_INFO *envelopeInfoPtr,
89  {
91 
92  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
93  assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
94 
95  /* Clear return value */
96  *iCryptContext = CRYPT_ERROR;
97 
98  switch( envelopeInfoPtr->usage )
99  {
100  case ACTION_CRYPT:
101  if( envelopeInfoPtr->flags & ENVELOPE_AUTHENC )
102  actionListPtr = findAction( envelopeInfoPtr->actionList,
103  ACTION_xxx );
104  else
105  actionListPtr = findAction( envelopeInfoPtr->actionList,
106  ACTION_CRYPT );
107  break;
108 
109  case ACTION_MAC:
110  actionListPtr = findAction( envelopeInfoPtr->actionList,
111  ACTION_MAC );
112  break;
113 
114  default:
115  retIntError();
116  }
117  REQUIRES( actionListPtr != NULL );
118  *iCryptContext = actionListPtr->iCryptHandle;
119 
120  return( CRYPT_OK );
121  }
122 
123 /* Get the OID for a CMS content type. If no type is explicitly given, we
124  assume raw data */
125 
126 static const OID_INFO FAR_BSS contentOIDs[] = {
130  { MKOID( "\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x04" ), CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA },
141  { MKOID( "\x06\x06\x67\x81\x08\x01\x01\x01" ), CRYPT_CONTENT_MRTD },
142  { NULL, 0 }, { NULL, 0 }
143  };
144 
145 CHECK_RETVAL_PTR \
146 static const BYTE *getContentOID( IN_ENUM( CRYPT_CONTENT ) \
147  const CRYPT_CONTENT_TYPE contentType )
148  {
149  int i;
150 
151  REQUIRES_N( contentType > CRYPT_CONTENT_NONE && \
152  contentType < CRYPT_CONTENT_LAST );
153 
154  for( i = 0; contentOIDs[ i ].oid != NULL && \
155  i < FAILSAFE_ARRAYSIZE( contentOIDs, OID_INFO ); i++ )
156  {
157  if( contentOIDs[ i ].selectionID == contentType )
158  return( contentOIDs[ i ].oid );
159  }
160 
162  }
163 
164 /* Copy as much post-data state information (i.e. signatures) from the
165  auxiliary buffer to the main buffer as possible */
166 
168 static int copyFromAuxBuffer( INOUT ENVELOPE_INFO *envelopeInfoPtr )
169  {
170  int bytesCopied, dataLeft;
171 
172  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
173 
174  /* Copy as much of the signature data as we can across */
175  bytesCopied = min( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos,
176  envelopeInfoPtr->auxBufPos );
177  REQUIRES( bytesCopied > 0 && \
178  envelopeInfoPtr->bufPos + \
179  bytesCopied <= envelopeInfoPtr->bufSize );
180  memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
181  envelopeInfoPtr->auxBuffer, bytesCopied );
182  envelopeInfoPtr->bufPos += bytesCopied;
183 
184  /* Since we're in the post-data state any necessary payload data
185  segmentation has been completed, however, the caller can't copy out
186  any post-payload data because it's past the end-of-segment position.
187  In order to allow the buffer to be emptied to make room for new data
188  from the auxBuffer we set the end-of-segment position to the end of
189  the new data */
190  envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;
191 
192  /* If there's anything left move it down in the buffer */
193  dataLeft = envelopeInfoPtr->auxBufPos - bytesCopied;
194  if( dataLeft > 0 )
195  {
196  REQUIRES( rangeCheck( bytesCopied, dataLeft, \
197  envelopeInfoPtr->auxBufPos ) );
198  memmove( envelopeInfoPtr->auxBuffer, \
199  envelopeInfoPtr->auxBuffer + bytesCopied, dataLeft );
200  }
201  envelopeInfoPtr->auxBufPos = dataLeft;
202 
203  ENSURES( dataLeft >= 0 );
204 
205  return( ( dataLeft > 0 ) ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
206  }
207 
208 /* Write one or more indefinite-length end-of-contents indicators */
209 
211 static int writeEOCs( INOUT ENVELOPE_INFO *envelopeInfoPtr, const int count )
212  {
213  static const BYTE indefEOC[ 16 ] = \
214  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
216  const int dataLeft = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;
217  const int eocLength = count * sizeofEOC();
218 
219  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
220 
221  REQUIRES( eocLength >= sizeofEOC() && \
222  eocLength <= ( 8 * sizeofEOC() ) ); /* Count = 1...8 */
223 
224  if( dataLeft < eocLength )
225  return( CRYPT_ERROR_OVERFLOW );
226  memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos, indefEOC,
227  eocLength );
228  envelopeInfoPtr->bufPos += eocLength;
229  return( CRYPT_OK );
230  }
231 
232 /****************************************************************************
233 * *
234 * Emit Content-Specific Headers *
235 * *
236 ****************************************************************************/
237 
238 /* Write the header fields that encapsulate any enveloped data:
239 
240  SignedData/DigestedData */
241 
242 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
243 static int writeSignedDataHeader( INOUT STREAM *stream,
244  const ENVELOPE_INFO *envelopeInfoPtr,
245  const BOOLEAN isSignedData )
246  {
247  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
249  long dataSize;
250  int hashActionSize = 0, iterationCount, status;
251 
252  assert( isWritePtr( stream, sizeof( STREAM ) ) );
253  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
254 
255  REQUIRES_S( contentOID != NULL );
256 
257  /* Determine the size of the hash actions */
258  for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
259  actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
260  actionListPtr = actionListPtr->next, iterationCount++ )
261  {
262  const int actionSize = \
263  sizeofContextAlgoID( actionListPtr->iCryptHandle,
264  CRYPT_ALGO_NONE );
265  if( cryptStatusError( actionSize ) )
266  return( actionSize );
267  hashActionSize += actionSize;
268  }
269  ENSURES_S( iterationCount < FAILSAFE_ITERATIONS_MED );
270 
271  /* Determine the size of the SignedData/DigestedData */
272  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \
273  ( envelopeInfoPtr->dataFlags & ENVDATA_HASINDEFTRAILER ) )
274  dataSize = CRYPT_UNUSED;
275  else
276  {
277  /* Determine the size of the content OID + content */
278  dataSize = ( envelopeInfoPtr->payloadSize > 0 ) ? \
279  sizeofObject( sizeofObject( envelopeInfoPtr->payloadSize ) ) : 0;
280  dataSize = sizeofObject( sizeofOID( contentOID ) + dataSize );
281 
282  /* Determine the size of the version, hash algoID, content,
283  certificate chain, and signatures */
284  dataSize = sizeofShortInteger( 1 ) + sizeofObject( hashActionSize ) + \
285  dataSize + envelopeInfoPtr->extraDataSize + \
286  sizeofObject( envelopeInfoPtr->signActionSize );
287  }
288  ENSURES_S( dataSize == CRYPT_UNUSED || \
289  ( dataSize >= MIN_CRYPT_OBJECTSIZE && \
290  dataSize < MAX_INTLENGTH ) );
291 
292  /* Write the SignedData/DigestedData header, version number, and SET OF
293  DigestInfo */
294  if( isSignedData )
295  {
296  status = writeCMSheader( stream, OID_CMS_SIGNEDDATA,
298  dataSize, FALSE );
299  }
300  else
301  {
302  status = writeCMSheader( stream, OID_CMS_DIGESTEDDATA,
304  dataSize, FALSE );
305  }
306  if( cryptStatusError( status ) )
307  return( status );
308  if( envelopeInfoPtr->contentType != CRYPT_CONTENT_DATA )
309  {
310  /* If the encapsulated content-type isn't Data, the version number
311  is 3 rather than 1 (no known implementation actually pays any
312  attention to this, but the spec requires it so we may as well do
313  it) */
314  writeShortInteger( stream, 3, DEFAULT_TAG );
315  }
316  else
317  writeShortInteger( stream, 1, DEFAULT_TAG );
318  writeSet( stream, hashActionSize );
319  for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
320  actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
321  actionListPtr = actionListPtr->next, iterationCount++ )
322  {
323  status = writeContextAlgoID( stream, actionListPtr->iCryptHandle,
324  CRYPT_ALGO_NONE );
325  if( cryptStatusError( status ) )
326  return( status );
327  }
328  ENSURES_S( iterationCount < FAILSAFE_ITERATIONS_MED );
329 
330  /* Write the inner Data header */
331  return( writeCMSheader( stream, contentOID, sizeofOID( contentOID ),
332  envelopeInfoPtr->payloadSize, TRUE ) );
333  }
334 
335 /* EncryptedContentInfo contained within EnvelopedData. This may also be
336  Authenticated or AuthEnc data so the encryption context can be
337  CRYPT_UNUSED */
338 
340 static int getBlockedPayloadSize( IN_LENGTH_INDEF const long payloadSize,
341  IN_LENGTH_IV const int blockSize,
342  OUT_LENGTH_INDEF long *blockedPayloadSize )
343  {
344  assert( isWritePtr( blockedPayloadSize, sizeof( long ) ) );
345 
346  REQUIRES( payloadSize == CRYPT_UNUSED || \
347  ( payloadSize > 0 && payloadSize < MAX_INTLENGTH ) );
348  REQUIRES( blockSize >= 1 && blockSize <= CRYPT_MAX_IVSIZE );
349 
350  /* Clear return value */
351  *blockedPayloadSize = 0;
352 
353  /* If it's an indefinite length payload the blocked size is also of
354  indefinite length */
355  if( payloadSize == CRYPT_UNUSED )
356  {
357  *blockedPayloadSize = CRYPT_UNUSED;
358  return( CRYPT_OK );
359  }
360 
361  /* If it's a stream cipher there's no encryption blocking */
362  if( blockSize <= 1 )
363  {
364  *blockedPayloadSize = payloadSize;
365  return( CRYPT_OK );
366  }
367 
368  /* Calculate the size of the payload after PKCS #5 block padding. This
369  isn't just the size rounded up to the nearest multiple of the block
370  size since if the size is already a multiple of the block size it
371  expands by another block, so we make the payload look one byte longer
372  before rounding to the block size to ensure the one-block expansion */
373  *blockedPayloadSize = roundUp( payloadSize + 1, blockSize );
374 
375  ENSURES( *blockedPayloadSize >= 8 && \
376  *blockedPayloadSize <= payloadSize + CRYPT_MAX_IVSIZE );
377 
378  return( CRYPT_OK );
379  }
380 
381 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
382 static int writeEncryptedContentHeader( INOUT STREAM *stream,
383  IN_BUFFER( contentOIDlength ) const BYTE *contentOID,
385  IN_HANDLE const CRYPT_CONTEXT iCryptContext,
386  IN_LENGTH_INDEF const long payloadSize,
387  IN_LENGTH_IV const long blockSize )
388  {
389  long blockedPayloadSize;
390  int status;
391 
392  assert( isWritePtr( stream, sizeof( STREAM ) ) );
393  assert( isReadPtr( contentOID, contentOIDlength ) );
394 
395  REQUIRES( isHandleRangeValid( iCryptContext ) || \
396  iCryptContext == CRYPT_UNUSED );
397  REQUIRES( payloadSize == CRYPT_UNUSED || \
398  ( payloadSize > 0 && payloadSize < MAX_INTLENGTH ) );
399  REQUIRES( blockSize > 1 && blockSize <= CRYPT_MAX_IVSIZE );
400 
401  status = getBlockedPayloadSize( payloadSize, blockSize,
402  &blockedPayloadSize );
403  if( cryptStatusError( status ) )
404  return( status );
405  return( writeCMSencrHeader( stream, contentOID, contentOIDlength,
406  blockedPayloadSize, iCryptContext ) );
407  }
408 
409 /* EncryptedData, EnvelopedData */
410 
411 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
412 static int getEncryptedContentSize( const ENVELOPE_INFO *envelopeInfoPtr,
413  IN_BUFFER( contentOIDlength ) const BYTE *contentOID,
414  IN_LENGTH_OID const int contentOIDlength,
415  OUT_LENGTH_INDEF long *blockedPayloadSize,
416  OUT_LENGTH_Z long *encrContentInfoSize )
417  {
419  long length;
420  int status;
421 
422  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
423  assert( isReadPtr( contentOID, contentOIDlength ) );
424  assert( isWritePtr( blockedPayloadSize, sizeof( long ) ) );
425  assert( isWritePtr( encrContentInfoSize, sizeof( long ) ) );
426 
427  REQUIRES( contentOIDlength >= MIN_OID_SIZE && \
428  contentOIDlength <= MAX_OID_SIZE );
429 
430  /* Clear return values */
431  *blockedPayloadSize = *encrContentInfoSize = 0;
432 
433  /* Calculate the size of the payload after encryption blocking */
434  status = getBlockedPayloadSize( envelopeInfoPtr->payloadSize,
435  envelopeInfoPtr->blockSize,
436  blockedPayloadSize );
437  if( cryptStatusError( status ) )
438  return( status );
439 
440  /* Calculate the size of the CMS ContentInfo header */
441  status = getActionContext( envelopeInfoPtr, &iCryptContext );
442  if( cryptStatusError( status ) )
443  return( status );
444  length = sizeofCMSencrHeader( contentOID, contentOIDlength,
445  *blockedPayloadSize, iCryptContext );
446  if( cryptStatusError( length ) )
447  return( ( int ) length );
448  *encrContentInfoSize = length;
449 
450  return( CRYPT_OK );
451  }
452 
453 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
454 static int writeEncryptionHeader( INOUT STREAM *stream,
455  IN_BUFFER( oidLength ) const BYTE *oid,
456  IN_LENGTH_OID const int oidLength,
457  IN_RANGE( 0, 2 ) const int version,
458  IN_LENGTH_INDEF const long blockedPayloadSize,
459  IN_LENGTH_INDEF const long extraSize )
460  {
461  int status;
462 
463  assert( isWritePtr( stream, sizeof( STREAM ) ) );
464  assert( isReadPtr( oid, oidLength ) );
465 
466  REQUIRES_S( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );
467  REQUIRES_S( version >= 0 && version <= 2 );
468  REQUIRES_S( ( oidLength == sizeofOID( OID_CMS_AUTHDATA ) && \
469  !memcmp( oid, OID_CMS_AUTHDATA, \
470  sizeofOID( OID_CMS_AUTHDATA ) ) ) || \
471  blockedPayloadSize == CRYPT_UNUSED || \
472  ( blockedPayloadSize >= 8 && \
473  blockedPayloadSize < MAX_INTLENGTH ) );
474  REQUIRES_S( extraSize == CRYPT_UNUSED || \
475  ( extraSize > 0 && extraSize < MAX_INTLENGTH ) );
476 
477  status = writeCMSheader( stream, oid, oidLength,
478  ( blockedPayloadSize == CRYPT_UNUSED || \
479  extraSize == CRYPT_UNUSED ) ? \
480  CRYPT_UNUSED : \
481  sizeofShortInteger( 0 ) + extraSize + \
482  blockedPayloadSize,
483  FALSE );
484  if( cryptStatusError( status ) )
485  return( status );
486  return( writeShortInteger( stream, version, DEFAULT_TAG ) );
487  }
488 
489 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
490 static int writeEncryptedDataHeader( INOUT STREAM *stream,
491  const ENVELOPE_INFO *envelopeInfoPtr )
492  {
493  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
494  long blockedPayloadSize, encrContentInfoSize;
495  int status;
496 
497  assert( isWritePtr( stream, sizeof( STREAM ) ) );
498  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
499 
500  REQUIRES_S( contentOID != NULL );
501 
502  /* Calculate the size of the payload due to blocking and the ContentInfo
503  header */
504  status = getEncryptedContentSize( envelopeInfoPtr, contentOID,
505  sizeofOID( contentOID ),
506  &blockedPayloadSize,
507  &encrContentInfoSize );
508  if( cryptStatusError( status ) )
509  return( status );
510 
511  /* Write the EncryptedData header, version number, and
512  EncryptedContentInfo header */
513  status = writeEncryptionHeader( stream, OID_CMS_ENCRYPTEDDATA,
515  blockedPayloadSize, encrContentInfoSize );
516  if( cryptStatusError( status ) )
517  return( status );
518  return( writeEncryptedContentHeader( stream, contentOID,
519  sizeofOID( contentOID ), envelopeInfoPtr->iCryptContext,
520  envelopeInfoPtr->payloadSize, envelopeInfoPtr->blockSize ) );
521  }
522 
523 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
524 static int writeEnvelopedDataHeader( INOUT STREAM *stream,
525  const ENVELOPE_INFO *envelopeInfoPtr )
526  {
527  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
528  long blockedPayloadSize, encrContentInfoSize;
529  int status;
530 
531  assert( isWritePtr( stream, sizeof( STREAM ) ) );
532  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
533 
534  REQUIRES_S( contentOID != NULL );
535 
536  /* Calculate the size of the payload due to blocking and the ContentInfo
537  header */
538  status = getEncryptedContentSize( envelopeInfoPtr, contentOID,
539  sizeofOID( contentOID ),
540  &blockedPayloadSize,
541  &encrContentInfoSize );
542  if( cryptStatusError( status ) )
543  return( status );
544 
545  /* Write the EnvelopedData header and version number and start of the
546  SET OF RecipientInfo/EncryptionKeyInfo. Technically we need to jump
547  through all sorts of hoops based on the contents and versions of
548  encapsulated RecipientInfo structures but nothing seems to care about
549  this so we just use a version of 0 */
550  status = writeEncryptionHeader( stream, OID_CMS_ENVELOPEDDATA,
552  blockedPayloadSize,
553  ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
554  CRYPT_UNUSED : \
555  sizeofObject( envelopeInfoPtr->cryptActionSize ) + \
556  encrContentInfoSize );
557  if( cryptStatusError( status ) )
558  return( status );
559 
560  return( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
561  writeSetIndef( stream ) : \
562  writeSet( stream, envelopeInfoPtr->cryptActionSize ) );
563  }
564 
565 /* AuthenticatedData, AuthEnvData */
566 
567 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
568 static int writeAuthenticatedDataHeader( INOUT STREAM *stream,
569  const ENVELOPE_INFO *envelopeInfoPtr )
570  {
571  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
572  const int macActionSize = \
573  sizeofContextAlgoID( envelopeInfoPtr->actionList->iCryptHandle,
574  CRYPT_ALGO_NONE );
575  int status;
576 
577  assert( isWritePtr( stream, sizeof( STREAM ) ) );
578  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
579 
580  REQUIRES_S( contentOID != NULL );
581 
582  if( cryptStatusError( macActionSize ) )
583  return( macActionSize );
584 
585  /* Write the AuthenticatedData header and version number and start of
586  the SET OF RecipientInfo. Technically this isn't an encryption
587  header but it uses the same format */
588  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
589  {
590  status = writeEncryptionHeader( stream, OID_CMS_AUTHDATA,
591  sizeofOID( OID_CMS_AUTHDATA ), 0, 1,
592  CRYPT_UNUSED );
593  }
594  else
595  {
596  int macSize, contentInfoSize;
597 
598  /* Determine the size of the MAC and the encapsulated content
599  header */
600  status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle,
601  IMESSAGE_GETATTRIBUTE, &macSize,
603  if( cryptStatusError( status ) )
604  return( status );
605  contentInfoSize = sizeofObject( \
606  sizeofObject( envelopeInfoPtr->payloadSize ) );
607  contentInfoSize = sizeofObject( sizeofOID( contentOID ) + \
608  contentInfoSize ) - \
609  envelopeInfoPtr->payloadSize;
610  REQUIRES_S( contentInfoSize >= 16 && \
611  contentInfoSize < MAX_INTLENGTH );
612 
613  /* Write the data header */
614  status = writeEncryptionHeader( stream, OID_CMS_AUTHDATA,
616  envelopeInfoPtr->payloadSize,
617  ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
618  CRYPT_UNUSED : \
619  sizeofObject( envelopeInfoPtr->cryptActionSize ) + \
620  macActionSize + contentInfoSize + \
621  sizeofObject( macSize ) );
622  }
623  if( cryptStatusError( status ) )
624  return( status );
625 
626  return( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
627  writeSetIndef( stream ) : \
628  writeSet( stream, envelopeInfoPtr->cryptActionSize ) );
629  }
630 
631 CHECK_RETVAL \
632 static int setAlgoParams( IN_HANDLE const CRYPT_CONTEXT iGenericSecret,
633  IN_HANDLE const CRYPT_CONTEXT iCryptContext,
635  {
637  STREAM stream;
638  BYTE algorithmParamData[ CRYPT_MAX_TEXTSIZE + 8 ];
639  int algorithmParamDataSize = DUMMY_INIT, status;
640 
641  REQUIRES( isHandleRangeValid( iGenericSecret ) );
642  REQUIRES( isHandleRangeValid( iCryptContext ) );
643  REQUIRES( attribute == CRYPT_IATTRIBUTE_ENCPARAMS || \
644  attribute == CRYPT_IATTRIBUTE_MACPARAMS );
645 
646  /* Get the algorithm parameter data from the encryption or MAC
647  context */
648  sMemOpen( &stream, algorithmParamData, CRYPT_MAX_TEXTSIZE );
649  if( attribute == CRYPT_IATTRIBUTE_ENCPARAMS )
650  status = writeCryptContextAlgoID( &stream, iCryptContext );
651  else
652  status = writeContextAlgoID( &stream, iCryptContext,
653  CRYPT_ALGO_NONE );
654  if( cryptStatusOK( status ) )
655  algorithmParamDataSize = stell( &stream );
656  sMemDisconnect( &stream );
657  if( cryptStatusError( status ) )
658  return( status );
659 
660  /* Send the encoded parameter information to the generic-secret
661  context */
662  setMessageData( &msgData, algorithmParamData, algorithmParamDataSize );
663  return( krnlSendMessage( iGenericSecret, IMESSAGE_SETATTRIBUTE_S,
664  &msgData, attribute ) );
665  }
666 
667 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
668 static int writeAuthEncDataHeader( INOUT STREAM *stream,
669  const ENVELOPE_INFO *envelopeInfoPtr )
670  {
671  CRYPT_CONTEXT iGenericSecret;
672  const ACTION_LIST *actionListPtr;
673  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
674  long blockedPayloadSize, encrContentInfoSize;
675  int macSize = 0, status;
676 
677  assert( isWritePtr( stream, sizeof( STREAM ) ) );
678  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
679 
680  REQUIRES_S( contentOID != NULL );
681 
682  /* Authenticated encryption derives the encryption and MAC keys from the
683  generic-secret value, with the encryption and MAC algorithm
684  parameters being provided in the generic-secret's AlgorithmIdentifier
685  value. In order to work with the generic secret we therefore have to
686  send the encryption and MAC parameter data to the generic-secret
687  context */
688  actionListPtr = findAction( envelopeInfoPtr->actionList, ACTION_xxx );
689  REQUIRES( actionListPtr != NULL );
690  iGenericSecret = actionListPtr->iCryptHandle;
691  actionListPtr = findAction( envelopeInfoPtr->actionList, ACTION_CRYPT );
692  REQUIRES( actionListPtr != NULL );
693  status = setAlgoParams( iGenericSecret, actionListPtr->iCryptHandle,
694  CRYPT_IATTRIBUTE_ENCPARAMS );
695  if( cryptStatusError( status ) )
696  return( status );
697  actionListPtr = findAction( envelopeInfoPtr->actionList, ACTION_MAC );
698  REQUIRES( actionListPtr != NULL );
699  status = setAlgoParams( iGenericSecret, actionListPtr->iCryptHandle,
700  CRYPT_IATTRIBUTE_MACPARAMS );
701  if( cryptStatusError( status ) )
702  return( status );
703 
704  /* Calculate the size of the payload due to blocking and the ContentInfo
705  header */
706  status = getEncryptedContentSize( envelopeInfoPtr, contentOID,
707  sizeofOID( contentOID ),
708  &blockedPayloadSize,
709  &encrContentInfoSize );
710  if( cryptStatusError( status ) )
711  return( status );
712 
713  /* If it's definite-length content we have to determine the size of the
714  MAC at the end of the data as well */
715  if( blockedPayloadSize != CRYPT_UNUSED )
716  {
717  actionListPtr = findAction( envelopeInfoPtr->actionList, ACTION_MAC );
718  REQUIRES( actionListPtr != NULL );
719  status = krnlSendMessage( actionListPtr->iCryptHandle,
720  IMESSAGE_GETATTRIBUTE, &macSize,
722  if( cryptStatusError( status ) )
723  return( status );
724  }
725 
726  /* Write the EnvelopedData header and version number and start of the
727  SET OF RecipientInfo/EncryptionKeyInfo */
728  status = writeEncryptionHeader( stream, OID_CMS_AUTHENVDATA,
730  blockedPayloadSize,
731  ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
732  CRYPT_UNUSED : \
733  sizeofObject( envelopeInfoPtr->cryptActionSize ) + \
734  encrContentInfoSize + \
735  sizeofObject( macSize ) );
736  if( cryptStatusError( status ) )
737  return( status );
738 
739  return( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \
740  writeSetIndef( stream ) : \
741  writeSet( stream, envelopeInfoPtr->cryptActionSize ) );
742  }
743 
744 /* CompressedData */
745 
746 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
747 static int writeCompressedDataHeader( INOUT STREAM *stream,
748  INOUT ENVELOPE_INFO *envelopeInfoPtr )
749  {
750  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
751  int status;
752 
753  assert( isWritePtr( stream, sizeof( STREAM ) ) );
754  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
755 
756  REQUIRES_S( contentOID != NULL );
757 
758  /* Since compressing the data changes its length we have to use the
759  indefinite-length encoding even if we know how big the payload is */
760  envelopeInfoPtr->payloadSize = CRYPT_UNUSED;
761 
762  /* Write the CompressedData header, version number, and Zlib algoID */
763  status = writeCMSheader( stream, OID_CMS_COMPRESSEDDATA,
765  CRYPT_UNUSED, FALSE );
766  if( cryptStatusError( status ) )
767  return( status );
768  writeShortInteger( stream, 0, DEFAULT_TAG );
769  writeGenericAlgoID( stream, OID_ZLIB, sizeofOID( OID_ZLIB ) );
770 
771  /* Write the inner Data header */
772  return( writeCMSheader( stream, contentOID, sizeofOID( contentOID ),
773  CRYPT_UNUSED, TRUE ) );
774  }
775 
776 /****************************************************************************
777 * *
778 * Header Processing Routines *
779 * *
780 ****************************************************************************/
781 
782 /* Write the envelope header */
783 
785 static int writeEnvelopeHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr )
786  {
787  STREAM stream;
788  int status;
789 
790  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
791 
792  /* If we're encrypting, set up the encryption-related information */
793  if( envelopeInfoPtr->usage == ACTION_CRYPT )
794  {
795  const ACTION_LIST *actionListPtr = \
796  findAction( envelopeInfoPtr->actionList, ACTION_CRYPT );
797 
798  REQUIRES( actionListPtr != NULL );
799  status = initEnvelopeEncryption( envelopeInfoPtr,
800  actionListPtr->iCryptHandle,
802  NULL, 0, FALSE );
803  if( cryptStatusError( status ) )
804  return( status );
805  }
806 
807  /* Write the appropriate CMS header based on the envelope usage. The
808  DigestedData/ACTION_HASH action is never taken since the higher-level
809  code assumes that the presence of hash actions indicates the desire
810  to create signed data and returns an error if no signature actions are
811  present */
812  sMemOpen( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );
813  switch( envelopeInfoPtr->usage )
814  {
815  case ACTION_CRYPT:
816  /* If we're using authenticated encryption then we have to use
817  a special-form AuthEnc CMS header even though technically
818  it's just an encrypted envelope */
819  if( envelopeInfoPtr->flags & ENVELOPE_AUTHENC )
820  {
821  status = writeAuthEncDataHeader( &stream,
822  envelopeInfoPtr );
823  break;
824  }
825 
826  /* It's standard encrypted data */
827  if( envelopeInfoPtr->preActionList == NULL )
828  status = writeEncryptedDataHeader( &stream,
829  envelopeInfoPtr );
830  else
831  status = writeEnvelopedDataHeader( &stream,
832  envelopeInfoPtr );
833  break;
834 
835  case ACTION_SIGN:
836  status = writeSignedDataHeader( &stream, envelopeInfoPtr, TRUE );
837  break;
838 
839  case ACTION_HASH:
840  status = writeSignedDataHeader( &stream, envelopeInfoPtr, FALSE );
841  break;
842 
843  case ACTION_COMPRESS:
844  status = writeCompressedDataHeader( &stream, envelopeInfoPtr );
845  break;
846 
847  case ACTION_NONE:
848  {
849  const BYTE *contentOID = \
850  getContentOID( envelopeInfoPtr->contentType );
851 
852  REQUIRES( contentOID != NULL );
853 
854  status = writeCMSheader( &stream, contentOID,
855  sizeofOID( contentOID ),
856  envelopeInfoPtr->payloadSize, FALSE );
857  break;
858  }
859 
860  case ACTION_MAC:
861  status = writeAuthenticatedDataHeader( &stream, envelopeInfoPtr );
862  break;
863 
864  default:
865  retIntError();
866  }
867  if( cryptStatusOK( status ) )
868  envelopeInfoPtr->bufPos = stell( &stream );
869  sMemDisconnect( &stream );
870  if( cryptStatusError( status ) )
871  return( status );
872 
873  /* If we're not encrypting with key exchange actions, we're done */
874  if( ( envelopeInfoPtr->usage != ACTION_CRYPT && \
875  envelopeInfoPtr->usage != ACTION_MAC ) || \
876  envelopeInfoPtr->preActionList == NULL )
877  {
878  /* Set the block size mask to all ones if we're not encrypting since
879  we can begin and end data segments on arbitrary boundaries and
880  inform the caller that we're done */
881  if( envelopeInfoPtr->usage != ACTION_CRYPT )
882  envelopeInfoPtr->blockSizeMask = -1;
883  envelopeInfoPtr->lastAction = NULL;
884  return( OK_SPECIAL );
885  }
886 
887  /* Start emitting the key exchange actions */
888  envelopeInfoPtr->lastAction = findAction( envelopeInfoPtr->preActionList,
890  if( envelopeInfoPtr->lastAction == NULL )
891  envelopeInfoPtr->lastAction = findAction( envelopeInfoPtr->preActionList,
893  ENSURES( envelopeInfoPtr->lastAction != NULL );
894 
895  return( CRYPT_OK );
896  }
897 
898 /* Write key exchange actions */
899 
901 static int writeKeyex( INOUT ENVELOPE_INFO *envelopeInfoPtr )
902  {
905  int iterationCount, status = CRYPT_OK;
906 
907  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
908 
909  /* Get the appropriate encryption, MAC, or generic-secret context to
910  export via the keyex actions */
911  status = getActionContext( envelopeInfoPtr, &iCryptContext );
912  if( cryptStatusError( status ) )
913  return( status );
914 
915  /* Export the session key/MAC using each of the PKC or conventional
916  keys. If it's a conventional key exchange we force the use of the
917  CMS format since there's no reason to use the cryptlib format */
918  for( actionListPtr = envelopeInfoPtr->lastAction, iterationCount = 0;
919  actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
920  actionListPtr = actionListPtr->next, iterationCount++ )
921  {
922  const CRYPT_FORMAT_TYPE formatType = \
923  ( actionListPtr->action == ACTION_KEYEXCHANGE ) ? \
924  CRYPT_FORMAT_CMS : envelopeInfoPtr->type;
925  const int dataLeft = min( envelopeInfoPtr->bufSize - \
926  envelopeInfoPtr->bufPos,
927  MAX_INTLENGTH_SHORT - 1 );
928  int keyexSize;
929 
930  ENSURES( dataLeft >= 0 && dataLeft < MAX_INTLENGTH_SHORT );
931 
932  /* Make sure that there's enough room to emit this key exchange
933  action */
934  if( actionListPtr->encodedSize + 128 > dataLeft )
935  {
936  status = CRYPT_ERROR_OVERFLOW;
937  break;
938  }
939 
940  /* Emit the key exchange action */
941  status = iCryptExportKey( envelopeInfoPtr->buffer + \
942  envelopeInfoPtr->bufPos, dataLeft,
943  &keyexSize, formatType, iCryptContext,
944  actionListPtr->iCryptHandle );
945  if( cryptStatusError( status ) )
946  break;
947  envelopeInfoPtr->bufPos += keyexSize;
948  }
949  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
950  envelopeInfoPtr->lastAction = actionListPtr;
951  if( cryptStatusError( status ) )
952  return( status );
953 
954  /* If it's an indefinite-length header close off the set of key
955  exchange actions */
956  if( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED )
957  return( writeEOCs( envelopeInfoPtr, 1 ) );
958 
959  return( CRYPT_OK );
960  }
961 
962 /****************************************************************************
963 * *
964 * Trailer Processing Routines *
965 * *
966 ****************************************************************************/
967 
968 /* Write the signing certificate chain. This can grow arbitrarily large and
969  in particular can become larger than the main envelope buffer if multiple
970  signatures with long chains and a small envelope buffer are used, so we
971  emit the certificate chain into a dynamically-allocated auxiliary buffer
972  if there isn't enough room to emit it into the main buffer */
973 
975 static int writeCertchainTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr )
976  {
977  STREAM stream;
978  void *certChainBufPtr;
979  const int dataLeft = min( envelopeInfoPtr->bufSize - \
980  envelopeInfoPtr->bufPos,
981  MAX_INTLENGTH_SHORT - 1 );
982  const int eocSize = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \
983  ( 3 * sizeofEOC() ) : 0;
984  int certChainBufSize, certChainSize = DUMMY_INIT, status;
985 
986  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
987 
988  ENSURES( dataLeft >= 0 && dataLeft < MAX_INTLENGTH_SHORT );
989 
990  /* Check whether there's enough room left in the buffer to emit the
991  signing certificate chain directly into it */
992  if( envelopeInfoPtr->extraDataSize + 64 < dataLeft )
993  {
994  /* The certificate chain will fit into the envelope buffer */
995  certChainBufPtr = envelopeInfoPtr->buffer + \
996  envelopeInfoPtr->bufPos + eocSize;
997  certChainBufSize = dataLeft - eocSize;
998  }
999  else
1000  {
1001  /* If there's almost no room left in the buffer anyway tell the
1002  caller that they have to pop some data before they can continue.
1003  Hopefully this will create enough room to emit the certificates
1004  directly into the buffer */
1005  if( dataLeft < 1024 )
1006  return( CRYPT_ERROR_OVERFLOW );
1007 
1008  /* We can't emit the certificates directly into the envelope buffer,
1009  allocate an auxiliary buffer for them and from there copy them
1010  into the main buffer */
1011  REQUIRES( envelopeInfoPtr->auxBuffer == NULL );
1012  if( ( envelopeInfoPtr->auxBuffer = \
1013  clDynAlloc( "emitPostamble",
1014  envelopeInfoPtr->extraDataSize + 64 ) ) == NULL )
1015  return( CRYPT_ERROR_MEMORY );
1016  certChainBufPtr = envelopeInfoPtr->auxBuffer;
1017  certChainBufSize = envelopeInfoPtr->auxBufSize = \
1018  envelopeInfoPtr->extraDataSize + 64;
1019  }
1020 
1021  /* Write the end-of-contents octets for the Data OCTET STRING, [0], and
1022  SEQUENCE if necessary */
1023  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
1024  {
1025  status = writeEOCs( envelopeInfoPtr, 3 );
1026  if( cryptStatusError( status ) )
1027  return( status );
1028  }
1029  envelopeInfoPtr->lastAction = envelopeInfoPtr->postActionList;
1030 
1031  /* Write the signing certificate chain if it's a CMS signature and
1032  they're not explicitly excluded, followed by the SET OF SignerInfo
1033  header */
1034  sMemOpen( &stream, certChainBufPtr, certChainBufSize );
1035  if( ( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
1036  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) && \
1037  !( envelopeInfoPtr->flags & ENVELOPE_NOSIGNINGCERTS ) )
1038  {
1039  status = exportCertToStream( &stream,
1040  ( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR ) ? \
1041  envelopeInfoPtr->iExtraCertChain : \
1042  envelopeInfoPtr->lastAction->iCryptHandle,
1043  CRYPT_ICERTFORMAT_CERTSET );
1044  if( cryptStatusError( status ) )
1045  {
1046  sMemDisconnect( &stream );
1047  return( status );
1048  }
1049  }
1050  if( envelopeInfoPtr->dataFlags & ENVDATA_HASINDEFTRAILER )
1051  status = writeSetIndef( &stream );
1052  else
1053  status = writeSet( &stream, envelopeInfoPtr->signActionSize );
1054  if( cryptStatusOK( status ) )
1055  certChainSize = stell( &stream );
1056  sMemDisconnect( &stream );
1057  if( cryptStatusError( status ) )
1058  return( status );
1059 
1060  /* If we're copying data via the auxBuffer flush as much as we can into
1061  the main buffer. If we can't copy it all in, resulting in an overflow
1062  error, we use the OK_SPECIAL status to tell the caller that although
1063  an overflow occurred it was due to the auxBuffer copy and not the
1064  certificate chain write and it's OK to move on to the next state */
1065  if( envelopeInfoPtr->auxBufSize > 0 )
1066  {
1067  envelopeInfoPtr->auxBufPos = certChainSize;
1068  status = copyFromAuxBuffer( envelopeInfoPtr );
1069  return( ( status == CRYPT_ERROR_OVERFLOW ) ? OK_SPECIAL : status );
1070  }
1071 
1072  /* Since we're in the post-data state any necessary payload data
1073  segmentation has been completed, however the caller can't copy out
1074  any post-payload data because it's past the end-of-segment position.
1075  In order to allow the buffer to be emptied to make room for signature
1076  data we set the end-of-segment position to the end of the new data */
1077  envelopeInfoPtr->bufPos += certChainSize;
1078  envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;
1079 
1080  return( CRYPT_OK );
1081  }
1082 
1083 /* Write signatures */
1084 
1085 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1086 static int writeSignatures( INOUT ENVELOPE_INFO *envelopeInfoPtr )
1087  {
1089  int iterationCount, status = CRYPT_OK;
1090 
1091  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1092 
1093  /* Sign each hash using the associated signature key */
1094  for( actionListPtr = envelopeInfoPtr->lastAction, iterationCount = 0;
1095  actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
1096  actionListPtr = actionListPtr->next, iterationCount++ )
1097  {
1099  const int sigBufSize = min( envelopeInfoPtr->bufSize - \
1100  envelopeInfoPtr->bufPos, \
1101  MAX_INTLENGTH_SHORT - 1 );
1102  int sigSize;
1103 
1104  REQUIRES( actionListPtr->action == ACTION_SIGN );
1105  ENSURES( sigBufSize >= 0 && sigBufSize < MAX_INTLENGTH_SHORT );
1106 
1107  /* Check whether there's enough room left in the buffer to emit the
1108  signature directly into it. Since signatures are fairly small (a
1109  few hundred bytes) we always require enough room in the buffer
1110  and don't bother with any overflow handling via the auxBuffer */
1111  if( actionListPtr->encodedSize + 64 > sigBufSize )
1112  {
1113  status = CRYPT_ERROR_OVERFLOW;
1114  break;
1115  }
1116 
1117  /* Set up any necessary signature parameters such as signature
1118  attributes and timestamps if necessary */
1119  status = cmsInitSigParams( actionListPtr, envelopeInfoPtr->type,
1120  envelopeInfoPtr->ownerHandle,
1121  &sigParams );
1122  if( cryptStatusError( status ) )
1123  break;
1124 
1125  /* Sign the data */
1126  REQUIRES( actionListPtr->associatedAction != NULL );
1127  status = iCryptCreateSignature( envelopeInfoPtr->buffer + \
1128  envelopeInfoPtr->bufPos, sigBufSize,
1129  &sigSize, envelopeInfoPtr->type,
1130  actionListPtr->iCryptHandle,
1131  actionListPtr->associatedAction->iCryptHandle,
1132  ( envelopeInfoPtr->type == CRYPT_FORMAT_CRYPTLIB ) ? \
1133  NULL : &sigParams );
1134  if( cryptStatusError( status ) )
1135  break;
1136  envelopeInfoPtr->bufPos += sigSize;
1137  }
1138  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
1139  envelopeInfoPtr->lastAction = actionListPtr;
1140 
1141  /* The possibilities for problems when creating a signature are complex
1142  enough that we provide special-case reporting for specific types of
1143  problems. In particular we pull up lower-level information from
1144  signature-creation related objects if they're being used, and if
1145  there are multiple signatures being created we identify the
1146  individual signature that caused the problem */
1147  if( cryptStatusError( status ) )
1148  {
1149  if( actionListPtr->iTspSession != CRYPT_ERROR )
1150  {
1151  retExtObj( status,
1152  ( status, ENVELOPE_ERRINFO,
1153  actionListPtr->iTspSession,
1154  "Couldn't emit signature to envelope trailer" ) );
1155  }
1156  if( iterationCount <= 0 )
1157  {
1158  retExt( status,
1159  ( status, ENVELOPE_ERRINFO,
1160  "Couldn't emit signature to envelope trailer" ) );
1161  }
1162  retExt( status,
1163  ( status, ENVELOPE_ERRINFO,
1164  "Couldn't emit signature #%d to envelope trailer",
1165  iterationCount + 1 ) );
1166  }
1167 
1168  return( CRYPT_OK );
1169  }
1170 
1171 /* Write MAC value */
1172 
1173 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1174 static int writeMAC( INOUT ENVELOPE_INFO *envelopeInfoPtr )
1175  {
1176  const ACTION_LIST *actionListPtr = \
1177  findAction( envelopeInfoPtr->actionList, ACTION_MAC );
1178  STREAM stream;
1180  BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
1181  const int eocSize = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \
1182  ( 3 * sizeofEOC() ) : 0;
1183  const int dataLeft = min( envelopeInfoPtr->bufSize - \
1184  envelopeInfoPtr->bufPos, 512 );
1185  int length = DUMMY_INIT, status;
1186 
1187  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1188 
1189  REQUIRES( actionListPtr != NULL );
1190 
1191  /* Make sure that there's room for the MAC data in the buffer */
1192  if( dataLeft < eocSize + sizeofObject( CRYPT_MAX_HASHSIZE ) )
1193  return( CRYPT_ERROR_OVERFLOW );
1194 
1195  /* Write the end-of-contents octets for the Data OCTET STRING, [0], and
1196  SEQUENCE if necessary */
1197  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
1198  {
1199  status = writeEOCs( envelopeInfoPtr, 3 );
1200  if( cryptStatusError( status ) )
1201  return( status );
1202  }
1203 
1204  /* Get the MAC value and write it to the buffer */
1205  setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
1206  status = krnlSendMessage( actionListPtr->iCryptHandle,
1207  IMESSAGE_GETATTRIBUTE_S, &msgData,
1209  if( cryptStatusError( status ) )
1210  return( status );
1211  sMemOpen( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
1212  dataLeft );
1213  status = writeOctetString( &stream, hash, msgData.length, DEFAULT_TAG );
1214  if( cryptStatusOK( status ) )
1215  length = stell( &stream );
1216  sMemDisconnect( &stream );
1217  if( cryptStatusError( status ) )
1218  return( status );
1219  envelopeInfoPtr->bufPos += length;
1220 
1221  return( CRYPT_OK );
1222  }
1223 
1224 /****************************************************************************
1225 * *
1226 * Emit Envelope Preamble/Postamble *
1227 * *
1228 ****************************************************************************/
1229 
1230 /* Output as much of the preamble as possible into the envelope buffer */
1231 
1232 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1233 static int emitPreamble( INOUT ENVELOPE_INFO *envelopeInfoPtr )
1234  {
1235  int status = CRYPT_OK;
1236 
1237  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1238 
1239  REQUIRES( sanityCheck( envelopeInfoPtr ) );
1240 
1241  /* If we've finished processing the header information, don't do
1242  anything */
1243  if( envelopeInfoPtr->envState == ENVSTATE_DONE )
1244  return( CRYPT_OK );
1245 
1246  /* If we haven't started doing anything yet perform various final
1247  initialisations */
1248  if( envelopeInfoPtr->envState == ENVSTATE_NONE )
1249  {
1250  /* If there's no nested content type set default to plain data */
1251  if( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )
1252  envelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;
1253 
1254  /* If there's an absolute data length set, remember it for when we
1255  copy in data */
1256  if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
1257  envelopeInfoPtr->segmentSize = envelopeInfoPtr->payloadSize;
1258 
1259  /* Perform any remaining initialisation. MAC'd data is a special-
1260  case form of encrypted data so we treat them as the same thing
1261  at the key exchange level */
1262  if( envelopeInfoPtr->usage == ACTION_CRYPT || \
1263  envelopeInfoPtr->usage == ACTION_MAC )
1264  status = cmsPreEnvelopeEncrypt( envelopeInfoPtr );
1265  else
1266  {
1267  if( envelopeInfoPtr->usage == ACTION_SIGN )
1268  status = cmsPreEnvelopeSign( envelopeInfoPtr );
1269  }
1270  if( cryptStatusError( status ) )
1271  {
1272  retExt( status,
1273  ( status, ENVELOPE_ERRINFO,
1274  "Couldn't perform final %s initialisation prior to "
1275  "enveloping data",
1276  ( envelopeInfoPtr->usage == ACTION_SIGN ) ? \
1277  "signing" : "encryption" ) );
1278  }
1279 
1280  /* Delete any orphaned actions such as automatically-added hash
1281  actions that were overridden with user-supplied alternate
1282  actions */
1283  status = deleteUnusedActions( envelopeInfoPtr );
1284  if( cryptStatusError( status ) )
1285  return( status );
1286 
1287  /* Make sure that we start a new segment when we add the first lot
1288  of payload data after we've emitted the header info */
1289  envelopeInfoPtr->dataFlags |= ENVDATA_SEGMENTCOMPLETE;
1290 
1291  /* We're ready to go, prepare to emit the outer header */
1292  envelopeInfoPtr->envState = ENVSTATE_HEADER;
1293 
1294  ENSURES( checkActions( envelopeInfoPtr ) );
1295  }
1296 
1297  /* Emit the outer header. This always follows directly from the final
1298  initialisation step but we keep the two logically distinct to
1299  emphasise the fact that the former is merely finalising enveloping
1300  actions without performing any header processing while the latter is
1301  the first stage that actually emits header data */
1302  if( envelopeInfoPtr->envState == ENVSTATE_HEADER )
1303  {
1304  status = writeEnvelopeHeader( envelopeInfoPtr );
1305  if( cryptStatusError( status ) )
1306  {
1307  /* If there's nothing else to emit, we're done */
1308  if( status == OK_SPECIAL )
1309  {
1310  envelopeInfoPtr->envState = ENVSTATE_DONE;
1311  ENSURES( sanityCheck( envelopeInfoPtr ) );
1312 
1313  return( CRYPT_OK );
1314  }
1315 
1316  retExt( status,
1317  ( status, ENVELOPE_ERRINFO,
1318  "Couldn't create envelope header" ) );
1319  }
1320 
1321  /* Move on to the next state */
1322  envelopeInfoPtr->envState = ENVSTATE_KEYINFO;
1323  }
1324 
1325  /* Handle key export actions */
1326  if( envelopeInfoPtr->envState == ENVSTATE_KEYINFO )
1327  {
1328  status = writeKeyex( envelopeInfoPtr );
1329  if( cryptStatusError( status ) )
1330  {
1331  retExt( status,
1332  ( status, ENVELOPE_ERRINFO,
1333  "Couldn't emit key exchange actions to envelope "
1334  "header" ) );
1335  }
1336 
1337  /* Move on to the next state */
1338  envelopeInfoPtr->envState = ENVSTATE_ENCRINFO;
1339  }
1340 
1341  /* Handle encrypted content information */
1342  if( envelopeInfoPtr->envState == ENVSTATE_ENCRINFO )
1343  {
1344  STREAM stream;
1345  const BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );
1346  const int originalBufPos = envelopeInfoPtr->bufPos;
1347  const int dataLeft = min( envelopeInfoPtr->bufSize - \
1348  envelopeInfoPtr->bufPos, \
1349  MAX_INTLENGTH_SHORT - 1 );
1350 
1351  REQUIRES( contentOID != NULL );
1352  ENSURES( dataLeft >= 0 && dataLeft < MAX_INTLENGTH_SHORT );
1353 
1354  /* Make sure that there's enough room to emit the data header. The
1355  value used is only approximate, if there's not enough room left
1356  the write will also return an overflow error */
1357  if( dataLeft < 256 )
1358  return( CRYPT_ERROR_OVERFLOW );
1359 
1360  /* Write the encrypted content header */
1361  sMemOpen( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
1362  dataLeft );
1363  if( envelopeInfoPtr->usage == ACTION_MAC )
1364  {
1365  /* If it's authenticated data, there's a MAC algorithm ID
1366  preceding standard EncapContent */
1367  status = writeContextAlgoID( &stream,
1368  envelopeInfoPtr->actionList->iCryptHandle,
1369  CRYPT_ALGO_NONE );
1370  if( cryptStatusOK ( status ) )
1371  {
1372  status = writeCMSheader( &stream, contentOID,
1373  sizeofOID( contentOID ),
1374  envelopeInfoPtr->payloadSize,
1375  TRUE );
1376  }
1377  }
1378  else
1379  {
1381 
1382  /* It's encrypted data, it's EncrContent */
1383  status = getActionContext( envelopeInfoPtr, &iCryptContext );
1384  if( cryptStatusError( status ) )
1385  return( status );
1386  status = writeEncryptedContentHeader( &stream, contentOID,
1387  sizeofOID( contentOID ), iCryptContext,
1388  envelopeInfoPtr->payloadSize,
1389  envelopeInfoPtr->blockSize );
1390  }
1391  if( cryptStatusOK( status ) )
1392  envelopeInfoPtr->bufPos += stell( &stream );
1393  sMemDisconnect( &stream );
1394  if( cryptStatusOK( status ) && \
1395  envelopeInfoPtr->flags & ENVELOPE_AUTHENC )
1396  {
1397  const ACTION_LIST *actionListPtr = \
1398  findAction( envelopeInfoPtr->actionList, ACTION_MAC );
1399  const void *macData = DUMMY_INIT_PTR;
1400  int macDataLength = DUMMY_INIT;
1401 
1402  REQUIRES( actionListPtr != NULL );
1403 
1404  /* For AuthEnc data we have to MAC the
1405  EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier
1406  information alongside the payload data to prevent an attacker
1407  from manipulating the algorithm parameters to cause
1408  corruption that won't be detected by the MAC on the payload
1409  data. This requires digging down into the encrypted content
1410  header to locate the AlgoID data and MACing that */
1411  sMemConnect( &stream, envelopeInfoPtr->buffer + originalBufPos,
1412  envelopeInfoPtr->bufPos - originalBufPos );
1413  readLongSequence( &stream, NULL ); /* Outer encapsulation */
1414  status = readUniversal( &stream ); /* Content-type OID */
1415  if( cryptStatusOK( status ) )
1416  status = getStreamObjectLength( &stream, &macDataLength );
1417  if( cryptStatusOK( status ) ) /* AlgoID */
1418  {
1419  status = sMemGetDataBlock( &stream, ( void ** ) &macData,
1420  macDataLength );
1421  }
1422  if( cryptStatusOK( status ) )
1423  {
1424  status = krnlSendMessage( actionListPtr->iCryptHandle,
1426  ( MESSAGE_CAST ) macData,
1427  macDataLength );
1428  }
1429  sMemDisconnect( &stream );
1430  }
1431  if( cryptStatusError( status ) )
1432  {
1433  retExt( status,
1434  ( status, ENVELOPE_ERRINFO,
1435  "Couldn't emit encrypted content header to envelope "
1436  "header" ) );
1437  }
1438 
1439 #if 0 /* ?/?/08 Commented out between 3.3.1 and 3.3.2 although there's no
1440  indication why */
1441  /* Make sure that we start a new segment if we try to add any data */
1442  envelopeInfoPtr->dataFlags |= ENVDATA_SEGMENTCOMPLETE;
1443 #endif /* 0 */
1444 
1445  /* We're done */
1446  envelopeInfoPtr->envState = ENVSTATE_DONE;
1447  }
1448 
1449  ENSURES( sanityCheck( envelopeInfoPtr ) );
1450 
1451  return( CRYPT_OK );
1452  }
1453 
1454 /* Output as much of the postamble as possible into the envelope buffer */
1455 
1456 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
1457 static int emitPostamble( INOUT ENVELOPE_INFO *envelopeInfoPtr,
1458  STDC_UNUSED const BOOLEAN dummy )
1459  {
1460  int status;
1461 
1462  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1463 
1464  REQUIRES( sanityCheck( envelopeInfoPtr ) );
1465 
1466  /* Before we can emit the trailer we need to flush any remaining data
1467  from internal buffers */
1468  if( envelopeInfoPtr->envState == ENVSTATE_NONE )
1469  {
1470  status = envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
1471  NULL, 0 );
1472  if( cryptStatusError( status ) )
1473  {
1474  retExt( status,
1475  ( status, ENVELOPE_ERRINFO,
1476  "Couldn't flush remaining data into envelope "
1477  "buffer" ) );
1478  }
1479  envelopeInfoPtr->envState = \
1480  ( envelopeInfoPtr->usage == ACTION_SIGN ) ? \
1482  }
1483 
1484  /* The only message type that has a trailer is signed or authenticated
1485  data so if we're not signing/authenticating data we can exit now */
1486  if( !( envelopeInfoPtr->usage == ACTION_SIGN || \
1487  envelopeInfoPtr->usage == ACTION_MAC || \
1488  ( envelopeInfoPtr->usage == ACTION_CRYPT && \
1489  ( envelopeInfoPtr->flags & ENVELOPE_AUTHENC ) ) ) )
1490  {
1491  /* Emit the various end-of-contents octets if necessary */
1492  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \
1493  ( envelopeInfoPtr->usage == ACTION_CRYPT &&
1494  envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) )
1495  {
1496  /* Write the end-of-contents octets for the encapsulated data if
1497  necessary. Normally we have two EOCs, however compressed
1498  data requires an extra one due to the explicit tagging */
1499  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \
1500  ( envelopeInfoPtr->usage == ACTION_CRYPT || \
1501  envelopeInfoPtr->usage == ACTION_COMPRESS ) )
1502  {
1503  status = writeEOCs( envelopeInfoPtr, 3 + \
1504  ( ( envelopeInfoPtr->usage == \
1505  ACTION_COMPRESS ) ? \
1506  3 : 2 ) );
1507  }
1508  else
1509  {
1510  /* Write the remaining end-of-contents octets for the OCTET
1511  STRING/SEQUENCE, [0], and SEQUENCE */
1512  status = writeEOCs( envelopeInfoPtr, 3 );
1513  }
1514  if( cryptStatusError( status ) )
1515  {
1516  retExt( status,
1517  ( status, ENVELOPE_ERRINFO,
1518  "Couldn't emit final EOC octets" ) );
1519  }
1520  }
1521 
1522  /* Now that we've written the final end-of-contents octets, set the end-
1523  of-segment-data pointer to the end of the data in the buffer so that
1524  copyFromEnvelope() can copy out the remaining data */
1525  envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;
1526  envelopeInfoPtr->envState = ENVSTATE_DONE;
1527 
1528  ENSURES( sanityCheck( envelopeInfoPtr ) );
1529 
1530  return( CRYPT_OK );
1531  }
1532 
1533  /* If there's any signature data left in the auxiliary buffer try and
1534  empty that first */
1535  if( envelopeInfoPtr->auxBufPos > 0 )
1536  {
1537  status = copyFromAuxBuffer( envelopeInfoPtr );
1538  if( cryptStatusError( status ) )
1539  {
1540  retExt( status,
1541  ( status, ENVELOPE_ERRINFO,
1542  "Couldn't flush remaining signature data into "
1543  "envelope buffer" ) );
1544  }
1545  }
1546 
1547  /* Handle signing certificate chain */
1548  if( envelopeInfoPtr->envState == ENVSTATE_FLUSHED )
1549  {
1550  status = writeCertchainTrailer( envelopeInfoPtr );
1551  if( cryptStatusError( status ) && status != OK_SPECIAL )
1552  {
1553  retExt( status,
1554  ( status, ENVELOPE_ERRINFO,
1555  "Couldn't emit certificate chain to envelope "
1556  "trailer" ) );
1557  }
1558 
1559  /* Move on to the next state */
1560  envelopeInfoPtr->envState = ENVSTATE_SIGNATURE;
1561 
1562  /* If we were writing the certificate chain using the auxBuffer as
1563  an intermediate stage because there wasn't enough room to
1564  assemble the complete chain in the main buffer and we then got an
1565  overflow error moving the data out into the main buffer we have
1566  to resume later in the signature state */
1567  if( status == OK_SPECIAL )
1568  return( CRYPT_ERROR_OVERFLOW );
1569  }
1570 
1571  /* Handle signing actions */
1572  REQUIRES( envelopeInfoPtr->envState == ENVSTATE_SIGNATURE );
1573 
1574  /* Write the signatures/MACs. The process of writing signatures is
1575  complex enough that the function itself sets the extended error
1576  information */
1577  if( envelopeInfoPtr->usage == ACTION_SIGN )
1578  {
1579  status = writeSignatures( envelopeInfoPtr );
1580  if( cryptStatusError( status ) )
1581  return( status );
1582  }
1583  else
1584  {
1585  status = writeMAC( envelopeInfoPtr );
1586  if( cryptStatusError( status ) )
1587  {
1588  retExt( status,
1589  ( status, ENVELOPE_ERRINFO,
1590  "Couldn't emit MAC to envelope trailer" ) );
1591  }
1592  }
1593 
1594  /* Write the end-of-contents octets for the OCTET STRING/SEQUENCE, [0],
1595  and SEQUENCE if necessary. If the trailer has an indefinite length
1596  then we need to add an EOC for the trailer as well */
1597  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \
1598  ( envelopeInfoPtr->dataFlags & ENVDATA_HASINDEFTRAILER ) )
1599  {
1600  status = writeEOCs( envelopeInfoPtr,
1601  3 + ( ( envelopeInfoPtr->dataFlags & \
1603  1 : 0 ) );
1604  if( cryptStatusError( status ) )
1605  {
1606  retExt( status,
1607  ( status, ENVELOPE_ERRINFO,
1608  "Couldn't emit final EOC octets" ) );
1609  }
1610  }
1611 
1612  /* Now that we've written the final end-of-contents octets set the end-
1613  of-segment-data pointer to the end of the data in the buffer so that
1614  copyFromEnvelope() can copy out the remaining data */
1615  envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;
1616  envelopeInfoPtr->envState = ENVSTATE_DONE;
1617 
1618  ENSURES( sanityCheck( envelopeInfoPtr ) );
1619 
1620  return( CRYPT_OK );
1621  }
1622 
1623 /****************************************************************************
1624 * *
1625 * Envelope Access Routines *
1626 * *
1627 ****************************************************************************/
1628 
1629 STDC_NONNULL_ARG( ( 1 ) ) \
1630 void initCMSEnveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr )
1631  {
1632  int algorithm, status;
1633 
1634  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
1635 
1636  REQUIRES_V( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) );
1637 
1638  /* Set the access method pointers */
1639  envelopeInfoPtr->processPreambleFunction = emitPreamble;
1640  envelopeInfoPtr->processPostambleFunction = emitPostamble;
1641  envelopeInfoPtr->checkAlgo = cmsCheckAlgo;
1642 
1643  /* Set up the processing state information */
1644  envelopeInfoPtr->envState = ENVSTATE_NONE;
1645 
1646  /* Remember the current default settings for use with the envelope.
1647  We force the use of the CBC encryption mode because this is the
1648  safest and most efficient encryption mode, and the only mode defined
1649  for many CMS algorithms. Since the CMS algorithms represent only a
1650  subset of what's available we have to drop back to fixed values if
1651  the caller has selected something exotic */
1652  status = krnlSendMessage( envelopeInfoPtr->ownerHandle,
1653  IMESSAGE_GETATTRIBUTE, &algorithm,
1655  if( cryptStatusError( status ) || \
1656  !checkAlgoID( algorithm, CRYPT_MODE_NONE ) )
1657  envelopeInfoPtr->defaultHash = CRYPT_ALGO_SHA1;
1658  else
1659  envelopeInfoPtr->defaultHash = algorithm; /* int vs.enum */
1660  status = krnlSendMessage( envelopeInfoPtr->ownerHandle,
1661  IMESSAGE_GETATTRIBUTE, &algorithm,
1663  if( cryptStatusError( status ) || \
1664  !checkAlgoID( algorithm, ( algorithm == CRYPT_ALGO_RC4 ) ? \
1666  envelopeInfoPtr->defaultAlgo = CRYPT_ALGO_3DES;
1667  else
1668  envelopeInfoPtr->defaultAlgo = algorithm; /* int vs.enum */
1669  status = krnlSendMessage( envelopeInfoPtr->ownerHandle,
1670  IMESSAGE_GETATTRIBUTE, &algorithm,
1672  if( cryptStatusError( status ) || \
1673  !checkAlgoID( algorithm, CRYPT_MODE_NONE ) )
1674  envelopeInfoPtr->defaultMAC = CRYPT_ALGO_HMAC_SHA1;
1675  else
1676  envelopeInfoPtr->defaultMAC = algorithm; /* int vs.enum */
1677  }
1678 #endif /* USE_ENVELOPES */