30 #define selectTag( tag, defaultTag ) \
31 ( ( ( tag ) == DEFAULT_TAG ) ? ( defaultTag ) : \
32 ( MAKE_CTAG_PRIMITIVE( tag ) ) )
60 int noLengthOctets, i,
status;
63 assert(
isWritePtr( length,
sizeof(
long ) ) );
72 status = dataLength = sgetc( stream );
75 if( !( dataLength & 0x80 ) )
82 noLengthOctets = dataLength & 0x7F;
83 if( noLengthOctets <= 0 )
95 if( noLengthOctets > 8 )
97 status = sread( stream, buffer, noLengthOctets );
106 if( buffer[ 0 ] == 0 )
109 for( i = 0; i < noLengthOctets && buffer[ i ] == 0; i++ );
111 if( noLengthOctets <= 0 )
117 if( noLengthOctets < 0 || noLengthOctets > ( shortLen ? 2 : 4 ) )
121 for( dataLength = 0, i = 0; i < noLengthOctets; i++ )
123 const long dataLenTmp = dataLength << 8;
132 dataLength = dataLenTmp |
data;
141 if( dataLength & 0xFFFF8000UL || dataLength > 32767L )
149 if( ( dataLength & 0x80000000UL ) || dataLength >=
MAX_INTLENGTH )
155 if( dataLength <= 0 )
170 static
int readIntegerHeader(
INOUT STREAM *stream,
174 int noLeadingZeroes,
status;
196 for( noLeadingZeroes = 0;
197 noLeadingZeroes < length && noLeadingZeroes < 8 && \
198 sPeek( stream ) == 0;
201 status = sgetc( stream );
206 if( noLeadingZeroes >= 8 )
209 return( length - noLeadingZeroes );
222 assert( value == NULL ||
isWritePtr( value,
sizeof(
long ) ) );
229 status = length = readIntegerHeader( stream,
NO_TAG );
238 status = sread( stream, buffer, length );
241 for( localValue = 0, i = 0; i <
length; i++ )
243 const long localValTmp = localValue << 8;
252 localValue = localValTmp |
data;
267 static
int readConstrainedData(
INOUT STREAM *stream,
277 assert( buffer == NULL ||
isWritePtr( buffer, length ) );
278 assert(
isWritePtr( bufferLength,
sizeof(
int ) ) );
289 return( sSkip( stream, dataLength ) );
292 if( dataLength > bufferMaxLength )
294 remainder = dataLength - bufferMaxLength;
295 dataLength = bufferMaxLength;
298 status = sread( stream, buffer, dataLength );
307 return( sSkip( stream, remainder ) );
323 if( tag <= 0 || tag >
MAX_TAG )
346 tag = sgetc( stream );
349 if( !checkTag( tag ) )
360 tag = sPeek( stream );
363 if( !checkTag( tag ) )
376 BYTE eocBuffer[ 2 + 8 ];
383 tag = sPeek( stream );
388 status = sread( stream, eocBuffer, 2 );
391 if( memcmp( eocBuffer,
"\x00\x00", 2 ) )
414 assert(
isWritePtr( buffer, bufferMaxLength ) );
415 assert(
isWritePtr( bufferLength,
sizeof(
int ) ) );
425 memset( buffer, 0,
min( 16, bufferMaxLength ) );
436 const int objectTag = readTag( stream );
439 if( tag != objectTag )
441 buffer[ offset++ ] = objectTag;
443 length = sgetc( stream );
446 buffer[ offset++ ] =
length;
454 length = sgetc( stream );
457 buffer[ offset++ ] =
length;
459 if( length <= 0 || length > 0xFF )
461 if( offset + length > bufferMaxLength )
471 *bufferLength = offset +
length;
472 return( sread( stream, buffer + offset, length ) );
488 assert( integer == NULL ||
isWritePtr( integer, integerMaxLength ) );
489 assert( integerLength == NULL || \
498 if( integer != NULL )
499 memset( integer, 0,
min( 16, integerMaxLength ) );
500 if( integerLength != NULL )
504 status = length = readIntegerHeader( stream, tag );
514 status = readConstrainedData( stream, integer, integerMaxLength,
515 &localIntegerLength, length );
517 *integerLength = localIntegerLength;
526 static
int readBignumInteger(
INOUT STREAM *stream,
542 REQUIRES_S( minLength > 0 && minLength <= maxLength && \
550 status = length = readIntegerHeader( stream, tag );
564 status = sread( stream, buffer, length );
567 status = importBignum( bignum, buffer, length, minLength, maxLength,
568 maxRange, checkType );
570 status = sSetError( stream, status );
583 return( readBignumInteger( stream, bignum, minLength, maxLength,
598 return( readBignumInteger( stream, bignum, minLength, maxLength,
619 return( sSkip( stream, length ) );
628 return( readUniversalData( stream ) );
639 assert( value == NULL ||
isWritePtr( value,
sizeof(
long ) ) );
650 return( readNumeric( stream, value ) );
665 assert( enumeration == NULL || \
672 if( enumeration != NULL )
677 status = readNumeric( stream, &value );
682 if( enumeration != NULL )
683 *enumeration = ( int ) value;
703 value = sgetc( stream );
718 BYTE buffer[ 2 + 8 ];
722 assert(
boolean == NULL || \
729 if(
boolean != NULL )
734 status = sread( stream, buffer, 2 );
737 if( buffer[ 0 ] != 1 )
739 if(
boolean != NULL )
740 *
boolean = ( buffer[ 1 ] != 0 ) ?
TRUE :
FALSE;
750 IN_RANGE( 1, 50 )
const int noOidSelectionEntries,
759 sizeof(
OID_INFO ) * noOidSelectionEntries ) );
760 assert( oidSelectionValue == NULL || \
763 REQUIRES_S( noOidSelectionEntries > 0 && noOidSelectionEntries <= 50 );
766 if( oidSelectionValue != NULL )
767 *oidSelectionValue = &nullOidSelection;
770 status = readRawObject( stream, buffer,
MAX_OID_SIZE, &length,
780 for( oidEntry = 0, iterationCount = 0;
781 oidEntry < noOidSelectionEntries && \
782 oidSelection[ oidEntry ].oid != NULL && \
784 oidEntry++, iterationCount++ )
786 const BYTE *oidPtr = oidSelection[ oidEntry ].oid;
794 ENSURES_S( oidEntry + 1 < noOidSelectionEntries && \
795 oidSelection[ oidEntry + 1 ].
oid == NULL );
800 if( length == oidLength && \
801 buffer[ length - 1 ] == oidPtr[ length - 1 ] && \
802 !memcmp( buffer, oidPtr, length ) )
805 ENSURES_S( iterationCount < FAILSAFE_ITERATIONS_MED );
806 if( oidEntry >= noOidSelectionEntries || \
807 oidSelection[ oidEntry ].
oid == NULL )
810 if( oidSelectionValue != NULL )
811 *oidSelectionValue = &oidSelection[ oidEntry ];
818 IN_RANGE( 1, 50 )
const int noOidSelectionEntries,
820 noOidSelectionEntries )
int *selectionID )
827 sizeof(
OID_INFO ) * noOidSelectionEntries ) );
828 assert(
isWritePtr( selectionID,
sizeof(
int ) ) );
830 REQUIRES_S( noOidSelectionEntries > 0 && noOidSelectionEntries <= 50 );
835 status = readOIDEx( stream, oidSelection, noOidSelectionEntries,
861 oidInfo[ 0 ].oid =
oid );
862 return( readOIDEx( stream, oidInfo, 3, NULL ) );
878 assert(
isWritePtr( oidLength,
sizeof(
int ) ) );
885 memset( oid, 0,
min( 16, oidMaxLength ) );
891 status = readRawObject( stream, oid, oidMaxLength, &length, tag );
894 if( length < ( tag ==
NO_TAG ? 0 : 1 ) + 1 + 3 || length > oidMaxLength )
915 assert(
string == NULL ||
isWritePtr(
string, maxLength ) );
916 assert(
isWritePtr( stringLength,
sizeof(
int ) ) );
918 REQUIRES_S( minLength > 0 && minLength <= maxLength && \
926 memset(
string, 0,
min( 16, maxLength ) );
942 if( readTag( stream ) != tag )
948 if( length < minLength )
950 if( isOctetString && length > maxLength )
954 return( readConstrainedData( stream,
string, maxLength, stringLength,
968 assert(
string == NULL ||
isWritePtr(
string, maxLength ) );
969 assert( stringLength == NULL || \
972 REQUIRES_S( minLength > 0 && minLength <= maxLength && \
977 return( readString( stream,
string, stringLength, minLength, maxLength,
998 assert(
string == NULL ||
isWritePtr(
string, stringMaxLength ) );
999 assert( stringLength == NULL || \
1006 return( readString( stream,
string, stringLength, 1, stringMaxLength,
1017 int length,
data, mask, flag, value = 0, noBits, i;
1020 assert( bitString == NULL ||
isWritePtr( bitString,
sizeof(
int ) ) );
1026 if( bitString != NULL )
1037 length = sgetc( stream );
1041 if( length < 0 || length > 4 || length >
sizeof(
int ) )
1043 noBits = sgetc( stream );
1046 if( noBits < 0 || noBits > 7 )
1050 ENSURES_S( length >= 1 && length <=
min( 4,
sizeof(
int ) ) );
1051 ENSURES_S( noBits >= 0 && noBits <= 7 );
1055 noBits = ( length * 8 ) - noBits;
1056 ENSURES_S( noBits >= 0 && noBits <= 32 );
1070 data = sgetc( stream );
1073 for( mask = 0x80, i = 1; i <
length; mask <<= 8, i++ )
1075 const long dataValTmp = data << 8;
1076 const int dataTmp = sgetc( stream );
1086 data = dataValTmp | dataTmp;
1093 for( flag = 1, i = 0; i < noBits; flag <<= 1, i++ )
1099 if( bitString != NULL )
1116 struct tm theTime, gmTimeInfo, *gmTimeInfoPtr = &gmTimeInfo;
1117 time_t utcTime, gmTime;
1121 assert(
isWritePtr( timePtr,
sizeof( time_t ) ) );
1133 length = sgetc( stream );
1136 if( ( isUTCTime && length != 13 ) || ( !isUTCTime && length != 15 ) )
1138 ENSURES_S( length == 13 || length == 15 );
1142 memset( buffer, 0, 16 );
1143 status = sread( stream, buffer, length );
1146 for( i = 0; i < length - 1; i++ )
1151 if( buffer[ length - 1 ] !=
'Z' )
1155 memset( &theTime, 0,
sizeof(
struct tm ) );
1156 theTime.tm_isdst = -1;
1159 status = strGetNumeric( bufPtr, 2, &value, 19, 20 );
1162 value = ( value - 19 ) * 100;
1165 status = strGetNumeric( bufPtr, 2, &theTime.tm_year, 0, 99 );
1168 theTime.tm_year +=
value;
1169 status = strGetNumeric( bufPtr + 2, 2, &theTime.tm_mon, 1, 12 );
1174 status = strGetNumeric( bufPtr + 4, 2, &theTime.tm_mday, 1, 31 );
1177 status = strGetNumeric( bufPtr + 6, 2, &theTime.tm_hour, 0, 23 );
1179 status = strGetNumeric( bufPtr + 8, 2, &theTime.tm_min, 0, 59 );
1181 status = strGetNumeric( bufPtr + 10, 2, &theTime.tm_sec, 0, 59 );
1183 return( sSetError( stream, status ) );
1205 if( isUTCTime && theTime.tm_year < 50 )
1206 theTime.tm_year += 100;
1207 utcTime = mktime( &theTime );
1218 if( theTime.tm_year >= 138 && theTime.tm_year < 180 )
1220 theTime.tm_year = 136;
1221 utcTime = mktime( &theTime );
1232 if( theTime.tm_year == 70 && theTime.tm_mon == 0 )
1267 gmTimeInfoPtr =
gmTime_s( &utcTime, gmTimeInfoPtr );
1268 if( gmTimeInfoPtr == NULL )
1270 gmTimeInfoPtr->tm_isdst = -1;
1271 gmTime = mktime( gmTimeInfoPtr );
1274 if( utcTime < gmTime )
1275 *timePtr = utcTime - ( gmTime - utcTime );
1277 *timePtr = utcTime + ( utcTime - gmTime );
1285 gmTimeInfoPtr =
gmTime_s( timePtr );
1286 gmTimeInfoPtr->tm_isdst = -1;
1287 gmTime = mktime( gmTimeInfoPtr );
1288 if( gmTime != utcTime )
1291 gmTimeInfoPtr =
gmTime_s( timePtr, gmTimeInfoPtr );
1292 gmTimeInfoPtr->tm_isdst = -1;
1293 gmTime = mktime( gmTimeInfoPtr );
1294 if( gmTime != utcTime )
1307 assert(
isWritePtr( timeVal,
sizeof( time_t ) ) );
1317 return( readTime( stream, timeVal,
TRUE ) );
1321 int readGeneralizedTimeTag(
INOUT STREAM *stream,
OUT time_t *timeVal,
1325 assert(
isWritePtr( timeVal,
sizeof( time_t ) ) );
1335 return( readTime( stream, timeVal,
FALSE ) );
1364 #define READOBJ_FLAG_NONE 0x00
1365 #define READOBJ_FLAG_BITSTRING 0x01
1366 #define READOBJ_FLAG_INDEFOK 0x02
1367 #define READOBJ_FLAG_UNIVERSAL 0x04
1368 #define READOBJ_FLAG_MAX 0x0F
1373 const BOOLEAN allowRelaxedMatch )
1383 tagValue = readTag( stream );
1390 if( tagValue != tag )
1414 if( allowRelaxedMatch && tagValue ==
BER_INTEGER )
1422 static
int readObjectHeader(
INOUT STREAM *stream,
1432 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1440 if( length != NULL )
1451 status = checkReadTag( stream, tag,
1455 status = readLengthValue( stream, &dataLength,
1457 length == NULL ) ? \
1475 value = sgetc( stream );
1485 ( dataLength < minLength || dataLength > 32767 ) )
1487 if( length != NULL )
1493 static
int readLongObjectHeader(
INOUT STREAM *stream,
1502 assert( length == NULL ||
isWritePtr( length,
sizeof(
long ) ) );
1510 if( length != NULL )
1514 status = checkReadTag( stream, tag,
1521 if( length != NULL )
1533 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1535 return( readObjectHeader( stream, length, 0,
BER_SEQUENCE,
1543 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1545 return( readObjectHeader( stream, length, 0,
BER_SEQUENCE,
1553 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1555 return( readObjectHeader( stream, length, 0,
BER_SET,
1563 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1565 return( readObjectHeader( stream, length, 0,
BER_SET,
1574 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1578 return( readObjectHeader( stream, length, 0, ( tag ==
DEFAULT_TAG ) ? \
1588 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1592 return( readObjectHeader( stream, length, 0, ( tag ==
DEFAULT_TAG ) ? \
1603 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1607 return( readObjectHeader( stream, length, minLength,
1619 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1623 return( readObjectHeader( stream, length, minLength,
1626 READOBJ_FLAG_BITSTRING ) );
1635 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1643 return( readObjectHeader( stream, length, minLength,
1655 assert( length == NULL ||
isWritePtr( length,
sizeof(
int ) ) );
1660 return( readObjectHeader( stream, length, minLength,
1676 assert( length == NULL ||
isWritePtr( length,
sizeof(
long ) ) );
1678 return( readLongObjectHeader( stream, length,
BER_SEQUENCE,
1686 assert( length == NULL ||
isWritePtr( length,
sizeof(
long ) ) );
1688 return( readLongObjectHeader( stream, length,
BER_SET,
1698 assert( length == NULL ||
isWritePtr( length,
sizeof(
long ) ) );
1702 return( readLongObjectHeader( stream, length, ( tag ==
DEFAULT_TAG ) ? \
1713 assert( length == NULL ||
isWritePtr( length,
sizeof(
long ) ) );
1718 return( readLongObjectHeader( stream, length,
1727 int readGenericObjectHeader(
INOUT STREAM *stream,
1732 assert(
isWritePtr( length,
sizeof(
long ) ) );
1741 status = readObjectHeader( stream, &localLength, 0,
ANY_TAG,
1745 *length = localLength;
1749 return( readLongObjectHeader( stream, length,
ANY_TAG,
1756 #define OBJECT_HEADER_DATA_SIZE 16
1771 assert(
isWritePtr( objectPtrPtr,
sizeof(
void * ) ) );
1772 assert(
isWritePtr( objectLengthPtr,
sizeof(
int ) ) );
1775 minLength < maxLength && \
1779 *objectPtrPtr = NULL;
1780 *objectLengthPtr = 0;
1789 status = readGenericHole( &headerStream, &objectLength,
1792 headerSize = stell( &headerStream );
1793 sMemDisconnect( &headerStream );
1796 sSetError( stream, status );
1801 if( objectLength < minLength || objectLength > maxLength )
1809 objectLength += headerSize;
1810 if( ( objectData =
clAlloc(
"readObjectData", objectLength ) ) == NULL )
1825 status = checkObjectEncoding( objectData, objectLength );
1832 *objectPtrPtr = objectData;