static int readRDNcomponent( INOUT STREAM *stream, INOUT DN_COMPONENT **dnComponentListPtrPtr, IN_LENGTH_SHORT const int rdnDataLeft ) { CRYPT_ERRTYPE_TYPE dummy; BYTE stringBuffer[ MAX_ATTRIBUTE_SIZE + 8 ]; void *value; const int rdnStart = stell( stream ); int type, valueLength, valueStringType, stringTag; int flags = DN_FLAG_NOCHECK, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( dnComponentListPtrPtr, sizeof( DN_COMPONENT * ) ) ); REQUIRES( rdnDataLeft > 0 && rdnDataLeft < MAX_INTLENGTH_SHORT ); REQUIRES( rdnStart > 0 && rdnStart < MAX_INTLENGTH_SHORT ); /* Read the type information for this AVA */ status = readAVA( stream, &type, &valueLength, &stringTag ); if( cryptStatusError( status ) ) return( status ); if( valueLength <= 0 ) { /* Skip broken AVAs with zero-length strings */ return( CRYPT_OK ); } status = sMemGetDataBlock( stream, &value, valueLength ); if( cryptStatusOK( status ) ) status = sSkip( stream, valueLength ); if( cryptStatusError( status ) ) return( status ); ANALYSER_HINT( value != NULL ); /* If there's room for another AVA, mark this one as being continued. The +10 value is the minimum length for an AVA: SEQUENCE { OID, value } (2-bytes SEQUENCE + 5 bytes OID + 2 bytes (tag + length) + 1 byte min- length data). We don't do a simple =/!= check to get around incorrectly encoded lengths */ if( rdnDataLeft >= ( stell( stream ) - rdnStart ) + 10 ) flags |= DN_FLAG_CONTINUED; /* Convert the string into the local character set */ status = copyFromAsn1String( stringBuffer, MAX_ATTRIBUTE_SIZE, &valueLength, &valueStringType, value, valueLength, stringTag ); if( cryptStatusError( status ) ) return( status ); /* Add the DN component to the DN. If we hit a non-memory related error we turn it into a generic CRYPT_ERROR_BADDATA error since the other codes are somewhat too specific for this case, something like CRYPT_ERROR_INITED or an arg error isn't too useful for the caller */ status = insertDNstring( dnComponentListPtrPtr, type, stringBuffer, valueLength, valueStringType, flags, &dummy ); return( ( cryptStatusError( status ) && status != CRYPT_ERROR_MEMORY ) ? \ CRYPT_ERROR_BADDATA : status ); }
static int readRDNcomponent( INOUT STREAM *stream, INOUT DN_COMPONENT **dnComponentListPtrPtr, IN_LENGTH_SHORT const int rdnDataLeft ) { CRYPT_ERRTYPE_TYPE dummy; BYTE stringBuffer[ MAX_ATTRIBUTE_SIZE + 8 ]; void *value; const int rdnStart = stell( stream ); int type, valueLength, valueStringType, stringTag; int flags = DN_FLAG_NOCHECK, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( dnComponentListPtrPtr, sizeof( DN_COMPONENT * ) ) ); REQUIRES( rdnDataLeft > 0 && rdnDataLeft < MAX_INTLENGTH_SHORT ); REQUIRES( rdnStart > 0 && rdnStart < MAX_INTLENGTH_SHORT ); /* Read the type information for this AVA */ status = readAVA( stream, &type, &valueLength, &stringTag ); if( cryptStatusError( status ) ) { /* If this is an unrecognised AVA, don't try and process it (the content will already have been skipped in readAVA()) */ if( status == OK_SPECIAL ) return( CRYPT_OK ); return( status ); } /* Make sure that the string is a valid type for a DirectoryString. We don't allow Universal strings since no-one in their right mind uses those. Alongside DirectoryString values we also allow IA5Strings, from the practice of stuffing email addresses into DNs */ if( stringTag != BER_STRING_PRINTABLE && stringTag != BER_STRING_T61 && \ stringTag != BER_STRING_BMP && stringTag != BER_STRING_UTF8 && \ stringTag != BER_STRING_IA5 ) return( CRYPT_ERROR_BADDATA ); /* Skip broken AVAs with zero-length strings */ if( valueLength <= 0 ) return( CRYPT_OK ); /* Record the string contents, avoiding moving it into a buffer */ status = sMemGetDataBlock( stream, &value, valueLength ); if( cryptStatusOK( status ) ) status = sSkip( stream, valueLength, MAX_INTLENGTH_SHORT ); if( cryptStatusError( status ) ) return( status ); ANALYSER_HINT( value != NULL ); /* If there's room for another AVA, mark this one as being continued. The +10 value is the minimum length for an AVA: SEQUENCE { OID, value } (2-bytes SEQUENCE + 5 bytes OID + 2 bytes (tag + length) + 1 byte min- length data). We don't do a simple =/!= check to get around incorrectly encoded lengths */ if( rdnDataLeft >= ( stell( stream ) - rdnStart ) + 10 ) flags |= DN_FLAG_CONTINUED; /* Convert the string into the local character set */ status = copyFromAsn1String( stringBuffer, MAX_ATTRIBUTE_SIZE, &valueLength, &valueStringType, value, valueLength, stringTag ); if( cryptStatusError( status ) ) return( status ); /* Add the DN component to the DN. If we hit a non-memory related error we turn it into a generic CRYPT_ERROR_BADDATA error since the other codes are somewhat too specific for this case, something like CRYPT_ERROR_INITED or an arg error isn't too useful for the caller */ status = insertDNstring( dnComponentListPtrPtr, type, stringBuffer, valueLength, valueStringType, flags, &dummy ); return( ( cryptStatusError( status ) && status != CRYPT_ERROR_MEMORY ) ? \ CRYPT_ERROR_BADDATA : status ); }