cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
asn1_chk.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * ASN.1 Checking Routines *
4 * Copyright Peter Gutmann 1992-2009 *
5 * *
6 ****************************************************************************/
7 
8 #include <ctype.h>
9 #if defined( INC_ALL )
10  #include "crypt.h"
11  #include "asn1.h"
12 #else
13  #include "crypt.h"
14  #include "enc_dec/asn1.h"
15 #endif /* Compiler-specific includes */
16 
17 /* The maximum nesting level for constructed or encapsulated objects (this
18  can get surprisingly high for some of the more complex attributes). This
19  value is chosen to pass all normal certs while avoiding stack overflows
20  for artificial bad data */
21 
22 #define MAX_NESTING_LEVEL 50
23 
24 /* When we parse a nested data object encapsulated within a larger object,
25  the length is initially set to a magic value which is adjusted to the
26  actual length once we start parsing the object. Even CRLs will hopefully
27  never reach 500MB, the current limits seems to be around 150MB */
28 
29 #define LENGTH_MAGIC 500000000L
30 
31 /* Current parse state. This is used to check for potential BIT STRING and
32  OCTET STRING targets for OCTET/BIT STRING holes, which are always
33  preceded by an AlgorithmIdentifier. In order to detect these without
34  having to know every imaginable AlgorithmIdentifier OID, we check for the
35  following sequence of events:
36 
37  SEQUENCE { -- STATE_SEQUENCE
38  OID, -- STATE_HOLE_OID
39  NULL -- STATE_NULL
40  },
41  -- STATE_CHECK_HOLE_BITSTRING
42  BIT STRING | ...
43 
44  SEQUENCE { -- STATE_SEQUENCE
45  OID, -- STATE_HOLE_OID
46  [ BOOLEAN OPT, -- STATE_BOOLEAN ]
47  -- STATE_CHECK_HOLE_OCTETSTRING
48  OCTET STRING | ...
49 
50  Once we reach any of the STATE_CHECK_HOLE_* states, if we hit a BIT STRING
51  or OCTET STRING as the next item then we try and locate encapsulated
52  content within it.
53 
54  This type of checking is rather awkward in the (otherwise stateless) code
55  but is the only way to be sure that it's safe to try burrowing into an
56  OCTET STRING or BIT STRING to try to find encapsulated data, since
57  otherwise even with relatively strict checking there's still a very small
58  chance that random data will look like a nested object.
59 
60  The handling of BIT STRING encapsulation is complicated by the fact that
61  for crypto use it really only occurs in one of two cases:
62 
63  SEQUENCE {
64  OID,
65  NULL
66  },
67  BIT STRING {
68  SEQUENCE {
69  INTEGER
70  ...
71 
72  for public keys and and:
73 
74  SEQUENCE {
75  OID,
76  NULL
77  },
78  BIT STRING ...
79 
80  for signatures (with an additional complication for DLP keys that the
81  NULL for the public-key parameters is replaced by a SEQUENCE { ... }
82  containing the public parameters). Because of this there's little point
83  in trying to track the state because any occurrence of a potential BIT
84  STRING hole has a 50:50 chance of actually being one or not. Because of
85  this we don't bother tracking the state for BIT STRINGs but rely on the
86  encapsulation-check to catch them. This should be fairly safe because we
87  require that the value be:
88 
89  [ SEQUENCE ][ = outerLength - SEQUENCE-hdrSize ]
90  [ INTEGER ][ <= innerlength - INTEGER-hdrSize ]
91 
92  which provides at least 26-28 bits of safety */
93 
94 typedef enum {
95  /* Generic non-state */
97 
98  /* States corresponding to ASN.1 primitives */
100 
101  /* States corresponding to different parts of a SEQUENCE { OID, optional,
102  potential OCTET/BIT STRING } sequence */
103  STATE_HOLE_OID, /*STATE_CHECK_HOLE_BITSTRING,*/ STATE_CHECK_HOLE_OCTETSTRING,
104 
105  /* Error state */
107 
109  } ASN1_STATE;
110 
111 /* Structure to hold info on an ASN.1 item */
112 
113 typedef struct {
114  int tag; /* Tag */
115  long length; /* Data length */
116  BOOLEAN indefinite; /* Item has indefinite length */
117  int headerSize; /* Size of tag+length */
118  } ASN1_ITEM;
119 
120 /* Get an ASN.1 object's tag and length */
121 
122 CHECK_RETVAL_ENUM( STATE ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
123 static int getItem( INOUT STREAM *stream, OUT ASN1_ITEM *item )
124  {
125  const long offset = stell( stream );
126  long length;
127  int status;
128 
129  assert( isWritePtr( stream, sizeof( STREAM ) ) );
130  assert( isWritePtr( item, sizeof( ASN1_ITEM ) ) );
131 
132  REQUIRES_EXT( ( offset >= 0 && offset < MAX_INTLENGTH ), STATE_ERROR );
133 
134  /* Clear return value */
135  memset( item, 0, sizeof( ASN1_ITEM ) );
136 
137  /* Read the tag. We can't use peekTag() for this since we may be
138  reading EOC octets, which would be rejected by peekTag() */
139  status = item->tag = sPeek( stream );
140  if( cryptStatusError( status ) )
141  return( STATE_ERROR );
142  if( item->tag == BER_EOC )
143  {
144  /* It looks like EOC octets, make sure that they're in order */
145  status = checkEOC( stream );
146  if( cryptStatusError( status ) )
147  return( STATE_ERROR );
148  if( status == TRUE )
149  {
150  item->headerSize = 2;
151  return( STATE_NONE );
152  }
153  }
154 
155  /* Make sure that it's at least vaguely valid before we try the
156  readLongGenericHole() */
157  if( item->tag <= 0 || item->tag >= MAX_TAG )
158  return( STATE_ERROR );
159 
160  /* It's not an EOC, read the tag and length as a generic hole */
161  status = readLongGenericHole( stream, &length, item->tag );
162  if( cryptStatusError( status ) )
163  return( STATE_ERROR );
164  item->headerSize = stell( stream ) - offset;
165  if( length == CRYPT_UNUSED )
166  item->indefinite = TRUE;
167  else
168  item->length = length;
169  return( STATE_NONE );
170  }
171 
172 /* Check whether an ASN.1 object is encapsulated inside an OCTET STRING or
173  BIT STRING. After performing the various checks we have to explicitly
174  clear the stream error state since the probing for valid data could have
175  set the error indicator if nothing valid was found.
176 
177  Note that this is a no-biased test since the best that we can do is guess
178  at the presence of encapsulated content and we can't risk rejecting valid
179  content based on a false positive. This means that unfortunately
180  maliciously-encoded nested content with (for example) an incorrect inner
181  length will slip past our checks, and we have to rely on the robustness
182  of the general ASN1-read code to avoid problems with it. It's not
183  obvious whether this is really a serious problem or not though (apart from
184  it being a certificational weakness), a too-short length will result in
185  whatever additional padding is present being skipped by the general ASN1-
186  read code, a too-long length will result in an immediate error as the
187  decoder encounters garbage from reading past the TLV that follows */
188 
190 static BOOLEAN checkEncapsulation( INOUT STREAM *stream,
191  IN_LENGTH const int length,
192  const BOOLEAN isBitstring,
194  const ASN1_STATE state )
195  {
196  BOOLEAN isEncapsulated = TRUE;
197  const long streamPos = stell( stream );
198  const int tag = peekTag( stream );
199  int innerLength, status;
200 
201  assert( isWritePtr( stream, sizeof( STREAM ) ) );
202 
203  REQUIRES_B( length > 0 && length < MAX_INTLENGTH );
204  REQUIRES_B( state >= STATE_NONE && state < STATE_ERROR );
205  REQUIRES_B( streamPos >= 0 && streamPos < MAX_INTLENGTH );
206 
207  /* Make sure that the tag is in order */
208  if( cryptStatusError( tag ) )
209  {
210  sClearError( stream );
211  sseek( stream, streamPos );
212  return( FALSE );
213  }
214 
215  /* Make sure that there's an encapsulated object present. This is a
216  reasonably effective check, but unfortunately this same effectiveness
217  means that it'll reject nested objects with incorrect lengths. It's
218  not really possible to fix this, either there'll be false positives
219  due to true OCTET/BIT STRINGs that look like they might contain
220  nested data or there'll be no false positives but nested content
221  with slightly incorrect encodings will be missed (see the comment at
222  the start for more on this) */
223  status = readGenericHole( stream, &innerLength, 1, DEFAULT_TAG );
224  if( cryptStatusError( status ) || \
225  ( stell( stream ) - streamPos ) + innerLength != length )
226  {
227  sClearError( stream );
228  sseek( stream, streamPos );
229  return( FALSE );
230  }
231 
232  /* A BIT STRING that encapsulates something only ever contains
233  { SEQUENCE { INTEGER, ... } } */
234  if( isBitstring )
235  {
236  /* Make sure that there's a SEQUENCE containing an INTEGER present */
237  if( tag != BER_SEQUENCE || peekTag( stream ) != BER_INTEGER || \
238  cryptStatusError( readGenericHole( stream, &innerLength, 1,
239  BER_INTEGER ) ) || \
240  innerLength > length - 4 )
241  isEncapsulated = FALSE;
242 
243  sClearError( stream );
244  sseek( stream, streamPos );
245  return( isEncapsulated );
246  }
247 
248  /* An OCTET STRING is more complex. This could encapsulate any of:
249 
250  BIT STRING: keyUsage, crlReason, Netscape certType, must be
251  <= 16 bits and a valid bitstring.
252  GeneralisedTime: invalidityDate: Not possible to check directly
253  since the obvious check for a valid length will also fail
254  invalid-length encodings, missing the very thing we usually
255  want to check for, so all that we can check for is a vaguely
256  valid length.
257  IA5String: Netscape extensions, the most that we can do is perform
258  an approximate length range check
259  INTEGER: deltaCRLIndicator, crlNumber, must be <= 16 bits.
260  OCTET STRING: keyID, again the most that we can do is perform an
261  approximate length range check.
262  OID: holdInstructionCode, again just an approximate length range
263  check.
264  SEQUENCE: most extensions, a bit difficult to check but again we can
265  make sure that the length is right for strict encapsulation.
266 
267  Note that we want these checks to be as liberal as possible since
268  we're only checking for the *possibility* of encapsulated data at
269  this point (again, see the comment at the start). Once we're fairly
270  certain that it's encapsulated data then we recurse down into it with
271  checkASN1(). If we rejected too many things at this level then it'd
272  never get checked via checkASN1() */
273  switch( tag )
274  {
275  case BER_BITSTRING:
276  if( innerLength < 0 || innerLength > 2 )
277  isEncapsulated = FALSE;
278  else
279  {
280  int ch = sgetc( stream );
281 
282  if( ch < 0 || ch > 7 )
283  isEncapsulated = FALSE;
284  }
285  break;
286 
288  if( innerLength < 10 || innerLength > 20 )
289  isEncapsulated = FALSE;
290  break;
291 
292  case BER_INTEGER:
293  if( innerLength < 0 || innerLength > 2 )
294  isEncapsulated = FALSE;
295  break;
296 
297  case BER_STRING_IA5:
298  case BER_OCTETSTRING:
299  if( innerLength < 2 || innerLength > 256 )
300  isEncapsulated = FALSE;
301  break;
302 
304  if( innerLength < MIN_OID_SIZE - 2 || \
305  innerLength > MAX_OID_SIZE )
306  isEncapsulated = FALSE;
307  break;
308 
309  case BER_SEQUENCE:
310  break;
311 
312  default:
313  isEncapsulated = FALSE;
314  }
315  sClearError( stream );
316  sseek( stream, streamPos );
317  return( isEncapsulated );
318  }
319 
320 /* Check a primitive ASN.1 object */
321 
323 static ASN1_STATE checkASN1( INOUT STREAM *stream,
324  IN_LENGTH const long length,
325  const BOOLEAN isIndefinite,
326  IN_RANGE( 0, MAX_NESTING_LEVEL ) const int level,
328  const BOOLEAN checkDataElements );
329 
330 CHECK_RETVAL_ENUM( STATE ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
331 static ASN1_STATE checkPrimitive( INOUT STREAM *stream, const ASN1_ITEM *item,
332  IN_RANGE( 1, MAX_NESTING_LEVEL ) const int level,
334  {
335  int length = ( int ) item->length, ch, i;
336 
337  assert( isWritePtr( stream, sizeof( STREAM ) ) );
338  assert( isReadPtr( item, sizeof( ASN1_ITEM ) ) );
339 
340  REQUIRES( level > 0 && level <= MAX_NESTING_LEVEL );
341  REQUIRES( state >= STATE_NONE && state < STATE_ERROR );
342  REQUIRES( length >= 0 && length < MAX_INTLENGTH );
343 
344  /* Make sure that we're not processing suspiciosly deeply nested data */
345  if( level >= MAX_NESTING_LEVEL )
346  return( STATE_ERROR );
347 
348  /* In theory only NULL and EOC elements (BER_RESERVED) are allowed to
349  have a zero length, but some broken implementations (Netscape, Van
350  Dyke) encode numeric zero values as a zero-length element so we have
351  to accept these as well */
352  if( length <= 0 && item->tag != BER_NULL && \
353  item->tag != BER_RESERVED && \
354  item->tag != BER_INTEGER )
355  return( STATE_ERROR );
356 
357  /* Perform a general check that everything is OK. We don't check for
358  invalid content except where it would impede decoding of the data in
359  order to avoid failing on all of the broken certs out there */
360  switch( item->tag )
361  {
362  case BER_BOOLEAN:
363  return( cryptStatusError( sgetc( stream ) ) ? \
365 
366  case BER_INTEGER:
367  case BER_ENUMERATED:
368  if( length > 0 && /* May be encoded as a zero-length value */
369  cryptStatusError( sSkip( stream, length ) ) )
370  return( STATE_ERROR );
371  return( STATE_NONE );
372 
373  case BER_BITSTRING:
374  /* Check the number of unused bits */
375  ch = sgetc( stream );
376  length--;
377  if( length < 0 || length >= MAX_INTLENGTH || \
378  ch < 0 || ch > 7 )
379  {
380  /* Invalid number of unused bits */
381  return( STATE_ERROR );
382  }
383 
384  /* If it's short enough to be a bit flag, it's just a sequence
385  of bits */
386  if( length <= 4 )
387  {
388  if( length > 0 && \
389  cryptStatusError( sSkip( stream, length ) ) )
390  return( STATE_ERROR );
391  return( STATE_NONE );
392  }
393  /* Fall through */
394 
395  case BER_OCTETSTRING:
396  {
397  const BOOLEAN isBitstring = ( item->tag == BER_BITSTRING ) ? \
398  TRUE : FALSE;
399 
400  /* Check to see whether an OCTET STRING or BIT STRING hole is
401  allowed at this point (a BIT STRING must be preceded by
402  { SEQ, OID, NULL }, an OCTET STRING must be preceded by
403  { SEQ, OID, {BOOLEAN} }), and if it's something encapsulated
404  inside the string, handle it as a constructed item */
405 #if 0 /* See comment at start */
406  if( ( ( isBitstring && state == STATE_CHECK_HOLE_BITSTRING ) || \
407  ( !isBitstring && ( state == STATE_HOLE_OID || \
408  state == STATE_CHECK_HOLE_OCTETSTRING ) ) ) && \
409  checkEncapsulation( stream, length, isBitstring, state ) )
410 #else
411  if( ( isBitstring || state == STATE_HOLE_OID || \
412  state == STATE_CHECK_HOLE_OCTETSTRING ) && \
413  checkEncapsulation( stream, length, isBitstring, state ) )
414 #endif /* 0 */
415  {
416  ASN1_STATE encapsState;
417 
418  encapsState = checkASN1( stream, length, item->indefinite,
419  level + 1, STATE_NONE, TRUE );
420  return( ( encapsState < STATE_NONE || \
421  encapsState >= STATE_ERROR ) ? \
423  }
424 
425  /* Skip the data */
426  return( cryptStatusError( sSkip( stream, length ) ) ? \
428  }
429 
431  if( length > MAX_OID_SIZE - 2 )
432  {
433  /* Total OID size (including tag and length, since they're
434  treated as a blob) should be less than a sane limit */
435  return( STATE_ERROR );
436  }
437  return( cryptStatusError( sSkip( stream, length ) ) ? \
439 
440  case BER_RESERVED:
441  break; /* EOC */
442 
443  case BER_NULL:
444  return( STATE_NULL );
445 
446  case BER_STRING_BMP:
447  case BER_STRING_GENERAL: /* Produced by Entrust software */
448  case BER_STRING_IA5:
449  case BER_STRING_ISO646:
450  case BER_STRING_NUMERIC:
452  case BER_STRING_T61:
453  case BER_STRING_UTF8:
454  return( cryptStatusError( sSkip( stream, length ) ) ? \
456 
457  case BER_TIME_UTC:
459  if( item->tag == BER_TIME_GENERALIZED )
460  {
461  if( length != 15 )
462  return( STATE_ERROR );
463  }
464  else
465  {
466  if( length != 13 )
467  return( STATE_ERROR );
468  }
469  for( i = 0; i < length - 1; i++ )
470  {
471  ch = sgetc( stream );
472  if( cryptStatusError( ch ) || !isDigit( ch ) )
473  return( STATE_ERROR );
474  }
475  if( sgetc( stream ) != 'Z' )
476  return( STATE_ERROR );
477  return( STATE_NONE );
478 
479  default:
480  /* Disallowed or unrecognised primitive */
481  return( STATE_ERROR );
482  }
483 
484  return( STATE_NONE );
485  }
486 
487 /* Check a single ASN.1 object. checkASN1() and checkASN1Object() are
488  mutually recursive, the ...Object() version only exists to avoid a
489  large if... else chain in checkASN1(). A typical checking run is
490  as follows:
491 
492  30 nn cASN1 -> cAObj -> cASN1
493  30 nn cASN1 -> cAObj -> cASN1
494  04 nn nn cASN1 -> cPrim
495 
496  30 80 cASN1 -> cAObj -> cASN1
497  30 80 cASN1 -> cAObj -> cASN1
498  04 nn nn cASN1 -> cPrim
499  00 00 cASN1 <- cAObj <- cASN1
500  00 00 cASN1 <- cAObj <- cASN1
501 
502  The use of checkASN1Object() leads to an (apparently) excessively deep
503  call hierarchy, but that's mostly just an artifact of the way that it's
504  diagrammed here */
505 
506 CHECK_RETVAL_ENUM( STATE ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
507 static ASN1_STATE checkASN1Object( INOUT STREAM *stream, const ASN1_ITEM *item,
509  const int level,
511  const BOOLEAN checkDataElements )
512  {
513  ASN1_STATE newState;
514 
515  assert( isWritePtr( stream, sizeof( STREAM ) ) );
516  assert( isReadPtr( item, sizeof( ASN1_ITEM ) ) );
517 
518  REQUIRES( level > 0 && level <= MAX_NESTING_LEVEL );
519  REQUIRES( state >= STATE_NONE && state < STATE_ERROR );
520 
521  /* Make sure that we're not processing suspiciosly deeply nested data */
522  if( level >= MAX_NESTING_LEVEL )
523  return( STATE_ERROR );
524 
525  /* Check the contents for validity. A straight data-length check doesn't
526  check nested elements since all it cares about is finding the overall
527  length with as little effort as possible */
528  if( ( item->tag & BER_CLASS_MASK ) == BER_UNIVERSAL )
529  {
530  /* If we're not interested in the data elements (i.e. if we're just
531  doing a length check) and the item has a definite length, just
532  skip over it and continue */
533  if( !checkDataElements && item->length > 0 )
534  {
535  if( cryptStatusError( sSkip( stream, item->length ) ) )
536  return( STATE_ERROR );
537  }
538 
539  /* If it's constructed, parse the nested object(s) */
540  if( ( item->tag & BER_CONSTRUCTED_MASK ) == BER_CONSTRUCTED )
541  {
542  /* Special-case for zero-length SEQUENCE/SET */
543  if( item->length <= 0 && !item->indefinite )
544  return( STATE_NONE );
545 
546  return( checkASN1( stream, item->length, item->indefinite,
547  level + 1, ( item->tag == BER_SEQUENCE ) ? \
549  checkDataElements ) );
550  }
551 
552  /* It's primitive, check the primitive element with optional state
553  update: SEQ + OID -> HOLE_OID; OID + { NULL | BOOLEAN } ->
554  HOLE_BITSTRING/HOLE_OCTETSTRING */
555  newState = checkPrimitive( stream, item, level + 1, state );
556  if( newState < STATE_NONE || newState >= STATE_ERROR )
557  return( STATE_ERROR );
558  if( state == STATE_SEQUENCE && newState == STATE_OID )
559  return( STATE_HOLE_OID );
560  if( state == STATE_HOLE_OID )
561  {
562 #if 0 /* See comment at start */
563  if( newState == STATE_NULL )
564  return( STATE_CHECK_HOLE_BITSTRING );
565 #endif /* 0 */
566  if( newState == STATE_BOOLEAN )
568  }
569  return( STATE_NONE );
570  }
571 
572  /* Zero-length objects are usually an error, however PKCS #10 has an
573  attribute-encoding ambiguity that produces zero-length tagged
574  extensions and OCSP has its braindamaged context-specific tagged
575  NULLs so we don't complain about them if they have low-valued
576  context-specific tags */
577  if( item->length <= 0 && !item->indefinite )
578  {
579  return( ( ( item->tag & BER_CLASS_MASK ) == BER_CONTEXT_SPECIFIC && \
580  EXTRACT_CTAG( item->tag ) <= 3 ) ? \
582  }
583 
584  ENSURES( item->length > 0 || item->indefinite );
585 
586  /* If it's constructed, parse the nested object(s) */
587  if( ( item->tag & BER_CONSTRUCTED_MASK ) == BER_CONSTRUCTED )
588  {
589  newState = checkASN1( stream, item->length, item->indefinite,
590  level + 1, STATE_NONE, checkDataElements );
591  return( ( newState < STATE_NONE || newState >= STATE_ERROR ) ? \
593  }
594 
595  /* It's a context-specific tagged item that could contain anything, just
596  skip it */
597  if( ( item->tag & BER_CLASS_MASK ) != BER_CONTEXT_SPECIFIC || \
598  item->length <= 0 )
599  return( STATE_ERROR );
600  return( cryptStatusError( sSkip( stream, item->length ) ) ? \
602  }
603 
604 /* Check a complex ASN.1 object. In order to handle huge CRLs with tens or
605  hundreds of thousands of individual entries we can't use a fixed loop
606  failsafe iteration count but have to vary it based on the size of the
607  input data. Luckily this situation is relatively easy to check for, it
608  only occurs at a nesting level of 6 (when we find the CRL entries) and we
609  only have to enable it when the data length is more than 30K since the
610  default FAILSAFE_ITERATIONS_LARGE will handle anything smaller than that */
611 
612 CHECK_RETVAL_ENUM( STATE ) STDC_NONNULL_ARG( ( 1 ) ) \
613 static ASN1_STATE checkASN1( INOUT STREAM *stream,
614  IN_LENGTH const long length,
615  const BOOLEAN isIndefinite,
616  IN_RANGE( 0, MAX_NESTING_LEVEL ) const int level,
618  const BOOLEAN checkDataElements )
619  {
620  ASN1_ITEM item;
621  ASN1_STATE newState;
622  const long maxIterationCount = ( level == 6 && length > 30000 ) ? \
623  length / 25 : FAILSAFE_ITERATIONS_LARGE;
624  long localLength = length, lastPos = stell( stream );
625  int iterationCount;
626 
627  assert( isWritePtr( stream, sizeof( STREAM ) ) );
628 
629  REQUIRES( ( level > 0 && level <= MAX_NESTING_LEVEL ) || \
630  ( level == 0 && length == LENGTH_MAGIC ) );
631  REQUIRES( state >= STATE_NONE && state < STATE_ERROR );
632  REQUIRES( ( isIndefinite && length == 0 ) || \
633  ( !isIndefinite && length >= 0 && length < MAX_INTLENGTH ) );
634  REQUIRES( lastPos >= 0 && lastPos < MAX_INTLENGTH );
635 
636  /* Make sure that we're not processing suspiciosly deeply nested data */
637  if( level >= MAX_NESTING_LEVEL )
638  return( STATE_ERROR );
639 
640  for( iterationCount = 0;
641  ( newState = getItem( stream, &item ) ) == STATE_NONE && \
642  iterationCount < maxIterationCount;
643  iterationCount++ )
644  {
645  /* If this is the top level (for which the length isn't known in
646  advance) and the item has a definite length, set the length to
647  the item's length */
648  if( level <= 0 && !item.indefinite )
649  localLength = item.headerSize + item.length;
650 
651  /* If this is an EOC (tag == BER_RESERVED) for an indefinite item,
652  we're done */
653  if( isIndefinite && item.tag == BER_RESERVED )
654  return( STATE_NONE );
655 
656  /* Check the object */
657  if( !checkDataElements && item.length > 0 )
658  {
659  /* Shortcut to save a level of recursion, if we're not
660  interested in the data elements (i.e. if we're just doing a
661  length check) and the item has a definite length, just skip
662  over it and continue */
663  if( cryptStatusError( sSkip( stream, item.length ) ) )
664  return( STATE_ERROR );
665  }
666  else
667  {
668  newState = checkASN1Object( stream, &item, level + 1, state,
669  checkDataElements );
670  if( newState < STATE_NONE || newState >= STATE_ERROR )
671  return( STATE_ERROR );
672  }
673 
674  /* If it's an indefinite-length object, we have to keep going until
675  we find the EOC octets */
676  if( isIndefinite )
677  continue;
678 
679  /* If the outermost object was of indefinite length and we've come
680  back to the top level, exit. The isIndefinite flag won't be set
681  at this point because we can't know the length status before we
682  start, but it's implicitly indicated by finding a length of
683  LENGTH_MAGIC at the topmost level */
684  if( level == 0 && length == LENGTH_MAGIC )
685  return( STATE_NONE );
686 
687  /* Check whether we've reached the end of the current (definite-
688  length) object */
689  localLength -= stell( stream ) - lastPos;
690  lastPos = stell( stream );
691  if( localLength < 0 || localLength >= MAX_INTLENGTH )
692  return( STATE_ERROR );
693  if( localLength == 0 )
694  {
695  /* We've reached the end of the object, we're done */
696  return( newState );
697  }
698 
699  /* We're reading more data from the current object, propagate any
700  state updates */
701  state = newState;
702  }
703  ENSURES_S( iterationCount < maxIterationCount );
704 
705  return( ( newState == STATE_NONE ) ? STATE_NONE : STATE_ERROR );
706  }
707 
708 /* Check the encoding of a complete object and determine its length (qui
709  omnes insidias timet in nullas incidit - Syrus) */
710 
712 int checkObjectEncoding( IN_BUFFER( objectLength ) const void *objectPtr,
713  IN_LENGTH const int objectLength )
714  {
715  STREAM stream;
716  ASN1_STATE state;
717  int length = DUMMY_INIT;
718 
719  assert( isReadPtr( objectPtr, objectLength ) );
720 
721  REQUIRES( objectLength > 0 && objectLength < MAX_INTLENGTH );
722 
723  sMemConnect( &stream, objectPtr, objectLength );
724  state = checkASN1( &stream, LENGTH_MAGIC, FALSE, 0, STATE_NONE, TRUE );
725  if( state >= STATE_NONE && state < STATE_ERROR )
726  length = stell( &stream );
727  sMemDisconnect( &stream );
728  return( ( state < STATE_NONE ) ? CRYPT_ERROR_INTERNAL : \
729  ( state >= STATE_ERROR ) ? CRYPT_ERROR_BADDATA : length );
730  }
731 
732 /* Recursively dig into an ASN.1 object as far as we need to to determine
733  its length */
734 
736 static int findObjectLength( INOUT STREAM *stream,
737  OUT_LENGTH_Z long *length,
738  const BOOLEAN isLongObject )
739  {
740  const long startPos = stell( stream );
741  long localLength;
742  int status;
743 
744  assert( isWritePtr( stream, sizeof( STREAM ) ) );
745  assert( isWritePtr( length, sizeof( long ) ) );
746 
747  REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
748 
749  /* Clear return value */
750  *length = 0;
751 
752  /* Try for a definite length (quousque tandem?) */
753  status = readGenericObjectHeader( stream, &localLength, isLongObject );
754  if( cryptStatusError( status ) )
755  return( status );
756 
757  /* If it's an indefinite-length object, burrow down into it to find its
758  actual length */
759  if( localLength == CRYPT_UNUSED )
760  {
761  ASN1_STATE state;
762 
763  /* We have to be a bit careful how we handle error reporting for
764  this since we can run out of input and hit an underflow while
765  we're in the process of burrowing through the data. This is
766  somewhat unfortunate since it leads to non-orthogonal behaviour
767  because a definite length only requires checking a few bytes at
768  the start of the data but an indefinite length requires
769  processing the entire data quantity in order to determine where
770  it ends */
771  sseek( stream, startPos );
772  state = checkASN1( stream, LENGTH_MAGIC, FALSE, 0, STATE_NONE,
773  FALSE );
774  if( state < STATE_NONE || state >= STATE_ERROR )
775  {
776  return( ( state < STATE_NONE ) ? \
778  ( sGetStatus( stream ) == CRYPT_ERROR_UNDERFLOW ) ? \
781  }
782  localLength = stell( stream ) - startPos;
783  }
784  else
785  {
786  /* It's a definite-length object, add the size of the tag+length */
787  localLength += stell( stream ) - startPos;
788  }
789 
790  /* If it's not a long object, make sure that the length is within bounds.
791  We have to do this explicitly here because indefinite-length objects
792  can be arbitrarily large so the length isn't checked as it is for
793  readGenericHoleI() */
794  if( !isLongObject && localLength > 32767L )
795  return( CRYPT_ERROR_OVERFLOW );
796  *length = localLength;
797  return( sseek( stream, startPos ) );
798  }
799 
800 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
801 int getStreamObjectLength( INOUT STREAM *stream, OUT_LENGTH_Z int *length )
802  {
803  long localLength;
804  int status;
805 
806  assert( isWritePtr( stream, sizeof( STREAM ) ) );
807  assert( isWritePtr( length, sizeof( int ) ) );
808 
809  /* Clear return value */
810  *length = 0;
811 
812  status = findObjectLength( stream, &localLength, FALSE );
813  if( cryptStatusOK( status ) )
814  *length = localLength;
815  return( status );
816  }
817 
818 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
819 int getLongStreamObjectLength( INOUT STREAM *stream,
820  OUT_LENGTH_Z long *length )
821  {
822  long localLength;
823  int status;
824 
825  assert( isWritePtr( stream, sizeof( STREAM ) ) );
826  assert( isWritePtr( length, sizeof( long ) ) );
827 
828  /* Clear return value */
829  *length = 0;
830 
831  status = findObjectLength( stream, &localLength, TRUE );
832  if( cryptStatusOK( status ) )
833  *length = localLength;
834  return( status );
835  }
836 
838 int getObjectLength( IN_BUFFER( objectLength ) const void *objectPtr,
839  IN_LENGTH const int objectLength,
840  OUT_LENGTH_Z int *length )
841  {
842  STREAM stream;
843  long localLength = DUMMY_INIT;
844  int status;
845 
846  assert( isReadPtr( objectPtr, objectLength ) );
847  assert( isWritePtr( length, sizeof( int ) ) );
848 
849  REQUIRES( objectLength > 0 && objectLength < MAX_INTLENGTH );
850 
851  /* Clear return value */
852  *length = 0;
853 
854  sMemConnect( &stream, objectPtr, objectLength );
855  status = findObjectLength( &stream, &localLength, FALSE );
856  sMemDisconnect( &stream );
857  if( cryptStatusError( status ) )
858  return( status );
859 
860  *length = localLength;
861  return( CRYPT_OK );
862  }
863 
864 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
865 int getLongObjectLength( IN_BUFFER( objectLength ) const void *objectPtr,
866  IN_LENGTH const long objectLength,
867  OUT_LENGTH_Z long *length )
868  {
869  STREAM stream;
870  long localLength;
871  int status;
872 
873  assert( isReadPtr( objectPtr, objectLength ) );
874  assert( isWritePtr( length, sizeof( long ) ) );
875 
876  REQUIRES( objectLength > 0 && objectLength < MAX_INTLENGTH );
877 
878  /* Clear return value */
879  *length = 0;
880 
881  sMemConnect( &stream, objectPtr, objectLength );
882  status = findObjectLength( &stream, &localLength, TRUE );
883  sMemDisconnect( &stream );
884  if( cryptStatusOK( status ) )
885  *length = localLength;
886  return( status );
887  }