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

📄 ssh2_cry.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
	if( cryptStatusOK( status ) )
		status = loadCryptovariable( isClient ? \
										sessionInfoPtr->iCryptOutContext : \
										sessionInfoPtr->iCryptInContext,
									 CRYPT_CTXINFO_KEY, keySize,
									 hashFunction, initialHashInfo, "C",
									 handshakeInfo->sessionID,
									 handshakeInfo->sessionIDlength );
	if( cryptStatusOK( status ) )
		status = loadCryptovariable( isClient ? \
										sessionInfoPtr->iCryptInContext : \
										sessionInfoPtr->iCryptOutContext,
									 CRYPT_CTXINFO_KEY, keySize,
									 hashFunction, initialHashInfo, "D",
									 handshakeInfo->sessionID,
									 handshakeInfo->sessionIDlength );
	if( cryptStatusOK( status ) )
		status = loadCryptovariable( isClient ? \
										sessionInfoPtr->iAuthOutContext : \
										sessionInfoPtr->iAuthInContext,
									 CRYPT_CTXINFO_KEY,
									 ( sessionInfoPtr->protocolFlags & \
									   SSH_PFLAG_HMACKEYSIZE ) ? \
										SSH2_FIXED_KEY_SIZE : \
										sessionInfoPtr->authBlocksize,
									 hashFunction, initialHashInfo, "E",
									 handshakeInfo->sessionID,
									 handshakeInfo->sessionIDlength );
	if( cryptStatusOK( status ) )
		status = loadCryptovariable( isClient ? \
										sessionInfoPtr->iAuthInContext : \
										sessionInfoPtr->iAuthOutContext,
									 CRYPT_CTXINFO_KEY,
									 ( sessionInfoPtr->protocolFlags & \
									   SSH_PFLAG_HMACKEYSIZE ) ? \
										SSH2_FIXED_KEY_SIZE : \
										sessionInfoPtr->authBlocksize,
									 hashFunction, initialHashInfo, "F",
									 handshakeInfo->sessionID,
									 handshakeInfo->sessionIDlength );
	return( status );
	}

/****************************************************************************
*																			*
*								Hash/MAC Data								*
*																			*
****************************************************************************/

/* Hash a value encoded as an SSH string and as an MPI */

int hashAsString( const CRYPT_CONTEXT iHashContext,
				  const BYTE *data, const int dataLength )
	{
	BYTE buffer[ 128 ], *bufPtr = buffer;
	int status;

	/* Prepend the string length to the data and hash it.  If it'll fit into
	   the buffer we copy it over to save a kernel call */
	mputLong( bufPtr, dataLength );
	if( dataLength <= 128 - LENGTH_SIZE )
		{
		memcpy( buffer + LENGTH_SIZE, data, dataLength );
		status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,
								  LENGTH_SIZE + dataLength );
		}
	else
		{
		krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,
						 LENGTH_SIZE );
		status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
								  ( void * ) data, dataLength );
		}
	zeroise( buffer, 128 );

	return( status );
	}

int hashAsMPI( const CRYPT_CONTEXT iHashContext, const BYTE *data, 
			   const int dataLength )
	{
	BYTE buffer[ 8 ], *bufPtr = buffer;
	const int length = ( data[ 0 ] & 0x80 ) ? dataLength + 1 : dataLength;
	int headerLength = LENGTH_SIZE;

	/* Prepend the MPI length to the data and hash it.  Since this is often
	   sensitive data, we don't take a local copy but hash it in two parts */
	mputLong( bufPtr, length );
	if( data[ 0 ] & 0x80 )
		{
		/* MPIs are signed values */
		*bufPtr++ = 0;
		headerLength++;
		}
	krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, headerLength );
	return( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
							  ( void * ) data, dataLength ) );
	}

/* MAC the payload of a data packet.  Since we may not have the whole packet
   available at once, we can do this in one go or incrementally */

int macPayload( const CRYPT_CONTEXT iMacContext, const long seqNo, 
				const BYTE *data, const int dataLength, 
				const int packetDataLength, const MAC_TYPE macType,
				const int macLength, const BOOLEAN isRead )
	{
	int status;

	/* MAC the data and either compare the result to the stored MAC or 
	   append the MAC value to the data:

		HMAC( seqNo || length || payload )

	   During the handshake process we have the entire packet at hand 
	   (dataLength == packetDataLength) and can process it at once.  When 
	   we're processing payload data (dataLength a subset of 
	   packetDataLength) we have to process the header separately in order 
	   to determine how much more we have to read, so we have to MAC the 
	   packet in two parts */
	if( macType == MAC_START || macType == MAC_ALL )
		{
		BYTE buffer[ 16 ], *bufPtr = buffer;
		int length = ( macType == MAC_ALL ) ? dataLength : packetDataLength;

		assert( ( macType == MAC_ALL && packetDataLength == 0 ) || \
				( macType == MAC_START && packetDataLength >= dataLength ) );

		/* Since the payload had the length stripped during the speculative
		   read if we're MAC'ing read data, we have to reconstruct it and 
		   hash it separately before we hash the data.  If we're doing the 
		   hash in parts, the amount of data being hashed won't match the 
		   overall length so the caller needs to supply the overall packet 
		   length as well as the current data length */
		mputLong( bufPtr, seqNo );
		mputLong( bufPtr, length );
		krnlSendMessage( iMacContext, IMESSAGE_DELETEATTRIBUTE, NULL,
						 CRYPT_CTXINFO_HASHVALUE );
		krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, buffer,
						 UINT32_SIZE + LENGTH_SIZE );
		}
	if( dataLength > 0 )
		status = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, 
								  ( void * ) data, dataLength );
	if( macType == MAC_END || macType == MAC_ALL )
		{
		RESOURCE_DATA msgData;

		status = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, "", 0 );
		if( cryptStatusError( status ) )
			return( status );
		setMessageData( &msgData, ( BYTE * ) data + dataLength, macLength );
		if( isRead )
			/* It's a read, compare the MAC value to the stored MAC
			   value */
			status = krnlSendMessage( iMacContext, IMESSAGE_COMPARE, 
									  &msgData, MESSAGE_COMPARE_HASH );
		else
			/* It's a write, append the MAC value to the data */
			status = krnlSendMessage( iMacContext, IMESSAGE_GETATTRIBUTE_S, 
									  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}

	return( status );
	}

/****************************************************************************
*																			*
*							Miscellaneous Functions							*
*																			*
****************************************************************************/

/* Complete the DH key agreement */

int completeKeyex( SESSION_INFO *sessionInfoPtr, 
				   SSH_HANDSHAKE_INFO *handshakeInfo, 
				   const BOOLEAN isServer )
	{
	KEYAGREE_PARAMS keyAgreeParams;
	RESOURCE_DATA msgData;
	STREAM stream;
	int status;

	/* Read the other side's key agreement information.  Note that the size 
	   check has already been performed at a higher level when the overall 
	   key agreement value was read, this is a secondary check of the MPI
	   payload */
	memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
	if( isServer )
		sMemConnect( &stream, handshakeInfo->clientKeyexValue,
					 handshakeInfo->clientKeyexValueLength );
	else
		sMemConnect( &stream, handshakeInfo->serverKeyexValue,
					 handshakeInfo->serverKeyexValueLength );
	status = readInteger32( &stream, keyAgreeParams.publicValue, 
							&keyAgreeParams.publicValueLen, 
							bitsToBytes( MIN_PKCSIZE_BITS ),
							CRYPT_MAX_PKCSIZE );
	sMemDisconnect( &stream );
	if( cryptStatusOK( status ) && \
		!isValidDHsize( keyAgreeParams.publicValueLen, 
						handshakeInfo->serverKeySize, 0 ) )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
				"Invalid DH phase 1 MPI" );

	/* Perform phase 2 of the DH key agreement */
	status = krnlSendMessage( handshakeInfo->iServerCryptContext,
							  IMESSAGE_CTX_DECRYPT, &keyAgreeParams,
							  sizeof( KEYAGREE_PARAMS ) );
	if( cryptStatusOK( status ) )
		{
		memcpy( handshakeInfo->secretValue, keyAgreeParams.wrappedKey,
				keyAgreeParams.wrappedKeyLen );
		handshakeInfo->secretValueLength = keyAgreeParams.wrappedKeyLen;
		}
	zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
	if( cryptStatusError( status ) )
		return( status );

	/* If we're using ephemeral DH, hash the requested keyex key length(s) 
	   and DH p and g values.  Since this has been deferred until long after 
	   the keyex negotiation took place, we have to recreate the original 
	   encoded values here */
	if( handshakeInfo->requestedServerKeySize > 0 )
		{
		BYTE keyexBuffer[ 128 + ( CRYPT_MAX_PKCSIZE * 2 ) ];
		const int extraLength = LENGTH_SIZE + sizeofString32( "ssh-dh", 6 );

		krnlSendMessage( handshakeInfo->iExchangeHashcontext,
						 IMESSAGE_CTX_HASH, 
						 handshakeInfo->encodedReqKeySizes, 
						 handshakeInfo->encodedReqKeySizesLength );
		setMessageData( &msgData, keyexBuffer, 
						128 + ( CRYPT_MAX_PKCSIZE * 2 ) );
		status = krnlSendMessage( handshakeInfo->iServerCryptContext,
								  IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_KEY_SSH2 );
		if( cryptStatusError( status ) )
			return( status );
		krnlSendMessage( handshakeInfo->iExchangeHashcontext, 
						 IMESSAGE_CTX_HASH, keyexBuffer + extraLength, 
						 msgData.length - extraLength );
		}

	/* Hash the client and server DH values and shared secret */
	krnlSendMessage( handshakeInfo->iExchangeHashcontext, IMESSAGE_CTX_HASH, 
					 handshakeInfo->clientKeyexValue,
					 handshakeInfo->clientKeyexValueLength );
	krnlSendMessage( handshakeInfo->iExchangeHashcontext, IMESSAGE_CTX_HASH,
					 handshakeInfo->serverKeyexValue,
					 handshakeInfo->serverKeyexValueLength );
	status = hashAsMPI( handshakeInfo->iExchangeHashcontext,
						handshakeInfo->secretValue,
						handshakeInfo->secretValueLength );
	if( cryptStatusError( status ) )
		return( status );

	/* Complete the hashing to obtain the exchange hash and then hash *that*
	   to get the hash that the server signs and sends to the client.  The
	   overall hashed data for the exchange hash is:

		string	V_C, client version string (CR and NL excluded)
		string	V_S, server version string (CR and NL excluded)
		string	I_C, client hello
		string	I_S, server hello
		string	K_S, the host key
	 [[	uint32	min, min.preferred keyex key size for ephemeral DH ]]
	  [	uint32	n, preferred keyex key size for ephemeral DH ]
	 [[	uint32	max, max.preferred keyex key size for ephemeral DH ]]
	  [	mpint	p, DH p for ephemeral DH ]
	  [	mpint	g, DH g for ephemeral DH ]
		mpint	e, client DH keyex value
		mpint	f, server DH keyex value
		mpint	K, the shared secret

	   The client and server version string ahd hellos and the host key were
	   hashed inline during the handshake.  The optional parameters are for 
	   negotiated DH values (see the conditional-hashing code above).  The 
	   double-optional parameters are for the revised version of the DH 
	   negotiation mechanism, the original only had n, the revised version 
	   allowed a { min, n, max } range */
	krnlSendMessage( handshakeInfo->iExchangeHashcontext, IMESSAGE_CTX_HASH,
					 "", 0 );
	setMessageData( &msgData, handshakeInfo->sessionID, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( handshakeInfo->iExchangeHashcontext,
							  IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusError( status ) )
		return( status );
	handshakeInfo->sessionIDlength = msgData.length;
	krnlSendMessage( handshakeInfo->iExchangeHashcontext,
					 IMESSAGE_DELETEATTRIBUTE, NULL,
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( handshakeInfo->iExchangeHashcontext,
					 IMESSAGE_CTX_HASH, handshakeInfo->sessionID,
					 handshakeInfo->sessionIDlength );
	return( krnlSendMessage( handshakeInfo->iExchangeHashcontext,
							 IMESSAGE_CTX_HASH, "", 0 ) );
	}
#endif /* USE_SSH2 */

⌨️ 快捷键说明

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