📄 cmp.c
字号:
MESSAGE_KEYMGMT_INFO getkeyInfo;
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
/* Set up general authentication information and if there's user info
still present from a previous transaction, clear it */
status = setProtocolInfo( protocolInfo, NULL, 0,
PROTOCOLINFO_SET_MACCTX );
if( cryptStatusError( status ) )
return( status );
if( cmpInfo->userInfo != CRYPT_ERROR )
{
krnlSendNotifier( cmpInfo->userInfo, IMESSAGE_DECREFCOUNT );
cmpInfo->userInfo = CRYPT_ERROR;
}
/* Get the user info for the user identified by the user ID from the
cert store. If we get a not-found error we report it as "signer not
trusted", which can also mean "signer unknown".
In theory we could perform a quick-reject check that the userID is
the correct length for a cryptlib-created ID (9 bytes), but it's
better to pass it into the system and let the failure come back
through the standard error-handling mechanisms */
setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID,
protocolInfo->userID, protocolInfo->userIDsize,
NULL, 0, KEYMGMT_FLAG_NONE );
status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PKIUSER );
if( cryptStatusError( status ) )
{
const ATTRIBUTE_LIST *userNamePtr = \
findSessionInfo( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_USERNAME );
char userID[ CRYPT_MAX_TEXTSIZE + 8 ];
int userIDlen;
if( userNamePtr->flags & ATTR_FLAG_ENCODEDVALUE && \
userNamePtr->valueLength > 10 && \
userNamePtr->valueLength < CRYPT_MAX_TEXTSIZE )
{
memcpy( userID, userNamePtr->value, userNamePtr->valueLength );
userIDlen = userNamePtr->valueLength;
}
else
{
strlcpy_s( userID, CRYPT_MAX_TEXTSIZE, "the requested user" );
userIDlen = 18;
}
protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
retExtObj( status,
( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
"Couldn't find PKI user information for %s",
sanitiseString( userID, CRYPT_MAX_TEXTSIZE,
userIDlen ) ) );
}
cmpInfo->userInfo = getkeyInfo.cryptHandle;
protocolInfo->userIDchanged = FALSE;
/* Get the password from the PKI user object if necessary */
if( findSessionInfo( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_PASSWORD ) == NULL )
{
MESSAGE_DATA msgData;
char password[ CRYPT_MAX_TEXTSIZE + 8 ];
setMessageData( &msgData, password, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( cmpInfo->userInfo,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD );
if( cryptStatusError( status ) )
{
retExt( status,
( status, SESSION_ERRINFO,
"Couldn't read PKI user data from PKI user object" ) );
}
status = updateSessionInfo( &sessionInfoPtr->attributeList,
CRYPT_SESSINFO_PASSWORD, password,
msgData.length, CRYPT_MAX_TEXTSIZE,
ATTR_FLAG_ENCODEDVALUE );
zeroise( password, CRYPT_MAX_TEXTSIZE );
if( cryptStatusError( status ) )
{
retExt( status,
( status, SESSION_ERRINFO,
"Couldn't copy PKI user data from PKI user object to "
"session object" ) );
}
}
return( CRYPT_OK );
}
int initServerAuthentSign( SESSION_INFO *sessionInfoPtr,
CMP_PROTOCOL_INFO *protocolInfo )
{
CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
const ATTRIBUTE_LIST *userNamePtr = \
findSessionInfo( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_USERNAME );
MESSAGE_KEYMGMT_INFO getkeyInfo;
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
/* Set up general authentication information and if there's client auth.
info still present from a previous transaction that used MAC
authentication, clear it */
status = setProtocolInfo( protocolInfo, NULL, 0, 0 );
if( cryptStatusError( status ) )
return( status );
if( cmpInfo->userInfo != CRYPT_ERROR )
{
krnlSendNotifier( cmpInfo->userInfo, IMESSAGE_DECREFCOUNT );
cmpInfo->userInfo = CRYPT_ERROR;
}
/* Get the user info for the user that originally authorised the issue
of the cert that signed the request. This serves two purposes, it
obtains the user ID if it wasn't supplied in the request (for example
if the request uses only a cert ID), and it verifies that the
authorising cert belongs to a valid user */
setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
protocolInfo->certID, protocolInfo->certIDsize,
NULL, 0, KEYMGMT_FLAG_GETISSUER );
status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PKIUSER );
if( cryptStatusError( status ) )
{
protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
retExtObj( status,
( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
"Couldn't find PKI user information for owner of "
"requesting cert" ) );
}
/* If there's currently no user ID present or if it's present but it's a
non-userID value such as a cert ID, replace it with the PKI user ID */
if( userNamePtr == NULL || \
!( userNamePtr->flags & ATTR_FLAG_ENCODEDVALUE ) )
{
MESSAGE_DATA msgData;
char userName[ CRYPT_MAX_TEXTSIZE + 8 ];
setMessageData( &msgData, userName, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( getkeyInfo.cryptHandle,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_PKIUSER_ID );
if( cryptStatusError( status ) )
{
krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, SESSION_ERRINFO,
"Couldn't read PKI user data from PKI user object" ) );
}
status = updateSessionInfo( &sessionInfoPtr->attributeList,
CRYPT_SESSINFO_USERNAME, userName,
msgData.length, CRYPT_MAX_TEXTSIZE,
ATTR_FLAG_ENCODEDVALUE );
if( cryptStatusError( status ) )
{
retExt( status,
( status, SESSION_ERRINFO,
"Couldn't copy PKI user data from PKI user object to "
"session object" ) );
}
}
krnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
/* Get the public key identified by the cert ID from the cert store.
This assumes that the owner of an existing cert/existing user is
authorised to request further certs using the existing one. If we
get a not found error we report it as "signer not trusted", which
can also mean "signer unknown" */
setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
protocolInfo->certID, protocolInfo->certIDsize,
NULL, 0, KEYMGMT_FLAG_USAGE_SIGN );
status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PUBLICKEY );
if( cryptStatusError( status ) )
{
protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
retExtObj( status,
( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
"Couldn't find certificate for requested user" ) );
}
sessionInfoPtr->iAuthInContext = getkeyInfo.cryptHandle;
protocolInfo->userIDchanged = FALSE;
return( CRYPT_OK );
}
/* Hash/MAC the message header and body */
int hashMessageContents( const CRYPT_CONTEXT iHashContext,
const void *data, const int length )
{
STREAM stream;
BYTE buffer[ 8 + 8 ];
assert( isHandleRangeValid( iHashContext ) );
assert( isReadPtr( data, length ) );
/* Delete the hash/MAC value, which resets the context */
krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
/* Write the pseudoheader used for hashing/MACing the header and body and
hash/MAC it */
sMemOpen( &stream, buffer, 8 );
writeSequence( &stream, length );
krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,
stell( &stream ) );
sMemClose( &stream );
krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) data,
length );
return( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 0 ) );
}
/* Deliver an Einladung betreff Kehrseite to the client. We don't bother
checking the return value for the write since there's nothing that we can
do in the case of an error except close the connection, which we do
anyway since this is the last message */
static void sendErrorResponse( SESSION_INFO *sessionInfoPtr,
CMP_PROTOCOL_INFO *protocolInfo,
const int errorStatus )
{
BOOLEAN writeHttpResponseOnly = !protocolInfo->headerRead;
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
assert( cryptStatusError( errorStatus ) );
/* If we were going to protect the communication with the client with a
MAC and something failed, make sure that we don't try and MAC the
response since the failure could be a client MAC failure, failure to
locate the MAC key, etc etc */
protocolInfo->useMACsend = FALSE;
protocolInfo->status = errorStatus;
/* Write the error response if we can. We only do this if at least the
header of the client's message was successfully read, otherwise we
can't create our own header for the response */
sioctl( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, NULL, TRUE );
if( !writeHttpResponseOnly )
{
status = writePkiMessage( sessionInfoPtr, protocolInfo, CMPBODY_ERROR );
if( cryptStatusError( status ) )
writeHttpResponseOnly = TRUE;
}
if( writeHttpResponseOnly )
{
HTTP_DATA_INFO httpDataInfo;
/* If we encounter an error processing the initial request, there
won't be enough information available to create an error
response. At this point the best that we can do is send an error
at the HTTP level */
initHttpDataInfo( &httpDataInfo, sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize );
httpDataInfo.reqStatus = errorStatus;
swrite( &sessionInfoPtr->stream, &httpDataInfo,
sizeof( HTTP_DATA_INFO ) );
return;
}
DEBUG_DUMP_CMP( CTAG_PB_ERROR, 1, sessionInfoPtr );
( void ) writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
CMP_CONTENT_TYPE_LEN );
}
/* Set up information needed to perform a client-side transaction */
static int initClientInfo( SESSION_INFO *sessionInfoPtr,
CMP_PROTOCOL_INFO *protocolInfo )
{
CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
const ATTRIBUTE_LIST *userNamePtr = \
findSessionInfo( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_USERNAME );
const ATTRIBUTE_LIST *passwordPtr = \
findSessionInfo( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_PASSWORD );
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
assert( !isServer( sessionInfoPtr ) );
/* Determine what we need to do based on the request type */
protocolInfo->operation = clibReqToReq( cmpInfo->requestType );
if( cryptStatusError( protocolInfo->operation ) )
return( protocolInfo->operation );
/* If we're using public key-based authentication, set up the key and
user ID information */
if( cmpInfo->requestType != CRYPT_REQUESTTYPE_PKIBOOT && \
cmpInfo->requestType != CRYPT_REQUESTTYPE_INITIALISATION && \
!( cmpInfo->requestType == CRYPT_REQUESTTYPE_REVOCATION && \
passwordPtr != NULL ) )
{
/* If it's an encryption-only key, remember this for later when we
need to authenticate our request messages */
status = krnlSendMessage( sessionInfoPtr->privateKey, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_SIGN );
if( cryptStatusError( status ) )
{
/* The private key can't be used for signature creation, use
the alternate authentication key instead */
protocolInfo->authContext = sessionInfoPtr->iAuthOutContext;
protocolInfo->cryptOnlyKey = TRUE;
}
else
/* The private key that we're using is capable of authenticating
requests */
protocolInfo->authContext = sessionInfoPtr->privateKey;
/* If we're not talking to a cryptlib peer, get the user ID. If
it's a standard signed request the authenticating object will be
the private key, however if the private key is an encryption-only
key the message authentication key is a separate object. To
handle this we get the user ID from the signing key rather than
automatically using the private key */
if( !protocolInfo->isCryptlib )
{
MESSAGE_DATA msgData;
BYTE userID[ CRYPT_MAX_HASHSIZE + 8 ];
setMessageData( &msgData, userID, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( protocolInfo->authContext,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusOK( status ) )
status = setProtocolInfo( protocolInfo, userID,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -