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

📄 certstr.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 2 页
字号:

#define utf8bytes( value )	( ( value <= 192 ) ? 1 : \
							  ( value <= 224 ) ? 2 : \
							  utf8bytesTbl[ ( value ) - 224 ] )

/* Parse one character from the string, enforcing the UTF-8 canonical-
   encoding rules:

	  00 -  7F = 0xxxxxxx
	 80 -  7FF = 110xxxxx 10xxxxxx 
	800 - FFFF = 1110xxxx 10xxxxxx 10xxxxxx */

static long getUnicodeChar( const BYTE *stringPtr, const int maxLen,
							int *charByteCount )
	{
	const int firstChar = *stringPtr;
	const int count = utf8bytes( firstChar );
	long ch;

	*charByteCount = count;
	if( count < 1 || count > 3 || count > maxLen )
		return( CRYPT_ERROR_BADDATA );
	switch( count )
		{
		case 0:
			ch = firstChar & 0x7F;
			break;

		case 1:
			if( ( firstChar & 0xE0 ) != 0xC0 || \
				( stringPtr[ 1 ] & 0xC0 ) != 0x80 )
				return( CRYPT_ERROR_BADDATA );
			ch = ( ( firstChar & 0x1F ) << 6 ) | \
				   ( stringPtr[ 1 ] & 0x3F );
			break;

		case 2:
			if( ( firstChar & 0xF0 ) != 0xE0 || \
				( stringPtr[ 1 ] & 0xC0 ) != 0x80 || \
				( stringPtr[ 2 ] & 0xC0 ) != 0x80 )
				return( CRYPT_ERROR_BADDATA );
			ch = ( ( firstChar & 0x1F ) << 12 ) | \
				 ( ( stringPtr[ 1 ] & 0x3F ) << 6 ) | \
				   ( stringPtr[ 2 ] & 0x3F );
			break;

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

	return( ch );
	}

static int copyFromUtf8String( void *dest, int *destLen, const int maxLen,
							   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;

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

	/* Scan the string to determine the widest character type in it */
	for( i = 0; i < sourceLen; i += count )
		{
		const long ch = getUnicodeChar( srcPtr + i, sourceLen - i, &count );

		if( ch < 0 || ch > 0xFFFFUL )
			return( CRYPT_ERROR_BADDATA );
		noChars++;
		if( ch > 0xFF )
			{
			stringType = STRINGTYPE_UNICODE;
			break;
			}

		/* Check which range it fits into */
		if( !( asn1CharFlags[ ( int ) ch ] & P ) )
			{
			/* If it's not a PrintableString char, mark it as T61 if it's
			   within range and we haven't already hit a Unicode char */
			if( asn1CharFlags[ ( int ) ch & 0x7F ] & I )
				stringType = STRINGTYPE_T61;
			else
				{
				stringType = STRINGTYPE_UNICODE;
				break;
				}
			}
		}

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

	/* Perform a second pass copying the string over */
	for( i = 0; i < sourceLen; i += count )
		{
		const long ch = getUnicodeChar( 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 );
	}

/* 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 );
	}

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

/* Convert a character string from the format used in the certificate into 
   the native format. This canonicalises the encoding (e.g. Unicode -> ASCII)
   and converts the character set, since we can't read the string with
   readCharacterString() because it hasn't been canonicalised at that point */

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 );

	/* Set default return values */
	*destLen = 0;

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

		if( newLen > maxLen )
			return( CRYPT_ERROR_OVERFLOW );
		for( i = 0; i < sourceLen / UCSIZE; i++ )
#ifdef DATA_LITTLEENDIAN
		/* BMPString characters are always big-endian, so we need to convert
		   them if we're on a little-endian system */
			wcDestPtr[ i ] = ( ( bmpSrcPtr[ i ] & 0xFF ) << 8 ) | \
							   ( bmpSrcPtr[ i ] >> 8 );
#else
			wcDestPtr[ i ] = ( wchar_t ) bmpSrcPtr[ i ];
#endif /* DATA_LITTLEENDIAN */
		*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 seperately */
	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. This canonicalises the encoding (e.g. Unicode -> ASCII)
   but doesn't convert the character set, since this is done by 
   writeCharacterString() */

int copyToAsn1String( void *dest, int *destLen, const int maxLen,
					  const void *source, const int sourceLen )
	{
	const ASN1_STRINGTYPE stringType = getNativeStringType( source, sourceLen );

	/* If it's Unicode, convert it to the appropriate format */
	if( stringType == STRINGTYPE_UNICODE )
		{
		const wchar_t *srcPtr = ( wchar_t * ) source;
		bmpchar_t *bmpDestPtr = ( bmpchar_t * ) dest;
		const int newLen = ( sourceLen / WCSIZE ) * UCSIZE;
		int length = sourceLen, i;

		/* If it's just a length check, we're done */
		*destLen = newLen;
		if( newLen > maxLen )
			return( CRYPT_ERROR_OVERFLOW );
		if( dest == NULL )
			return( BER_STRING_BMP );

		/* 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 )
			{
			wchar_t ch = *srcPtr++;
#ifdef DATA_LITTLEENDIAN
			ch = ( ( ch & 0xFF ) << 8 ) | ( ch >> 8 );
#endif /* DATA_LITTLEENDIAN */
			*bmpDestPtr++ = ch;
			}

		return( BER_STRING_BMP );
		}

	/* 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 seperately */
	if( stringType == STRINGTYPE_UNICODE_PRINTABLE || \
		stringType == STRINGTYPE_UNICODE_IA5 || \
		stringType == STRINGTYPE_UNICODE_T61 )
		{
		*destLen = sourceLen / WCSIZE;
		if( sourceLen / WCSIZE > maxLen )
			return( CRYPT_ERROR_OVERFLOW );
		if( dest != NULL )
			{
			const wchar_t *srcPtr = ( wchar_t * ) source;
			BYTE *destPtr = dest;
			int i;

			for( i = 0; i < sourceLen; i += WCSIZE )
				*destPtr++ = ( BYTE ) *srcPtr++;
			}
		return( ( stringType == STRINGTYPE_UNICODE_PRINTABLE ) ? \
					BER_STRING_PRINTABLE : \
				( stringType == STRINGTYPE_UNICODE_IA5 ) ? \
					BER_STRING_IA5 : BER_STRING_T61 );
		}

	/* It's an 8-bit character set, just copy it across */
	*destLen = sourceLen;
	if( sourceLen > maxLen )
		return( CRYPT_ERROR_OVERFLOW );
	if( dest != NULL )
		memcpy( dest, source, sourceLen );
	return( ( stringType == STRINGTYPE_PRINTABLE ) ? \
				BER_STRING_PRINTABLE : \
			( stringType == STRINGTYPE_IA5 ) ? \
				BER_STRING_IA5 : BER_STRING_T61 );
	}

⌨️ 快捷键说明

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