⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*					cryptlib SSL v3/TLS Session Management					*
*					   Copyright Peter Gutmann 1998-2003					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "session.h"
  #include "ssl.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../session/session.h"
  #include "../session/ssl.h"
#else
  #include "crypt.h"
  #include "session/session.h"
  #include "session/ssl.h"
#endif /* Compiler-specific includes */

#ifdef USE_SSL

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Most of the SSL packets have fixed formats, so we can construct them by
   copying in a constant template and setting up the variable fields.  The
   following templates are for various packet types */

#define CHANGECIPHERSPEC_TEMPLATE_SIZE		6
#define FINISHED_TEMPLATE_SIZE				4
#define CLOSEALERT_TEMPLATE_SIZE			7
#define HANDSHAKEFAILALERT_TEMPLATE_SIZE	7

static const FAR_BSS SSL_MESSAGE_TEMPLATE changeCipherSpecTemplate = {
	/*	byte		type = 20 (change cipherspec)
		byte[2]		version = { 0x03, 0x0n }
		uint16		len = 1
		byte		1 */
	{ SSL_MSG_CHANGE_CIPHER_SPEC, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_SSL, 0, 1, 1 },
	{ SSL_MSG_CHANGE_CIPHER_SPEC, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_TLS, 0, 1, 1 },
	{ SSL_MSG_CHANGE_CIPHER_SPEC, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_TLS11, 0, 1, 1 }
	};
static const FAR_BSS SSL_MESSAGE_TEMPLATE finishedTemplate[] = {
	/*	byte		ID = 0x14
		uint24		len = 16 + 20 (SSL), 12 (TLS) */
	{ SSL_HAND_FINISHED, 0, 0, MD5MAC_SIZE + SHA1MAC_SIZE },
	{ SSL_HAND_FINISHED, 0, 0, TLS_HASHEDMAC_SIZE },
	{ SSL_HAND_FINISHED, 0, 0, TLS_HASHEDMAC_SIZE },
	};
static const FAR_BSS SSL_MESSAGE_TEMPLATE closeAlertTemplate[] = {
	/*	byte		type = 21 (alert)
		byte[2]		version = { 0x03, 0x0n }
		uint16		len = 2
		byte		level = 1 (warning)
		byte		description = 0 (close_notify) */
	{ SSL_MSG_ALERT, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_SSL, 0, 2, 
	  SSL_ALERTLEVEL_WARNING, SSL_ALERT_CLOSE_NOTIFY },
	{ SSL_MSG_ALERT, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_TLS, 0, 2, 
	  SSL_ALERTLEVEL_WARNING, SSL_ALERT_CLOSE_NOTIFY },
	{ SSL_MSG_ALERT, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_TLS11, 0, 2, 
	  SSL_ALERTLEVEL_WARNING, SSL_ALERT_CLOSE_NOTIFY },
	};
static const FAR_BSS SSL_MESSAGE_TEMPLATE handshakeFailAlertTemplate[] = {
	/*	byte		type = 21 (alert)
		byte[2]		version = { 0x03, 0x0n }
		uint16		len = 2
		byte		level = 2 (fatal)
		byte		description = 40 (handshake_failure) */
	{ SSL_MSG_ALERT, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_SSL, 0, 2,
	  SSL_ALERTLEVEL_FATAL, SSL_ALERT_HANDSHAKE_FAILURE },
	{ SSL_MSG_ALERT, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_TLS, 0, 2,
	  SSL_ALERTLEVEL_FATAL, SSL_ALERT_HANDSHAKE_FAILURE },
	{ SSL_MSG_ALERT, SSL_MAJOR_VERSION, SSL_MINOR_VERSION_TLS11, 0, 2,
	  SSL_ALERTLEVEL_FATAL, SSL_ALERT_HANDSHAKE_FAILURE },
	};

/* Set up the information implied by an SSL cipher suite */

int initCiphersuiteInfo( SESSION_INFO *sessionInfoPtr,
						 SSL_HANDSHAKE_INFO *handshakeInfo,
						 const int cipherSuite )
	{
	const CRYPT_ALGO_TYPE integrityAlgoMD5 = \
					( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL ) ? \
					CRYPT_ALGO_MD5 : CRYPT_ALGO_HMAC_MD5;
	const CRYPT_ALGO_TYPE integrityAlgoSHA = \
					( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL ) ? \
					CRYPT_ALGO_SHA : CRYPT_ALGO_HMAC_SHA;

	if( cipherSuite == TLS_RSA_WITH_AES_128_CBC_SHA || \
		cipherSuite == TLS_RSA_WITH_AES_256_CBC_SHA )
		{
		sessionInfoPtr->cryptAlgo = CRYPT_ALGO_AES;
		sessionInfoPtr->integrityAlgo = integrityAlgoSHA;
		sessionInfoPtr->cryptBlocksize = 16;
		handshakeInfo->cryptKeysize = \
				( cipherSuite == TLS_RSA_WITH_AES_128_CBC_SHA ) ? 16 : 32;
		sessionInfoPtr->authBlocksize = SHA1MAC_SIZE;
		return( CRYPT_OK );
		}
	if( cipherSuite == SSL_RSA_WITH_3DES_EDE_CBC_SHA )
		{
		sessionInfoPtr->cryptAlgo = CRYPT_ALGO_3DES;
		sessionInfoPtr->integrityAlgo = integrityAlgoSHA;
		sessionInfoPtr->cryptBlocksize = 8;
		handshakeInfo->cryptKeysize = 24;
		sessionInfoPtr->authBlocksize = SHA1MAC_SIZE;
		return( CRYPT_OK );
		}
	if( cipherSuite == SSL_RSA_WITH_RC4_128_SHA )
		{
		sessionInfoPtr->cryptAlgo = CRYPT_ALGO_RC4;
		sessionInfoPtr->integrityAlgo = integrityAlgoSHA;
		sessionInfoPtr->cryptBlocksize = 1;
		handshakeInfo->cryptKeysize = 16;
		sessionInfoPtr->authBlocksize = SHA1MAC_SIZE;
		return( CRYPT_OK );
		}
	if( cipherSuite == SSL_RSA_WITH_RC4_128_MD5 )
		{
		sessionInfoPtr->cryptAlgo = CRYPT_ALGO_RC4;
		sessionInfoPtr->integrityAlgo = integrityAlgoMD5;
		sessionInfoPtr->cryptBlocksize = 1;
		handshakeInfo->cryptKeysize = 16;
		sessionInfoPtr->authBlocksize = MD5MAC_SIZE;
		return( CRYPT_OK );
		}
	if( cipherSuite == SSL_RSA_WITH_IDEA_CBC_SHA )
		{
		sessionInfoPtr->cryptAlgo = CRYPT_ALGO_IDEA;
		sessionInfoPtr->integrityAlgo = integrityAlgoSHA;
		sessionInfoPtr->cryptBlocksize = 8;
		handshakeInfo->cryptKeysize = 16;
		sessionInfoPtr->authBlocksize = SHA1MAC_SIZE;
		return( CRYPT_OK );
		}
	if( cipherSuite == SSL_RSA_WITH_DES_CBC_SHA )
		{
		sessionInfoPtr->cryptAlgo = CRYPT_ALGO_DES;
		sessionInfoPtr->integrityAlgo = integrityAlgoSHA;
		sessionInfoPtr->cryptBlocksize = 8;
		handshakeInfo->cryptKeysize = 8;
		sessionInfoPtr->authBlocksize = SHA1MAC_SIZE;
		return( CRYPT_OK );
		}

	return( CRYPT_ERROR_NOTAVAIL );
	}

/* Initialise and destroy the handshake state information */

static void destroyHandshakeInfo( 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 );

	zeroise( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );
	}

static int initHandshakeInfo( SSL_HANDSHAKE_INFO *handshakeInfo,
							  const BOOLEAN isServer )
	{
	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;
	if( isServer )
		initSSLserverProcessing( handshakeInfo );
	else
		initSSLclientProcessing( handshakeInfo );

	/* 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 is available */
	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 the
	   contexts that 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,
						  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;
		}
	}

static int initSecurityContexts( 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 the
		   contexts that have been created so far */
		destroySecurityContexts( sessionInfoPtr );
	return( status );
	}

/* 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 */

static void expandSharedSecret( BYTE *premaster_secret, 
								const BYTE *shared_secret, 
							    const int shared_secret_length )
	{
	int premaster_index;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -