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

📄 tsp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
						tspInfo->imprint, tspInfo->imprintSize );
	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 );

#ifdef USE_CMP_TRANSPORT
	/* 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;
		}
#endif /* USE_CMP_TRANSPORT */

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

/* Read the response from the TSP server */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readServerResponse( SESSION_INFO *sessionInfoPtr,
							   TSP_PROTOCOL_INFO *protocolInfo )
	{
	STREAM stream;
#ifdef USE_CMP_TRANSPORT
	const int oldBufSize = sessionInfoPtr->receiveBufSize;
#endif /* USE_CMP_TRANSPORT */
	int status;

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

#ifdef USE_CMP_TRANSPORT
	/* If we're using the socket protocol, read back the header and make
	   sure that 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->errorInfo );
			return( status );
			}
		packetLength = mgetLong( bufPtr );
		if( packetLength < 16 || \
			packetLength > sessionInfoPtr->receiveBufSize || \
			( *bufPtr != TSP_MESSAGE_REQUEST && \
			  *bufPtr != TSP_MESSAGE_RESPONSE ) )
			{
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "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;
		}
#endif /* USE_CMP_TRANSPORT */

	/* Read the response data from the server */
	status = readPkiDatagram( sessionInfoPtr );
#ifdef USE_CMP_TRANSPORT
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		{
		/* Reset the receive buffer size to its true value */
		sessionInfoPtr->receiveBufSize = oldBufSize;
		}
#endif /* USE_CMP_TRANSPORT */
	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( CRYPT_ERROR_INVALID,
				( CRYPT_ERROR_INVALID, SESSION_ERRINFO, 
				  "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->errorInfo );
	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 that we got back a timestamp of the value we sent.  This 
	   check means that 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, 16, 
						 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
		{
		void *msgImprintPtr;

		status = sMemGetDataBlock( &stream, &msgImprintPtr, 
								   protocolInfo->msgImprintSize );
		if( cryptStatusOK( status ) && \
			memcmp( protocolInfo->msgImprint, msgImprintPtr,
					protocolInfo->msgImprintSize ) )
			status = CRYPT_ERROR_INVALID;
		}
	sMemDisconnect( &stream );

	if( cryptStatusError( status ) )
		{
		retExt( status,
				( status, SESSION_ERRINFO, 
				  ( status == CRYPT_ERROR_BADDATA || \
					status == CRYPT_ERROR_UNDERFLOW ) ? \
					"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 */

#ifdef USE_CMP_TRANSPORT

#define respSize( data )	( data[ 3 ] + 4 )

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

#define respSize( data )	( data[ 1 ] + 2 )

static const BYTE FAR_BSS respBadGeneric[] = {
	0x30, 0x05, 
		  0x30, 0x03, 
			    0x02, 0x01, 0x02		/* Rejection, unspecified reason */
	};
static const BYTE FAR_BSS respBadData[] = {
	0x30, 0x09, 
		  0x30, 0x07, 
			    0x02, 0x01, 0x02, 
				0x03, 0x02, 0x05, 0x20	/* Rejection, badDataFormat */
	};
static const BYTE FAR_BSS respBadExtension[] = {
	0x30, 0x0B, 
		  0x30, 0x09, 
				0x02, 0x01, 0x02, 
				0x03, 0x04, 0x07, 0x00, 0x00, 0x80	/* Rejection, unacceptedExtension */
	};
#endif /* USE_CMP_TRANSPORT */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr,
							  const BYTE *errorResponse, const int status )
	{
	/* Since we're already in an error state there's not much that we can do
	   in terms of alerting the user if a further error occurs when writing 
	   the error response, so we ignore any potential write errors that occur
	   at this point */
#ifdef USE_CMP_TRANSPORT
	if( !( sessionInfoPtr->flags & SESSION_ISHTTPTRANSPORT ) )
		{
		memcpy( sessionInfoPtr->receiveBuffer, errorResponse,
				respSize( errorResponse ) );
		sessionInfoPtr->receiveBufEnd = respSize( errorResponse );
		}
	else
#endif /* USE_CMP_TRANSPORT */
		{
		memcpy( sessionInfoPtr->receiveBuffer, errorResponse,
				respSize( errorResponse ) );
		sessionInfoPtr->receiveBufEnd = respSize( errorResponse );
		}
	( void ) writePkiDatagram( sessionInfoPtr, TSP_CONTENT_TYPE_RESP,
							   TSP_CONTENT_TYPE_RESP_LEN );
	return( status );
	}

/* Read a request from a TSP client */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readClientRequest( INOUT SESSION_INFO *sessionInfoPtr,
							  INOUT TSP_PROTOCOL_INFO *protocolInfo )
	{
	STREAM stream;
#ifdef USE_CMP_TRANSPORT
	BYTE *bufPtr = sessionInfoPtr->receiveBuffer;
	const int oldBufSize = sessionInfoPtr->receiveBufSize;
#endif /* USE_CMP_TRANSPORT */
	int status;

#ifdef USE_CMP_TRANSPORT
	/* 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->errorInfo );
			return( status );
			}
		packetLength = mgetLong( bufPtr );
		if( packetLength < 16 || \
			packetLength > sessionInfoPtr->receiveBufSize || \
			( *bufPtr != TSP_MESSAGE_REQUEST && \
			  *bufPtr != TSP_MESSAGE_RESPONSE ) )
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, 
					  "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;
		}
#endif /* USE_CMP_TRANSPORT */

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

⌨️ 快捷键说明

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