⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn1_rw.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Read the numeric field */
	status = readNumeric( stream, &value );
	if( cryptStatusOK( status ) && enumeration != NULL )
		*enumeration = ( int ) value;
	return( status );
	}

/* Read a null value */

int readNullTag( STREAM *stream, const int tag )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Read the identifier if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_NULL ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Skip the length octet */
	if( sgetc( stream ) )
		sSetError( stream, CRYPT_ERROR_BADDATA );
	return( sGetStatus( stream ) );
	}

/* Read a boolean value */

int readBooleanTag( STREAM *stream, BOOLEAN *boolean, const int tag )
	{
	int value;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Clear return value */
	if( boolean != NULL )
		*boolean = FALSE;

	/* Read the identifier if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_BOOLEAN ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Skip the length octet and read the boolean value */
	if( sgetc( stream ) != 1 )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( sGetStatus( stream ) );
		}
	value = sgetc( stream );
	if( !cryptStatusError( value ) && boolean != NULL )
		*boolean = value ? TRUE : FALSE;
	return( sGetStatus( stream ) );
	}

/* Read an octet string value */

int readOctetStringTag( STREAM *stream, BYTE *string, int *stringLength,
						const int maxLength, const int tag )
	{
	int length;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( maxLength > 0 );

	/* Clear return value */
	if( string != NULL )
		{
		*string = '\0';
		*stringLength = 0;
		}

	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_OCTETSTRING ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Now read in the string, limiting the size to the maximum buffer size */
	length = readLengthValue( stream, READLENGTH_SHORT );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	return( readConstrainedData( stream, string, stringLength, length, 
								 maxLength ) );
	}

/* Read a character string.  This handles any of the myriad ASN.1 character
   string types.  The handling of the tag works somewhat differently here to
   the usual manner in that since the function is polymorphic, the tag
   defines the character string type and is always used (there's no
   NO_TAG or DEFAULT_TAG like the other functions use).  This works because
   the plethora of string types means that the higher-level routines that 
   read them invariably have to sort out the valid tag types themselves */

int readCharacterString( STREAM *stream, BYTE *string, int *stringLength,
						 const int maxLength, const int tag )
	{
	int length;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( maxLength > 0 );
	assert( tag != NO_TAG && tag != DEFAULT_TAG );

	/* Clear return value */
	if( string != NULL )
		{
		*string = '\0';
		*stringLength = 0;
		}

	/* Read the identifier field if necessary */
	if( readTag( stream ) != tag )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( sGetStatus( stream ) );
		}

	/* Now read in the string, limiting the size to the maximum buffer size */
	length = readLengthValue( stream, READLENGTH_SHORT );
	if( length <= 0 )
		return( length );	/* Error or zero length */
	return( readConstrainedData( stream, string, stringLength, length, 
								 maxLength ) );
	}

/* Read a bit string */

int readBitStringTag( STREAM *stream, int *bitString, const int tag )
	{
	unsigned int data, mask = 0x80;
	int length, flag = 1, value = 0, noBits, i;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	
	/* Clear return value */
	if( bitString != NULL )
		*bitString = 0;

	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_BITSTRING ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( sGetStatus( stream ) );
			}
		}

	/* Make sure that we have a bitstring with between 0 and sizeof( int ) 
	   bits.  This isn't as machine-dependant as it seems, the only place 
	   where bit strings longer than one or two bytes are used is with the 
	   more obscure CMP error subcodes that just provide further information
	   above and beyond the main error code and text message, so we provide
	   the extra information if the machine architecture can handle it and
	   skip it otherwise */
	length = sgetc( stream ) - 1;
	noBits = sgetc( stream );
	if( length < 0 || length > sizeof( int ) || noBits < 0 || noBits > 7 )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}
	if( length == 0 )
		return( CRYPT_OK );		/* Zero value */
	noBits = ( length * 8 ) - noBits;

	/* ASN.1 bitstrings start at bit 0, so we need to reverse the order of
	   the bits */
	data = sgetc( stream );
	for( i = noBits - 8; i > 0; i -= 8 )
		{
		data = ( data << 8 ) | sgetc( stream );
		mask <<= 8;
		}
	for( i = 0; i < noBits; i++ )
		{
		if( data & mask )
			value |= flag;
		flag <<= 1;
		data <<= 1;
		}
	if( bitString != NULL )
		*bitString = value;

	return( sGetStatus( stream ) );
	}

/* Read a UTCTime and GeneralizedTime value */

static int getDigits( const BYTE *bufPtr )
	{
	int result, ch = *bufPtr++;

	if( ch < '0' || ch > '9' )
		return( -1 );
	result = ( ch - '0' ) * 10;
	ch = *bufPtr++;
	if( ch < '0' || ch > '9' )
		return( -1 );
	return( result + ( ch - '0' ) );
	}

static int readTime( STREAM *stream, time_t *timePtr, const BOOLEAN isUTCTime )
	{
	BYTE buffer[ 32 ], *bufPtr = buffer;
	struct tm theTime,  *gm_tm;
	time_t utcTime, gmTime;
#if 0
	time_t localTime;
#endif /* 0 */
	int value = 0, length, status;

	/* Read the length field and make sure that it's of the correct size.  
	   There's only one encoding allowed although in theory the encoded 
	   value could range in length from 11 to 17 bytes for UTCTime and 13 to 
	   19 bytes for GeneralizedTime.  In practice we also have to allow 11-
	   byte UTCTimes since an obsolete encoding rule allowed the time to be 
	   encoded without seconds, and Sweden Post haven't realised that this 
	   has changed yet */
	length = sgetc( stream );
	if( ( isUTCTime && length != 13 && length != 11 ) || \
		( !isUTCTime && length != 15 ) )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( sGetStatus( stream ) );
		}

	/* Read the encoded time data */
	memset( buffer, 0, 32 );
	status = sread( stream, buffer, length );
	if( cryptStatusError( status ) )
		return( status );

	/* Decode the time fields.  Ideally we should use sscanf(), but there
	   are too many dodgy versions of this around */
	memset( &theTime, 0, sizeof( struct tm ) );
	theTime.tm_isdst = -1;		/* Get the system to adjust for DST */
	if( !isUTCTime )
		{
		value = ( getDigits( bufPtr ) - 19 ) * 100;	/* Read the century */
		bufPtr += 2;
		length -= 2;
		}
	theTime.tm_year = getDigits( bufPtr ) + value;
	theTime.tm_mon = getDigits( bufPtr + 2 ) - 1;
	theTime.tm_mday = getDigits( bufPtr + 4 );
	theTime.tm_hour = getDigits( bufPtr + 6 );
	theTime.tm_min = getDigits( bufPtr + 8 );

	/* Read the seconds field if there's one present */
	if( length == 13 )
		{
		theTime.tm_sec = getDigits( bufPtr + 10 );
		if( bufPtr[ 12 ] != 'Z' )
			status = CRYPT_ERROR_BADDATA;
		}
	else
		if( length != 11 || bufPtr[ 10 ] != 'Z' )
			status = CRYPT_ERROR_BADDATA;

	/* Make sure that there were no format errors */
	if( cryptStatusOK( status ) && \
		( theTime.tm_year | theTime.tm_mon | theTime.tm_mday | \
		  theTime.tm_hour | theTime.tm_min | theTime.tm_sec ) < 0 )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		sSetError( stream, status );
		return( status );
		}

	/* Finally, convert it to the local time.  Since the UTCTime format
	   doesn't take centuries into account (and you'd think that when the ISO
	   came up with the world's least efficient time encoding format they
	   could have spared another two bytes to fully specify the year), we
	   have to adjust by one century for years < 50 (and hope there aren't
	   any Y2K bugs in mktime()) if the format is UTCTime.  Note that there
	   are some implementations that currently roll over a century from 1970
	   (the Unix/Posix epoch and sort-of ISO/ANSI C epoch although they never
	   come out and say it), but hopefully these will be fixed by 2050.

		"The time is out of joint; o cursed spite,
		 That ever I was born to set it right"	- Shakespeare, "Hamlet" */
	if( isUTCTime && theTime.tm_year < 50 )
		theTime.tm_year += 100;
	utcTime = mktime( &theTime );
	if( utcTime == -1 )
		{
		sSetError( stream, CRYPT_ERROR_BADDATA );
		return( CRYPT_ERROR_BADDATA );
		}

	/* Convert the UTC time to local time.  This is complicated by the fact 
	   that although the C standard library can convert from local time -> 
	   UTC, it can't convert the time back, so we calculate the local offset 
	   from UTC and adjust the time as appropriate.  Since we can't assume 
	   that time_t is signed, we have to treat a negative and positive offset 
	   separately.  An extra complication is added by daylight savings time 
	   adjustment, some systems adjust for DST by default, some don't, and 
	   some allow you to set it in the Control Panel so it varies from 
	   machine to machine (thanks Bill!), so we have to make it explicit as 
	   part of the conversion process.  Even this still isn't perfect 
	   because it displays the time adjusted for DST now rather than DST 
	   when the cert was created, however this problem is more or less 
	   undecidable, the code used here has the property that the values for 
	   Windows agree with those for Unix and everything else which is the 
	   main thing */
#if 0							/* Changed 22/10/02 */
	localTime = getTime();
	gm_tm = gmtime( &localTime );
	gm_tm->tm_isdst = -1;		/* Force correct DST adjustment */
	gmTime = mktime( gm_tm );
	if( timePtr != NULL )
		if( localTime < gmTime )
			*timePtr = utcTime - ( gmTime - localTime );
		else
			*timePtr = utcTime + ( localTime - gmTime );
#else
	/* Another attempt: Treat the UTC time as local time (gmtime() always 
	   assumes the input is local time) and covert to GMT and back, which 
	   should give the offset from GMT */
	gm_tm = gmtime( &utcTime );
	gm_tm->tm_isdst = -1;		/* Force correct DST adjustment */
	gmTime = mktime( gm_tm );
	if( timePtr != NULL )
		{
		if( utcTime < gmTime )
			*timePtr = utcTime - ( gmTime - utcTime );
		else
			*timePtr = utcTime +  ( utcTime - gmTime );

		/* This still isn't quite perfect, since it can't handle time at
		   a DST changeover.  This is really a user problem ("Don't do that,
		   then"), but if necessary can be corrected by converting back to
		   GMT as a sanity check and applying a +/- 1 hour correction if 
		   there's a mismatch */
  #if 0
		gm_tm = gmtime( timePtr );
		gm_tm->tm_isdst = -1;
		gmTime = mktime( gm_tm );
		if( gmTime != utcTime )
			{
			*timePtr = ( *timePtr ) + 3600;	/* Try +1 first */
			gm_tm = gmtime( timePtr );
			gm_tm->tm_isdst = -1;
			gmTime = mktime( gm_tm );
			if( gmTime != utcTime )
				/* Nope, use -1 instead */
				*timePtr = ( *timePtr ) -7200;
			}
  #endif /* 0 */
		}
#endif /* 0 */

	return( CRYPT_OK );
	}

int readUTCTimeTag( STREAM *stream, time_t *timeVal, const int tag )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Clear return value */
	if( timeVal != NULL )
		*timeVal = 0;
	
	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_TIME_UTC ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( CRYPT_ERROR_BADDATA );
			}
		}

	/* Read the time fields */
	return( readTime( stream, timeVal, TRUE ) );
	}

int readGeneralizedTimeTag( STREAM *stream, time_t *timeVal, const int tag )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Clear return value */
	if( timeVal != NULL )
		*timeVal = 0;
	
	/* Read the identifier field if necessary */
	if( tag != NO_TAG )
		{
		if( readTag( stream ) != selectTag( tag, BER_TIME_GENERALIZED ) )
			{
			sSetError( stream, CRYPT_ERROR_BADDATA );
			return( CRYPT_ERROR_BADDATA );
			}
		}

	/* Read the time fields */
	return( readTime( stream, timeVal, FALSE ) );
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -