cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pgp_rw.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Miscellaneous (Non-ASN.1) Read/Write Routines *
4 * Copyright Peter Gutmann 1992-2007 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "pgp_rw.h"
11 #else
12  #include "crypt.h"
13  #include "enc_dec/pgp_rw.h"
14 #endif /* Compiler-specific includes */
15 
16 #ifdef USE_PGP
17 
18 /****************************************************************************
19 * *
20 * PGP Read/Write Routines *
21 * *
22 ****************************************************************************/
23 
24 /* Read a length in OpenPGP or PGP2 format */
25 
26 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
27 static int readOpenPGPLength( INOUT STREAM *stream,
28  OUT_LENGTH_Z long *length,
29  OUT_BOOL BOOLEAN *indefiniteLength,
30  const BOOLEAN indefOK )
31  {
32  long localLength;
33 
34  assert( isWritePtr( stream, sizeof( STREAM ) ) );
35  assert( isWritePtr( length, sizeof( long ) ) );
36  assert( isWritePtr( indefiniteLength, sizeof( BOOLEAN ) ) );
37 
38  /* Clear return values */
39  *length = 0;
40  *indefiniteLength = FALSE;
41 
42  /* Get the initial length byte to allow us to decode what else is there.
43  The error status is also checked later but we make it explicit here */
44  localLength = sgetc( stream );
45  if( cryptStatusError( localLength ) )
46  return( localLength );
47 
48  /* 0...191 is a literal value */
49  if( localLength <= 191 )
50  {
51  *length = localLength;
52  return( CRYPT_OK );
53  }
54 
55  /* 192...223 is a 13-bit value with offset 192, giving a length in the
56  range 192...8383 */
57  if( localLength <= 223 )
58  {
59  const int value = sgetc( stream );
60  if( cryptStatusError( value ) )
61  return( value );
62  localLength = ( ( localLength - 192 ) << 8 ) + value + 192;
63  if( localLength < 192 || localLength > 8383 )
64  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
65  *length = localLength;
66 
67  return( CRYPT_OK );
68  }
69 
70  /* 224...254 is PGP's annoying interpretation of indefinite-length
71  encoding. This is an incredible pain to handle but fortunately
72  except for McAfee's PGP implementation it doesn't seem to be used by
73  anything. The only data type that would normally need indefinite
74  lengths, compressed data, uses the 2.x CTB 0xA3 instead */
75  if( localLength < 255 )
76  {
77  if( !indefOK )
78  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
79 
80  /* Unlike ASN.1, which encodes an outer indefinite-length marker and
81  then encodes each sub-segment as a data unit within it, PGP
82  encodes a partial length as a sequence of power-of-two exponent
83  values with a standard length encoding for the last sub-segment.
84  So once we're in indefinite-length mode we have to record the
85  current *type* of the length (as well as its value) to determine
86  whether more length packets follow */
87  *indefiniteLength = TRUE;
88  localLength = 1 << ( localLength & 0x1F );
89  if( localLength < 1 || localLength >= MAX_INTLENGTH )
90  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
91  *length = localLength;
92 
93  return( CRYPT_OK );
94  }
95  ENSURES( localLength == 255 );
96 
97  /* 255 is a marker that a standard 32-bit length follows */
98  localLength = readUint32( stream );
99  if( cryptStatusError( localLength ) )
100  return( localLength );
101  *length = localLength;
102 
103  return( CRYPT_OK );
104  }
105 
106 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
107 static int readPGP2Length( INOUT STREAM *stream,
108  OUT_LENGTH_Z long *length,
109  IN_BYTE const int ctb )
110  {
111  long localLength;
112 
113  assert( isWritePtr( stream, sizeof( STREAM ) ) );
114  assert( isWritePtr( length, sizeof( long ) ) );
115 
116  /* Clear return value */
117  *length = 0;
118 
119  /* It's a PGP 2.x CTB, decode the length as a byte, word, or long */
120  switch( ctb & 3 )
121  {
122  case 0:
123  localLength = sgetc( stream );
124  break;
125 
126  case 1:
127  localLength = readUint16( stream );
128  break;
129 
130  case 2:
131  localLength = readUint32( stream );
132  break;
133 
134  default:
135  /* A length value of 3 indicates that the data length is
136  determined externally, this is a deprecated PGP 2.x value
137  that we don't handle */
138  localLength = CRYPT_ERROR_BADDATA;
139  }
140  if( cryptStatusError( localLength ) )
141  return( localLength );
142  if( localLength < 0 || localLength >= MAX_INTLENGTH )
143  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
144  *length = localLength;
145 
146  return( CRYPT_OK );
147  }
148 
149 /* Read PGP variable-length length values and packet headers (CTB + length).
150  We also have a short-length version which is used to read small packets
151  such as keyrings and sigs and which ensures that the length is in the
152  range 1...16K */
153 
155 static int pgpReadLength( INOUT STREAM *stream,
156  OUT_LENGTH long *length,
157  IN_BYTE const int ctb,
158  IN_LENGTH_SHORT_Z const int minLength,
159  IN_LENGTH const int maxLength,
160  const BOOLEAN indefOK )
161  {
162  BOOLEAN indefiniteLength = FALSE;
163  long localLength;
164  int status;
165 
166  assert( isWritePtr( stream, sizeof( STREAM ) ) );
167  assert( isWritePtr( length, sizeof( long ) ) );
168 
169  REQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT && \
170  minLength < maxLength && maxLength <= MAX_INTLENGTH );
171 
172  /* Clear return value */
173  *length = 0;
174 
175  /* If it doesn't look like PGP data, don't go any further */
176  if( !pgpIsCTB( ctb ) )
177  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
178 
179  /* If it's an OpenPGP CTB, undo the hand-Huffman-coding */
181  {
182  status = readOpenPGPLength( stream, &localLength,
183  &indefiniteLength, indefOK );
184  }
185  else
186  status = readPGP2Length( stream, &localLength, ctb );
187  if( cryptStatusError( status ) )
188  return( status );
189  if( localLength < minLength || localLength > maxLength )
190  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
191  *length = localLength;
192  return( indefiniteLength ? OK_SPECIAL : CRYPT_OK );
193  }
194 
196 static int readPacketHeader( INOUT STREAM *stream,
197  OUT_OPT_BYTE int *ctb,
198  OUT_OPT_LENGTH_Z long *length,
199  IN_LENGTH_SHORT_Z const int minLength,
200  IN_LENGTH const int maxLength,
201  const BOOLEAN indefOK )
202  {
203  long localLength;
204  int localCTB, status;
205 
206  assert( isWritePtr( stream, sizeof( STREAM ) ) );
207  assert( ctb == NULL || isWritePtr( ctb, sizeof( int ) ) );
208  assert( length == NULL || isWritePtr( length, sizeof( long ) ) );
209 
210  REQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT && \
211  minLength < maxLength && maxLength <= MAX_INTLENGTH );
212 
213  /* Clear return values */
214  if( ctb != NULL )
215  *ctb = 0;
216  if( length != NULL )
217  *length = 0;
218 
219  /* Examine the CTB and figure out whether we need to perform any
220  special-case handling */
221  localCTB = sgetc( stream );
222  if( cryptStatusError( localCTB ) )
223  return( localCTB );
224  if( !pgpIsCTB( localCTB ) )
225  {
226  /* If it doesn't look like PGP data, don't go any further */
227  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
228  }
229  if( localCTB == PGP_CTB_COMPRESSED )
230  {
231  /* If it's a compressed data packet, there's no length present.
232  Normally we reject any indefinite-length packets since these
233  can't be processed sensibly (PGP 2.x, which used intermediate
234  files for everything, just read to EOF, OpenPGP deprecates them
235  because this doesn't exactly lead to portable implementations).
236  However, compressed-data packets can only be stored in this
237  manner but can still be processed because the user has to
238  explicitly flush the data at some point and we assume that this
239  is EOF. For this reason we don't return OK_SPECIAL to indicate
240  an indefinite-length encoding because this isn't a standard
241  segmented encoding but a virtual definite-length that ends when
242  the user says it ends. This is far uglier than the PKCS #7/CMS/
243  SMIME equivalent where we've got an explicit end-of-data
244  indication, but it's the best that we can do */
245  if( ctb != NULL )
246  *ctb = localCTB;
247  if( length != NULL )
248  *length = CRYPT_UNUSED;
249  return( CRYPT_OK ); /* Not-really-indef. return status */
250  }
251 
252  /* Now that we know the format, get the length information */
253  status = pgpReadLength( stream, &localLength, localCTB,
254  minLength, maxLength, indefOK );
255  if( cryptStatusError( status ) )
256  {
257  int type;
258 
259  if( status != OK_SPECIAL )
260  return( status );
261 
262  /* It's an indefinite-length encoding, this is only valid for
263  payload data packets so we make sure that we've got one of these
264  packet types present */
265  ENSURES( indefOK );
266  type = pgpGetPacketType( localCTB );
267  if( type != PGP_PACKET_DATA && type != PGP_PACKET_COPR && \
268  type != PGP_PACKET_ENCR && type != PGP_PACKET_ENCR_MDC )
269  return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
270  }
271  if( ctb != NULL )
272  *ctb = localCTB;
273  if( length != NULL )
274  *length = localLength;
275 
276  return( CRYPT_OK );
277  }
278 
279 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
280 int pgpReadShortLength( INOUT STREAM *stream,
281  OUT_LENGTH int *length,
282  IN_BYTE const int ctb )
283  {
284  long localLength;
285  int status;
286 
287  assert( isWritePtr( stream, sizeof( STREAM ) ) );
288 
289  status = pgpReadLength( stream, &localLength, ctb, 0,
291  if( cryptStatusError( status ) )
292  return( status );
293  *length = ( int ) localLength;
294 
295  return( CRYPT_OK );
296  }
297 
299 int pgpReadPacketHeader( INOUT STREAM *stream, OUT_OPT_BYTE int *ctb,
300  OUT_OPT_LENGTH_Z long *length,
301  IN_LENGTH_SHORT const int minLength )
302  {
303  assert( isWritePtr( stream, sizeof( STREAM ) ) );
304  assert( ctb == NULL || isWritePtr( ctb, sizeof( int ) ) );
305  assert( length == NULL || isWritePtr( length, sizeof( long ) ) );
306 
307  REQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT );
308 
309  return( readPacketHeader( stream, ctb, length, minLength, MAX_INTLENGTH,
310  FALSE ) );
311  }
312 
314 int pgpReadPacketHeaderI( INOUT STREAM *stream, OUT_OPT_BYTE int *ctb,
315  OUT_OPT_LENGTH_Z long *length,
316  IN_LENGTH_SHORT const int minLength )
317  {
318  assert( isWritePtr( stream, sizeof( STREAM ) ) );
319  assert( ctb == NULL || isWritePtr( ctb, sizeof( int ) ) );
320  assert( length == NULL || isWritePtr( length, sizeof( long ) ) );
321 
322  REQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT );
323 
324  return( readPacketHeader( stream, ctb, length, minLength, MAX_INTLENGTH,
325  TRUE ) );
326  }
327 
328 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
329 int pgpReadPartialLength( INOUT STREAM *stream,
330  OUT_LENGTH_Z long *length )
331  {
332  assert( isWritePtr( stream, sizeof( STREAM ) ) );
333  assert( isWritePtr( length, sizeof( long ) ) );
334 
335  /* This is a raw length value so we have to feed in a pseudo-CTB */
336  return( pgpReadLength( stream, length, PGP_CTB_OPENPGP,
337  0, MAX_INTLENGTH, TRUE ) );
338  }
339 
340 /* Write PGP variable-length length values and packet headers (CTB +
341  length) */
342 
343 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
344 int pgpWriteLength( INOUT STREAM *stream, IN_LENGTH const long length )
345  {
346  assert( isWritePtr( stream, sizeof( STREAM ) ) );
347 
348  REQUIRES_S( length > 0 && length < MAX_INTLENGTH );
349 
350  if( length <= 191 )
351  return( sputc( stream, length ) );
352  if( length <= 8383 )
353  {
354  const long adjustedLength = length - 192;
355 
356  sputc( stream, ( ( adjustedLength >> 8 ) & 0xFF ) + 192 );
357  return( sputc( stream, ( adjustedLength & 0xFF ) ) );
358  }
359  sputc( stream, 0xFF );
360  sputc( stream, ( length >> 24 ) & 0xFF );
361  sputc( stream, ( length >> 16 ) & 0xFF );
362  sputc( stream, ( length >> 8 ) & 0xFF );
363  return( sputc( stream, ( length & 0xFF ) ) );
364  }
365 
366 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
367 int pgpWritePacketHeader( INOUT STREAM *stream,
368  IN_ENUM( PGP_PACKET ) const PGP_PACKET_TYPE packetType,
369  IN_LENGTH const long length )
370  {
371  assert( isWritePtr( stream, sizeof( STREAM ) ) );
372 
373  REQUIRES_S( packetType > PGP_PACKET_NONE && \
374  packetType < PGP_PACKET_LAST );
375  REQUIRES_S( length > 0 && length < MAX_INTLENGTH );
376 
377  sputc( stream, PGP_CTB_OPENPGP | packetType );
378  return( pgpWriteLength( stream, length ) );
379  }
380 #endif /* USE_PGP */