📄 cmp_wr.c
字号:
/* Determine how big the sender and recipient info will be. We
shouldn't need to send a recipient name for an ir because it won't
usually be known yet, but various implementations can't handle a zero-
length GeneralName, so we supply it if it's available even though it's
redundant */
if( useFullHeader )
{
/* Get the sender DN info */
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( senderNameObject, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SUBJECT );
if( status == CRYPT_ERROR_NOTFOUND && !isServer( sessionInfoPtr ) && \
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,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_SUBJECT );
}
}
if( cryptStatusError( status ) )
return( status );
senderNameLength = msgData.length;
/* Get the recipient DN info */
setMessageData( &msgData, NULL, 0 );
if( recipNameObject != CRYPT_ERROR )
status = krnlSendMessage( recipNameObject,
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, and if
this is a MAC-authenticated PKIBoot we don't have the CA's
cert yet so we don't know its DN. To work around this 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;
}
else
{
/* We're not using sender or recipient info since it doesn't serve
any useful purpose, just set the fields to an empty SEQUENCE */
senderNameLength = recipNameLength = sizeofObject( 0 );
}
/* Determine how big the remaining header data will be */
sMemNullOpen( &nullStream );
if( protocolInfo->useMACsend )
{
writeMacInfo( &nullStream, protocolInfo,
sessionInfoPtr->protocolFlags & CMP_PFLAG_MACINFOSENT );
}
else
{
writeContextAlgoID( &nullStream, protocolInfo->authContext,
protocolInfo->hashAlgo );
}
protInfoLength = stell( &nullStream );
sMemClose( &nullStream );
if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_CLIBIDSENT ) )
{
attributeLength += sizeofObject( \
sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
sizeofObject( 0 ) );
sendClibID = TRUE;
}
if( !( sessionInfoPtr->protocolFlags & CMP_PFLAG_CERTIDSENT ) && \
( ( isServer( sessionInfoPtr ) && \
protocolInfo->operation == CTAG_PB_GENM ) || \
!protocolInfo->useMACsend ) )
{
attributeLength += writeCertID( NULL, protocolInfo->authContext );
sendCertID = TRUE;
}
totalLength = sizeofShortInteger( CMP_VERSION ) + \
objSize( senderNameLength ) + objSize( recipNameLength ) + \
objSize( protInfoLength ) + \
objSize( sizeofObject( protocolInfo->transIDsize ) );
if( ( useFullHeader || \
!( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) ) && \
( protocolInfo->userIDsize > 0 ) )
totalLength += objSize( sizeofObject( protocolInfo->userIDsize ) );
if( useFullHeader )
totalLength += ( protocolInfo->senderNonceSize > 0 ? \
objSize( sizeofObject( protocolInfo->senderNonceSize ) ) : 0 ) + \
( protocolInfo->recipNonceSize > 0 ? \
objSize( sizeofObject( protocolInfo->recipNonceSize ) ) : 0 );
if( attributeLength > 0 )
totalLength += 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 name information present */
writeSequence( stream, totalLength );
writeShortInteger( stream, CMP_VERSION, DEFAULT_TAG );
if( useFullHeader )
{
writeConstructed( stream, senderNameLength, 4 );
if( senderNameObject != CRYPT_ERROR )
{
status = exportAttributeToStream( stream, senderNameObject,
CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( status );
}
else
writeSequence( stream, 0 );
writeConstructed( stream, recipNameLength, 4 );
if( recipNameObject != CRYPT_ERROR )
{
status = exportAttributeToStream( stream, recipNameObject,
CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusError( status ) )
return( status );
}
else
writeSequence( stream, 0 );
}
else
{
/* This is one of the portions of CMP where an optional field is
marked as mandatory, to balance out the mandatory fields that are
marked as optional. To work around this, we write the names as
zero-length DNs */
writeConstructed( stream, senderNameLength, 4 );
writeSequence( stream, 0 );
writeConstructed( stream, recipNameLength, 4 );
writeSequence( stream, 0 );
}
/* Write the protection info, assorted nonces and IDs, and extra
information that the other side may be able to make use of */
writeConstructed( stream, protInfoLength, CTAG_PH_PROTECTIONALGO );
if( protocolInfo->useMACsend )
{
writeMacInfo( stream, protocolInfo,
sessionInfoPtr->protocolFlags & CMP_PFLAG_MACINFOSENT );
sessionInfoPtr->protocolFlags |= CMP_PFLAG_MACINFOSENT;
}
else
{
writeContextAlgoID( stream, protocolInfo->authContext,
protocolInfo->hashAlgo );
}
if( ( useFullHeader || \
!( sessionInfoPtr->protocolFlags & CMP_PFLAG_USERIDSENT ) ) && \
( protocolInfo->userIDsize > 0 ) )
{
/* We're using full headers or we're the client sending our first
message, identify the sender key. If we're sending an error
response to an initial message that we couldn't even start to
parse, the transaction ID won't be present yet so we only send
this if it's present */
writeConstructed( stream, objSize( protocolInfo->userIDsize ),
CTAG_PH_SENDERKID );
writeOctetString( stream, protocolInfo->userID,
protocolInfo->userIDsize, DEFAULT_TAG );
sessionInfoPtr->protocolFlags |= CMP_PFLAG_USERIDSENT;
}
writeConstructed( stream, objSize( protocolInfo->transIDsize ),
CTAG_PH_TRANSACTIONID );
status = writeOctetString( stream, protocolInfo->transID,
protocolInfo->transIDsize, DEFAULT_TAG );
if( useFullHeader )
{
if( protocolInfo->senderNonceSize > 0 )
{
writeConstructed( stream,
objSize( protocolInfo->senderNonceSize ),
CTAG_PH_SENDERNONCE );
status = writeOctetString( stream, protocolInfo->senderNonce,
protocolInfo->senderNonceSize,
DEFAULT_TAG );
}
if( protocolInfo->recipNonceSize > 0 )
{
writeConstructed( stream,
objSize( protocolInfo->recipNonceSize ),
CTAG_PH_RECIPNONCE );
status = writeOctetString( stream, protocolInfo->recipNonce,
protocolInfo->recipNonceSize,
DEFAULT_TAG );
}
}
if( attributeLength > 0 )
{
assert( sendClibID || sendCertID );
/* We haven't sent any messages yet, let the other side know that
we're running cryptlib and identify our signing cert */
writeConstructed( stream, objSize( attributeLength ),
CTAG_PH_GENERALINFO );
status = writeSequence( stream, attributeLength );
if( sendClibID )
{
writeSequence( stream, sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \
sizeofObject( 0 ) );
writeOID( stream, OID_CRYPTLIB_PRESENCECHECK );
status = writeSet( stream, 0 );
sessionInfoPtr->protocolFlags |= CMP_PFLAG_CLIBIDSENT;
}
if( sendCertID )
{
status = writeCertID( stream, protocolInfo->authContext );
sessionInfoPtr->protocolFlags |= CMP_PFLAG_CERTIDSENT;
}
}
return( status );
}
/****************************************************************************
* *
* Write a PKI Message *
* *
****************************************************************************/
/* Write a PKI message:
PkiMessage ::= SEQUENCE {
header PKIHeader,
body CHOICE { [0]... [24]... },
protection [0] BIT STRING
} */
int writePkiMessage( SESSION_INFO *sessionInfoPtr,
CMP_PROTOCOL_INFO *protocolInfo,
const CMPBODY_TYPE bodyType )
{
BYTE protInfo[ 64 + MAX_PKCENCRYPTED_SIZE + 8 ], headerBuffer[ 8 + 8 ];
STREAM stream;
int headerSize, protInfoSize, status;
/* Write the header and payload so that we can MAC/sign it */
sMemOpen( &stream, sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufSize );
status = writePkiHeader( &stream, sessionInfoPtr, protocolInfo );
if( cryptStatusOK( status ) )
{
switch( bodyType )
{
case CMPBODY_NORMAL:
if( isServer( sessionInfoPtr ) )
status = writeResponseBody( &stream, sessionInfoPtr,
protocolInfo );
else
status = writeRequestBody( &stream, sessionInfoPtr,
protocolInfo );
break;
case CMPBODY_CONFIRMATION:
status = writeConfBody( &stream, sessionInfoPtr,
protocolInfo );
break;
case CMPBODY_ACK:
writeConstructed( &stream, sizeofNull(), CTAG_PB_PKICONF );
status = writeNull( &stream, DEFAULT_TAG );
break;
case CMPBODY_GENMSG:
if( isServer( sessionInfoPtr ) )
status = writeGenMsgBody( &stream, sessionInfoPtr );
else
{
writeConstructed( &stream,
objSize( objSize( sizeofOID( OID_PKIBOOT ) ) ),
CTAG_PB_GENM );
writeSequence( &stream,
objSize( sizeofOID( OID_PKIBOOT ) ) );
writeSequence( &stream, sizeofOID( OID_PKIBOOT ) );
status = writeOID( &stream, OID_PKIBOOT );
}
break;
case CMPBODY_ERROR:
status = writeErrorBody( &stream, protocolInfo );
break;
default:
retIntError();
}
}
if( cryptStatusError( status ) )
{
sMemClose( &stream );
return( status );
}
/* Generate the MAC or signature as appropriate */
if( protocolInfo->useMACsend )
{
status = writeMacProtinfo( protocolInfo->iMacContext,
sessionInfoPtr->receiveBuffer, stell( &stream ),
protInfo, 64 + MAX_PKCENCRYPTED_SIZE, &protInfoSize );
}
else
{
status = writeSignedProtinfo( protocolInfo->authContext,
protocolInfo->hashAlgo,
sessionInfoPtr->receiveBuffer, stell( &stream ),
protInfo, 64 + MAX_PKCENCRYPTED_SIZE, &protInfoSize );
}
if( cryptStatusError( status ) )
{
sMemClose( &stream );
return( status );
}
/* Attach the MAC/signature to the payload */
writeConstructed( &stream, protInfoSize, CTAG_PM_PROTECTION );
status = swrite( &stream, protInfo, protInfoSize );
sessionInfoPtr->receiveBufEnd = stell( &stream );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
/* Write the wrapper and move it onto the front of the message */
sMemOpen( &stream, headerBuffer, 8 );
writeSequence( &stream, sessionInfoPtr->receiveBufEnd );
headerSize = stell( &stream );
sMemDisconnect( &stream );
memmove( sessionInfoPtr->receiveBuffer + headerSize,
sessionInfoPtr->receiveBuffer,
sessionInfoPtr->receiveBufEnd );
memcpy( sessionInfoPtr->receiveBuffer, headerBuffer, headerSize );
sessionInfoPtr->receiveBufEnd += headerSize;
return( CRYPT_OK );
}
#endif /* USE_CMP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -