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

📄 ssl_cry.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
							min( attributeListPtr->valueLength, 
								 SSL_SECRET_SIZE ) );

	/* Create the master secret from the expanded user-supplied password.  
	   Note that since the use of shared secrets is specified only for TLS, 
	   we always use the TLS key derivation even if it's with the SSL 
	   protocol */
	setMechanismDeriveInfo( &mechanismInfo,
							masterSecret, SSL_SECRET_SIZE,
							premasterSecret, SSL_SECRET_SIZE,
							CRYPT_USE_DEFAULT, "shared secret", 13, 1 );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_DERIVE, &mechanismInfo, 
							  MECHANISM_DERIVE_TLS );
	zeroise( premasterSecret, SSL_SECRET_SIZE );
	if( cryptStatusOK( status ) )
		*masterSecretLength = SSL_SECRET_SIZE;
	return( status );
	}
#else

int createSharedPremasterSecret( void *premasterSecret, 
								 int *premasterSecretLength,
								 const SESSION_INFO *sessionInfoPtr )
	{
	const ATTRIBUTE_LIST *attributeListPtr = \
				findSessionAttribute( sessionInfoPtr->attributeList,
									  CRYPT_SESSINFO_PASSWORD );
	STREAM stream;
	BYTE zeroes[ CRYPT_MAX_TEXTSIZE + 8 ];

	/* Write the PSK-derived premaster secret value:

		uint16	otherSecretLen
		byte[]	otherSecret
		uint16	pskLen
		byte[]	psk 
	
	   Because the TLS PRF splits the input into two halves, one half which
	   is processed by HMAC-MD5 and the other by HMAC-SHA1, it's necessary
	   to extend the PSK in some way to provide input to both halves of the
	   PRF.  In a rather dubious decision, the spec requires that the MD5
	   half be set to all zeroes, with only the SHA1 half being used.  To
	   achieve this, we write otherSecret as a number of zero bytes equal in 
	   length to the password */
	memset( zeroes, 0, CRYPT_MAX_TEXTSIZE );
	sMemOpen( &stream, premasterSecret, 
			  ( UINT16_SIZE + CRYPT_MAX_TEXTSIZE ) * 2 );
	if( attributeListPtr->flags & ATTR_FLAG_ENCODEDVALUE )
		{
		BYTE decodedValue[ CRYPT_MAX_TEXTSIZE + 8 ];
		int decodedValueLength;

		/* It's a cryptlib-style encoded password, decode it into its binary 
		   value */
		decodedValueLength = decodePKIUserValue( decodedValue,
											attributeListPtr->value,
											attributeListPtr->valueLength );
		if( cryptStatusError( decodedValueLength ) )
			{
			assert( NOTREACHED );
			return( decodedValueLength );
			}
		writeUint16( &stream, decodedValueLength );
		swrite( &stream, zeroes, decodedValueLength );
		writeUint16( &stream, decodedValueLength );
		swrite( &stream, decodedValue, decodedValueLength );
		zeroise( decodedValue, decodedValueLength );
		}
	else
		{
		writeUint16( &stream, attributeListPtr->valueLength );
		swrite( &stream, zeroes, attributeListPtr->valueLength );
		writeUint16( &stream, attributeListPtr->valueLength );
		swrite( &stream, attributeListPtr->value, 
				attributeListPtr->valueLength );
		}
	*premasterSecretLength = stell( &stream );
	sMemDisconnect( &stream );

	return( CRYPT_OK );
	}
#endif /* 0 */

/* Wrap/unwrap the pre-master secret */

int wrapPremasterSecret( SESSION_INFO *sessionInfoPtr, 
						 SSL_HANDSHAKE_INFO *handshakeInfo,
						 void *data, int *dataLength )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	RESOURCE_DATA msgData;
	int status;

	/* Clear return value */
	*dataLength = 0;

	/* Create the premaster secret and wrap it using the server's public 
	   key.  Note that the version that we advertise at this point is the 
	   version originally offered by the client in its hello message, not 
	   the version eventually negotiated for the connection.  This is 
	   designed to prevent rollback attacks (but see also the comment in
	   unwrapPremasterSecret() below) */
	handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
	handshakeInfo->premasterSecret[ 0 ] = SSL_MAJOR_VERSION;
	handshakeInfo->premasterSecret[ 1 ] = handshakeInfo->clientOfferedVersion;
	setMessageData( &msgData, 
					handshakeInfo->premasterSecret + VERSIONINFO_SIZE, 
					handshakeInfo->premasterSecretSize - VERSIONINFO_SIZE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_IATTRIBUTE_RANDOM );
	if( cryptStatusError( status ) )
		return( status );
	setMechanismWrapInfo( &mechanismInfo, data, CRYPT_MAX_PKCSIZE, 
						  handshakeInfo->premasterSecret, 
						  handshakeInfo->premasterSecretSize, CRYPT_UNUSED, 
						  sessionInfoPtr->iKeyexCryptContext, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, 
							  &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
	if( cryptStatusOK( status ) )
		*dataLength = mechanismInfo.wrappedDataLength;
	clearMechanismInfo( &mechanismInfo );

	return( status );
	}

int unwrapPremasterSecret( SESSION_INFO *sessionInfoPtr, 
						   SSL_HANDSHAKE_INFO *handshakeInfo,
						   const void *data, const int dataLength )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	int status;

	/* Decrypt the encrypted premaster secret.  In theory we could 
	   explicitly defend against Bleichenbacher-type attacks at this point 
	   by setting the premaster secret to a pseudorandom value if we get a 
	   bad data or (later) an incorrect version error and continuing as 
	   normal, however the attack depends on the server returning 
	   information required to pinpoint the cause of the failure and 
	   cryptlib just returns a generic "failed" response for any handshake 
	   failure, so this explicit defence isn't really necessary */
	handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
	setMechanismWrapInfo( &mechanismInfo, ( void * ) data, dataLength, 
						  handshakeInfo->premasterSecret, 
						  handshakeInfo->premasterSecretSize, CRYPT_UNUSED, 
						  sessionInfoPtr->privateKey, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT, 
							  &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
	if( cryptStatusOK( status ) && \
		mechanismInfo.keyDataLength != handshakeInfo->premasterSecretSize )
		status = CRYPT_ERROR_BADDATA;
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusError( status ) )
		return( status );

	/* Make sure that it looks OK.  Note that the version that we check for 
	   at this point is the version originally offered by the client in its 
	   hello message, not the version eventually negotiated for the 
	   connection.  This is designed to prevent rollback attacks */
	if( handshakeInfo->premasterSecret[ 0 ] != SSL_MAJOR_VERSION || \
		handshakeInfo->premasterSecret[ 1 ] != handshakeInfo->clientOfferedVersion )
		{
		/* Microsoft braindamage, even the latest versions of MSIE still send
		   the wrong version number for the premaster secret (making it look
		   like a rollback attack), so if we're expecting 3.1 and get 3.0, it's
		   MSIE screwing up */
		if( handshakeInfo->premasterSecret[ 0 ] == SSL_MAJOR_VERSION && \
			handshakeInfo->premasterSecret[ 1 ] == SSL_MINOR_VERSION_SSL && \
			sessionInfoPtr->version == SSL_MINOR_VERSION_SSL && \
			handshakeInfo->clientOfferedVersion == SSL_MINOR_VERSION_TLS )
			strcpy( sessionInfoPtr->errorMessage,
					"Warning: Accepting invalid premaster secret version "
					"3.0 (MSIE bug)" );
		else
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Invalid premaster secret version data 0x%02X 0x%02X, "
					"expected 0x03 0x%02X",
					handshakeInfo->premasterSecret[ 0 ],
					handshakeInfo->premasterSecret[ 1 ],
					handshakeInfo->clientOfferedVersion );
		}
	
	return( CRYPT_OK );
	}

/* Convert a pre-master secret to a master secret, and a master secret to 
   keying material */

int premasterToMaster( const SESSION_INFO *sessionInfoPtr, 
					   const SSL_HANDSHAKE_INFO *handshakeInfo, 
					   void *masterSecret, const int masterSecretLength )
	{
	MECHANISM_DERIVE_INFO mechanismInfo;
	BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE ];

	if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
		{
		memcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
		memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
				SSL_NONCE_SIZE );
		setMechanismDeriveInfo( &mechanismInfo, masterSecret, 
								masterSecretLength,
								handshakeInfo->premasterSecret, 
								handshakeInfo->premasterSecretSize,
								CRYPT_USE_DEFAULT, nonceBuffer,
								SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
		return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, 
								 &mechanismInfo, MECHANISM_DERIVE_SSL ) );
		}

	memcpy( nonceBuffer, "master secret", 13 );
	memcpy( nonceBuffer + 13, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
	memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
			SSL_NONCE_SIZE );
	setMechanismDeriveInfo( &mechanismInfo, masterSecret, masterSecretLength,
							handshakeInfo->premasterSecret, 
							handshakeInfo->premasterSecretSize,
							CRYPT_USE_DEFAULT, nonceBuffer,
							13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
	return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, 
							 &mechanismInfo, MECHANISM_DERIVE_TLS ) );
	}

int masterToKeys( const SESSION_INFO *sessionInfoPtr, 
				  const SSL_HANDSHAKE_INFO *handshakeInfo, 
				  const void *masterSecret, const int masterSecretLength,
				  void *keyBlock, const int keyBlockLength )
	{
	MECHANISM_DERIVE_INFO mechanismInfo;
	BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE ];

	if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
		{
		memcpy( nonceBuffer, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
		memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
				SSL_NONCE_SIZE );
		setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
								masterSecret, masterSecretLength, CRYPT_USE_DEFAULT,
								nonceBuffer, SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
		return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, 
								 &mechanismInfo, MECHANISM_DERIVE_SSL ) );
		}

	memcpy( nonceBuffer, "key expansion", 13 );
	memcpy( nonceBuffer + 13, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
	memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
			SSL_NONCE_SIZE );
	setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
							masterSecret, masterSecretLength, CRYPT_USE_DEFAULT,
							nonceBuffer, 13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
	return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, 
							 &mechanismInfo, MECHANISM_DERIVE_TLS ) );
	}

/* Load the SSL/TLS cryptovariables */

int loadKeys( SESSION_INFO *sessionInfoPtr, 
			  const SSL_HANDSHAKE_INFO *handshakeInfo, 
			  const BOOLEAN isClient, const void *keyBlock )
	{
	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
	RESOURCE_DATA msgData;
	BYTE *keyBlockPtr = ( BYTE * ) keyBlock;
	int status;

	/* Load the keys and secrets:

		( client_write_mac || server_write_mac || \
		  client_write_key || server_write_key || \
		  client_write_iv  || server_write_iv )

	   First, we load the MAC keys.  For TLS these are proper MAC keys, for
	   SSL we have to build the proto-HMAC ourselves from a straight hash
	   context so we store the raw cryptovariables rather than loading them
	   into a context */
	if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
		{
		memcpy( isClient ? sslInfo->macWriteSecret : sslInfo->macReadSecret,
				keyBlockPtr, sessionInfoPtr->authBlocksize );
		memcpy( isClient ? sslInfo->macReadSecret : sslInfo->macWriteSecret,
				keyBlockPtr + sessionInfoPtr->authBlocksize,
				sessionInfoPtr->authBlocksize );
		keyBlockPtr = keyBlockPtr + sessionInfoPtr->authBlocksize * 2;
		}
	else
		{
		setMessageData( &msgData, keyBlockPtr, sessionInfoPtr->authBlocksize );
		status = krnlSendMessage( isClient ? \
										sessionInfoPtr->iAuthOutContext : \
										sessionInfoPtr->iAuthInContext,
								  IMESSAGE_SETATTRIBUTE_S, &msgData, 
								  CRYPT_CTXINFO_KEY );
		if( cryptStatusError( status ) )
			return( status );
		setMessageData( &msgData, keyBlockPtr + sessionInfoPtr->authBlocksize,
						sessionInfoPtr->authBlocksize );
		status = krnlSendMessage( isClient ? \
										sessionInfoPtr->iAuthInContext: \
										sessionInfoPtr->iAuthOutContext,
								  IMESSAGE_SETATTRIBUTE_S, &msgData, 
								  CRYPT_CTXINFO_KEY );
		if( cryptStatusError( status ) )
			return( status );
		keyBlockPtr = keyBlockPtr + sessionInfoPtr->authBlocksize * 2;
		}

	/* Then we load the encryption keys */
	setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
	status = krnlSendMessage( isClient ? \
									sessionInfoPtr->iCryptOutContext : \
									sessionInfoPtr->iCryptInContext,
							  IMESSAGE_SETATTRIBUTE_S, &msgData, 
							  CRYPT_CTXINFO_KEY );
	keyBlockPtr += handshakeInfo->cryptKeysize;
	if( cryptStatusError( status ) )
		return( status );
	setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
	status = krnlSendMessage( isClient ? \
									sessionInfoPtr->iCryptInContext : \
									sessionInfoPtr->iCryptOutContext,
							  IMESSAGE_SETATTRIBUTE_S, &msgData, 
							  CRYPT_CTXINFO_KEY );
	keyBlockPtr += handshakeInfo->cryptKeysize;
	if( cryptStatusError( status ) )
		return( status );

	/* Finally we load the IVs if required.  This load is actually redundant
	   for TLS 1.1, which uses explicit IVs, but it's easier to just do it
	   anyway */
	if( isStreamCipher( sessionInfoPtr->cryptAlgo ) )
		return( CRYPT_OK );	/* No IV, we're done */
	setMessageData( &msgData, keyBlockPtr,
					sessionInfoPtr->cryptBlocksize );
	krnlSendMessage( isClient ? sessionInfoPtr->iCryptOutContext : \
								sessionInfoPtr->iCryptInContext,
					 IMESSAGE_SETATTRIBUTE_S, &msgData, 
					 CRYPT_CTXINFO_IV );
	keyBlockPtr += sessionInfoPtr->cryptBlocksize;
	setMessageData( &msgData, keyBlockPtr,
					sessionInfoPtr->cryptBlocksize );
	return( krnlSendMessage( isClient ? sessionInfoPtr->iCryptInContext : \
										sessionInfoPtr->iCryptOutContext,
							 IMESSAGE_SETATTRIBUTE_S, &msgData, 
							 CRYPT_CTXINFO_IV ) );
	}

/* TLS versions greater than 1.0 prepend an explicit IV to the data, the
   following function loads this from the packet data stream */

⌨️ 快捷键说明

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