cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ext_rd.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Certificate Attribute Read Routines *
4 * Copyright Peter Gutmann 1996-2008 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "cert.h"
10  #include "certattr.h"
11  #include "asn1.h"
12  #include "asn1_ext.h"
13 #else
14  #include "cert/cert.h"
15  #include "cert/certattr.h"
16  #include "enc_dec/asn1.h"
17  #include "enc_dec/asn1_ext.h"
18 #endif /* Compiler-specific includes */
19 
20 /* Define the following to print a trace of the certificate fields being
21  parsed, useful for debugging broken certificates */
22 
23 #if !defined( NDEBUG ) && 0
24  #if defined( _MSC_VER )
25  #pragma warning( disable: 4127 ) /* 'stackPos' may be hardcoded */
26  #endif /* VC++ */
27  #define TRACE_FIELDTYPE( attributeInfoPtr, stackPos ) \
28  { \
29  int i; \
30  \
31  DEBUG_PRINT(( "%4d:", stell( stream ) )); \
32  for( i = 0; i < stackPos; i++ ) \
33  DEBUG_PRINT(( " " )); \
34  if( ( attributeInfoPtr ) != NULL && \
35  ( attributeInfoPtr )->description != NULL ) \
36  { \
37  DEBUG_PRINT(( ( attributeInfoPtr )->description )); \
38  DEBUG_PRINT(( "\n" )); \
39  } \
40  else \
41  { \
42  DEBUG_PRINT(( "<Unknown field>\n" )); \
43  } \
44  }
45  #define TRACE_DEBUG( message ) \
46  DEBUG_PRINT( message ); \
47  DEBUG_PRINT(( "\n" ));
48 #else
49  #define TRACE_FIELDTYPE( attributeInfoPtr, stackPos )
50  #define TRACE_DEBUG( message )
51 #endif /* NDEBUG */
52 
53 #ifdef USE_CERTIFICATES
54 
55 /****************************************************************************
56 * *
57 * Utility Routines *
58 * *
59 ****************************************************************************/
60 
61 /* Get the tag for a field from the attribute field definition */
62 
63 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
64 static int getFieldTag( INOUT STREAM *stream,
65  const ATTRIBUTE_INFO *attributeInfoPtr,
66  int *tag )
67  {
68  int status, value;
69 
70  assert( isWritePtr( stream, sizeof( STREAM ) ) );
71  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
72  assert( isWritePtr( tag, sizeof( int ) ) );
73 
74  /* Clear return value. This is actually a bit difficult to do because
75  the output can have both positive values (tags) and negative values
76  (field codes), setting the output to -1000 is invalid for both
77  types */
78  *tag = -1000;
79 
80  /* Check whether the field is tagged */
81  status = value = getFieldEncodedTag( attributeInfoPtr );
82  if( cryptStatusError( status ) )
83  {
84  /* If there's no tagging (i.e. the tag is the same as the field
85  type) we'll get an OK_SPECIAL return value, this isn't an
86  error */
87  if( status != OK_SPECIAL )
88  return( status );
89  }
90  else
91  {
92  /* It's a tagged field, return the encoded form */
93  *tag = value;
94 
95  return( CRYPT_OK );
96  }
97  ENSURES( status == OK_SPECIAL );
98 
99  /* It's a non-tagged field, the tag is the same as the field type */
100  value = attributeInfoPtr->fieldType;
101  if( value == FIELDTYPE_TEXTSTRING )
102  {
103  static const int allowedStringTypes[] = {
106  CRYPT_ERROR, CRYPT_ERROR
107  };
108  int i;
109 
110  /* This is a variable-tag field that can have one of a number of
111  tags. To handle this we peek ahead into the stream to see if an
112  acceptable tag is present and if not set the value to a non-
113  matching tag value */
114  status = value = peekTag( stream );
115  if( cryptStatusError( status ) )
116  return( status );
117  for( i = 0; allowedStringTypes[ i ] != value && \
118  i < FAILSAFE_ARRAYSIZE( allowedStringTypes, int ); i++ )
119  {
120  /* If we've reached the end of the list of allowed types without
121  finding a match, change the tag value from what we've found to
122  make sure that it results in a non-match when the caller uses
123  it */
124  if( allowedStringTypes[ i ] == CRYPT_ERROR )
125  {
126  value++;
127  break;
128  }
129  }
130  ENSURES( i < FAILSAFE_ARRAYSIZE( allowedStringTypes, int ) );
131  }
132  if( value == FIELDTYPE_BLOB_BITSTRING || \
133  value == FIELDTYPE_BLOB_SEQUENCE )
134  {
135  /* This is a typed blob that's read as a blob but still has a type
136  for type-checking purposes */
137  value = ( value == FIELDTYPE_BLOB_BITSTRING ) ? \
139  }
140 
141  ENSURES( ( ( value == FIELDTYPE_BLOB_ANY || value == FIELDTYPE_DN ) && \
142  !( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) ) || \
143  ( value > 0 && value <= MAX_TAG ) );
144  /* A FIELDTYPE_BLOB_ANY or FIELDTYPE_DN can't be optional
145  fields because with no type information for them available
146  there's no way to check whether we've encountered them or
147  not */
148  *tag = value;
149 
150  return( CRYPT_OK );
151  }
152 
153 /* Read an explicit tag that wraps the actual item that we're after */
154 
155 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
156 static int readExplicitTag( INOUT STREAM *stream,
157  const ATTRIBUTE_INFO *attributeInfoPtr,
158  OUT_TAG_Z int *tag )
159  {
160  int status;
161 
162  assert( isWritePtr( stream, sizeof( STREAM ) ) );
163  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
164  assert( isWritePtr( tag, sizeof( int ) ) );
165 
166  REQUIRES( attributeInfoPtr->encodingFlags & FL_EXPLICIT );
167  REQUIRES( attributeInfoPtr->fieldEncodedType >= 0 && \
168  attributeInfoPtr->fieldEncodedType < MAX_TAG );
169 
170  /* Clear return value */
171  *tag = 0;
172 
173  /* Read the explicit wrapper */
174  status = readConstructed( stream, NULL,
175  attributeInfoPtr->fieldEncodedType );
176  if( cryptStatusError( status ) )
177  return( status );
178 
179  /* We've processed the explicit wrappper, we're now on the actual tag */
180  *tag = attributeInfoPtr->fieldType;
181 
182  return( CRYPT_OK );
183  }
184 
185 /* Find the end of an item (either primitive or constructed) in the attribute
186  table. Sometimes we may have already entered a constructed object (for
187  example when an attribute has a version number so we don't know until we've
188  started processing it that we can't do anything with it), if this is the
189  case then the depth parameter indicates how many nesting levels we have to
190  undo */
191 
193 static int findItemEnd( const ATTRIBUTE_INFO **attributeInfoPtrPtr,
194  IN_RANGE( 0, 3 ) const int depth )
195  {
196  const ATTRIBUTE_INFO *attributeInfoPtr;
197  int currentDepth = depth, iterationCount;
198 
199  assert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );
200  assert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );
201 
202  REQUIRES( depth >= 0 && depth < 3 );
203 
204  /* Skip to the end of the (potentially) constructed item by recording the
205  nesting level and continuing until either it reaches zero or we reach
206  the end of the item */
207  for( attributeInfoPtr = *attributeInfoPtrPtr, iterationCount = 0;
208  !( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) && \
209  iterationCount < FAILSAFE_ITERATIONS_MED;
210  attributeInfoPtr++, iterationCount++ )
211  {
212  /* If it's a sequence/set, increment the depth; if it's an end-of-
213  constructed-item marker, decrement it by the appropriate amount */
214  if( attributeInfoPtr->fieldType == BER_SEQUENCE || \
215  attributeInfoPtr->fieldType == BER_SET )
216  currentDepth++;
217  currentDepth -= decodeNestingLevel( attributeInfoPtr->encodingFlags );
218  if( currentDepth <= 0 )
219  break;
220  }
221  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
222 
223  /* We return the next-to-last entry by stopping when we find the
224  FL_ATTR_ATTREND flag since we're going to move on to the next entry
225  once we return */
226  *attributeInfoPtrPtr = attributeInfoPtr;
227  return( CRYPT_OK );
228  }
229 
230 /****************************************************************************
231 * *
232 * SET/SEQUENCE Management Routines *
233 * *
234 ****************************************************************************/
235 
236 /* When we're processing SETs/SEQUENCEs (generically referred to as a SET
237  OF) we need to maintain a stack of state information to handle a nested
238  SET OF. The following code implements the state stack */
239 
240 #define SETOF_STATE_STACKSIZE 16
241 
242 #define SETOF_FLAG_NONE 0x00 /* No flag value */
243 #define SETOF_FLAG_SUBTYPED 0x01 /* SET ends on a subtyped value */
244 #define SETOF_FLAG_RESTARTPOINT 0x02 /* SET OF rather than SET */
245 #define SETOF_FLAG_ISEMPTY 0x04 /* Cleared if SET OF contains at least one entry */
246 
247 typedef struct {
248  /* SET OF state information */
249  const ATTRIBUTE_INFO *infoStart; /* Start of SET OF attribute information */
250  int startPos, endPos; /* Start and end position of SET OF */
251  int flags; /* SET OF flags */
252 
253  /* Subtype information */
254  CRYPT_ATTRIBUTE_TYPE subtypeParent; /* Parent type if this is subtyped */
255  int inheritedFlags; /* Flags inherited from parent if subtyped */
256  } SETOF_STATE_INFO;
257 
258 typedef struct {
259  ARRAY( SETOF_STATE_STACKSIZE, stackPos ) \
260  SETOF_STATE_INFO stateInfo[ SETOF_STATE_STACKSIZE + 8 ];
261  int stackPos; /* Current position in stack */
262  } SETOF_STACK;
263 
264 STDC_NONNULL_ARG( ( 1 ) ) \
265 static void setofStackInit( OUT SETOF_STACK *setofStack )
266  {
267  assert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );
268 
269  memset( setofStack, 0, sizeof( SETOF_STACK ) );
270  }
271 
273 static BOOLEAN setofStackPush( INOUT SETOF_STACK *setofStack )
274  {
275  assert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );
276 
277  /* Increment the stack pointer and make sure that we don't overflow */
278  if( setofStack->stackPos < 0 || \
279  setofStack->stackPos >= SETOF_STATE_STACKSIZE - 1 )
280  return( FALSE );
281  setofStack->stackPos++;
282  ENSURES_B( setofStack->stackPos >= 1 && \
283  setofStack->stackPos < SETOF_STATE_STACKSIZE );
284 
285  /* Initialise the new entry */
286  memset( &setofStack->stateInfo[ setofStack->stackPos ], 0, \
287  sizeof( SETOF_STATE_INFO ) );
288 
289  return( TRUE );
290  }
291 
293 static BOOLEAN setofStackPop( INOUT SETOF_STACK *setofStack )
294  {
295  assert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );
296 
297  /* Decrement the stack pointer and make sure that we don't underflow */
298  if( setofStack->stackPos <= 0 || \
299  setofStack->stackPos >= SETOF_STATE_STACKSIZE )
300  return( FALSE );
301  setofStack->stackPos--;
302  ENSURES_B( setofStack->stackPos >= 0 && \
303  setofStack->stackPos < SETOF_STATE_STACKSIZE - 1 );
304 
305  return( TRUE );
306  }
307 
309 static SETOF_STATE_INFO *setofTOS( const SETOF_STACK *setofStack )
310  {
311  assert( isReadPtr( setofStack, sizeof( SETOF_STACK ) ) );
312 
313  ENSURES_N( setofStack->stackPos >= 0 && \
314  setofStack->stackPos < SETOF_STATE_STACKSIZE );
315 
316  return( ( SETOF_STATE_INFO * ) \
317  &setofStack->stateInfo[ setofStack->stackPos ] );
318  }
319 
320 /* Process the start of a SET/SET OF/SEQUENCE/SEQUENCE OF */
321 
322 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
323 static int beginSetof( INOUT STREAM *stream,
324  INOUT SETOF_STACK *setofStack,
325  const ATTRIBUTE_INFO *attributeInfoPtr )
326  {
327  SETOF_STATE_INFO *setofInfoPtr;
328  CRYPT_ATTRIBUTE_TYPE oldSubtypeParent;
329  int oldInheritedFlags, setofLength, status;
330 
331  assert( isWritePtr( stream, sizeof( STREAM ) ) );
332  assert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );
333  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
334 
335  /* Determine the length and start position of the SET OF items. If the
336  tag is an explicit tag then we don't have to process it since it's
337  already been handled by the caller */
338  if( attributeInfoPtr->fieldEncodedType >= 0 && \
339  !( attributeInfoPtr->encodingFlags & FL_EXPLICIT ) )
340  {
341  status = readConstructed( stream, &setofLength,
342  attributeInfoPtr->fieldEncodedType );
343  }
344  else
345  {
346  if( attributeInfoPtr->fieldType == BER_SET )
347  status = readSet( stream, &setofLength );
348  else
349  status = readSequence( stream, &setofLength );
350  }
351  if( cryptStatusError( status ) )
352  return( status );
353 
354  /* When processing a SET/SEQUENCE with default values for the elements
355  the result may be a zero-length object, in which case we don't take
356  any action */
357  if( setofLength <= 0 )
358  return( CRYPT_OK );
359 
360  /* Remember assorted information such as where the SET/SEQUENCE ends.
361  In addition if this is a SET OF/SEQUENCE OF, remember this as a
362  restart point for when we're parsing the next item in the
363  SET/SEQUENCE OF */
364  setofInfoPtr = setofTOS( setofStack );
365  ENSURES( setofInfoPtr != NULL );
366  oldSubtypeParent = setofInfoPtr->subtypeParent;
367  oldInheritedFlags = setofInfoPtr->inheritedFlags;
368  if( !setofStackPush( setofStack ) )
369  {
370  /* Stack overflow, there's a problem with the certificate */
371  return( CRYPT_ERROR_OVERFLOW );
372  }
373  setofInfoPtr = setofTOS( setofStack );
374  ENSURES( setofInfoPtr != NULL );
375  setofInfoPtr->infoStart = attributeInfoPtr;
376  if( attributeInfoPtr->encodingFlags & FL_SETOF )
377  setofInfoPtr->flags |= SETOF_FLAG_RESTARTPOINT;
378  if( !( attributeInfoPtr->encodingFlags & FL_EMPTYOK ) )
379  setofInfoPtr->flags |= SETOF_FLAG_ISEMPTY;
380  setofInfoPtr->subtypeParent = oldSubtypeParent;
381  setofInfoPtr->inheritedFlags = oldInheritedFlags;
382  setofInfoPtr->startPos = stell( stream );
383  setofInfoPtr->endPos = setofInfoPtr->startPos + setofLength;
384 
385  return( CRYPT_OK );
386  }
387 
388 /* Check whether we've reached the end of a SET/SEQUENCE. Returns OK_SPECIAL
389  if the end has been reached */
390 
391 CHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
392 static int checkSetofEnd( const STREAM *stream,
393  INOUT SETOF_STACK *setofStack,
394  const ATTRIBUTE_INFO **attributeInfoPtrPtr )
395  {
396  const SETOF_STATE_INFO *setofInfoPtr = setofTOS( setofStack );
397  const ATTRIBUTE_INFO *oldAttributeInfoPtr = *attributeInfoPtrPtr;
398  const ATTRIBUTE_INFO *attributeInfoPtr = *attributeInfoPtrPtr;
399  const int currentPos = stell( stream );
400  int iterationCount;
401 
402  assert( isReadPtr( stream, sizeof( STREAM ) ) );
403  assert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );
404  assert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );
405  assert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );
406 
407  REQUIRES( setofInfoPtr != NULL );
408  REQUIRES( currentPos > 0 && currentPos < MAX_INTLENGTH );
409 
410  /* If we're still within the SET/SEQUENCE, we're done */
411  if( setofStack->stackPos <= 0 || currentPos < setofInfoPtr->endPos )
412  return( CRYPT_OK );
413 
414  /* We've reached the end of one or more layers of SET/SEQUENCE, keep
415  popping SET/SEQUENCE state information until we can continue */
416  for( iterationCount = 0;
417  setofStack->stackPos > 0 && \
418  currentPos >= setofInfoPtr->endPos && \
419  iterationCount < SETOF_STATE_STACKSIZE;
420  iterationCount++ )
421  {
422  const int flags = setofInfoPtr->flags;
423 
424  /* Pop one level of parse state */
425  if( !setofStackPop( setofStack ) )
426  {
427  /* Stack underflow, there's a problem with the certificate */
428  return( CRYPT_ERROR_UNDERFLOW );
429  }
430  setofInfoPtr = setofTOS( setofStack );
431  ENSURES( setofInfoPtr != NULL );
432  attributeInfoPtr = setofInfoPtr->infoStart;
433  ENSURES( setofInfoPtr->endPos > 0 && \
434  setofInfoPtr->endPos < MAX_INTLENGTH_SHORT );
435 
436  /* If it's a pure SET/SEQUENCE (not a SET OF/SEQUENCE OF) and there
437  are no more elements present, go to the end of the SET/SEQUENCE
438  information in the decoding table */
439  if( !( flags & SETOF_FLAG_RESTARTPOINT ) && \
440  currentPos >= setofInfoPtr->endPos )
441  {
442  int status;
443 
444  status = findItemEnd( &attributeInfoPtr, 0 );
445  if( cryptStatusError( status ) )
446  return( status );
447  }
448  }
449  ENSURES( iterationCount < SETOF_STATE_STACKSIZE );
450 
451  *attributeInfoPtrPtr = attributeInfoPtr;
452  return( ( attributeInfoPtr != oldAttributeInfoPtr ) ? \
453  OK_SPECIAL : CRYPT_OK );
454  }
455 
456 /****************************************************************************
457 * *
458 * Identified Item Management Routines *
459 * *
460 ****************************************************************************/
461 
462 /* Given a pointer to a set of SEQUENCE { type, value } entries, return a
463  pointer to the { value } entry appropriate for the data in the stream.
464  If the entry contains user data in the { value } portion then the
465  returned pointer points to this, if it contains a fixed value or isn't
466  present at all then the returned pointer points to the { type } portion */
467 
469 static const ATTRIBUTE_INFO *findIdentifiedItem( INOUT STREAM *stream,
470  const ATTRIBUTE_INFO *attributeInfoPtr )
471  {
472  BYTE oid[ MAX_OID_SIZE + 8 ];
473  int oidLength, sequenceLength, iterationCount, status;
474 
475  assert( isWritePtr( stream, sizeof( STREAM ) ) );
476  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
477 
478  REQUIRES_N( attributeInfoPtr->encodingFlags & FL_IDENTIFIER );
479 
480  /* Skip the header and read the OID. We only check for a sane total
481  length in the debug version since this isn't a fatal error */
482  readSequence( stream, &sequenceLength );
483  status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength,
485  if( cryptStatusError( status ) )
486  return( NULL );
487  sequenceLength -= oidLength;
488  ENSURES_N( sequenceLength >= 0 && sequenceLength < MAX_INTLENGTH );
489 
490  /* Walk down the list of entries trying to match it to an allowed value.
491  Unfortunately we can't use the attributeInfoSize bounds check limit
492  here because we don't know how far through the attribute table we
493  already are, so we have to use a generic large value */
494  for( iterationCount = 0;
495  ( attributeInfoPtr->encodingFlags & FL_IDENTIFIER ) && \
496  iterationCount < FAILSAFE_ITERATIONS_LARGE;
497  iterationCount++ )
498  {
499  const BYTE *oidPtr;
500 
501  /* Skip the SEQUENCE and OID. The fact that an OID follows the
502  entry with the FL_IDENTIFIER field unless it's the finall catch-
503  all blob entry has been verified during the startup check */
504  attributeInfoPtr++;
505  oidPtr = attributeInfoPtr->oid;
506  if( !( attributeInfoPtr->encodingFlags & FL_NONENCODING ) )
507  attributeInfoPtr++;
508  else
509  {
510  /* If this is a blob field we've hit a don't-care value (usually
511  the last in a series of type-and-value pairs) which ensures
512  that { type }s added after the encoding table was defined
513  don't get processed as errors, skip the field and continue */
514  if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB_ANY )
515  {
516  /* If there's a { value } attached to the type, skip it */
517  if( sequenceLength > 0 )
518  {
519  status = sSkip( stream, sequenceLength );
520  if( cryptStatusError( status ) )
521  return( NULL );
522  }
523  return( attributeInfoPtr );
524  }
525  }
526  ENSURES_N( oidPtr != NULL );
527 
528  /* If the OID matches, return a pointer to the value entry */
529  if( oidLength == sizeofOID( oidPtr ) && \
530  !memcmp( oidPtr, oid, sizeofOID( oidPtr ) ) )
531  {
532  /* If this is a fixed field and there's a value attached, skip
533  it */
534  if( ( attributeInfoPtr->encodingFlags & FL_NONENCODING ) && \
535  sequenceLength > 0 )
536  {
537  status = sSkip( stream, sequenceLength );
538  if( cryptStatusError( status ) )
539  return( NULL );
540  }
541 
542  return( attributeInfoPtr );
543  }
544 
545  /* The OID doesn't match, skip the { value } entry and continue. We
546  set the current nesting depth parameter to 1 since we've already
547  entered the SEQUENCE above */
548  status = findItemEnd( &attributeInfoPtr, 1 );
549  if( cryptStatusError( status ) )
550  return( NULL );
551  attributeInfoPtr++; /* Move to start of next item */
552  }
553  ENSURES_N( iterationCount < FAILSAFE_ITERATIONS_LARGE );
554 
555  /* We reached the end of the set of entries without matching the OID */
556  return( NULL );
557  }
558 
559 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5, 6, 7 ) ) \
560 static int processIdentifiedItem( INOUT STREAM *stream,
561  INOUT ATTRIBUTE_LIST **attributeListPtrPtr,
562  IN_FLAGS( ATTR ) const int flags,
563  const SETOF_STACK *setofStack,
564  const ATTRIBUTE_INFO **attributeInfoPtrPtr,
565  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
566  CRYPT_ATTRIBUTE_TYPE *errorLocus,
567  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
568  CRYPT_ERRTYPE_TYPE *errorType )
569  {
570  const SETOF_STATE_INFO *setofInfoPtr = setofTOS( setofStack );
571  const ATTRIBUTE_INFO *attributeInfoPtr;
572 
573  assert( isWritePtr( stream, sizeof( STREAM ) ) );
574  assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
575  assert( isReadPtr( setofStack, sizeof( SETOF_STACK ) ) );
576  assert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );
577  assert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );
578  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
579  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
580 
581 assert( ( flags & ~( ATTR_FLAG_CRITICAL ) ) == 0 );
582  REQUIRES( flags >= ATTR_FLAG_NONE && flags <= ATTR_FLAG_MAX );
583  REQUIRES( setofInfoPtr != NULL );
584 
585  /* Search for the identified item from the start of the set of items.
586  The 0-th value is the SET OF/SEQUENCE OF so we start the search at
587  the next entry which is the first FL_IDENTIFIER */
588  ENSURES( setofInfoPtr->infoStart->encodingFlags & FL_SETOF );
589  attributeInfoPtr = findIdentifiedItem( stream,
590  setofInfoPtr->infoStart + 1 );
591  if( attributeInfoPtr == NULL )
592  return( CRYPT_ERROR_BADDATA );
593  *attributeInfoPtrPtr = attributeInfoPtr;
594 
595  /* If it's a subtyped field, tell the caller to restart the decoding
596  using the new attribute information. This is typically used where
597  the { type, value } combinations that we're processing are
598  { OID, GeneralName }, so the process consists of locating the entry
599  that corresponds to the OID and then continuing the decoding with
600  the the subtyped attribute information entry that points to the
601  GeneralName decoding table */
602  if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )
603  return( OK_SPECIAL );
604 
605  /* If it's not a special-case, non-encoding field, we're done */
606  if( !( attributeInfoPtr->encodingFlags & FL_NONENCODING ) )
607  return( CRYPT_OK );
608 
609  /* If the { type, value } pair has a fixed value then the information
610  being conveyed is its presence, not its contents, so we add an
611  attribute corresponding to its ID and continue. The addition of the
612  attribute is a bit tricky, some of the fixed type-and-value pairs can
613  have multiple entries denoting things like { algorithm, weak key },
614  { algorithm, average key }, { algorithm, strong key }, however all
615  that we're interested in is the strong key so we ignore the value and
616  only use the type (in his ordo est ordinem non servare). Since the
617  same type can be present multiple times (with different { value }s)
618  we ignore data duplicate errors and continue. If we're processing a
619  blob field type then we've ended up at a generic catch-any value and
620  can't do much with it */
621  if( attributeInfoPtr->fieldType != FIELDTYPE_BLOB_ANY )
622  {
623  int status;
624 
625  /* Add the field type, discarding warnings about duplicates */
626  TRACE_FIELDTYPE( attributeInfoPtr, 0 );
627  status = addAttributeField( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
628  attributeInfoPtr->fieldID,
630  flags, errorLocus, errorType );
631  if( cryptStatusError( status ) && status != CRYPT_ERROR_INITED )
632  return( CRYPT_ERROR_BADDATA );
633  }
634 
635  /* Reset the attribute information position in preparation for
636  processing the next value and tell the caller to continue using the
637  reset attribute information */
638  *attributeInfoPtrPtr = setofInfoPtr->infoStart + 1;
639  return( OK_SPECIAL );
640  }
641 
642 /* Read a sequence of identifier fields of the form { oid, value OPTIONAL }.
643  This is used to read both SEQUENCE OF (via FIELDTYPE_IDENTIFIER) and
644  CHOICE (via FIELDTYPE_CHOICE), with SEQUENCE OF allowing multiple entries
645  and CHOICE allowing only a single entry */
646 
647 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \
648 static int readIdentifierFields( INOUT STREAM *stream,
649  INOUT ATTRIBUTE_LIST **attributeListPtrPtr,
650  const ATTRIBUTE_INFO **attributeInfoPtrPtr,
651  IN_FLAGS( ATTR ) const int flags,
653  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
654  CRYPT_ATTRIBUTE_TYPE *errorLocus,
655  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
656  CRYPT_ERRTYPE_TYPE *errorType )
657  {
658  const ATTRIBUTE_INFO *attributeInfoPtr;
659  const BOOLEAN isChoice = ( fieldID != CRYPT_ATTRIBUTE_NONE );
660  int count = 0, iterationCount;
661 
662  assert( isWritePtr( stream, sizeof( STREAM ) ) );
663  assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
664  assert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );
665  assert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );
666  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
667  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
668 
669 assert( ( flags == ATTR_FLAG_NONE ) || ( flags == ATTR_FLAG_CRITICAL ) );
670  REQUIRES( flags >= ATTR_FLAG_NONE && flags <= ATTR_FLAG_MAX );
671 
672  for( iterationCount = 0;
673  peekTag( stream ) == BER_OBJECT_IDENTIFIER && \
674  iterationCount < FAILSAFE_ITERATIONS_MED;
675  iterationCount++ )
676  {
677  BYTE oid[ MAX_OID_SIZE + 8 ];
678  BOOLEAN addField = TRUE;
679  int oidLength, innerIterationCount, status;
680 
681  /* The fact that the FIELDTYPE_IDENTIFIER field is present and
682  associated with an OID has been verified during the startup
683  check */
684  attributeInfoPtr = *attributeInfoPtrPtr;
685  ENSURES( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER && \
686  attributeInfoPtr->oid != NULL );
687 
688  /* Read the OID and walk down the list of possible OIDs up to the end
689  of the group of alternatives trying to match it to an allowed
690  value */
691  status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength,
693  if( cryptStatusError( status ) )
694  return( status );
695  for( innerIterationCount = 0;
696  ( oidLength != sizeofOID( attributeInfoPtr->oid ) || \
697  memcmp( attributeInfoPtr->oid, oid, oidLength ) ) && \
698  innerIterationCount < FAILSAFE_ITERATIONS_MED;
699  innerIterationCount++ )
700  {
701  /* If we've reached the end of the list and the OID wasn't
702  matched, exit */
703  if( ( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK ) || \
704  ( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )
705  return( CRYPT_ERROR_BADDATA );
706 
707  attributeInfoPtr++;
708 
709  /* If this is a blob field we've hit a don't-care value which
710  ensures that { type }s added after the encoding table was
711  defined don't get processed as errors, skip the field and
712  continue */
713  if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB_ANY )
714  {
715  addField = FALSE;
716  break;
717  }
718 
719  /* The fact that the FIELDTYPE_IDENTIFIER field is present and
720  associated with an OID has been verified during the startup
721  check */
722  ENSURES( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER && \
723  attributeInfoPtr->oid != NULL );
724  }
725  ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_MED );
726  TRACE_FIELDTYPE( attributeInfoPtr, 0 );
727  if( addField )
728  {
729  /* The OID matches, add this field as an identifier field. This
730  will catch duplicate OIDs since we can't add the same
731  identifier field twice */
732  if( isChoice )
733  {
734  /* If there's a field value present then this is a CHOICE of
735  attributes whose value is the field value so we add it with
736  this value */
737  status = addAttributeField( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
738  fieldID, CRYPT_ATTRIBUTE_NONE,
739  attributeInfoPtr->fieldID,
740  flags, errorLocus, errorType );
741  }
742  else
743  {
744  /* It's a standard field */
745  status = addAttributeField( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
746  attributeInfoPtr->fieldID,
748  CRYPT_UNUSED, flags,
749  errorLocus, errorType );
750  }
751  if( cryptStatusError( status ) )
752  return( status );
753  }
754  count++;
755 
756  /* If there's more than one OID present in a CHOICE, it's an error */
757  if( isChoice && count > 1 )
758  {
759  *errorLocus = attributeInfoPtr->fieldID,
760  *errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
761  return( CRYPT_ERROR_BADDATA );
762  }
763  }
764  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
765 
766  /* We've processed the non-data field(s), move on to the next field.
767  We move to the last valid non-data field rather than the start of the
768  field following it since the caller needs to be able to check whether
769  there are more fields to follow using the current field's flags.
770  Unfortunately we can't use the attributeInfoSize bounds check limit
771  here because we don't know how far through the attribute table we
772  already are, so we have to use a generic value */
773  for( attributeInfoPtr = *attributeInfoPtrPtr, iterationCount = 0;
774  !( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK ) && \
775  !( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) && \
776  iterationCount < FAILSAFE_ITERATIONS_MED;
777  attributeInfoPtr++, iterationCount++ );
778  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
779  *attributeInfoPtrPtr = attributeInfoPtr;
780 
781  return( CRYPT_OK );
782  }
783 
784 /****************************************************************************
785 * *
786 * Attribute/Attribute Field Read Routines *
787 * *
788 ****************************************************************************/
789 
790 /* Generic error-handler that sets extended error codes */
791 
792 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
793 static int fieldErrorReturn( OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
794  CRYPT_ATTRIBUTE_TYPE *errorLocus,
795  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
796  CRYPT_ERRTYPE_TYPE *errorType,
797  IN_ERROR const int status,
798  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID )
799  {
800  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
801  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
802 
803  REQUIRES( cryptStatusError( status ) );
804  REQUIRES( ( fieldID == CRYPT_ATTRIBUTE_NONE ) || \
805  ( fieldID > CRYPT_CERTINFO_FIRST && \
806  fieldID < CRYPT_CERTINFO_LAST ) );
807 
808  /* Since some fields are internal-use only (e.g. meaningless blob data,
809  version numbers, and other paraphernalia) we only set the locus if
810  it has a meaningful value */
811  *errorLocus = ( fieldID > CRYPT_CERTINFO_FIRST && \
812  fieldID < CRYPT_CERTINFO_LAST ) ? \
813  fieldID : CRYPT_ATTRIBUTE_NONE;
814  *errorType = CRYPT_ERRTYPE_ATTR_VALUE;
815 
816  return( status );
817  }
818 
819 /* Switch from the main encoding table to a subtype encoding table */
820 
822 static ATTRIBUTE_INFO *switchToSubtype( const ATTRIBUTE_INFO *attributeInfoPtr,
823  INOUT SETOF_STATE_INFO *setofInfoPtr )
824  {
825  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
826  assert( isReadPtr( attributeInfoPtr->extraData,
827  sizeof( ATTRIBUTE_INFO ) ) );
828  assert( isWritePtr( setofInfoPtr, sizeof( SETOF_STATE_INFO ) ) );
829 
830  /* This has already been verified during the startup check */
831  REQUIRES_N( attributeInfoPtr->extraData != NULL );
832 
833  /* Record the subtype parent information */
834  setofInfoPtr->subtypeParent = attributeInfoPtr->fieldID;
835  setofInfoPtr->inheritedFlags = \
836  ( attributeInfoPtr->encodingFlags & FL_MULTIVALUED ) ? \
838 
839  /* If the subtype is being used to process a list of { ... OPTIONAL,
840  ... OPTIONAL } and at least one entry must be present, remember
841  that we haven't seen any entries yet */
842  if( !( attributeInfoPtr->encodingFlags & FL_EMPTYOK ) )
843  setofInfoPtr->flags |= SETOF_FLAG_ISEMPTY;
844 
845  /* If the subtype ends once the current SET/SEQUENCE ends, remember this
846  so that we return to the main type when appropriate */
847  if( ( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK ) || \
848  ( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )
849  setofInfoPtr->flags |= SETOF_FLAG_SUBTYPED;
850 
851  /* Switch to the subtype encoding table */
852  return( ( ATTRIBUTE_INFO * ) attributeInfoPtr->extraData );
853  }
854 
855 /* Read the contents of an attribute field. This uses the readXXXData()
856  variants of the read functions because the field that we're reading may
857  be tagged so we process the tag at a higher level and only read the
858  contents here */
859 
860 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \
861 static int readAttributeField( INOUT STREAM *stream,
862  INOUT ATTRIBUTE_LIST **attributeListPtrPtr,
863  const ATTRIBUTE_INFO *attributeInfoPtr,
865  const CRYPT_ATTRIBUTE_TYPE subtypeParent,
866  IN_FLAGS( ATTR ) const int flags,
867  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
868  CRYPT_ATTRIBUTE_TYPE *errorLocus,
869  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
870  CRYPT_ERRTYPE_TYPE *errorType )
871  {
873  const int fieldType = attributeInfoPtr->fieldType;
874  int length, status = CRYPT_OK;
875 
876  assert( isWritePtr( stream, sizeof( STREAM ) ) );
877  assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
878  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
879  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
880  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
881 
882  REQUIRES( ( subtypeParent == CRYPT_ATTRIBUTE_NONE ) || \
883  ( subtypeParent > CRYPT_CERTINFO_FIRST && \
884  subtypeParent < CRYPT_CERTINFO_LAST ) );
885 assert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED ) ) == 0 );
886  REQUIRES( flags >= ATTR_FLAG_NONE && flags <= ATTR_FLAG_MAX );
887 
888  /* Set up the field identifiers depending on whether it's a normal field
889  or a subfield of a parent field */
890  if( subtypeParent == CRYPT_ATTRIBUTE_NONE )
891  {
892  fieldID = attributeInfoPtr->fieldID;
893  subFieldID = CRYPT_ATTRIBUTE_NONE;
894  }
895  else
896  {
897  fieldID = subtypeParent;
898  subFieldID = attributeInfoPtr->fieldID;
899  }
900 
901  /* Read the field as appropriate */
902  switch( fieldType )
903  {
904  case BER_INTEGER:
905  case BER_ENUMERATED:
906  case BER_BITSTRING:
907  case BER_BOOLEAN:
908  case BER_NULL:
909  {
910  int value;
911 
912  /* Read the data as appropriate */
913  switch( fieldType )
914  {
915  case BER_BITSTRING:
916  status = readBitStringData( stream, &value );
917  break;
918 
919  case BER_BOOLEAN:
920  {
922 
923  status = readBooleanData( stream, &boolean );
924  value = boolean;
925  break;
926  }
927 
928  case BER_ENUMERATED:
929  status = readEnumeratedData( stream, &value );
930  break;
931 
932  case BER_INTEGER:
933  {
934  long longValue;
935 
936  status = readShortIntegerData( stream, &longValue );
937  value = ( int ) longValue;
938  break;
939  }
940 
941  case BER_NULL:
942  /* NULL values have no associated data so we explicitly
943  set the value to CRYPT_UNUSED to ensure that this is
944  returned on any attempt to read it */
945  value = CRYPT_UNUSED;
946  break;
947 
948  default:
949  retIntError();
950  }
951  if( cryptStatusError( status ) )
952  return( fieldErrorReturn( errorLocus, errorType, status,
953  attributeInfoPtr->fieldID ) );
954 
955  /* Add the data for this attribute field */
956  return( addAttributeField( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
957  fieldID, subFieldID, value, flags,
958  errorLocus, errorType ) );
959  }
960 
962  case BER_TIME_UTC:
963  {
964  time_t timeVal;
965 
966  if( fieldType == BER_TIME_GENERALIZED )
967  status = readGeneralizedTimeData( stream, &timeVal );
968  else
969  status = readUTCTimeData( stream, &timeVal );
970  if( cryptStatusError( status ) )
971  return( fieldErrorReturn( errorLocus, errorType, status,
972  attributeInfoPtr->fieldID ) );
973 
974  /* Add the data for this attribute field */
975  return( addAttributeFieldString( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
976  fieldID, subFieldID, &timeVal,
977  sizeof( time_t ), flags,
978  errorLocus, errorType ) );
979  }
980 
981  case BER_STRING_BMP:
982  case BER_STRING_IA5:
983  case BER_STRING_ISO646:
984  case BER_STRING_NUMERIC:
986  case BER_STRING_T61:
987  case BER_STRING_UTF8:
988  case BER_OCTETSTRING:
989  case FIELDTYPE_BLOB_ANY:
993  {
994  /* If it's a string type or a blob read it in as a blob (the
995  only difference being that for a true blob we read the tag +
996  length as well) */
997  BYTE buffer[ 256 + 8 ];
998 
999  /* Read in the string to a maximum length of 256 bytes */
1000  if( isBlobField( fieldType ) )
1001  {
1002  int tag;
1003 
1004  /* Reading in blob fields is somewhat difficult since these
1005  are typically used to read SET/SEQUENCE OF kitchensink
1006  values and so won't have a consistent tag that we can pass
1007  to readRawObject(). To get around this we peek ahead into
1008  the stream to get the tag and then pass that down to
1009  readRawObject(). Note that this requires that the blob
1010  have an internal structure (with its own { tag, length }
1011  data) since the caller has already stripped off the tag
1012  and length */
1013  status = tag = peekTag( stream );
1014  if( cryptStatusError( status ) )
1015  {
1016  return( fieldErrorReturn( errorLocus, errorType, status,
1017  attributeInfoPtr->fieldID ) );
1018  }
1019  status = readRawObject( stream, buffer, 256, &length, tag );
1020  }
1021  else
1022  {
1023  status = readOctetStringData( stream, buffer, &length, \
1024  1, 256 );
1025  }
1026  if( cryptStatusError( status ) )
1027  return( fieldErrorReturn( errorLocus, errorType, status,
1028  attributeInfoPtr->fieldID ) );
1029 
1030  /* There are enough broken certificates out there with
1031  enormously long disclaimers in the certificate policy
1032  explicit text field that we have to specifically check for
1033  them here and truncate the text at a valid length in order to
1034  get it past the extension validity checking code */
1035  if( fieldID == CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT && \
1036  length > 200 )
1037  length = 200;
1038 
1039  /* Add the data for this attribute field, setting the payload-
1040  blob flag to disable type-checking of the payload data so
1041  that users can cram any old rubbish into the strings */
1042  return( addAttributeFieldString( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1043  fieldID, subFieldID, buffer, length,
1044  flags | ATTR_FLAG_BLOB_PAYLOAD,
1045  errorLocus, errorType ) );
1046  }
1047 
1048  case BER_OBJECT_IDENTIFIER:
1049  {
1050  BYTE oid[ MAX_OID_SIZE + 8 ];
1051 
1052  /* If it's an OID we need to reassemble the entire OID since
1053  this is the form expected by addAttributeFieldString() */
1054  oid[ 0 ] = BER_OBJECT_IDENTIFIER; /* Add skipped tag */
1055  status = readEncodedOID( stream, oid + 1, MAX_OID_SIZE - 1,
1056  &length, NO_TAG );
1057  if( cryptStatusError( status ) )
1058  return( fieldErrorReturn( errorLocus, errorType, status,
1059  attributeInfoPtr->fieldID ) );
1060  return( addAttributeFieldString( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1061  fieldID, subFieldID, oid, length + 1,
1062  flags, errorLocus, errorType ) );
1063  }
1064 
1065  case FIELDTYPE_DN:
1066  {
1067  DN_PTR *dnPtr;
1068 
1069  /* Read the DN */
1070  status = readDN( stream, &dnPtr );
1071  if( cryptStatusError( status ) )
1072  {
1073  return( fieldErrorReturn( errorLocus, errorType, status,
1074  attributeInfoPtr->fieldID ) );
1075  }
1076 
1077  /* Some buggy certificates can include zero-length DNs, which we
1078  skip */
1079  if( dnPtr == NULL )
1080  return( CRYPT_OK );
1081 
1082  /* We're being asked to instantiate the field containing the DN,
1083  create the attribute field and fill in the DN value. Since
1084  the value that we're passing in is actually a DN_PTR rather
1085  than a standard string value we set set the size field to the
1086  pseudo-length of a DN_PTR_STORAGE value to keep the static/
1087  runtime code checks happy */
1088  status = addAttributeFieldString( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1089  fieldID, subFieldID, dnPtr,
1090  sizeof( DN_PTR_STORAGE ),
1091  flags, errorLocus, errorType );
1092  if( cryptStatusError( status ) )
1093  deleteDN( &dnPtr );
1094  return( status );
1095  }
1096  }
1097 
1098  retIntError();
1099  }
1100 
1101 /* Read an attribute */
1102 
1103 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \
1104 static int readAttribute( INOUT STREAM *stream,
1105  INOUT ATTRIBUTE_LIST **attributeListPtrPtr,
1106  const ATTRIBUTE_INFO *attributeInfoPtr,
1107  IN_LENGTH_Z const int attributeLength,
1108  const BOOLEAN criticalFlag,
1109  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
1110  CRYPT_ATTRIBUTE_TYPE *errorLocus,
1111  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
1112  CRYPT_ERRTYPE_TYPE *errorType )
1113  {
1114  SETOF_STACK setofStack;
1115  SETOF_STATE_INFO *setofInfoPtr;
1116  const int maxAttributeFields = \
1117  ( attributeInfoPtr->fieldID == CRYPT_CERTINFO_AUTONOMOUSSYSIDS || \
1118  attributeInfoPtr->fieldID == CRYPT_CERTINFO_IPADDRESSBLOCKS ) ? \
1119  5 + ( attributeLength / 3 ) : min( 5 + ( attributeLength / 3 ), 256 );
1120  /* The RPKI extensions can contain vast lists of 3-4 byte entries
1121  that exceed the normal sanity-check limit */
1122  const int endPos = stell( stream ) + attributeLength;
1123  BOOLEAN attributeContinues = TRUE;
1124  int flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;
1125  int attributeFieldsProcessed = 0, status = CRYPT_OK;
1126 
1127  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1128  assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
1129  assert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );
1130  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
1131  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
1132 
1133  REQUIRES( attributeLength >= 0 && attributeLength < MAX_INTLENGTH );
1134  REQUIRES( endPos > 0 && endPos < MAX_INTLENGTH );
1135 
1136  /* Initialise the SET OF state stack */
1137  setofStackInit( &setofStack );
1138  setofInfoPtr = setofTOS( &setofStack );
1139  ENSURES( setofInfoPtr != NULL );
1140 
1141  /* Process each field in the attribute. This is a simple FSM driven by
1142  the encoding table and the data that we encounter. The various
1143  states and associated actions are indicated by the comment tags */
1144  do
1145  {
1146  int tag;
1147 
1148  /* Inside a SET/SET OF/SEQUENCE/SEQUENCE OF: Check for the end of the
1149  item/collection of items. This must be the first action taken
1150  since reaching the end of a SET/SEQUENCE pre-empts all other
1151  parsing actions */
1152  if( setofInfoPtr->endPos > 0 )
1153  {
1154  /* If we've reached the end of the collection of items, exit */
1155  status = checkSetofEnd( stream, &setofStack, &attributeInfoPtr );
1156  if( cryptStatusError( status ) && status != OK_SPECIAL )
1157  return( status );
1158  setofInfoPtr = setofTOS( &setofStack );
1159  ENSURES( setofInfoPtr != NULL );
1160  if( status == OK_SPECIAL )
1161  goto continueDecoding;
1162 
1163  /* If we're looking for a new item find the table entry that it
1164  corresponds to. This takes a pointer to the start of a set of
1165  SEQUENCE { type, value } entries and returns a pointer to the
1166  appropriate value entry.
1167 
1168  The test for the start of a new item is a bit complex since we
1169  could be at the end of the previous item (i.e. on the next item
1170  flagged as an identifier) or at the end of the attribute (i.e.
1171  on the start of the next attribute) */
1172  if( ( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTRSTART ) || \
1173  ( attributeInfoPtr->encodingFlags & FL_IDENTIFIER ) )
1174  {
1175  status = processIdentifiedItem( stream, attributeListPtrPtr,
1176  flags, &setofStack,
1177  &attributeInfoPtr,
1178  errorLocus, errorType );
1179  if( cryptStatusError( status ) )
1180  {
1181  if( status == OK_SPECIAL )
1182  {
1183  /* We've switched to a new encoding table, continue
1184  from there */
1185  status = CRYPT_OK;
1186  continue;
1187  }
1188  return( fieldErrorReturn( errorLocus, errorType,
1190  attributeInfoPtr->fieldID ) );
1191  }
1192  }
1193  }
1194 
1195  /* Subtyped field: Switch to the new encoding table */
1196  if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )
1197  {
1198  attributeInfoPtr = switchToSubtype( attributeInfoPtr,
1199  setofInfoPtr );
1200  ENSURES( attributeInfoPtr != NULL );
1201  }
1202 
1203  /* CHOICE (of object identifiers): Read a single OID from a
1204  selection defined in a subtable.
1205  Identifier field: Read a sequence of one or more { oid, value }
1206  fields and continue */
1207  if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE || \
1208  attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )
1209  {
1210  if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
1211  {
1212  const ATTRIBUTE_INFO *extraDataPtr = \
1213  attributeInfoPtr->extraData;
1214  /* Needed because ->extraData is read-only */
1215 
1216  /* This has already been verified during the startup check */
1217  ENSURES( extraDataPtr != NULL );
1218 
1219  status = readIdentifierFields( stream, attributeListPtrPtr,
1220  &extraDataPtr, flags, attributeInfoPtr->fieldID,
1221  errorLocus, errorType );
1222  }
1223  else
1224  {
1225  status = readIdentifierFields( stream, attributeListPtrPtr,
1226  &attributeInfoPtr, flags, CRYPT_ATTRIBUTE_NONE,
1227  errorLocus, errorType );
1228  }
1229  if( cryptStatusError( status ) )
1230  {
1231  return( fieldErrorReturn( errorLocus, errorType,
1233  attributeInfoPtr->fieldID ) );
1234  }
1235  if( setofInfoPtr->endPos > 0 )
1236  {
1237  /* Remember that we've seen an entry in the SET/SEQUENCE */
1238  setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1239  }
1240  goto continueDecoding;
1241  }
1242 
1243  /* Non-encoding field: Skip it and continue */
1244  if( attributeInfoPtr->encodingFlags & FL_NONENCODING )
1245  {
1246  /* Read the data and continue. We don't check its value or set
1247  specific error information for the reasons given under the SET
1248  OF handling code above (value check) and optional field code
1249  below (error locus set) */
1250  TRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );
1251  status = readUniversal( stream );
1252  if( cryptStatusError( status ) )
1253  return( status );
1254  if( setofInfoPtr->endPos > 0 )
1255  {
1256  /* Remember that we've seen an entry in the SET/SEQUENCE */
1257  setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1258  }
1259  goto continueDecoding;
1260  }
1261 
1262  /* Get the tag for the field */
1263  status = getFieldTag( stream, attributeInfoPtr, &tag );
1264  if( cryptStatusError( status ) )
1265  return( status );
1266 
1267  /* Optional field: Check whether it's present and if it isn't, move
1268  on to the next field */
1269  if( ( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) && \
1270  peekTag( stream ) != tag )
1271  {
1272  /* If it's a field with a default value, add that value. This
1273  isn't needed for cryptlib's own use since it knows the default
1274  values for fields but can cause confusion for the caller if
1275  all fields in an attribute have default values because the
1276  attribute will appear to disappear when it's read in as no
1277  fields are ever added */
1278  if( attributeInfoPtr->encodingFlags & FL_DEFAULT )
1279  {
1282 
1283  status = addAttributeField( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1284  attributeInfoPtr->fieldID,
1286  attributeInfoPtr->defaultValue,
1287  flags, &dummy1, &dummy2 );
1288  if( cryptStatusError( status ) )
1289  {
1290  /* This is a field contributed from internal data so we
1291  don't try and get an error locus or value for it
1292  since this would only confuse the caller */
1293  return( CRYPT_ERROR_BADDATA );
1294  }
1295  }
1296 
1297  /* Skip to the end of the item and continue */
1298  status = findItemEnd( &attributeInfoPtr, 0 );
1299  if( cryptStatusError( status ) )
1300  return( status );
1301 
1302  /* Since this was a (non-present) optional attribute it
1303  shouldn't be counted in the total when we continue decoding,
1304  so we adjust the fields-processed value to account for this */
1305  if( attributeFieldsProcessed > 0 )
1306  attributeFieldsProcessed--;
1307 
1308  goto continueDecoding;
1309  }
1310 
1311  /* Print a trace of what we're processing. Everything before this
1312  point does its own special-case tracing if required so we don't
1313  trace before we get here to avoid displaying duplicate/
1314  misleading information */
1315  TRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );
1316 
1317  /* Explicitly tagged field: Read the explicit wrapper and make sure
1318  that it matches what we're expecting */
1319  if( attributeInfoPtr->encodingFlags & FL_EXPLICIT )
1320  {
1321  REQUIRES( tag == MAKE_CTAG( attributeInfoPtr->fieldEncodedType ) );
1322  /* Always constructed */
1323 
1324  status = readExplicitTag( stream, attributeInfoPtr, &tag );
1325  if( cryptStatusError( status ) )
1326  return( fieldErrorReturn( errorLocus, errorType, status,
1327  attributeInfoPtr->fieldID ) );
1328  }
1329 
1330  /* Blob field or DN: We don't try and interpret blobs in any way,
1331  and DNs are a composite structure read as a complete unit by the
1332  lower-level code */
1333  if( isBlobField( attributeInfoPtr->fieldType ) || \
1334  attributeInfoPtr->fieldType == FIELDTYPE_DN )
1335  {
1336  status = readAttributeField( stream, attributeListPtrPtr,
1337  attributeInfoPtr,
1338  setofInfoPtr->subtypeParent,
1339  flags | setofInfoPtr->inheritedFlags,
1340  errorLocus, errorType );
1341  if( cryptStatusError( status ) )
1342  {
1343  /* Adding complex attributes such as DNs can return detailed
1344  error codes that report the exact parameter that was wrong,
1345  we don't need this much detail so we convert a parameter
1346  error into a more general bad data status */
1347  return( fieldErrorReturn( errorLocus, errorType,
1348  cryptArgError( status ) ? \
1349  CRYPT_ERROR_BADDATA : status,
1350  attributeInfoPtr->fieldID ) );
1351  }
1352  if( setofInfoPtr->endPos > 0 )
1353  {
1354  /* Remember that we've seen an entry in the SET/SEQUENCE */
1355  setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1356  }
1357  goto continueDecoding;
1358  }
1359 
1360  /* Standard field: Read the tag for the field and make sure that it
1361  matches what we're expecting */
1362  if( peekTag( stream ) != tag )
1363  {
1364  return( fieldErrorReturn( errorLocus, errorType,
1366  attributeInfoPtr->fieldID ) );
1367  }
1368  if( setofInfoPtr->endPos > 0 )
1369  {
1370  /* Remember that we've seen an entry in the SET/SEQUENCE */
1371  setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1372  }
1373 
1374  /* SET/SET OF/SEQUENCE/SEQUENCE OF start: Record its end position,
1375  stack the current processing state, and continue */
1376  if( attributeInfoPtr->fieldType == BER_SEQUENCE || \
1377  attributeInfoPtr->fieldType == BER_SET )
1378  {
1379  status = beginSetof( stream, &setofStack, attributeInfoPtr );
1380  if( cryptStatusError( status ) )
1381  return( fieldErrorReturn( errorLocus, errorType, status,
1382  attributeInfoPtr->fieldID ) );
1383  setofInfoPtr = setofTOS( &setofStack );
1384  ENSURES( setofInfoPtr != NULL );
1385  goto continueDecoding;
1386  }
1387  ENSURES( !( attributeInfoPtr->encodingFlags & FL_SETOF ) );
1388 
1389  /* We've checked the tag, skip it. We do this at this level rather
1390  than in readAttributeField() because it doesn't know about
1391  context-specific tagging requirements */
1392  status = readTag( stream );
1393  if( cryptStatusError( status ) )
1394  return( status );
1395 
1396  /* Standard field, read the field data */
1397  status = readAttributeField( stream, attributeListPtrPtr,
1398  attributeInfoPtr,
1399  setofInfoPtr->subtypeParent,
1400  flags | setofInfoPtr->inheritedFlags,
1401  errorLocus, errorType );
1402  if( cryptStatusError( status ) )
1403  {
1404  /* Adding invalid attribute data can return detailed error codes
1405  that report the exact parameter that was wrong, we don't
1406  need this much detail so we convert a parameter error into a
1407  more general bad data status */
1408  return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
1409  }
1410 
1411  /* Move on to the next field */
1412 continueDecoding:
1413  attributeContinues = \
1414  ( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) ? \
1415  FALSE : TRUE;
1416  attributeInfoPtr++;
1417 
1418  /* If this is the end of the attribute encoding information but we're
1419  inside a SET OF/SEQUENCE OF and there's more attribute data
1420  present, go back to the restart point and try again */
1421  if( !attributeContinues && setofInfoPtr->endPos > 0 && \
1422  stell( stream ) < setofInfoPtr->endPos )
1423  {
1424  /* If we require at least one entry in the SET OF/SEQUENCE OF
1425  but we haven't found one, this is an error */
1426  if( setofInfoPtr->flags & SETOF_FLAG_ISEMPTY )
1427  return( CRYPT_ERROR_BADDATA );
1428 
1429  /* If we haven't made any progress in processing the SET OF/
1430  SEQUENCE OF then further iterations through the loop won't
1431  make any difference, there's a bug in the decoder */
1432  ENSURES( stell( stream ) > setofInfoPtr->startPos );
1433 
1434  /* Retry from the restart point */
1435  attributeInfoPtr = setofInfoPtr->infoStart + 1;
1436  ENSURES( ( setofInfoPtr->flags & SETOF_FLAG_RESTARTPOINT ) || \
1437  attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER );
1438  attributeContinues = TRUE;
1439  }
1440  }
1441  while( ( attributeContinues || setofStack.stackPos > 1 ) && \
1442  stell( stream ) < endPos && \
1443  attributeFieldsProcessed++ < maxAttributeFields );
1444 
1445  /* If we got stuck in a loop trying to decode an attribute, complain and
1446  exit. At this point we could have encountered either a certificate-
1447  parsing error or a CRYPT_ERROR_INTERNAL internal error, since we
1448  can't tell without human intervention we treat it as a certificate
1449  error rather than throwing a retIntError() exception. This is
1450  particularly important for the CRYPT_CERTINFO_IPADDRESSBLOCKS and
1451  CRYPT_CERTINFO_AUTONOMOUSSYSIDS extensions, which are an end-run
1452  around the nonexistence of attribute certificates but turn standard
1453  certificates into arbitrary-length capability lists that exceed
1454  normal sanity-check limits */
1455  if( attributeFieldsProcessed >= maxAttributeFields )
1456  {
1457  DEBUG_DIAG(( "Processed more than %d fields in attribute, decoder "
1458  "may be stuck", maxAttributeFields ));
1459  assert( DEBUG_WARN );
1460  return( CRYPT_ERROR_BADDATA );
1461  }
1462 
1463  /* Handle the special case of (a) the encoded data ending but fields with
1464  default values being present or (b) the encoded data continuing but no
1465  more decoding information being present */
1466  if( attributeContinues )
1467  {
1468  /* If there are default fields to follow, add the default value, see
1469  the comment on the handling of default fields above for more
1470  details. For now we only add the first field since the only
1471  attributes where this case can occur have a single default value
1472  as the next possible entry, burrowing down further causes
1473  complications due to default values present in optional sequences.
1474  As usual we don't set any specific error information for the
1475  default fields */
1476  if( attributeInfoPtr->encodingFlags & FL_DEFAULT )
1477  {
1480 
1481  status = addAttributeField( ( ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1482  attributeInfoPtr->fieldID,
1484  attributeInfoPtr->defaultValue,
1485  flags, &dummy1, &dummy2 );
1486  if( cryptStatusError( status ) )
1487  return( status );
1488  }
1489  }
1490  else
1491  {
1492  int iterationCount;
1493 
1494  /* Some attributes have a SEQUENCE OF fields of no great use (e.g.
1495  Microsoft's extensive crlDistributionPoints lists providing
1496  redundant pointers to the same inaccessible site-internal
1497  servers, although these are already handled above), if there's
1498  any extraneous data left we just skip it */
1499  for( iterationCount = 0;
1500  stell( stream ) < endPos && cryptStatusOK( status ) && \
1501  iterationCount < FAILSAFE_ITERATIONS_LARGE;
1502  iterationCount++ )
1503  {
1504  DEBUG_DIAG(( "Skipping extraneous data at end of extension" ));
1505  assert( DEBUG_WARN );
1506  status = readUniversal( stream );
1507  }
1508  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
1509  }
1510 
1511  return( status );
1512  }
1513 
1514 /****************************************************************************
1515 * *
1516 * Attribute Collection Read Routines *
1517 * *
1518 ****************************************************************************/
1519 
1520 /* Read the certificate object-specific wrapper for a set of attributes */
1521 
1522 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1523 static int readAttributeWrapper( INOUT STREAM *stream,
1524  OUT_LENGTH_Z int *lengthPtr,
1525  IN_ENUM_OPT( CRYPT_CERTTYPE ) \
1526  const CRYPT_CERTTYPE_TYPE type,
1527  IN_LENGTH const int attributeLength )
1528  {
1529  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1530  assert( isWritePtr( lengthPtr, sizeof( int ) ) );
1531 
1532  REQUIRES( type >= CRYPT_CERTTYPE_NONE && type < CRYPT_CERTTYPE_LAST );
1533  /* Single CRL entries have the special-case type
1534  CRYPT_CERTTYPE_NONE */
1535  REQUIRES( attributeLength >= 0 && attributeLength < MAX_INTLENGTH );
1536 
1537  /* Clear return value */
1538  *lengthPtr = 0;
1539 
1540  /* Read the appropriate extensions tag for the certificate object and
1541  determine how far we can read. CRLs and OCSP requests/responses have
1542  two extension types that have different tagging, per-entry extensions
1543  and entire-CRL/request extensions. To differentiate between the two
1544  we read per-entry extensions with a type of CRYPT_CERTTYPE_NONE */
1545  switch( type )
1546  {
1548  readConstructed( stream, NULL, CTAG_CE_EXTENSIONS );
1549  return( readSequence( stream, lengthPtr ) );
1550 
1551  case CRYPT_CERTTYPE_CRL:
1552  readConstructed( stream, NULL, CTAG_CL_EXTENSIONS );
1553  return( readSequence( stream, lengthPtr ) );
1554 
1557  case CRYPT_CERTTYPE_NONE:
1558  /* Any outer wrapper for per-entry CRL/OCSP extensions has
1559  already been read by the caller so there's only the inner
1560  SEQUENCE left to read */
1561  return( readSequence( stream, lengthPtr ) );
1562 
1564  return( readConstructed( stream, lengthPtr,
1566 
1569  /* CRMF/CMP attributes don't contain any wrapper so there's
1570  nothing to read */
1571  *lengthPtr = attributeLength;
1572  return( CRYPT_OK );
1573 
1575  return( readSet( stream, lengthPtr ) );
1576 
1578  return( readConstructed( stream, lengthPtr, CTAG_RP_EXTENSIONS ) );
1579 
1581  readConstructed( stream, NULL, CTAG_OR_EXTENSIONS );
1582  return( readSequence( stream, lengthPtr ) );
1583 
1585  readConstructed( stream, NULL, CTAG_OP_EXTENSIONS );
1586  return( readSequence( stream, lengthPtr ) );
1587  }
1588 
1589  retIntError();
1590  }
1591 
1592 #ifdef USE_CERTREQ
1593 
1594 /* Read a PKCS #10 certificate request wrapper for a set of attributes.
1595  This isn't as simple as it should be because there are two approaches to
1596  adding extensions to a request, the PKCS #10 approach which puts them all
1597  inside a PKCS #9 extensionRequest attribute and the SET approach which
1598  lists them all individually (CRMF is a separate case handled by
1599  readAttributeWrapper() above). In addition Microsoft invented their own
1600  incompatible version of the PKCS #9 extensionRequest which is exactly
1601  the same as the PKCS #9 one but with a MS OID, however they also invented
1602  other values to add containing God knows what sort of data (long Unicode
1603  strings describing the Windows module that created it (as if you'd need
1604  that to know where it came from), the scripts from "Gilligan's Island",
1605  every "Brady Bunch" episode ever made, dust from under somebody's bed
1606  from the 1930s, etc). Because of this, the following code skips over
1607  unknown garbage until it finds a valid extension. Since all attributes
1608  may be either skipped or processed at this stage we include provisions
1609  for bailing out if we exhaust the available attributes */
1610 
1611 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 6 ) ) \
1612 static int readCertReqWrapper( INOUT STREAM *stream,
1613  INOUT ATTRIBUTE_LIST **attributeListPtrPtr,
1614  OUT_LENGTH_Z int *lengthPtr,
1615  IN_LENGTH const int attributeLength,
1616  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
1617  CRYPT_ATTRIBUTE_TYPE *errorLocus,
1618  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
1619  CRYPT_ERRTYPE_TYPE *errorType )
1620  {
1621  const int endPos = stell( stream ) + attributeLength;
1622  int attributesProcessed, status;
1623 
1624  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1625  assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
1626  assert( isWritePtr( lengthPtr, sizeof( int ) ) );
1627  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
1628  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
1629 
1630  REQUIRES( attributeLength >= 0 && attributeLength < MAX_INTLENGTH );
1631  REQUIRES( endPos > 0 && endPos < MAX_INTLENGTH );
1632 
1633  /* Clear return value */
1634  *lengthPtr = 0;
1635 
1636  for( attributesProcessed = 0; attributesProcessed < 16; \
1637  attributesProcessed++ )
1638  {
1639 #ifdef USE_CERT_OBSOLETE
1640  const ATTRIBUTE_INFO *attributeInfoPtr;
1641 #endif /* USE_CERT_OBSOLETE */
1642  BYTE oid[ MAX_OID_SIZE + 8 ];
1643  int oidLength;
1644 
1645  /* If we've run out of attributes without finding anything useful,
1646  exit */
1647  if( stell( stream ) > endPos - MIN_ATTRIBUTE_SIZE )
1648  return( CRYPT_OK );
1649 
1650  /* Read the wrapper SEQUENCE and OID */
1651  readSequence( stream, NULL );
1652  status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength,
1654  if( cryptStatusError( status ) )
1655  return( status );
1656 
1657 #ifdef USE_CERT_OBSOLETE
1658  /* Check for a known attribute, which can happen with SET
1659  certificate requests. If it's a known attribute, process it */
1660  attributeInfoPtr = oidToAttribute( ATTRIBUTE_CERTIFICATE,
1661  oid, oidLength );
1662  if( attributeInfoPtr != NULL )
1663  {
1664  status = readSet( stream, lengthPtr );
1665  if( cryptStatusOK( status ) )
1666  {
1667  status = readAttribute( stream, attributeListPtrPtr,
1668  attributeInfoPtr, *lengthPtr, FALSE,
1669  errorLocus, errorType );
1670  }
1671  if( cryptStatusError( status ) )
1672  return( status );
1673  }
1674  else
1675 #endif /* USE_CERT_OBSOLETE */
1676  {
1677  /* It's not a known attribute, check whether it's a CRMF or MS
1678  wrapper attribute */
1679  if( !memcmp( oid, OID_PKCS9_EXTREQ, oidLength ) || \
1680  !memcmp( oid, OID_MS_EXTREQ, oidLength ) )
1681  {
1682  /* Skip the wrapper to reveal the encapsulated attributes */
1683  readSet( stream, NULL );
1684  return( readSequence( stream, lengthPtr ) );
1685  }
1686 
1687  /* It's unknown MS garbage, skip it */
1688  status = readUniversal( stream );
1689  if( cryptStatusError( status ) )
1690  return( status );
1691  }
1692  }
1693 
1694  /* As with the check in readAttribute() above this could be either a
1695  certificate-parsing error or a CRYPT_ERROR_INTERNAL internal error,
1696  since we can't tell without human intervention we treat it as a
1697  certificate error rather than throwing a retIntError() exception */
1698  DEBUG_DIAG(( "Unknown certificate request wrapper type encountered" ));
1699  assert( DEBUG_WARN );
1700  return( CRYPT_ERROR_BADDATA );
1701  }
1702 #endif /* USE_CERTREQ */
1703 
1704 /* Read a set of attributes */
1705 
1706 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 6 ) ) \
1707 int readAttributes( INOUT STREAM *stream,
1708  INOUT ATTRIBUTE_PTR **attributeListPtrPtr,
1709  IN_ENUM_OPT( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,
1710  IN_LENGTH_Z const int attributeLength,
1711  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
1712  CRYPT_ATTRIBUTE_TYPE *errorLocus,
1713  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
1714  CRYPT_ERRTYPE_TYPE *errorType )
1715  {
1717  type == CRYPT_CERTTYPE_RTCS_REQUEST || \
1718  type == CRYPT_CERTTYPE_RTCS_RESPONSE ) ? \
1720  const BOOLEAN wrapperTagSet = ( attributeType == ATTRIBUTE_CMS ) ? \
1721  TRUE : FALSE;
1722  int length, endPos, complianceLevel, iterationCount, status;
1723 
1724  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1725  assert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );
1726  assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
1727  assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );
1728 
1729  REQUIRES( type >= CRYPT_CERTTYPE_NONE && type < CRYPT_CERTTYPE_LAST );
1730  /* Single CRL entries have the special-case type
1731  CRYPT_CERTTYPE_NONE */
1732  REQUIRES( ( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES && \
1733  attributeLength == 0 ) || \
1734  ( type != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \
1735  attributeLength >= 0 && attributeLength < MAX_INTLENGTH ) );
1736  /* CMS attributes are pure attribute data with no
1737  encapsulation to indicate the length so the length is
1738  implicitly "everything that's present" */
1739 
1741  IMESSAGE_GETATTRIBUTE, &complianceLevel,
1743  if( cryptStatusError( status ) )
1744  return( status );
1745 
1746  /* Read the wrapper for the certificate object's attributes and
1747  determine how far we can read */
1748 #ifdef USE_CERTREQ
1749  if( type == CRYPT_CERTTYPE_CERTREQUEST )
1750  {
1751  status = readCertReqWrapper( stream,
1752  ( ATTRIBUTE_LIST ** ) attributeListPtrPtr,
1753  &length, attributeLength, errorLocus,
1754  errorType );
1755  }
1756  else
1757 #endif /* USE_CERTREQ */
1758  status = readAttributeWrapper( stream, &length, type, attributeLength );
1759  if( cryptStatusError( status ) )
1760  return( status );
1761  endPos = stell( stream ) + length;
1762 
1763  /* Read the collection of attributes. We allow for a bit of slop for
1764  software that gets the length encoding wrong by a few bytes */
1765  TRACE_DEBUG(( "\nReading attributes for certificate object starting at "
1766  "offset %d.", stell( stream ) ));
1767  for( iterationCount = 0;
1768  stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE && \
1769  iterationCount < FAILSAFE_ITERATIONS_LARGE;
1770  iterationCount++ )
1771  {
1772  const ATTRIBUTE_INFO *attributeInfoPtr;
1773  BYTE oid[ MAX_OID_SIZE + 8 ];
1774  BOOLEAN criticalFlag = FALSE, ignoreAttribute = FALSE;
1775  void *attributeDataPtr;
1776  int oidLength, attributeDataLength;
1777 
1778  /* Read the outer wrapper and determine the attribute type based on
1779  the OID */
1780  readSequence( stream, NULL );
1781  status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength,
1783  if( cryptStatusError( status ) )
1784  {
1785  TRACE_DEBUG(( "Couldn't read attribute OID, status %d.",
1786  status ));
1787  return( status );
1788  }
1789  attributeInfoPtr = oidToAttribute( attributeType, oid, oidLength );
1790  if( attributeInfoPtr != NULL && \
1791  complianceLevel < decodeComplianceLevel( attributeInfoPtr->typeInfoFlags ) )
1792  {
1793  /* If we're running at a lower compliance level than that
1794  required for the attribute, ignore it by treating it as a
1795  blob-type attribute */
1796  TRACE_DEBUG(( "Reading %s (%d) as a blob.",
1797  attributeInfoPtr->description,
1798  attributeInfoPtr->fieldID ));
1799  attributeInfoPtr = NULL;
1800  ignoreAttribute = TRUE;
1801  }
1802 
1803  /* Read the optional critical flag if it's a certificate. If the
1804  extension is marked critical and we don't recognise it we don't
1805  reject it at this point because that'd make it impossible to
1806  examine the contents of the certificate or display it to the
1807  user. Instead we reject the certificate when we try and check
1808  it */
1809  if( attributeType != ATTRIBUTE_CMS && \
1810  peekTag( stream ) == BER_BOOLEAN )
1811  {
1812  status = readBoolean( stream, &criticalFlag );
1813  if( cryptStatusError( status ) )
1814  {
1815  *errorLocus = ( attributeInfoPtr != NULL ) ? \
1816  attributeInfoPtr->fieldID : CRYPT_ATTRIBUTE_NONE;
1817  *errorType = CRYPT_ERRTYPE_ATTR_VALUE;
1818  return( status );
1819  }
1820  }
1821 
1822  /* Read the wrapper around the attribute payload */
1823  if( wrapperTagSet )
1824  status = readSet( stream, &attributeDataLength );
1825  else
1826  status = readOctetStringHole( stream, &attributeDataLength, 2,
1827  DEFAULT_TAG );
1828  if( cryptStatusError( status ) )
1829  {
1830  *errorLocus = ( attributeInfoPtr != NULL ) ? \
1831  attributeInfoPtr->fieldID : CRYPT_ATTRIBUTE_NONE;
1832  *errorType = CRYPT_ERRTYPE_ATTR_VALUE;
1833  TRACE_DEBUG(( "Couldn't read attribute wrapper for %s, status %d.",
1834  ( attributeInfoPtr->description != NULL ) ? \
1835  attributeInfoPtr->description : \
1836  "(unrecognised blob attribute)", status ));
1837  return( status );
1838  }
1839 
1840  /* If it's a known attribute, parse the payload */
1841  if( attributeInfoPtr != NULL )
1842  {
1843  status = readAttribute( stream,
1844  ( ATTRIBUTE_LIST ** ) attributeListPtrPtr,
1845  attributeInfoPtr, attributeDataLength,
1846  criticalFlag, errorLocus, errorType );
1847  if( cryptStatusError( status ) )
1848  {
1849  TRACE_DEBUG(( "Error %d reading %s attribute.", status,
1850  ( attributeInfoPtr->description != NULL ) ? \
1851  attributeInfoPtr->description : \
1852  "(unrecognised blob attribute)" ));
1853  return( status );
1854  }
1855  continue;
1856  }
1857 
1858  /* If it's a zero-length unrecognised attribute, don't add anything.
1859  A zero length indicates that the attribute contains all default
1860  values, however since we don't recognise the attribute we can't
1861  fill these in so the attribute is in effect not present */
1862  if( attributeDataLength <= 0 )
1863  continue;
1864 
1865  /* It's an unrecognised or ignored attribute type, add the raw data
1866  to the list of attributes */
1867  status = sMemGetDataBlock( stream, &attributeDataPtr,
1868  attributeDataLength );
1869  if( cryptStatusOK( status ) )
1870  {
1871  ANALYSER_HINT( attributeDataPtr != NULL );
1872  status = addAttribute( attributeType, attributeListPtrPtr,
1873  oid, oidLength, criticalFlag,
1874  attributeDataPtr, attributeDataLength,
1875  ignoreAttribute ? \
1877  ATTR_FLAG_BLOB );
1878  }
1879  if( cryptStatusError( status ) )
1880  {
1881  if( status == CRYPT_ERROR_INITED )
1882  {
1883  /* If there's a duplicate attribute present, set error
1884  information for it and flag it as a bad data error. We
1885  can't set an error locus since it's an unknown blob */
1886  *errorLocus = CRYPT_ATTRIBUTE_NONE;
1887  *errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
1888  status = CRYPT_ERROR_BADDATA;
1889  }
1890  TRACE_DEBUG(( "Error %d adding unrecognised blob attribute data.",
1891  status ));
1892  return( status );
1893  }
1894  sSkip( stream, attributeDataLength ); /* Skip the attribute data */
1895  }
1896  ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
1897  TRACE_DEBUG(( "Finished reading attributes for certificate object ending at "
1898  "offset %d.\n", stell( stream ) ));
1899 
1900  return( CRYPT_OK );
1901  }
1902 #endif /* USE_CERTIFICATES */