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

📄 ocsp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						 cryptlib OCSP Session Management					*
*						Copyright Peter Gutmann 1999-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "asn1.h"
  #include "asn1oid.h"
  #include "stream.h"
  #include "session.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../keymgmt/asn1.h"
  #include "../keymgmt/asn1oid.h"
  #include "../keymgmt/stream.h"
  #include "../session/session.h"
#else
  #include "crypt.h"
  #include "keymgmt/asn1.h"
  #include "keymgmt/asn1oid.h"
  #include "keymgmt/stream.h"
  #include "session/session.h"
#endif /* Compiler-specific includes */

/* The following macro can be used to enable dumping of PDUs to disk (as a 
   safeguard, this only works in the Win32 debug version to prevent it from
   being accidentally enabled in any release version) */

#if defined( __WIN32__ ) && !defined( NDEBUG )
  #define DEBUG_DUMP( name, length ) \
	{ \
	FILE *filePtr; \
	char fileName[ 1024 ]; \
	\
	strcpy( fileName, "r:/tmp/" ); \
	strcat( fileName, name ); \
	strcat( fileName, ".der" ); \
	\
	filePtr = fopen( fileName, "wb" ); \
	if( filePtr != NULL ) \
		{ \
		fwrite( sessionInfoPtr->receiveBuffer, 1, length, filePtr ); \
		fclose( filePtr ); \
		} \
	}
#else
  #define DEBUG_DUMP( name, length )
#endif /* Win32 debug */

/* OCSP response status values */

enum { OCSP_RESP_SUCCESSFUL, OCSP_RESP_MALFORMEDREQUEST, 
	   OCSP_RESP_INTERNALERROR, OCSP_RESP_TRYLATER, OCSP_RESP_DUMMY, 
	   OCSP_RESP_SIGREQUIRED, OCSP_RESP_UNAUTHORISED }; 

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

/* Exchange a datagram with an OCSP responder */

static int exchangeClientDatagram( STREAM *stream, void *buffer, 
								   const int bufSize, const int dataOutSize )
	{
	int status;

	/* Send the request to the responder */
	sioctl( stream, STREAM_IOCTL_CONTENTTYPE, "application/ocsp-request", 24 );
	status = swrite( stream, buffer, dataOutSize );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the response from the responder, converting the sread() byte 
	   count into a CRYPT_OK */
	status = sread( stream, buffer, bufSize );
	return( cryptStatusError( status ) ? status : CRYPT_OK );
	}

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

/* Send an error response back to the client.  Since there are only a small
   number of these, we write back a fixed blob rather than encoding each
   one */

#define RESPONSE_SIZE		5

static const BYTE respBadRequest[] = {
	0x30, 0x03, 0x0A, 0x01, 0x01	/* Rejection, malformed request */
	};
static const BYTE respIntError[] = {
	0x30, 0x03, 0x0A, 0x01, 0x02	/* Rejection, internal error */
	};

/* Read a request from an OCSP client */

static int readOcspRequest( SESSION_INFO *sessionInfoPtr )
	{
	CRYPT_CERTIFICATE iOcspRequest;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BYTE *bufPtr = sessionInfoPtr->receiveBuffer;
	int status;

	/* Read the request data from the client */
	status = sread( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer, 
					sessionInfoPtr->receiveBufSize );
	if( cryptStatusError( status ) )
		return( status );
	DEBUG_DUMP( "ocsp_sreq", status );

	/* Import the request as a cryptlib object */
	setMessageCreateObjectIndirectInfo( &createInfo, 
							sessionInfoPtr->receiveBuffer, status );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		{
		swrite( &sessionInfoPtr->stream, respBadRequest, RESPONSE_SIZE );
		return( status );
		}
	iOcspRequest = createInfo.cryptHandle;

	/* Create an OSCP response and add the request information to it */
	setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_OCSP_RESPONSE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( createInfo.cryptHandle, 
						RESOURCE_IMESSAGE_SETATTRIBUTE, &iOcspRequest, 
						CRYPT_IATTRIBUTE_OCSPREQUEST );
		sessionInfoPtr->iCertResponse = createInfo.cryptHandle;
		}
	krnlSendNotifier( iOcspRequest, RESOURCE_IMESSAGE_DECREFCOUNT );
	if( cryptStatusOK( status ) )
		sessionInfoPtr->iCertResponse = createInfo.cryptHandle;
	else
		{
		krnlSendNotifier( createInfo.cryptHandle, 
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
		}
	return( status );
	}

/* Return a response to an OCSP client */

static int sendOcspResponse( SESSION_INFO *sessionInfoPtr )
	{
	RESOURCE_DATA msgData;
	STREAM stream;
	int responseLength, status;

	/* Check the entries from the request against the cert store and sign
	   the resulting status information ("Love, ken") */
	status = krnlSendMessage( sessionInfoPtr->iCertResponse, 
							  RESOURCE_IMESSAGE_CRT_SIGCHECK, NULL,
							  sessionInfoPtr->cryptKeyset );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( sessionInfoPtr->iCertResponse, 
								  RESOURCE_IMESSAGE_CRT_SIGN, NULL,
								  sessionInfoPtr->privateKey );
	if( cryptStatusError( status ) )
		{
		swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
		return( status );
		}

	/* Determine how long the response is and write the wrapper for it */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( sessionInfoPtr->iCertResponse, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
	if( cryptStatusError( status ) )
		{
		swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
		return( status );
		}
	sMemOpen( &stream, sessionInfoPtr->receiveBuffer, 
			  sessionInfoPtr->receiveBufSize );
	responseLength = sizeofOID( OID_OCSP_RESPONSE ) + \
					 sizeofObject( msgData.length );
	writeSequence( &stream, sizeofEnumerated( 0 ) + \
				   sizeofObject( sizeofObject( responseLength ) ) );
	writeEnumerated( &stream, 0, DEFAULT_TAG );		/* respStatus */
	writeConstructed( &stream, sizeofObject( responseLength ), 0 );
	writeSequence( &stream, responseLength );		/* respBytes */
	writeOID( &stream, OID_OCSP_RESPONSE );			/* respType */
	writeTag( &stream, BER_OCTETSTRING );			/* response */
	writeLength( &stream, msgData.length );

	/* Get the encoded response data */
	setResourceData( &msgData, sMemBufPtr( &stream ), 
					 sessionInfoPtr->receiveBufSize - stell( &stream ) );
	status = krnlSendMessage( sessionInfoPtr->iCertResponse, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
	sessionInfoPtr->receiveBufEnd = stell( &stream ) + msgData.length;
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		{
		swrite( &sessionInfoPtr->stream, respIntError, RESPONSE_SIZE );
		return( status );
		}
	DEBUG_DUMP( "ocsp_sresp", sessionInfoPtr->receiveBufEnd );

	/* Send the response to the client */
	sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_CONTENTTYPE, 
			"application/ocsp-response", 25 );
	status = swrite( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer, 
					 sessionInfoPtr->receiveBufEnd );
	if( cryptStatusError( status ) )
		return( status );

	return( status );
	}

/****************************************************************************
*																			*
*								Init/Shutdown Functions						*
*																			*
****************************************************************************/

/* Init/shutdown functions.  Since OCSP is stateless there isn't much to
   do */

static int initFunction( SESSION_INFO *sessionInfoPtr )
	{
	/* Set various OCSP session parameters */
	sessionInfoPtr->requiredAttributeFlags |= \
		SESSION_SERVER_NEEDSPRIVATEKEY | SESSION_SERVER_NEEDSPRIVKEYCERT | \
		SESSION_SERVER_NEEDSCERTSTORE;
	sessionInfoPtr->sendBufSize = CRYPT_UNUSED;
	sessionInfoPtr->receiveBufSize = MIN_BUFFER_SIZE;
	sessionInfoPtr->serverPort = 80;
	sessionInfoPtr->version = 1;

	return( CRYPT_OK );
	}

/* Exchange data with an OCSP server */

static int clientStartup( SESSION_INFO *sessionInfoPtr )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE nonceBuffer[ CRYPT_MAX_HASHSIZE ];
	int timeout, value, length, dataStartPos, status;

	krnlSendMessage( sessionInfoPtr->ownerHandle, 
					 RESOURCE_IMESSAGE_GETATTRIBUTE, &timeout, 
					 CRYPT_OPTION_NET_CONNECTTIMEOUT );

	/* Make sure we have all the needed information */
	if( sessionInfoPtr->iCertRequest == CRYPT_ERROR )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST, 
					  CRYPT_ERRTYPE_ATTR_ABSENT );
		return( CRYPT_ERROR_NOTINITED );
		}

	/* Get the encoded request data.  We read this into the send buffer which
	   at its minimum size is roughly two orders of magnitude larger than the 
	   request */
	setResourceData( &msgData, sessionInfoPtr->receiveBuffer, 
					 sessionInfoPtr->receiveBufSize );

⌨️ 快捷键说明

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