sslcon.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,213 行 · 第 1/5 页

C
2,213
字号
/* * SSL v2 handshake functions, and functions common to SSL2 and SSL3. * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. * * $Id: sslcon.c,v 1.4 2000/09/12 20:15:42 jgmyers%netscape.com Exp $ */#include "cert.h"#include "secitem.h"#include "sechash.h"#include "cryptohi.h"		/* for SGN_ funcs */#include "keyhi.h" 		/* for SECKEY_ high level functions. */#include "softoken.h"		/* for RSA_FormatBlock */#include "ssl.h"#include "sslimpl.h"#include "sslproto.h"#include "ssl3prot.h"#include "sslerr.h"#include "pk11func.h"#include "prinit.h"#include "prtime.h" 	/* for PR_Now() */#define XXXstatic PRBool policyWasSet;/* This ordered list is indexed by (SSL_CK_xx * 3)   *//* Second and third bytes are MSB and LSB of master key length. */static const PRUint8 allCipherSuites[] = {    0,						0,    0,    SSL_CK_RC4_128_WITH_MD5,			0x00, 0x80,    SSL_CK_RC4_128_EXPORT40_WITH_MD5,		0x00, 0x80,    SSL_CK_RC2_128_CBC_WITH_MD5,		0x00, 0x80,    SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,	0x00, 0x80,    SSL_CK_IDEA_128_CBC_WITH_MD5,		0x00, 0x80,    SSL_CK_DES_64_CBC_WITH_MD5,			0x00, 0x40,    SSL_CK_DES_192_EDE3_CBC_WITH_MD5,		0x00, 0xC0,    0,						0,    0};#define ssl2_NUM_SUITES_IMPLEMENTED 6/* This list is sent back to the client when the client-hello message  * contains no overlapping ciphers, so the client can report what ciphers * are supported by the server.  Unlike allCipherSuites (above), this list * is sorted by descending preference, not by cipherSuite number.  */static const PRUint8 implementedCipherSuites[ssl2_NUM_SUITES_IMPLEMENTED * 3] = {    SSL_CK_RC4_128_WITH_MD5,			0x00, 0x80,    SSL_CK_DES_192_EDE3_CBC_WITH_MD5,		0x00, 0xC0,    SSL_CK_RC2_128_CBC_WITH_MD5,		0x00, 0x80,    SSL_CK_DES_64_CBC_WITH_MD5,			0x00, 0x40,    SSL_CK_RC4_128_EXPORT40_WITH_MD5,		0x00, 0x80,    SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,	0x00, 0x80};typedef struct ssl2SpecsStr {    PRUint8           nkm; /* do this many hashes to generate key material. */    PRUint8           nkd; /* size of readKey and writeKey in bytes. */    PRUint8           blockSize;    PRUint8           blockShift;    CK_MECHANISM_TYPE mechanism;    PRUint8           keyLen;	/* cipher symkey size in bytes. */    PRUint8           pubLen;	/* publicly reveal this many bytes of key. */    PRUint8           ivLen;	/* length of IV data at *ca.	*/} ssl2Specs;static const ssl2Specs ssl_Specs[] = {/* NONE                                 */ 				{  0,  0, 0, 0, },/* SSL_CK_RC4_128_WITH_MD5		*/ 				{  2, 16, 1, 0, CKM_RC4,       16,   0, 0, },/* SSL_CK_RC4_128_EXPORT40_WITH_MD5	*/ 				{  2, 16, 1, 0, CKM_RC4,       16,  11, 0, },/* SSL_CK_RC2_128_CBC_WITH_MD5		*/ 				{  2, 16, 8, 3, CKM_RC2_CBC,   16,   0, 8, },/* SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5	*/ 				{  2, 16, 8, 3, CKM_RC2_CBC,   16,  11, 8, },/* SSL_CK_IDEA_128_CBC_WITH_MD5		*/ 				{  0,  0, 0, 0, },/* SSL_CK_DES_64_CBC_WITH_MD5		*/ 				{  1,  8, 8, 3, CKM_DES_CBC,    8,   0, 8, },/* SSL_CK_DES_192_EDE3_CBC_WITH_MD5	*/ 				{  3, 24, 8, 3, CKM_DES3_CBC,  24,   0, 8, },};#define SET_ERROR_CODE	  /* reminder */#define TEST_FOR_FAILURE  /* reminder *//*** Put a string tag in the library so that we can examine an executable** and see what kind of security it supports.*/const char *ssl_version = "SECURITY_VERSION:"			" +us"			" +export"#ifdef TRACE			" +trace"#endif#ifdef DEBUG			" +debug"#endif			;const char * const ssl_cipherName[] = {    "unknown",    "RC4",    "RC4-Export",    "RC2-CBC",    "RC2-CBC-Export",    "IDEA-CBC",    "DES-CBC",    "DES-EDE3-CBC",    "unknown",    "Fortezza",};/* bit-masks, showing which SSLv2 suites are allowed. * lsb corresponds to first cipher suite in allCipherSuites[]. */static PRUint16	allowedByPolicy;          /* all off by default */static PRUint16	maybeAllowedByPolicy;     /* all off by default */static PRUint16	chosenPreference = 0xff;  /* all on  by default *//* bit values for the above two bit masks */#define SSL_CB_RC4_128_WITH_MD5              (1 << SSL_CK_RC4_128_WITH_MD5)#define SSL_CB_RC4_128_EXPORT40_WITH_MD5     (1 << SSL_CK_RC4_128_EXPORT40_WITH_MD5)#define SSL_CB_RC2_128_CBC_WITH_MD5          (1 << SSL_CK_RC2_128_CBC_WITH_MD5)#define SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)#define SSL_CB_IDEA_128_CBC_WITH_MD5         (1 << SSL_CK_IDEA_128_CBC_WITH_MD5)#define SSL_CB_DES_64_CBC_WITH_MD5           (1 << SSL_CK_DES_64_CBC_WITH_MD5)#define SSL_CB_DES_192_EDE3_CBC_WITH_MD5     (1 << SSL_CK_DES_192_EDE3_CBC_WITH_MD5)#define SSL_CB_IMPLEMENTED \   (SSL_CB_RC4_128_WITH_MD5              | \    SSL_CB_RC4_128_EXPORT40_WITH_MD5     | \    SSL_CB_RC2_128_CBC_WITH_MD5          | \    SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 | \    SSL_CB_DES_64_CBC_WITH_MD5           | \    SSL_CB_DES_192_EDE3_CBC_WITH_MD5)/* Construct a socket's list of cipher specs from the global default values. */static SECStatusssl2_ConstructCipherSpecs(sslSocket *ss) {    PRUint8 *	        cs		= NULL;    unsigned int	allowed;    unsigned int	count;    int 		ssl3_count	= 0;    int 		final_count;    int 		i;    SECStatus 		rv;    PORT_Assert( ssl_Have1stHandshakeLock(ss) );    count = 0;    PORT_Assert(ss != 0);    allowed = !ss->enableSSL2 ? 0 :    	(ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED);    while (allowed) {    	if (allowed & 1) 	    ++count;	allowed >>= 1;    }    /* Call ssl3_config_match_init() once here,      * instead of inside ssl3_ConstructV2CipherSpecsHack(),     * because the latter gets called twice below,      * and then again in ssl2_BeginClientHandshake().     */    ssl3_config_match_init(ss);    /* ask SSL3 how many cipher suites it has. */    rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3_count);    if (rv < 0) 	return rv;    count += ssl3_count;    /* Allocate memory to hold cipher specs */    if (count > 0)	cs = (PRUint8*) PORT_Alloc(count * 3);    else	PORT_SetError(SSL_ERROR_SSL_DISABLED);    if (cs == NULL)    	return SECFailure;    if (ss->cipherSpecs != NULL) {	PORT_Free(ss->cipherSpecs);    }    ss->cipherSpecs     = cs;    ss->sizeCipherSpecs = count * 3;    /* fill in cipher specs for SSL2 cipher suites */    allowed = !ss->enableSSL2 ? 0 :    	(ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED);    for (i = 0; i < ssl2_NUM_SUITES_IMPLEMENTED * 3; i += 3) {	const PRUint8 * hs = implementedCipherSuites + i;	int             ok = allowed & (1U << hs[0]);	if (ok) {	    cs[0] = hs[0];	    cs[1] = hs[1];	    cs[2] = hs[2];	    cs += 3;	}    }    /* now have SSL3 add its suites onto the end */    rv = ssl3_ConstructV2CipherSpecsHack(ss, cs, &final_count);        /* adjust for any difference between first pass and second pass */    ss->sizeCipherSpecs -= (ssl3_count - final_count) * 3;    return rv;}/* This function is called immediately after ssl2_ConstructCipherSpecs()** at the beginning of a handshake.  It detects cases where a protocol** (e.g. SSL2 or SSL3) is logically enabled, but all its cipher suites** for that protocol have been disabled.  If such cases, it clears the ** enable bit for the protocol.  If no protocols remain enabled, or** if no cipher suites are found, it sets the error code and returns** SECFailure, otherwise it returns SECSuccess.*/static SECStatusssl2_CheckConfigSanity(sslSocket *ss){    unsigned int      allowed;    int               ssl3CipherCount = 0;    SECStatus         rv;    /* count the SSL2 and SSL3 enabled ciphers.     * if either is zero, clear the socket's enable for that protocol.     */    if (!ss->cipherSpecs)    	goto disabled;    allowed = ss->allowedByPolicy & ss->chosenPreference;    if (! allowed)	ss->enableSSL2 = PR_FALSE;     /* not really enabled if no ciphers */    /* ssl3_config_match_init was called in ssl2_ConstructCipherSpecs(). */    /* Ask how many ssl3 CipherSuites were enabled. */    rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3CipherCount);    if (rv != SECSuccess || ssl3CipherCount <= 0) {	ss->enableSSL3 = PR_FALSE;     /* not really enabled if no ciphers */	ss->enableTLS  = PR_FALSE;    }    if (!ss->enableSSL2 && !ss->enableSSL3 && !ss->enableTLS) {	SSL_DBG(("%d: SSL[%d]: Can't handshake! both v2 and v3 disabled.",		 SSL_GETPID(), ss->fd));disabled:	PORT_SetError(SSL_ERROR_SSL_DISABLED);	return SECFailure;    }    return SECSuccess;}/*  * Since this is a global (not per-socket) setting, we cannot use the * HandshakeLock to protect this.  Probably want a global lock. */SECStatusssl2_SetPolicy(PRInt32 which, PRInt32 policy){    PRUint32  bitMask;    SECStatus rv       = SECSuccess;    which &= 0x000f;    bitMask = 1 << which;    if (!(bitMask & SSL_CB_IMPLEMENTED)) {    	PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);    	return SECFailure;    }    if (policy == SSL_ALLOWED) {	allowedByPolicy 	|= bitMask;	maybeAllowedByPolicy 	|= bitMask;    } else if (policy == SSL_RESTRICTED) {    	allowedByPolicy 	&= ~bitMask;	maybeAllowedByPolicy 	|= bitMask;    } else {    	allowedByPolicy 	&= ~bitMask;    	maybeAllowedByPolicy 	&= ~bitMask;    }    allowedByPolicy 		&= SSL_CB_IMPLEMENTED;    maybeAllowedByPolicy 	&= SSL_CB_IMPLEMENTED;    policyWasSet = PR_TRUE;    return rv;}SECStatusssl2_GetPolicy(PRInt32 which, PRInt32 *oPolicy){    PRUint32     bitMask;    PRInt32      policy;    which &= 0x000f;    bitMask = 1 << which;    /* Caller assures oPolicy is not null. */    if (!(bitMask & SSL_CB_IMPLEMENTED)) {    	PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);	*oPolicy = SSL_NOT_ALLOWED;    	return SECFailure;    }    if (maybeAllowedByPolicy & bitMask) {    	policy = (allowedByPolicy & bitMask) ? SSL_ALLOWED : SSL_RESTRICTED;    } else {	policy = SSL_NOT_ALLOWED;    }    *oPolicy = policy;    return SECSuccess;}/*  * Since this is a global (not per-socket) setting, we cannot use the * HandshakeLock to protect this.  Probably want a global lock. * Called from SSL_CipherPrefSetDefault in sslsock.c * These changes have no effect on any sslSockets already created.  */SECStatusssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled){    PRUint32     bitMask;        which &= 0x000f;    bitMask = 1 << which;    if (!(bitMask & SSL_CB_IMPLEMENTED)) {    	PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);    	return SECFailure;    }    if (enabled)	chosenPreference |= bitMask;    else    	chosenPreference &= ~bitMask;    chosenPreference &= SSL_CB_IMPLEMENTED;    return SECSuccess;}SECStatus ssl2_CipherPrefGetDefault(PRInt32 which, PRBool *enabled){    PRBool       rv       = PR_FALSE;    PRUint32     bitMask;    which &= 0x000f;    bitMask = 1 << which;    if (!(bitMask & SSL_CB_IMPLEMENTED)) {    	PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);	*enabled = PR_FALSE;    	return SECFailure;    }    rv = (PRBool)((chosenPreference & bitMask) != 0);    *enabled = rv;    return SECSuccess;}SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled){    PRUint32     bitMask;        which &= 0x000f;    bitMask = 1 << which;    if (!(bitMask & SSL_CB_IMPLEMENTED)) {    	PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);    	return SECFailure;    }    if (enabled)	ss->chosenPreference |= bitMask;    else    	ss->chosenPreference &= ~bitMask;    ss->chosenPreference &= SSL_CB_IMPLEMENTED;    return SECSuccess;}SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled){    PRBool       rv       = PR_FALSE;    PRUint32     bitMask;    which &= 0x000f;    bitMask = 1 << which;    if (!(bitMask & SSL_CB_IMPLEMENTED)) {    	PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);	*enabled = PR_FALSE;    	return SECFailure;    }    rv = (PRBool)((ss->chosenPreference & bitMask) != 0);    *enabled = rv;    return SECSuccess;}/* copy global default policy into socket. */

⌨️ 快捷键说明

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