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

📄 ssl_rw.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
			totaLength <= MAX_PACKET_SIZE + sessionInfoPtr->authBlocksize + \
						  256 );
	assert( isWritePtr( bufPtr, totaLength ) );

	/* Make sure that the length is a multiple of the block cipher size */
	if( sessionInfoPtr->cryptBlocksize > 1 && \
		( totaLength % sessionInfoPtr->cryptBlocksize ) )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid encrypted packet length %d relative to cipher "
				"block size %d for packet type %d", totaLength, 
				sessionInfoPtr->cryptBlocksize, packetType );

	/* Decrypt the packet in the buffer.  We allow zero-length blocks (once
	   the padding is stripped) because some versions of OpenSSL send these 
	   as a kludge to work around pre-TLS 1.1 chosen-IV attacks */
	length = decryptData( sessionInfoPtr, bufPtr, totaLength );
	if( cryptStatusError( length ) )
		{
		/* If there's a padding error, don't exit immediately but record 
		   that there was a problem for after we've done the MAC'ing.  
		   Delaying the error reporting until then helps prevent timing 
		   attacks of the kind described by Brice Canvel, Alain Hiltgen,
		   Serge Vaudenay, and Martin Vuagnoux in "Password Interception 
		   in a SSL/TLS Channel", Crypto'03, LNCS No.2729, p.583.  These 
		   are close to impossible in most cases because we delay sending 
		   the close notify over a much longer period than the MAC vs.non-
		   MAC time difference and because it requires repeatedly connecting
		   with a fixed-format secret such as a password at the same location
		   in the packet (which MS Outlook does however manage to do), but 
		   we take this step anyway just to be safe */
		if( length == CRYPT_ERROR_BADDATA )
			{
			badDecrypt = TRUE;
			length = totaLength;
			}
		else
			return( length );
		}
	length -= sessionInfoPtr->authBlocksize;
	if( length < 0 )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid packet payload length %d for packet type %d", 
				length, packetType );

	/* MAC the decrypted data */
	if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
		status = macDataSSL( sessionInfoPtr, bufPtr, length, packetType, 
							 TRUE, badDecrypt );
	else
		status = macDataTLS( sessionInfoPtr, bufPtr, length, packetType, 
							 TRUE, badDecrypt );
	if( badDecrypt )
		/* Report the delayed decrypt error, held to this point to make 
		   timing attacks more difficult */
		return( CRYPT_ERROR_BADDATA );
	if( cryptStatusError( status ) )
		return( status );

	return( length );
	}

/* Read an SSL packet.  This function is only used during the handshake 
   phase (the data transfer phase has its own read/write code) so we can 
   perform some special-case handling based on this */

int readPacketSSL( SESSION_INFO *sessionInfoPtr,
				   SSL_HANDSHAKE_INFO *handshakeInfo, const int packetType )
	{
	STREAM stream;
	BYTE *bufPtr = sessionInfoPtr->receiveBuffer + \
				   sessionInfoPtr->receiveBufEnd;
	int length, status;

	/* Read and process the header.  We don't have to check for status == 0
	   (meaning no data was read) at this point since all reads during the
	   handshake phase are blocking reads */
	status = length = readFixedHeader( sessionInfoPtr, 
									   sessionInfoPtr->receiveBufStartOfs );
	if( status <= 0 )
		return( status );
	assert( status == sessionInfoPtr->receiveBufStartOfs );

	/* Check for an SSL alert message */
	if( bufPtr[ 0 ] == SSL_MSG_ALERT )
		return( processAlert( sessionInfoPtr, bufPtr, length ) );

	/* Decode and process the SSL packet header */
	if( packetType == SSL_MSG_FIRST_HANDSHAKE && \
		bufPtr[ 0 ] == SSL_MSG_V2HANDSHAKE )
		/* It's an SSLv2 handshake, handle it specially */
		return( handleSSLv2Header( sessionInfoPtr, handshakeInfo, bufPtr ) );
	sMemConnect( &stream, bufPtr, length );
	status = length = \
		checkPacketHeader( sessionInfoPtr, &stream, packetType, 
						   ( packetType == SSL_MSG_CHANGE_CIPHER_SPEC ) ? \
						   1 : MIN_PACKET_SIZE ); 
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the payload packet(s) */
	status = sread( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer, 
					length );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream,
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	if( status < length )
		/* If we timed out during the handshake phase, treat it as a hard 
		   timeout error */
		retExt( sessionInfoPtr, CRYPT_ERROR_TIMEOUT,
				"Timed out reading packet data for packet type %d, only "
				"got %d of %d bytes", packetType, status, length );
	sessionInfoPtr->receiveBufPos = 0;
	sessionInfoPtr->receiveBufEnd = length;
	if( handshakeInfo != NULL )
		{
		sMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );
		dualMacData( handshakeInfo, &stream, TRUE );
		sMemDisconnect( &stream );
		}
	return( length );
	}

/* Read the next handshake stream packet */

int refreshHSStream( SESSION_INFO *sessionInfoPtr, 
					 SSL_HANDSHAKE_INFO *handshakeInfo )
	{
	STREAM *stream = &handshakeInfo->stream;
	int length;

	/* If there's still data present in the stream, there's nothing left
	   to do */
	if( sMemDataLeft( stream ) > 0 )
		return( CRYPT_OK );

	/* Refill the stream */
	sMemDisconnect( stream );
	length = readPacketSSL( sessionInfoPtr, handshakeInfo, 
							SSL_MSG_HANDSHAKE );
	if( cryptStatusError( length ) )
		return( length );
	assert( length > 0 );
	sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );

	return( CRYPT_OK );
	}		

/****************************************************************************
*																			*
*							Write Packet Utility Functions					*
*																			*
****************************************************************************/

/* Open and complete an SSL packet */

static void openPacketStream( STREAM *stream, const SESSION_INFO *sessionInfoPtr, 
							  const int bufferSize, const BOOLEAN isNewStream, 
							  const int packetType )
	{
	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isNewStream || stell( stream ) >= SSL_HEADER_SIZE );
	assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );

	/* Create the stream if necessary */
	if( isNewStream )
		{
		const int streamSize = ( bufferSize == CRYPT_USE_DEFAULT ) ? \
						sessionInfoPtr->sendBufSize - EXTRA_PACKET_SIZE : \
						bufferSize + sessionInfoPtr->sendBufStartOfs;

		assert( isWritePtr( sessionInfoPtr->sendBuffer, streamSize ) );
		assert( streamSize >= sessionInfoPtr->sendBufStartOfs );

		sMemOpen( stream, sessionInfoPtr->sendBuffer, streamSize );
		}

	/* Write the packet header:

		byte		ID = packetType
		byte[2]		version = { 0x03, 0x0n }
		uint16		len = 0 (placeholder) 
	  [ byte[]		iv	- TLS 1.1 only ] */
	sputc( stream, packetType );
	sputc( stream, SSL_MAJOR_VERSION );
	sputc( stream, sessionInfoPtr->version );
	writeUint16( stream, 0 );		/* Placeholder */
	if( ( sessionInfoPtr->flags & SESSION_ISSECURE_WRITE ) && \
		sslInfo->ivSize > 0 )
		{
		RESOURCE_DATA msgData;
		BYTE iv[ CRYPT_MAX_IVSIZE ];

		setMessageData( &msgData, iv, sslInfo->ivSize );
		krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
						 &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		swrite( stream, iv, sslInfo->ivSize );
		}
	}

void openPacketStreamSSL( STREAM *stream, const SESSION_INFO *sessionInfoPtr, 
						  const int bufferSize, const int packetType )
	{
	openPacketStream( stream, sessionInfoPtr, bufferSize, TRUE, 
					  packetType );
	}

int continuePacketStreamSSL( STREAM *stream, 
							  const SESSION_INFO *sessionInfoPtr, 
							  const int packetType )
	{
	const int offset = stell( stream );

	openPacketStream( stream, sessionInfoPtr, CRYPT_USE_DEFAULT, FALSE, 
					  packetType );
	return( offset );
	}

int completePacketStreamSSL( STREAM *stream, const int offset )
	{
	const int packetEndOffset = stell( stream );
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Update the length field at the start of the packet */
	sseek( stream, offset + ID_SIZE + VERSIONINFO_SIZE );
	status = writeUint16( stream, ( packetEndOffset - offset ) - \
								  SSL_HEADER_SIZE );
	sseek( stream, packetEndOffset );
	return( status );
	}

/* Start and complete a handshake packet within an SSL packet.  Since this
   continues an existing packet stream that's been opened using 
   openPacketStreamSSL(), it's denoted as continueXXX() rather than 
   openXXX() */

int continueHSPacketStream( STREAM *stream, const int packetType )
	{
	const int offset = stell( stream );

	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Write the handshake packet header:

		byte		ID = packetType
		uint24		len = 0 (placeholder) */
	sputc( stream, packetType );
	writeUint24( stream, 0 );
	return( offset );
	}

int completeHSPacketStream( STREAM *stream, const int offset )
	{
	const int packetEndOffset = stell( stream );
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( offset >= SSL_HEADER_SIZE );

	/* Update the length field at the start of the packet */
	sseek( stream, offset + ID_SIZE );
	status = writeUint24( stream, packetEndOffset - \
								  ( offset + ID_SIZE + LENGTH_SIZE ) );
	sseek( stream, packetEndOffset );
	return( status );
	}

/****************************************************************************
*																			*
*							Write/wrap a Packet								*
*																			*
****************************************************************************/

/* Wrap an SSL data packet:

				------				MAC'd
				==================  Encrypted

	[ hdr | IV | data | MAC | pad ]
	|		   +------+
	|			  |
   buffer		length 

   This MACs the data, adds the IV if necessary, pads and encrypts, and
   updates the header */

int wrapPacketSSL( SESSION_INFO *sessionInfoPtr, STREAM *stream, 
				   const int offset )
	{
	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
	const int payloadLength = ( stell( stream ) - \
								sessionInfoPtr->sendBufStartOfs ) - offset;
	BYTE *bufPtr = sMemBufPtr( stream ) - payloadLength;
	BYTE *headerPtr = bufPtr - ( SSL_HEADER_SIZE + sslInfo->ivSize );
	int length;

	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
	assert( sessionInfoPtr->flags & SESSION_ISSECURE_WRITE );
	assert( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE );
	assert( isWritePtr( bufPtr, payloadLength ) );
	assert( *headerPtr >= SSL_MSG_FIRST && *headerPtr <= SSL_MSG_LAST );

	/* Safety check to make sure that the stream is OK */
	if( !sStatusOK( stream ) )
		{
		assert( NOTREACHED );
		return( sGetStatus( stream ) );

⌨️ 快捷键说明

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