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

📄 ssl.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*					cryptlib SSL v3/TLS Session Management					*
*					   Copyright Peter Gutmann 1998-2002					*
*																			*
****************************************************************************/

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

/* Default SSL port */

#define SSL_PORT					443

/* SSL constants */

#define ID_SIZE						1	/* ID byte */
#define UINT16_SIZE					2	/* 16 bits */
#define LENGTH_SIZE					3	/* 24 bits */
#define VERSIONINFO_SIZE			2	/* 0x03, 0x0n */
#define ALERTINFO_SIZE				2	/* level + description */
#define SSL_HEADER_SIZE				5	/* Type, version, length */
#define SSL_NONCE_SIZE				32	/* Size of client/svr nonce */
#define SSL_SECRET_SIZE				48	/* Size of premaster/master secret */
#define MIN_SSL_PACKET_SIZE			4	/* Server hello done */
#define MAX_KEYBLOCK_SIZE			( ( 20 + 24 + 8 ) * 2 )	/* 3DES + SHA-1 */
#define MD5MAC_SIZE					16	/* Size of MD5 proto-HMAC */
#define SHA1MAC_SIZE				20	/* Size of SHA-1 proto-HMAC */
#define TLS_HASHEDMAC_SIZE			12	/* Size of TLS PRF( MD5 + SHA1 ) */
#define APPLICATION_DATA_OFFSET		( 3 * SSL_HEADER_SIZE )
										/* Start of app.data in packet */

/* Default SSL send/receive buffer size */

#define BUFFER_SIZE					( 16384 + 64 )

/* Maximum SSL header size, used to determine how much space we need to
   reserve at the start of the buffer when encoding data packets */

#define MAX_HEADER_SIZE				( SSL_HEADER_SIZE * 3 )

/* SSL message types */

#define SSL_MSG_CHANGE_CIPHER_SPEC	20
#define SSL_MSG_ALERT				21
#define SSL_MSG_HANDSHAKE			22
#define SSL_MSG_APPLICATION_DATA	23

#define SSL_MSG_FIRST				20
#define SSL_MSG_LAST				23

/* Special-case expected-packet-type values which are passed to readPacket()
   to handle situations where more than one return value is valid (the client
   handshake is supposed to be a v3 handshake but is usually a hacked v2 one
   with forwards-compatibility kludges, since this looks nothing like a 
   normal v3 packet we have to treat is specially) */

#define SSL_MSG_SPECIAL_HANDSHAKE	0x80

/* SSL handshake message subtypes */

#define SSL_HAND_CLIENT_HELLO		0x01
#define SSL_HAND_SERVER_HELLO		0x02
#define SSL_HAND_SERVER_CERT		0x0B
#define SSL_HAND_SERVER_HELLODONE	0x0E
#define SSL_HAND_SERVER_CERTREQUEST	0x0D
#define SSL_HAND_CLIENT_CERTVERIFY	0x0F
#define SSL_HAND_CLIENT_KEYEXCHANGE	0x10
#define SSL_HAND_FINISHED			0x14

/* SSL alert levels and types */

#define SSL_ALERTLEVEL_WARNING				1
#define SSL_ALERTLEVEL_FATAL				2

#define SSL_ALERT_CLOSE_NOTIFY				0
#define SSL_ALERT_UNEXPECTED_MESSAGE		10
#define SSL_ALERT_BAD_RECORD_MAC			20
#define TLS_ALERT_DECRYPTION_FAILED			21
#define TLS_ALERT_RECORD_OVERFLOW			22
#define SSL_ALERT_DECOMPRESSION_FAILURE		30
#define SSL_ALERT_HANDSHAKE_FAILURE			40
#define SSL_ALERT_NO_CERTIFICATE			41
#define SSL_ALERT_BAD_CERTIFICATE			42
#define SSL_ALERT_UNSUPPORTED_CERTIFICATE	43
#define SSL_ALERT_CERTIFICATE_REVOKED		44
#define SSL_ALERT_CERTIFICATE_EXPIRED		45
#define SSL_ALERT_CERTIFICATE_UNKNOWN		46
#define SSL_ALERT_ILLEGAL_PARAMETER			47
#define TLS_ALERT_UNKNOWN_CA				48
#define TLS_ALERT_ACCESS_DENIED				49
#define TLS_ALERT_DECODE_ERROR				50
#define TLS_ALERT_DECRYPT_ERROR				51
#define TLS_ALERT_EXPORT_RESTRICTION		60
#define TLS_ALERT_PROTOCOL_VERSION			70
#define TLS_ALERT_INSUFFICIENT_SECURITY		71
#define TLS_ALERT_INTERNAL_ERROR			80
#define TLS_ALERT_USER_CANCELLED			90
#define TLS_ALERT_NO_RENEGOTIATION			100

/* SSL cipher suites */

typedef enum {
	SSL_NULL_WITH_NULL, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA,
	SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_WITH_RC4_128_MD5,
	SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
	SSL_RSA_WITH_IDEA_CBC_SHA, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
	SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA,
	SSL_LAST } SSL_CIPHERSUITE_TYPE;

/* SSL and TLS major and minor version numbers */

#define SSL_MAJOR_VERSION		3
#define SSL_MINOR_VERSION		0
#define TLS_MINOR_VERSION		1

/* SSL sender label values for the finished message MAC */

#define SSL_SENDER_CLIENTLABEL	"CLNT"
#define SSL_SENDER_SERVERLABEL	"SRVR"
#define SSL_SENDERLABEL_SIZE	4

/* Proto-HMAC padding data */

#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" 

/* SSL handshake state information.  This is passed around various 
   subfunctions which handle individual parts of the handshake */

typedef struct {
	/* Client and server proto-HMAC contexts */
	CRYPT_CONTEXT clientMD5context, clientSHA1context;
	CRYPT_CONTEXT serverMD5context, serverSHA1context;

	/* Client and server nonces */
	BYTE clientNonce[ SSL_NONCE_SIZE ], serverNonce[ SSL_NONCE_SIZE ];

	/* Premaster secret */
	BYTE premasterSecret[ SSL_SECRET_SIZE ];

	/* Other info */
	int cryptKeysize;			/* Size of session key */
	} SSL_HANDSHAKE_INFO;

/****************************************************************************
*																			*
*								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 SERVERHELLODONE_TEMPLATE_SIZE		4
#define SERVERCERTREQUEST_TEMPLATE_SIZE		13
#define CHANGECIPHERSPEC_TEMPLATE_SIZE		6
#define FINISHED_TEMPLATE_SIZE				4
#define CLOSEALERT_TEMPLATE_SIZE			7
#define HANDSHAKEFAILALERT_TEMPLATE_SIZE	7
#define NOCERTALERT_TEMPLATE_SIZE			7
#define NOCERT_TEMPLATE_SIZE				7

static const BYTE serverHelloDoneTemplate[] = {
	SSL_HAND_SERVER_HELLODONE,				/* ID */
	0, 0, 0									/* Length */
	};
static const BYTE serverCertRequestTemplate[] = {
	SSL_HAND_SERVER_CERTREQUEST,			/* ID */
	0, 0, 9,								/* Length */
	2,										/* Cert type length */
	1, 2,									/* RSA, DSA */
	0, 4,									/* CA name list length */
	0, 2,									/* CA name length */
	0x30, 0x00								/* CA name */
	};
static const BYTE changeCipherSpecSSLTemplate[] = {
	SSL_MSG_CHANGE_CIPHER_SPEC,				/* ID */
	SSL_MAJOR_VERSION, SSL_MINOR_VERSION,	/* Version */
	0, 1,									/* Length */
	1										/* Data */
	};
static const BYTE changeCipherSpecTLSTemplate[] = {
	SSL_MSG_CHANGE_CIPHER_SPEC,				/* ID */
	SSL_MAJOR_VERSION, TLS_MINOR_VERSION,	/* Version */
	0, 1,									/* Length */
	1										/* Data */
	};
static const BYTE finishedSSLTemplate[] = {
	SSL_HAND_FINISHED,						/* ID */
	0, 0, MD5MAC_SIZE + SHA1MAC_SIZE		/* Length */
	};
static const BYTE finishedTLSTemplate[] = {
	SSL_HAND_FINISHED,						/* ID */
	0, 0, TLS_HASHEDMAC_SIZE				/* Length */
	};
static const BYTE closeAlertSSLTemplate[] = {
	SSL_MSG_ALERT,							/* ID */
	SSL_MAJOR_VERSION, SSL_MINOR_VERSION,	/* Version */
	0, 2,									/* Length */
	SSL_ALERTLEVEL_WARNING, SSL_ALERT_CLOSE_NOTIFY
	};
static const BYTE closeAlertTLSTemplate[] = {
	SSL_MSG_ALERT,							/* ID */
	SSL_MAJOR_VERSION, TLS_MINOR_VERSION,	/* Version */
	0, 2,									/* Length */
	SSL_ALERTLEVEL_WARNING, SSL_ALERT_CLOSE_NOTIFY
	};
static const BYTE handshakeFailAlertSSLTemplate[] = {
	SSL_MSG_ALERT,							/* ID */
	SSL_MAJOR_VERSION, SSL_MINOR_VERSION,	/* Version */
	0, 2,									/* Length */
	SSL_ALERTLEVEL_FATAL, SSL_ALERT_HANDSHAKE_FAILURE
	};
static const BYTE handshakeFailAlertTLSTemplate[] = {
	SSL_MSG_ALERT,							/* ID */
	SSL_MAJOR_VERSION, TLS_MINOR_VERSION,	/* Version */
	0, 2,									/* Length */
	SSL_ALERTLEVEL_FATAL, SSL_ALERT_HANDSHAKE_FAILURE
	};
static const BYTE noCertAlertSSLTemplate[] = {
	SSL_MSG_ALERT,							/* ID */
	SSL_MAJOR_VERSION, SSL_MINOR_VERSION,	/* Version */
	0, 2,									/* Length */
	SSL_ALERTLEVEL_WARNING, SSL_ALERT_NO_CERTIFICATE
	};
static const BYTE noCertTLSTemplate[] = {
	SSL_HAND_SERVER_CERT,					/* ID */
	0, 0, 3,								/* Length */
	0, 0, 0									/* Cert list length */
	};

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

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

	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 = 64;
		sessionInfoPtr->authBlocksize = SHA1MAC_SIZE;
		return( CRYPT_OK );
		}

	return( CRYPT_ERROR_NOTAVAIL );
	}

/* Choose the best cipher suite from a list of suites */

const int chooseCipherSuite( const BYTE *suitePtr, const int noSuites, 
							 const BOOLEAN isV2 )
	{
	int suite = SSL_NULL_WITH_NULL, i;

	for( i = 0; i < noSuites; i++ )
		{
		int ch, currentSuite;

		/* Get the cipher suite info, if it's a v2 suite (the high byte is 
		   nonzero), skip it and continue */
		if( isV2 )
			ch = *suitePtr++;
		currentSuite = mgetBWord( suitePtr );
		if( isV2 && ch )
			continue;

		/* Pick out the best suite available.  The order is 3DES, IDEA, 
		   RC4/128, DES */
		switch( currentSuite )
			{
			case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
				if( algoAvailable( CRYPT_ALGO_3DES ) )
					suite = currentSuite;
				break;

			case SSL_RSA_WITH_IDEA_CBC_SHA:
				if( suite != SSL_RSA_WITH_3DES_EDE_CBC_SHA && \
					algoAvailable( CRYPT_ALGO_IDEA ) )
					suite = currentSuite;
				break;

			case SSL_RSA_WITH_RC4_128_MD5:
			case SSL_RSA_WITH_RC4_128_SHA:
				if( suite != SSL_RSA_WITH_3DES_EDE_CBC_SHA && \
					suite != SSL_RSA_WITH_IDEA_CBC_SHA && \

⌨️ 快捷键说明

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