📄 rtcs.c
字号:
/****************************************************************************
* *
* cryptlib RTCS Session Management *
* Copyright Peter Gutmann 1999-2003 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "asn1.h"
#include "asn1_ext.h"
#include "session.h"
#else
#include "crypt.h"
#include "misc/asn1.h"
#include "misc/asn1_ext.h"
#include "session/session.h"
#endif /* Compiler-specific includes */
#ifdef USE_RTCS
/* RTCS HTTP content types */
#define RTCS_CONTENT_TYPE_REQ "application/rtcs-request"
#define RTCS_CONTENT_TYPE_REQ_LEN 24
#define RTCS_CONTENT_TYPE_RESP "application/rtcs-response"
#define RTCS_CONTENT_TYPE_RESP_LEN 25
/* 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 + 8 ];
int nonceSize;
} RTCS_PROTOCOL_INFO;
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Check for a valid-looking RTCS request/response header */
static const CMS_CONTENT_INFO FAR_BSS oidInfoSignedData = { 0, 3 };
static const CMS_CONTENT_INFO FAR_BSS oidInfoEnvelopedData = { 0, 3 };
static const OID_INFO FAR_BSS envelopeOIDinfo[] = {
{ OID_CRYPTLIB_RTCSREQ, ACTION_UNWRAP },
{ OID_CRYPTLIB_RTCSRESP, ACTION_UNWRAP },
{ OID_CRYPTLIB_RTCSRESP_EXT, ACTION_UNWRAP },
{ OID_CMS_SIGNEDDATA, ACTION_SIGN, &oidInfoSignedData },
{ OID_CMS_ENVELOPEDDATA, ACTION_CRYPT, &oidInfoEnvelopedData },
{ NULL, 0 }, { NULL, 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, envelopeOIDinfo,
FAILSAFE_ARRAYSIZE( envelopeOIDinfo, OID_INFO ),
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 )
{
MESSAGE_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( status,
( status, SESSION_ERRINFO,
"Couldn't get RTCS request data from RTCS request "
"object" ) );
}
status = envelopeWrap( sessionInfoPtr->receiveBuffer, msgData.length,
sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize,
&sessionInfoPtr->receiveBufEnd,
CRYPT_FORMAT_CMS, CRYPT_CONTENT_RTCSREQUEST,
CRYPT_UNUSED );
if( cryptStatusError( status ) )
{
retExt( status,
( status, SESSION_ERRINFO,
"Couldn't CMS wrap RTCS request data" ) );
}
DEBUG_DUMP( "rtcs_req", sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufEnd );
/* Send the request to the responder */
return( writePkiDatagram( sessionInfoPtr, RTCS_CONTENT_TYPE_REQ,
RTCS_CONTENT_TYPE_REQ_LEN ) );
}
/* Read the response from the RTCS server */
static int readServerResponse( SESSION_INFO *sessionInfoPtr )
{
CRYPT_CERTIFICATE iCmsAttributes;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
ACTION_TYPE actionType;
BYTE nonceBuffer[ CRYPT_MAX_HASHSIZE + 8 ];
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( status,
( status, SESSION_ERRINFO,
"Invalid RTCS response header" ) );
}
if( actionType != ACTION_SIGN )
{
retExt( status,
( status, SESSION_ERRINFO,
"Unexpected RTCS encapsulation type %d", actionType ) );
}
/* Sig.check the data using the responder's key */
status = envelopeSigCheck( sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufEnd,
sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize, &dataLength,
CRYPT_UNUSED, &sigResult, NULL,
&iCmsAttributes );
if( cryptStatusError( status ) )
{
retExt( status,
( status, SESSION_ERRINFO,
"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 ) )
{
MESSAGE_DATA responseMsgData;
BYTE responseNonceBuffer[ CRYPT_MAX_HASHSIZE + 8 ];
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( status,
( status, SESSION_ERRINFO,
( 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( status,
( status, SESSION_ERRINFO,
"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;
MESSAGE_DATA msgData;
ACTION_TYPE actionType;
int dataLength, status;
/* 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 );
if( cryptStatusError( status ) )
return( status );
DEBUG_DUMP( "rtcs_sreq", sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufEnd );
status = checkRtcsHeader( sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufEnd, &actionType );
if( cryptStatusError( status ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -