📄 dnstring.c
字号:
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 + -