📄 ssl_cry.c
字号:
/****************************************************************************
* *
* cryptlib SSL v3/TLS Crypto Routines *
* Copyright Peter Gutmann 1998-2004 *
* *
****************************************************************************/
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "misc_rw.h"
#include "session.h"
#include "ssl.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "../misc/misc_rw.h"
#include "session.h"
#include "ssl.h"
#else
#include "crypt.h"
#include "misc/misc_rw.h"
#include "session/session.h"
#include "session/ssl.h"
#endif /* Compiler-specific includes */
/* Proto-HMAC padding data */
#define PROTOHMAC_PAD1_VALUE 0x36
#define PROTOHMAC_PAD2_VALUE 0x5C
#define PROTOHMAC_PAD1 "\x36\x36\x36\x36\x36\x36\x36\x36" \
"\x36\x36\x36\x36\x36\x36\x36\x36" \
"\x36\x36\x36\x36\x36\x36\x36\x36" \
"\x36\x36\x36\x36\x36\x36\x36\x36" \
"\x36\x36\x36\x36\x36\x36\x36\x36" \
"\x36\x36\x36\x36\x36\x36\x36\x36"
#define PROTOHMAC_PAD2 "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
"\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
"\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
"\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
"\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
"\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
#ifdef USE_SSL
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
/* Initialise and destroy the crypto information in the handshake state
info */
int initHandshakeCryptInfo( SSL_HANDSHAKE_INFO *handshakeInfo )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
/* Clear the handshake info contexts */
handshakeInfo->clientMD5context = \
handshakeInfo->serverMD5context = \
handshakeInfo->clientSHA1context = \
handshakeInfo->serverSHA1context = \
handshakeInfo->dhContext = CRYPT_ERROR;
/* Create the MAC/dual-hash contexts for incoming 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 dual
hash and MACs that once a MAC key becomes available at the end of the
handshake */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
handshakeInfo->clientMD5context = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
handshakeInfo->serverMD5context = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
handshakeInfo->clientSHA1context = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
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 of the
contexts that have been created so far */
destroyHandshakeCryptInfo( handshakeInfo );
return( status );
}
int destroyHandshakeCryptInfo( SSL_HANDSHAKE_INFO *handshakeInfo )
{
/* Destroy any active contexts. We need to do this here (even though
it's also done in the general session code) to provide a clean exit in
case the session activation fails, so that a second activation attempt
doesn't overwrite still-active contexts */
if( handshakeInfo->clientMD5context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->clientMD5context,
IMESSAGE_DECREFCOUNT );
if( handshakeInfo->serverMD5context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->serverMD5context,
IMESSAGE_DECREFCOUNT );
if( handshakeInfo->clientSHA1context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->clientSHA1context,
IMESSAGE_DECREFCOUNT );
if( handshakeInfo->serverSHA1context != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->serverSHA1context,
IMESSAGE_DECREFCOUNT );
if( handshakeInfo->dhContext != CRYPT_ERROR )
krnlSendNotifier( handshakeInfo->dhContext, IMESSAGE_DECREFCOUNT );
return( CRYPT_OK );
}
/* Initialise and destroy the security contexts */
int initSecurityContextsSSL( SESSION_INFO *sessionInfoPtr )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->integrityAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
sessionInfoPtr->iAuthInContext = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->integrityAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
sessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
}
if( cryptStatusOK( status ) )
{
sessionInfoPtr->iCryptInContext = createInfo.cryptHandle;
setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
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 of
the contexts that have been created so far */
destroySecurityContextsSSL( sessionInfoPtr );
return( status );
}
void destroySecurityContextsSSL( SESSION_INFO *sessionInfoPtr )
{
/* Destroy any active contexts */
if( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,
IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iKeyexCryptContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iAuthInContext,
IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iAuthInContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iAuthOutContext,
IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iAuthOutContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iCryptInContext,
IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iCryptInContext = CRYPT_ERROR;
}
if( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )
{
krnlSendNotifier( sessionInfoPtr->iCryptOutContext,
IMESSAGE_DECREFCOUNT );
sessionInfoPtr->iCryptOutContext = CRYPT_ERROR;
}
}
/****************************************************************************
* *
* Keying Functions *
* *
****************************************************************************/
/* Load a DH key into a context, with the fixed value below being used for
the SSL server. The prime is the value 2^1024 - 2^960 - 1 +
2^64 * { [2^894 pi] + 129093 }, from the Oakley spec (RFC 2412, other
locations omit the q value). Unfortunately the choice of q leads to
horribly inefficient operations since it's 860 bits larger than it needs
to be */
static const FAR_BSS BYTE dh1024SSL[] = {
0x00, 0x80, /* p */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x01, /* g */
0x02
};
int initDHcontextSSL( CRYPT_CONTEXT *iCryptContext, const void *keyData,
const int keyDataLength )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
int status;
assert( ( keyData == NULL && keyDataLength == 0 ) || \
isReadPtr( keyData, keyDataLength ) );
*iCryptContext = CRYPT_ERROR;
/* Create the DH context */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DH );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
/* Load the key into the context */
setMessageData( &msgData, "TLS DH key", 10 );
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
if( cryptStatusOK( status ) )
{
/* If we're being given externally-supplied DH key components, load
them, otherwise use the built-in key */
if( keyData != NULL )
{ setMessageData( &msgData, ( void * ) keyData,
keyDataLength ); }
else
{ setMessageData( &msgData, ( void * ) dh1024SSL,
sizeof( dh1024SSL ) ); }
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEY_SSL );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
*iCryptContext = createInfo.cryptHandle;
return( CRYPT_OK );
}
/* Create the master secret from a shared secret value, typically a
password. The expandSharedSecret function uses a slightly different
coding style because it's taken directly from the RFC */
#if 0 /* Old PSK mechanism */
static void expandSharedSecret( BYTE *premaster_secret,
const BYTE *shared_secret,
const int shared_secret_length )
{
int premaster_index;
for( premaster_index = 0; premaster_index < 48; )
{
int i;
premaster_secret[ premaster_index++ ] = shared_secret_length;
for( i = 0; i < shared_secret_length && premaster_index < 48; i++ )
premaster_secret[ premaster_index++ ] = shared_secret[ i ];
}
}
int createSharedMasterSecret( void *masterSecret, int *masterSecretLength,
const SESSION_INFO *sessionInfoPtr )
{
const ATTRIBUTE_LIST *attributeListPtr = \
findSessionAttribute( sessionInfoPtr->attributeList,
CRYPT_SESSINFO_PASSWORD );
MECHANISM_DERIVE_INFO mechanismInfo;
BYTE premasterSecret[ SSL_SECRET_SIZE + 8 ];
int status;
/* Expand the shared secret to create the premaster secret */
if( attributeListPtr->flags & ATTR_FLAG_ENCODEDVALUE )
{
BYTE decodedValue[ CRYPT_MAX_TEXTSIZE ];
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 );
}
expandSharedSecret( premasterSecret, decodedValue,
min( decodedValueLength, SSL_SECRET_SIZE ) );
zeroise( decodedValue, CRYPT_MAX_TEXTSIZE );
}
else
expandSharedSecret( premasterSecret, attributeListPtr->value,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -