📄 tsp.c
字号:
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 + -