cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
encode.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Datagram Encoding Routines *
4 * Copyright Peter Gutmann 1996-2009 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "asn1.h"
10  #include "envelope.h"
11 #else
12  #include "enc_dec/asn1.h"
13  #include "envelope/envelope.h"
14 #endif /* Compiler-specific includes */
15 
16 /* .... NO! ... ... MNO! ...
17  ..... MNO!! ...................... MNNOO! ...
18  ..... MMNO! ......................... MNNOO!! .
19  .... MNOONNOO! MMMMMMMMMMPPPOII! MNNO!!!! .
20  ... !O! NNO! MMMMMMMMMMMMMPPPOOOII!! NO! ....
21  ...... ! MMMMMMMMMMMMMPPPPOOOOIII! ! ...
22  ........ MMMMMMMMMMMMPPPPPOOOOOOII!! .....
23  ........ MMMMMOOOOOOPPPPPPPPOOOOMII! ...
24  ....... MMMMM.. OPPMMP .,OMI! ....
25  ...... MMMM:: o.,OPMP,.o ::I!! ...
26  .... NNM:::.,,OOPM!P,.::::!! ....
27  .. MMNNNNNOOOOPMO!!IIPPO!!O! .....
28  ... MMMMMNNNNOO:!!:!!IPPPPOO! ....
29  .. MMMMMNNOOMMNNIIIPPPOO!! ......
30  ...... MMMONNMMNNNIIIOO!..........
31  ....... MN MOMMMNNNIIIIIO! OO ..........
32  ......... MNO! IiiiiiiiiiiiI OOOO ...........
33  ...... NNN.MNO! . O!!!!!!!!!O . OONO NO! ........
34  .... MNNNNNO! ...OOOOOOOOOOO . MMNNON!........
35  ...... MNNNNO! .. PPPPPPPPP .. MMNON!........
36  ...... OO! ................. ON! .......
37  ................................
38 
39  Be very careful when modifying this code, the data manipulation that it
40  performs is somewhat tricky */
41 
42 #ifdef USE_ENVELOPES
43 
44 /****************************************************************************
45 * *
46 * Utility Routines *
47 * *
48 ****************************************************************************/
49 
50 /* Sanity-check the envelope state */
51 
53 static BOOLEAN sanityCheck( const ENVELOPE_INFO *envelopeInfoPtr )
54  {
55  assert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
56 
57  /* Make sure that the buffer position is within bounds */
58  if( envelopeInfoPtr->buffer == NULL || \
59  envelopeInfoPtr->bufPos < 0 || \
60  envelopeInfoPtr->bufPos > envelopeInfoPtr->bufSize || \
61  envelopeInfoPtr->bufSize < MIN_BUFFER_SIZE || \
62  envelopeInfoPtr->bufSize >= MAX_INTLENGTH )
63  return( FALSE );
64 
65  /* Make sure that the block buffer position is within bounds */
66  if( envelopeInfoPtr->blockSize > 0 && \
67  ( envelopeInfoPtr->blockBufferPos < 0 || \
68  envelopeInfoPtr->blockBufferPos >= envelopeInfoPtr->blockSize || \
69  envelopeInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) )
70  return( FALSE );
71 
72  /* If we're drained the envelope buffer, we're done */
73  if( envelopeInfoPtr->segmentStart == 0 && \
74  envelopeInfoPtr->segmentDataStart == 0 && \
75  envelopeInfoPtr->bufPos == 0 )
76  return( TRUE );
77 
78  /* Make sure that the buffer internal bookeeping is OK. First we apply
79  the general one-size-fits-all checks, then we apply further
80  situation-specific checks */
81  if( envelopeInfoPtr->segmentStart < 0 || \
82  envelopeInfoPtr->segmentStart > envelopeInfoPtr->segmentDataStart || \
83  envelopeInfoPtr->segmentStart > MAX_INTLENGTH )
84  return( FALSE );
85  if( envelopeInfoPtr->segmentDataStart < 0 || \
86  envelopeInfoPtr->segmentDataStart > envelopeInfoPtr->bufPos || \
87  envelopeInfoPtr->segmentDataStart > MAX_INTLENGTH )
88  return( FALSE );
89 
90  /* The sitaution-specific checks get a bit complicated because we have
91  to distinguish between definite- and indefinite-length encodings.
92  For the definite length segmentStart == segmentDataStart since there
93  are no intermediate segment headers, for the indefinite length
94  segmentStart < segmentDataStart to accomodate the intervening header.
95 
96  In some rare cases segmentDataStart can be the same as bufPos if
97  we're using compression and all input data was absorbed by the
98  zStream buffer so we check for segmentDataStart > bufPos rather than
99  segmentDataStart >= bufPos */
100  if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
101  {
102  /* It's a non-segmenting encoding so segmentStart must track
103  segmentDataStart */
104  if( envelopeInfoPtr->segmentStart != \
105  envelopeInfoPtr->segmentDataStart )
106  return( FALSE );
107 
108  return( TRUE );
109  }
110  if( envelopeInfoPtr->segmentStart >= envelopeInfoPtr->bufPos )
111  return( FALSE );
112  if( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE )
113  {
114  /* If we're just started a new segment and there's no data left in
115  the envelope buffer, segmentStart may be the same as
116  segmentDataStart */
117  if( envelopeInfoPtr->segmentStart == 0 && \
118  envelopeInfoPtr->segmentDataStart == 0 )
119  return( TRUE );
120  }
121  if( envelopeInfoPtr->segmentStart >= envelopeInfoPtr->segmentDataStart )
122  return( FALSE );
123 
124  return( TRUE );
125  }
126 
127 /* Apply the hash/MAC actions in the action list to data. This function is
128  shared with decode.c */
129 
130 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
131 int hashEnvelopeData( const ACTION_LIST *actionListPtr,
132  IN_BUFFER( dataLength ) const void *data,
133  IN_LENGTH const int dataLength )
134  {
135  int iterationCount, status;
136 
137  assert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );
138  assert( dataLength == 0 || isReadPtr( data, dataLength ) );
139 
140  REQUIRES( data != NULL );
141  REQUIRES( dataLength >= 0 && dataLength < MAX_INTLENGTH );
142 
143  for( iterationCount = 0;
144  actionListPtr != NULL && \
145  iterationCount < FAILSAFE_ITERATIONS_MED;
146  actionListPtr = actionListPtr->next, iterationCount++ )
147  {
148  /* If we're using authenticated encryption there may be other
149  actions present in the action list so we only hash/MAC where
150  required */
151  if( actionListPtr->action != ACTION_HASH && \
152  actionListPtr->action != ACTION_MAC )
153  continue;
154 
155  status = krnlSendMessage( actionListPtr->iCryptHandle,
156  IMESSAGE_CTX_HASH, ( MESSAGE_CAST ) data,
157  dataLength );
158  if( cryptStatusError( status ) )
159  return( status );
160  }
161  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
162 
163  return( CRYPT_OK );
164  }
165 
166 /****************************************************************************
167 * *
168 * Header Processing Routines *
169 * *
170 ****************************************************************************/
171 
172 /* Determine the length of the encoded length value and the threshold at which the
173  length encoding changes for constructed indefinite-length strings. The
174  length encoding is the actual length if <= 127, or a one-byte length-of-
175  length followed by the length if > 127 */
176 
177 #define TAG_SIZE 1 /* Useful symbolic define */
178 
179 #if INT_MAX > 32767
180 
181 #define lengthOfLength( length ) ( ( length < 0x80 ) ? 1 : \
182  ( length < 0x100 ) ? 2 : \
183  ( length < 0x10000 ) ? 3 : \
184  ( length < 0x1000000 ) ? 4 : 5 )
185 
186 #define findThreshold( length ) ( ( length < 0x80 ) ? 0x7F : \
187  ( length < 0x100 ) ? 0xFF : \
188  ( length < 0x10000 ) ? 0xFFFF : \
189  ( length < 0x1000000 ) ? 0xFFFFFF : INT_MAX )
190 #else
191 
192 #define lengthOfLength( length ) ( ( length < 0x80 ) ? 1 : \
193  ( length < 0x100 ) ? 2 : 3 )
194 
195 #define findThreshold( length ) ( ( length < 0x80 ) ? 127 : \
196  ( length < 0x100 ) ? 0xFF : INT_MAX )
197 #endif /* 32-bit ints */
198 
199 /* Begin a new segment in the buffer. The layout is:
200 
201  bufPos
202  v
203  tag len payload
204  +-------+-+---+---------------------+-------+
205  | | | | | |
206  +-------+-+---+---------------------+-------+
207  ^ ^ ^
208  | | |
209  sStart sDataStart sDataEnd
210 
211  If we're using a definite-length encoding then
212  segmentStart == segmentDataStart = bufPos */
213 
215 static int beginSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr )
216  {
217  int segHeaderSize = 0;
218 
219  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
220 
221  REQUIRES( sanityCheck( envelopeInfoPtr ) );
222 
223  /* If we're using an indefinite-length encoding we have to factor in the
224  length of the segment header. Since we can't determine the overall
225  segment data size at this point we use a worst-case estimate in which
226  the segment fills the entire buffer */
227  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
228  {
229  segHeaderSize = TAG_SIZE + \
230  lengthOfLength( envelopeInfoPtr->bufSize );
231  }
232 
233  /* Make sure that there's enough room in the buffer to accommodate the
234  start of a new segment. In the worst case this is 6 bytes (OCTET
235  STRING tag + 5-byte length) + 15 bytes (blockBuffer contents for a
236  128-bit block cipher). Although in practice we could eliminate this
237  condition, it would require tracking a lot of state information to
238  record which data had been encoded into the buffer and whether the
239  blockBuffer data had been copied into the buffer, so to keep it
240  simple we require enough room to do everything at once */
241  if( envelopeInfoPtr->bufPos + segHeaderSize + \
242  envelopeInfoPtr->blockBufferPos >= envelopeInfoPtr->bufSize )
243  return( CRYPT_ERROR_OVERFLOW );
244 
245  /* Adjust the buffer position indicators to handle potential
246  intermediate headers */
247  envelopeInfoPtr->segmentStart = envelopeInfoPtr->bufPos;
248  if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
249  {
250  /* Begin a new segment after the end of the current segment. We
251  always leave enough room for the largest allowable length field
252  because we may have a short segment at the end of the buffer which
253  is moved to the start of the buffer after data is copied out,
254  turning it into a longer segment. For this reason we rely on
255  completeSegment() to get the length right and move any data down
256  as required */
257  envelopeInfoPtr->bufPos += segHeaderSize;
258  }
259  envelopeInfoPtr->segmentDataStart = envelopeInfoPtr->bufPos;
260  ENSURES( envelopeInfoPtr->bufPos + \
261  envelopeInfoPtr->blockBufferPos <= envelopeInfoPtr->bufSize );
262 
263  /* Now copy anything left in the block buffer to the start of the new
264  segment. We know that everything will fit because we've checked
265  earlier on that the header and blockbuffer contents will fit into
266  the remaining space */
267  if( envelopeInfoPtr->blockBufferPos > 0 )
268  {
269  REQUIRES( rangeCheckZ( envelopeInfoPtr->bufPos,
270  envelopeInfoPtr->blockBufferPos,
271  envelopeInfoPtr->bufSize ) );
272  memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
273  envelopeInfoPtr->blockBuffer, envelopeInfoPtr->blockBufferPos );
274  envelopeInfoPtr->bufPos += envelopeInfoPtr->blockBufferPos;
275  }
276  envelopeInfoPtr->blockBufferPos = 0;
277 
278  /* We've started the new segment, mark it as incomplete */
279  envelopeInfoPtr->dataFlags &= ~ENVDATA_SEGMENTCOMPLETE;
280 
281  ENSURES( sanityCheck( envelopeInfoPtr ) );
282  return( CRYPT_OK );
283  }
284 
285 /* Complete a segment of data in the buffer. This is incredibly complicated
286  because we need to take into account the indefinite-length encoding (which
287  has a variable-size length field) and the quantization to the cipher block
288  size. In particular the indefinite-length encoding means that we can
289  never encode a block with a size of 130 bytes (we get tag + length + 127 =
290  129, then tag + length-of-length + length + 128 = 131), and the same for
291  the next boundary at 256 bytes */
292 
294 static int encodeSegmentHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr )
295  {
296  STREAM stream;
297  const BOOLEAN isEncrypted = \
298  ( envelopeInfoPtr->iCryptContext != CRYPT_ERROR ) ? TRUE : FALSE;
299  const int oldHdrLen = envelopeInfoPtr->segmentDataStart - \
300  envelopeInfoPtr->segmentStart;
301  BOOLEAN needsPadding = \
302  ( envelopeInfoPtr->dataFlags & ENVDATA_NEEDSPADDING ) ? TRUE : FALSE;
303  int dataLen = envelopeInfoPtr->bufPos - envelopeInfoPtr->segmentDataStart;
304  int hdrLen, remainder = 0, status;
305 
306  REQUIRES( sanityCheck( envelopeInfoPtr ) );
307 
308  /* If we're adding PKCS #5 padding try and add one block's worth of
309  pseudo-data. This adjusted data length is then fed into the block
310  size quantisation process, after which any odd-sized remainder is
311  ignored, and the necessary padding bytes are added to account for the
312  difference between the actual and padded size */
313  if( needsPadding )
314  {
315  /* Check whether the padding will fit onto the end of the data. This
316  check isn't completely accurate since the length encoding might
317  shrink by one or two bytes and allow a little extra data to be
318  squeezed in, however the extra data could cause the length
319  encoding to expand again, requiring a complex adjustment process.
320  To make things easier we ignore this possibility at the expense of
321  emitting one more segment than is necessary in a few very rare
322  cases */
323  if( envelopeInfoPtr->segmentDataStart + dataLen + \
324  envelopeInfoPtr->blockSize < envelopeInfoPtr->bufSize )
325  dataLen += envelopeInfoPtr->blockSize;
326  else
327  needsPadding = FALSE;
328  }
329  ENSURES( dataLen > 0 && envelopeInfoPtr->segmentDataStart + \
330  dataLen <= envelopeInfoPtr->bufSize );
331 
332  /* Now that we've made any necessary adjustments to the data length,
333  determine the length of the length encoding (which may have grown or
334  shrunk since we initially calculated it when we began the segment) */
335  hdrLen = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \
336  TAG_SIZE + lengthOfLength( dataLen ) : 0;
337 
338  /* Quantize and adjust the length if we're encrypting in a block mode:
339 
340  segDataStart bufPos
341  segStart | |
342  v v<--------- dLen ---------->v
343  ----+-------+---------------------------+
344  | hdr |///////////////////////| |
345  ----+-------+---------------------------+
346  |<------ qTotLen ------>|<+>|
347  |
348  remainder */
349  if( isEncrypted )
350  {
351  int quantisedTotalLen, threshold;
352 
353  /* Determine the length due to cipher block-size quantisation */
354  quantisedTotalLen = dataLen & envelopeInfoPtr->blockSizeMask;
355 
356  /* If the block-size quantisation has moved the quantised length
357  across a length-of-length encoding boundary, adjust hdrLen to
358  account for this */
359  threshold = findThreshold( quantisedTotalLen );
360  if( quantisedTotalLen <= threshold && dataLen > threshold )
361  hdrLen--;
362 
363  /* Remember how many bytes we can't fit into the current block
364  (these will be copied into the block buffer for later use), and
365  the new size of the data due to quantisation */
366  remainder = dataLen - quantisedTotalLen;
367  dataLen = quantisedTotalLen;
368  }
369  ENSURES( ( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && hdrLen == 0 ) || \
370  ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \
371  hdrLen > 0 && hdrLen <= TAG_SIZE + 5 ) );
372  ENSURES( ( envelopeInfoPtr->blockSize == 0 && remainder == 0 ) || \
373  ( envelopeInfoPtr->blockSize > 0 && \
374  remainder >= 0 && remainder < envelopeInfoPtr->blockSize && \
375  remainder <= CRYPT_MAX_IVSIZE ) );
376 
377  /* If there's not enough data present to do anything, tell the caller */
378  if( dataLen <= 0 )
379  return( CRYPT_ERROR_UNDERFLOW );
380  ENSURES( dataLen > 0 && dataLen < MAX_INTLENGTH );
381 
382  /* If there's a header between segments and the header length encoding
383  has shrunk (either due to the cipher block size quantization
384  shrinking the segment or because we've wrapped up a segment at less
385  than the original projected length), move the data down. In the
386  worst case the shrinking can cover several bytes if we go from a
387  > 255 byte segment to a <= 127 byte one:
388 
389  segDataStart bufPos
390  segStart | |
391  v v v
392  ----+-------+---------------------------+
393  | hdr |///////////////////////////| Before
394  ----+-------+---------------------------+
395  |<--+-->|
396  |
397  oldHdrLen
398 
399  segDataStart' bufPos'
400  segStart| |
401  v v v
402  ----+-------+-----------------------+---+
403  |hdr|///////////////////////////| | After
404  ----+-------+-----------------------+---+
405  |<+>|<+>| |<+>|
406  | | |
407  | delta delta
408  hdrLen */
409  if( hdrLen > 0 && hdrLen < oldHdrLen )
410  {
411  BYTE *segmentDataPtr = envelopeInfoPtr->buffer + \
412  envelopeInfoPtr->segmentStart;
413  const int delta = oldHdrLen - hdrLen;
414 
415  memmove( segmentDataPtr + hdrLen, segmentDataPtr + oldHdrLen,
416  envelopeInfoPtr->bufPos - envelopeInfoPtr->segmentDataStart );
417  envelopeInfoPtr->bufPos -= delta;
418  envelopeInfoPtr->segmentDataStart -= delta;
419  }
420  ENSURES( sanityCheck( envelopeInfoPtr ) );
421  ENSURES( envelopeInfoPtr->segmentDataStart + \
422  dataLen <= envelopeInfoPtr->bufSize );
423 
424  /* If we need to add PKCS #5 block padding, do so now (we know from the
425  needsPadding and quantisedTotalLen check above that there's enough
426  room for this). Since the extension of the data length to allow for
427  padding data is performed by adding one block of pseudo-data and
428  letting the block quantisation system take care of any discrepancies
429  we can calculate the padding amount as the difference between any
430  remainder after quantisation and the block size */
431  if( needsPadding )
432  {
433  const int padSize = envelopeInfoPtr->blockSize - remainder;
434  int i;
435 
436  ENSURES( padSize > 0 && padSize <= envelopeInfoPtr->blockSize && \
437  envelopeInfoPtr->bufPos + \
438  padSize <= envelopeInfoPtr->bufSize );
439 
440  /* Add the block padding and set the remainder to zero, since we're
441  now at an even block boundary */
442  for( i = 0; i < padSize; i++ )
443  {
444  envelopeInfoPtr->buffer[ envelopeInfoPtr->bufPos + i ] = \
445  intToByte( padSize );
446  }
447  envelopeInfoPtr->bufPos += padSize;
448  envelopeInfoPtr->dataFlags &= ~ENVDATA_NEEDSPADDING;
449  ENSURES( envelopeInfoPtr->bufPos >= 0 && \
450  envelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );
451  }
452  else
453  {
454  /* If there are any bytes left over move them across into the block
455  buffer */
456  if( remainder > 0 )
457  {
458  REQUIRES( envelopeInfoPtr->bufPos > remainder );
459  memcpy( envelopeInfoPtr->blockBuffer,
460  envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos - \
461  remainder, remainder );
462  envelopeInfoPtr->blockBufferPos = remainder;
463  envelopeInfoPtr->bufPos -= remainder;
464  }
465  }
466 
467  ENSURES( sanityCheck( envelopeInfoPtr ) );
468 
469  /* If we're using the definite length form, exit */
470  if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
471  return( CRYPT_OK );
472 
473  /* Insert the OCTET STRING header into the data stream */
474  sMemOpen( &stream, envelopeInfoPtr->buffer + \
475  envelopeInfoPtr->segmentStart, hdrLen );
476  status = writeOctetStringHole( &stream, dataLen, DEFAULT_TAG );
477  ENSURES( cryptStatusOK( status ) && stell( &stream ) == hdrLen );
478  sMemDisconnect( &stream );
479 
480  return( CRYPT_OK );
481  }
482 
484 static int completeSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr,
485  const BOOLEAN forceCompletion )
486  {
487  int status;
488 
489  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
490 
491  REQUIRES( sanityCheck( envelopeInfoPtr ) );
492 
493  /* If we're enveloping data using indefinite encoding and we're not at
494  the end of the data, don't emit a sub-segment containing less then 10
495  bytes of data. This is to protect against users who write code that
496  performs byte-at-a-time enveloping, at least we can quantize the data
497  amount to make it slightly more efficient. As a side-effect it
498  avoids occasional inefficiencies at boundaries where one or two bytes
499  may still be hanging around from a previous data block since they'll
500  be coalesced into the following block */
501  if( !forceCompletion && \
502  envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \
503  ( envelopeInfoPtr->bufPos - envelopeInfoPtr->segmentDataStart ) < 10 )
504  {
505  /* We can't emit any of the small sub-segment, however there may be
506  (non-)data preceding this that we can hand over so we set the
507  segment data end value to the start of the segment */
508  envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->segmentStart;
509  return( CRYPT_OK );
510  }
511 
512  /* Wrap up the segment */
513  if( !( envelopeInfoPtr->dataFlags & ENVDATA_NOSEGMENT ) )
514  {
515  status = encodeSegmentHeader( envelopeInfoPtr );
516  if( cryptStatusError( status ) )
517  return( status );
518  }
519  if( envelopeInfoPtr->iCryptContext != CRYPT_ERROR )
520  {
521  void *dataPtr = envelopeInfoPtr->buffer + \
522  envelopeInfoPtr->segmentDataStart;
523  const int dataLen = envelopeInfoPtr->bufPos - \
524  envelopeInfoPtr->segmentDataStart;
525 
526  status = krnlSendMessage( envelopeInfoPtr->iCryptContext,
527  IMESSAGE_CTX_ENCRYPT, dataPtr, dataLen );
528  if( cryptStatusError( status ) )
529  return( status );
530  if( envelopeInfoPtr->dataFlags & ENVDATA_AUTHENCACTIONSACTIVE )
531  {
532  /* We're performing authenticated encryotion, hash the
533  ciphertext now that it's available */
534  status = hashEnvelopeData( envelopeInfoPtr->actionList, dataPtr,
535  dataLen );
536  if( cryptStatusError( status ) )
537  return( status );
538  }
539  }
540 
541  /* Remember how much data is now available to be read out */
542  envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;
543 
544  /* Mark this segment as complete */
545  envelopeInfoPtr->dataFlags |= ENVDATA_SEGMENTCOMPLETE;
546 
547  return( CRYPT_OK );
548  }
549 
550 /****************************************************************************
551 * *
552 * Copy to Envelope *
553 * *
554 ****************************************************************************/
555 
556 /* Flush any remaining data through into the envelope buffer */
557 
559 static int flushEnvelopeData( INOUT ENVELOPE_INFO *envelopeInfoPtr )
560  {
561  BOOLEAN needNewSegment = \
562  ( envelopeInfoPtr->dataFlags & ENVDATA_NEEDSPADDING ) ? \
563  TRUE : FALSE;
564  int status;
565 
566  REQUIRES( sanityCheck( envelopeInfoPtr ) );
567 
568  /* If we're using an explicit payload length make sure that we copied in
569  as much data as was explicitly declared */
570  if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
571  envelopeInfoPtr->segmentSize != 0 )
572  return( CRYPT_ERROR_UNDERFLOW );
573 
574 #ifdef USE_COMPRESSION
575  /* If we're using compression, flush any remaining data out of the
576  zStream */
577  if( envelopeInfoPtr->flags & ENVELOPE_ZSTREAMINITED )
578  {
579  int bytesToCopy;
580 
581  /* If we've just completed a segment, begin a new one. This action
582  is slightly anomalous in that normally a flush can't add more
583  data to the envelope and so we'd never need to start a new
584  segment during a flush, however since we can have arbitrarily
585  large amounts of data trapped in subspace via zlib we need to be
586  able to handle starting new segments at this point */
587  if( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE )
588  {
589  status = beginSegment( envelopeInfoPtr );
590  if( cryptStatusError( status ) )
591  return( status );
592  if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
593  return( CRYPT_ERROR_OVERFLOW );
594  }
595 
596  /* Flush any remaining compressed data into the envelope buffer */
597  bytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;
598  envelopeInfoPtr->zStream.next_in = NULL;
599  envelopeInfoPtr->zStream.avail_in = 0;
600  envelopeInfoPtr->zStream.next_out = envelopeInfoPtr->buffer + \
601  envelopeInfoPtr->bufPos;
602  envelopeInfoPtr->zStream.avail_out = bytesToCopy;
603  status = deflate( &envelopeInfoPtr->zStream, Z_FINISH );
604  if( status != Z_STREAM_END && status != Z_OK )
605  {
606  /* There was some problem other than the output buffer being
607  full */
608  retIntError();
609  }
610 
611  /* Adjust the status information based on the data flushed out of
612  the zStream. We don't have to check for the output buffer being
613  full because this case is already handled by the check of the
614  deflate() return value */
615  envelopeInfoPtr->bufPos += bytesToCopy - \
616  envelopeInfoPtr->zStream.avail_out;
617  ENSURES( envelopeInfoPtr->bufPos >= 0 && \
618  envelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );
619 
620  /* If we didn't finish flushing data because the output buffer is
621  full, complete the segment and tell the caller that they need to
622  pop some data */
623  if( status == Z_OK )
624  {
625  status = completeSegment( envelopeInfoPtr, TRUE );
626  return( cryptStatusError( status ) ? \
627  status : CRYPT_ERROR_OVERFLOW );
628  }
629  }
630 #endif /* USE_COMPRESSION */
631 
632  /* If we're encrypting data with a block cipher we need to add PKCS #5
633  padding at the end of the last block */
634  if( envelopeInfoPtr->blockSize > 1 )
635  {
636  envelopeInfoPtr->dataFlags |= ENVDATA_NEEDSPADDING;
637  if( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE )
638  {
639  /* The current segment has been wrapped up, we need to begin a
640  new segment to contain the padding */
641  needNewSegment = TRUE;
642  }
643  }
644 
645  /* If we're carrying over the padding requirement from a previous block
646  we need to begin a new block before we can try and add the padding.
647  This can happen if there was data left after the previous segment was
648  completed or if the addition of padding would have overflowed the
649  buffer when the segment was completed, in other words if the
650  needPadding flag is still set from the previous call */
651  if( needNewSegment )
652  {
653  status = beginSegment( envelopeInfoPtr );
654  if( cryptStatusError( status ) )
655  return( status );
656  if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
657  {
658  /* We've filled the envelope buffer with the new segment header,
659  we can't copy in anything */
660  return( CRYPT_ERROR_OVERFLOW );
661  }
662  }
663 
664  /* Complete the segment if necessary */
665  if( !( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE ) || \
666  ( envelopeInfoPtr->dataFlags & ENVDATA_NEEDSPADDING ) )
667  {
668  status = completeSegment( envelopeInfoPtr, TRUE );
669  if( cryptStatusError( status ) )
670  return( status );
671 
672  /* If there wasn't sufficient room to add the trailing PKCS #5
673  padding tell the caller to try again */
674  if( envelopeInfoPtr->dataFlags & ENVDATA_NEEDSPADDING )
675  return( CRYPT_ERROR_OVERFLOW );
676  }
677 
678  /* If there's no hashing being performed or we've completed the hashing,
679  we're done. In addition unlike CMS, PGP handles authenticated
680  attributes by extending the hashing of the payload data to cover the
681  additional attributes, so if we're using the PGP format we can't wrap
682  up the hashing yet */
683  if( !( envelopeInfoPtr->dataFlags & ( ENVDATA_HASHACTIONSACTIVE | \
685  envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
686  return( CRYPT_OK );
687 
688  /* We've finished processing everything, complete each hash action */
689  return( hashEnvelopeData( envelopeInfoPtr->actionList, "", 0 ) );
690  }
691 
692 /* Copy data into the envelope. Returns the number of bytes copied or an
693  overflow error if we're trying to flush data and there isn't room to
694  perform the flush (this somewhat peculiar case is because the caller
695  expects to have 0 bytes copied in this case) */
696 
698 static int copyToEnvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr,
699  IN_BUFFER_OPT( length ) const BYTE *buffer,
700  IN_LENGTH_Z const int length )
701  {
702  BOOLEAN needCompleteSegment = FALSE;
703  BYTE *bufPtr;
704  int bytesToCopy, status;
705 
706  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
707  assert( length == 0 || isReadPtr( buffer, length ) );
708 
709  REQUIRES( sanityCheck( envelopeInfoPtr ) );
710  REQUIRES( ( buffer == NULL && length == 0 ) || \
711  ( buffer != NULL && length >= 0 && length < MAX_INTLENGTH ) );
712 
713  /* If we're trying to copy into a full buffer, return a count of 0 bytes
714  unless we're trying to flush the buffer (the calling routine may
715  convert the zero byte count to an overflow error if necessary) */
716  if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
717  return( ( length > 0 ) ? 0 : CRYPT_ERROR_OVERFLOW );
718 
719  /* If we're generating a detached signature just hash the data and exit */
720  if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
721  {
722  /* Unlike CMS, PGP handles authenticated attributes by extending the
723  hashing of the payload data to cover the additional attributes
724  so if this is a flush and we're using the PGP format we can't
725  wrap up the hashing yet */
726  if( length <= 0 && envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
727  return( 0 );
728 
729  status = hashEnvelopeData( envelopeInfoPtr->actionList,
730  ( length > 0 ) ? \
731  buffer : ( const void * ) "", length );
732  /* Cast needed for gcc */
733  return( cryptStatusError( status ) ? status : length );
734  }
735 
736  /* If we're flushing data, wrap up the segment and exit. An OK status
737  translates to zero bytes copied */
738  if( length <= 0 )
739  {
740  status = flushEnvelopeData( envelopeInfoPtr );
741  return( cryptStatusError( status ) ? status : 0 );
742  }
743 
744  /* If we're using an explicit payload length make sure that we don't try
745  and copy in more data than has been explicitly declared */
746  if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
747  length > envelopeInfoPtr->segmentSize )
748  return( CRYPT_ERROR_OVERFLOW );
749 
750  /* If we've just completed a segment, begin a new one before we add any
751  data */
752  if( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE )
753  {
754  status = beginSegment( envelopeInfoPtr );
755  if( cryptStatusError( status ) )
756  return( ( status == CRYPT_ERROR_OVERFLOW ) ? 0 : status );
757  if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
758  {
759  /* We've filled the envelope buffer with the new segment header,
760  we can't copy in anything */
761  return( 0 );
762  }
763  }
764 
765  /* Copy over as much as we can fit into the envelope buffer */
766  bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;
767  bytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;
768  ENSURES( bytesToCopy > 0 && \
769  envelopeInfoPtr->bufPos + \
770  bytesToCopy <= envelopeInfoPtr->bufSize );
771 #ifdef USE_COMPRESSION
772  if( envelopeInfoPtr->flags & ENVELOPE_ZSTREAMINITED )
773  {
774  /* Compress the data into the envelope buffer */
775  envelopeInfoPtr->zStream.next_in = ( BYTE * ) buffer;
776  envelopeInfoPtr->zStream.avail_in = length;
777  envelopeInfoPtr->zStream.next_out = bufPtr;
778  envelopeInfoPtr->zStream.avail_out = bytesToCopy;
779  status = deflate( &envelopeInfoPtr->zStream, Z_NO_FLUSH );
780  if( status != Z_OK )
781  {
782  /* There was some problem other than the output buffer being
783  full */
784  retIntError();
785  }
786 
787  /* Adjust the status information based on the data copied into the
788  zStream and flushed from the zStream into the buffer */
789  envelopeInfoPtr->bufPos += bytesToCopy - \
790  envelopeInfoPtr->zStream.avail_out;
791  bytesToCopy = length - envelopeInfoPtr->zStream.avail_in;
792 
793  /* If the buffer is full (there's no more room left for further
794  input) we need to close off the segment */
795  if( envelopeInfoPtr->zStream.avail_out <= 0 )
796  needCompleteSegment = TRUE;
797  }
798  else
799 #endif /* USE_COMPRESSION */
800  {
801  /* We're not using compression */
802  if( bytesToCopy > length )
803  bytesToCopy = length;
804  memcpy( bufPtr, buffer, bytesToCopy );
805  envelopeInfoPtr->bufPos += bytesToCopy;
806 
807  /* Hash the data if necessary */
808  if( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE )
809  {
810  status = hashEnvelopeData( envelopeInfoPtr->actionList, bufPtr,
811  bytesToCopy );
812  if( cryptStatusError( status ) )
813  return( status );
814  }
815 
816  /* If the buffer is full (i.e. we've been fed more input data than we
817  could copy into the buffer) we need to close off the segment */
818  if( bytesToCopy < length )
819  needCompleteSegment = TRUE;
820  }
821 
822  /* Adjust the bytes-left counter if necessary */
823  if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
824  envelopeInfoPtr->segmentSize -= bytesToCopy;
825 
826  ENSURES( sanityCheck( envelopeInfoPtr ) );
827 
828  /* Close off the segment if necessary */
829  if( needCompleteSegment )
830  {
831  status = completeSegment( envelopeInfoPtr, FALSE );
832  if( cryptStatusError( status ) )
833  return( status );
834  }
835 
836  return( bytesToCopy );
837  }
838 
839 /****************************************************************************
840 * *
841 * Copy from Envelope *
842 * *
843 ****************************************************************************/
844 
845 /* Copy data from the envelope and begin a new segment in the newly-created
846  room. If called with a zero length value this will create a new segment
847  without moving any data. Returns the number of bytes copied */
848 
849 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
850 static int copyFromEnvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr,
851  OUT_BUFFER( maxLength, *length ) BYTE *buffer,
852  IN_LENGTH const int maxLength,
853  OUT_LENGTH_Z int *length,
854  IN_FLAGS( ENVCOPY ) const int flags )
855  {
856  int bytesToCopy = maxLength, remainder;
857 
858  assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
859  assert( maxLength == 0 || isWritePtr( buffer, maxLength ) );
860 
861  REQUIRES( sanityCheck( envelopeInfoPtr ) );
862  REQUIRES( maxLength > 0 && maxLength < MAX_INTLENGTH );
863  REQUIRES( flags == ENVCOPY_FLAG_NONE );
864 
865  /* Clear return values */
866  memset( buffer, 0, min( 16, maxLength ) );
867  *length = 0;
868 
869  /* If the caller wants more data than there is available in the set of
870  completed segments try to wrap up the next segment to make more data
871  available */
872  if( bytesToCopy > envelopeInfoPtr->segmentDataEnd )
873  {
874  /* Try and complete the segment if necessary. This may not be
875  possible if we're using a block encryption mode and there isn't
876  enough room at the end of the buffer to encrypt a full block. In
877  addition if we're generating a detached signature the data is
878  communicated out-of-band so there's no segmenting */
879  if( !( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) && \
880  !( envelopeInfoPtr->dataFlags & ENVDATA_SEGMENTCOMPLETE ) )
881  {
882  const int status = completeSegment( envelopeInfoPtr, FALSE );
883  if( cryptStatusError( status ) )
884  return( status );
885  }
886 
887  /* Return all of the data that we've got */
888  if( envelopeInfoPtr->segmentDataEnd < bytesToCopy )
889  bytesToCopy = envelopeInfoPtr->segmentDataEnd;
890  }
891  remainder = envelopeInfoPtr->bufPos - bytesToCopy;
892  ENSURES( bytesToCopy >= 0 && bytesToCopy <= envelopeInfoPtr->bufPos );
893  ENSURES( remainder >= 0 && remainder <= envelopeInfoPtr->bufPos );
894 
895  /* Copy the data out and move any remaining data down to the start of the
896  buffer */
897  if( bytesToCopy > 0 )
898  {
899  memcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );
900 
901  /* Move any remaining data down in the buffer */
902  if( remainder > 0 )
903  {
904  REQUIRES( rangeCheck( bytesToCopy, remainder,
905  envelopeInfoPtr->bufPos ) );
906  memmove( envelopeInfoPtr->buffer,
907  envelopeInfoPtr->buffer + bytesToCopy, remainder );
908  }
909  envelopeInfoPtr->bufPos = remainder;
910 
911  /* Update the segment location information. The segment start
912  values track the start position of the last completed segment and
913  aren't updated until we begin a new segment so they may
914  temporarily go negative at this point when the data from the last
915  completed segment is moved past the start of the buffer. If this
916  happens we set them to a safe value of zero to ensure that they
917  pass the sanity checks elsewhere in the code */
918  envelopeInfoPtr->segmentStart -= bytesToCopy;
919  if( envelopeInfoPtr->segmentStart < 0 )
920  envelopeInfoPtr->segmentStart = 0;
921  envelopeInfoPtr->segmentDataStart -= bytesToCopy;
922  if( envelopeInfoPtr->segmentDataStart < 0 )
923  envelopeInfoPtr->segmentDataStart = 0;
924  envelopeInfoPtr->segmentDataEnd -= bytesToCopy;
925  ENSURES( envelopeInfoPtr->segmentDataEnd >= 0 && \
926  envelopeInfoPtr->segmentDataEnd < MAX_INTLENGTH );
927  }
928  *length = bytesToCopy;
929 
930  ENSURES( sanityCheck( envelopeInfoPtr ) );
931  return( CRYPT_OK );
932  }
933 
934 /****************************************************************************
935 * *
936 * Envelope Access Routines *
937 * *
938 ****************************************************************************/
939 
940 STDC_NONNULL_ARG( ( 1 ) ) \
941 void initEnvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr )
942  {
943  /* Set the access method pointers */
944  envelopeInfoPtr->copyToEnvelopeFunction = copyToEnvelope;
945  envelopeInfoPtr->copyFromEnvelopeFunction = copyFromEnvelope;
946  }
947 #endif /* USE_ENVELOPES */