Implement two new SSL socket options: SSL_BYPASS_PKCS11 and SSL_NO_LOCKS.

Reorganize the SSL Socket structure contents to obviate ssl3 pointer.
Move much of the ECC code from ssl3con to new file ssl3ecc.c.  derive.c
implements derivation of the SSL/TLS master secret and the encryption and
MAC keys and IVs without using PKCS11. Bug 305147. r=rrelyea.
Modified Files: ssl/config.mk ssl/manifest.mn ssl/ssl.h ssl/ssl3con.c
    ssl/ssl3gthr.c ssl/sslauth.c ssl/sslcon.c ssl/ssldef.c ssl/sslgathr.c
    ssl/sslimpl.h ssl/sslinfo.c ssl/sslnonce.c ssl/sslsecur.c ssl/sslsnce.c
    ssl/sslsock.c
Added Files: ssl/derive.c ssl/ssl3ecc.c
This commit is contained in:
nelsonb%netscape.com 2005-09-09 03:02:16 +00:00
Родитель ec09744d98
Коммит 4b56704437
17 изменённых файлов: 3317 добавлений и 1994 удалений

Просмотреть файл

@ -66,8 +66,32 @@ EXTRA_SHARED_LIBS += \
$(NULL)
endif # NS_USE_GCC
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
CRYPTODIR=../freebl
ifdef MOZILLA_SECURITY_BUILD
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
CRYPTODIR=../crypto
endif
EXTRA_LIBS += \
$(CRYPTOLIB) \
$(NULL)
else
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
CRYPTODIR=../freebl
ifdef MOZILLA_SECURITY_BUILD
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
CRYPTODIR=../crypto
endif
EXTRA_LIBS += \
$(CRYPTOLIB) \
$(NULL)
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
@ -92,6 +116,7 @@ ifeq ($(OS_TARGET),SunOS)
# The -R '$ORIGIN' linker option instructs this library to search for its
# dependencies in the same directory where it resides.
MKSHLIB += -R '$$ORIGIN'
#EXTRA_SHARED_LIBS += -ldl -lrt -lc -z defs
endif
endif

Просмотреть файл

@ -0,0 +1,481 @@
/*
* Key Derivation that doesn't use PKCS11
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 the Initial Developer are Copyright (C) 1994-2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: derive.c,v 1.2 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "ssl.h" /* prereq to sslimpl.h */
#include "certt.h" /* prereq to sslimpl.h */
#include "keythi.h" /* prereq to sslimpl.h */
#include "sslimpl.h"
#include "blapi.h"
/* make this a macro! */
#ifdef NOT_A_MACRO
static void
buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result)
{
result->type = siBuffer;
result->data = keyBlock;
result->len = keyLen;
}
#else
#define buildSSLKey(keyBlock, keyLen, result) \
{ \
(result)->type = siBuffer; \
(result)->data = keyBlock; \
(result)->len = keyLen; \
}
#endif
/*
* SSL Key generation given pre master secret
*/
#ifndef NUM_MIXERS
#define NUM_MIXERS 9
#endif
static const char * const mixers[NUM_MIXERS] = {
"A",
"BB",
"CCC",
"DDDD",
"EEEEE",
"FFFFFF",
"GGGGGGG",
"HHHHHHHH",
"IIIIIIIII"
};
SECStatus
ssl3_KeyAndMacDeriveBypass(
ssl3CipherSpec * pwSpec,
const unsigned char * cr,
const unsigned char * sr,
PRBool isTLS,
PRBool isExport)
{
const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;
unsigned char * key_block = pwSpec->key_block;
unsigned char * key_block2 = NULL;
unsigned int block_bytes = 0;
unsigned int block_needed = 0;
unsigned int i;
unsigned int keySize; /* actual size of cipher keys */
unsigned int effKeySize; /* effective size of cipher keys */
unsigned int macSize; /* size of MAC secret */
unsigned int IVSize; /* size of IV */
SECStatus rv = SECFailure;
SECStatus status = SECSuccess;
PRBool isFIPS = PR_FALSE;
SECItem srcr;
SECItem crsr;
unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
PRUint64 md5buf[22];
PRUint64 shabuf[40];
#define md5Ctx ((MD5Context *)md5buf)
#define shaCtx ((SHA1Context *)shabuf)
static const SECItem zed = { siBuffer, NULL, 0 };
if (pwSpec->msItem.data == NULL ||
pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return rv;
}
/* figure out how much is needed */
macSize = pwSpec->mac_size;
keySize = cipher_def->key_size;
effKeySize = cipher_def->secret_key_size;
IVSize = cipher_def->iv_size;
if (keySize == 0) {
effKeySize = IVSize = 0; /* only MACing */
}
block_needed = 2 * (macSize + effKeySize + ((!isExport) * IVSize));
/*
* clear out our returned keys so we can recover on failure
*/
pwSpec->client.write_key_item = zed;
pwSpec->client.write_mac_key_item = zed;
pwSpec->server.write_key_item = zed;
pwSpec->server.write_mac_key_item = zed;
/* initialize the server random, client random block */
srcr.type = siBuffer;
srcr.data = srcrdata;
srcr.len = sizeof srcrdata;
PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH);
/* initialize the client random, server random block */
crsr.type = siBuffer;
crsr.data = crsrdata;
crsr.len = sizeof crsrdata;
PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
/*
* generate the key material:
*/
if (isTLS) {
SECItem keyblk;
keyblk.type = siBuffer;
keyblk.data = key_block;
keyblk.len = block_needed;
status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk,
isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
}
block_bytes = keyblk.len;
} else {
/* key_block =
* MD5(master_secret + SHA('A' + master_secret +
* ServerHello.random + ClientHello.random)) +
* MD5(master_secret + SHA('BB' + master_secret +
* ServerHello.random + ClientHello.random)) +
* MD5(master_secret + SHA('CCC' + master_secret +
* ServerHello.random + ClientHello.random)) +
* [...];
*/
int made = 0;
for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) {
unsigned int outLen;
unsigned char sha_out[SHA1_LENGTH];
SHA1_Begin(shaCtx);
SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1);
SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len);
SHA1_Update(shaCtx, srcr.data, srcr.len);
SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
PORT_Assert(outLen == SHA1_LENGTH);
MD5_Begin(md5Ctx);
MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len);
MD5_Update(md5Ctx, sha_out, outLen);
MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
PORT_Assert(outLen == MD5_LENGTH);
made += MD5_LENGTH;
}
block_bytes = made;
}
PORT_Assert(block_bytes >= block_needed);
PORT_Assert(block_bytes <= sizeof pwSpec->key_block);
/*
* Put the key material where it goes.
*/
key_block2 = key_block + block_bytes;
i = 0; /* now shows how much consumed */
/*
* The key_block is partitioned as follows:
* client_write_MAC_secret[CipherSpec.hash_size]
*/
buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item);
i += macSize;
/*
* server_write_MAC_secret[CipherSpec.hash_size]
*/
buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item);
i += macSize;
if (!keySize) {
/* only MACing */
buildSSLKey(NULL, 0, &pwSpec->client.write_key_item);
buildSSLKey(NULL, 0, &pwSpec->server.write_key_item);
buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item);
buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item);
} else if (!isExport) {
/*
** Generate Domestic write keys and IVs.
** client_write_key[CipherSpec.key_material]
*/
buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item);
i += keySize;
/*
** server_write_key[CipherSpec.key_material]
*/
buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item);
i += keySize;
if (IVSize > 0) {
/*
** client_write_IV[CipherSpec.IV_size]
*/
buildSSLKey(&key_block[i], IVSize, &pwSpec->client.write_iv_item);
i += IVSize;
/*
** server_write_IV[CipherSpec.IV_size]
*/
buildSSLKey(&key_block[i], IVSize, &pwSpec->server.write_iv_item);
i += IVSize;
}
PORT_Assert(i <= block_bytes);
} else if (!isTLS) {
/*
** Generate SSL3 Export write keys and IVs.
*/
unsigned int outLen;
/*
** client_write_key[CipherSpec.key_material]
** final_client_write_key = MD5(client_write_key +
** ClientHello.random + ServerHello.random);
*/
MD5_Begin(md5Ctx);
MD5_Update(md5Ctx, &key_block[i], effKeySize);
MD5_Update(md5Ctx, crsr.data, crsr.len);
MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
i += effKeySize;
buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item);
key_block2 += keySize;
/*
** server_write_key[CipherSpec.key_material]
** final_server_write_key = MD5(server_write_key +
** ServerHello.random + ClientHello.random);
*/
MD5_Begin(md5Ctx);
MD5_Update(md5Ctx, &key_block[i], effKeySize);
MD5_Update(md5Ctx, srcr.data, srcr.len);
MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
i += effKeySize;
buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item);
key_block2 += keySize;
PORT_Assert(i <= block_bytes);
if (IVSize) {
/*
** client_write_IV =
** MD5(ClientHello.random + ServerHello.random);
*/
MD5_Begin(md5Ctx);
MD5_Update(md5Ctx, crsr.data, crsr.len);
MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item);
key_block2 += IVSize;
/*
** server_write_IV =
** MD5(ServerHello.random + ClientHello.random);
*/
MD5_Begin(md5Ctx);
MD5_Update(md5Ctx, srcr.data, srcr.len);
MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH);
buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item);
key_block2 += IVSize;
}
PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
} else {
/*
** Generate TLS Export write keys and IVs.
*/
SECItem secret ;
SECItem keyblk ;
secret.type = siBuffer;
keyblk.type = siBuffer;
/*
** client_write_key[CipherSpec.key_material]
** final_client_write_key = PRF(client_write_key,
** "client write key",
** client_random + server_random);
*/
secret.data = &key_block[i];
secret.len = effKeySize;
i += effKeySize;
keyblk.data = key_block2;
keyblk.len = keySize;
status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
}
buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item);
key_block2 += keySize;
/*
** server_write_key[CipherSpec.key_material]
** final_server_write_key = PRF(server_write_key,
** "server write key",
** client_random + server_random);
*/
secret.data = &key_block[i];
secret.len = effKeySize;
i += effKeySize;
keyblk.data = key_block2;
keyblk.len = keySize;
status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
}
buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item);
key_block2 += keySize;
/*
** iv_block = PRF("", "IV block", client_random + server_random);
** client_write_IV[SecurityParameters.IV_size]
** server_write_IV[SecurityParameters.IV_size]
*/
if (IVSize) {
secret.data = NULL;
secret.len = 0;
keyblk.data = key_block2;
keyblk.len = 2 * IVSize;
status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
}
buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item);
buildSSLKey(key_block2 + IVSize, IVSize, &pwSpec->server.write_iv_item);
key_block2 += 2 * IVSize;
}
PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block);
}
rv = SECSuccess;
key_and_mac_derive_fail:
MD5_DestroyContext(md5Ctx, PR_FALSE);
SHA1_DestroyContext(shaCtx, PR_FALSE);
if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
}
return rv;
}
/* derive the Master Secret from the PMS */
/* Presently, this is only done wtih RSA PMS, os isRSA is always true. */
SECStatus
ssl3_MasterKeyDeriveBypass(
ssl3CipherSpec * pwSpec,
const unsigned char * cr,
const unsigned char * sr,
const SECItem * pms,
PRBool isTLS,
PRBool isRSA)
{
unsigned char * key_block = pwSpec->key_block;
SECStatus rv = SECSuccess;
PRBool isFIPS = PR_FALSE;
SECItem crsr;
unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
PRUint64 md5buf[22];
PRUint64 shabuf[40];
#define md5Ctx ((MD5Context *)md5buf)
#define shaCtx ((SHA1Context *)shabuf)
/* first do the consistancy checks */
if (isRSA) {
PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH);
if (pms->len != SSL3_RSA_PMS_LENGTH) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* test PMS version for rollback here? or in caller? */
}
/* initialize the client random, server random block */
crsr.type = siBuffer;
crsr.data = crsrdata;
crsr.len = sizeof crsrdata;
PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH);
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH);
/* finally do the key gen */
if (isTLS) {
SECItem master = { siBuffer, NULL, 0 };
master.data = key_block;
master.len = SSL3_MASTER_SECRET_LENGTH;
rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS);
if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
}
} else {
int i;
int made = 0;
for (i = 0; i < 3; i++) {
unsigned int outLen;
unsigned char sha_out[SHA1_LENGTH];
SHA1_Begin(shaCtx);
SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1);
SHA1_Update(shaCtx, pms->data, pms->len);
SHA1_Update(shaCtx, crsr.data, crsr.len);
SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH);
PORT_Assert(outLen == SHA1_LENGTH);
MD5_Begin(md5Ctx);
MD5_Update(md5Ctx, pms->data, pms->len);
MD5_Update(md5Ctx, sha_out, outLen);
MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH);
PORT_Assert(outLen == MD5_LENGTH);
made += outLen;
}
}
/* store the results */
PORT_Memcpy(pwSpec->raw_master_secret, key_block,
SSL3_MASTER_SECRET_LENGTH);
pwSpec->msItem.data = pwSpec->raw_master_secret;
pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH;
return rv;
}

Просмотреть файл

@ -55,6 +55,7 @@ MODULE = nss
MAPFILE = $(OBJDIR)/ssl.def
CSRCS = \
derive.c \
emulate.c \
prelib.c \
ssl3con.c \
@ -77,14 +78,13 @@ CSRCS = \
cmpcert.c \
nsskea.c \
sslinfo.c \
ssl3ecc.c \
$(NULL)
REQUIRES = dbm
ifdef NSS_ENABLE_ECC
DEFINES += -DNSS_ENABLE_ECC
endif
LIBRARY_NAME = ssl
LIBRARY_VERSION = 3

Просмотреть файл

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: ssl.h,v 1.22 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: ssl.h,v 1.23 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#ifndef __ssl_h_
#define __ssl_h_
@ -110,6 +110,8 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
/* if step-down keys are needed. */
/* default: off, generate */
/* step-down keys if needed. */
#define SSL_BYPASS_PKCS11 16 /* use PKCS#11 for pub key only */
#define SSL_NO_LOCKS 17 /* Don't use locks for protection */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,675 @@
/*
* SSL3 Protocol
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* ECC code moved here from ssl3con.c */
/* $Id: ssl3ecc.c,v 1.2 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#ifdef NSS_ENABLE_ECC
#include "nssrenam.h"
#include "cert.h"
#include "ssl.h"
#include "cryptohi.h" /* for DSAU_ stuff */
#include "keyhi.h"
#include "secder.h"
#include "secitem.h"
#include "sslimpl.h"
#include "sslproto.h"
#include "sslerr.h"
#include "prtime.h"
#include "prinrval.h"
#include "prerror.h"
#include "pratom.h"
#include "prthread.h"
#include "pk11func.h"
#include "secmod.h"
#include "nsslocks.h"
#include "ec.h"
#include "blapi.h"
#include <stdio.h>
/*
line 297: implicit function declaration: ssl3_InitPendingCipherSpec
line 305: implicit function declaration: ssl3_AppendHandshakeHeader
line 311: implicit function declaration: ssl3_AppendHandshakeVariable
line 356: implicit function declaration: ssl3_ConsumeHandshakeVariable
*/
#ifndef PK11_SETATTRS
#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
(x)->pValue=(v); (x)->ulValueLen = (l);
#endif
/* Types and names of elliptic curves used in TLS */
typedef enum { ec_type_explicitPrime = 1,
ec_type_explicitChar2Curve,
ec_type_named
} ECType;
typedef enum { ec_noName = 0,
ec_sect163k1, ec_sect163r1, ec_sect163r2,
ec_sect193r1, ec_sect193r2, ec_sect233k1,
ec_sect233r1, ec_sect239k1, ec_sect283k1,
ec_sect283r1, ec_sect409k1, ec_sect409r1,
ec_sect571k1, ec_sect571r1, ec_secp160k1,
ec_secp160r1, ec_secp160r2, ec_secp192k1,
ec_secp192r1, ec_secp224k1, ec_secp224r1,
ec_secp256k1, ec_secp256r1, ec_secp384r1,
ec_secp521r1,
ec_pastLastName
} ECName;
#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
/* Table containing OID tags for elliptic curves named in the
* ECC-TLS IETF draft.
*/
static const SECOidTag ecName2OIDTag[] = {
0,
SEC_OID_SECG_EC_SECT163K1, /* 1 */
SEC_OID_SECG_EC_SECT163R1, /* 2 */
SEC_OID_SECG_EC_SECT163R2, /* 3 */
SEC_OID_SECG_EC_SECT193R1, /* 4 */
SEC_OID_SECG_EC_SECT193R2, /* 5 */
SEC_OID_SECG_EC_SECT233K1, /* 6 */
SEC_OID_SECG_EC_SECT233R1, /* 7 */
SEC_OID_SECG_EC_SECT239K1, /* 8 */
SEC_OID_SECG_EC_SECT283K1, /* 9 */
SEC_OID_SECG_EC_SECT283R1, /* 10 */
SEC_OID_SECG_EC_SECT409K1, /* 11 */
SEC_OID_SECG_EC_SECT409R1, /* 12 */
SEC_OID_SECG_EC_SECT571K1, /* 13 */
SEC_OID_SECG_EC_SECT571R1, /* 14 */
SEC_OID_SECG_EC_SECP160K1, /* 15 */
SEC_OID_SECG_EC_SECP160R1, /* 16 */
SEC_OID_SECG_EC_SECP160R2, /* 17 */
SEC_OID_SECG_EC_SECP192K1, /* 18 */
SEC_OID_SECG_EC_SECP192R1, /* 19 */
SEC_OID_SECG_EC_SECP224K1, /* 20 */
SEC_OID_SECG_EC_SECP224R1, /* 21 */
SEC_OID_SECG_EC_SECP256K1, /* 22 */
SEC_OID_SECG_EC_SECP256R1, /* 23 */
SEC_OID_SECG_EC_SECP384R1, /* 24 */
SEC_OID_SECG_EC_SECP521R1, /* 25 */
};
static SECStatus
ecName2params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
{
SECOidData *oidData = NULL;
if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
/*
* params->data needs to contain the ASN encoding of an object ID (OID)
* representing the named curve. The actual OID is in
* oidData->oid.data so we simply prepend 0x06 and OID length
*/
params->data[0] = SEC_ASN1_OBJECT_ID;
params->data[1] = oidData->oid.len;
memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
return SECSuccess;
}
static ECName
params2ecName(SECKEYECParams * params)
{
SECItem oid = { siBuffer, NULL, 0};
SECOidData *oidData = NULL;
ECName i;
/*
* params->data needs to contain the ASN encoding of an object ID (OID)
* representing a named curve. Here, we strip away everything
* before the actual OID and use the OID to look up a named curve.
*/
if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName;
oid.len = params->len - 2;
oid.data = params->data + 2;
if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
for (i = ec_noName + 1; i < ec_pastLastName; i++) {
if (ecName2OIDTag[i] == oidData->offset)
return i;
}
return ec_noName;
}
/* Caller must set hiLevel error code. */
static SECStatus
ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint,
SSL3Random *client_rand, SSL3Random *server_rand,
SSL3Hashes *hashes, PRBool bypassPKCS11)
{
PRUint8 * hashBuf;
PRUint8 * pBuf;
SECStatus rv = SECSuccess;
unsigned int bufLen;
/*
* XXX For now, we only support named curves (the appropriate
* checks are made before this method is called) so ec_params
* takes up only two bytes. ECPoint needs to fit in 256 bytes
* (because the spec says the length must fit in one byte)
*/
PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
if (bufLen <= sizeof buf) {
hashBuf = buf;
} else {
hashBuf = PORT_Alloc(bufLen);
if (!hashBuf) {
return SECFailure;
}
}
memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
pBuf = hashBuf + SSL3_RANDOM_LENGTH;
memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
pBuf += SSL3_RANDOM_LENGTH;
memcpy(pBuf, ec_params.data, ec_params.len);
pBuf += ec_params.len;
pBuf[0] = (PRUint8)(server_ecpoint.len);
pBuf += 1;
memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
pBuf += server_ecpoint.len;
PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));
done:
if (hashBuf != buf && hashBuf != NULL)
PORT_Free(hashBuf);
return rv;
}
/* Called from ssl3_SendClientKeyExchange(). */
SECStatus
ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
{
PK11SymKey * pms = NULL;
SECStatus rv = SECFailure;
PRBool isTLS;
CK_MECHANISM_TYPE target;
SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */
SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */
CK_EC_KDF_TYPE kdf;
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
/* Generate ephemeral EC keypair */
privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams,
&pubKey, NULL);
if (!privKey || !pubKey) {
ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
rv = SECFailure;
goto loser;
}
PRINT_BUF(50, (ss, "ECDH public value:",
pubKey->u.ec.publicValue.data,
pubKey->u.ec.publicValue.len));
if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
/* If field size is not more than 24 octets, then use SHA-1 hash of result;
* otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt).
*/
if ((pubKey->u.ec.publicValue.len - 1) / 2 <= 24) {
kdf = CKD_SHA1_KDF;
} else {
kdf = CKD_NULL;
}
/* Determine the PMS */
pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
kdf, NULL, NULL);
if (pms == NULL) {
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
goto loser;
}
SECKEY_DestroyPrivateKey(privKey);
privKey = NULL;
rv = ssl3_InitPendingCipherSpec(ss, pms);
PK11_FreeSymKey(pms); pms = NULL;
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
goto loser;
}
rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
pubKey->u.ec.publicValue.len + 1);
if (rv != SECSuccess) {
goto loser; /* err set by ssl3_AppendHandshake* */
}
rv = ssl3_AppendHandshakeVariable(ss,
pubKey->u.ec.publicValue.data,
pubKey->u.ec.publicValue.len, 1);
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
if (rv != SECSuccess) {
goto loser; /* err set by ssl3_AppendHandshake* */
}
rv = SECSuccess;
loser:
if(pms) PK11_FreeSymKey(pms);
if(privKey) SECKEY_DestroyPrivateKey(privKey);
if(pubKey) SECKEY_DestroyPublicKey(pubKey);
return rv;
}
/*
** Called from ssl3_HandleClientKeyExchange()
*/
SECStatus
ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
PRUint32 length,
SECKEYPublicKey *srvrPubKey,
SECKEYPrivateKey *srvrPrivKey)
{
PK11SymKey * pms;
SECStatus rv;
SECKEYPublicKey clntPubKey;
CK_MECHANISM_TYPE target;
PRBool isTLS;
CK_EC_KDF_TYPE kdf;
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
clntPubKey.keyType = ecKey;
clntPubKey.u.ec.DEREncodedParams.len =
srvrPubKey->u.ec.DEREncodedParams.len;
clntPubKey.u.ec.DEREncodedParams.data =
srvrPubKey->u.ec.DEREncodedParams.data;
rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
1, &b, &length);
if (rv != SECSuccess) {
SEND_ALERT
return SECFailure; /* XXX Who sets the error code?? */
}
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
/* If field size is not more than 24 octets, then use SHA-1 hash of result;
* otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt).
*/
if (srvrPubKey->u.ec.size <= 24 * 8) {
kdf = CKD_SHA1_KDF;
} else {
kdf = CKD_NULL;
}
/* Determine the PMS */
pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
kdf, NULL, NULL);
PORT_Free(clntPubKey.u.ec.publicValue.data);
if (pms == NULL) {
/* last gasp. */
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
return SECFailure;
}
rv = ssl3_InitPendingCipherSpec(ss, pms);
PK11_FreeSymKey(pms);
if (rv != SECSuccess) {
SEND_ALERT
return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
}
return SECSuccess;
}
/*
* Creates the ephemeral public and private ECDH keys used by
* server in ECDHE_RSA and ECDHE_ECDSA handshakes.
* XXX For now, the elliptic curve is hardcoded to NIST P-224.
* We need an API to specify the curve. This won't be a real
* issue until we further develop server-side support for ECC
* cipher suites.
*/
SECStatus
ssl3_CreateECDHEphemeralKeys(sslSocket *ss)
{
SECStatus rv = SECSuccess;
SECKEYPrivateKey * privKey;
SECKEYPublicKey * pubKey;
SECKEYECParams ecParams = { siBuffer, NULL, 0 };
if (ss->ephemeralECDHKeyPair)
ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
ss->ephemeralECDHKeyPair = NULL;
if (ecName2params(NULL, ec_secp224r1, &ecParams) == SECFailure)
return SECFailure;
privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
if (!privKey || !pubKey ||
!(ss->ephemeralECDHKeyPair = ssl3_NewKeyPair(privKey, pubKey))) {
ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
rv = SECFailure;
}
PORT_Free(ecParams.data);
return rv;
}
SECStatus
ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
{
PRArenaPool * arena = NULL;
SECKEYPublicKey *peerKey = NULL;
PRBool isTLS;
SECStatus rv;
int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
SSL3AlertDescription desc = illegal_parameter;
SSL3Hashes hashes;
SECItem signature = {siBuffer, NULL, 0};
SECItem ec_params = {siBuffer, NULL, 0};
SECItem ec_point = {siBuffer, NULL, 0};
unsigned char paramBuf[2];
isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
/* XXX This works only for named curves, revisit this when
* we support generic curves.
*/
ec_params.len = 2;
ec_params.data = paramBuf;
rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len,
&b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
/* Fail if the curve is not a named curve */
if ((ec_params.data[0] != ec_type_named) ||
!supportedCurve(ec_params.data[1])) {
errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
desc = handshake_failure;
goto alert_loser;
}
rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
/* Fail if the ec point uses compressed representation */
if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
desc = handshake_failure;
goto alert_loser;
}
rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed. */
}
if (length != 0) {
if (isTLS)
desc = decode_error;
goto alert_loser; /* malformed. */
}
PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
ec_params.len));
PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
/* failures after this point are not malformed handshakes. */
/* TLS: send decrypt_error if signature failed. */
desc = isTLS ? decrypt_error : handshake_failure;
/*
* check to make sure the hash is signed by right guy
*/
rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point,
&ss->ssl3.hs.client_random,
&ss->ssl3.hs.server_random,
&hashes, ss->opt.bypassPKCS11);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto alert_loser;
}
rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
isTLS, ss->pkcs11PinArg);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto alert_loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
goto no_memory;
}
ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
if (peerKey == NULL) {
goto no_memory;
}
peerKey->arena = arena;
peerKey->keyType = ecKey;
/* set up EC parameters in peerKey */
if (ecName2params(arena, ec_params.data[1],
&peerKey->u.ec.DEREncodedParams) != SECSuccess) {
/* we should never get here since we already
* checked that we are dealing with a supported curve
*/
errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
goto alert_loser;
}
/* copy publicValue in peerKey */
if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point))
{
PORT_FreeArena(arena, PR_FALSE);
goto no_memory;
}
peerKey->pkcs11Slot = NULL;
peerKey->pkcs11ID = CK_INVALID_HANDLE;
ss->sec.peerKey = peerKey;
ss->ssl3.hs.ws = wait_cert_request;
return SECSuccess;
alert_loser:
(void)SSL3_SendAlert(ss, alert_fatal, desc);
loser:
PORT_SetError( errCode );
return SECFailure;
no_memory: /* no-memory error has already been set. */
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
return SECFailure;
}
SECStatus
ssl3_SendECDHServerKeyExchange(sslSocket *ss)
{
const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def;
SECStatus rv = SECFailure;
int length;
PRBool isTLS;
SECItem signed_hash = {siBuffer, NULL, 0};
SSL3Hashes hashes;
SECKEYPublicKey * ecdhePub;
SECItem ec_params = {siBuffer, NULL, 0};
ECName curve;
SSL3KEAType certIndex;
/* Generate ephemeral ECDH key pair and send the public key */
rv = ssl3_CreateECDHEphemeralKeys(ss);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
}
ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
PORT_Assert(ecdhePub != NULL);
if (!ecdhePub) {
PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
return SECFailure;
}
ec_params.len = 2;
ec_params.data = (unsigned char*)PORT_Alloc(ec_params.len);
curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams);
if (curve != ec_noName) {
ec_params.data[0] = ec_type_named;
ec_params.data[1] = curve;
} else {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
goto loser;
}
rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue,
&ss->ssl3.hs.client_random,
&ss->ssl3.hs.server_random,
&hashes, ss->opt.bypassPKCS11);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto loser;
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
/* XXX SSLKEAType isn't really a good choice for
* indexing certificates but that's all we have
* for now.
*/
if (kea_def->kea == kea_ecdhe_rsa)
certIndex = kt_rsa;
else /* kea_def->kea == kea_ecdhe_ecdsa */
certIndex = kt_ecdh;
rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
&signed_hash, isTLS);
if (rv != SECSuccess) {
goto loser; /* ssl3_SignHashes has set err. */
}
if (signed_hash.data == NULL) {
/* how can this happen and rv == SECSuccess ?? */
PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto loser;
}
length = ec_params.len +
1 + ecdhePub->u.ec.publicValue.len +
2 + signed_hash.len;
rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
ecdhePub->u.ec.publicValue.len, 1);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
signed_hash.len, 2);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
}
PORT_Free(ec_params.data);
PORT_Free(signed_hash.data);
return SECSuccess;
loser:
if (ec_params.data != NULL)
PORT_Free(ec_params.data);
if (signed_hash.data != NULL)
PORT_Free(signed_hash.data);
return SECFailure;
}
#endif /* NSS_ENABLE_ECC */

Просмотреть файл

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: ssl3gthr.c,v 1.6 2004/04/27 23:04:39 gerv%gerv.net Exp $ */
/* $Id: ssl3gthr.c,v 1.7 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "cert.h"
#include "ssl.h"
@ -72,7 +72,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
int err;
int rv = 1;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
if (gs->state == GS_INIT) {
gs->state = GS_HEADER;
gs->remainder = 5;
@ -189,7 +189,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
SSL3Ciphertext cText;
int rv;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
do {
/* bring in the next sslv3 record. */
rv = ssl3_GatherData(ss, &ss->gs, flags);
@ -207,7 +207,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
if (rv < 0) {
return ss->recvdCloseNotify ? 0 : rv;
}
} while (ss->ssl3->hs.ws != idle_handshake && ss->gs.buf.len == 0);
} while (ss->ssl3.hs.ws != idle_handshake && ss->gs.buf.len == 0);
ss->gs.readOffset = 0;
ss->gs.writeOffset = ss->gs.buf.len;
@ -230,7 +230,7 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
{
int rv;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
do {
rv = ssl3_GatherCompleteHandshake(ss, flags);
} while (rv > 0 && ss->gs.buf.len == 0);

Просмотреть файл

@ -33,7 +33,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslauth.c,v 1.14 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: sslauth.c,v 1.15 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "cert.h"
#include "secitem.h"
#include "ssl.h"
@ -53,7 +53,7 @@ SSL_PeerCertificate(PRFileDesc *fd)
SSL_GETPID(), fd));
return 0;
}
if (ss->useSecurity && ss->sec.peerCert) {
if (ss->opt.useSecurity && ss->sec.peerCert) {
return CERT_DupCertificate(ss->sec.peerCert);
}
return 0;
@ -71,7 +71,7 @@ SSL_LocalCertificate(PRFileDesc *fd)
SSL_GETPID(), fd));
return NULL;
}
if (ss->useSecurity) {
if (ss->opt.useSecurity) {
if (ss->sec.localCert) {
return CERT_DupCertificate(ss->sec.localCert);
}
@ -109,7 +109,7 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
*op = SSL_SECURITY_STATUS_OFF;
}
if (ss->useSecurity && ss->firstHsDone) {
if (ss->opt.useSecurity && ss->firstHsDone) {
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
cipherName = ssl_cipherName[ss->sec.cipherType];

Просмотреть файл

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslcon.c,v 1.27 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: sslcon.c,v 1.28 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "nssrenam.h"
#include "cert.h"
@ -186,11 +186,11 @@ ssl2_ConstructCipherSpecs(sslSocket *ss)
int i;
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
count = 0;
PORT_Assert(ss != 0);
allowed = !ss->enableSSL2 ? 0 :
allowed = !ss->opt.enableSSL2 ? 0 :
(ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED);
while (allowed) {
if (allowed & 1)
@ -226,7 +226,7 @@ ssl2_ConstructCipherSpecs(sslSocket *ss)
ss->sizeCipherSpecs = count * 3;
/* fill in cipher specs for SSL2 cipher suites */
allowed = !ss->enableSSL2 ? 0 :
allowed = !ss->opt.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;
@ -271,17 +271,17 @@ ssl2_CheckConfigSanity(sslSocket *ss)
allowed = ss->allowedByPolicy & ss->chosenPreference;
if (! allowed)
ss->enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */
ss->opt.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;
ss->opt.enableSSL3 = PR_FALSE; /* not really enabled if no ciphers */
ss->opt.enableTLS = PR_FALSE;
}
if (!ss->enableSSL2 && !ss->enableSSL3 && !ss->enableTLS) {
if (!ss->opt.enableSSL2 && !ss->opt.enableSSL3 && !ss->opt.enableTLS) {
SSL_DBG(("%d: SSL[%d]: Can't handshake! both v2 and v3 disabled.",
SSL_GETPID(), ss->fd));
disabled:
@ -495,7 +495,7 @@ ssl2_GetSendBuffer(sslSocket *ss, unsigned int len)
{
SECStatus rv = SECSuccess;
PORT_Assert(ssl_HaveXmitBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
if (len < 128) {
len = 128;
@ -530,7 +530,7 @@ ssl2_SendErrorMessage(sslSocket *ss, int error)
int rv;
PRUint8 msg[SSL_HL_ERROR_HBYTES];
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
msg[0] = SSL_MT_ERROR;
msg[1] = MSB(error);
@ -559,7 +559,7 @@ ssl2_SendClientFinishedMessage(sslSocket *ss)
int sent;
PRUint8 msg[1 + SSL_CONNECTIONID_BYTES];
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetXmitBufLock(ss); /***************************************/
@ -595,7 +595,7 @@ ssl2_SendServerVerifyMessage(sslSocket *ss)
int sent;
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetXmitBufLock(ss); /***************************************/
@ -630,7 +630,7 @@ ssl2_SendServerFinishedMessage(sslSocket *ss)
int sendLen, sent;
SECStatus rv = SECSuccess;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetXmitBufLock(ss); /***************************************/
@ -660,7 +660,7 @@ ssl2_SendServerFinishedMessage(sslSocket *ss)
/* If send failed, it is now a bogus session-id */
(*ss->sec.uncache)(sid);
rv = (SECStatus)sent;
} else if (!ss->noCache) {
} else if (!ss->opt.noCache) {
/* Put the sid in session-id cache, (may already be there) */
(*ss->sec.cache)(sid);
rv = SECSuccess;
@ -689,7 +689,7 @@ ssl2_SendSessionKeyMessage(sslSocket *ss, int cipher, int keySize,
int sent;
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetXmitBufLock(ss); /***************************************/
@ -735,7 +735,7 @@ ssl2_SendCertificateRequestMessage(sslSocket *ss)
int sendLen;
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetXmitBufLock(ss); /***************************************/
@ -775,7 +775,7 @@ ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert,
PRUint8 *msg;
int rv, sendLen;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetXmitBufLock(ss); /***************************************/
@ -887,7 +887,7 @@ ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
int amount;
int count = 0;
PORT_Assert( ssl_HaveXmitBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes in the clear",
SSL_GETPID(), ss->fd, len));
@ -962,7 +962,7 @@ ssl2_SendStream(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
int nout;
int buflen;
PORT_Assert( ssl_HaveXmitBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using stream cipher",
SSL_GETPID(), ss->fd, len));
@ -1067,7 +1067,7 @@ ssl2_SendBlock(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags)
int nout; /* ciphertext size after header. */
int buflen; /* size of generated record. */
PORT_Assert( ssl_HaveXmitBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using block cipher",
SSL_GETPID(), ss->fd, len));
@ -1251,7 +1251,7 @@ ssl_GatherRecord1stHandshake(sslSocket *ss)
{
int rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetRecvBufLock(ss);
@ -1369,7 +1369,7 @@ ssl2_ProduceKeys(sslSocket * ss,
readKey->data = 0;
writeKey->data = 0;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
rv = SECSuccess;
cx = PK11_CreateDigestContext(SEC_OID_MD5);
@ -1441,7 +1441,7 @@ ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient)
readKey.data = 0;
writeKey.data = 0;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
if((ss->sec.ci.sid == 0))
goto sec_loser; /* don't crash if asserts are off */
@ -1591,9 +1591,9 @@ ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits,
PRUint8 mkbuf[SSL_MAX_MASTER_KEY_BYTES];
sslServerCerts * sc = ss->serverCerts + kt_rsa;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert((sc->serverKey != 0));
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
PORT_Assert((sc->SERVERKEY != 0));
PORT_Assert((ss->sec.ci.sid != 0));
sid = ss->sec.ci.sid;
@ -1651,11 +1651,11 @@ ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits,
** NOTE: PK11_PubDecryptRaw will barf on a non-RSA key. This is
** desired behavior here.
*/
rv = PK11_PubDecryptRaw(sc->serverKey, kbuf, &el1, ekLen, ek, ekLen);
rv = PK11_PubDecryptRaw(sc->SERVERKEY, kbuf, &el1, ekLen, ek, ekLen);
if (rv != SECSuccess)
goto hide_loser;
modulusLen = PK11_GetPrivateModulusLen(sc->serverKey);
modulusLen = PK11_GetPrivateModulusLen(sc->SERVERKEY);
if (modulusLen == -1) {
/* If the key was really bad, then PK11_pubDecryptRaw
* would have failed, therefore the we must assume that the card
@ -1679,7 +1679,7 @@ ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits,
}
/* Make sure we're not subject to a version rollback attack. */
if (ss->enableSSL3 || ss->enableTLS) {
if (ss->opt.enableSSL3 || ss->opt.enableTLS) {
PRUint8 threes[8] = { 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03 };
@ -1763,8 +1763,8 @@ ssl2_QualifyCypherSpecs(sslSocket *ss,
int hc;
PRUint8 qualifiedSpecs[ssl2_NUM_SUITES_IMPLEMENTED * 3];
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
if (!ss->cipherSpecs) {
ssl2_ConstructCipherSpecs(ss);
@ -1824,8 +1824,8 @@ ssl2_ChooseSessionCypher(sslSocket *ss,
int realKeySize;
PRUint8 * ohs = hs;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
if (!ss->cipherSpecs) {
ssl2_ConstructCipherSpecs(ss);
@ -2044,7 +2044,7 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
PRUint8 keyData[SSL_MAX_MASTER_KEY_BYTES];
PRUint8 iv [8];
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
eblock = NULL;
@ -2131,7 +2131,7 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen)
/* Set up the padding for version 2 rollback detection. */
/* XXX We should really use defines here */
if (ss->enableSSL3 || ss->enableTLS) {
if (ss->opt.enableSSL3 || ss->opt.enableTLS) {
PORT_Assert((modulusLen - rek.len) > 12);
PORT_Memset(eblock + modulusLen - rek.len - 8 - 1, 0x03, 8);
}
@ -2185,7 +2185,7 @@ ssl2_ClientRegSessionID(sslSocket *ss, PRUint8 *s)
sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
}
if (!ss->noCache)
if (!ss->opt.noCache)
(*ss->sec.cache)(sid);
}
@ -2195,7 +2195,7 @@ ssl2_TriggerNextMessage(sslSocket *ss)
{
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
if ((ss->sec.ci.requiredElements & CIS_HAVE_CERTIFICATE) &&
!(ss->sec.ci.sentElements & CIS_HAVE_CERTIFICATE)) {
@ -2223,7 +2223,7 @@ ssl2_TryToFinish(sslSocket *ss)
SECStatus rv;
char e, ef;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
e = ss->sec.ci.elements;
ef = e | CIS_HAVE_FINISHED;
@ -2261,7 +2261,7 @@ ssl2_SignResponse(sslSocket *ss,
unsigned int len;
SECStatus rv = SECFailure;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
challenge = ss->sec.ci.serverChallenge;
len = ss->sec.ci.serverChallengeLen;
@ -2424,8 +2424,8 @@ ssl2_HandleClientCertificate(sslSocket * ss,
SECItem certItem;
SECItem rep;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
/* Extract the certificate */
certItem.data = cd;
@ -2512,7 +2512,7 @@ ssl2_HandleMessage(sslSocket *ss)
int rv;
int rv2;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetRecvBufLock(ss);
@ -2706,7 +2706,7 @@ ssl2_HandleVerifyMessage(sslSocket *ss)
PRUint8 * data;
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ssl_GetRecvBufLock(ss);
data = ss->gs.buf.buf + ss->gs.recordOffset;
@ -2758,9 +2758,9 @@ ssl2_HandleServerHelloMessage(sslSocket *ss)
SECStatus rv;
int needed, sidHit, certLen, csLen, cidLen, certType, err;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
if (!ss->enableSSL2) {
if (!ss->opt.enableSSL2) {
PORT_SetError(SSL_ERROR_SSL2_DISABLED);
return SECFailure;
}
@ -2989,7 +2989,7 @@ ssl2_BeginClientHandshake(sslSocket *ss)
int sendLen, sidLen = 0;
SECStatus rv;
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
ss->sec.isServer = 0;
ss->sec.sendSequence = 0;
@ -3035,7 +3035,7 @@ ssl2_BeginClientHandshake(sslSocket *ss)
SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd));
/* Try to find server in our session-id cache */
if (ss->noCache) {
if (ss->opt.noCache) {
sid = NULL;
} else {
sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
@ -3043,15 +3043,15 @@ ssl2_BeginClientHandshake(sslSocket *ss)
}
while (sid) { /* this isn't really a loop */
/* if we're not doing this SID's protocol any more, drop it. */
if (((sid->version < SSL_LIBRARY_VERSION_3_0) && !ss->enableSSL2) ||
((sid->version == SSL_LIBRARY_VERSION_3_0) && !ss->enableSSL3) ||
((sid->version > SSL_LIBRARY_VERSION_3_0) && !ss->enableTLS)) {
if (((sid->version < SSL_LIBRARY_VERSION_3_0) && !ss->opt.enableSSL2) ||
((sid->version == SSL_LIBRARY_VERSION_3_0) && !ss->opt.enableSSL3) ||
((sid->version > SSL_LIBRARY_VERSION_3_0) && !ss->opt.enableTLS)) {
ss->sec.uncache(sid);
ssl_FreeSID(sid);
sid = NULL;
break;
}
if (ss->enableSSL2 && sid->version < SSL_LIBRARY_VERSION_3_0) {
if (ss->opt.enableSSL2 && sid->version < SSL_LIBRARY_VERSION_3_0) {
/* If the cipher in this sid is not enabled, drop it. */
for (i = 0; i < ss->sizeCipherSpecs; i += 3) {
if (ss->cipherSpecs[i] == sid->u.ssl2.cipherType)
@ -3096,8 +3096,8 @@ ssl2_BeginClientHandshake(sslSocket *ss)
PORT_Assert(sid != NULL);
if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->v2CompatibleHello) &&
(ss->enableSSL3 || ss->enableTLS)) {
if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->opt.v2CompatibleHello) &&
(ss->opt.enableSSL3 || ss->opt.enableTLS)) {
ss->gs.state = GS_INIT;
ss->handshake = ssl_GatherRecord1stHandshake;
@ -3138,9 +3138,9 @@ ssl2_BeginClientHandshake(sslSocket *ss)
/* Construct client-hello message */
cp = msg = ss->sec.ci.sendBuf.buf;
msg[0] = SSL_MT_CLIENT_HELLO;
if ( ss->enableTLS ) {
if ( ss->opt.enableTLS ) {
ss->clientHelloVersion = SSL_LIBRARY_VERSION_3_1_TLS;
} else if ( ss->enableSSL3 ) {
} else if ( ss->opt.enableSSL3 ) {
ss->clientHelloVersion = SSL_LIBRARY_VERSION_3_0;
} else {
ss->clientHelloVersion = SSL_LIBRARY_VERSION_2;
@ -3441,7 +3441,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
#endif
PRUint8 csImpl[sizeof implementedCipherSuites];
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
sc = ss->serverCerts + kt_rsa;
serverCert = sc->serverCert;
@ -3470,7 +3470,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
*/
if ((data[0] == SSL_MT_CLIENT_HELLO) &&
(data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) &&
(ss->enableSSL3 || ss->enableTLS)) {
(ss->opt.enableSSL3 || ss->opt.enableTLS)) {
rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen);
if (rv != SECFailure) { /* Success */
ss->handshake = NULL;
@ -3558,7 +3558,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
goto loser;
}
/* Since this handhsake is going to fail, don't cache it. */
ss->noCache = 1;
ss->opt.noCache = 1;
}
/* Squirrel away the challenge for later */
@ -3566,7 +3566,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
/* Examine message and see if session-id is good */
ss->sec.ci.elements = 0;
if (sdLen > 0 && !ss->noCache) {
if (sdLen > 0 && !ss->opt.noCache) {
SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
ss->sec.ci.peer.pr_s6_addr32[1],
@ -3648,7 +3648,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss)
/* Build up final list of required elements */
ss->sec.ci.requiredElements = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED;
if (ss->requestCertificate) {
if (ss->opt.requestCertificate) {
ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE;
}
ss->sec.ci.sentElements = 0;
@ -3742,8 +3742,8 @@ ssl2_BeginServerHandshake(sslSocket *ss)
ss->sec.rcvSequence = 0;
/* don't turn on SSL2 if we don't have an RSA key and cert */
if (!rsaAuth->serverKey || !rsaAuth->serverCert) {
ss->enableSSL2 = PR_FALSE;
if (!rsaAuth->SERVERKEY || !rsaAuth->serverCert) {
ss->opt.enableSSL2 = PR_FALSE;
}
if (!ss->cipherSpecs) {

Просмотреть файл

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: ssldef.c,v 1.9 2004/04/27 23:04:39 gerv%gerv.net Exp $ */
/* $Id: ssldef.c,v 1.10 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "cert.h"
#include "ssl.h"
@ -117,7 +117,7 @@ int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
/* Although this is overkill, we disable Nagle delays completely for
** SSL sockets.
*/
if (ss->useSecurity && !ss->delayDisabled) {
if (ss->opt.useSecurity && !ss->delayDisabled) {
ssl_EnableNagleDelay(ss, PR_FALSE); /* ignore error */
ss->delayDisabled = 1;
}

Просмотреть файл

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslgathr.c,v 1.7 2004/04/27 23:04:39 gerv%gerv.net Exp $ */
/* $Id: sslgathr.c,v 1.8 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "cert.h"
#include "ssl.h"
#include "sslimpl.h"
@ -90,7 +90,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
unsigned char * pBuf;
int nb, err, rv;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
if (gs->state == GS_INIT) {
/* Initialize gathering engine */
@ -141,9 +141,9 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
/* Probably finished this piece */
switch (gs->state) {
case GS_HEADER:
if ((ss->enableSSL3 || ss->enableTLS) && !ss->firstHsDone) {
if ((ss->opt.enableSSL3 || ss->opt.enableTLS) && !ss->firstHsDone) {
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
/* If this looks like an SSL3 handshake record,
** and we're expecting an SSL2 Hello message from our peer,
@ -185,7 +185,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
return SECFailure;
}
}
} /* ((ss->enableSSL3 || ss->enableTLS) && !ss->firstHsDone) */
} /* ((ss->opt.enableSSL3 || ss->opt.enableTLS) && !ss->firstHsDone) */
/* we've got the first 3 bytes. The header may be two or three. */
if (gs->hdr[0] & 0x80) {
@ -411,7 +411,7 @@ ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs, unsigned int count)
{
int rv;
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
gs->state = GS_DATA;
gs->remainder = count;
gs->count = count;
@ -455,8 +455,8 @@ ssl2_HandleV3HandshakeRecord(sslSocket *ss)
SECStatus rv;
SSL3ProtocolVersion version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
PORT_Assert( ssl_HaveRecvBufLock(ss) );
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
/* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */
ss->gs.remainder = 2;

Просмотреть файл

@ -39,7 +39,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslimpl.h,v 1.39 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: sslimpl.h,v 1.40 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#ifndef __sslimpl_h_
#define __sslimpl_h_
@ -93,6 +93,10 @@ typedef SSLSignType SSL3SignType;
#define hmac_md5 ssl_hmac_md5
#define hmac_sha ssl_hmac_sha
#define SET_ERROR_CODE /* reminder */
#define SEND_ALERT /* reminder */
#define TEST_FOR_FAILURE /* reminder */
#define DEAL_WITH_FAILURE /* reminder */
#if defined(DEBUG) || defined(TRACE)
#ifdef __cplusplus
@ -162,12 +166,17 @@ typedef enum { SSLAppOpRead = 0,
#define SSL_MAX_MAC_BYTES 16
#define SSL3_RSA_PMS_LENGTH 48
#define SSL3_MASTER_SECRET_LENGTH 48
/* number of wrap mechanisms potentially used to wrap master secrets. */
#define SSL_NUM_WRAP_MECHS 13
/* This makes the cert cache entry exactly 4k. */
#define SSL_MAX_CACHED_CERT_LEN 4060
#define NUM_MIXERS 9
#ifndef BPB
#define BPB 8 /* Bits Per Byte */
#endif
@ -281,6 +290,8 @@ typedef struct sslOptionsStr {
unsigned int v2CompatibleHello : 1; /* 13 */
unsigned int detectRollBack : 1; /* 14 */
unsigned int noStepDown : 1; /* 15 */
unsigned int bypassPKCS11 : 1; /* 16 */
unsigned int noLocks : 1; /* 17 */
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
@ -292,10 +303,11 @@ typedef struct sslServerCertsStr {
/* Configuration state for server sockets */
CERTCertificate * serverCert;
CERTCertificateList * serverCertChain;
SECKEYPrivateKey * serverKey;
ssl3KeyPair * serverKeyPair;
unsigned int serverKeyBits;
} sslServerCerts;
#define SERVERKEY serverKeyPair->privKey
#define SSL_LOCK_RANK_SPEC 255
#define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE
@ -432,21 +444,31 @@ typedef struct {
uint32 low;
} SSL3SequenceNumber;
typedef struct {
SSL3Opaque write_iv[MAX_IV_LENGTH];
PK11SymKey *write_key;
PK11SymKey *write_mac_key;
PK11Context *write_mac_context;
} ssl3KeyMaterial;
#define MAX_MAC_CONTEXT_BYTES 400
#define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8)
#define MAX_CIPHER_CONTEXT_BYTES 2080
#define MAX_CIPHER_CONTEXT_LLONGS (MAX_CIPHER_CONTEXT_BYTES / 8)
typedef struct {
SSL3Opaque wrapped_client_write_key[12]; /* wrapped with Ks */
SSL3Opaque wrapped_server_write_key[12]; /* wrapped with Ks */
SSL3Opaque client_write_iv [24];
SSL3Opaque server_write_iv [24];
SSL3Opaque wrapped_master_secret [48];
PRUint16 wrapped_master_secret_len;
} ssl3SidKeys;
PRUint8 msIsWrapped;
PRUint8 resumable;
} ssl3SidKeys; /* 100 bytes */
typedef struct {
PK11SymKey *write_key;
PK11SymKey *write_mac_key;
PK11Context *write_mac_context;
SECItem write_key_item;
SECItem write_iv_item;
SECItem write_mac_key_item;
SSL3Opaque write_iv[MAX_IV_LENGTH];
PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS];
} ssl3KeyMaterial;
/*
** These are the "specs" in the "ssl3" struct.
@ -458,16 +480,20 @@ typedef struct {
const ssl3MACDef * mac_def;
int mac_size;
SSLCipher encode;
void * encodeContext;
SSLCipher decode;
void * decodeContext;
SSLDestroy destroy;
void * encodeContext;
void * decodeContext;
PRBool bypassCiphers; /* did double bypass (at least) */
PK11SymKey * master_secret;
ssl3KeyMaterial client;
ssl3KeyMaterial server;
SSL3SequenceNumber write_seq_num;
SSL3SequenceNumber read_seq_num;
SSL3ProtocolVersion version;
ssl3KeyMaterial client;
ssl3KeyMaterial server;
SECItem msItem;
unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
unsigned char raw_master_secret[56];
} ssl3CipherSpec;
typedef enum { never_cached,
@ -519,7 +545,6 @@ struct sslSessionIDStr {
ssl3CipherSuite cipherSuite;
SSL3CompressionMethod compression;
PRBool resumable;
int policy;
ssl3SidKeys keys;
CK_MECHANISM_TYPE masterWrapMech;
@ -533,7 +558,6 @@ struct sslSessionIDStr {
*/
PK11SymKey * clientWriteKey;
PK11SymKey * serverWriteKey;
PK11SymKey * tek;
/* The following values pertain to the slot that wrapped the
** master secret. (used only in client)
@ -631,6 +655,8 @@ typedef struct SSL3HandshakeStateStr {
SSL3Random server_random;
SSL3Random client_random;
SSL3WaitState ws;
PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS];
PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS];
PK11Context * md5; /* handshake running hashes */
PK11Context * sha;
const ssl3KEADef * kea_def;
@ -673,9 +699,6 @@ struct ssl3StateStr {
ssl3CipherSpec * prSpec; /* pending read spec. */
ssl3CipherSpec * cwSpec; /* current write spec. */
ssl3CipherSpec * pwSpec; /* pending write spec. */
ssl3CipherSpec specs[2]; /* one is current, one is pending. */
SSL3HandshakeState hs;
CERTCertificate * clientCertificate; /* used by client */
SECKEYPrivateKey * clientPrivateKey; /* used by client */
@ -692,7 +715,9 @@ struct ssl3StateStr {
/* chain while we are trying to validate it. */
CERTDistNames * ca_list;
/* used by server. trusted CAs for this socket. */
PRBool initialized;
SSL3HandshakeState hs;
ssl3CipherSpec specs[2]; /* one is current, one is pending. */
};
typedef struct {
@ -739,7 +764,7 @@ typedef struct SSLWrappedSymWrappingKeyStr {
*/
/*
** This is "ci", as in "ss->sec->ci".
** This is "ci", as in "ss->sec.ci".
**
** Protection: All the variables in here are protected by
** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock
@ -861,30 +886,17 @@ struct sslSocketStr {
/* Pointer to operations vector for this socket */
const sslSocketOps * ops;
/* SSL socket options */
sslOptions opt;
/* State flags */
unsigned int useSocks : 1;
unsigned int useSecurity : 1;
unsigned int requestCertificate : 1;
unsigned int requireCertificate : 2;
unsigned int handshakeAsClient : 1;
unsigned int handshakeAsServer : 1;
unsigned int enableSSL2 : 1;
unsigned int enableSSL3 : 1;
unsigned int enableTLS : 1;
unsigned int clientAuthRequested: 1;
unsigned int noCache : 1;
unsigned int fdx : 1; /* simultaneous R/W threads */
unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */
unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */
unsigned int firstHsDone : 1; /* first handshake is complete. */
unsigned int recvdCloseNotify : 1; /* received SSL EOF. */
unsigned int lastWriteBlocked : 1;
unsigned int TCPconnected : 1;
unsigned int handshakeBegun : 1;
unsigned int delayDisabled : 1; /* Nagle delay disabled */
unsigned int noStepDown : 1;
unsigned long clientAuthRequested;
unsigned long delayDisabled; /* Nagle delay disabled */
unsigned long firstHsDone; /* first handshake is complete. */
unsigned long handshakeBegun;
unsigned long lastWriteBlocked;
unsigned long recvdCloseNotify; /* received SSL EOF. */
unsigned long TCPconnected;
/* version of the protocol to use */
SSL3ProtocolVersion version;
@ -895,28 +907,17 @@ struct sslSocketStr {
/* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock. */
const char *url; /* ssl 2 & 3 */
/* Gather object used for gathering data */
sslGather gs; /*recvBufLock*/
sslHandshakeFunc handshake; /*firstHandshakeLock*/
sslHandshakeFunc nextHandshake; /*firstHandshakeLock*/
sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/
sslBuffer saveBuf; /*xmitBufLock*/
sslBuffer pendingBuf; /*xmitBufLock*/
/* the following variable is only used with socks or other proxies. */
char * peerID; /* String uniquely identifies target server. */
ssl3State * ssl3;
unsigned char * cipherSpecs;
unsigned int sizeCipherSpecs;
const unsigned char * preferredCipher;
/* Configuration state for server sockets */
/* server cert and key for each KEA type */
sslServerCerts serverCerts[kt_kea_size];
ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */
/* Callbacks */
@ -971,8 +972,21 @@ const unsigned char * preferredCipher;
sslHandshakingType handshaking;
/* Gather object used for gathering data */
sslGather gs; /*recvBufLock*/
sslBuffer saveBuf; /*xmitBufLock*/
sslBuffer pendingBuf; /*xmitBufLock*/
/* Configuration state for server sockets */
/* server cert and key for each KEA type */
sslServerCerts serverCerts[kt_kea_size];
ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED];
ssl3KeyPair * ephemeralECDHKeyPair; /* for ECDHE-* handshake */
/* SSL3 state info. Formerly was a pointer */
ssl3State ssl3;
};
@ -1062,7 +1076,7 @@ extern int ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs,
extern SECStatus ssl_CreateSecurityInfo(sslSocket *ss);
extern SECStatus ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os);
extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec);
extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset);
extern void ssl_DestroySecurityInfo(sslSecurityInfo *sec);
extern sslSocket * ssl_DupSocket(sslSocket *old);
@ -1099,34 +1113,58 @@ extern void ssl_SetAlwaysBlock(sslSocket *ss);
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
#define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock)
#define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock)
#define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock)
#define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock)
#define SSL_UNLOCK_WRITER(ss) if (ss->sendLock) PZ_Unlock(ss->sendLock)
#define SSL_UNLOCK_WRITER(ss) if (ss->sendLock) PZ_Unlock(ss->sendLock)
#define ssl_Get1stHandshakeLock(ss) PZ_EnterMonitor((ss)->firstHandshakeLock)
#define ssl_Release1stHandshakeLock(ss) PZ_ExitMonitor((ss)->firstHandshakeLock)
#define ssl_Have1stHandshakeLock(ss) PZ_InMonitor( (ss)->firstHandshakeLock)
#define ssl_Get1stHandshakeLock(ss) \
{ if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->firstHandshakeLock); }
#define ssl_Release1stHandshakeLock(ss) \
{ if (!ss->opt.noLocks) PZ_ExitMonitor((ss)->firstHandshakeLock); }
#define ssl_Have1stHandshakeLock(ss) \
(PZ_InMonitor((ss)->firstHandshakeLock))
#define ssl_GetSSL3HandshakeLock(ss) PZ_EnterMonitor((ss)->ssl3HandshakeLock)
#define ssl_ReleaseSSL3HandshakeLock(ss) PZ_ExitMonitor((ss)->ssl3HandshakeLock)
#define ssl_HaveSSL3HandshakeLock(ss) PZ_InMonitor( (ss)->ssl3HandshakeLock)
#define ssl_GetSSL3HandshakeLock(ss) \
{ if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->ssl3HandshakeLock); }
#define ssl_ReleaseSSL3HandshakeLock(ss) \
{ if (!ss->opt.noLocks) PZ_ExitMonitor((ss)->ssl3HandshakeLock); }
#define ssl_HaveSSL3HandshakeLock(ss) \
(PZ_InMonitor((ss)->ssl3HandshakeLock))
#define ssl_GetSpecReadLock(ss) NSSRWLock_LockRead( (ss)->specLock)
#define ssl_ReleaseSpecReadLock(ss) NSSRWLock_UnlockRead( (ss)->specLock)
#define ssl_GetSpecReadLock(ss) \
{ if (!ss->opt.noLocks) NSSRWLock_LockRead((ss)->specLock); }
#define ssl_ReleaseSpecReadLock(ss) \
{ if (!ss->opt.noLocks) NSSRWLock_UnlockRead((ss)->specLock); }
#define ssl_GetSpecWriteLock(ss) NSSRWLock_LockWrite( (ss)->specLock)
#define ssl_ReleaseSpecWriteLock(ss) NSSRWLock_UnlockWrite((ss)->specLock)
#define ssl_HaveSpecWriteLock(ss) NSSRWLock_HaveWriteLock((ss)->specLock)
#define ssl_GetSpecWriteLock(ss) \
{ if (!ss->opt.noLocks) NSSRWLock_LockWrite((ss)->specLock); }
#define ssl_ReleaseSpecWriteLock(ss) \
{ if (!ss->opt.noLocks) NSSRWLock_UnlockWrite((ss)->specLock); }
#define ssl_HaveSpecWriteLock(ss) \
(NSSRWLock_HaveWriteLock((ss)->specLock))
#define ssl_GetRecvBufLock(ss) PZ_EnterMonitor((ss)->recvBufLock)
#define ssl_ReleaseRecvBufLock(ss) PZ_ExitMonitor( (ss)->recvBufLock)
#define ssl_HaveRecvBufLock(ss) PZ_InMonitor( (ss)->recvBufLock)
#define ssl_GetRecvBufLock(ss) \
{ if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->recvBufLock); }
#define ssl_ReleaseRecvBufLock(ss) \
{ if (!ss->opt.noLocks) PZ_ExitMonitor( (ss)->recvBufLock); }
#define ssl_HaveRecvBufLock(ss) \
(PZ_InMonitor((ss)->recvBufLock))
#define ssl_GetXmitBufLock(ss) PZ_EnterMonitor((ss)->xmitBufLock)
#define ssl_ReleaseXmitBufLock(ss) PZ_ExitMonitor( (ss)->xmitBufLock)
#define ssl_HaveXmitBufLock(ss) PZ_InMonitor( (ss)->xmitBufLock)
#define ssl_GetXmitBufLock(ss) \
{ if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->xmitBufLock); }
#define ssl_ReleaseXmitBufLock(ss) \
{ if (!ss->opt.noLocks) PZ_ExitMonitor( (ss)->xmitBufLock); }
#define ssl_HaveXmitBufLock(ss) \
(PZ_InMonitor((ss)->xmitBufLock))
extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec * pwSpec,
const unsigned char * cr, const unsigned char * sr,
PRBool isTLS, PRBool isExport);
extern SECStatus ssl3_MasterKeyDeriveBypass( ssl3CipherSpec * pwSpec,
const unsigned char * cr, const unsigned char * sr,
const SECItem * pms, PRBool isTLS, PRBool isRSA);
/* These functions are called from secnav, even though they're "private". */
extern int ssl2_SendErrorMessage(struct sslSocketStr *ss, int error);
@ -1208,13 +1246,46 @@ extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss,
extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache);
extern void ssl3_DestroySSL3Info(ssl3State *ssl3);
extern void ssl3_DestroySSL3Info(sslSocket *ss);
extern SECStatus ssl3_NegotiateVersion(sslSocket *ss,
SSL3ProtocolVersion peerVersion);
extern SECStatus ssl_GetPeerInfo(sslSocket *ss);
#ifdef NSS_ENABLE_ECC
/* ECDH functions */
extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket * ss,
SECKEYPublicKey * svrPubKey);
extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss,
SSL3Opaque *b, PRUint32 length);
extern SECStatus ssl3_HandleECDHClientKeyExchange(sslSocket *ss,
SSL3Opaque *b, PRUint32 length,
SECKEYPublicKey *srvrPubKey,
SECKEYPrivateKey *srvrPrivKey);
extern SECStatus ssl3_SendECDHServerKeyExchange(sslSocket *ss);
#endif
extern SECStatus ssl3_ComputeCommonKeyHash(PRUint8 * hashBuf,
unsigned int bufLen, SSL3Hashes *hashes,
PRBool bypassPKCS11);
extern SECStatus ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms);
extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src,
PRInt32 bytes);
extern SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss,
SSL3HandshakeType t, PRUint32 length);
extern SECStatus ssl3_AppendHandshakeVariable( sslSocket *ss,
const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize);
extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes,
SSL3Opaque **b, PRUint32 *length);
extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i,
PRInt32 bytes, SSL3Opaque **b, PRUint32 *length);
extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key,
SECItem *buf, PRBool isTLS);
extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash,
CERTCertificate *cert, SECItem *buf, PRBool isTLS,
void *pwArg);
/* Construct a new NSPR socket for the app to use */
extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd);
extern void ssl_FreePRSocket(PRFileDesc *fd);

Просмотреть файл

@ -34,7 +34,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslinfo.c,v 1.13 2005/09/06 17:15:32 glen.beasley%sun.com Exp $ */
/* $Id: sslinfo.c,v 1.14 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "ssl.h"
#include "sslimpl.h"
#include "sslproto.h"
@ -60,17 +60,17 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
memset(&inf, 0, sizeof inf);
inf.length = PR_MIN(sizeof inf, len);
if (ss->useSecurity && ss->firstHsDone) {
if (ss->opt.useSecurity && ss->firstHsDone) {
sid = ss->sec.ci.sid;
inf.protocolVersion = ss->version;
inf.authKeyBits = ss->sec.authKeyBits;
inf.keaKeyBits = ss->sec.keaKeyBits;
if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
inf.cipherSuite = ss->sec.cipherType | 0xff00;
} else if (ss->ssl3) { /* SSL3 and TLS */
} else if (ss->ssl3.initialized) { /* SSL3 and TLS */
/* XXX These should come from crSpec */
inf.cipherSuite = ss->ssl3->hs.cipher_suite;
inf.cipherSuite = ss->ssl3.hs.cipher_suite;
}
if (sid) {
inf.creationTime = sid->creationTime;
@ -78,7 +78,8 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
inf.expirationTime = sid->expirationTime;
if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */
inf.sessionIDLength = SSL2_SESSIONID_BYTES;
memcpy(inf.sessionID, sid->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
memcpy(inf.sessionID, sid->u.ssl2.sessionID,
SSL2_SESSIONID_BYTES);
} else {
unsigned int sidLen = sid->u.ssl3.sessionIDLength;
sidLen = PR_MIN(sidLen, sizeof inf.sessionID);

Просмотреть файл

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslnonce.c,v 1.16 2004/12/17 02:01:35 julien.pierre.bugs%sun.com Exp $ */
/* $Id: sslnonce.c,v 1.17 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "nssrenam.h"
#include "cert.h"
@ -193,7 +193,7 @@ ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
PORT_Strcmp(sid->peerID, peerID) == 0)) &&
/* is cacheable */
(sid->version < SSL_LIBRARY_VERSION_3_0 ||
sid->u.ssl3.resumable) &&
sid->u.ssl3.keys.resumable) &&
/* server hostname matches. */
(sid->urlSvrName != NULL) &&
((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) ||

Просмотреть файл

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslsecur.c,v 1.31 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: sslsecur.c,v 1.32 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "cert.h"
#include "secitem.h"
#include "keyhi.h"
@ -112,9 +112,9 @@ ssl_Do1stHandshake(sslSocket *ss)
int loopCount = 0;
do {
PORT_Assert( ssl_Have1stHandshakeLock(ss) );
PORT_Assert( !ssl_HaveRecvBufLock(ss) );
PORT_Assert( !ssl_HaveXmitBufLock(ss) );
PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
if (ss->handshake == 0) {
/* Previous handshake finished. Switch to next one */
@ -153,8 +153,8 @@ ssl_Do1stHandshake(sslSocket *ss)
*/
} while (rv != SECFailure); /* was (rv >= 0); XXX_1 */
PORT_Assert( !ssl_HaveRecvBufLock(ss) );
PORT_Assert( !ssl_HaveXmitBufLock(ss) );
PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
if (rv == SECWouldBlock) {
PORT_SetError(PR_WOULD_BLOCK_ERROR);
@ -202,7 +202,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
}
/* Don't waste my time */
if (!ss->useSecurity)
if (!ss->opt.useSecurity)
return SECSuccess;
SSL_LOCK_READER(ss);
@ -231,7 +231,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
** Blow away old security state and get a fresh setup.
*/
ssl_GetXmitBufLock(ss);
ssl_ResetSecurityInfo(&ss->sec);
ssl_ResetSecurityInfo(&ss->sec, PR_TRUE);
status = ssl_CreateSecurityInfo(ss);
ssl_ReleaseXmitBufLock(ss);
@ -264,7 +264,7 @@ SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
return SECFailure;
}
if (!ss->useSecurity)
if (!ss->opt.useSecurity)
return SECSuccess;
ssl_Get1stHandshakeLock(ss);
@ -306,7 +306,7 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
return SECFailure;
}
if (!ss->useSecurity) {
if (!ss->opt.useSecurity) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@ -347,7 +347,7 @@ SSL_ForceHandshake(PRFileDesc *fd)
}
/* Don't waste my time */
if (!ss->useSecurity)
if (!ss->opt.useSecurity)
return SECSuccess;
ssl_Get1stHandshakeLock(ss);
@ -388,6 +388,7 @@ SSL_ForceHandshake(PRFileDesc *fd)
SECStatus
sslBuffer_Grow(sslBuffer *b, unsigned int newLen)
{
newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048);
if (newLen > b->space) {
unsigned char *newBuf;
if (b->buf) {
@ -419,7 +420,7 @@ ssl_SaveWriteData(sslSocket *ss, sslBuffer *buf, const void *data,
unsigned int newlen;
SECStatus rv;
PORT_Assert( ssl_HaveXmitBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
newlen = buf->len + len;
if (newlen > buf->space) {
rv = sslBuffer_Grow(buf, newlen);
@ -446,7 +447,7 @@ ssl_SendSavedWriteData(sslSocket *ss, sslBuffer *buf, sslSendFunc send)
int rv = 0;
int len = buf->len;
PORT_Assert( ssl_HaveXmitBufLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
if (len != 0) {
SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
SSL_GETPID(), ss->fd, len));
@ -664,19 +665,47 @@ SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
}
/* load the private key */
if (sc->serverKey != NULL) {
SECKEY_DestroyPrivateKey(sc->serverKey);
sc->serverKey = NULL;
if (sc->serverKeyPair != NULL) {
ssl3_FreeKeyPair(sc->serverKeyPair);
sc->serverKeyPair = NULL;
}
if (key) {
sc->serverKey = SECKEY_CopyPrivateKey(key);
if (sc->serverKey == NULL)
SECKEYPrivateKey * keyCopy = NULL;
CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM;
if (key->pkcs11Slot) {
PK11SlotInfo * bestSlot;
bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
if (bestSlot) {
keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
PK11_FreeSlot(bestSlot);
}
}
if (keyCopy == NULL)
keyMech = PK11_MapSignKeyType(key->keyType);
if (keyMech != CKM_INVALID_MECHANISM) {
PK11SlotInfo * bestSlot;
/* XXX Maybe should be bestSlotMultiple? */
bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
if (bestSlot) {
keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
PK11_FreeSlot(bestSlot);
}
}
if (keyCopy == NULL)
keyCopy = SECKEY_CopyPrivateKey(key);
if (keyCopy == NULL)
goto loser;
SECKEY_CacheStaticFlags(sc->serverKey);
SECKEY_CacheStaticFlags(keyCopy);
sc->serverKeyPair = ssl3_NewKeyPair(keyCopy, NULL);
if (sc->serverKeyPair == NULL) {
SECKEY_DestroyPrivateKey(keyCopy);
goto loser;
}
}
if (kea == kt_rsa && cert && sc->serverKeyBits > 512) {
if (ss->noStepDown) {
if (ss->opt.noStepDown) {
/* disable all export ciphersuites */
} else {
rv = ssl3_CreateRSAStepDownKeys(ss);
@ -701,9 +730,9 @@ loser:
CERT_DestroyCertificateList(sc->serverCertChain);
sc->serverCertChain = NULL;
}
if (sc->serverKey != NULL) {
SECKEY_DestroyPrivateKey(sc->serverKey);
sc->serverKey = NULL;
if (sc->serverKeyPair != NULL) {
ssl3_FreeKeyPair(sc->serverKeyPair);
sc->serverKeyPair = NULL;
}
return SECFailure;
}
@ -788,7 +817,7 @@ loser:
** Caller holds any relevant locks.
*/
void
ssl_ResetSecurityInfo(sslSecurityInfo *sec)
ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset)
{
/* Destroy MAC */
if (sec->hash && sec->hashcx) {
@ -830,7 +859,10 @@ ssl_ResetSecurityInfo(sslSecurityInfo *sec)
ssl_FreeSID(sec->ci.sid);
}
PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
memset(&sec->ci, 0, sizeof sec->ci);
if (doMemset) {
memset(&sec->ci, 0, sizeof sec->ci);
}
}
/*
@ -841,7 +873,7 @@ ssl_ResetSecurityInfo(sslSecurityInfo *sec)
void
ssl_DestroySecurityInfo(sslSecurityInfo *sec)
{
ssl_ResetSecurityInfo(sec);
ssl_ResetSecurityInfo(sec, PR_FALSE);
PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
sec->writeBuf.buf = 0;
@ -857,7 +889,7 @@ ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
PRFileDesc *osfd = ss->fd->lower;
int rv;
if ( ss->handshakeAsServer ) {
if ( ss->opt.handshakeAsServer ) {
ss->securityHandshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
} else {
@ -892,7 +924,7 @@ ssl_SecureClose(sslSocket *ss)
ss->firstHsDone &&
!(ss->shutdownHow & ssl_SHUTDOWN_SEND) &&
!ss->recvdCloseNotify &&
(ss->ssl3 != NULL)) {
ss->ssl3.initialized) {
/* We don't want the final alert to be Nagle delayed. */
if (!ss->delayDisabled) {
@ -924,7 +956,7 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow)
(ss->version >= SSL_LIBRARY_VERSION_3_0) &&
ss->firstHsDone &&
!ss->recvdCloseNotify &&
(ss->ssl3 != NULL)) {
ss->ssl3.initialized) {
(void) SSL3_SendAlert(ss, alert_warning, close_notify);
}
@ -956,7 +988,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
return PR_FAILURE;
}
if (!ssl_SocketIsBlocking(ss) && !ss->fdx) {
if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
ssl_GetXmitBufLock(ss);
if (ss->pendingBuf.len != 0) {
rv = ssl_SendSavedWriteData(ss, &ss->pendingBuf, ssl_DefSend);
@ -1132,7 +1164,7 @@ SSL_DataPending(PRFileDesc *fd)
ss = ssl_FindSocket(fd);
if (ss && ss->useSecurity) {
if (ss && ss->opt.useSecurity) {
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
@ -1180,7 +1212,7 @@ SSL_GetSessionID(PRFileDesc *fd)
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
if (ss->useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
item = (SECItem *)PORT_Alloc(sizeof(SECItem));
if (item) {
sslSessionID * sid = ss->sec.ci.sid;

Просмотреть файл

@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslsnce.c,v 1.34 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: sslsnce.c,v 1.35 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
* cache sids!
@ -146,17 +146,15 @@ struct sidCacheEntryStr {
/* 2 */ ssl3CipherSuite cipherSuite;
/* 2 */ PRUint16 compression; /* SSL3CompressionMethod */
/*122 */ ssl3SidKeys keys; /* keys and ivs, wrapped as needed. */
/* 1 */ PRUint8 unused; /* was hasFortezza; */
/* 1 */ PRUint8 resumable;
/*100 */ ssl3SidKeys keys; /* keys and ivs, wrapped as needed. */
/* 4 */ PRUint32 masterWrapMech;
/* 4 */ SSL3KEAType exchKeyType;
/* 4 */ PRInt32 certIndex;
/*140 */} ssl3;
#if defined(LINUX)
/*116 */} ssl3;
#if defined(LINUX) /* XXX Why only on Linux ? */
struct {
PRUint8 filler[144];
PRUint8 filler[144]; /* XXX why this number ? */
} forceSize;
#endif
} u;
@ -441,7 +439,6 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
to->u.ssl3.compression = (uint16)from->u.ssl3.compression;
to->u.ssl3.resumable = from->u.ssl3.resumable;
to->u.ssl3.keys = from->u.ssl3.keys;
to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
@ -516,7 +513,6 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce,
to->u.ssl3.sessionIDLength = from->sessionIDLength;
to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
to->u.ssl3.compression = (SSL3CompressionMethod)from->u.ssl3.compression;
to->u.ssl3.resumable = from->u.ssl3.resumable;
to->u.ssl3.keys = from->u.ssl3.keys;
to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
@ -528,7 +524,7 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce,
*/
to->u.ssl3.clientWriteKey = NULL;
to->u.ssl3.serverWriteKey = NULL;
to->u.ssl3.tek = NULL;
to->urlSvrName = NULL;
to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */

Просмотреть файл

@ -40,7 +40,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: sslsock.c,v 1.38 2005/08/16 03:42:26 nelsonb%netscape.com Exp $ */
/* $Id: sslsock.c,v 1.39 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
#include "seccomon.h"
#include "cert.h"
#include "keyhi.h"
@ -161,6 +161,8 @@ static sslOptions ssl_defaults = {
PR_TRUE, /* v2CompatibleHello */
PR_TRUE, /* detectRollBack */
PR_FALSE, /* noStepDown */
PR_FALSE, /* bypassPKCS11 */
PR_FALSE, /* noLocks */
};
sslSessionIDLookupFunc ssl_sid_lookup;
@ -170,13 +172,15 @@ sslSessionIDUncacheFunc ssl_sid_uncache;
static PRBool ssl_inited = PR_FALSE;
static PRDescIdentity ssl_layer_id;
PRBool locksEverDisabled; /* implicitly PR_FALSE */
int ssl_lock_readers = 1; /* default true. */
char ssl_debug;
char ssl_trace;
/* forward declarations. */
static sslSocket *ssl_NewSocket(void);
static sslSocket *ssl_NewSocket(PRBool makeLocks);
static SECStatus ssl_MakeLocks(sslSocket *ss);
static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
PRDescIdentity id);
@ -227,22 +231,10 @@ ssl_DupSocket(sslSocket *os)
sslSocket *ss;
SECStatus rv;
ss = ssl_NewSocket();
ss = ssl_NewSocket((PRBool)(!os->opt.noLocks));
if (ss) {
ss->useSocks = PR_FALSE;
ss->useSecurity = os->useSecurity;
ss->requestCertificate = os->requestCertificate;
ss->requireCertificate = os->requireCertificate;
ss->handshakeAsClient = os->handshakeAsClient;
ss->handshakeAsServer = os->handshakeAsServer;
ss->enableSSL2 = os->enableSSL2;
ss->enableSSL3 = os->enableSSL3;
ss->enableTLS = os->enableTLS;
ss->noCache = os->noCache;
ss->fdx = os->fdx;
ss->v2CompatibleHello = os->v2CompatibleHello;
ss->detectRollBack = os->detectRollBack;
ss->noStepDown = os->noStepDown;
ss->opt = os->opt;
ss->opt.useSocks = PR_FALSE;
ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
ss->url = !os->url ? NULL : PORT_Strdup(os->url);
@ -271,7 +263,7 @@ ssl_DupSocket(sslSocket *os)
ss->sizeCipherSpecs = 0;
ss->preferredCipher = NULL;
}
if (ss->useSecurity) {
if (ss->opt.useSecurity) {
/* This int should be SSLKEAType, but CC on Irix complains,
* during the for loop.
*/
@ -289,9 +281,9 @@ ssl_DupSocket(sslSocket *os)
sc->serverCert = NULL;
sc->serverCertChain = NULL;
}
sc->serverKey = oc->serverKey ?
SECKEY_CopyPrivateKey(oc->serverKey) : NULL;
if (oc->serverKey && !sc->serverKey)
sc->serverKeyPair = oc->serverKeyPair ?
ssl3_GetKeyPairRef(oc->serverKeyPair) : NULL;
if (oc->serverKeyPair && !sc->serverKeyPair)
goto loser;
sc->serverKeyBits = oc->serverKeyBits;
}
@ -328,7 +320,6 @@ loser:
static void
ssl_DestroyLocks(sslSocket *ss)
{
/* Destroy locks. */
if (ss->firstHandshakeLock) {
PZ_DestroyMonitor(ss->firstHandshakeLock);
@ -373,7 +364,7 @@ ssl_DestroySocketContents(sslSocket *ss)
/* Free up socket */
ssl_DestroySecurityInfo(&ss->sec);
ssl3_DestroySSL3Info(ss->ssl3);
ssl3_DestroySSL3Info(ss);
PORT_Free(ss->saveBuf.buf);
PORT_Free(ss->pendingBuf.buf);
@ -396,8 +387,8 @@ ssl_DestroySocketContents(sslSocket *ss)
CERT_DestroyCertificate(sc->serverCert);
if (sc->serverCertChain != NULL)
CERT_DestroyCertificateList(sc->serverCertChain);
if (sc->serverKey != NULL)
SECKEY_DestroyPrivateKey(sc->serverKey);
if (sc->serverKeyPair != NULL)
ssl3_FreeKeyPair(sc->serverKeyPair);
}
if (ss->stepDownKeyPair) {
ssl3_FreeKeyPair(ss->stepDownKeyPair);
@ -476,7 +467,7 @@ ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled)
static void
ssl_ChooseOps(sslSocket *ss)
{
ss->ops = ss->useSecurity ? &ssl_secure_ops : &ssl_default_ops;
ss->ops = ss->opt.useSecurity ? &ssl_secure_ops : &ssl_default_ops;
}
/* Called from SSL_Enable (immediately below) */
@ -511,7 +502,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
switch (which) {
case SSL_SOCKS:
ss->useSocks = PR_FALSE;
ss->opt.useSocks = PR_FALSE;
rv = PrepareSocket(ss);
if (on) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@ -520,38 +511,38 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
break;
case SSL_SECURITY:
ss->useSecurity = on;
ss->opt.useSecurity = on;
rv = PrepareSocket(ss);
break;
case SSL_REQUEST_CERTIFICATE:
ss->requestCertificate = on;
ss->opt.requestCertificate = on;
break;
case SSL_REQUIRE_CERTIFICATE:
ss->requireCertificate = on;
ss->opt.requireCertificate = on;
break;
case SSL_HANDSHAKE_AS_CLIENT:
if ( ss->handshakeAsServer && on ) {
if ( ss->opt.handshakeAsServer && on ) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
break;
}
ss->handshakeAsClient = on;
ss->opt.handshakeAsClient = on;
break;
case SSL_HANDSHAKE_AS_SERVER:
if ( ss->handshakeAsClient && on ) {
if ( ss->opt.handshakeAsClient && on ) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
break;
}
ss->handshakeAsServer = on;
ss->opt.handshakeAsServer = on;
break;
case SSL_ENABLE_TLS:
ss->enableTLS = on;
ss->opt.enableTLS = on;
ss->preferredCipher = NULL;
if (ss->cipherSpecs) {
PORT_Free(ss->cipherSpecs);
@ -561,7 +552,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
break;
case SSL_ENABLE_SSL3:
ss->enableSSL3 = on;
ss->opt.enableSSL3 = on;
ss->preferredCipher = NULL;
if (ss->cipherSpecs) {
PORT_Free(ss->cipherSpecs);
@ -571,9 +562,9 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
break;
case SSL_ENABLE_SSL2:
ss->enableSSL2 = on;
ss->opt.enableSSL2 = on;
if (on) {
ss->v2CompatibleHello = on;
ss->opt.v2CompatibleHello = on;
}
ss->preferredCipher = NULL;
if (ss->cipherSpecs) {
@ -584,30 +575,45 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
break;
case SSL_NO_CACHE:
ss->noCache = on;
ss->opt.noCache = on;
break;
case SSL_ENABLE_FDX:
ss->fdx = on;
ss->opt.fdx = on;
break;
case SSL_V2_COMPATIBLE_HELLO:
ss->v2CompatibleHello = on;
ss->opt.v2CompatibleHello = on;
if (!on) {
ss->enableSSL2 = on;
ss->opt.enableSSL2 = on;
}
break;
case SSL_ROLLBACK_DETECTION:
ss->detectRollBack = on;
ss->opt.detectRollBack = on;
break;
case SSL_NO_STEP_DOWN:
ss->noStepDown = on;
ss->opt.noStepDown = on;
if (on)
SSL_DisableExportCipherSuites(fd);
break;
case SSL_BYPASS_PKCS11:
if (ss->handshakeBegun) {
PORT_SetError(PR_INVALID_STATE_ERROR);
rv = SECFailure;
} else {
ss->opt.bypassPKCS11 = on;
}
break;
case SSL_NO_LOCKS:
ss->opt.noLocks = on;
if (on)
locksEverDisabled = PR_TRUE;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@ -641,19 +647,21 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
switch (which) {
case SSL_SOCKS: on = PR_FALSE; break;
case SSL_SECURITY: on = ss->useSecurity; break;
case SSL_REQUEST_CERTIFICATE: on = ss->requestCertificate; break;
case SSL_REQUIRE_CERTIFICATE: on = ss->requireCertificate; break;
case SSL_HANDSHAKE_AS_CLIENT: on = ss->handshakeAsClient; break;
case SSL_HANDSHAKE_AS_SERVER: on = ss->handshakeAsServer; break;
case SSL_ENABLE_TLS: on = ss->enableTLS; break;
case SSL_ENABLE_SSL3: on = ss->enableSSL3; break;
case SSL_ENABLE_SSL2: on = ss->enableSSL2; break;
case SSL_NO_CACHE: on = ss->noCache; break;
case SSL_ENABLE_FDX: on = ss->fdx; break;
case SSL_V2_COMPATIBLE_HELLO: on = ss->v2CompatibleHello; break;
case SSL_ROLLBACK_DETECTION: on = ss->detectRollBack; break;
case SSL_NO_STEP_DOWN: on = ss->noStepDown; break;
case SSL_SECURITY: on = ss->opt.useSecurity; break;
case SSL_REQUEST_CERTIFICATE: on = ss->opt.requestCertificate; break;
case SSL_REQUIRE_CERTIFICATE: on = ss->opt.requireCertificate; break;
case SSL_HANDSHAKE_AS_CLIENT: on = ss->opt.handshakeAsClient; break;
case SSL_HANDSHAKE_AS_SERVER: on = ss->opt.handshakeAsServer; break;
case SSL_ENABLE_TLS: on = ss->opt.enableTLS; break;
case SSL_ENABLE_SSL3: on = ss->opt.enableSSL3; break;
case SSL_ENABLE_SSL2: on = ss->opt.enableSSL2; break;
case SSL_NO_CACHE: on = ss->opt.noCache; break;
case SSL_ENABLE_FDX: on = ss->opt.fdx; break;
case SSL_V2_COMPATIBLE_HELLO: on = ss->opt.v2CompatibleHello; break;
case SSL_ROLLBACK_DETECTION: on = ss->opt.detectRollBack; break;
case SSL_NO_STEP_DOWN: on = ss->opt.noStepDown; break;
case SSL_BYPASS_PKCS11: on = ss->opt.bypassPKCS11; break;
case SSL_NO_LOCKS: on = ss->opt.noLocks; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@ -693,6 +701,8 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
case SSL_V2_COMPATIBLE_HELLO: on = ssl_defaults.v2CompatibleHello; break;
case SSL_ROLLBACK_DETECTION: on = ssl_defaults.detectRollBack; break;
case SSL_NO_STEP_DOWN: on = ssl_defaults.noStepDown; break;
case SSL_BYPASS_PKCS11: on = ssl_defaults.bypassPKCS11; break;
case SSL_NO_LOCKS: on = ssl_defaults.noLocks; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@ -790,6 +800,16 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
SSL_DisableDefaultExportCipherSuites();
break;
case SSL_BYPASS_PKCS11:
ssl_defaults.bypassPKCS11 = on;
break;
case SSL_NO_LOCKS:
ssl_defaults.noLocks = on;
if (on)
locksEverDisabled = PR_TRUE;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@ -906,7 +926,7 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefSet", SSL_GETPID(), fd));
return SECFailure;
}
if (enabled && ss->noStepDown && SSL_IsExportCipherSuite(which)) {
if (enabled && ss->opt.noStepDown && SSL_IsExportCipherSuite(which)) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
@ -999,7 +1019,7 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
if (model == NULL) {
/* Just create a default socket if we're given NULL for the model */
ns = ssl_NewSocket();
ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks));
} else {
sslSocket * ss = ssl_FindSocket(model);
if (ss == NULL) {
@ -1084,8 +1104,8 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout)
/* Now start server connection handshake with client.
** Don't need locks here because nobody else has a reference to ns yet.
*/
if ( ns->useSecurity ) {
if ( ns->handshakeAsClient ) {
if ( ns->opt.useSecurity ) {
if ( ns->opt.handshakeAsClient ) {
ns->handshake = ssl2_BeginClientHandshake;
ss->handshaking = sslHandshakingAsClient;
} else {
@ -1241,7 +1261,7 @@ ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
}
SSL_LOCK_READER(ss);
ss->rTimeout = timeout;
if (!ss->fdx)
if (!ss->opt.fdx)
ss->wTimeout = timeout;
rv = (*ss->ops->recv)(ss, (unsigned char*)buf, len, flags);
SSL_UNLOCK_READER(ss);
@ -1262,7 +1282,7 @@ ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
}
SSL_LOCK_WRITER(ss);
ss->wTimeout = timeout;
if (!ss->fdx)
if (!ss->opt.fdx)
ss->rTimeout = timeout;
rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags);
SSL_UNLOCK_WRITER(ss);
@ -1282,7 +1302,7 @@ ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len)
}
SSL_LOCK_READER(ss);
ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
if (!ss->fdx)
if (!ss->opt.fdx)
ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
rv = (*ss->ops->read)(ss, (unsigned char*)buf, len);
SSL_UNLOCK_READER(ss);
@ -1302,7 +1322,7 @@ ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
}
SSL_LOCK_WRITER(ss);
ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
if (!ss->fdx)
if (!ss->opt.fdx)
ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
rv = (*ss->ops->write)(ss, (const unsigned char*)buf, len);
SSL_UNLOCK_WRITER(ss);
@ -1398,7 +1418,7 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
return 0; /* don't poll on this socket */
}
if (ss->useSecurity &&
if (ss->opt.useSecurity &&
ss->handshaking != sslHandshakingUndetermined &&
!ss->firstHsDone &&
(how_flags & PR_POLL_RW)) {
@ -1840,38 +1860,83 @@ loser:
return PR_FAILURE;
}
/* if this fails, caller must destroy socket. */
static SECStatus
ssl_MakeLocks(sslSocket *ss)
{
ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->firstHandshakeLock)
goto loser;
ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->ssl3HandshakeLock)
goto loser;
ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);
if (!ss->specLock)
goto loser;
ss->recvBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->recvBufLock)
goto loser;
ss->xmitBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->xmitBufLock)
goto loser;
ss->writerThread = NULL;
if (ssl_lock_readers) {
ss->recvLock = PZ_NewLock(nssILockSSL);
if (!ss->recvLock)
goto loser;
ss->sendLock = PZ_NewLock(nssILockSSL);
if (!ss->sendLock)
goto loser;
}
return SECSuccess;
loser:
return SECFailure;
}
#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)) && !defined(_WIN32_WCE)
#define NSS_HAVE_GETENV 1
#endif
/*
** Create a newsocket structure for a file descriptor.
*/
static sslSocket *
ssl_NewSocket(void)
ssl_NewSocket(PRBool makeLocks)
{
sslSocket *ss;
#ifdef DEBUG
#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)) && !defined(_WIN32_WCE)
#if defined( NSS_HAVE_GETENV )
static int firsttime = 1;
if (firsttime) {
char * ev;
firsttime = 0;
{
char *ev = getenv("SSLDEBUG");
if (ev && ev[0]) {
ssl_debug = atoi(ev);
SSL_TRACE(("SSL: debugging set to %d", ssl_debug));
}
}
#ifdef DEBUG
#ifdef TRACE
{
char *ev = getenv("SSLTRACE");
if (ev && ev[0]) {
ssl_trace = atoi(ev);
SSL_TRACE(("SSL: tracing set to %d", ssl_trace));
}
ev = getenv("SSLTRACE");
if (ev && ev[0]) {
ssl_trace = atoi(ev);
SSL_TRACE(("SSL: tracing set to %d", ssl_trace));
}
#endif /* TRACE */
}
#endif /* XP_UNIX || XP_WIN32 */
ev = getenv("SSLDEBUG");
if (ev && ev[0]) {
ssl_debug = atoi(ev);
SSL_TRACE(("SSL: debugging set to %d", ssl_debug));
}
#endif /* DEBUG */
ev = getenv("SSLBYPASS");
if (ev && ev[0]) {
ssl_defaults.bypassPKCS11 = (ev[0] == '1');
SSL_TRACE(("SSL: bypass default set to %d", \
ssl_defaults.bypassPKCS11));
}
ev = getenv("SSLNOLOCKS");
if (ev && ev[0]) {
ssl_defaults.noLocks = (ev[0] == '1');
SSL_TRACE(("SSL: noLocks default set to %d", ssl_defaults.noLocks));
}
}
#endif /* NSS_HAVE_GETENV */
/* Make a new socket and get it ready */
ss = (sslSocket*) PORT_ZAlloc(sizeof(sslSocket));
@ -1882,20 +1947,10 @@ ssl_NewSocket(void)
int i;
SECStatus status;
ss->useSecurity = ssl_defaults.useSecurity;
ss->useSocks = PR_FALSE;
ss->requestCertificate = ssl_defaults.requestCertificate;
ss->requireCertificate = ssl_defaults.requireCertificate;
ss->handshakeAsClient = ssl_defaults.handshakeAsClient;
ss->handshakeAsServer = ssl_defaults.handshakeAsServer;
ss->enableSSL2 = ssl_defaults.enableSSL2;
ss->enableSSL3 = ssl_defaults.enableSSL3;
ss->enableTLS = ssl_defaults.enableTLS ;
ss->fdx = ssl_defaults.fdx;
ss->v2CompatibleHello = ssl_defaults.v2CompatibleHello;
ss->detectRollBack = ssl_defaults.detectRollBack;
ss->noStepDown = ssl_defaults.noStepDown;
ss->noCache = ssl_defaults.noCache;
ss->opt = ssl_defaults;
ss->opt.useSocks = PR_FALSE;
ss->opt.noLocks = !makeLocks;
ss->peerID = NULL;
ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
@ -1909,7 +1964,7 @@ ssl_NewSocket(void)
sslServerCerts * sc = ss->serverCerts + i;
sc->serverCert = NULL;
sc->serverCertChain = NULL;
sc->serverKey = NULL;
sc->serverKeyPair = NULL;
sc->serverKeyBits = 0;
}
ss->stepDownKeyPair = NULL;
@ -1927,25 +1982,14 @@ ssl_NewSocket(void)
ssl2_InitSocketPolicy(ss);
ssl3_InitSocketPolicy(ss);
ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->firstHandshakeLock) goto loser;
ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL);
if (!ss->ssl3HandshakeLock) goto loser;
ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL);
if (!ss->specLock) goto loser;
ss->recvBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->recvBufLock) goto loser;
ss->xmitBufLock = PZ_NewMonitor(nssILockSSL);
if (!ss->xmitBufLock) goto loser;
ss->writerThread = NULL;
if (ssl_lock_readers) {
ss->recvLock = PZ_NewLock(nssILockSSL);
if (!ss->recvLock) goto loser;
ss->sendLock = PZ_NewLock(nssILockSSL);
if (!ss->sendLock) goto loser;
if (makeLocks) {
status = ssl_MakeLocks(ss);
if (status != SECSuccess)
goto loser;
}
status = ssl_CreateSecurityInfo(ss);
if (status != SECSuccess) goto loser;
if (status != SECSuccess)
goto loser;
status = ssl_InitGather(&ss->gs);
if (status != SECSuccess) {
loser: