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

📄 dnstring.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:

	return( CRYPT_OK );
	}
#endif /* 0 */

/****************************************************************************
*																			*
*						ASN.1 String Conversion Functions					*
*																			*
****************************************************************************/

/* Check that a text string contains valid characters for its string type.
   This is used in non-DN strings where we can't vary the string type based 
   on the characters being used */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN checkTextStringData( IN_BUFFER( stringLen ) const char *string, 
							 IN_LENGTH_SHORT const int stringLen,
							 const BOOLEAN isPrintableString )
	{
	const int charTypeMask = isPrintableString ? P : I;
	int i;

	assert( isReadPtr( string, stringLen ) );

	REQUIRES_B( stringLen > 0 && stringLen < MAX_INTLENGTH_SHORT );

	for( i = 0; i < stringLen && i < FAILSAFE_ITERATIONS_LARGE; i++ )
		{
		const int ch = string[ i ];

		if( ch <= 0 || ch > 0x7F || !isPrint( ch ) )
			return( FALSE );
		if( !( nativeCharFlags[ ch ] & charTypeMask ) )
			return( FALSE );
		}
	ENSURES_B( i < FAILSAFE_ITERATIONS_LARGE );

	return( TRUE );
	}

/* Convert a character string from the format used in the certificate into 
   the native format */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int copyFromAsn1String( OUT_BUFFER( destMaxLen, destLen ) void *dest, 
						IN_LENGTH_SHORT const int destMaxLen, 
						OUT_LENGTH_SHORT_Z int *destLen, 
						IN_BUFFER( sourceLen ) const void *source, 
						IN_LENGTH_SHORT const int sourceLen,
						IN_TAG_ENCODED const int stringTag )
	{
	const ASN1_STRINGTYPE stringType = getAsn1StringType( source, sourceLen, 
														  stringTag );

	assert( isWritePtr( dest, destMaxLen ) );
	assert( isWritePtr( destLen, sizeof( int ) ) );
	assert( isReadPtr( source, sourceLen ) );

	REQUIRES( destMaxLen > 0 && destMaxLen < MAX_INTLENGTH_SHORT );
	REQUIRES( sourceLen > 0 && sourceLen < MAX_INTLENGTH_SHORT );
	REQUIRES( stringTag >= BER_STRING_UTF8 && stringTag <= BER_STRING_BMP );
	REQUIRES( stringType != STRINGTYPE_ERROR );

	/* Clear return value */
	memset( dest, 0, min( 16, destMaxLen ) );
	*destLen = 0;

	/* If it's a BMP or UTF-8 string convert it to the native format */
	if( stringType == STRINGTYPE_UNICODE )
		{
		const BYTE *string = source;
		wchar_t *wcDestPtr = ( wchar_t * ) dest;
		const int newLen = ( sourceLen / UCSIZE ) * WCSIZE;
		int i;

		if( newLen > destMaxLen )
			return( CRYPT_ERROR_OVERFLOW );
		
		/* Since we're reading bmpchar_t-sized values from a char-aligned
		   source we have to assemble the data a byte at a time to handle
		   systems where non-char values can only be accessed on word-
		   aligned boundaries */
		for( i = 0; i < sourceLen / UCSIZE && \
					i < FAILSAFE_ITERATIONS_LARGE; i++ )
			{
			*wcDestPtr++ = getBmpchar( string );
			string += UCSIZE;
			}
		*destLen = newLen;

		return( CRYPT_OK );
		}
	if( stringTag == BER_STRING_UTF8 )
		{
		return( copyFromUtf8String( dest, destMaxLen, destLen, source, 
									sourceLen ) );
		}

	/* If it's something masquerading as Unicode convert it to the narrower
	   format.  Note that STRINGTYPE_UNICODE_VISIBLE is already covered by 
	   STRINGTYPE_UNICODE_IA5 so we don't need to check for this separately */
	if( stringType == STRINGTYPE_UNICODE_PRINTABLE || \
		stringType == STRINGTYPE_UNICODE_IA5 || \
		stringType == STRINGTYPE_UNICODE_T61 )
		{
		const BYTE *srcPtr = source;
		BYTE *destPtr = dest;
		int i;

		if( sourceLen / UCSIZE > destMaxLen )
			return( CRYPT_ERROR_OVERFLOW );
		for( i = 1; i < sourceLen && \
					i < FAILSAFE_ITERATIONS_LARGE; i += UCSIZE )
			*destPtr++ = ( BYTE ) srcPtr[ i ];
		ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
		*destLen = sourceLen / UCSIZE;

		return( CRYPT_OK );
		}

	/* It's an 8-bit character set, just copy it across */
	if( sourceLen > destMaxLen )
		return( CRYPT_ERROR_OVERFLOW );
	memcpy( dest, source, sourceLen );
	*destLen = sourceLen;

	/* If it's a T61String try and guess whether it's using floating 
	   diacritics and convert them to the correct latin-1 representation.  
	   This is mostly guesswork since some implementations use floating 
	   diacritics and some don't, the only known user is Deutsche Telekom 
	   who use them for a/o/u-umlauts so we only interpret the character if 
	   the result would be one of these values */
	if( stringTag == BER_STRING_T61 )
		{
		BYTE *destPtr = dest;
		int length = sourceLen, i;

		for( i = 0; i < length - 1 && i < FAILSAFE_ITERATIONS_LARGE; i++ )
			{
			if( destPtr[ i ] == 0xC8 )
				{
				int ch = destPtr[ i + 1 ];

				/* If it's an umlautable character convert the following
				   ASCII value to the equivalent latin-1 form and move the
				   rest of the string down */
				if( ch == 0x61 || ch == 0x41 ||		/* a, A */
					ch == 0x6F || ch == 0x4F ||		/* o, O */
					ch == 0x75 || ch == 0x55 )		/* u, U */
					{
					typedef struct { int src, dest; } CHARMAP_INFO;
					static const CHARMAP_INFO charMap[] = {
						{ 0x61, 0xE4 }, { 0x41, 0xC4 },	/* a, A */
						{ 0x6F, 0xF6 }, { 0x4F, 0xD6 },	/* o, O */
						{ 0x75, 0xFC }, { 0x55, 0xDC },	/* u, U */
						{ 0x00, '?' }
						};
					int charIndex;

					for( charIndex = 0; 
						 charMap[ charIndex ].src && \
							charMap[ charIndex ].src != ch && \
							charIndex < FAILSAFE_ARRAYSIZE( charMap, CHARMAP_INFO ); 
						 charIndex++ );
					ENSURES( charIndex < FAILSAFE_ARRAYSIZE( charMap, CHARMAP_INFO ) );
					destPtr[ i ] = charMap[ charIndex ].dest;
					if( length - i > 2 )
						memmove( destPtr + i + 1, destPtr + i + 2,
								 length - ( i + 2 ) );
					length--;
					}
				}
			}
		ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
		*destLen = length;
		}

	return( CRYPT_OK );
	}

/* Convert a character string from the native format to the format used in 
   the certificate.  The 'stringType' value doesn't have any meaning outside
   this module, it's merely used as a cookie to pass back to other functions 
   here */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \
int getAsn1StringInfo( IN_BUFFER( stringLen ) const void *string, 
					   IN_LENGTH_SHORT const int stringLen,
					   OUT_RANGE( 0, 20 ) int *stringType, 
					   int *asn1StringType,
					   OUT_LENGTH_SHORT_Z int *asn1StringLen )
	{
	const ASN1_STRINGTYPE localStringType = getNativeStringType( string, 
																 stringLen );

	assert( isReadPtr( string, stringLen ) );
	assert( isWritePtr( stringType, sizeof( int ) ) );
	assert( isWritePtr( asn1StringType, sizeof( int ) ) );
	assert( isWritePtr( asn1StringLen, sizeof( int ) ) );

	REQUIRES( stringLen > 0 && stringLen < MAX_INTLENGTH_SHORT );
	REQUIRES( localStringType != STRINGTYPE_ERROR );

	/* Clear return value */
	*asn1StringLen = 0;

	*stringType = localStringType;
	switch( localStringType )
		{
		case STRINGTYPE_UNICODE:
			/* It's a widechar string, output is Unicode */
			*asn1StringLen = ( stringLen / WCSIZE ) * UCSIZE;
			*asn1StringType = BER_STRING_BMP;
			return( CRYPT_OK );

		case STRINGTYPE_UNICODE_PRINTABLE:
		case STRINGTYPE_UNICODE_IA5:
		case STRINGTYPE_UNICODE_T61:
			/* It's an ASCII string masquerading as Unicode, output is an 
			   8-bit string type */
			*asn1StringLen = stringLen / WCSIZE;
			*asn1StringType = ( *stringType == STRINGTYPE_UNICODE_PRINTABLE ) ? \
								BER_STRING_PRINTABLE : \
							  ( *stringType == STRINGTYPE_UNICODE_IA5 ) ? \
								BER_STRING_IA5 : BER_STRING_T61;
			return( CRYPT_OK );

		case STRINGTYPE_UTF8:
			{
			int status;

			/* It's a widechar string encoded as UTF-8, output is a 
			   variable-length UTF-8 string.  This isn't currently used
			   but is only present as a placeholder, see the comment at the 
			   start of this module for details */
			status = utf8TargetStringLen( string, stringLen, asn1StringLen,
						( *stringType == STRINGTYPE_UNICODE || \
						  *stringType == STRINGTYPE_UNICODE_PRINTABLE || \
						  *stringType == STRINGTYPE_UNICODE_IA5 || \
							  *stringType == STRINGTYPE_UNICODE_T61 ) ? \
						TRUE : FALSE );
			if( cryptStatusError( status ) )
				return( status );
			*asn1StringType = BER_STRING_UTF8;
			return( CRYPT_OK );
			}
		}

	/* If nothing specialised matches then the default string type is an 
	   ASCII string */
	*asn1StringLen = stringLen;
	*asn1StringType = ( *stringType == STRINGTYPE_PRINTABLE ) ? \
						BER_STRING_PRINTABLE : \
					  ( *stringType == STRINGTYPE_IA5 ) ? \
						BER_STRING_IA5 : BER_STRING_T61;
	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int copyToAsn1String( OUT_BUFFER( destMaxLen, destLen ) void *dest, 
					  IN_LENGTH_SHORT const int destMaxLen, 
					  OUT_LENGTH_SHORT_Z int *destLen, 
					  IN_BUFFER( sourceLen ) const void *source, 
					  IN_LENGTH_SHORT const int sourceLen,
					  IN_RANGE( 0, 20 ) const int stringType )
	{
	assert( isWritePtr( dest, destMaxLen ) );
	assert( isWritePtr( destLen, sizeof( int ) ) );
	assert( isReadPtr( source, sourceLen ) );

	REQUIRES( destMaxLen > 0 && destMaxLen < MAX_INTLENGTH_SHORT );
	REQUIRES( sourceLen > 0 && sourceLen < MAX_INTLENGTH_SHORT );
	REQUIRES( stringType >= STRINGTYPE_NONE && \
			  stringType < STRINGTYPE_LAST && \
			  stringType != STRINGTYPE_ERROR );

	/* Clear return value */
	memset( dest, 0, min( 16, destMaxLen ) );
	*destLen = 0;

	switch( stringType )
		{
		case STRINGTYPE_UNICODE:
			{
			const BYTE *srcPtr = source;
			BYTE *destPtr = dest;
			const int newLen = ( sourceLen / WCSIZE ) * UCSIZE;
			int length = sourceLen, i;

			/* It's a widechar, convert it to Unicode */
			*destLen = newLen;
			if( newLen > destMaxLen )
				return( CRYPT_ERROR_OVERFLOW );

			/* Copy the string across, converting from wchar_t to bmpchar_t 
			   as we go, with endianness conversion if necessary */
			for( i = 0; i < length && \
						i < FAILSAFE_ITERATIONS_LARGE; i += WCSIZE )
				{
				const wchar_t wCh = getWidechar( srcPtr );
				srcPtr += WCSIZE;

				*destPtr++ = ( BYTE ) ( ( wCh >> 8 ) & 0xFF );
				*destPtr++ = ( BYTE ) ( wCh & 0xFF );
				}
			ENSURES( i < FAILSAFE_ITERATIONS_LARGE );

			return( CRYPT_OK );
			}

		case STRINGTYPE_UNICODE_PRINTABLE:
		case STRINGTYPE_UNICODE_IA5:
		case STRINGTYPE_UNICODE_T61:
			{
			const wchar_t *srcPtr = ( wchar_t * ) source;
			BYTE *destPtr = dest;
			int i;

			/* It's something masquerading as Unicode, convert it to the 
			   narrower format.  Note that STRINGTYPE_UNICODE_VISIBLE is 
			   already covered by STRINGTYPE_UNICODE_IA5, so we don't need 
			   to check for this separately */
			*destLen = sourceLen / WCSIZE;
			if( sourceLen / WCSIZE > destMaxLen )
				return( CRYPT_ERROR_OVERFLOW );
			for( i = 0; i < sourceLen && \
						i < FAILSAFE_ITERATIONS_LARGE; i += WCSIZE )
				*destPtr++ = ( BYTE ) *srcPtr++;
			ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
			return( CRYPT_OK );
			}
		}

	/* If nothing specialised matches then the default string type is an 
	   ASCII string */
	*destLen = sourceLen;
	if( sourceLen > destMaxLen )
		return( CRYPT_ERROR_OVERFLOW );
	memcpy( dest, source, sourceLen );

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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