📄 ssl_cry.c
字号:
/* Compare the calculated MAC to the MAC present at the end of the
data */
setMessageData( &msgData, ( BYTE * ) data + payloadLength,
sessionInfoPtr->authBlocksize );
status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
IMESSAGE_COMPARE, &msgData,
MESSAGE_COMPARE_HASH );
if( cryptStatusError( status ) )
{
/* If the error message has already been set at a higher level,
don't update the error info */
if( noReportError )
return( CRYPT_ERROR_SIGNATURE );
retExt( CRYPT_ERROR_SIGNATURE,
( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO,
"Bad message MAC for packet type %d, length %d",
type, dataLength ) );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* TLS MAC Functions *
* *
****************************************************************************/
/* Perform a TLS MAC of a data block. We have to provide special-case
handling of zero-length blocks since some versions of OpenSSL send these
as a kludge in SSL/TLS 1.0 to work around chosen-IV attacks */
CHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \
static int macDataTLS( const CRYPT_CONTEXT iHashContext, const long seqNo,
const int version,
IN_BUFFER( dataLength ) \
const void *data, const int dataLength,
const int type )
{
STREAM stream;
BYTE buffer[ 64 + 8 ];
int length = DUMMY_INIT, status;
assert( isHandleRangeValid( iHashContext ) );
assert( seqNo >= 0 );
assert( version >= 1 );
assert( isReadPtr( data, dataLength ) );
assert( dataLength >= 0 && dataLength <= MAX_PACKET_SIZE );
/* Set up the sequence number, type, version, and length data */
sMemOpen( &stream, buffer, 64 );
writeUint64( &stream, seqNo );
sputc( &stream, type );
sputc( &stream, SSL_MAJOR_VERSION );
sputc( &stream, version );
status = writeUint16( &stream, dataLength );
if( cryptStatusOK( status ) )
length = stell( &stream );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
/* Reset the hash context and generate the MAC:
HMAC( seq_num || type || version || length || data ) */
krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, length );
if( dataLength > 0 )
krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, ( void * ) data,
dataLength );
return( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 ) );
}
int createMacTLS( SESSION_INFO *sessionInfoPtr, void *data,
const int dataMaxLength, int *dataLength,
const int payloadLength, const int type )
{
SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
MESSAGE_DATA msgData;
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isWritePtr( data, dataMaxLength ) );
assert( isWritePtr( dataLength, sizeof( int ) ) );
assert( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE && \
payloadLength + sessionInfoPtr->authBlocksize <= dataMaxLength );
/* Sanity-check the state */
if( payloadLength < 0 || payloadLength > MAX_PACKET_SIZE || \
payloadLength + sessionInfoPtr->authBlocksize > dataMaxLength )
retIntError();
/* Clear return value */
*dataLength = 0;
/* MAC the payload */
status = macDataTLS( sessionInfoPtr->iAuthOutContext, sslInfo->writeSeqNo,
sessionInfoPtr->version, data, payloadLength, type );
if( cryptStatusError( status ) )
return( status );
sslInfo->writeSeqNo++;
/* Set the MAC value at the end of the packet */
setMessageData( &msgData, ( BYTE * ) data + payloadLength,
sessionInfoPtr->authBlocksize );
status = krnlSendMessage( sessionInfoPtr->iAuthOutContext,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusError( status ) )
return( status );
*dataLength = payloadLength + msgData.length;
return( CRYPT_OK );
}
int checkMacTLS( SESSION_INFO *sessionInfoPtr, const void *data,
const int dataLength, const int payloadLength,
const int type, const BOOLEAN noReportError )
{
SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
MESSAGE_DATA msgData;
int status;
assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
assert( isReadPtr( data, dataLength ) );
assert( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE && \
payloadLength + sessionInfoPtr->authBlocksize <= dataLength );
/* Sanity-check the state */
if( payloadLength < 0 || payloadLength > MAX_PACKET_SIZE || \
payloadLength + sessionInfoPtr->authBlocksize > dataLength )
retIntError();
/* MAC the payload */
status = macDataTLS( sessionInfoPtr->iAuthInContext, sslInfo->readSeqNo,
sessionInfoPtr->version, data, payloadLength, type );
if( cryptStatusError( status ) )
return( status );
sslInfo->readSeqNo++;
/* Compare the calculated MAC to the MAC present at the end of the
data */
setMessageData( &msgData, ( BYTE * ) data + payloadLength,
sessionInfoPtr->authBlocksize );
status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
IMESSAGE_COMPARE, &msgData,
MESSAGE_COMPARE_HASH );
if( cryptStatusError( status ) )
{
/* If the error message has already been set at a higher level,
don't update the error info */
if( noReportError )
return( CRYPT_ERROR_SIGNATURE );
retExt( CRYPT_ERROR_SIGNATURE,
( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO,
"Bad message MAC for packet type %d, length %d",
type, dataLength ) );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Dual-MAC Functions *
* *
****************************************************************************/
/* Perform a dual MAC of a data block */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int dualMacData( const SSL_HANDSHAKE_INFO *handshakeInfo,
IN_BUFFER( dataLength ) \
const void *data, const int dataLength )
{
int status;
assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
assert( isReadPtr( data, dataLength ) );
status = krnlSendMessage( handshakeInfo->clientMD5context,
IMESSAGE_CTX_HASH, ( void * ) data,
dataLength );
if( cryptStatusOK( status ) )
status = krnlSendMessage( handshakeInfo->clientSHA1context,
IMESSAGE_CTX_HASH, ( void * ) data,
dataLength );
if( cryptStatusOK( status ) )
status = krnlSendMessage( handshakeInfo->serverMD5context,
IMESSAGE_CTX_HASH, ( void * ) data,
dataLength );
if( cryptStatusOK( status ) )
status = krnlSendMessage( handshakeInfo->serverSHA1context,
IMESSAGE_CTX_HASH, ( void * ) data,
dataLength );
return( status );
}
int dualMacDataRead( const SSL_HANDSHAKE_INFO *handshakeInfo,
STREAM *stream )
{
const int dataLength = sMemDataLeft( stream );
void *data;
int status;
assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
assert( isReadPtr( stream, sizeof( STREAM ) ) );
assert( dataLength > 0 );
/* On a read we've just processed the packet header and everything
that's left in the stream is the data to be MACd */
status = sMemGetDataBlock( stream, &data, dataLength );
if( cryptStatusOK( status ) )
status = dualMacData( handshakeInfo, data, dataLength );
return( status );
}
int dualMacDataWrite( const SSL_HANDSHAKE_INFO *handshakeInfo,
STREAM *stream )
{
const int dataLength = stell( stream ) - SSL_HEADER_SIZE;
void *data;
int status;
assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
assert( isReadPtr( stream, sizeof( STREAM ) ) );
assert( dataLength > 0 );
/* On a write we've just finished writing the packet and everything but
the header needs to be MACd */
status = sMemGetDataBlockAbs( stream, SSL_HEADER_SIZE, &data,
dataLength );
if( cryptStatusOK( status ) )
status = dualMacData( handshakeInfo, data, dataLength );
return( status );
}
/* Complete the dual MD5/SHA1 hash/MAC used in the finished message */
int completeSSLDualMAC( const CRYPT_CONTEXT md5context,
const CRYPT_CONTEXT sha1context,
BYTE *hashValues, const int hashValuesMaxLen,
int *hashValuesLen, const char *label,
const int labelLength, const BYTE *masterSecret,
const int masterSecretLen )
{
MESSAGE_DATA msgData;
int status;
assert( isHandleRangeValid( md5context ) );
assert( isHandleRangeValid( sha1context ) );
assert( isWritePtr( hashValues, hashValuesMaxLen ) );
assert( isWritePtr( hashValuesLen, sizeof( int ) ) );
assert( isReadPtr( label, labelLength ) );
assert( isReadPtr( masterSecret, masterSecretLen ) );
assert( hashValuesMaxLen >= MD5MAC_SIZE + SHA1MAC_SIZE );
/* Clear return value */
*hashValuesLen = 0;
/* Generate the inner portion of the handshake message's MAC:
hash( handshake_messages || cl/svr_label || master_secret || pad1 ).
Note that the SHA-1 pad size is 40 bytes and not 44 (to get a total
length of 64 bytes), this is due to an error in the spec */
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) label,
labelLength );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) label,
labelLength );
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) masterSecret,
masterSecretLen );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) masterSecret,
masterSecretLen );
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 48 );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 40 );
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
setMessageData( &msgData, hashValues, MD5MAC_SIZE );
status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
}
if( cryptStatusError( status ) )
return( status );
/* Reset the hash contexts */
krnlSendMessage( md5context, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
krnlSendMessage( sha1context, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
/* Generate the outer portion of the handshake message's MAC:
hash( master_secret || pad2 || inner_hash ) */
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, ( void * ) masterSecret,
masterSecretLen );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, ( void * ) masterSecret,
masterSecretLen );
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 48 );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 40 );
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, hashValues,
MD5MAC_SIZE );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, hashValues + MD5MAC_SIZE,
SHA1MAC_SIZE );
krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
setMessageData( &msgData, hashValues, MD5MAC_SIZE );
status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusError( status ) )
return( status );
setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusOK( status ) )
*hashValuesLen = MD5MAC_SIZE + SHA1MAC_SIZE;
return( status );
}
int completeTLSHashedMAC( const CRYPT_CONTEXT md5context,
const CRYPT_CONTEXT sha1context,
BYTE *hashValues, const int hashValuesMaxLen,
int *hashValuesLen, const char *label,
const int labelLength, const BYTE *masterSecret,
const int masterSecretLen )
{
MECHANISM_DERIVE_INFO mechanismInfo;
MESSAGE_DATA msgData;
BYTE hashBuffer[ 64 + ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];
int status;
assert( isHandleRangeValid( md5context ) );
assert( isHandleRangeValid( sha1context ) );
assert( isWritePtr( hashValues, hashValuesMaxLen ) );
assert( isWritePtr( hashValuesLen, sizeof( int ) ) );
assert( isReadPtr( label, labelLength ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -