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

📄 cryptses.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
							  STREAM_PROTOCOL_HTTP_TRANSACTION,
							  &connectInfo, sessionInfoPtr->errorMessage, 
							  &sessionInfoPtr->errorCode );
	else
		{
		if( sessionInfoPtr->flags & SESSION_USEALTTRANSPORT )
			{
			const ALTPROTOCOL_INFO *altProtocolInfoPtr = \
									protocolInfoPtr->altProtocolInfo;

			/* If we're using the HTTP port for a session-specific protocol, 
			   change it to the default port for the session-specific 
			   protocol instead */
			if( connectInfo.port == 80 )
				connectInfo.port = altProtocolInfoPtr->port;
			status = sNetConnect( &sessionInfoPtr->stream, 
								  altProtocolInfoPtr->type, 
								  &connectInfo, sessionInfoPtr->errorMessage, 
								  &sessionInfoPtr->errorCode );
			}
		else
			status = sNetConnect( &sessionInfoPtr->stream,
								  STREAM_PROTOCOL_TCPIP, 
								  &connectInfo, sessionInfoPtr->errorMessage, 
								  &sessionInfoPtr->errorCode );
		}
	if( cryptStatusError( status ) )
		return( status );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_HANDSHAKETIMEOUT, NULL, 0 );
	if( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT )
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_CONTENTTYPE, 
				( void * ) protocolInfoPtr->clientContentType, 
				strlen( protocolInfoPtr->clientContentType ) );

	return( CRYPT_OK );
	}

static int defaultServerStartupFunction( SESSION_INFO *sessionInfoPtr )
	{
	const PROTOCOL_INFO *protocolInfoPtr = sessionInfoPtr->protocolInfo;
	NET_CONNECT_INFO connectInfo;
	int status;

	/* Wait for a client connection */
	initSessionNetConnectInfo( sessionInfoPtr, &connectInfo );
	if( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT )
		status = sNetListen( &sessionInfoPtr->stream,
							 STREAM_PROTOCOL_HTTP_TRANSACTION, 
							 &connectInfo, sessionInfoPtr->errorMessage, 
							 &sessionInfoPtr->errorCode );
	else
		{
		if( sessionInfoPtr->flags & SESSION_USEALTTRANSPORT )
			{
			const ALTPROTOCOL_INFO *altProtocolInfoPtr = \
									protocolInfoPtr->altProtocolInfo;

			/* If we're using the HTTP port for a session-specific protocol, 
			   change it to the default port for the session-specific 
			   protocol instead */
			if( connectInfo.port == 80 )
				connectInfo.port = altProtocolInfoPtr->port;
			status = sNetListen( &sessionInfoPtr->stream, 
								 altProtocolInfoPtr->type, 
								 &connectInfo, sessionInfoPtr->errorMessage, 
								 &sessionInfoPtr->errorCode );
			}
		else
			status = sNetListen( &sessionInfoPtr->stream,
								 STREAM_PROTOCOL_TCPIP, 
								 &connectInfo, sessionInfoPtr->errorMessage, 
								 &sessionInfoPtr->errorCode );
		}
	if( cryptStatusError( status ) )
		return( status );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_HANDSHAKETIMEOUT, NULL, 0 );
	if( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT )
		sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_CONTENTTYPE,
				( void * ) protocolInfoPtr->serverContentType, 
				strlen( protocolInfoPtr->serverContentType ) );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_GETCLIENTNAME,
			sessionInfoPtr->clientName, 0 );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_GETCLIENTPORT,
			&sessionInfoPtr->clientPort, 0 );

	return( CRYPT_OK );
	}

static void defaultShutdownFunction( SESSION_INFO *sessionInfoPtr )
	{
	sNetDisconnect( &sessionInfoPtr->stream );
	}

/* Default get-attribute function used when no session-specific ones is
   provided */

static int defaultGetAttributeFunction( SESSION_INFO *sessionInfoPtr,
										void *data, 
										const CRYPT_ATTRIBUTE_TYPE type )
	{
	CRYPT_CERTIFICATE *responsePtr = ( CRYPT_CERTIFICATE * ) data;

	assert( type == CRYPT_SESSINFO_RESPONSE );

	/* If we didn't get a response there's nothing to return */
	if( sessionInfoPtr->iCertResponse == CRYPT_ERROR )
		return( CRYPT_ERROR_NOTFOUND );

	/* Return the info to the caller */
	krnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_INCREFCOUNT );
	*responsePtr = sessionInfoPtr->iCertResponse;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Secure Session Data Handling Functions				*
*																			*
****************************************************************************/

/* Common code to read and write data over the secure connection.  This
   is called by the protocol-specific handlers, which supply three functions:

	readHeaderFunction()	- Reads the header for a packet and sets up
							  length information.
	processBodyFunction()	- Processes the body of a packet.
	writeDataFunction()		- Wraps and sends a packet.

   The read data code uses a helper function tryRead() that either reads
   everything which is available or to the end of the current packet.  In 
   other words it's an atomic, all-or-nothing function that can be used by 
   higher-level code to handle network-level packetisation.  Buffer 
   management is handled as follows: The bPos index always points to the end 
   of the decoded data (i.e. data that can be used by the user), if there's 
   no partial packet present this index is the same as bEnd:

	----+------------------------
	////|
	----+------------------------
		^
		|
	bEnd/bPos

   If there's a partial packet present, pendingPacketRemaining contains the
   number of bytes required to complete the packet and bEnd points to the 
   end of the received data, and is advanced as more data is read:

							<----> pPR
	----+-------------------+----+----
	////|///////////////////|....|
	----+-------------------+----+----
		^					^
		|					|
	  bPos				  bEnd

   Once the complete packet is read (pPR reaches 0), it's decrypted, and 
   bPos and bEnd are adjusted to point to the end of the new data:

	----+------------------------+----
	////|////////////////////////|
	----+------------------------+----
								 ^
								 |
							 bEnd/bPos

   The handling of any header data present at the start of the packet 
   depends on the packet format, if the header is independent of the 
   encrypted data it's handled entirely by readHeaderFunction() and there's 
   no need to provide special-case handling.  If the header is part of the 
   encrypted data, decryption is a two-stage operation in which 
   readHeaderFunction() decrypts just enough of the packet to extract and
   process the header (depositing any leftover non-header data at the start
   of the buffer), and processBodyFunction() processes the rest of the data.
   
   Errors in the readHeaderFunction() are fatal if they come from the session
   protocol level (e.g. a MAC failure or bad packet) and nonfatal if they 
   come from the network layer below the session (the stream-level code has 
   its own handling of fatal vs. nonfatal errors, so we don't try and get
   down to that level).

   Errors in the processBodyFunction() and writeDataFunction() are always
   fatal.  In theory we could try to recover, however the functions update 
   assorted crypto state such as packet sequence numbers and IVs that would
   be tricky to roll back, and in practice recoverable errors are likely to 
   be extremely rare (at best perhaps a CRYPT_ERROR_TIMEOUT for a context
   tied to a device, however even this won't occur since the conventional
   encryption and MAC contexts are all internal native contexts), so there's
   little point in trying to make the functions recoverable */

static int tryRead( SESSION_INFO *sessionInfoPtr, READSTATE_INFO *readInfo )
	{
	int bytesLeft, status;

	/* Clear return value */
	*readInfo = READINFO_NONE;

	/* If there's no pending packet information present, try and read it.  
	   This can return one of four classes of values:

		1. An error code.
		2. Zero, to indicate that nothing was read.
		3. OK_SPECIAL and read info READINFO_NOOP to indicate that header 
		   data but no payload data was read.
		4. A byte count and read info READINFO_HEADERPAYLOAD to indicate 
		   that some payload data was read as part of the header */
	if( sessionInfoPtr->pendingPacketLength <= 0 )
		{
		status = sessionInfoPtr->readHeaderFunction( sessionInfoPtr, readInfo );
		if( status <= 0 && status != OK_SPECIAL )
			return( status );
		assert( ( status == OK_SPECIAL && *readInfo == READINFO_NOOP ) || \
				( status > 0 && *readInfo == READINFO_HEADERPAYLOAD ) );
		if( *readInfo == READINFO_HEADERPAYLOAD )
			{
			/* Some protocols treat the header information for a secured
			   data packet as part of the data, so when we read the header we
			   can get part of the payload included in the read.  When the 
			   protocol-specific header read code obtained some payload data
			   alongside the header, it returns READINFO_HEADERPAYLOAD to
			   indicate that the packet info needs to be adjusted for the 
			   packet header data that was just read */
			sessionInfoPtr->receiveBufEnd += status;
			sessionInfoPtr->pendingPacketPartialLength = status;
			sessionInfoPtr->pendingPacketRemaining -= status;
			}
		}
	bytesLeft = sessionInfoPtr->receiveBufSize - sessionInfoPtr->receiveBufEnd;

	assert( sessionInfoPtr->partialHeaderLength == 0 );
	assert( sessionInfoPtr->receiveBufEnd <= sessionInfoPtr->receiveBufSize );
	assert( sessionInfoPtr->receiveBufPos <= sessionInfoPtr->receiveBufEnd );

	/* Sanity-check the read state */
	if( sessionInfoPtr->pendingPacketLength < 0 || \
		sessionInfoPtr->pendingPacketRemaining < 0 || \
		sessionInfoPtr->pendingPacketPartialLength < 0 )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_BADDATA );
		}

	/* If there's not enough room in the receive buffer to read at least 1K
	   of packet data, don't try anything until the user has emptied more
	   data from the buffer */
	if( bytesLeft < min( sessionInfoPtr->pendingPacketRemaining, 1024 ) )
		return( 0 );

	/* Try and read more of the packet */
	status = sread( &sessionInfoPtr->stream,
					sessionInfoPtr->receiveBuffer + sessionInfoPtr->receiveBufEnd,
					min( sessionInfoPtr->pendingPacketRemaining, bytesLeft ) );
	if( cryptStatusError( status ) )
		{
		sNetGetErrorInfo( &sessionInfoPtr->stream,
						  sessionInfoPtr->errorMessage,
						  &sessionInfoPtr->errorCode );
		return( status );
		}
	if( status == 0 )
		/* Nothing read, try again later */
		return( 0 );
	sessionInfoPtr->receiveBufEnd += status;
	sessionInfoPtr->pendingPacketRemaining -= status;
	if( sessionInfoPtr->pendingPacketRemaining > 0 )
		{
		/* We got some but not all of the data, try again later */
		*readInfo = READINFO_PARTIAL;
		return( OK_SPECIAL );
		}
	assert( sessionInfoPtr->pendingPacketRemaining == 0 );

	/* We've got a complete packet in the buffer, process it */
	return( sessionInfoPtr->processBodyFunction( sessionInfoPtr, readInfo ) );
	}

/* Get data from the remote system */

static int getData( SESSION_INFO *sessionInfoPtr, void *data,
					const int length )
	{
	BYTE *dataPtr = data;
	int bytesCopied = 0, savedTimeout, status;

	/* If there's an error pending (which will always be fatal, see the 
	   comment after the tryRead() call below), set the current error state 
	   to the pending state and return */
	if( cryptStatusError( sessionInfoPtr->pendingErrorState ) )
		{
		assert( sessionInfoPtr->receiveBufPos == 0 );

		status = sessionInfoPtr->readErrorState = \
						sessionInfoPtr->pendingErrorState;
		sessionInfoPtr->pendingErrorState = CRYPT_OK; 
		return( status );
		}

	/* Update the stream timeout to the current user-selected timeout in case
	   the user has changed the timeout setting */
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_TIMEOUT, &savedTimeout, 0 );
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_TIMEOUT, NULL, 
			sessionInfoPtr->timeout );

	while( bytesCopied < length )
		{
		const int bytesToCopy = min( length - bytesCopied, \
									 sessionInfoPtr->receiveBufPos );
		READSTATE_INFO readInfo = READINFO_NONE;
		int remainder;

		assert( bytesToCopy >= 0 );

		/* Sanity-check the read state */
		if( sessionInfoPtr->receiveBufPos < 0 || \
			sessionInfoPtr->receiveBufPos > sessionInfoPtr->receiveBufEnd || \
			sessionInfoPtr->receiveBufEnd < 0 || \
			sessionInfoPtr->receiveBufEnd > sessionInfoPtr->receiveBufSize )
			{
			assert( NOTREACHED );
			return( CRYPT_ERROR_BADDATA );
			}

		/* Copy as much data as we can across and move any remaining data down
		   to the start of the receive buffer */
		if( bytesToCopy > 0 )
			{
			memcpy( dataPtr, sessionInfoPtr->receiveBuffer, bytesToCopy );
			remainder = sessionInfoPtr->receiveBufEnd - bytesToCopy;
			assert( remainder >= 0 );
			if( remainder > 0 )
				memmove( sessionInfoPtr->receiveBuffer,
						 sessionInfoPtr->receiveBuffer + bytesToCopy, remainder );
			sessionInfoPtr->receiveBufPos -= bytesToCopy;
			sessionInfoPtr->receiveBufEnd = remainder;
			assert( sessionInfoPtr->receiveBufPos >= 0 );

			/* Adjust the byte count info and, if we've satisfied the request,
			   exit */
			bytesCopied += bytesToCopy;
			dataPtr += bytesToCopy;
			if( bytesCopied >= length )
				break;
			}
		assert( sessionInfoPtr->receiveBufPos == 0 );

		/* Try and read a complete packet.  This can return one of four classes 
		   of values:

			1. An error code.
			2. Zero to indicate that nothing was read.
			3a.OK_SPECIAL and read info READINFO_PARTIAL to indicate that a 
			   partial packet (not enough to process) was read.
			3b.OK_SPECIAL and read info READINFO_NOOP to indicate that a 

⌨️ 快捷键说明

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