23 #if !defined( NDEBUG ) && 0
24 #if defined( _MSC_VER )
25 #pragma warning( disable: 4127 )
27 #define TRACE_FIELDTYPE( attributeInfoPtr, stackPos ) \
31 DEBUG_PRINT(( "%4d:", stell( stream ) )); \
32 for( i = 0; i < stackPos; i++ ) \
33 DEBUG_PRINT(( " " )); \
34 if( ( attributeInfoPtr ) != NULL && \
35 ( attributeInfoPtr )->description != NULL ) \
37 DEBUG_PRINT(( ( attributeInfoPtr )->description )); \
38 DEBUG_PRINT(( "\n" )); \
42 DEBUG_PRINT(( "<Unknown field>\n" )); \
45 #define TRACE_DEBUG( message ) \
46 DEBUG_PRINT( message ); \
47 DEBUG_PRINT(( "\n" ));
49 #define TRACE_FIELDTYPE( attributeInfoPtr, stackPos )
50 #define TRACE_DEBUG( message )
53 #ifdef USE_CERTIFICATES
81 status = value = getFieldEncodedTag( attributeInfoPtr );
103 static const int allowedStringTypes[] = {
114 status = value = peekTag( stream );
117 for( i = 0; allowedStringTypes[ i ] != value && \
143 ( value > 0 && value <=
MAX_TAG ) );
174 status = readConstructed( stream, NULL,
197 int currentDepth = depth, iterationCount;
202 REQUIRES( depth >= 0 && depth < 3 );
207 for( attributeInfoPtr = *attributeInfoPtrPtr, iterationCount = 0;
210 attributeInfoPtr++, iterationCount++ )
218 if( currentDepth <= 0 )
226 *attributeInfoPtrPtr = attributeInfoPtr;
240 #define SETOF_STATE_STACKSIZE 16
242 #define SETOF_FLAG_NONE 0x00
243 #define SETOF_FLAG_SUBTYPED 0x01
244 #define SETOF_FLAG_RESTARTPOINT 0x02
245 #define SETOF_FLAG_ISEMPTY 0x04
259 ARRAY( SETOF_STATE_STACKSIZE, stackPos ) \
260 SETOF_STATE_INFO
stateInfo[ SETOF_STATE_STACKSIZE + 8 ];
265 static
void setofStackInit(
OUT SETOF_STACK *setofStack )
267 assert(
isWritePtr( setofStack,
sizeof( SETOF_STACK ) ) );
269 memset( setofStack, 0,
sizeof( SETOF_STACK ) );
273 static
BOOLEAN setofStackPush(
INOUT SETOF_STACK *setofStack )
275 assert(
isWritePtr( setofStack,
sizeof( SETOF_STACK ) ) );
278 if( setofStack->stackPos < 0 || \
279 setofStack->stackPos >= SETOF_STATE_STACKSIZE - 1 )
281 setofStack->stackPos++;
282 ENSURES_B( setofStack->stackPos >= 1 && \
283 setofStack->stackPos < SETOF_STATE_STACKSIZE );
286 memset( &setofStack->stateInfo[ setofStack->stackPos ], 0, \
287 sizeof( SETOF_STATE_INFO ) );
293 static
BOOLEAN setofStackPop(
INOUT SETOF_STACK *setofStack )
295 assert(
isWritePtr( setofStack,
sizeof( SETOF_STACK ) ) );
298 if( setofStack->stackPos <= 0 || \
299 setofStack->stackPos >= SETOF_STATE_STACKSIZE )
301 setofStack->stackPos--;
302 ENSURES_B( setofStack->stackPos >= 0 && \
303 setofStack->stackPos < SETOF_STATE_STACKSIZE - 1 );
309 static SETOF_STATE_INFO *setofTOS(
const SETOF_STACK *setofStack )
311 assert(
isReadPtr( setofStack,
sizeof( SETOF_STACK ) ) );
313 ENSURES_N( setofStack->stackPos >= 0 && \
314 setofStack->stackPos < SETOF_STATE_STACKSIZE );
316 return( ( SETOF_STATE_INFO * ) \
317 &setofStack->stateInfo[ setofStack->stackPos ] );
324 INOUT SETOF_STACK *setofStack,
327 SETOF_STATE_INFO *setofInfoPtr;
329 int oldInheritedFlags, setofLength,
status;
332 assert(
isWritePtr( setofStack,
sizeof( SETOF_STACK ) ) );
341 status = readConstructed( stream, &setofLength,
347 status = readSet( stream, &setofLength );
349 status = readSequence( stream, &setofLength );
357 if( setofLength <= 0 )
364 setofInfoPtr = setofTOS( setofStack );
365 ENSURES( setofInfoPtr != NULL );
366 oldSubtypeParent = setofInfoPtr->subtypeParent;
367 oldInheritedFlags = setofInfoPtr->inheritedFlags;
368 if( !setofStackPush( setofStack ) )
373 setofInfoPtr = setofTOS( setofStack );
374 ENSURES( setofInfoPtr != NULL );
375 setofInfoPtr->infoStart = attributeInfoPtr;
377 setofInfoPtr->flags |= SETOF_FLAG_RESTARTPOINT;
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;
392 static
int checkSetofEnd(
const STREAM *stream,
393 INOUT SETOF_STACK *setofStack,
396 const SETOF_STATE_INFO *setofInfoPtr = setofTOS( setofStack );
399 const int currentPos = stell( stream );
403 assert(
isWritePtr( setofStack,
sizeof( SETOF_STACK ) ) );
411 if( setofStack->stackPos <= 0 || currentPos < setofInfoPtr->
endPos )
416 for( iterationCount = 0;
417 setofStack->stackPos > 0 && \
418 currentPos >= setofInfoPtr->endPos && \
419 iterationCount < SETOF_STATE_STACKSIZE;
422 const int flags = setofInfoPtr->flags;
425 if( !setofStackPop( setofStack ) )
430 setofInfoPtr = setofTOS( setofStack );
431 ENSURES( setofInfoPtr != NULL );
432 attributeInfoPtr = setofInfoPtr->infoStart;
433 ENSURES( setofInfoPtr->endPos > 0 && \
439 if( !( flags & SETOF_FLAG_RESTARTPOINT ) && \
440 currentPos >= setofInfoPtr->endPos )
444 status = findItemEnd( &attributeInfoPtr, 0 );
449 ENSURES( iterationCount < SETOF_STATE_STACKSIZE );
451 *attributeInfoPtrPtr = attributeInfoPtr;
452 return( ( attributeInfoPtr != oldAttributeInfoPtr ) ? \
482 readSequence( stream, &sequenceLength );
483 status = readEncodedOID( stream, oid,
MAX_OID_SIZE, &oidLength,
494 for( iterationCount = 0;
505 oidPtr = attributeInfoPtr->
oid;
517 if( sequenceLength > 0 )
519 status = sSkip( stream, sequenceLength );
523 return( attributeInfoPtr );
529 if( oidLength ==
sizeofOID( oidPtr ) && \
530 !memcmp( oidPtr, oid,
sizeofOID( oidPtr ) ) )
537 status = sSkip( stream, sequenceLength );
542 return( attributeInfoPtr );
548 status = findItemEnd( &attributeInfoPtr, 1 );
560 static
int processIdentifiedItem(
INOUT STREAM *stream,
563 const SETOF_STACK *setofStack,
570 const SETOF_STATE_INFO *setofInfoPtr = setofTOS( setofStack );
575 assert(
isReadPtr( setofStack,
sizeof( SETOF_STACK ) ) );
589 attributeInfoPtr = findIdentifiedItem( stream,
590 setofInfoPtr->infoStart + 1 );
591 if( attributeInfoPtr == NULL )
593 *attributeInfoPtrPtr = attributeInfoPtr;
627 status = addAttributeField( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
630 flags, errorLocus, errorType );
638 *attributeInfoPtrPtr = setofInfoPtr->infoStart + 1;
648 static
int readIdentifierFields(
INOUT STREAM *stream,
660 int count = 0, iterationCount;
672 for( iterationCount = 0;
686 attributeInfoPtr->
oid != NULL );
691 status = readEncodedOID( stream, oid,
MAX_OID_SIZE, &oidLength,
695 for( innerIterationCount = 0;
697 memcmp( attributeInfoPtr->
oid, oid, oidLength ) ) && \
698 innerIterationCount < FAILSAFE_ITERATIONS_MED;
699 innerIterationCount++ )
723 attributeInfoPtr->
oid != NULL );
725 ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_MED );
737 status = addAttributeField( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
740 flags, errorLocus, errorType );
745 status = addAttributeField( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
749 errorLocus, errorType );
757 if( isChoice && count > 1 )
759 *errorLocus = attributeInfoPtr->
fieldID,
764 ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
773 for( attributeInfoPtr = *attributeInfoPtrPtr, iterationCount = 0;
777 attributeInfoPtr++, iterationCount++ );
778 ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
779 *attributeInfoPtrPtr = attributeInfoPtr;
793 static
int fieldErrorReturn(
OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
823 INOUT SETOF_STATE_INFO *setofInfoPtr )
828 assert(
isWritePtr( setofInfoPtr,
sizeof( SETOF_STATE_INFO ) ) );
834 setofInfoPtr->subtypeParent = attributeInfoPtr->
fieldID;
835 setofInfoPtr->inheritedFlags = \
843 setofInfoPtr->flags |= SETOF_FLAG_ISEMPTY;
849 setofInfoPtr->flags |= SETOF_FLAG_SUBTYPED;
861 static
int readAttributeField(
INOUT STREAM *stream,
873 const int fieldType = attributeInfoPtr->
fieldType;
892 fieldID = attributeInfoPtr->
fieldID;
897 fieldID = subtypeParent;
898 subFieldID = attributeInfoPtr->
fieldID;
937 value = ( int ) longValue;
952 return( fieldErrorReturn( errorLocus, errorType, status,
956 return( addAttributeField( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
957 fieldID, subFieldID, value, flags,
958 errorLocus, errorType ) );
971 return( fieldErrorReturn( errorLocus, errorType, status,
975 return( addAttributeFieldString( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
976 fieldID, subFieldID, &timeVal,
977 sizeof( time_t ), flags,
978 errorLocus, errorType ) );
1013 status = tag = peekTag( stream );
1016 return( fieldErrorReturn( errorLocus, errorType, status,
1017 attributeInfoPtr->
fieldID ) );
1019 status = readRawObject( stream, buffer, 256, &length, tag );
1027 return( fieldErrorReturn( errorLocus, errorType, status,
1028 attributeInfoPtr->
fieldID ) );
1042 return( addAttributeFieldString( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1043 fieldID, subFieldID, buffer, length,
1045 errorLocus, errorType ) );
1055 status = readEncodedOID( stream, oid + 1,
MAX_OID_SIZE - 1,
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 ) );
1070 status = readDN( stream, &dnPtr );
1073 return( fieldErrorReturn( errorLocus, errorType, status,
1074 attributeInfoPtr->
fieldID ) );
1088 status = addAttributeFieldString( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1089 fieldID, subFieldID, dnPtr,
1091 flags, errorLocus, errorType );
1114 SETOF_STACK setofStack;
1115 SETOF_STATE_INFO *setofInfoPtr;
1116 const int maxAttributeFields = \
1119 5 + ( attributeLength / 3 ) :
min( 5 + ( attributeLength / 3 ), 256 );
1125 int attributeFieldsProcessed = 0, status =
CRYPT_OK;
1137 setofStackInit( &setofStack );
1138 setofInfoPtr = setofTOS( &setofStack );
1139 ENSURES( setofInfoPtr != NULL );
1152 if( setofInfoPtr->endPos > 0 )
1155 status = checkSetofEnd( stream, &setofStack, &attributeInfoPtr );
1158 setofInfoPtr = setofTOS( &setofStack );
1159 ENSURES( setofInfoPtr != NULL );
1161 goto continueDecoding;
1175 status = processIdentifiedItem( stream, attributeListPtrPtr,
1178 errorLocus, errorType );
1188 return( fieldErrorReturn( errorLocus, errorType,
1190 attributeInfoPtr->
fieldID ) );
1198 attributeInfoPtr = switchToSubtype( attributeInfoPtr,
1200 ENSURES( attributeInfoPtr != NULL );
1217 ENSURES( extraDataPtr != NULL );
1219 status = readIdentifierFields( stream, attributeListPtrPtr,
1220 &extraDataPtr, flags, attributeInfoPtr->
fieldID,
1221 errorLocus, errorType );
1225 status = readIdentifierFields( stream, attributeListPtrPtr,
1227 errorLocus, errorType );
1231 return( fieldErrorReturn( errorLocus, errorType,
1233 attributeInfoPtr->
fieldID ) );
1235 if( setofInfoPtr->endPos > 0 )
1238 setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1240 goto continueDecoding;
1251 status = readUniversal( stream );
1254 if( setofInfoPtr->endPos > 0 )
1257 setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1259 goto continueDecoding;
1263 status = getFieldTag( stream, attributeInfoPtr, &tag );
1270 peekTag( stream ) != tag )
1283 status = addAttributeField( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1287 flags, &dummy1, &dummy2 );
1298 status = findItemEnd( &attributeInfoPtr, 0 );
1305 if( attributeFieldsProcessed > 0 )
1306 attributeFieldsProcessed--;
1308 goto continueDecoding;
1324 status = readExplicitTag( stream, attributeInfoPtr, &tag );
1326 return( fieldErrorReturn( errorLocus, errorType, status,
1327 attributeInfoPtr->
fieldID ) );
1336 status = readAttributeField( stream, attributeListPtrPtr,
1338 setofInfoPtr->subtypeParent,
1339 flags | setofInfoPtr->inheritedFlags,
1340 errorLocus, errorType );
1347 return( fieldErrorReturn( errorLocus, errorType,
1350 attributeInfoPtr->
fieldID ) );
1352 if( setofInfoPtr->endPos > 0 )
1355 setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1357 goto continueDecoding;
1362 if( peekTag( stream ) != tag )
1364 return( fieldErrorReturn( errorLocus, errorType,
1366 attributeInfoPtr->
fieldID ) );
1368 if( setofInfoPtr->endPos > 0 )
1371 setofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;
1379 status = beginSetof( stream, &setofStack, attributeInfoPtr );
1381 return( fieldErrorReturn( errorLocus, errorType, status,
1382 attributeInfoPtr->
fieldID ) );
1383 setofInfoPtr = setofTOS( &setofStack );
1384 ENSURES( setofInfoPtr != NULL );
1385 goto continueDecoding;
1392 status = readTag( stream );
1397 status = readAttributeField( stream, attributeListPtrPtr,
1399 setofInfoPtr->subtypeParent,
1400 flags | setofInfoPtr->inheritedFlags,
1401 errorLocus, errorType );
1413 attributeContinues = \
1421 if( !attributeContinues && setofInfoPtr->endPos > 0 && \
1422 stell( stream ) < setofInfoPtr->endPos )
1426 if( setofInfoPtr->flags & SETOF_FLAG_ISEMPTY )
1432 ENSURES( stell( stream ) > setofInfoPtr->startPos );
1435 attributeInfoPtr = setofInfoPtr->infoStart + 1;
1436 ENSURES( ( setofInfoPtr->flags & SETOF_FLAG_RESTARTPOINT ) || \
1438 attributeContinues =
TRUE;
1441 while( ( attributeContinues || setofStack.stackPos > 1 ) && \
1442 stell( stream ) < endPos && \
1443 attributeFieldsProcessed++ < maxAttributeFields );
1455 if( attributeFieldsProcessed >= maxAttributeFields )
1457 DEBUG_DIAG((
"Processed more than %d fields in attribute, decoder "
1458 "may be stuck", maxAttributeFields ));
1466 if( attributeContinues )
1481 status = addAttributeField( (
ATTRIBUTE_PTR ** ) attributeListPtrPtr,
1485 flags, &dummy1, &dummy2 );
1499 for( iterationCount = 0;
1504 DEBUG_DIAG((
"Skipping extraneous data at end of extension" ));
1506 status = readUniversal( stream );
1508 ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
1523 static
int readAttributeWrapper(
INOUT STREAM *stream,
1530 assert(
isWritePtr( lengthPtr,
sizeof(
int ) ) );
1549 return( readSequence( stream, lengthPtr ) );
1553 return( readSequence( stream, lengthPtr ) );
1561 return( readSequence( stream, lengthPtr ) );
1564 return( readConstructed( stream, lengthPtr,
1575 return( readSet( stream, lengthPtr ) );
1582 return( readSequence( stream, lengthPtr ) );
1586 return( readSequence( stream, lengthPtr ) );
1612 static
int readCertReqWrapper(
INOUT STREAM *stream,
1622 int attributesProcessed,
status;
1626 assert(
isWritePtr( lengthPtr,
sizeof(
int ) ) );
1636 for( attributesProcessed = 0; attributesProcessed < 16; \
1637 attributesProcessed++ )
1639 #ifdef USE_CERT_OBSOLETE
1651 readSequence( stream, NULL );
1652 status = readEncodedOID( stream, oid,
MAX_OID_SIZE, &oidLength,
1657 #ifdef USE_CERT_OBSOLETE
1662 if( attributeInfoPtr != NULL )
1664 status = readSet( stream, lengthPtr );
1667 status = readAttribute( stream, attributeListPtrPtr,
1668 attributeInfoPtr, *lengthPtr,
FALSE,
1669 errorLocus, errorType );
1683 readSet( stream, NULL );
1684 return( readSequence( stream, lengthPtr ) );
1688 status = readUniversal( stream );
1698 DEBUG_DIAG((
"Unknown certificate request wrapper type encountered" ));
1733 attributeLength == 0 ) || \
1735 attributeLength >= 0 && attributeLength <
MAX_INTLENGTH ) );
1751 status = readCertReqWrapper( stream,
1753 &length, attributeLength, errorLocus,
1758 status = readAttributeWrapper( stream, &length, type, attributeLength );
1761 endPos = stell( stream ) +
length;
1765 TRACE_DEBUG((
"\nReading attributes for certificate object starting at "
1766 "offset %d.", stell( stream ) ));
1767 for( iterationCount = 0;
1775 void *attributeDataPtr;
1780 readSequence( stream, NULL );
1781 status = readEncodedOID( stream, oid,
MAX_OID_SIZE, &oidLength,
1785 TRACE_DEBUG((
"Couldn't read attribute OID, status %d.",
1789 attributeInfoPtr = oidToAttribute( attributeType, oid, oidLength );
1790 if( attributeInfoPtr != NULL && \
1799 attributeInfoPtr = NULL;
1800 ignoreAttribute =
TRUE;
1815 *errorLocus = ( attributeInfoPtr != NULL ) ? \
1824 status = readSet( stream, &attributeDataLength );
1826 status = readOctetStringHole( stream, &attributeDataLength, 2,
1830 *errorLocus = ( attributeInfoPtr != NULL ) ? \
1833 TRACE_DEBUG((
"Couldn't read attribute wrapper for %s, status %d.",
1836 "(unrecognised blob attribute)", status ));
1841 if( attributeInfoPtr != NULL )
1843 status = readAttribute( stream,
1845 attributeInfoPtr, attributeDataLength,
1846 criticalFlag, errorLocus, errorType );
1849 TRACE_DEBUG((
"Error %d reading %s attribute.", status,
1852 "(unrecognised blob attribute)" ));
1862 if( attributeDataLength <= 0 )
1867 status = sMemGetDataBlock( stream, &attributeDataPtr,
1868 attributeDataLength );
1872 status = addAttribute( attributeType, attributeListPtrPtr,
1873 oid, oidLength, criticalFlag,
1874 attributeDataPtr, attributeDataLength,
1890 TRACE_DEBUG((
"Error %d adding unrecognised blob attribute data.",
1894 sSkip( stream, attributeDataLength );
1896 ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
1897 TRACE_DEBUG((
"Finished reading attributes for certificate object ending at "
1898 "offset %d.\n", stell( stream ) ));