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

📄 tsp.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 3 页
字号:
						sessionInfoPtr->tspImprintSize );
	memcpy( protocolInfo->msgImprint, msgImprintPtr, 
			protocolInfo->msgImprintSize );
	if( protocolInfo->includeSigCerts )
		writeBoolean( &stream, TRUE, DEFAULT_TAG );
	sessionInfoPtr->receiveBufEnd = stell( &stream );
	sMemDisconnect( &stream );
	DEBUG_DUMP( "tsa_req", sessionInfoPtr->receiveBuffer, 
				sessionInfoPtr->receiveBufEnd );

	/* If we're using the socket protocol, add the TSP header:
		uint32		length of type + data
		byte		type
		byte[]		data */
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		{
		memmove( bufPtr + TSP_HEADER_SIZE, bufPtr, 
				 sessionInfoPtr->receiveBufEnd );
		mputLong( bufPtr, sessionInfoPtr->receiveBufEnd + 1 );
		*bufPtr = TSP_MESSAGE_REQUEST;
		sessionInfoPtr->receiveBufEnd += TSP_HEADER_SIZE;
		}

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

/* Read the response from the TSP server */

static int readServerResponse( SESSION_INFO *sessionInfoPtr,
							   TSP_PROTOCOL_INFO *protocolInfo )
	{
	STREAM stream;
	const int oldBufSize = sessionInfoPtr->receiveBufSize;
	int status;

	/* Reset the buffer position indicators to clear any old data in the
	   buffer from previous transactions */
	sessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos = 0;

	/* If we're using the socket protocol, read back the header and make 
	   sure it's in order.  The check for a response labelled as a request 
	   is necessary because some buggy implementations use the request 
	   message type for any normal communication (in fact since the socket
	   protocol arose from a botched cut&paste of the equivalent CMP 
	   protocol it serves no actual purpose and so some implementations just 
	   memcpy() in a fixed header) */
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		{
		BYTE buffer[ TSP_HEADER_SIZE + 8 ], *bufPtr = buffer;
		long packetLength;

		status = sread( &sessionInfoPtr->stream, buffer, TSP_HEADER_SIZE );
		if( cryptStatusError( status ) )
			{
			sNetGetErrorInfo( &sessionInfoPtr->stream,
							  sessionInfoPtr->errorMessage,
							  &sessionInfoPtr->errorCode );
			return( status );
			}
		packetLength = mgetLong( bufPtr );
		if( packetLength < 16 || \
			packetLength > sessionInfoPtr->receiveBufSize || \
			( *bufPtr != TSP_MESSAGE_REQUEST && \
			  *bufPtr != TSP_MESSAGE_RESPONSE ) )
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Invalid TSP socket protocol data" );

		/* Fiddle the read buffer size to make sure we only try and read as
		   much as the wrapper protocol has told us is present.  This kludge 
		   is necessary because the wrapper protocol isn't any normal 
		   transport mechanism like HTTP but a botched cut&paste from CMP 
		   that can't easily be accommodated by the network-layer code */
		sessionInfoPtr->receiveBufSize = ( int ) packetLength - 1;
		}

	/* Read the response data from the server */
	status = readPkiDatagram( sessionInfoPtr );
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		/* Reset the receive buffer size to its true value */
		sessionInfoPtr->receiveBufSize = oldBufSize;
	if( cryptStatusError( status ) )
		return( status );
	if( sessionInfoPtr->receiveBufEnd < 16 )
		/* If the length is tiny, it's an error response.  We don't even
		   bother trying to feed it to the cert handling code, in theory to
		   save a few cycles but mostly to avoid triggering sanity checks
		   within the code for too-short objects */
		retExt( sessionInfoPtr, CRYPT_ERROR_INVALID,
				"TSA returned error response" );

	/* Strip off the header and check the PKIStatus wrapper to make sure 
	   everything is OK */
	sMemConnect( &stream, sessionInfoPtr->receiveBuffer, 
				 sessionInfoPtr->receiveBufEnd );
	readSequence( &stream, NULL );
	status = readPkiStatusInfo( &stream, &sessionInfoPtr->errorCode,
								sessionInfoPtr->errorMessage );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}

	/* Remember where the encoded timestamp payload starts in the buffer so 
	   that we can return it to the caller */
	sessionInfoPtr->receiveBufPos = stell( &stream );

	/* Make sure we got back a timestamp of the value we sent.  This check
	   means it works with and without nonces (in theory someone could
	   repeatedly contersign the same signature rather than countersigning
	   the last timestamp as they're supposed to, but (a) that's rather
	   unlikely and (b) cryptlib doesn't support it so they'd have to make
	   some rather serious changes to the code to do it) */
	readSequence( &stream, NULL );		/* contentInfo */
	readUniversal( &stream );			/* contentType */
	readConstructed( &stream, NULL, 0 );/* content */
	readSequence( &stream, NULL );			/* signedData */
	readShortInteger( &stream, NULL );		/* version */
	readUniversal( &stream );				/* digestAlgos */
	readSequence( &stream, NULL );			/* encapContent */
	readUniversal( &stream );					/* contentType */
	readConstructed( &stream, NULL, 0 );		/* content */
	readOctetStringHole( &stream, NULL, DEFAULT_TAG );/* OCTET STRING hole */
	readSequence( &stream, NULL );					/* tstInfo */
	readShortInteger( &stream, NULL );				/* version */
	status = readUniversal( &stream );				/* policy */
	if( cryptStatusError( status ) )
		status = CRYPT_ERROR_BADDATA;
	else
		if( protocolInfo->msgImprintSize > sMemDataLeft( &stream ) || \
			memcmp( protocolInfo->msgImprint, sMemBufPtr( &stream ), 
					protocolInfo->msgImprintSize ) )
			status = CRYPT_ERROR_INVALID;
	sMemDisconnect( &stream );

	if( cryptStatusError( status ) )
		retExt( sessionInfoPtr, status, 
				( status == CRYPT_ERROR_BADDATA ) ? \
					"Invalid timestamp data" : \
					"Timestamp message imprint doesn't match message "
					"imprint" );
	return( 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 respSize( data )	( data[ 3 ] + 4 )

static const FAR_BSS BYTE respBadGeneric[] = {
	0x00, 0x00, 0x00, 0x08,			/* Length */
	0x05,							/* Type */
	0x30, 0x05, 0x30, 0x03, 0x02, 0x01, 0x02
	};								/* Rejection, unspecified reason */
static const FAR_BSS BYTE respBadData[] = {
	0x00, 0x00, 0x00, 0x0C,			/* Length */
	0x05,							/* Type */
	0x30, 0x09, 0x30, 0x07, 0x02, 0x01, 0x02, 0x03,
	0x02, 0x05, 0x20				/* Rejection, badDataFormat */
	};
static const FAR_BSS BYTE respBadPolicy[] = {
	0x00, 0x00, 0x00, 0x0D,			/* Length */
	0x05,							/* Type */
	0x30, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x02, 0x03,
	0x03, 0x00, 0x00, 0x01			/* Rejection, unacceptedPolicy */
	};
static const FAR_BSS BYTE respBadExtension[] = {
	0x00, 0x00, 0x00, 0x0E,			/* Length */
	0x05,							/* Type */
	0x30, 0x0B, 0x30, 0x09, 0x02, 0x01, 0x02, 0x03,
	0x04, 0x07, 0x00, 0x00, 0x80	/* Rejection, unacceptedExtension */
	};

static int sendErrorResponse( SESSION_INFO *sessionInfoPtr,
							  const BYTE *errorResponse, const int status )
	{
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		{
		memcpy( sessionInfoPtr->receiveBuffer, errorResponse,
				respSize( errorResponse ) );
		sessionInfoPtr->receiveBufEnd = respSize( errorResponse );
		}
	else
		{
		memcpy( sessionInfoPtr->receiveBuffer, 
				errorResponse + TSP_HEADER_SIZE,
				respSize( errorResponse ) - TSP_HEADER_SIZE );
		sessionInfoPtr->receiveBufEnd = \
							respSize( errorResponse ) - TSP_HEADER_SIZE;
		}
	writePkiDatagram( sessionInfoPtr );
	return( status );
	}

/* Read a request from a TSP client */

static int readClientRequest( SESSION_INFO *sessionInfoPtr,
							  TSP_PROTOCOL_INFO *protocolInfo )
	{
	STREAM stream;
	BYTE *bufPtr = sessionInfoPtr->receiveBuffer;
	const int oldBufSize = sessionInfoPtr->receiveBufSize;
	int status;

	/* If we're using the socket protocol, read the request header and make 
	   sure it's in order.  We don't write an error response at this initial 
	   stage to prevent scanning/DOS attacks (vir sapit qui pauca 
	   loquitur) */
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		{
		long packetLength;

		status = sread( &sessionInfoPtr->stream, bufPtr, TSP_HEADER_SIZE );
		if( cryptStatusError( status ) )
			{
			sNetGetErrorInfo( &sessionInfoPtr->stream,
							  sessionInfoPtr->errorMessage,
							  &sessionInfoPtr->errorCode );
			return( status );
			}
		packetLength = mgetLong( bufPtr );
		if( packetLength < 16 || \
			packetLength > sessionInfoPtr->receiveBufSize || \
			( *bufPtr != TSP_MESSAGE_REQUEST && \
			  *bufPtr != TSP_MESSAGE_RESPONSE ) )
			retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
					"Invalid TSP socket protocol data" );

		/* Fiddle the read buffer size to make sure we only try and read as
		   much as the wrapper protocol has told us is present.  This kludge 
		   is necessary because the wrapper protocol isn't any normal 
		   transport mechanism like HTTP but a botched cut&paste from CMP 
		   that can't easily be accommodated by the network-layer code */
		sessionInfoPtr->receiveBufSize = ( int ) packetLength - 1;
		}

	/* Read the request data from the client */
	status = readPkiDatagram( sessionInfoPtr );
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		/* Reset the receive buffer size to its true value */
		sessionInfoPtr->receiveBufSize = oldBufSize;
	if( cryptStatusError( status ) )
		return( sendErrorResponse( sessionInfoPtr, respBadGeneric, status ) );
	sMemConnect( &stream, sessionInfoPtr->receiveBuffer, 
				 sessionInfoPtr->receiveBufEnd );
	status = readTSPRequest( &stream, protocolInfo, sessionInfoPtr );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( sendErrorResponse( sessionInfoPtr, \
					( status == CRYPT_ERROR_BADDATA || \
					  status == CRYPT_ERROR_UNDERFLOW ) ? respBadData : \
					( status == CRYPT_ERROR_INVALID ) ? respBadExtension : \
					respBadGeneric, status ) );
	return( CRYPT_OK );
	}

/* Send the response to the TSP client */

static int sendServerResponse( SESSION_INFO *sessionInfoPtr,
							   TSP_PROTOCOL_INFO *protocolInfo )
	{
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE serialNo[ 16 ];
	BYTE *bufPtr = sessionInfoPtr->receiveBuffer;
	const time_t currentTime = getReliableTime( sessionInfoPtr->privateKey );
	const int headerOfs = ( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) ? \
						  0 : TSP_HEADER_SIZE;
	int length, responseLength, status;

	/* If the time is screwed up we can't provide a signed indication of the 
	   time.  The error information is somewhat misleading, but there's not
	   much else we can provide at this point */
	if( currentTime < MIN_TIME_VALUE )
		{
		setErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_VALIDFROM,
					  CRYPT_ERRTYPE_ATTR_VALUE );

⌨️ 快捷键说明

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