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

📄 pgpsecsh.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 4 页
字号:
/*____________________________________________________________________________
	Copyright (C) 2002 PGP Corporation
	All rights reserved.
	
	Platform independent implementation of SECSH v 1.5
	
	$Id: pgpSECSH.c,v 1.7 2002/08/06 20:11:13 dallen Exp $
____________________________________________________________________________*/

#include "pgpSECSHPriv.h"

#include "pgpErrors.h"
#include "pgpContext.h"
#include "pgpMem.h"
#include "pgpEndianConversion.h"
#include "pgpHash.h"
#include "pgpHMAC.h"
#include "pgpPublicKey.h"
#include "pgpSymmetricCipher.h"
#include "pgpCBC.h"
#include "pgpCFB.h"
#include "pgpKeys.h"
#include "pgpFeatures.h"
#include "pgpPFLPriv.h"
#include "pgpKeyPriv.h"
#include "pgpBigNum.h"

#include "pgpOptionListPriv.h"

#include <string.h>


#define CKERR			if( err ) goto done	
#define CKNULL(p)		if( IsNull(p) ) {					\
							err = kPGPError_OutOfMemory;	\
							goto done; }
#define FATALSECSH( x )	{									\
			err = x;										\
			session->state = kPGPsecsh_FatalErrorState;		\
			goto done;	}
#define CRC32_POLY		0xedb88320L
#define SECSHIDPREFIX	"SSH-"
#define	SECSHID			"SSH-1.4-PGPTest1.0\n"
#define SECSHNUMCLIENTSTATES	5
#define SECSHNUMEVENTS			5

/* -1 is ignored, -2 is an error */
static PGPInt8 kPGPsecsh_ClientStateTable[SECSHNUMCLIENTSTATES][SECSHNUMEVENTS] =
{
	/*		 S	 F	PK	CH	 D	*/
{	/* 0 */	-2,	-2,	 1,	-2,	 0,	},		/* Waiting for Server PK */
{	/* 1 */	 2,	-2,	-2,	-2,	 1,	},		/* Sent session key */
{	/* 2 */	 5,	 3,	-2,	-2,	 2,	},		/* Sent user name */
{	/* 3 */	-2,	-2,	-2,	 4,	 3,	},		/* Requested RSA challenge */
{	/* 4 */	 5,	-2,	-2,	-2,	 4,	}		/* Sent RSA response */
};


	PGPInt8
pgpSECSHNextState(
	PGPsecshSessionPriv *	session,
	PGPByte					event )
{
	PGPInt8					newState;
	
	pgpAssert( session->isClientSide );
	newState = kPGPsecsh_ClientStateTable[session->intState][event];
	if( newState == -2 )
		session->state = kPGPsecsh_FatalErrorState;
	else if( newState >= 0 )
		session->intState = newState;
	return newState;
}



	static void
sCalculateCRC(
	PGPByte const *		inBuffer,
	PGPSize				inLength,
	PGPByte *			outCRC )
{
	PGPUInt32 crc = 0;
	PGPUInt32 b;
	PGPUInt32 i;

	while( inLength-- )
	{
		crc ^= *inBuffer++;
		for( i = 0; i < 8; i++ )
		{
			b = (crc & 1);
			crc >>= 1;
			if( b )
				crc ^= CRC32_POLY;
		}
	}
	PGPUInt32ToEndian( crc, kPGPBigEndian, outCRC );
}


/* Return the size in bits of the bignum stored in bigendian form in
 * inBuffer.  Return outOffset as the offset to the first nonzero
 * byte.
 */
	static PGPUInt16
sCountBits(
	const PGPByte *		inBuffer,
	PGPSize				inLength,
	PGPSize *			outOffset )
{
	PGPSize				off;
	PGPUInt16			cnt;

	for( off=0; off<inLength; ++off )
		if( inBuffer[off] != 0 )
			break;
	*outOffset = off;
	if( off == inLength )
		return 0;
	for( cnt=7; (inBuffer[off] & (1<<cnt))==0; --cnt )
		;
	return cnt + 8*(inLength - off - 1);
}

/*
 * Starting with RSA key data in SECSH format (exponent then modulus),
 * create a PGP key with that data and return the keydb and key.
 */
	static PGPError
sDataToPGPKey (
	PGPsecshSessionPriv *	session,
	PGPByte *				inBuffer,
	PGPUInt32				inLength,
	PGPUInt32				*outDataUsed,
	PGPKeyDBRef *			outKDB,
	PGPKeyDBObjRef *		outKey)
{
	PGPUInt32				expbytes,
							modbytes;
	PGPUInt32				keybufLength;
	PGPUInt32				len = inLength;
	PGPByte *				p = inBuffer;
	PGPByte					*bp,
							*exponent,
							*modulus;
	PGPKeyIterRef			kiter;
	PGPKeyDBRef				kdb;
	PGPKeyDBObjRef			key;
	PGPByte *				pgpBuffer = NULL;
	PGPSize					bufLength = 0;
	PGPError				err = kPGPError_NoErr;

	*outDataUsed = 0;
	*outKDB = kInvalidPGPKeyDBRef;
	*outKey = kInvalidPGPKeyDBObjRef;

	expbytes = (((p[0]<<8) | p[1]) + 7) / 8;
	if( len < expbytes + 2 )
	{
		(void)pgpSECSHAlert( session,	kPGPsecsh_AL_FatalAlert,
									kPGPsecsh_AT_DecodeError );
		FATALSECSH( kPGPError_SECSHProtocolViolation );
	}
	exponent = p;
	p += expbytes + 2;
	len -= expbytes + 2;
	modbytes = (((p[0]<<8) | p[1]) + 7) / 8;
	if( len < modbytes + 2 )
	{
		(void)pgpSECSHAlert( session,	kPGPsecsh_AL_FatalAlert,
									kPGPsecsh_AT_DecodeError );
		FATALSECSH( kPGPError_SECSHProtocolViolation );
	}
	modulus = p;
	p += modbytes + 2;
	len -= modbytes + 2;

	keybufLength = 1 + 2 + 1 + 4 + 2 + 1 + 2 + modbytes + 2 + expbytes;
	bufLength = keybufLength + 2 + strlen( session->hostName );
	pgpBuffer = (PGPByte *) PGPNewData(session->memMgr, bufLength, 0 );
	CKNULL( pgpBuffer );
	bp = pgpBuffer;
	*bp++ = 0x99; /* RSA key buffer */
	*bp++ = ((keybufLength-3)>>8) & 0xff;
	*bp++ = (keybufLength-3) & 0xff;
	*bp++ = 0x03; /* key version */
	*bp++ = 0x00; /* creation date */
	*bp++ = 0x00;
	*bp++ = 0x00;
	*bp++ = 0x00;
	*bp++ = 0x00; /* expiration interval */
	*bp++ = 0x00;
	*bp++ = 0x01; /* key type (1 = RSA) */
	pgpCopyMemory( modulus, bp, modbytes+2 );
	bp += modbytes+2;
	pgpCopyMemory( exponent, bp, expbytes+2 );
	bp += expbytes+2;

	*bp++ = 0xb4; /* userid */
	*bp++ = strlen( session->hostName );
	pgpCopyMemory( session->hostName, bp, strlen( session->hostName ) );
	bp += strlen( session->hostName );

	PGPImport( session->pgpContext, &kdb,
			   PGPOInputBuffer( session->pgpContext, pgpBuffer, bufLength ),
			   PGPOLastOption( session->pgpContext ) );
	if( !PGPKeyDBRefIsValid( kdb ) )
	{
		(void)pgpSECSHAlert( session,	kPGPsecsh_AL_FatalAlert,
									kPGPsecsh_AT_DecodeError );
		FATALSECSH( kPGPError_SECSHProtocolViolation );
	}

	PGPNewKeyIterFromKeyDB( kdb, &kiter );
	PGPKeyIterNextKeyDBObj( kiter, kPGPKeyDBObjType_Key, &key );
	PGPFreeKeyIter( kiter );

	*outDataUsed = p - inBuffer;
	*outKDB = kdb;
	*outKey = key;

done:
	if( IsntNull( pgpBuffer ) )
	{
		(void)PGPFreeData( pgpBuffer );
	}
	return err;
}

/* Print a bignum to a buffer, return length of string.  If buffer is
 * null just return the length. */
	static PGPInt32
sPrint10(PGPContextRef context, char *outbuf, PGPBigNumRef bn)
{
	PGPBigNumRef pbig, pbig1;
	PGPBigNumRef ten, zero, rem;
	char buf[3000];			/* up to 9000 bits */
	PGPInt32 bufi = sizeof(buf)-1;
	PGPInt32 n;

	buf[bufi] = '\0';
	PGPNewBigNum( context, FALSE, &pbig );
	PGPNewBigNum( context, FALSE, &pbig1 );
	PGPNewBigNum( context, FALSE, &rem );
	
	PGPNewBigNum( context, FALSE, &zero );
	PGPNewBigNum( context, FALSE, &ten );
	PGPBigNumSetQ( ten, 10 );

	PGPAssignBigNum (bn, pbig);
	
	while (PGPBigNumCompare (pbig, zero) != 0) {
		PGPBigNumDivide( pbig, ten, pbig1, rem );
		PGPAssignBigNum( pbig1, pbig );
		n = PGPBigNumGetLSWord (rem);
		buf[--bufi] = n + '0';
	}

	PGPFreeBigNum (zero);
	PGPFreeBigNum (ten);
	PGPFreeBigNum (pbig);
	PGPFreeBigNum (pbig1);
	PGPFreeBigNum (rem);

	if( outbuf != NULL )
		memcpy( outbuf, buf+bufi, sizeof(buf)-bufi );

	return sizeof(buf) - bufi - 1;
}



	PGPError
pgpSECSHClientChooseAlgorithm(
	PGPsecshSessionPriv *	session,
	PGPCipherAlgorithm *	outCipher )
{
	PGPError				err = kPGPError_NoErr;

	if( ! ( session->cipherMask & (1 << kPGPsecsh_CT_IDEA) ) )
	{
		(void)pgpSECSHAlert( session,	kPGPsecsh_AL_FatalAlert,
									kPGPsecsh_AT_InsufficientSecurity );
		FATALSECSH( kPGPError_SECSHNoCommonCipher );
	}

	*outCipher = kPGPCipherAlgorithm_IDEA;

 done:
	return err;
}


	PGPError
pgpSECSHBufferRawData(
	PGPsecshSessionPriv *	session,
	const PGPByte *			rawData,
	PGPSize					rawDataSize )
{
	PGPError				err = kPGPError_NoErr;
	
	err = PGPReallocData( session->memMgr,
							(void **) &session->rcvdRawData,
							session->rawDataSize + rawDataSize, 0 ); CKERR;
	pgpCopyMemory( rawData, session->rcvdRawData + session->rawDataSize,
					rawDataSize );
	session->rawDataSize += rawDataSize;

done:
	return err;
}


	PGPError
pgpSECSHExtractRawData(
	PGPsecshSessionPriv *	session,
	PGPByte *				rawData,
	PGPSize *				rawDataSize )
{
	PGPError				err = kPGPError_NoErr;
	PGPSize					maxSize = *rawDataSize;
	
	*rawDataSize = 0;
	if( ( maxSize > 0 ) && ( session->rawDataSize > 0 ) )
	{
		if( maxSize > session->rawDataSize )
			maxSize = session->rawDataSize;
		pgpCopyMemory( session->rcvdRawData, rawData, maxSize );
		*rawDataSize = maxSize;
		pgpCopyMemory( session->rcvdRawData + maxSize,
						session->rcvdRawData, session->rawDataSize - maxSize );
		session->rawDataSize -= maxSize;
		err = PGPReallocData( session->memMgr,
							(void **) &session->rcvdRawData,
							session->rawDataSize, 0 ); CKERR;
	}
done:
	return err;
}

	PGPError
pgpSECSHBufferSendData(
	PGPsecshSessionPriv *	session,
	const PGPByte *			sendData,
	PGPSize					sendDataSize )
{
	PGPError				err = kPGPError_NoErr;
	
	err = PGPReallocData( session->memMgr,
					(void **) &session->queuedSendData,
					session->queuedSendSize + sendDataSize, 0 ); CKERR;
	pgpCopyMemory( sendData, session->queuedSendData + session->queuedSendSize,
					sendDataSize );
	session->queuedSendSize += sendDataSize;

done:
	return err;
}


	PGPError
pgpSECSHReceivePacket(
	PGPsecshSessionPriv *	session,
	PGPByte *				outType,
	PGPByte **				outBuffer,
	PGPSize *				outLength )
{
	PGPError				err	= kPGPError_NoErr;
    PGPError            	rerr = kPGPError_NoErr;
	PGPByte					header[kPGPsecsh_RecordLengthSize];
	PGPByte *				buffer = NULL;
	PGPSize					rcvd;
	PGPUInt16				length;
	PGPUInt16				bufLength;
	PGPUInt8				padLength;
	PGPInt32				bytesRead;
	PGPByte					crcCheck[kPGPsecsh_CRCSize];

	*outType	= 0;
	*outBuffer	= NULL;
	*outLength	= 0;
	
	rcvd = kPGPsecsh_RecordLengthSize;
	err = pgpSECSHExtractRawData( session, header, &rcvd );	CKERR;
	for(; rcvd < kPGPsecsh_RecordLengthSize; rcvd += bytesRead)
	{
		bytesRead = (session->secshReceiveProc)( session->secshReceiveUserData,
						header + rcvd,
						(PGPInt32)( kPGPsecsh_RecordLengthSize - rcvd ) );
		if( bytesRead < 0 )
		{
			if( bytesRead != kPGPError_SECSHWouldBlock )
			{
				FATALSECSH( kPGPError_SECSHUnexpectedClose );
			}
			else
            {
                rerr = kPGPError_SECSHWouldBlock;
				bytesRead = 0;
            }
		}
		if( bytesRead == 0 )
		{
			if( session->blocking )
			{
				FATALSECSH( kPGPError_SECSHUnexpectedClose );
			}
			else
			{
				if( rcvd )
                {
                    err = pgpSECSHBufferRawData( session, header, rcvd );  CKERR;
                    if(rerr == kPGPError_SECSHWouldBlock)
                    /* check to see if receive call returned a blocking error */
                    {
                        err = kPGPError_SECSHWouldBlock;
                    }
                }
                else if(rerr == kPGPError_SECSHWouldBlock)
                /* check for blocking error */
                {
                    err = kPGPError_SECSHWouldBlock;
                }
				goto done;
			}
		}
	}
	pgpAssert( rcvd == kPGPsecsh_RecordLengthSize );

	length = PGPEndianToUInt32( kPGPBigEndian, &header[0] );
	if( length <= 0 || length > kPGPsecsh_MaximumPacketSize )
	{
		(void)pgpSECSHAlert( session,	kPGPsecsh_AL_FatalAlert,
									kPGPsecsh_AT_DecodeError );
		FATALSECSH( kPGPError_SECSHProtocolViolation );
	}
	padLength = 8 - (length & 7);
	bufLength = length + padLength;
	buffer = (PGPByte *) PGPNewData(session->memMgr, bufLength, 0 );
	CKNULL( buffer );
	rcvd = bufLength;
	err = pgpSECSHExtractRawData( session, buffer, &rcvd );	CKERR;
	for(; rcvd < bufLength; rcvd += bytesRead)
	{
		bytesRead = (session->secshReceiveProc)( session->secshReceiveUserData,
						buffer + rcvd, (PGPInt32)( bufLength - rcvd ) );
		if( bytesRead < 0 )
		{
			if( bytesRead != kPGPError_SECSHWouldBlock )
			{
				(void)PGPFreeData( buffer );
				buffer = NULL;
				FATALSECSH( kPGPError_SECSHUnexpectedClose );
			}
			else
            {
                bytesRead = 0;
                rerr = kPGPError_SECSHWouldBlock;  
            }
		}
		if( bytesRead == 0 )
		{
			if( session->blocking )
			{
				FATALSECSH( kPGPError_SECSHUnexpectedClose );
			}
			else
			{
				if( rcvd )
				{
					err = pgpSECSHBufferRawData( session, header,
												kPGPsecsh_RecordLengthSize );CKERR;
					err = pgpSECSHBufferRawData( session, buffer, rcvd );	CKERR;
				}
                if(rerr == kPGPError_SECSHWouldBlock)
                    err = kPGPError_SECSHWouldBlock;
				(void)PGPFreeData( buffer );
				buffer = NULL;
				goto done;
			}
		}
	}
	pgpAssert( rcvd == bufLength );

	/* Decrypt data if appropriate */
	if( session->encrypting )

⌨️ 快捷键说明

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