static int readAVABitstring( INOUT STREAM *stream, OUT_LENGTH_SHORT_Z int *length, OUT_TAG_ENCODED_Z int *stringTag ) { long streamPos; int bitStringLength, innerTag, innerLength = DUMMY_INIT, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( length, sizeof( int ) ) ); assert( isWritePtr( stringTag, sizeof( int ) ) ); /* Bitstrings are used for uniqueIdentifiers, however these usually encapsulate something else: BIT STRING { IA5String 'xxxxx' } so we try and dig one level deeper to find the encapsulated string if there is one. This gets a bit complicated because we have to speculatively try and decode the inner content and if that fails assume that it's raw bitstring data. First we read the bitstring wrapper and remember where the bitstring data starts */ status = readBitStringHole( stream, &bitStringLength, 2, DEFAULT_TAG ); if( cryptStatusError( status ) ) return( status ); streamPos = stell( stream ); /* Then we try and read any inner content */ status = innerTag = peekTag( stream ); if( !cryptStatusError( status ) ) status = readGenericHole( stream, &innerLength, 1, innerTag ); if( !cryptStatusError( status ) && \ bitStringLength == sizeofObject( innerLength ) ) { /* There was inner content present, treat it as the actual type and value of the bitstring. This assumes that the inner content is a string data type, which always seems to be the case (in any event it's not certain what we should be returning to the user if we find, for example, a SEQUENCE with further encapsulated content at this point) */ *stringTag = innerTag; *length = innerLength; return( CRYPT_OK ); } /* We couldn't identify any (obvious) inner content, it must be raw bitstring data. Unfortunately we have no idea what format this is in, it could in fact really be raw binary data but never actually seems to be this, it's usually ASCII text so we mark it as such and let the string-read routines sort it out */ sClearError( stream ); sseek( stream, streamPos ); *stringTag = BER_STRING_IA5; *length = bitStringLength; return( CRYPT_OK ); }
static int readProtectionAlgo( INOUT STREAM *stream, INOUT CMP_PROTOCOL_INFO *protocolInfo ) { CRYPT_ALGO_TYPE cryptAlgo, hashAlgo; int hashParam, streamPos, status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) ); /* Read the wrapper. If there's a problem we exit immediately since an error status from the readAlgoIDex() that follows is interpreted to indicate the presence of the weird Entrust MAC rather than a real error */ status = readConstructed( stream, NULL, CTAG_PH_PROTECTIONALGO ); if( cryptStatusError( status ) ) return( status ); streamPos = stell( stream ); status = readAlgoIDex( stream, &cryptAlgo, &hashAlgo, &hashParam, ALGOID_CLASS_PKCSIG ); if( cryptStatusOK( status ) ) { /* Make sure that it's a recognised signature algorithm to avoid false positives if the other side sends some bizarre algorithm ID */ if( !isSigAlgo( cryptAlgo ) ) return( CRYPT_ERROR_NOTAVAIL ); /* It's a recognised signature algorithm, use the CA certificate to verify it rather than the MAC */ protocolInfo->useMACreceive = FALSE; protocolInfo->hashAlgo = hashAlgo; protocolInfo->hashParam = hashParam; return( CRYPT_OK ); } ENSURES( cryptStatusError( status ) ); /* It's nothing normal, it must be the Entrust MAC algorithm information, remember where it starts so that we can process it later */ sClearError( stream ); protocolInfo->macInfoPos = streamPos; status = readUniversal( stream ); protocolInfo->useMACreceive = TRUE; return( status ); }