📄 ssl.c
字号:
algoAvailable( CRYPT_ALGO_RC4 ) )
suite = currentSuite;
break;
case SSL_RSA_WITH_DES_CBC_SHA:
if( suite == SSL_NULL_WITH_NULL && \
algoAvailable( CRYPT_ALGO_DES ) )
suite = currentSuite;
break;
}
}
return( suite );
}
/* Initialise and destroy the handshake state information */
static void destroyHandshakeInfo( SSL_HANDSHAKE_INFO *handshakeInfo )
{
/* Destroy any active contexts */
if( handshakeInfo->clientMD5context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->clientMD5context,
RESOURCE_IMESSAGE_DECREFCOUNT );
if( handshakeInfo->serverMD5context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->serverMD5context,
RESOURCE_IMESSAGE_DECREFCOUNT );
if( handshakeInfo->clientSHA1context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->clientSHA1context,
RESOURCE_IMESSAGE_DECREFCOUNT );
if( handshakeInfo->serverSHA1context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->serverSHA1context,
RESOURCE_IMESSAGE_DECREFCOUNT );
zeroise( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );
}
static int initHandshakeInfo( SSL_HANDSHAKE_INFO *handshakeInfo )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
/* Initialise the handshake state info values */
memset( handshakeInfo, 0, sizeof( SSL_HANDSHAKE_INFO ) );
handshakeInfo->clientMD5context = \
handshakeInfo->serverMD5context = \
handshakeInfo->clientSHA1context = \
handshakeInfo->serverSHA1context = CRYPT_ERROR;
/* Create the MAC contexts for ingoing and outgoing data. SSL uses a
pre-HMAC variant for which we can't use real HMAC but have to
construct it ourselves from MD5 and SHA-1, TLS uses a straight hash
and MACs that once a MAC key is available */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
handshakeInfo->clientMD5context = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
handshakeInfo->serverMD5context = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
handshakeInfo->clientSHA1context = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
handshakeInfo->serverSHA1context = createInfo.cryptHandle;
return( CRYPT_OK );
}
/* One or more of the contexts couldn't be created, destroy all the
contexts which have been created so far */
destroyHandshakeInfo( handshakeInfo );
return( status );
}
/* Initialise and destroy the security contexts */
static void destroySecurityContexts( SESSION_INFO *sessionInfoPtr )
{
/* Destroy any active contexts */
if( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,
RESOURCE_IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iKeyexCryptContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iAuthInContext,
RESOURCE_IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iAuthInContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iAuthOutContext,
RESOURCE_IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iAuthOutContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iCryptInContext,
RESOURCE_IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iCryptInContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iCryptOutContext,
RESOURCE_IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iCryptOutContext = CRYPT_ERROR;
}
}
static int initSecurityContexts( SESSION_INFO *sessionInfoPtr )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->integrityAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
sessionInfoPtr->iAuthInContext = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->integrityAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
sessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
sessionInfoPtr->iCryptInContext = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
sessionInfoPtr->iCryptOutContext = createInfo.cryptHandle;
else
/* One or more of the contexts couldn't be created, destroy all the
contexts which have been created so far */
destroySecurityContexts( sessionInfoPtr );
return( status );
}
/* Encrypt/decrypt a data block */
static int encryptData( SESSION_INFO *sessionInfoPtr, BYTE *data,
const int dataLength )
{
int length = dataLength, status;
/* If it's a block cipher, we need to add end-of-block padding */
if( sessionInfoPtr->cryptBlocksize > 1 )
{
BYTE *dataPadPtr = data + dataLength;
const int padSize = ( sessionInfoPtr->cryptBlocksize - 1 ) - \
( dataLength & ( sessionInfoPtr->cryptBlocksize - 1 ) );
int i;
for( i = 0; i < padSize + 1; i++ )
*dataPadPtr++ = padSize; /* PKCS #5 padding required by TLS */
length += padSize + 1;
}
status = krnlSendMessage( sessionInfoPtr->iCryptOutContext,
RESOURCE_IMESSAGE_CTX_ENCRYPT, data, length );
return( cryptStatusError( status ) ? status : length );
}
static int decryptData( SESSION_INFO *sessionInfoPtr, BYTE *data,
const int dataLength )
{
int length = dataLength, status;
/* Decrypt the data */
status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
RESOURCE_IMESSAGE_CTX_DECRYPT, data, length );
if( cryptStatusError( status ) )
return( status );
/* If it's a block cipher, we need to remove end-of-block padding */
if( sessionInfoPtr->cryptBlocksize > 1 )
{
const int ch = data[ dataLength - 1 ];
if( ch < 0 || ch > sessionInfoPtr->cryptBlocksize - 1 )
return( CRYPT_ERROR_BADDATA );
length -= ch + 1;
}
return( length );
}
/* Perform a MAC or dual MAC of a data block */
static int macDataSSL( SESSION_INFO *sessionInfoPtr, const void *data,
const int dataLength, const int type,
const BOOLEAN isRead )
{
RESOURCE_DATA msgData;
BYTE buffer[ 128 ], *bufPtr;
BYTE *macPtr = isRead ? buffer : ( BYTE * ) data + dataLength;
const CRYPT_CONTEXT iHashContext = isRead ? \
sessionInfoPtr->iAuthInContext : sessionInfoPtr->iAuthOutContext;
const void *macSecret = isRead ? \
sessionInfoPtr->sslMacReadSecret : sessionInfoPtr->sslMacWriteSecret;
const long seqNo = isRead ? \
sessionInfoPtr->readSeqNo++ : sessionInfoPtr->writeSeqNo++;
const int padSize = \
( sessionInfoPtr->integrityAlgo == CRYPT_ALGO_MD5 ) ? 48 : 40;
int status;
/* Set up the sequence number and length data */
memset( buffer, 0, sizeof( buffer ) );
memcpy( buffer, PROTOHMAC_PAD1, padSize );
bufPtr = buffer + padSize + 4;
mputBLong( bufPtr, seqNo );
*bufPtr++ = type;
mputBWord( bufPtr, dataLength );
/* Reset the hash context and generate the inner portion of the MAC:
hash( MAC_secret || pad1 || seq_num || type || length || data ) */
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
( void * ) macSecret, sessionInfoPtr->authBlocksize );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
buffer, padSize + 8 + ID_SIZE + UINT16_SIZE );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
( void * ) data, dataLength );
status = krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
"", 0 );
if( cryptStatusError( status ) )
return( status );
/* Extract the inner hash value */
memcpy( buffer, PROTOHMAC_PAD2, padSize );
setResourceData( &msgData, buffer + padSize, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
if( cryptStatusError( status ) )
return( status );
/* Generate the outer portion of the handshake message's MAC and get the
MAC value, which is either written to the end of the data (for a
write) or to a separate buffer (for a read):
hash( MAC_secret || pad2 || inner_hash ) */
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
( void * ) macSecret, sessionInfoPtr->authBlocksize );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
buffer, padSize + msgData.length );
status = krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH, "", 0 );
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, macPtr, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iHashContext,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_HASHVALUE );
}
if( cryptStatusError( status ) )
return( status );
/* If it's a read, compare the calculated MAC to the MAC present at the
end of the data */
if( isRead )
return( memcmp( macPtr, ( BYTE * ) data + dataLength, msgData.length ) ? \
CRYPT_ERROR_SIGNATURE : CRYPT_OK );
return( dataLength + msgData.length );
}
static int macDataTLS( SESSION_INFO *sessionInfoPtr, const void *data,
const int dataLength, const int type,
const BOOLEAN isRead )
{
RESOURCE_DATA msgData;
BYTE buffer[ 128 ], *bufPtr;
BYTE *macPtr = isRead ? buffer : ( BYTE * ) data + dataLength;
const CRYPT_CONTEXT iHashContext = isRead ? \
sessionInfoPtr->iAuthInContext : sessionInfoPtr->iAuthOutContext;
const long seqNo = isRead ? \
sessionInfoPtr->readSeqNo++ : sessionInfoPtr->writeSeqNo++;
int status;
/* Set up the sequence number, type, version, and length data */
memset( buffer, 0, sizeof( buffer ) );
bufPtr = buffer + 4;
mputBLong( bufPtr, seqNo );
*bufPtr++ = type;
*bufPtr++ = SSL_MAJOR_VERSION;
*bufPtr++ = TLS_MINOR_VERSION;
mputBWord( bufPtr, dataLength );
/* Reset the hash context and generate the MAC, which is either written
to the end of the data (for a write) or to a separate buffer (for a
read):
HMAC( seq_num || type || version || length || data ) */
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_HASHVALUE );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
buffer, 8 + ID_SIZE + VERSIONINFO_SIZE + UINT16_SIZE );
krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
( void * ) data, dataLength );
status = krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
"", 0 );
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, macPtr, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iHashContext,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
}
if( cryptStatusError( status ) )
return( status );
/* If it's a read, compare the calculated MAC to the MAC present at the
end of the data */
if( isRead )
return( memcmp( macPtr, ( BYTE * ) data + dataLength, msgData.length ) ? \
CRYPT_ERROR_SIGNATURE : CRYPT_OK );
return( dataLength + msgData.length );
}
static int dualMacData( SSL_HANDSHAKE_INFO *handshakeInfo, const void *data,
const int dataLength )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -