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

📄 rtcs.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						 cryptlib RTCS Session Management					*
*						Copyright Peter Gutmann 1999-2003					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "asn1_rw.h"
  #include "asn1s_rw.h"
  #include "session.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../misc/asn1_rw.h"
  #include "../misc/asn1s_rw.h"
  #include "../session/session.h"
#else
  #include "crypt.h"
  #include "misc/asn1_rw.h"
  #include "misc/asn1s_rw.h"
  #include "session/session.h"
#endif /* Compiler-specific includes */

#ifdef USE_RTCS

/* Uncomment the following to read predefined requests/responses from disk
   instead of communicating with the client/server */

/* #define SKIP_IO					/* Don't communicate with server */
#ifdef SKIP_IO
  #define readPkiDatagram( dummy )	CRYPT_OK
  #define writePkiDatagram( dummy )	CRYPT_OK
#endif /* SKIP_IO */

/* The action to take to process an RTCS request/response */

typedef enum {
	ACTION_NONE,				/* No processing */
	ACTION_UNWRAP,				/* Unwrap raw data */
	ACTION_CRYPT,				/* Decrypt data */
	ACTION_SIGN,				/* Sig.check data */
	ACTION_LAST					/* Last valid action type */
	} ACTION_TYPE;

/* RTCS protocol state information.  This is passed around various
   subfunctions that handle individual parts of the protocol */

typedef struct {
	/* State variable information.  The nonce is copied from the request to 
	   the response to prevent replay attacks */
	BYTE nonce[ CRYPT_MAX_HASHSIZE ];
	int nonceSize;
	} RTCS_PROTOCOL_INFO;

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Check for a valid-looking RTCS request/response header */

static const FAR_BSS OID_SELECTION envelopeOIDselection[] = {
	{ OID_CRYPTLIB_RTCSREQ, CRYPT_UNUSED, CRYPT_UNUSED, ACTION_UNWRAP },
	{ OID_CRYPTLIB_RTCSRESP, CRYPT_UNUSED, CRYPT_UNUSED, ACTION_UNWRAP },
	{ OID_CRYPTLIB_RTCSRESP_EXT, CRYPT_UNUSED, CRYPT_UNUSED, ACTION_UNWRAP },
	{ OID_CMS_SIGNEDDATA, 0, 3, ACTION_SIGN },
	{ OID_CMS_ENVELOPEDDATA, 0, 2, ACTION_CRYPT },
	{ NULL, 0, 0, 0 }
	};

static int checkRtcsHeader( const void *rtcsData, const int rtcsDataLength,
							ACTION_TYPE *actionType )
	{
	STREAM stream;
	int status;

	*actionType = ACTION_NONE;

	/* We've got a valid response, check the CMS encapsulation */
	sMemConnect( &stream, rtcsData, rtcsDataLength );
	status = readCMSheader( &stream, envelopeOIDselection, NULL, FALSE );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	*actionType = status;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Client-side Functions							*
*																			*
****************************************************************************/

/* Send a request to an RTCS server */

static int sendClientRequest( SESSION_INFO *sessionInfoPtr )
	{
	RESOURCE_DATA msgData;
	int status;

	/* Get the encoded request data and wrap it up for sending */
	setMessageData( &msgData, sessionInfoPtr->receiveBuffer,
					sessionInfoPtr->receiveBufSize );
	status = krnlSendMessage( sessionInfoPtr->iCertRequest,
							  IMESSAGE_CRT_EXPORT, &msgData, 
							  CRYPT_ICERTFORMAT_DATA );
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, 
				"Couldn't get RTCS request data from RTCS request object" );
	status = envelopeWrap( sessionInfoPtr->receiveBuffer, msgData.length,
						   sessionInfoPtr->receiveBuffer, 
						   &sessionInfoPtr->receiveBufEnd, 
						   sessionInfoPtr->receiveBufSize, 
						   CRYPT_FORMAT_CMS, CRYPT_CONTENT_RTCSREQUEST, 
						   CRYPT_UNUSED );
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, 
				"Couldn't CMS wrap RTCS request data" );
	DEBUG_DUMP( "rtcs_req", sessionInfoPtr->receiveBuffer, 
				sessionInfoPtr->receiveBufEnd );

	/* Send the request to the responder */
	return( writePkiDatagram( sessionInfoPtr ) );
	}

/* Read the response from the RTCS server */

static int readServerResponse( SESSION_INFO *sessionInfoPtr )
	{
	CRYPT_CERTIFICATE iCmsAttributes;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	ACTION_TYPE actionType;
	BYTE nonceBuffer[ CRYPT_MAX_HASHSIZE ];
	int dataLength, sigResult, status;

	/* Read the response from the responder */
	status = readPkiDatagram( sessionInfoPtr );
	if( cryptStatusError( status ) )
		return( status );
	DEBUG_DUMP( "rtcs_resp", sessionInfoPtr->receiveBuffer, 
				sessionInfoPtr->receiveBufEnd );
	status = checkRtcsHeader( sessionInfoPtr->receiveBuffer, 
							  sessionInfoPtr->receiveBufEnd, &actionType );
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, "Invalid RTCS response header" );
	if( actionType != ACTION_SIGN )
		retExt( sessionInfoPtr, status, 
				"Unexpected RTCS encapsulation type %d", actionType );

	/* Sig.check the data using the responder's key */
	status = envelopeSigCheck( sessionInfoPtr->receiveBuffer, 
							   sessionInfoPtr->receiveBufEnd,
							   sessionInfoPtr->receiveBuffer, &dataLength, 
							   sessionInfoPtr->receiveBufSize, 
							   CRYPT_UNUSED, &sigResult, NULL, 
							   &iCmsAttributes );
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, 
				"Invalid RTCS response data (CMS enveloped data)" );

	/* Make sure that the nonce in the response matches the one in the 
	   request */
	setMessageData( &msgData, nonceBuffer, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, CRYPT_CERTINFO_CMS_NONCE );
	krnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA responseMsgData;
		BYTE responseNonceBuffer[ CRYPT_MAX_HASHSIZE ];

		setMessageData( &responseMsgData, responseNonceBuffer,
						CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( sessionInfoPtr->iCertRequest, 
								  IMESSAGE_GETATTRIBUTE_S, &responseMsgData, 
								  CRYPT_CERTINFO_CMS_NONCE );
		if( cryptStatusOK( status ) && \
			( msgData.length < 4 || \
			  msgData.length != responseMsgData.length || \
			  memcmp( msgData.data, responseMsgData.data, msgData.length ) ) )
			status = CRYPT_ERROR_SIGNATURE;
		}
	krnlSendNotifier( sessionInfoPtr->iCertRequest, IMESSAGE_DECREFCOUNT );
	sessionInfoPtr->iCertRequest = CRYPT_ERROR;
	if( cryptStatusError( status ) )
		/* The response doesn't contain a nonce or it doesn't match what
		   we sent, we can't trust it.  The best error that we can return 
		   here is a signature error to indicate that the integrity check
		   failed */
		retExt( sessionInfoPtr, status, 
				( status != CRYPT_ERROR_SIGNATURE ) ? \
				"RTCS response doesn't contain a nonce" : \
				"RTCS response nonce doesn't match the one in the request" );

	/* Everything is OK, import the response */
	setMessageCreateObjectIndirectInfo( &createInfo,
							sessionInfoPtr->receiveBuffer, dataLength,
							CRYPT_CERTTYPE_RTCS_RESPONSE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, "Invalid RTCS response contents" );
	sessionInfoPtr->iCertResponse = createInfo.cryptHandle;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Server-side Functions							*
*																			*
****************************************************************************/

/* Read a request from an RTCS client */

static int readClientRequest( SESSION_INFO *sessionInfoPtr,
							  RTCS_PROTOCOL_INFO *protocolInfo )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	ACTION_TYPE actionType;
	int dataLength, status;

/*-----------------------------------------------------------------------*/
#ifdef SKIP_IO
{
FILE *filePtr = fopen( "/tmp/rtcs_sreq.der", "rb" );
sessionInfoPtr->receiveBufEnd = fread( sessionInfoPtr->receiveBuffer, 1,
									   sessionInfoPtr->receiveBufSize, filePtr );
fclose( filePtr );
status = sessionInfoPtr->receiveBufEnd;
}
#endif /* SKIP_IO */
/*-----------------------------------------------------------------------*/
	/* Read the request data from the client.  We don't write an error
	   response at this initial stage to prevent scanning/DOS attacks 
	   (vir sapit qui pauca loquitur) */
	status = readPkiDatagram( sessionInfoPtr );

⌨️ 快捷键说明

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