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

📄 dnstring.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
				( string[ 1 ] & 0xC0 ) != 0x80 || \
				( string[ 2 ] & 0xC0 ) != 0x80 )
				return( CRYPT_ERROR_BADDATA );
			ch = ( ( firstChar & 0x1F ) << 12 ) | \
				 ( ( string[ 1 ] & 0x3F ) << 6 ) | \
				   ( string[ 2 ] & 0x3F );
			break;

		default:
			assert( NOTREACHED );
			return( CRYPT_ERROR_BADDATA );
		}

	return( ch );
	}

#if 0	/* Currently unused, see note at start */

static int putUTF8Char( BYTE *string, const long ch )
	{
	if( ch < 0x80 )
		{
		*string = ( BYTE ) ch;
		return( 1 );
		}
	if( ch < 0x0800 )
		{
		*string++ = ( BYTE )( 0xC0 | ch >> 6 );
		*string = ( BYTE )( 0x80 | ch & 0x3F );
		return( 2 );
		}
	*string++ = ( BYTE )( 0xE0 | ch >> 12 );
	*string++ = ( BYTE )( 0x80 | ( ( ch >> 6 ) & 0x3F ) );
	*string = ( BYTE )( 0x80 | ch & 0x3F );
	return( 3 );
	}
#endif /* 0 */

/* Determine the length of a string encoded as UTF-8 */

static int utf8DestStringLen( const void *string, const int stringLen,
							  const BOOLEAN isWideChar )
	{
	if( isWideChar )
		{
		const wchar_t *wcStrPtr = ( wchar_t * ) string;
		int length = 0, i;

		for( i = 0; i < stringLen; i += WCSIZE )
			{
			const wchar_t ch = *wcStrPtr++;

			length += ( ch < 0x80 ) ? 1 : ( ch < 0x0800 ) ? 2 : 3;
			}

		return( length );
		}

	return( stringLen );
	}

/* Convert a UTF-8 string to ASCII, 8859-1, or Unicode, and vice versa */

static int copyFromUtf8String( void *dest, int *destLen, const int destMaxLen,
							   const void *source, const int sourceLen )
	{
	ASN1_STRINGTYPE stringType = STRINGTYPE_PRINTABLE;
	const BYTE *srcPtr = source;
	wchar_t *wcDestPtr = dest;
	BYTE *destPtr = dest;
	int noChars = 0, count, i;

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

	/* Clear the return value */
	*destLen = 0;

	/* Scan the string to determine its length and the widest character type 
	   in it.  We have to process the entire string even once we've 
	   identified it as containing the widest string type (Unicode) in order 
	   to check for malformed chars */
	for( i = 0; i < sourceLen; i += count )
		{
		const long ch = getUTF8Char( srcPtr + i, sourceLen - i, &count );

		if( ch < 0 || ch > 0xFFFFL )
			return( CRYPT_ERROR_BADDATA );
		noChars++;
		if( stringType == STRINGTYPE_UNICODE || ch > 0xFF )
			stringType = STRINGTYPE_UNICODE;
		else
			/* If it's not a PrintableString char, mark it as T61 if it's
			   within range, otherwise it's Unicode */
			if( ch >= 128 )
				stringType = ( asn1CharFlags[ ( int ) ch & 0x7F ] & P ) ? \
							 STRINGTYPE_T61 : STRINGTYPE_UNICODE;
		}

	/* Make sure that the translated string will fit into the destination 
	   buffer */
	*destLen = noChars * ( ( stringType == STRINGTYPE_UNICODE ) ? \
						   WCSIZE : 1 );
	if( *destLen > destMaxLen )
		return( CRYPT_ERROR_OVERFLOW );

	/* Perform a second pass copying the string over */
	for( i = 0; i < sourceLen; i += count )
		{
		const long ch = getUTF8Char( srcPtr + i, sourceLen - i, &count );

		/* Copy the result as a Unicode or ASCII/8859-1 character */
		if( stringType == STRINGTYPE_UNICODE )
			*wcDestPtr++ = ( wchar_t ) ch;
		else
			*destPtr++ = ( BYTE ) ch;
		}

	return( stringType );
	}

#if 0	/* Currently unused, see note at start */

static int copyToUtf8String( void *dest, const int destMaxLen,
							 const void *source, const int sourceLen,
							 const BOOLEAN isWideChar )
	{
	assert( isWritePtr( dest, destMaxLen ) );
	assert( isReadPtr( source, sourceLen ) );

	if( isWideChar )
		{
		const wchar_t *wcStrPtr = source;
		BYTE *destPtr = dest;
		int length = 0, i;

		for( i = 0; i < sourceLen; i += WCSIZE )
			{
			length += putUTF8Char( destPtr, *wcStrPtr++ );
			destPtr += length;
			}
		return( length );
		}

	memcpy( dest, source, sourceLen );
	return( sourceLen );
	}
#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 */

BOOLEAN checkTextStringData( const char *string, const int stringLength,
							 const BOOLEAN isPrintableString )
	{
	const int charTypeMask = isPrintableString ? P : I;
	int i;

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

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

	return( TRUE );
	}

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

int copyFromAsn1String( void *dest, int *destLen, const int maxLen, 
						const void *source, const int sourceLen, 
						const int stringTag )
	{
	const ASN1_STRINGTYPE stringType = getAsn1StringType( source, sourceLen, 
														  stringTag );

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

	/* Clear return values */
	*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;

		assert( !( ( int ) dest & 1 ) );

		if( newLen > maxLen )
			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++ )
			{
			*wcDestPtr++ = getBmpchar( string );
			string += UCSIZE;
			}
		*destLen = newLen;
		return( CRYPT_OK );
		}
	if( stringTag == BER_STRING_UTF8 )
		return( copyFromUtf8String( dest, destLen, maxLen, 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 > maxLen )
			return( CRYPT_ERROR_OVERFLOW );
		for( i = 1; i < sourceLen; i += UCSIZE )
			*destPtr++ = ( BYTE ) srcPtr[ i ];
		*destLen = sourceLen / UCSIZE;

		return( CRYPT_OK );
		}

	/* It's an 8-bit character set, just copy it across */
	if( sourceLen > maxLen )
		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++ )
			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 */
					{
					static const struct {
						int src, dest;
						} 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++ );
					destPtr[ i ] = charMap[ charIndex ].dest;
					if( length - i > 2 )
						memmove( destPtr + i + 1, destPtr + i + 2,
								 length - ( i + 2 ) );
					length--;
					}
				}
		*destLen = length;
		}

	return( CRYPT_OK );
	}

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

int getAsn1StringInfo( const void *string, const int stringLen,
					   int *stringType, int *asn1StringType, 
					   int *asn1StringLen )
	{
	assert( isReadPtr( string, stringLen ) );
	assert( isWritePtr( stringType, sizeof( int ) ) );
	assert( isWritePtr( asn1StringType, sizeof( int ) ) );
	assert( isWritePtr( asn1StringLen, sizeof( int ) ) );

	*stringType = getNativeStringType( string, stringLen );
	switch( *stringType )
		{
		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:
			/* 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 */
			*asn1StringLen = utf8DestStringLen( string, stringLen,
						( *stringType == STRINGTYPE_UNICODE || \
						  *stringType == STRINGTYPE_UNICODE_PRINTABLE || \
						  *stringType == STRINGTYPE_UNICODE_IA5 || \
							  *stringType == STRINGTYPE_UNICODE_T61 ) ? \
						TRUE : FALSE );
			*asn1StringType = BER_STRING_UTF8;
			return( CRYPT_OK );

		default:
			/* It's an ASCII string */
			*asn1StringLen = stringLen;
			*asn1StringType = ( *stringType == STRINGTYPE_PRINTABLE ) ? \
								BER_STRING_PRINTABLE : \
							  ( *stringType == STRINGTYPE_IA5 ) ? \
								BER_STRING_IA5 : BER_STRING_T61;
			return( CRYPT_OK );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

int copyToAsn1String( void *dest, int *destLen, const int maxLen,
					  const void *source, const int sourceLen, 
					  const int stringType )
	{
	assert( isWritePtr( dest, maxLen ) );
	assert( isWritePtr( destLen, sizeof( int ) ) );
	assert( isReadPtr( source, sourceLen ) );

	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 > maxLen )
				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 += WCSIZE )
				{
				const wchar_t wCh = getWidechar( srcPtr );
				srcPtr += WCSIZE;

				*destPtr++ = ( BYTE ) ( ( wCh >> 8 ) & 0xFF );
				*destPtr++ = ( BYTE ) ( wCh & 0xFF );
				}

			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 > maxLen )
				return( CRYPT_ERROR_OVERFLOW );
			for( i = 0; i < sourceLen; i += WCSIZE )
				*destPtr++ = ( BYTE ) *srcPtr++;
			return( CRYPT_OK );
			}

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

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

⌨️ 快捷键说明

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