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

📄 ssl.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
			}
		else
			/* If it's not an SSLv2 handshake it has to be an SSLv3/TLS
			   handshake */
			if( type != SSL_MSG_HANDSHAKE )
				retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
						"Unknown SSL/TLS hello message type %d, should be %d", 
						type, SSL_MSG_HANDSHAKE );
		}
	else
		if( type != packetType )
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Unknown SSL/TLS message type %d, should be %d", 
					type, packetType );
	if( *bufPtr++ != SSL_MAJOR_VERSION )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid SSL major version number %d", bufPtr[ -1 ] );
	version = *bufPtr++;
	if( version < SSL_MINOR_VERSION_SSL || \
		version > ( ( ( packetType == SSL_MSG_SPECIAL_HANDSHAKE ) ? \
					5 : SSL_MINOR_VERSION_TLS11 ) ) )
		/* If it's the first handshake packet we allow versions up to a 
		   hypothetical SSLv3.5 (which would be TLS 1.4), after that we 
		   should have fallen back to a version that we understand */
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid SSL minor version number %d", version );
	if( !isV2handshake )
		{ totalLength = mgetWord( bufPtr ); }
	if( totalLength < 1 || totalLength > sessionInfoPtr->receiveBufSize || \
		( packetType != SSL_MSG_CHANGE_CIPHER_SPEC && \
		  totalLength < MIN_PACKET_SIZE ) )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid packet length %d", totalLength );
	if( ( sessionInfoPtr->flags & SESSION_ISSECURE ) && \
		( sessionInfoPtr->protocolFlags & SSL_PFLAG_EXPLICITIV ) )
		{
		/* If we're using an explicit IV, the IV data is counted as part of 
		   the header so we have to adjust the payload read for the data that 
		   we've already read */
		memmove( sessionInfoPtr->receiveBuffer, bufPtr, 
				 sessionInfoPtr->cryptBlocksize );
		bufPtr = sessionInfoPtr->receiveBuffer + \
				 sessionInfoPtr->cryptBlocksize;
		effectiveTotalLength = totalLength - sessionInfoPtr->cryptBlocksize;
		assert( effectiveTotalLength > 0 );
		}
	else
		{
		bufPtr = sessionInfoPtr->receiveBuffer;
		effectiveTotalLength = totalLength;
		}

	/* Read the payload packet(s) */
	status = sread( &sessionInfoPtr->stream, bufPtr, effectiveTotalLength );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream,
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	if( status < effectiveTotalLength )
		/* If we timed out during the handshake phase, treat it as a hard 
		   timeout error */
		retExt( sessionInfoPtr, CRYPT_ERROR_TIMEOUT,
				"Timeout during packet data read, only got %d of %d bytes", 
				status, totalLength );
	sessionInfoPtr->receiveBufPos = 0;
	sessionInfoPtr->receiveBufEnd = totalLength;
	if( handshakeInfo != NULL )
		dualMacData( handshakeInfo, sessionInfoPtr->receiveBuffer,
					 totalLength );
	if( isV2handshake )
		{
		/* SSLv2 puts the version info in the header, so we have to move the
		   data up in the buffer and drop in the minor version to return it
		   to the caller, with the high bit set to ensure that it doesn't 
		   get confused with a normal SSL packet type */
		memmove( sessionInfoPtr->receiveBuffer + 1, 
				 sessionInfoPtr->receiveBuffer, totalLength );
		sessionInfoPtr->receiveBuffer[ 0 ] = version | 0x80;
		}
	return( CRYPT_OK );
	}

/* Check that the header of an SSL packet is in order:

	byte		ID = <type>
	uint24		len
	[ byte		opaque = <nextByte>] */

int checkPacketHeader( SESSION_INFO *sessionInfoPtr, BYTE **bufPtrPtr,
					   const int type, const int minSize, const int nextByte )
	{
	BYTE *bufPtr = *bufPtrPtr;
	int length;

	if( *bufPtr++ != type || *bufPtr++ != 0 )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid packet header 0x%02X 0x%02X", *bufPtrPtr[ 0 ], 
				*bufPtrPtr[ 1 ] );
	length = mgetWord( bufPtr );
	if( length < minSize || length > MAX_PACKET_SIZE || \
		sessionInfoPtr->receiveBufPos + ID_SIZE + LENGTH_SIZE + length > \
			sessionInfoPtr->receiveBufEnd )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid packet length", length ); 
	if( nextByte != CRYPT_UNUSED && *bufPtr++ != nextByte )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid packet header data byte 0x%02X, expected 0x%02X", 
				bufPtr[ -1 ], nextByte ); 
	*bufPtrPtr = bufPtr;
	sessionInfoPtr->receiveBufPos = ID_SIZE + LENGTH_SIZE + length;
	return( length );
	}

/****************************************************************************
*																			*
*								Shared Connect Functions					*
*																			*
****************************************************************************/

/* Complete the dual MD5/SHA1 hash/MAC used in the finished message */

static int completeSSLDualMAC( const CRYPT_CONTEXT md5context,
							   const CRYPT_CONTEXT sha1context,
							   BYTE *hashValues, const char *label,
							   const BYTE *masterSecret )
	{
	RESOURCE_DATA msgData;
	int status;

	/* Generate the inner portion of the handshake message's MAC:

		hash( handshake_messages || cl/svr_label || master_secret || pad1 ).

	   Note that the SHA-1 pad size is 40 bytes and not 44 (to get a total
	   length of 64 bytes), this is due to an error in the spec */
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) label, 
					 SSL_SENDERLABEL_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) label, 
					 SSL_SENDERLABEL_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 48 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 40 );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
	setMessageData( &msgData, hashValues, MD5MAC_SIZE );
	status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
		status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Reset the hash contexts */
	krnlSendMessage( md5context, IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( sha1context, IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CTXINFO_HASHVALUE );

	/* Generate the outer portion of the handshake message's MAC:

		hash( master_secret || pad2 || inner_hash ) */
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) masterSecret, 
					 SSL_SECRET_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 48 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 40 );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, hashValues, 
					 MD5MAC_SIZE );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, hashValues + MD5MAC_SIZE, 
					 SHA1MAC_SIZE );
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
	setMessageData( &msgData, hashValues, MD5MAC_SIZE );
	status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
		status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	return( status );
	}

static int completeTLSHashedMAC( const CRYPT_CONTEXT md5context,
								 const CRYPT_CONTEXT sha1context,
								 BYTE *hashValues, const char *label,
								 const BYTE *masterSecret )
	{
	MECHANISM_DERIVE_INFO mechanismInfo;
	RESOURCE_DATA msgData;
	BYTE hashBuffer[ 64 + CRYPT_MAX_HASHSIZE * 2 ];
	const int labelLength = strlen( label );
	int status;

	memcpy( hashBuffer, label, labelLength );

	/* Complete the hashing and get the MD5 and SHA-1 hashes */
	krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
	krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
	setMessageData( &msgData, hashBuffer + labelLength, MD5MAC_SIZE );
	status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hashBuffer + labelLength + MD5MAC_SIZE,
						SHA1MAC_SIZE );
		status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Generate the TLS check value.  This isn't really a hash or a MAC, but
	   is generated by feeding the MD5 and SHA1 hashes of the handshake
	   messages into the TLS key derivation (PRF) function and truncating
	   the result to 12 bytes for no adequately explored reason, most 
	   probably it's IPsec cargo cult protocol design:

		TLS_PRF( label || MD5_hash || SHA1_hash ) */
	setMechanismDeriveInfo( &mechanismInfo, hashValues, TLS_HASHEDMAC_SIZE,
							( void * ) masterSecret, 48, CRYPT_USE_DEFAULT,
							hashBuffer, labelLength + MD5MAC_SIZE + SHA1MAC_SIZE, 1 );
	return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
							 &mechanismInfo, MECHANISM_TLS ) );
	}

/* Complete the handshake with the client or server.  The logic gets a bit
   complex here because the roles of the client and server are reversed if
   we're resuming a session:

		Normal					Resumed
	Client		Server		Client		Server
	------		------		------		------
	KeyEx  --->					   <---	Hello
	CCS	   --->					   <--- CCS
	Fin	   --->					   <--- Fin
		   <---	CCS			CCS	   --->
		   <---	Fin			Fin	   --->

   Because of this the handshake-completion step treats the two sides as
   initiator and responder rather than client and server.  The overall flow
   is then:

	dualMAC( initiator );
	if( !initiator )
		read initiator CCS;
	dualMAC( responder );
	send initiator/responder CCS;
	if( initiator )
		read responder CCS; */

static int readHandshakeCompletionData( SESSION_INFO *sessionInfoPtr,
										SSL_HANDSHAKE_INFO *handshakeInfo,
										const BYTE *hashValues )
	{
	BYTE *bufPtr;
	const int macValueLength = \
					( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL ) ? \
					MD5MAC_SIZE + SHA1MAC_SIZE : TLS_HASHEDMAC_SIZE;
	int status, length;

	/* Process the other side's change cipher spec (we could do this more
	   simply via an sread() and memcmp() against a template but that
	   doesn't process alerts properly).  Since change cipherspec is its
	   own protocol, the packet data consists of only a '1' byte:

		byte		1
	
	   At this point we've sent our change cipher spec (so the send channel
	   is in the secure state) but haven't received the other side's one yet
	   so the receive channel isn't.  To handle this we need to temporarily 
	   turn off the secure-session flag to ensure that there's no security 
	   processing applied to the received message */
	sessionInfoPtr->flags &= ~SESSION_ISSECURE;
	status = readPacketSSL( sessionInfoPtr, NULL, 
							SSL_MSG_CHANGE_CIPHER_SPEC );
	sessionInfoPtr->flags |= SESSION_ISSECURE;
	if( cryptStatusError( status ) )
		return( status );
	bufPtr = sessionInfoPtr->receiveBuffer;
	if( *bufPtr++ != 1 )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid change cipher spec payload, expected 0x01, got "
				"0x%02X", bufPtr[ -1 ] );

	/* Change cipher spec was the last message not subject to security 
	   encapsulation, if we're using explicit IVs the effective header size 
	   changes at this point because of the extra IV data so we update the 
	   receive buffer start offset to accomodate this */
	if( sessionInfoPtr->protocolFlags & SSL_PFLAG_EXPLICITIV )
		sessionInfoPtr->receiveBufStartOfs += sessionInfoPtr->cryptBlocksize;

	/* Process the other side's finished.  Since this is the first chance that 
	   we have to test whether our crypto keys are set up correctly, we 
	   report problems with decryption or MAC'ing or a failure to find any 
	   recognisable header as a wrong key rather than bad data error:

			SSLv3						TLS
		byte		ID = 0x14		byte		ID = 0x14
		uint24		len				uint24		len
		byte[16]	MD5 MAC			byte[12]	hashedMAC
		byte[20]	SHA-1 MAC */
	status = readPacketSSL( sessionInfoPtr, NULL, SSL_MSG_HANDSHAKE );
	if( cryptStatusError( status ) )
		return( status );
	bufPtr = sessionInfoPtr->receiveBuffer;
	length = sessionInfoPtr->receiveBufEnd;
	if( sessionInfoPtr->protocolFlags & SSL_PFLAG_EXPLICITIV )
		{
#if 0
		/* If we're using explicit IVs, the first block constitutes the IV.
		   Decrypt it and discard it (alternate code used when we can't 
		   reload an IV during decryption) */
		status = krnlSe

⌨️ 快捷键说明

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