📄 cmp.c
字号:
/****************************************************************************
* *
* Control Information Management Functions *
* *
****************************************************************************/
static int getAttributeFunction( SESSION_INFO *sessionInfoPtr,
void *data, const CRYPT_ATTRIBUTE_TYPE type )
{
CRYPT_CERTIFICATE *cmpResponsePtr = ( CRYPT_CERTIFICATE * ) data;
CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( type == CRYPT_SESSINFO_CMP_REQUESTTYPE || \
type == CRYPT_SESSINFO_RESPONSE );
/* If it's a general protocol-specific attribute read, return the
information and exit */
if( type == CRYPT_SESSINFO_CMP_REQUESTTYPE )
{
if( cmpInfo->requestType == CRYPT_REQUESTTYPE_NONE )
{
setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTFOUND );
}
*( ( int * ) data ) = cmpInfo->requestType;
return( CRYPT_OK );
}
/* If we didn't get a response there's nothing to return */
if( sessionInfoPtr->iCertResponse == CRYPT_ERROR )
return( CRYPT_ERROR_NOTFOUND );
/* Return the information to the caller */
krnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_INCREFCOUNT );
*cmpResponsePtr = sessionInfoPtr->iCertResponse;
return( CRYPT_OK );
}
static int setAttributeFunction( SESSION_INFO *sessionInfoPtr,
const void *data,
const CRYPT_ATTRIBUTE_TYPE type )
{
CRYPT_CERTIFICATE cryptCert = *( ( CRYPT_CERTIFICATE * ) data );
CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
int value, status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( type == CRYPT_SESSINFO_CMP_REQUESTTYPE || \
type == CRYPT_SESSINFO_CMP_PRIVKEYSET || \
type == CRYPT_SESSINFO_REQUEST || \
type == CRYPT_SESSINFO_CACERTIFICATE );
/* Standard CMP (with user-supplied request info) can't be combined with
plug-and-play CMP (with automatically-generated request info) */
if( ( type == CRYPT_SESSINFO_CMP_REQUESTTYPE || \
type == CRYPT_SESSINFO_REQUEST ) && \
sessionInfoPtr->privKeyset != CRYPT_ERROR )
{
setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_PRIVKEYSET,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
if( type == CRYPT_SESSINFO_CMP_PRIVKEYSET && \
( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE || \
sessionInfoPtr->iCertRequest != CRYPT_ERROR ) )
{
setErrorInfo( sessionInfoPtr,
( sessionInfoPtr->iCertRequest != CRYPT_ERROR ) ? \
CRYPT_SESSINFO_REQUEST : \
CRYPT_SESSINFO_CMP_REQUESTTYPE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* If it's general protocol-specific information other than a request or
cert, set it */
if( type == CRYPT_SESSINFO_CMP_REQUESTTYPE )
{
/* Make sure that the value hasn't been set yet */
value = *( ( int * ) data );
if( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE )
{
setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* If the request object is already present, make sure that it
matches the request type. We can't do this check unconditionally
because the request type may be set before the request object is
set */
if( sessionInfoPtr->iCertRequest != CRYPT_ERROR )
{
int requestType;
status = krnlSendMessage( sessionInfoPtr->iCertRequest,
IMESSAGE_GETATTRIBUTE, &requestType,
CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) )
return( status );
if( requestType == CRYPT_CERTTYPE_REQUEST_CERT )
{
if( value != CRYPT_REQUESTTYPE_INITIALISATION && \
value != CRYPT_REQUESTTYPE_CERTIFICATE && \
value != CRYPT_REQUESTTYPE_KEYUPDATE )
status = CRYPT_ERROR_INVALID;
}
else
if( value != CRYPT_REQUESTTYPE_REVOCATION )
status = CRYPT_ERROR_INVALID;
if( cryptStatusError( status ) )
{
setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,
CRYPT_ERRTYPE_CONSTRAINT );
return( status );
}
}
/* Set the request type and tell the higher-level code that further
information needs to be provided before we can activate the
session */
cmpInfo->requestType = value;
if( value == CRYPT_REQUESTTYPE_INITIALISATION || \
value == CRYPT_REQUESTTYPE_PKIBOOT )
sessionInfoPtr->clientReqAttrFlags = \
SESSION_NEEDS_USERID | \
SESSION_NEEDS_PASSWORD;
else
if( value == CRYPT_REQUESTTYPE_REVOCATION )
sessionInfoPtr->clientReqAttrFlags = \
SESSION_NEEDS_PRIVATEKEY | \
SESSION_NEEDS_PRIVKEYSIGN | \
SESSION_NEEDS_PRIVKEYCERT | \
SESSION_NEEDS_KEYORPASSWORD;
else
sessionInfoPtr->clientReqAttrFlags = \
SESSION_NEEDS_PRIVATEKEY | \
SESSION_NEEDS_PRIVKEYSIGN | \
SESSION_NEEDS_PRIVKEYCERT;
return( CRYPT_OK );
}
if( type == CRYPT_SESSINFO_CMP_PRIVKEYSET )
{
CRYPT_CERTIFICATE privKeyset = *( ( CRYPT_CERTIFICATE * ) data );
/* Make sure that the value hasn't been set yet */
if( sessionInfoPtr->privKeyset != CRYPT_ERROR )
{
setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_PRIVKEYSET,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Remember that we're using plug-and-play PKI functionality */
sessionInfoPtr->sessionCMP->flags |= CMP_PFLAG_PNPPKI;
krnlSendNotifier( privKeyset, IMESSAGE_INCREFCOUNT );
sessionInfoPtr->privKeyset = privKeyset;
return( CRYPT_OK );
}
/* Make sure that the request/cert type is consistent with the operation
being performed. The requirements for this are somewhat more complex
than the basic ACL-based check can manage, so we handle it here with
custom code */
status = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
switch( type )
{
case CRYPT_SESSINFO_REQUEST:
if( value != CRYPT_CERTTYPE_REQUEST_CERT && \
value != CRYPT_CERTTYPE_REQUEST_REVOCATION )
return( CRYPT_ARGERROR_NUM1 );
/* If the request type is already present, make sure that it
matches the request object. We can't do this check
unconditionally because the request object may be set before
the request type is set */
if( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE )
{
const CRYPT_REQUESTTYPE_TYPE requestType = \
cmpInfo->requestType;
if( value == CRYPT_CERTTYPE_REQUEST_CERT )
{
if( requestType != CRYPT_REQUESTTYPE_INITIALISATION && \
requestType != CRYPT_REQUESTTYPE_CERTIFICATE && \
requestType != CRYPT_REQUESTTYPE_KEYUPDATE )
status = CRYPT_ERROR_INVALID;
}
else
if( requestType != CRYPT_REQUESTTYPE_REVOCATION )
status = CRYPT_ERROR_INVALID;
if( cryptStatusError( status ) )
{
setErrorInfo( sessionInfoPtr,
CRYPT_SESSINFO_CMP_REQUESTTYPE,
CRYPT_ERRTYPE_CONSTRAINT );
return( status );
}
}
/* If it's a non-ir cert request, make sure that there's a
subject DN present. We perform this check because subject
DNs are optional for irs but not for any other request types
and we want to catch this before we get into the CMP exchange
itself */
if( cmpInfo->requestType == CRYPT_REQUESTTYPE_CERTIFICATE || \
cmpInfo->requestType == CRYPT_REQUESTTYPE_KEYUPDATE )
{
MESSAGE_DATA msgData = { NULL, 0 };
status = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
{
setErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ARGERROR_NUM1 );
}
}
break;
case CRYPT_SESSINFO_CACERTIFICATE:
if( value != CRYPT_CERTTYPE_CERTIFICATE )
return( CRYPT_ARGERROR_NUM1 );
break;
default:
retIntError();
}
if( value == CRYPT_CERTTYPE_CERTIFICATE || \
value == CRYPT_CERTTYPE_REQUEST_CERT )
{
/* Make sure that everything is set up ready to go */
status = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_IMMUTABLE );
if( cryptStatusError( status ) || !value )
return( CRYPT_ARGERROR_NUM1 );
#if 0 /* RA certs aren't necessarily CA certs */
if( type == CRYPT_SESSINFO_CACERTIFICATE )
{
/* Make sure that it really is a CA cert */
status = krnlSendMessage( cryptCert, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_CA );
if( cryptStatusError( status ) )
{
setErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_CA,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ARGERROR_NUM1 );
}
}
#endif /* 0 */
}
else
{
MESSAGE_DATA msgData = { NULL, 0 };
/* Make sure that everything is set up ready to go. Since revocation
requests aren't signed like normal cert objects we can't just
check the immutable attribute but have to perform a dummy export
for which the cert export code will return an error status if
there's a problem with the request */
status = krnlSendMessage( cryptCert, IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_ICERTFORMAT_DATA );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
}
/* Add the request and increment its usage count */
krnlSendNotifier( cryptCert, IMESSAGE_INCREFCOUNT );
if( type == CRYPT_SESSINFO_CACERTIFICATE )
sessionInfoPtr->iAuthInContext = cryptCert;
else
sessionInfoPtr->iCertRequest = cryptCert;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Session Access Routines *
* *
****************************************************************************/
int setAccessMethodCMP( SESSION_INFO *sessionInfoPtr )
{
static const ALTPROTOCOL_INFO altProtocolInfo = {
STREAM_PROTOCOL_CMP, /* Alt.protocol type */
"cmp://", 6, /* Alt.protocol URI type */
CMP_PORT, /* Alt.protocol port */
SESSION_ISHTTPTRANSPORT, /* Protocol flags to replace */
SESSION_USEALTTRANSPORT /* Alt.protocol flags */
};
static const PROTOCOL_INFO protocolInfo = {
/* General session information */
TRUE, /* Request-response protocol */
SESSION_ISHTTPTRANSPORT, /* Flags */
80, /* HTTP port */
0, /* Client attributes */
SESSION_NEEDS_PRIVATEKEY | /* Server attributes */
SESSION_NEEDS_PRIVKEYSIGN | \
SESSION_NEEDS_PRIVKEYCERT | \
SESSION_NEEDS_PRIVKEYCACERT | \
SESSION_NEEDS_KEYSET | \
SESSION_NEEDS_CERTSTORE,
2, 2, 2, /* Version 2 */
/* Protocol-specific information */
BUFFER_SIZE_DEFAULT, /* Buffer size info */
&altProtocolInfo /* Alt.transport protocol */
};
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
/* Set the access method pointers */
sessionInfoPtr->protocolInfo = &protocolInfo;
if( isServer( sessionInfoPtr ) )
sessionInfoPtr->transactFunction = serverTransact;
else
{
sessionInfoPtr->connectFunction = clientStartup;
sessionInfoPtr->transactFunction = clientTransactWrapper;
}
sessionInfoPtr->shutdownFunction = shutdownFunction;
sessionInfoPtr->getAttributeFunction = getAttributeFunction;
sessionInfoPtr->setAttributeFunction = setAttributeFunction;
/* Initialise CMP-specific objects */
sessionInfoPtr->sessionCMP->userInfo = CRYPT_ERROR;
sessionInfoPtr->sessionCMP->savedMacContext = CRYPT_ERROR;
return( CRYPT_OK );
}
#endif /* USE_CMP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -