cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cryptenv.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Enveloping Routines *
4 * Copyright Peter Gutmann 1996-2007 *
5 * *
6 ****************************************************************************/
7 
8 #include "crypt.h"
9 #ifdef INC_ALL
10  #include "envelope.h"
11 #else
12  #include "envelope/envelope.h"
13 #endif /* Compiler-specific includes */
14 
15 /* The default size for the envelope buffer. On 16-bit systems they're
16  smaller because of memory and int size limitations */
17 
18 #if defined( CONFIG_CONSERVE_MEMORY )
19  #define DEFAULT_BUFFER_SIZE 8192
20 #elif INT_MAX <= 32767
21  #define DEFAULT_BUFFER_SIZE 16384
22 #else
23  #define DEFAULT_BUFFER_SIZE 32768
24 #endif /* OS-specific envelope size defines */
25 
26 /* When pushing and popping data, overflow and underflow errors can be
27  recovered from by adding or removing data so we don't retain the error
28  state for these error types */
29 
30 #define isRecoverableError( status ) \
31  ( ( status ) == CRYPT_ERROR_OVERFLOW || \
32  ( status ) == CRYPT_ERROR_UNDERFLOW )
33 
34 #ifdef USE_ENVELOPES
35 
36 /****************************************************************************
37 * *
38 * Envelope Data Handling Functions *
39 * *
40 ****************************************************************************/
41 
42 /* Push data into an envelope */
43 
45 static int envelopePush( INOUT ENVELOPE_INFO *envelopeInfoPtr,
46  IN_BUFFER_OPT( length ) const void *buffer,
47  IN_LENGTH_Z const int length,
49  {
50  int status;
51 
52  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
53  assert( ( buffer == NULL && length == 0 ) || \
54  isReadPtr( buffer, length ) );
55  assert( isWritePtr( bytesCopied, sizeof( int ) ) );
56 
57  REQUIRES( ( buffer == NULL && length == 0 ) || \
58  ( buffer != NULL && length > 0 && length < MAX_INTLENGTH ) );
59 
60  /* Clear return value */
61  *bytesCopied = 0;
62 
63  /* If we haven't started processing data yet, handle the initial data
64  specially */
65  if( envelopeInfoPtr->state == STATE_PREDATA )
66  {
67  /* Make sure that all of the information that we need to proceed is
68  present */
69  status = envelopeInfoPtr->checkMissingInfo( envelopeInfoPtr );
70  if( cryptStatusError( status ) )
71  return( status );
72 
73  /* If the envelope buffer hasn't been allocated yet, allocate it now */
74  if( envelopeInfoPtr->buffer == NULL )
75  {
76  if( ( envelopeInfoPtr->buffer = \
77  clAlloc( "envelopePush", \
78  envelopeInfoPtr->bufSize + 8 ) ) == NULL )
79  return( CRYPT_ERROR_MEMORY );
80  memset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );
81  }
82 
83  /* Emit the header information into the envelope */
84  status = envelopeInfoPtr->processPreambleFunction( envelopeInfoPtr );
85  if( cryptStatusError( status ) )
86  {
87  if( !isRecoverableError( status ) )
88  envelopeInfoPtr->errorState = status;
89  return( status );
90  }
91 
92  /* The envelope is ready to process data, move it into the high
93  state */
94  status = krnlSendMessage( envelopeInfoPtr->objectHandle,
96  CRYPT_IATTRIBUTE_INITIALISED );
97  if( cryptStatusError( status ) )
98  {
99  envelopeInfoPtr->errorState = status;
100  return( status );
101  }
102 
103  /* Move on to the data-processing state */
104  envelopeInfoPtr->state = STATE_DATA;
105  }
106 
107  /* If we're in the main data processing state, add the data and perform
108  any necessary actions on it */
109  if( envelopeInfoPtr->state == STATE_DATA )
110  {
111  if( length > 0 )
112  {
113  /* Copy the data to the envelope */
114  status = envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
115  buffer, length );
116  if( cryptStatusError( status ) )
117  {
118  if( !isRecoverableError( status ) )
119  envelopeInfoPtr->errorState = status;
120  return( status );
121  }
122  *bytesCopied = status;
123 
124  return( ( *bytesCopied < length ) ? \
126  }
127 
128  /* This was a flush, move on to the postdata state */
129  envelopeInfoPtr->state = STATE_POSTDATA;
130  envelopeInfoPtr->envState = ENVSTATE_NONE;
131  }
132 
133  ENSURES( envelopeInfoPtr->state == STATE_POSTDATA );
134 
135  /* We're past the main data-processing state, emit the postamble */
136  status = envelopeInfoPtr->processPostambleFunction( envelopeInfoPtr,
137  FALSE );
138  if( cryptStatusError( status ) )
139  {
140  if( !isRecoverableError( status ) )
141  envelopeInfoPtr->errorState = status;
142  return( status );
143  }
144  envelopeInfoPtr->state = STATE_FINISHED;
145 
146  return( CRYPT_OK );
147  }
148 
150 static int deenvelopePush( INOUT ENVELOPE_INFO *envelopeInfoPtr,
151  IN_BUFFER_OPT( length ) const void *buffer,
152  IN_LENGTH_Z const int length,
154  {
155  BYTE *bufPtr = ( BYTE * ) buffer;
156  int bytesIn = length, status = CRYPT_OK;
157 
158  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
159  assert( ( buffer == NULL && length == 0 ) || \
160  isReadPtr( buffer, length ) );
161  assert( isWritePtr( bytesCopied, sizeof( int ) ) );
162 
163  REQUIRES( ( buffer == NULL && length == 0 ) || \
164  ( buffer != NULL && length > 0 && length < MAX_INTLENGTH ) );
165 
166  /* Clear return value */
167  *bytesCopied = 0;
168 
169  /* If we haven't started processing data yet, handle the initial data
170  specially */
171  if( envelopeInfoPtr->state == STATE_PREDATA )
172  {
173  BOOLEAN copiedData = FALSE;
174 
175  /* Perform any initialisation actions */
176  if( envelopeInfoPtr->buffer == NULL )
177  {
178  /* Allocate the envelope buffer */
179  if( ( envelopeInfoPtr->buffer = \
180  clAlloc( "deenvelopePush", \
181  envelopeInfoPtr->bufSize + 8 ) ) == NULL )
182  return( CRYPT_ERROR_MEMORY );
183  memset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );
184 
185 #ifdef USE_PGP
186  /* Try and determine what the data format being used is. If it
187  looks like PGP data, try and process it as such, otherwise
188  default to PKCS #7/CMS/S/MIME */
189  if( length > 0 && ( bufPtr[ 0 ] & 0x80 ) )
190  {
191  /* When we initially created the envelope we defaulted to CMS
192  formatting so we have to select PGP de-enveloping before
193  we can continue */
194  envelopeInfoPtr->type = CRYPT_FORMAT_PGP;
195  initPGPDeenveloping( envelopeInfoPtr );
196  }
197 #endif /* USE_PGP */
198  }
199 
200  /* Since we're processing out-of-band information, just copy it in
201  directly */
202  if( bytesIn > 0 )
203  {
204  const int bytesToCopy = min( envelopeInfoPtr->bufSize - \
205  envelopeInfoPtr->bufPos, bytesIn );
206 
207  ENSURES( bytesToCopy >= 0 && bytesToCopy <= length && \
208  envelopeInfoPtr->bufPos + \
209  bytesToCopy <= envelopeInfoPtr->bufSize );
210  if( bytesToCopy > 0 )
211  {
212  memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
213  bufPtr, bytesToCopy );
214  envelopeInfoPtr->bufPos += bytesToCopy;
215  bytesIn -= bytesToCopy;
216  *bytesCopied = bytesToCopy;
217  bufPtr += bytesToCopy;
218  copiedData = TRUE;
219  }
220  }
221 
222  /* Process the preamble */
223  status = envelopeInfoPtr->processPreambleFunction( envelopeInfoPtr );
224  if( cryptStatusError( status ) )
225  {
226  /* If we've processed at least some data and it's a non-fatal
227  error like an underflow, suppress it. We need to do this
228  because the copy function above will always consume input (if
229  it can) and if we returned an error at this point it would
230  indicate to the caller that they can ignore the bytes-copied
231  parameter */
232  if( isRecoverableError( status ) )
233  {
234  if( copiedData )
235  return( CRYPT_OK );
236  }
237  else
238  {
239  /* It's a fatal error, make it persistent */
240  envelopeInfoPtr->errorState = status;
241  }
242  return( status );
243  }
244 
245  /* The envelope is ready to process data, move it into the high
246  state */
247  status = krnlSendMessage( envelopeInfoPtr->objectHandle,
249  CRYPT_IATTRIBUTE_INITIALISED );
250  if( cryptStatusError( status ) )
251  {
252  /* The envelope may already have been moved into the high state
253  as a side-effect of adding de-enveloping information (whether
254  the transition occurs here or in res_denv.c depends on the
255  order in which the caller performs operations) so if we get a
256  permission error it's means that we're already in the high
257  state and we can ignore it */
258  if( status != CRYPT_ERROR_PERMISSION )
259  {
260  envelopeInfoPtr->errorState = status;
261  return( status );
262  }
263  status = CRYPT_OK;
264  }
265 
266  /* Move on to the data-processing state */
267  envelopeInfoPtr->state = STATE_DATA;
268  }
269 
270  /* If we're in the main data processing state, add the data and perform
271  any necessary actions on it */
272  if( envelopeInfoPtr->state == STATE_DATA )
273  {
274  /* If there's data to be copied, copy it into the envelope. If we've
275  come from the predata state we may have zero bytes to copy if
276  everything was consumed by the preamble processing, or there may
277  be room to copy more in now if the preamble processing consumed
278  some of what was present */
279  if( bytesIn > 0 )
280  {
281  /* Copy the data to the envelope */
282  const int byteCount = \
283  envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
284  bufPtr, bytesIn );
285  if( cryptStatusError( byteCount ) )
286  {
287  if( !isRecoverableError( byteCount ) )
288  envelopeInfoPtr->errorState = byteCount;
289  return( byteCount );
290  }
291  *bytesCopied += byteCount;
292  bytesIn -= byteCount;
293  bufPtr += byteCount;
294  }
295 
296  /* If we've reached the end of the payload (either by having seen the
297  EOC octets with the indefinite encoding or by having reached the
298  end of the single segment with the definite encoding), move on to
299  the postdata state */
300  if( ( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) || \
301  ( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
302  envelopeInfoPtr->segmentSize <= 0 ) )
303  {
304  envelopeInfoPtr->state = STATE_POSTDATA;
305  envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
306  }
307 
308 #ifdef USE_PGP
309  /* Special-case for the wierd non-length-encoding that some PGP
310  implementations use for compressed data which uses neither a
311  definite nor indefinite-length encoding but consists of an
312  implicit "until you run out of input", see the comment in the PGP
313  readPacketHeader() for more details. To accomodate this lack of
314  the data's ability to tell us when it's ended, if we're processing
315  PGP compressed data and there's no length information present and
316  it's a data flush we assume that that's all there is */
317  if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
318  envelopeInfoPtr->usage == ACTION_COMPRESS && \
319  envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \
320  length <= 0 )
321  {
322  envelopeInfoPtr->state = STATE_POSTDATA;
323  envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
324  }
325 #endif /* USE_PGP */
326  }
327 
328  /* If we're past the main data-processing state, process the postamble */
329  if( envelopeInfoPtr->state == STATE_POSTDATA )
330  {
331  /* Since we're processing trailer information, just copy it in
332  directly */
333  if( bytesIn > 0 )
334  {
335  const int bytesToCopy = min( envelopeInfoPtr->bufSize - \
336  envelopeInfoPtr->bufPos, bytesIn );
337 
338  ENSURES( bytesToCopy >= 0 && bytesToCopy <= bytesIn && \
339  envelopeInfoPtr->bufPos + \
340  bytesToCopy <= envelopeInfoPtr->bufSize );
341  if( bytesToCopy > 0 )
342  {
343  memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
344  bufPtr, bytesToCopy );
345  envelopeInfoPtr->bufPos += bytesToCopy;
346  *bytesCopied += bytesToCopy;
347  }
348  }
349 
350  /* Process the postamble. During this processing we can encounter
351  two special types of recoverable error, CRYPT_ERROR_UNDERFLOW (we
352  need more data to continue) or OK_SPECIAL (we processed all of
353  the data but there's out-of-band information still to go), if
354  it's one of these then we don't treat it as a standard error */
355  status = envelopeInfoPtr->processPostambleFunction( envelopeInfoPtr,
356  ( bytesIn <= 0 ) ? TRUE : FALSE );
357  if( cryptStatusError( status ) && status != OK_SPECIAL )
358  {
359  if( !isRecoverableError( status ) )
360  {
361  envelopeInfoPtr->errorState = status;
362 
363  /* MACd and authenticated-encrypted envelopes differ
364  somewhat from signed envelopes in that the integrity
365  check results are available immediately that payload
366  processing is complete rather than afterwards as the
367  result of user action with signature metadata. As a
368  result the postamble processing can return a
369  CRYPT_ERROR_SIGNATURE to indicate that although all data
370  was processed successfully (which would normally produce
371  a CRYPT_OK result) the integrity check for the data
372  failed. To reconcile the two status values we treat the
373  envelope as if a CRYPT_OK had been returned (by marking
374  processing as being complete) while recording a
375  CRYPT_ERROR_SIGNATURE. However we do return the
376  signature error since the user may be using authenticated
377  encryption and not even be aware that they should perform
378  an explicit check for a signature failure */
379  if( status == CRYPT_ERROR_SIGNATURE && \
380  ( envelopeInfoPtr->usage == ACTION_MAC || \
381  ( envelopeInfoPtr->usage == ACTION_CRYPT && \
382  ( envelopeInfoPtr->flags & ENVELOPE_AUTHENC ) ) ) )
383  envelopeInfoPtr->state = STATE_FINISHED;
384  }
385  return( status );
386  }
387  ENSURES( status == CRYPT_OK || status == OK_SPECIAL );
388 
389  /* If the postamble processing routine returns OK_SPECIAL then it's
390  processed enough of the postamble for the caller to continue, but
391  there's more to go so we shouldn't change the overall state yet */
392  if( status == CRYPT_OK )
393  {
394  /* We've processed all data, we're done unless it's a detached
395  sig with the data supplied out-of-band */
396  envelopeInfoPtr->state = \
397  ( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) ? \
399  }
400 
401  /* At this point we always exit since the out-of-band data has to be
402  processed in a separate push */
403  return( CRYPT_OK );
404  }
405 
406  /* If there's extra out-of-band data present, process it separately.
407  This is slightly complicated by the fact that the single envelope is
408  being used to process two independent lots of data, so we have to be
409  careful to distinguish between handling of the main payload data and
410  handling of this additional out-of-band data */
411  if( envelopeInfoPtr->state == STATE_EXTRADATA )
412  {
413  /* We pass this point twice, the first time round we check the state
414  and if it's DEENVSTATE_DONE (set when processing of the main data
415  was completed) we reset it to DEENVSTATE_NONE and make sure that
416  it's a flush */
417  if( envelopeInfoPtr->deenvState == DEENVSTATE_DONE )
418  {
419  /* We've finished with the main payload data, reset the state for
420  the additional out-of-band data. Normally we exit here since
421  it's a flush, however if the hash value was supplied
422  externally (which means that hashing was never active, since
423  it was done by the caller) we drop through to the wrap-up,
424  since there's no second flush of payload data to be performed
425  and so the flush applies to both sets of data */
426  envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
427  if( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE )
428  return( length ? CRYPT_ERROR_BADDATA : CRYPT_OK );
429  }
430 
431  /* This is just raw additional data so we feed it directly to the
432  processing function. If this is a flush then the buffer will be
433  set to NULL which the low-level routines don't allow so we
434  substitute an empty buffer */
435  status = envelopeInfoPtr->processExtraData( envelopeInfoPtr,
436  ( buffer == NULL ) ? "" : buffer, length );
437  if( cryptStatusOK( status ) )
438  {
439  *bytesCopied = length;
440  if( length <= 0 )
441  envelopeInfoPtr->state = STATE_FINISHED;
442  }
443  }
444 
445  return( status );
446  }
447 
448 /* Pop data from an envelope */
449 
450 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
451 static int envelopePop( INOUT ENVELOPE_INFO *envelopeInfoPtr,
452  OUT_BUFFER( length, *bytesCopied ) void *buffer,
453  IN_LENGTH const int length,
454  OUT_LENGTH_Z int *bytesCopied )
455  {
456  int status;
457 
458  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
459  assert( isWritePtr( buffer, length ) );
460  assert( isWritePtr( bytesCopied, sizeof( int ) ) );
461 
462  REQUIRES( length > 0 && length < MAX_INTLENGTH );
463 
464  /* Clear return value */
465  *bytesCopied = 0;
466 
467  /* Copy the data from the envelope to the output */
468  status = envelopeInfoPtr->copyFromEnvelopeFunction( envelopeInfoPtr,
469  buffer, length,
470  bytesCopied,
472  if( cryptStatusError( status ) )
473  envelopeInfoPtr->errorState = status;
474  return( status );
475  }
476 
477 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
478 static int deenvelopePop( INOUT ENVELOPE_INFO *envelopeInfoPtr,
479  OUT_BUFFER( length, *bytesCopied ) void *buffer,
480  IN_LENGTH const int length,
481  OUT_LENGTH_Z int *bytesCopied )
482  {
483  int status;
484 
485  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
486  assert( isWritePtr( buffer, length ) );
487  assert( isWritePtr( bytesCopied, sizeof( int ) ) );
488 
489  REQUIRES( length > 0 && length < MAX_INTLENGTH );
490 
491  /* Clear return value */
492  *bytesCopied = 0;
493 
494  /* If we haven't reached the data yet force a flush to try and get to
495  it. We can end up with this condition if the caller pushes in
496  deenveloping information and then immediately tries to pop data
497  without an intervening flush (or implicit flush on the initial push) to
498  resolve the state of the data in the envelope */
499  if( envelopeInfoPtr->state == STATE_PREDATA )
500  {
501  int dummy;
502 
503  status = deenvelopePush( envelopeInfoPtr, NULL, 0, &dummy );
504  if( cryptStatusError( status ) )
505  return( status );
506 
507  /* If we still haven't got anywhere return an underflow error */
508  if( envelopeInfoPtr->state == STATE_PREDATA )
509  return( CRYPT_ERROR_UNDERFLOW );
510  }
511 
512  /* Copy the data from the envelope to the output */
513  status = envelopeInfoPtr->copyFromEnvelopeFunction( envelopeInfoPtr,
514  buffer, length,
515  bytesCopied,
517  if( cryptStatusError( status ) && !isRecoverableError( status ) )
518  envelopeInfoPtr->errorState = status;
519  return( status );
520  }
521 
522 /****************************************************************************
523 * *
524 * Envelope Message Handler *
525 * *
526 ****************************************************************************/
527 
528 /* Handle a message sent to an envelope */
529 
531 static int envelopeMessageFunction( INOUT TYPECAST( ENVELOPE_INFO * ) \
532  void *objectInfoPtr,
534  void *messageDataPtr,
535  IN_INT_Z const int messageValue )
536  {
537  ENVELOPE_INFO *envelopeInfoPtr = ( ENVELOPE_INFO * ) objectInfoPtr;
538 
539  assert( isWritePtr( objectInfoPtr, sizeof( ENVELOPE_INFO ) ) );
540 
541  REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
542  REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH );
543 
544  /* Process destroy object messages */
545  if( message == MESSAGE_DESTROY )
546  {
547  int status = CRYPT_OK;
548 
549  /* Check to see whether the envelope still needs operations performed
550  on it to resolve the state of the data within it (for example if
551  the caller pushes data but doesn't flush it, there will be a few
552  bytes left that can't be popped). For enveloping, destroying the
553  envelope while it's in any state other than STATE_PREDATA or
554  STATE_FINISHED or if there's data still left in the buffer is
555  regarded as an error. For de-enveloping we have to be more
556  careful since deenveloping information required to resolve the
557  envelope state could be unavailable so we shouldn't return an
558  error if something like a signature check remains to be done.
559  What we therefore do is check to see whether we've processed any
560  data yet and report an error if there's data left in the envelope
561  or if we're destroying it in the middle of processing data */
562  if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
563  {
564  const BOOLEAN isAuthEnvelope = \
565  ( envelopeInfoPtr->usage == ACTION_MAC || \
566  ( envelopeInfoPtr->usage == ACTION_CRYPT && \
567  ( envelopeInfoPtr->flags & ENVELOPE_AUTHENC ) ) ) ? \
568  TRUE : FALSE;
569 
570  /* If we've got to the point of processing data in the envelope
571  and there's either more to come or some left to pop, we
572  shouldn't be destroying it yet. This straightforward check
573  is complicated by the integrity check performed with
574  authenticated envelopes, leading to two special cases:
575 
576  1. If the integrity checks fails then the integrity-check-
577  failed status prevents the user from popping the
578  (corrupted) data so that there may be data left in the
579  envelope through no fault of the user. In this case we
580  don't treat the data-left status as an error.
581 
582  2. If an attacker truncates the data in an attempt to
583  convert a fatal CRYPT_ERROR_SIGNATURE into a more benign
584  CRYPT_ERROR_UNDERFLOW then we want to try and alert the
585  caller to the fact that there's a problem, so we convert
586  a non-finished state for an authenticated envelope into
587  an integrity-check failure */
588  if( envelopeInfoPtr->state == STATE_DATA )
589  status = CRYPT_ERROR_INCOMPLETE;
590  if( ( envelopeInfoPtr->state == STATE_POSTDATA || \
591  envelopeInfoPtr->state == STATE_FINISHED ) && \
592  envelopeInfoPtr->dataLeft > 0 && \
593  !( isAuthEnvelope && \
594  envelopeInfoPtr->errorState == CRYPT_ERROR_SIGNATURE ) )
595  status = CRYPT_ERROR_INCOMPLETE;
596  if( status == CRYPT_ERROR_INCOMPLETE && isAuthEnvelope )
597  status = CRYPT_ERROR_SIGNATURE;
598  }
599  else
600  {
601  /* If we're in the middle of processing data we shouldn't be
602  destroying the envelope yet */
603  if( envelopeInfoPtr->state != STATE_PREDATA && \
604  envelopeInfoPtr->state != STATE_FINISHED )
605  status = CRYPT_ERROR_INCOMPLETE;
606  if( envelopeInfoPtr->bufPos > 0 )
607  status = CRYPT_ERROR_INCOMPLETE;
608  }
609 
610  /* Delete the action and content lists */
611  if( envelopeInfoPtr->preActionList != NULL )
612  deleteActionList( envelopeInfoPtr->memPoolState,
613  envelopeInfoPtr->preActionList );
614  if( envelopeInfoPtr->actionList != NULL )
615  deleteActionList( envelopeInfoPtr->memPoolState,
616  envelopeInfoPtr->actionList );
617  if( envelopeInfoPtr->postActionList != NULL )
618  deleteActionList( envelopeInfoPtr->memPoolState,
619  envelopeInfoPtr->postActionList );
620  if( envelopeInfoPtr->contentList != NULL )
621  deleteContentList( envelopeInfoPtr->memPoolState,
622  &envelopeInfoPtr->contentList );
623 
624 #ifdef USE_COMPRESSION
625  /* Delete the zlib compression state information if necessary */
626  if( envelopeInfoPtr->flags & ENVELOPE_ZSTREAMINITED )
627  {
628  if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
629  inflateEnd( &envelopeInfoPtr->zStream );
630  else
631  deflateEnd( &envelopeInfoPtr->zStream );
632  }
633 #endif /* USE_COMPRESSION */
634 
635  /* Clean up keysets */
636  if( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )
637  krnlSendNotifier( envelopeInfoPtr->iSigCheckKeyset,
639  if( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )
640  krnlSendNotifier( envelopeInfoPtr->iEncryptionKeyset,
642  if( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )
643  krnlSendNotifier( envelopeInfoPtr->iDecryptionKeyset,
645 
646  /* Clean up other envelope objects */
647  if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
648  krnlSendNotifier( envelopeInfoPtr->iExtraCertChain,
650 
651  /* Clear and free the buffers if necessary */
652  if( envelopeInfoPtr->buffer != NULL )
653  {
654  zeroise( envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );
655  clFree( "envelopeMessageFunction", envelopeInfoPtr->buffer );
656  }
657  if( envelopeInfoPtr->auxBuffer != NULL )
658  {
659  zeroise( envelopeInfoPtr->auxBuffer, envelopeInfoPtr->auxBufSize );
660  clFree( "envelopeMessageFunction", envelopeInfoPtr->auxBuffer );
661  }
662 
663  return( status );
664  }
665 
666  /* Process attribute get/set/delete messages */
667  if( isAttributeMessage( message ) )
668  {
669  REQUIRES( message == MESSAGE_GETATTRIBUTE || \
670  message == MESSAGE_GETATTRIBUTE_S || \
671  message == MESSAGE_SETATTRIBUTE || \
672  message == MESSAGE_SETATTRIBUTE_S || \
673  message == MESSAGE_DELETEATTRIBUTE );
674  REQUIRES( isAttribute( messageValue ) || \
675  isInternalAttribute( messageValue ) );
676 
677  if( message == MESSAGE_GETATTRIBUTE )
678  return( getEnvelopeAttribute( envelopeInfoPtr,
679  ( int * ) messageDataPtr,
680  messageValue ) );
681  if( message == MESSAGE_GETATTRIBUTE_S )
682  return( getEnvelopeAttributeS( envelopeInfoPtr,
683  ( MESSAGE_DATA * ) messageDataPtr,
684  messageValue ) );
685  if( message == MESSAGE_SETATTRIBUTE )
686  {
687  /* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message
688  with no parameters so we don't pass it down to the attribute-
689  handling code */
690  if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
691  return( CRYPT_OK );
692 
693  return( setEnvelopeAttribute( envelopeInfoPtr,
694  *( ( int * ) messageDataPtr ),
695  messageValue ) );
696  }
697  if( message == MESSAGE_SETATTRIBUTE_S )
698  {
699  const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
700 
701  return( setEnvelopeAttributeS( envelopeInfoPtr, msgData->data,
702  msgData->length, messageValue ) );
703  }
704 
705  retIntError();
706  }
707 
708  /* Process object-specific messages */
709  if( message == MESSAGE_ENV_PUSHDATA )
710  {
711  MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
712  const int length = msgData->length;
713  int bytesCopied, status;
714 
715  assert( ( msgData->data == NULL && msgData->length == 0 ) || \
716  ( isReadPtr( msgData->data, msgData->length ) ) );
717 
718  REQUIRES( ( msgData->data == NULL && msgData->length == 0 ) || \
719  ( msgData->data != NULL && \
720  msgData->length > 0 && msgData->length < MAX_INTLENGTH ) );
721 
722  /* Unless we're told otherwise, we've copied zero bytes */
723  msgData->length = 0;
724 
725  /* Make sure that everything is in order */
726  if( length == 0 )
727  {
728  /* If it's a flush make sure that we're in a state where this is
729  valid. We can only perform a flush on enveloping if we're in
730  the data or postdata state, on deenveloping a flush can
731  happen at any time since the entire payload could be buffered
732  pending the addition of a deenveloping resource, so the
733  envelope goes from pre -> post in one step. There is however
734  one special case in which a push in the pre-data state is
735  valid and that's when we're creating a zero-length CMS signed
736  message as a means of communicating authenticated attributes
737  (of all the standard users of CMS, only SCEP normally does
738  this). In order to indicate that this special case is in
739  effect we require that the user set the ENVELOPE_ATTRONLY
740  flag before pushing data, although for completeness we could
741  also check the CMS attributes for the presence of SCEP
742  attributes. The downside of this additional checking is that
743  it makes any non-SCEP use of signature-only CMS envelopes
744  impossible */
745  if( envelopeInfoPtr->state == STATE_FINISHED )
746  return( CRYPT_OK );
747  if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
748  ( envelopeInfoPtr->state != STATE_DATA && \
749  envelopeInfoPtr->state != STATE_POSTDATA ) && \
750  !( envelopeInfoPtr->state == STATE_PREDATA && \
751  envelopeInfoPtr->usage == ACTION_SIGN && \
752  envelopeInfoPtr->type == CRYPT_FORMAT_CMS && \
753  ( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY ) ) )
754  return( CRYPT_ERROR_INCOMPLETE );
755  }
756  else
757  {
758  if( envelopeInfoPtr->state == STATE_FINISHED )
759  return( CRYPT_ERROR_COMPLETE );
760  }
761  if( envelopeInfoPtr->errorState != CRYPT_OK )
762  return( envelopeInfoPtr->errorState );
763  if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
764  ( envelopeInfoPtr->dataFlags & ENVDATA_NOSEGMENT ) && \
765  envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
766  {
767  /* If we're enveloping using a non-segmenting encoding of the
768  payload then the caller has to explicitly set the payload
769  size before they can add any data */
770  setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_DATASIZE,
772  return( CRYPT_ERROR_NOTINITED );
773  }
774 
775  /* Send the data to the envelope */
776  if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
777  status = deenvelopePush( envelopeInfoPtr, msgData->data,
778  length, &bytesCopied );
779  else
780  status = envelopePush( envelopeInfoPtr, msgData->data,
781  length, &bytesCopied );
782  if( cryptStatusOK( status ) )
783  msgData->length = bytesCopied;
784  else
785  {
786  /* In some cases data can be copied even if an error status is
787  returned. The most usual case is when the error is
788  recoverable (underflow or overflow), however when we're de-
789  enveloping we can also copy data but then stall with a
790  CRYPT_ENVELOPE_RESOURCE notification */
791  if( ( isRecoverableError( status ) && bytesCopied > 0 ) || \
792  ( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
793  status == CRYPT_ENVELOPE_RESOURCE && bytesCopied > 0 ) )
794  msgData->length = bytesCopied;
795  }
796  return( status );
797  }
798  if( message == MESSAGE_ENV_POPDATA )
799  {
800  MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
801  const int length = msgData->length;
802  int bytesCopied, status;
803 
804  assert( isWritePtr( msgData->data, msgData->length ) );
805 
806  REQUIRES( msgData->length > 0 && msgData->length < MAX_INTLENGTH );
807 
808  /* Unless we're told otherwise, we've copied zero bytes */
809  msgData->length = 0;
810 
811  /* Make sure that everything is in order */
812  if( envelopeInfoPtr->errorState != CRYPT_OK )
813  return( envelopeInfoPtr->errorState );
814 
815  /* Get the data from the envelope */
816  if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
817  status = deenvelopePop( envelopeInfoPtr, msgData->data,
818  length, &bytesCopied );
819  else
820  status = envelopePop( envelopeInfoPtr, msgData->data,
821  length, &bytesCopied );
822  if( cryptStatusOK( status ) )
823  msgData->length = bytesCopied;
824  return( status );
825  }
826 
827  retIntError();
828  }
829 
830 /* Create an envelope. This is a low-level function encapsulated by
831  createEnvelope() and used to manage error exits */
832 
833 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
834 static int initEnvelope( OUT_HANDLE_OPT CRYPT_ENVELOPE *iCryptEnvelope,
836  IN_ENUM( CRYPT_FORMAT ) \
838  OUT_OPT_PTR ENVELOPE_INFO **envelopeInfoPtrPtr )
839  {
840  ENVELOPE_INFO *envelopeInfoPtr;
841  const BOOLEAN isDeenvelope = ( formatType == CRYPT_FORMAT_AUTO ) ? \
842  TRUE : FALSE;
843  const int subType = \
844  isDeenvelope ? SUBTYPE_ENV_DEENV : \
845  ( formatType == CRYPT_FORMAT_PGP ) ? \
847  const int storageSize = 3 * sizeof( CONTENT_LIST );
848  int status;
849 
850  assert( isWritePtr( iCryptEnvelope, sizeof( CRYPT_ENVELOPE * ) ) );
851  assert( isWritePtr( envelopeInfoPtrPtr, sizeof( ENVELOPE_INFO * ) ) );
852 
853  REQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
854  isHandleRangeValid( iCryptOwner ) );
855  REQUIRES( formatType > CRYPT_FORMAT_NONE && \
856  formatType < CRYPT_FORMAT_LAST_EXTERNAL );
857 
858  /* Clear return values */
859  *iCryptEnvelope = CRYPT_ERROR;
860  *envelopeInfoPtrPtr = NULL;
861 
862  /* If PGP support is disabled we can't specify PGP as a target format */
863 #ifndef USE_PGP
864  if( formatType == CRYPT_FORMAT_PGP )
865  return( CRYPT_ARGERROR_NUM1 );
866 #endif /* USE_PGP */
867 
868  /* Create the envelope object */
869  status = krnlCreateObject( iCryptEnvelope, ( void ** ) &envelopeInfoPtr,
870  sizeof( ENVELOPE_INFO ) + storageSize,
871  OBJECT_TYPE_ENVELOPE, subType,
872  CREATEOBJECT_FLAG_NONE, iCryptOwner,
873  ACTION_PERM_NONE_ALL, envelopeMessageFunction );
874  if( cryptStatusError( status ) )
875  return( status );
876  ANALYSER_HINT( envelopeInfoPtr != NULL );
877  *envelopeInfoPtrPtr = envelopeInfoPtr;
878  envelopeInfoPtr->objectHandle = *iCryptEnvelope;
879  envelopeInfoPtr->ownerHandle = iCryptOwner;
880  envelopeInfoPtr->bufSize = DEFAULT_BUFFER_SIZE;
881  if( isDeenvelope )
882  envelopeInfoPtr->flags = ENVELOPE_ISDEENVELOPE;
883  envelopeInfoPtr->type = formatType;
884  envelopeInfoPtr->state = STATE_PREDATA;
885  envelopeInfoPtr->storageSize = storageSize;
886  status = initMemPool( envelopeInfoPtr->memPoolState,
887  envelopeInfoPtr->storage, storageSize );
888  if( cryptStatusError( status ) )
889  return( status );
890 
891  /* Set up any internal objects to contain invalid handles */
892  envelopeInfoPtr->iCryptContext = \
893  envelopeInfoPtr->iExtraCertChain = CRYPT_ERROR;
894  envelopeInfoPtr->iSigCheckKeyset = envelopeInfoPtr->iEncryptionKeyset = \
895  envelopeInfoPtr->iDecryptionKeyset = CRYPT_ERROR;
896  envelopeInfoPtr->payloadSize = CRYPT_UNUSED;
897 
898  /* Set up the enveloping methods */
899  if( isDeenvelope )
900  {
901  /* For de-enveloping we default to PKCS #7/CMS/SMIME, if the data
902  is in some other format we'll adjust the function pointers once
903  the user pushes in the first data quantity */
904  initCMSDeenveloping( envelopeInfoPtr );
905  initDeenvelopeStreaming( envelopeInfoPtr );
906  initDenvResourceHandling( envelopeInfoPtr );
907  }
908  else
909  {
910  if( formatType == CRYPT_FORMAT_PGP )
911  initPGPEnveloping( envelopeInfoPtr );
912  else
913  initCMSEnveloping( envelopeInfoPtr );
914  initEnvelopeStreaming( envelopeInfoPtr );
915  initEnvResourceHandling( envelopeInfoPtr );
916  }
917 
918  return( CRYPT_OK );
919  }
920 
922 int createEnvelope( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
923  STDC_UNUSED const void *auxDataPtr,
924  STDC_UNUSED const int auxValue )
925  {
926  CRYPT_ENVELOPE iCryptEnvelope;
927  ENVELOPE_INFO *envelopeInfoPtr = NULL;
928  int initStatus, status;
929 
930  assert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );
931 
932  REQUIRES( auxDataPtr == NULL && auxValue == 0 );
933  REQUIRES( createInfo->arg1 > CRYPT_FORMAT_NONE && \
934  createInfo->arg1 < CRYPT_FORMAT_LAST_EXTERNAL );
935 
936  /* Pass the call on to the lower-level open function */
937  initStatus = initEnvelope( &iCryptEnvelope, createInfo->cryptOwner,
938  createInfo->arg1, &envelopeInfoPtr );
939  if( cryptStatusError( initStatus ) )
940  {
941  /* If the create object failed, return immediately */
942  if( envelopeInfoPtr == NULL )
943  return( initStatus );
944 
945  /* The init failed, make sure that the object gets destroyed when we
946  notify the kernel that the setup process is complete */
947  krnlSendNotifier( iCryptEnvelope, IMESSAGE_DESTROY );
948  }
949 
950  /* We've finished setting up the object-type-specific info, tell the
951  kernel that the object is ready for use */
952  status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
953  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
954  if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
955  return( cryptStatusError( initStatus ) ? initStatus : status );
956  createInfo->cryptHandle = iCryptEnvelope;
957 
958  return( CRYPT_OK );
959  }
960 #endif /* USE_ENVELOPES */