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 + -
显示快捷键?