📄 cmp.c
字号:
/* Write the request body */
writeConstructed( stream, objSize( msgData.length ),
protocolInfo->operation );
writeSequence( stream, msgData.length );
msgData.data = sMemBufPtr( stream );
status = krnlSendMessage( sessionInfoPtr->iCertRequest,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
attrType );
if( cryptStatusOK( status ) )
status = sSkip( stream, msgData.length );
return( status );
}
static int writeResponseBody( STREAM *stream,
const SESSION_INFO *sessionInfoPtr,
const CMP_PROTOCOL_INFO *protocolInfo )
{
RESOURCE_DATA msgData;
int payloadSize, status;
UNUSED( protocolInfo );
/* Find out how big the payload will be */
if( protocolInfo->operation != CTAG_PB_RR )
{
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENC_CERT );
if( cryptStatusError( status ) )
return( status );
payloadSize = sizeofShortInteger( 0 ) + \
objSize( sizeofShortInteger( 0 ) ) + \
objSize( objSize( msgData.length ) );
}
else
payloadSize = sizeofShortInteger( 0 );
/* Write the response body wrapper */
writeConstructed( stream, objSize( objSize( objSize( payloadSize ) ) ),
reqToRespType( protocolInfo->operation ) );
writeSequence( stream, objSize( objSize( payloadSize ) ) );
/* Write the response. We always write an OK status here because an
error will have been communicated by sending an explicit error
response */
writeSequence( stream, objSize( payloadSize ) );
writeSequence( stream, payloadSize );
if( protocolInfo->operation != CTAG_PB_RR )
{
writeShortInteger( stream, 0, DEFAULT_TAG );
writeSequence( stream, sizeofShortInteger( 0 ) );
}
writeShortInteger( stream, PKISTATUS_OK, DEFAULT_TAG );
if( protocolInfo->operation != CTAG_PB_RR )
{
writeSequence( stream, objSize( msgData.length ) );
writeConstructed( stream, msgData.length, CTAG_CK_CERT );
msgData.data = sMemBufPtr( stream );
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENC_CERT );
if( cryptStatusOK( status ) )
status = sSkip( stream, msgData.length );
}
return( status );
}
static int writeConfBody( STREAM *stream,
const SESSION_INFO *sessionInfoPtr,
const CMP_PROTOCOL_INFO *protocolInfo )
{
RESOURCE_DATA msgData;
BYTE hashBuffer[ CRYPT_MAX_HASHSIZE ];
int length, status;
/* Get the certificate hash */
setResourceData( &msgData, hashBuffer, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( sessionInfoPtr->iCertResponse,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
( protocolInfo->confHashAlgo == CRYPT_ALGO_SHA ) ? \
CRYPT_CERTINFO_FINGERPRINT_SHA : \
CRYPT_CERTINFO_FINGERPRINT_MD5 );
if( cryptStatusError( status ) )
return( status );
length = ( int ) sizeofObject( msgData.length ) + sizeofShortInteger( 0 );
/* Write the confirmation body */
writeConstructed( stream, objSize( objSize( length ) ),
CTAG_PB_CERTCONF );
writeSequence( stream, objSize( length ) );
writeSequence( stream, length );
writeOctetString( stream, hashBuffer, msgData.length, DEFAULT_TAG );
return( writeShortInteger( stream, 0, DEFAULT_TAG ) );
}
static int writeErrorBody( STREAM *stream,
const SESSION_INFO *sessionInfoPtr,
const CMP_PROTOCOL_INFO *protocolInfo )
{
const int length = writePkiStatusInfo( NULL, protocolInfo->status,
protocolInfo->pkiFailInfo );
/* Write the error body */
writeConstructed( stream, length, CTAG_PB_ERROR );
return( writePkiStatusInfo( stream, protocolInfo->status,
protocolInfo->pkiFailInfo ) );
}
/* Read assorted PKI body messages */
static int readErrorBody( STREAM *stream, SESSION_INFO *sessionInfoPtr )
{
int endPos, length, status;
/* Read the outer wrapper and PKI status info. An error return status
is valid when we read the status info since we're reading an error
status and converting it into a cryptlib status, so we don't exit
unless it's a problem with the status info itself */
readConstructed( stream, NULL, CTAG_PB_ERROR );
readSequence( stream, &length ); /* Outer wrapper */
endPos = stell( stream ) + length;
status = readPkiStatusInfo( stream, &sessionInfoPtr->errorCode,
sessionInfoPtr->errorMessage );
if( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_UNDERFLOW )
return( status );
/* In addition to the PKI status info there can be another layer of
error information wrapped around it which is exactly the same only
different, so if we haven't got anything from the status info we
check to see whether this layer can give us anything */
if( stell( stream ) < endPos && peekTag( stream ) == BER_INTEGER )
{
/* If there's an error code present and we haven't already set the
error code from the pkiStatusInfo, set it now */
if( !sessionInfoPtr->errorCode )
{
long value;
readShortInteger( stream, &value );
sessionInfoPtr->errorCode = ( int ) value;
}
else
readUniversal( stream );
}
if( stell( stream ) < endPos && peekTag( stream ) == BER_SEQUENCE && \
!*sessionInfoPtr->errorMessage )
/* Read the error text, ignoring any possible error status since the
overall error code from the status info is more meaningful than
a data format problem in trying to read the error text */
readFreeText( stream, sessionInfoPtr->errorMessage,
MAX_ERRMSG_SIZE - 1 );
return( status );
}
/****************************************************************************
* *
* PKI Header Functions *
* *
****************************************************************************/
/* Write a PKI header from the session and protocol information:
header SEQUENCE {
version INTEGER (2),
sender [4] EXPLICIT DirectoryName, -- DN of initiator
recipient [4] EXPLICIT DirectoryName, -- DN of responder
protAlgo [1] EXPLICIT AlgorithmIdentifier,
protKeyID [2] EXPLICIT OCTET STRING,
transID [4] EXPLICIT OCTET STRING SIZE (16),-- Random/copied from sender
nonce [5] EXPLICIT OCTET STRING SIZE (16),-- Random
nonceX [6] EXPLICIT OCTET STRING SIZE (n), -- Copied from sender
generalInfo [8] EXPLICIT SEQUENCE OF Info OPT -- cryptlib-specific info
} */
static int writePkiHeader( STREAM *stream, SESSION_INFO *sessionInfoPtr,
CMP_PROTOCOL_INFO *protocolInfo )
{
CRYPT_HANDLE senderNameObject = \
( sessionInfoPtr->flags & SESSION_ISSERVER ) ? \
sessionInfoPtr->privateKey : sessionInfoPtr->iCertRequest;
const CRYPT_HANDLE recipNameObject = \
( sessionInfoPtr->flags & SESSION_ISSERVER ) ? \
sessionInfoPtr->iCertResponse : sessionInfoPtr->iAuthInContext;
STREAM nullStream;
RESOURCE_DATA msgData;
int senderNameLength, recipNameLength, protInfoLength, totalLength;
int attributeLength = sizeofObject( \
sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) +
sizeofObject( 0 ) );
int status;
/* Determine how big the header data will be. In theory we don't need
to send a recipient name for an ir but various implementations can't
handle a zero-length GeneralName so we supply it if it's available
even though it's redundant */
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( senderNameObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_SUBJECT );
if( status == CRYPT_ERROR_NOTFOUND && \
!( sessionInfoPtr->flags & SESSION_ISSERVER ) && \
protocolInfo->operation == CTAG_PB_IR )
{
/* If there's no subject DN present and it's the first message in a
client's ir exchange, this isn't an error because the subject may
not know their DN yet (at least that's the theory, most servers
will reject a message with no sender name) */
if( sessionInfoPtr->iCertResponse == CRYPT_ERROR )
{
senderNameObject = CRYPT_ERROR;
msgData.length = ( int ) sizeofObject( 0 );
status = CRYPT_OK;
}
else
{
/* Try again with the response from the server, which contains
our newly-allocated DN */
senderNameObject = sessionInfoPtr->iCertResponse;
status = krnlSendMessage( senderNameObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_SUBJECT );
}
}
if( cryptStatusOK( status ) )
{
senderNameLength = msgData.length;
setResourceData( &msgData, NULL, 0 );
if( recipNameObject != CRYPT_ERROR )
status = krnlSendMessage( recipNameObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_SUBJECT );
else
/* If we're sending an error response there may not be any
recipient name information present yet if the error occurred
before the recipient information could be established, in
which case we send a zero-length DN (this is one of those
places where an optional field is specified as being
mandatory, to lend balance to the places where mandatory
fields are specified as optional) */
msgData.length = ( int ) sizeofObject( 0 );
}
if( cryptStatusError( status ) )
return( status );
recipNameLength = msgData.length;
sMemOpen( &nullStream, NULL, 0 );
if( protocolInfo->useMACsend )
writeMacInfo( &nullStream, protocolInfo );
else
{
writeContextAlgoID( &nullStream, sessionInfoPtr->privateKey,
CRYPT_ALGO_SHA, ALGOID_FLAG_ALGOID_ONLY );
attributeLength += writeCertID( NULL, sessionInfoPtr->privateKey );
}
protInfoLength = stell( &nullStream );
sMemClose( &nullStream );
totalLength = sizeofShortInteger( CMP_VERSION ) + \
objSize( senderNameLength ) + objSize( recipNameLength ) + \
objSize( protInfoLength ) + \
objSize( sizeofObject( protocolInfo->userIDsize ) ) + \
objSize( sizeofObject( protocolInfo->transIDsize ) ) + \
objSize( sizeofObject( protocolInfo->senderNonceSize ) ) + \
( protocolInfo->recipNonceSize ? \
objSize( sizeofObject( protocolInfo->recipNonceSize ) ) : 0 ) + \
objSize( objSize( attributeLength ) );
if( sizeofObject( totalLength ) > sMemDataLeft( stream ) )
return( CRYPT_ERROR_OVERFLOW );
/* Write the PKI header wrapper, version info, and sender and recipient
names (if there's recipient name information present). We don't have
to worry about overflowing the stream when we get the names since
we've already done a length check */
writeSequence( stream, totalLength );
writeShortInteger( stream, CMP_VERSION, DEFAULT_TAG );
writeConstructed( stream, senderNameLength, 4 );
if( senderNameObject != CRYPT_ERROR )
{
setResourceData( &msgData, sMemBufPtr( stream ), senderNameLength );
status = krnlSendMessage( senderNameObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( status );
sSkip( stream, senderNameLength );
}
else
writeSequence( stream, 0 );
writeConstructed( stream, recipNameLength, 4 );
if( recipNameObject != CRYPT_ERROR )
{
setResourceData( &msgData, sMemBufPtr( stream ), recipNameLength );
status = krnlSendMessage( recipNameObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( status );
sSkip( stream, recipNameLength );
}
else
writeSequence( stream, 0 );
/* Write the protection info, assorted nonces and ID's, and extra
information which the other side may be able to make use of */
writeConstructed( stream, protInfoLength, CTAG_PH_PROTECTIONALGO );
if( protocolInfo->useMACsend )
writeMacInfo( stream, protocolInfo );
else
writeContextAlgoID( stream, sessionInfoPtr->privateKey,
CRYPT_ALGO_SHA, ALGOID_FLAG_ALGOID_ONLY );
writeConstructed( stream, objSize( protocolInfo->userIDsize ),
CTAG_PH_SENDERKID );
writeOctetString( stream, protocolInfo->userID,
protocolInfo->userIDsize, DEFAULT_TAG );
writeConstructed( stream, objSize( protocolInfo->transIDsize ),
CTAG_PH_TRANSACTIONID );
writeOctetString( stream, protocolInfo->transID,
protocolInfo->transIDsize, DEFAULT_TAG );
writeConstructed( stream, objSize( protocolInfo->senderNonceSize ),
CTAG_PH_SENDERNONCE );
writeOctetString( stream, protocolInfo->senderNonce,
protocolInfo->senderNonceSize, DEFAULT_TAG );
if( protocolInfo->recipNonceSize )
{
writeConstructed( stream, objSize( protocolInfo->recipNonceSize ),
CTAG_PH_RECIPNONCE );
writeOctetString( stream, protocolInfo->recipNonce,
protocolInfo->recipNonceSize, DEFAULT_TAG );
}
writeConstructed( stream, objSize( attributeLength ),
CTAG_PH_GENERALINFO );
writeSequence( stream, attributeLength );
writeSequence( stream, sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
sizeofObject( 0 ) );
writeOID( stream, OID_CRYPTLIB_PRESENCECHECK );
status = writeSet( stream, 0 );
if( !protocolInfo->useMACsend )
status = writeCertID( stream, sessionInfoPtr->privateKey );
return( status );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -