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

📄 ssh.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
	if( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
		{
		krnlSendNotifier( sessionInfoPtr->iAuthInContext,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		sessionInfoPtr->iAuthInContext = CRYPT_ERROR;
		}
	if( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )
		{
		krnlSendNotifier( sessionInfoPtr->iAuthOutContext,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		sessionInfoPtr->iAuthOutContext = CRYPT_ERROR;
		}
	}

static int initSecurityContexts( SESSION_INFO *sessionInfoPtr )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int status;

	setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusOK( status ) )
		{
		sessionInfoPtr->iCryptInContext = createInfo.cryptHandle;
		setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		}
	if( cryptStatusOK( status ) )
		{
		int blockSize;

		sessionInfoPtr->iCryptOutContext = createInfo.cryptHandle;
		krnlSendMessage( sessionInfoPtr->iCryptInContext,
						 RESOURCE_IMESSAGE_GETATTRIBUTE, &blockSize,
						 CRYPT_CTXINFO_BLOCKSIZE );
		sessionInfoPtr->cryptBlocksize = blockSize;
		}
	if( cryptStatusOK( status ) && sessionInfoPtr->version == 1 )
		{
		/* SSHv1 uses some stream ciphers, for which we have to set the
		   mode explicitly */
		if( sessionInfoPtr->cryptAlgo == CRYPT_ALGO_RC4 || \
			sessionInfoPtr->cryptAlgo == CRYPT_ALGO_IDEA )
			{
			const int cryptMode = \
						( sessionInfoPtr->cryptAlgo == CRYPT_ALGO_RC4 ) ? \
						CRYPT_MODE_OFB : CRYPT_MODE_CFB;

			status = krnlSendMessage( createInfo.cryptHandle,
								RESOURCE_IMESSAGE_SETATTRIBUTE,
								( void * ) &cryptMode, CRYPT_CTXINFO_MODE );
			if( cryptStatusOK( status ) )
				status = krnlSendMessage( createInfo.cryptHandle,
								RESOURCE_IMESSAGE_SETATTRIBUTE,
								( void * ) &cryptMode, CRYPT_CTXINFO_MODE );
			}
		}
	if( cryptStatusOK( status ) && sessionInfoPtr->version == 2 )
		{
		setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->integrityAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		if( cryptStatusOK( status ) )
			{
			sessionInfoPtr->iAuthInContext = createInfo.cryptHandle;
			setMessageCreateObjectInfo( &createInfo, 
										sessionInfoPtr->integrityAlgo );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
									  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
									  &createInfo, OBJECT_TYPE_CONTEXT );
			}
		if( cryptStatusOK( status ) )
			{
			int blockSize;

			sessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;
			krnlSendMessage( sessionInfoPtr->iAuthInContext,
							 RESOURCE_IMESSAGE_GETATTRIBUTE, &blockSize,
							 CRYPT_CTXINFO_BLOCKSIZE );
			sessionInfoPtr->authBlocksize = blockSize;
			}
		}
	if( cryptStatusError( status ) )
		/* One or more of the contexts couldn't be created, destroy all the 
		   contexts which have been created so far */
		destroySecurityContexts( sessionInfoPtr );
	return( status );
	}

/* Read the SSH version information string */

static int readVersionString( SESSION_INFO *sessionInfoPtr )
	{
	int i, status;

	/* Read the server version info.  This is rather ugly since it's a
	   variable-length string terminated with a newline, so we have to 
	   process it a character at a time after the initial fixed data */
	status = sread( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer, 
					SSH_ID_SIZE );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream, 
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	if( memcmp( sessionInfoPtr->receiveBuffer, SSH_ID, SSH_ID_SIZE ) )
		return( CRYPT_ERROR_BADDATA );
	for( i = 0; i < SSH_ID_MAX_SIZE - SSH_ID_SIZE; i++ )
		{
		status = sread( &sessionInfoPtr->stream, 
						sessionInfoPtr->receiveBuffer + i, 1 );
		if( cryptStatusError( status ) )
			{
			sNetGetErrorInfo( &sessionInfoPtr->stream, 
							  sessionInfoPtr->errorMessage,
							  &sessionInfoPtr->errorCode );
			return( status );
			}
		if( sessionInfoPtr->receiveBuffer[ i ] == '\n' )
			break;
		}
	if( ( i < 5 ) || ( i >= SSH_ID_MAX_SIZE - SSH_ID_SIZE ) )
		return( CRYPT_ERROR_BADDATA );

	/* Null-terminate the string so we can hash it to create the SSHv2
	   exchange hash */
	while( i > 0 && \
		   ( sessionInfoPtr->receiveBuffer[ i - 1 ] == '\r' || \
			 sessionInfoPtr->receiveBuffer[ i - 1 ] == '\n' ) )
		i--;
	sessionInfoPtr->receiveBuffer[ i ] = '\0';

	/* Determine which version we're talking to */
	if( sessionInfoPtr->receiveBuffer[ 0 ] == '1' )
		{
		if( !memcmp( sessionInfoPtr->receiveBuffer, "1.99", 4 ) )
			/* SSHv2 server in backwards-compatibility mode */
			sessionInfoPtr->version = 2;
		else
			{
			/* If the caller has specifically asked for SSHv2 but all that 
			   the server offers is SSHv1, we can't continue */
			if( sessionInfoPtr->version == 2 )
				return( CRYPT_ERROR_NOSECURE );
			sessionInfoPtr->version = 1;
			}
		}
	else
		if( sessionInfoPtr->receiveBuffer[ 0 ] == '2' )
			sessionInfoPtr->version = 2;
		else
			return( CRYPT_ERROR_BADDATA );

	/* Check whether the peer is using cryptlib */
	if( !memcmp( sessionInfoPtr->receiveBuffer, SSH_ID_STRING + SSH_ID_SIZE,
				 strlen( SSH_ID_STRING + SSH_ID_SIZE ) ) || \
		!memcmp( sessionInfoPtr->receiveBuffer, SSH2_ID_STRING + SSH_ID_SIZE,
				 strlen( SSH2_ID_STRING + SSH_ID_SIZE ) ) )
		sessionInfoPtr->flags |= SESSION_ISCRYPTLIB;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								SSHv1 Functions								*
*																			*
****************************************************************************/

/* Calculate the CRC32 for a data block.  This uses the slightly nonstandard
   variant from SSH which calculates the UART-style reflected value and
   doesn't pre-set the value to all ones (done to to catch leading zero
   bytes, which happens quite a bit with SSH because of the 32-bit length at
   the start) or XOR it with all ones before returning it.  This means that
   the resulting CRC is not the same as the one in Ethernet, Pkzip, and most
   other implementations */

static const LONG crc32table[] = {
	0x00000000UL, 0x77073096UL, 0xEE0E612CUL, 0x990951BAUL,
	0x076DC419UL, 0x706AF48FUL, 0xE963A535UL, 0x9E6495A3UL,
	0x0EDB8832UL, 0x79DCB8A4UL, 0xE0D5E91EUL, 0x97D2D988UL,
	0x09B64C2BUL, 0x7EB17CBDUL, 0xE7B82D07UL, 0x90BF1D91UL,
	0x1DB71064UL, 0x6AB020F2UL, 0xF3B97148UL, 0x84BE41DEUL,
	0x1ADAD47DUL, 0x6DDDE4EBUL, 0xF4D4B551UL, 0x83D385C7UL,
	0x136C9856UL, 0x646BA8C0UL, 0xFD62F97AUL, 0x8A65C9ECUL,
	0x14015C4FUL, 0x63066CD9UL, 0xFA0F3D63UL, 0x8D080DF5UL,
	0x3B6E20C8UL, 0x4C69105EUL, 0xD56041E4UL, 0xA2677172UL,
	0x3C03E4D1UL, 0x4B04D447UL, 0xD20D85FDUL, 0xA50AB56BUL,
	0x35B5A8FAUL, 0x42B2986CUL, 0xDBBBC9D6UL, 0xACBCF940UL,
	0x32D86CE3UL, 0x45DF5C75UL, 0xDCD60DCFUL, 0xABD13D59UL,
	0x26D930ACUL, 0x51DE003AUL, 0xC8D75180UL, 0xBFD06116UL,
	0x21B4F4B5UL, 0x56B3C423UL, 0xCFBA9599UL, 0xB8BDA50FUL,
	0x2802B89EUL, 0x5F058808UL, 0xC60CD9B2UL, 0xB10BE924UL,
	0x2F6F7C87UL, 0x58684C11UL, 0xC1611DABUL, 0xB6662D3DUL,
	0x76DC4190UL, 0x01DB7106UL, 0x98D220BCUL, 0xEFD5102AUL,
	0x71B18589UL, 0x06B6B51FUL, 0x9FBFE4A5UL, 0xE8B8D433UL,
	0x7807C9A2UL, 0x0F00F934UL, 0x9609A88EUL, 0xE10E9818UL,
	0x7F6A0DBBUL, 0x086D3D2DUL, 0x91646C97UL, 0xE6635C01UL,
	0x6B6B51F4UL, 0x1C6C6162UL, 0x856530D8UL, 0xF262004EUL,
	0x6C0695EDUL, 0x1B01A57BUL, 0x8208F4C1UL, 0xF50FC457UL,
	0x65B0D9C6UL, 0x12B7E950UL, 0x8BBEB8EAUL, 0xFCB9887CUL,
	0x62DD1DDFUL, 0x15DA2D49UL, 0x8CD37CF3UL, 0xFBD44C65UL,
	0x4DB26158UL, 0x3AB551CEUL, 0xA3BC0074UL, 0xD4BB30E2UL,
	0x4ADFA541UL, 0x3DD895D7UL, 0xA4D1C46DUL, 0xD3D6F4FBUL,
	0x4369E96AUL, 0x346ED9FCUL, 0xAD678846UL, 0xDA60B8D0UL,
	0x44042D73UL, 0x33031DE5UL, 0xAA0A4C5FUL, 0xDD0D7CC9UL,
	0x5005713CUL, 0x270241AAUL, 0xBE0B1010UL, 0xC90C2086UL,
	0x5768B525UL, 0x206F85B3UL, 0xB966D409UL, 0xCE61E49FUL,
	0x5EDEF90EUL, 0x29D9C998UL, 0xB0D09822UL, 0xC7D7A8B4UL,
	0x59B33D17UL, 0x2EB40D81UL, 0xB7BD5C3BUL, 0xC0BA6CADUL,
	0xEDB88320UL, 0x9ABFB3B6UL, 0x03B6E20CUL, 0x74B1D29AUL,
	0xEAD54739UL, 0x9DD277AFUL, 0x04DB2615UL, 0x73DC1683UL,
	0xE3630B12UL, 0x94643B84UL, 0x0D6D6A3EUL, 0x7A6A5AA8UL,
	0xE40ECF0BUL, 0x9309FF9DUL, 0x0A00AE27UL, 0x7D079EB1UL,
	0xF00F9344UL, 0x8708A3D2UL, 0x1E01F268UL, 0x6906C2FEUL,
	0xF762575DUL, 0x806567CBUL, 0x196C3671UL, 0x6E6B06E7UL,
	0xFED41B76UL, 0x89D32BE0UL, 0x10DA7A5AUL, 0x67DD4ACCUL,
	0xF9B9DF6FUL, 0x8EBEEFF9UL, 0x17B7BE43UL, 0x60B08ED5UL,
	0xD6D6A3E8UL, 0xA1D1937EUL, 0x38D8C2C4UL, 0x4FDFF252UL,
	0xD1BB67F1UL, 0xA6BC5767UL, 0x3FB506DDUL, 0x48B2364BUL,
	0xD80D2BDAUL, 0xAF0A1B4CUL, 0x36034AF6UL, 0x41047A60UL,
	0xDF60EFC3UL, 0xA867DF55UL, 0x316E8EEFUL, 0x4669BE79UL,
	0xCB61B38CUL, 0xBC66831AUL, 0x256FD2A0UL, 0x5268E236UL,
	0xCC0C7795UL, 0xBB0B4703UL, 0x220216B9UL, 0x5505262FUL,
	0xC5BA3BBEUL, 0xB2BD0B28UL, 0x2BB45A92UL, 0x5CB36A04UL,
	0xC2D7FFA7UL, 0xB5D0CF31UL, 0x2CD99E8BUL, 0x5BDEAE1DUL,
	0x9B64C2B0UL, 0xEC63F226UL, 0x756AA39CUL, 0x026D930AUL,
	0x9C0906A9UL, 0xEB0E363FUL, 0x72076785UL, 0x05005713UL,
	0x95BF4A82UL, 0xE2B87A14UL, 0x7BB12BAEUL, 0x0CB61B38UL,
	0x92D28E9BUL, 0xE5D5BE0DUL, 0x7CDCEFB7UL, 0x0BDBDF21UL,
	0x86D3D2D4UL, 0xF1D4E242UL, 0x68DDB3F8UL, 0x1FDA836EUL,
	0x81BE16CDUL, 0xF6B9265BUL, 0x6FB077E1UL, 0x18B74777UL,
	0x88085AE6UL, 0xFF0F6A70UL, 0x66063BCAUL, 0x11010B5CUL,
	0x8F659EFFUL, 0xF862AE69UL, 0x616BFFD3UL, 0x166CCF45UL,
	0xA00AE278UL, 0xD70DD2EEUL, 0x4E048354UL, 0x3903B3C2UL,
	0xA7672661UL, 0xD06016F7UL, 0x4969474DUL, 0x3E6E77DBUL,
	0xAED16A4AUL, 0xD9D65ADCUL, 0x40DF0B66UL, 0x37D83BF0UL,
	0xA9BCAE53UL, 0xDEBB9EC5UL, 0x47B2CF7FUL, 0x30B5FFE9UL,
	0xBDBDF21CUL, 0xCABAC28AUL, 0x53B39330UL, 0x24B4A3A6UL,
	0xBAD03605UL, 0xCDD70693UL, 0x54DE5729UL, 0x23D967BFUL,
	0xB3667A2EUL, 0xC4614AB8UL, 0x5D681B02UL, 0x2A6F2B94UL,
	0xB40BBE37UL, 0xC30C8EA1UL, 0x5A05DF1BUL, 0x2D02EF8DUL
	};

static LONG calculateCRC( const BYTE *data, const int dataLength )
	{
	LONG crc32 = 0;
	int i;

	for( i = 0; i < dataLength; i++ )
		crc32 = crc32table[ ( int ) ( crc32 ^ data[ i ] ) & 0xFF ] ^ ( crc32 >> 8 );

	return( crc32 );
	}

/* If we detect that the other side is also running cryptlib, we use a
   truncated MAC instead of CRC32 once we're running in secure mode.  This 
   prevents extension attacks on the CRC-protected data.  The reason for 
   the truncation is to make it the same length as the CRC, this makes it a 
   bit weaker than a full-length MAC but no weaker than a cryptographically 
   strong CRC (in any case the chances of a successful attack are only 1/2^31,
   and you get only one chance to get it right) */

static LONG calculateTruncatedMAC( const CRYPT_CONTEXT iMacContext,
								   const BYTE *data, const int dataLength )
	{
	RESOURCE_DATA msgData;
	BYTE macBuffer[ CRYPT_MAX_HASHSIZE ], *bufPtr = macBuffer;
	LONG macValue;
	int status;

	/* MAC the data and return the 32-bit truncated MAC value */
	krnlSendMessage( iMacContext, RESOURCE_IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CTXINFO_HASHVALUE );
	krnlSendMessage( iMacContext, RESOURCE_IMESSAGE_CTX_HASH, 
					 ( void * ) data, dataLength );
	krnlSendMessage( iMacContext, RESOURCE_IMESSAGE_CTX_HASH, "", 0 );
	setResourceData( &msgData, macBuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( iMacContext, RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusError( status ) )
		return( 0 );	/* Will cause a protocol failure */
	macValue = mgetBLong( bufPtr );

	return( macValue );
	}

/* Convert an SSHv1 algorithm ID to a cryptlib ID in preferred-algorithm 
   order, and return a list of available algorithms in SSHv1 cipher-mask 
   format.  We can't use 3DES since this uses inner-CBC which is both 
   nonstandard and has known (although not serious) weaknesses.  If we 
   wanted to implement it in a portable manner (ie usable with external 
   drivers and devices) we'd have to synthesize it using three lots of 
   DES-CBC since nothing implements the variant which SSHv1 uses */

static CRYPT_ALGO maskToAlgoID( const int value )
	{
	if( ( value & ( 1 << SSH_CIPHER_BLOWFISH ) ) && \
		algoAvailable( CRYPT_ALGO_BLOWFISH ) )
		return( CRYPT_ALGO_BLOWFISH );
	if( ( value & ( 1 << SSH_CIPHER_IDEA ) ) && \
		algoAvailable( CRYPT_ALGO_IDEA ) )
		return( CRYPT_ALGO_IDEA );
	if( ( value & ( 1 << SSH_CIPHER_RC4 ) ) && \
		algoAvailable( CRYPT_ALGO_RC4 ) )
		return( CRYPT_ALGO_RC4 );
	if( value & ( 1 << SSH_CIPHER_DES ) )
		return( CRYPT_ALGO_DES );

	return( CRYPT_ALGO_NONE );
	}

static CRYPT_ALGO sshIDToAlgoID( const int value )
	{
	switch( value )
		{
		case SSH_CIPHER_IDEA:
			if( algoAvailable( CRYPT_ALGO_IDEA ) )
				return( CRYPT_ALGO_IDEA );
			break;
	
		case SSH_CIPHER_DES:
			return( CRYPT_ALGO_DES );
	
		case SSH_CIPHER_RC4:
			if( algoAvailable( CRYPT_ALGO_RC4 ) )
				return( CRYPT_ALGO_RC4 );
			break;
	

⌨️ 快捷键说明

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