📄 ssl_cry.c
字号:
min( attributeListPtr->valueLength,
SSL_SECRET_SIZE ) );
/* Create the master secret from the expanded user-supplied password.
Note that since the use of shared secrets is specified only for TLS,
we always use the TLS key derivation even if it's with the SSL
protocol */
setMechanismDeriveInfo( &mechanismInfo,
masterSecret, SSL_SECRET_SIZE,
premasterSecret, SSL_SECRET_SIZE,
CRYPT_USE_DEFAULT, "shared secret", 13, 1 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_DERIVE, &mechanismInfo,
MECHANISM_DERIVE_TLS );
zeroise( premasterSecret, SSL_SECRET_SIZE );
if( cryptStatusOK( status ) )
*masterSecretLength = SSL_SECRET_SIZE;
return( status );
}
#else
int createSharedPremasterSecret( void *premasterSecret,
int *premasterSecretLength,
const SESSION_INFO *sessionInfoPtr )
{
const ATTRIBUTE_LIST *attributeListPtr = \
findSessionAttribute( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_PASSWORD );
STREAM stream;
BYTE zeroes[ CRYPT_MAX_TEXTSIZE + 8 ];
/* Write the PSK-derived premaster secret value:
uint16 otherSecretLen
byte[] otherSecret
uint16 pskLen
byte[] psk
Because the TLS PRF splits the input into two halves, one half which
is processed by HMAC-MD5 and the other by HMAC-SHA1, it's necessary
to extend the PSK in some way to provide input to both halves of the
PRF. In a rather dubious decision, the spec requires that the MD5
half be set to all zeroes, with only the SHA1 half being used. To
achieve this, we write otherSecret as a number of zero bytes equal in
length to the password */
memset( zeroes, 0, CRYPT_MAX_TEXTSIZE );
sMemOpen( &stream, premasterSecret,
( UINT16_SIZE + CRYPT_MAX_TEXTSIZE ) * 2 );
if( attributeListPtr->flags & ATTR_FLAG_ENCODEDVALUE )
{
BYTE decodedValue[ CRYPT_MAX_TEXTSIZE + 8 ];
int decodedValueLength;
/* It's a cryptlib-style encoded password, decode it into its binary
value */
decodedValueLength = decodePKIUserValue( decodedValue,
attributeListPtr->value,
attributeListPtr->valueLength );
if( cryptStatusError( decodedValueLength ) )
{
assert( NOTREACHED );
return( decodedValueLength );
}
writeUint16( &stream, decodedValueLength );
swrite( &stream, zeroes, decodedValueLength );
writeUint16( &stream, decodedValueLength );
swrite( &stream, decodedValue, decodedValueLength );
zeroise( decodedValue, decodedValueLength );
}
else
{
writeUint16( &stream, attributeListPtr->valueLength );
swrite( &stream, zeroes, attributeListPtr->valueLength );
writeUint16( &stream, attributeListPtr->valueLength );
swrite( &stream, attributeListPtr->value,
attributeListPtr->valueLength );
}
*premasterSecretLength = stell( &stream );
sMemDisconnect( &stream );
return( CRYPT_OK );
}
#endif /* 0 */
/* Wrap/unwrap the pre-master secret */
int wrapPremasterSecret( SESSION_INFO *sessionInfoPtr,
SSL_HANDSHAKE_INFO *handshakeInfo,
void *data, int *dataLength )
{
MECHANISM_WRAP_INFO mechanismInfo;
RESOURCE_DATA msgData;
int status;
/* Clear return value */
*dataLength = 0;
/* Create the premaster secret and wrap it using the server's public
key. Note that the version that we advertise at this point is the
version originally offered by the client in its hello message, not
the version eventually negotiated for the connection. This is
designed to prevent rollback attacks (but see also the comment in
unwrapPremasterSecret() below) */
handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
handshakeInfo->premasterSecret[ 0 ] = SSL_MAJOR_VERSION;
handshakeInfo->premasterSecret[ 1 ] = handshakeInfo->clientOfferedVersion;
setMessageData( &msgData,
handshakeInfo->premasterSecret + VERSIONINFO_SIZE,
handshakeInfo->premasterSecretSize - VERSIONINFO_SIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM );
if( cryptStatusError( status ) )
return( status );
setMechanismWrapInfo( &mechanismInfo, data, CRYPT_MAX_PKCSIZE,
handshakeInfo->premasterSecret,
handshakeInfo->premasterSecretSize, CRYPT_UNUSED,
sessionInfoPtr->iKeyexCryptContext, CRYPT_UNUSED );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,
&mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
if( cryptStatusOK( status ) )
*dataLength = mechanismInfo.wrappedDataLength;
clearMechanismInfo( &mechanismInfo );
return( status );
}
int unwrapPremasterSecret( SESSION_INFO *sessionInfoPtr,
SSL_HANDSHAKE_INFO *handshakeInfo,
const void *data, const int dataLength )
{
MECHANISM_WRAP_INFO mechanismInfo;
int status;
/* Decrypt the encrypted premaster secret. In theory we could
explicitly defend against Bleichenbacher-type attacks at this point
by setting the premaster secret to a pseudorandom value if we get a
bad data or (later) an incorrect version error and continuing as
normal, however the attack depends on the server returning
information required to pinpoint the cause of the failure and
cryptlib just returns a generic "failed" response for any handshake
failure, so this explicit defence isn't really necessary */
handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
setMechanismWrapInfo( &mechanismInfo, ( void * ) data, dataLength,
handshakeInfo->premasterSecret,
handshakeInfo->premasterSecretSize, CRYPT_UNUSED,
sessionInfoPtr->privateKey, CRYPT_UNUSED );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,
&mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
if( cryptStatusOK( status ) && \
mechanismInfo.keyDataLength != handshakeInfo->premasterSecretSize )
status = CRYPT_ERROR_BADDATA;
clearMechanismInfo( &mechanismInfo );
if( cryptStatusError( status ) )
return( status );
/* Make sure that it looks OK. Note that the version that we check for
at this point is the version originally offered by the client in its
hello message, not the version eventually negotiated for the
connection. This is designed to prevent rollback attacks */
if( handshakeInfo->premasterSecret[ 0 ] != SSL_MAJOR_VERSION || \
handshakeInfo->premasterSecret[ 1 ] != handshakeInfo->clientOfferedVersion )
{
/* Microsoft braindamage, even the latest versions of MSIE still send
the wrong version number for the premaster secret (making it look
like a rollback attack), so if we're expecting 3.1 and get 3.0, it's
MSIE screwing up */
if( handshakeInfo->premasterSecret[ 0 ] == SSL_MAJOR_VERSION && \
handshakeInfo->premasterSecret[ 1 ] == SSL_MINOR_VERSION_SSL && \
sessionInfoPtr->version == SSL_MINOR_VERSION_SSL && \
handshakeInfo->clientOfferedVersion == SSL_MINOR_VERSION_TLS )
strcpy( sessionInfoPtr->errorMessage,
"Warning: Accepting invalid premaster secret version "
"3.0 (MSIE bug)" );
else
retExt( sessionInfoPtr, CRYPT_ERROR_BADDATA,
"Invalid premaster secret version data 0x%02X 0x%02X, "
"expected 0x03 0x%02X",
handshakeInfo->premasterSecret[ 0 ],
handshakeInfo->premasterSecret[ 1 ],
handshakeInfo->clientOfferedVersion );
}
return( CRYPT_OK );
}
/* Convert a pre-master secret to a master secret, and a master secret to
keying material */
int premasterToMaster( const SESSION_INFO *sessionInfoPtr,
const SSL_HANDSHAKE_INFO *handshakeInfo,
void *masterSecret, const int masterSecretLength )
{
MECHANISM_DERIVE_INFO mechanismInfo;
BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE ];
if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
{
memcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
SSL_NONCE_SIZE );
setMechanismDeriveInfo( &mechanismInfo, masterSecret,
masterSecretLength,
handshakeInfo->premasterSecret,
handshakeInfo->premasterSecretSize,
CRYPT_USE_DEFAULT, nonceBuffer,
SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
&mechanismInfo, MECHANISM_DERIVE_SSL ) );
}
memcpy( nonceBuffer, "master secret", 13 );
memcpy( nonceBuffer + 13, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
SSL_NONCE_SIZE );
setMechanismDeriveInfo( &mechanismInfo, masterSecret, masterSecretLength,
handshakeInfo->premasterSecret,
handshakeInfo->premasterSecretSize,
CRYPT_USE_DEFAULT, nonceBuffer,
13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
&mechanismInfo, MECHANISM_DERIVE_TLS ) );
}
int masterToKeys( const SESSION_INFO *sessionInfoPtr,
const SSL_HANDSHAKE_INFO *handshakeInfo,
const void *masterSecret, const int masterSecretLength,
void *keyBlock, const int keyBlockLength )
{
MECHANISM_DERIVE_INFO mechanismInfo;
BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE ];
if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
{
memcpy( nonceBuffer, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
SSL_NONCE_SIZE );
setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
masterSecret, masterSecretLength, CRYPT_USE_DEFAULT,
nonceBuffer, SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
&mechanismInfo, MECHANISM_DERIVE_SSL ) );
}
memcpy( nonceBuffer, "key expansion", 13 );
memcpy( nonceBuffer + 13, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
SSL_NONCE_SIZE );
setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
masterSecret, masterSecretLength, CRYPT_USE_DEFAULT,
nonceBuffer, 13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
&mechanismInfo, MECHANISM_DERIVE_TLS ) );
}
/* Load the SSL/TLS cryptovariables */
int loadKeys( SESSION_INFO *sessionInfoPtr,
const SSL_HANDSHAKE_INFO *handshakeInfo,
const BOOLEAN isClient, const void *keyBlock )
{
SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
RESOURCE_DATA msgData;
BYTE *keyBlockPtr = ( BYTE * ) keyBlock;
int status;
/* Load the keys and secrets:
( client_write_mac || server_write_mac || \
client_write_key || server_write_key || \
client_write_iv || server_write_iv )
First, we load the MAC keys. For TLS these are proper MAC keys, for
SSL we have to build the proto-HMAC ourselves from a straight hash
context so we store the raw cryptovariables rather than loading them
into a context */
if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
{
memcpy( isClient ? sslInfo->macWriteSecret : sslInfo->macReadSecret,
keyBlockPtr, sessionInfoPtr->authBlocksize );
memcpy( isClient ? sslInfo->macReadSecret : sslInfo->macWriteSecret,
keyBlockPtr + sessionInfoPtr->authBlocksize,
sessionInfoPtr->authBlocksize );
keyBlockPtr = keyBlockPtr + sessionInfoPtr->authBlocksize * 2;
}
else
{
setMessageData( &msgData, keyBlockPtr, sessionInfoPtr->authBlocksize );
status = krnlSendMessage( isClient ? \
sessionInfoPtr->iAuthOutContext : \
sessionInfoPtr->iAuthInContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY );
if( cryptStatusError( status ) )
return( status );
setMessageData( &msgData, keyBlockPtr + sessionInfoPtr->authBlocksize,
sessionInfoPtr->authBlocksize );
status = krnlSendMessage( isClient ? \
sessionInfoPtr->iAuthInContext: \
sessionInfoPtr->iAuthOutContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY );
if( cryptStatusError( status ) )
return( status );
keyBlockPtr = keyBlockPtr + sessionInfoPtr->authBlocksize * 2;
}
/* Then we load the encryption keys */
setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
status = krnlSendMessage( isClient ? \
sessionInfoPtr->iCryptOutContext : \
sessionInfoPtr->iCryptInContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY );
keyBlockPtr += handshakeInfo->cryptKeysize;
if( cryptStatusError( status ) )
return( status );
setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
status = krnlSendMessage( isClient ? \
sessionInfoPtr->iCryptInContext : \
sessionInfoPtr->iCryptOutContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY );
keyBlockPtr += handshakeInfo->cryptKeysize;
if( cryptStatusError( status ) )
return( status );
/* Finally we load the IVs if required. This load is actually redundant
for TLS 1.1, which uses explicit IVs, but it's easier to just do it
anyway */
if( isStreamCipher( sessionInfoPtr->cryptAlgo ) )
return( CRYPT_OK ); /* No IV, we're done */
setMessageData( &msgData, keyBlockPtr,
sessionInfoPtr->cryptBlocksize );
krnlSendMessage( isClient ? sessionInfoPtr->iCryptOutContext : \
sessionInfoPtr->iCryptInContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV );
keyBlockPtr += sessionInfoPtr->cryptBlocksize;
setMessageData( &msgData, keyBlockPtr,
sessionInfoPtr->cryptBlocksize );
return( krnlSendMessage( isClient ? sessionInfoPtr->iCryptInContext : \
sessionInfoPtr->iCryptOutContext,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV ) );
}
/* TLS versions greater than 1.0 prepend an explicit IV to the data, the
following function loads this from the packet data stream */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -