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 readUserID( INOUT STREAM *stream, INOUT CMP_PROTOCOL_INFO *protocolInfo ) { BYTE userID[ CRYPT_MAX_HASHSIZE + 8 ]; int userIDsize, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) ); /* Read the PKI user ID that we'll need to handle the integrity protection on the message */ readConstructed( stream, NULL, CTAG_PH_SENDERKID ); status = readOctetString( stream, userID, &userIDsize, 8, CRYPT_MAX_HASHSIZE ); if( cryptStatusError( status ) ) return( status ); ANALYSER_HINT( userIDsize >= 8 && userIDsize <= CRYPT_MAX_HASHSIZE ); /* If there's already been a previous transaction (which means that we have PKI user information present) and the current transaction matches what was used in the previous one, we don't have to update the user information */ if( protocolInfo->userIDsize == userIDsize && \ !memcmp( protocolInfo->userID, userID, userIDsize ) ) { DEBUG_PRINT(( "%s: Skipped repeated userID.\n", protocolInfo->isServer ? "SVR" : "CLI" )); DEBUG_DUMP_HEX( protocolInfo->isServer ? "SVR" : "CLI", protocolInfo->userID, protocolInfo->userIDsize ); return( CRYPT_OK ); } /* Record the new or changed the PKI user information and delete the MAC context associated with the previous user if necessary */ memcpy( protocolInfo->userID, userID, userIDsize ); protocolInfo->userIDsize = userIDsize; protocolInfo->userIDchanged = TRUE; if( protocolInfo->iMacContext != CRYPT_ERROR ) { krnlSendNotifier( protocolInfo->iMacContext, IMESSAGE_DECREFCOUNT ); protocolInfo->iMacContext = CRYPT_ERROR; } DEBUG_PRINT(( "%s: Read new userID.\n", protocolInfo->isServer ? "SVR" : "CLI" )); DEBUG_DUMP_HEX( protocolInfo->isServer ? "SVR" : "CLI", protocolInfo->userID, protocolInfo->userIDsize ); return( CRYPT_OK ); }
static int readTransactionID( INOUT STREAM *stream, INOUT CMP_PROTOCOL_INFO *protocolInfo, const BOOLEAN isServerInitialMessage ) { BYTE buffer[ CRYPT_MAX_HASHSIZE + 8 ]; int length, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) ); /* If this is the first message and we're the server, record the transaction ID for later */ if( isServerInitialMessage ) { status = readOctetString( stream, protocolInfo->transID, &protocolInfo->transIDsize, 4, CRYPT_MAX_HASHSIZE ); if( cryptStatusError( status ) ) return( status ); DEBUG_PRINT(( "%s: Read initial transID.\n", protocolInfo->isServer ? "SVR" : "CLI" )); DEBUG_DUMP_HEX( protocolInfo->isServer ? "SVR" : "CLI", protocolInfo->transID, protocolInfo->transIDsize ); return( CRYPT_OK ); } /* Make sure that the transaction ID for this message matches the recorded value (the bad signature error code is the best that we can provide here) */ status = readOctetString( stream, buffer, &length, 4, CRYPT_MAX_HASHSIZE ); if( cryptStatusError( status ) ) return( status ); ANALYSER_HINT( length >= 4 && length <= CRYPT_MAX_HASHSIZE ); DEBUG_PRINT(( "%s: Read transID.\n", protocolInfo->isServer ? "SVR" : "CLI" )); DEBUG_DUMP_HEX( protocolInfo->isServer ? "SVR" : "CLI", protocolInfo->transID, protocolInfo->transIDsize ); if( protocolInfo->transIDsize != length || \ memcmp( protocolInfo->transID, buffer, length ) ) return( CRYPT_ERROR_SIGNATURE ); return( CRYPT_OK ); }
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 ); }