mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 17:31:47 +09:00
[NSS] ported mozilla upstream changes:
- Bug 1552254 internal_error alert on Certificate Request with sha1+ecdsa in TLS 1.3 (be6a9782) - Bug 1753535 - Remove obsolete stateEnd check in SEC_ASN1DecoderUpdate. r=rrelyea (800111fa) - Bug 1756271 - Remove token member from NSSSlot struct. r=rrelyea (55052f78) - Bug 1396616 - Update nssUTF8_Length to RFC 3629 and fix buffer overrun. r=nss-reviewers,jschanck (2f2c8564) - Bug 1755264 - TLS 1.3 Illegal legacy_version handling/alerts. r=djackson (7d931c59) - Bug 1751305 - Remove expired explicitly distrusted certificates from certdata.txt. r=KathleenWilson (b722e523) - Bug 1751298 - Add Telia Root CA v2 root certificate. r=KathleenWilson (1fcbbd7e) - Bug 1754890 - Add two D-TRUST 2020 root certificates. r=KathleenWilson (f63fb86d)
This commit is contained in:
parent
f155978c51
commit
3336114a36
37 changed files with 1556 additions and 671 deletions
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
4 Added functions:
|
||||
|
||||
'function SECStatus CERT_FilterCertListByCertList(CERTCertList*, const CERTCertList*)' {CERT_FilterCertListByCertList@@NSS_3.77}
|
||||
'function SECStatus CERT_FilterCertListByNickname(CERTCertList*, char*, void*)' {CERT_FilterCertListByNickname@@NSS_3.77}
|
||||
'function PRBool CERT_IsInList(const CERTCertificate*, const CERTCertList*)' {CERT_IsInList@@NSS_3.77}
|
||||
'function CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate*, void*, PK11SlotInfo**)' {PK11_FindObjectForCert@@NSS_3.77}
|
||||
|
||||
|
|
@ -11,3 +11,7 @@
|
|||
'PRUint32 SSLPreliminaryChannelInfoStr::authKeyBits', at offset 224 (in bits) at sslt.h:419:1
|
||||
'SSLSignatureScheme SSLPreliminaryChannelInfoStr::signatureScheme', at offset 256 (in bits) at sslt.h:420:1
|
||||
|
||||
2 Added functions:
|
||||
|
||||
'function PRBool SSL_CertIsUsable(PRFileDesc*, CERTCertificate*)' {SSL_CertIsUsable@@NSS_3.77}
|
||||
'function SECStatus SSL_FilterClientCertListBySocket(PRFileDesc*, CERTCertList*)' {SSL_FilterClientCertListBySocket@@NSS_3.77}
|
||||
|
|
|
|||
43
security/nss/gtests/base_gtest/Makefile
Normal file
43
security/nss/gtests/base_gtest/Makefile
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#! gmake
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../common/gtest.mk
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
31
security/nss/gtests/base_gtest/base_gtest.gyp
Normal file
31
security/nss/gtests/base_gtest/base_gtest.gyp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi',
|
||||
'../common/gtest.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'base_gtest',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'utf8_unittest.cc',
|
||||
'<(DEPTH)/gtests/common/gtests.cc'
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
|
||||
'<(DEPTH)/lib/util/util.gyp:nssutil3',
|
||||
'<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
|
||||
'<(DEPTH)/lib/nss/nss.gyp:nss3',
|
||||
'<(DEPTH)/lib/smime/smime.gyp:smime3',
|
||||
'<(DEPTH)/lib/base/base.gyp:nssb',
|
||||
]
|
||||
}
|
||||
],
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
||||
23
security/nss/gtests/base_gtest/manifest.mn
Normal file
23
security/nss/gtests/base_gtest/manifest.mn
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
CORE_DEPTH = ../..
|
||||
DEPTH = ../..
|
||||
MODULE = nss
|
||||
|
||||
CPPSRCS = \
|
||||
utf8_unittest.cc \
|
||||
$(NULL)
|
||||
|
||||
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
|
||||
-I$(CORE_DEPTH)/gtests/common \
|
||||
-I$(CORE_DEPTH)/cpputil
|
||||
|
||||
REQUIRES = nspr nss libdbm gtest
|
||||
|
||||
PROGRAM = base_gtest
|
||||
|
||||
EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) $(EXTRA_OBJS) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX)
|
||||
150
security/nss/gtests/base_gtest/utf8_unittest.cc
Normal file
150
security/nss/gtests/base_gtest/utf8_unittest.cc
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "nss.h"
|
||||
#include "base.h"
|
||||
#include "secerr.h"
|
||||
|
||||
namespace nss_test {
|
||||
|
||||
class Utf8Test : public ::testing::Test {};
|
||||
|
||||
// Tests nssUTF8_Length rejects overlong forms, surrogates, etc.
|
||||
TEST_F(Utf8Test, Utf8Length) {
|
||||
PRStatus status;
|
||||
|
||||
EXPECT_EQ(0u, nssUTF8_Length("", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
|
||||
// U+0000..U+007F
|
||||
EXPECT_EQ(1u, nssUTF8_Length("\x01", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(1u, nssUTF8_Length("\x7F", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
|
||||
// lone trailing byte
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// overlong U+0000..U+007F
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xC0\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xC1\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// U+0080..U+07FF
|
||||
EXPECT_EQ(2u, nssUTF8_Length("\xC2\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(2u, nssUTF8_Length("\xDF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
|
||||
// overlong U+0000..U+07FF
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xE0\x80\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xE0\x9F\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// U+0800..U+D7FF
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xE0\xA0\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xE0\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xE1\x80\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xEC\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xED\x80\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xED\x9F\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
|
||||
// lone surrogate
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xED\xA0\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xED\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// U+E000..U+FFFF
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xEE\x80\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(3u, nssUTF8_Length("\xEF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
|
||||
// overlong U+0000..U+FFFF
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF0\x80\x80\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF0\x8F\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// U+10000..U+10FFFF
|
||||
EXPECT_EQ(4u, nssUTF8_Length("\xF0\x90\x80\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(4u, nssUTF8_Length("\xF0\xBF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(4u, nssUTF8_Length("\xF1\x80\x80\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(4u, nssUTF8_Length("\xF3\xBF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(4u, nssUTF8_Length("\xF4\x80\x80\x80", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
EXPECT_EQ(4u, nssUTF8_Length("\xF4\x8F\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_SUCCESS, status);
|
||||
|
||||
// out of Unicode range
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF4\x90\x80\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF4\xBF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF5\x80\x80\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF7\xBF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// former 5-byte sequence
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xF8\x80\x80\x80\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xFB\xBF\xBF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// former 6-byte sequence
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xFC\x80\x80\x80\x80\x80", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xFD\xBF\xBF\xBF\xBF\xBF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
// invalid lead byte
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xFE", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
EXPECT_EQ(0u, nssUTF8_Length("\xFF", &status));
|
||||
EXPECT_EQ(PR_FAILURE, status);
|
||||
EXPECT_EQ(NSS_ERROR_INVALID_STRING, NSS_GetError());
|
||||
|
||||
nss_DestroyErrorStack();
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ endif
|
|||
ifneq ($(NSS_BUILD_SOFTOKEN_ONLY),1)
|
||||
ifneq ($(NSS_BUILD_UTIL_ONLY),1)
|
||||
NSS_SRCDIRS = \
|
||||
base_gtest \
|
||||
certdb_gtest \
|
||||
certhigh_gtest \
|
||||
cryptohi_gtest \
|
||||
|
|
|
|||
|
|
@ -268,6 +268,126 @@ static SECStatus GetClientAuthDataHook(void* self, PRFileDesc* fd,
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
typedef struct AutoClientTestStr {
|
||||
SECStatus result;
|
||||
const std::string cert;
|
||||
} AutoClientTest;
|
||||
|
||||
typedef struct AutoClientResultsStr {
|
||||
AutoClientTest isRsa2048;
|
||||
AutoClientTest isClient;
|
||||
AutoClientTest isNull;
|
||||
bool hookCalled;
|
||||
} AutoClientResults;
|
||||
|
||||
void VerifyClientCertMatch(CERTCertificate* clientCert,
|
||||
const std::string expectedName) {
|
||||
const char* name = clientCert->nickname;
|
||||
std::cout << "Match name=\"" << name << "\" expected=\"" << expectedName
|
||||
<< "\"" << std::endl;
|
||||
EXPECT_TRUE(PORT_Strcmp(name, expectedName.c_str()) == 0)
|
||||
<< " Certmismatch: \"" << name << "\" != \"" << expectedName << "\"";
|
||||
}
|
||||
|
||||
static SECStatus GetAutoClientAuthDataHook(void* expectResults, PRFileDesc* fd,
|
||||
CERTDistNames* caNames,
|
||||
CERTCertificate** clientCert,
|
||||
SECKEYPrivateKey** clientKey) {
|
||||
AutoClientResults& results = *(AutoClientResults*)expectResults;
|
||||
SECStatus rv;
|
||||
|
||||
results.hookCalled = true;
|
||||
*clientCert = NULL;
|
||||
*clientKey = NULL;
|
||||
rv = NSS_GetClientAuthData((void*)TlsAgent::kRsa2048.c_str(), fd, caNames,
|
||||
clientCert, clientKey);
|
||||
if (rv == SECSuccess) {
|
||||
VerifyClientCertMatch(*clientCert, results.isRsa2048.cert);
|
||||
CERT_DestroyCertificate(*clientCert);
|
||||
SECKEY_DestroyPrivateKey(*clientKey);
|
||||
*clientCert = NULL;
|
||||
*clientKey = NULL;
|
||||
}
|
||||
EXPECT_EQ(results.isRsa2048.result, rv);
|
||||
|
||||
rv = NSS_GetClientAuthData((void*)TlsAgent::kClient.c_str(), fd, caNames,
|
||||
clientCert, clientKey);
|
||||
if (rv == SECSuccess) {
|
||||
VerifyClientCertMatch(*clientCert, results.isClient.cert);
|
||||
CERT_DestroyCertificate(*clientCert);
|
||||
SECKEY_DestroyPrivateKey(*clientKey);
|
||||
*clientCert = NULL;
|
||||
*clientKey = NULL;
|
||||
}
|
||||
EXPECT_EQ(results.isClient.result, rv);
|
||||
EXPECT_EQ(*clientCert, nullptr);
|
||||
EXPECT_EQ(*clientKey, nullptr);
|
||||
rv = NSS_GetClientAuthData(NULL, fd, caNames, clientCert, clientKey);
|
||||
if (rv == SECSuccess) {
|
||||
VerifyClientCertMatch(*clientCert, results.isNull.cert);
|
||||
// return this result
|
||||
}
|
||||
EXPECT_EQ(results.isNull.result, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// while I would have liked to use a new INSTANTIATE macro the
|
||||
// generates the following three tests, figuring out how to make that
|
||||
// work on top of the existing TlsConnect* plumbing hurts my head.
|
||||
TEST_P(TlsConnectTls12, AutoClientSelectRsaPss) {
|
||||
AutoClientResults rsa = {{SECSuccess, TlsAgent::kRsa2048},
|
||||
{SECSuccess, TlsAgent::kClient},
|
||||
{SECSuccess, TlsAgent::kDelegatorRsaPss2048},
|
||||
false};
|
||||
static const SSLSignatureScheme kSchemes[] = {ssl_sig_rsa_pss_pss_sha256,
|
||||
ssl_sig_rsa_pkcs1_sha256,
|
||||
ssl_sig_rsa_pkcs1_sha1};
|
||||
Reset("rsa_pss_noparam");
|
||||
client_->SetupClientAuth();
|
||||
server_->RequestClientAuth(true);
|
||||
EXPECT_EQ(SECSuccess,
|
||||
SSL_GetClientAuthDataHook(client_->ssl_fd(),
|
||||
GetAutoClientAuthDataHook, (void*)&rsa));
|
||||
server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
Connect();
|
||||
EXPECT_TRUE(rsa.hookCalled);
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectTls12, AutoClientSelectEcc) {
|
||||
AutoClientResults ecc = {{SECFailure, TlsAgent::kClient},
|
||||
{SECFailure, TlsAgent::kClient},
|
||||
{SECSuccess, TlsAgent::kDelegatorEcdsa256},
|
||||
false};
|
||||
static const SSLSignatureScheme kSchemes[] = {ssl_sig_ecdsa_secp256r1_sha256};
|
||||
client_->SetupClientAuth();
|
||||
server_->RequestClientAuth(true);
|
||||
EXPECT_EQ(SECSuccess,
|
||||
SSL_GetClientAuthDataHook(client_->ssl_fd(),
|
||||
GetAutoClientAuthDataHook, (void*)&ecc));
|
||||
server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
Connect();
|
||||
EXPECT_TRUE(ecc.hookCalled);
|
||||
}
|
||||
|
||||
TEST_P(TlsConnectTls12, AutoClientSelectDsa) {
|
||||
AutoClientResults dsa = {{SECFailure, TlsAgent::kClient},
|
||||
{SECFailure, TlsAgent::kClient},
|
||||
{SECSuccess, TlsAgent::kServerDsa},
|
||||
false};
|
||||
static const SSLSignatureScheme kSchemes[] = {ssl_sig_dsa_sha256};
|
||||
client_->SetupClientAuth();
|
||||
server_->RequestClientAuth(true);
|
||||
EXPECT_EQ(SECSuccess,
|
||||
SSL_GetClientAuthDataHook(client_->ssl_fd(),
|
||||
GetAutoClientAuthDataHook, (void*)&dsa));
|
||||
server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
Connect();
|
||||
EXPECT_TRUE(dsa.hookCalled);
|
||||
}
|
||||
|
||||
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMultiple) {
|
||||
client_->SetupClientAuth();
|
||||
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
|
||||
|
|
|
|||
|
|
@ -327,13 +327,24 @@ TEST_F(TlsConnectStreamTls13, Tls14ClientHelloWithSupportedVersions) {
|
|||
ASSERT_LT(static_cast<uint32_t>(SSL_LIBRARY_VERSION_TLS_1_2), version);
|
||||
}
|
||||
|
||||
// Offer 1.3 but with ClientHello.legacy_version == SSL 3.0. This
|
||||
// Offer 1.3 but with Server/ClientHello.legacy_version == SSL 3.0. This
|
||||
// causes a protocol version alert. See RFC 8446 Appendix D.5.
|
||||
TEST_F(TlsConnectStreamTls13, Ssl30ClientHelloWithSupportedVersions) {
|
||||
MakeTlsFilter<TlsClientHelloVersionSetter>(client_, SSL_LIBRARY_VERSION_3_0);
|
||||
ConnectExpectAlert(server_, kTlsAlertProtocolVersion);
|
||||
}
|
||||
|
||||
TEST_F(TlsConnectStreamTls13, Ssl30ServerHelloWithSupportedVersions) {
|
||||
MakeTlsFilter<TlsServerHelloVersionSetter>(server_, SSL_LIBRARY_VERSION_3_0);
|
||||
StartConnect();
|
||||
client_->ExpectSendAlert(kTlsAlertProtocolVersion);
|
||||
/* Since the handshake is not finished the client will send an unencrypted
|
||||
* alert. The server is expected to close the connection with a unexpected
|
||||
* message alert. */
|
||||
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
|
||||
Handshake();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TlsDowngradeSentinelTest, TlsDowngradeTest,
|
||||
::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
|
||||
|
|
|
|||
|
|
@ -1060,6 +1060,14 @@ PacketFilter::Action TlsClientHelloVersionSetter::FilterHandshake(
|
|||
return CHANGE;
|
||||
}
|
||||
|
||||
PacketFilter::Action TlsServerHelloVersionSetter::FilterHandshake(
|
||||
const HandshakeHeader& header, const DataBuffer& input,
|
||||
DataBuffer* output) {
|
||||
*output = input;
|
||||
output->Write(0, version_, 2);
|
||||
return CHANGE;
|
||||
}
|
||||
|
||||
PacketFilter::Action SelectedCipherSuiteReplacer::FilterHandshake(
|
||||
const HandshakeHeader& header, const DataBuffer& input,
|
||||
DataBuffer* output) {
|
||||
|
|
|
|||
|
|
@ -669,6 +669,21 @@ class TlsClientHelloVersionSetter : public TlsHandshakeFilter {
|
|||
uint16_t version_;
|
||||
};
|
||||
|
||||
// Set the version number in the ServerHello.
|
||||
class TlsServerHelloVersionSetter : public TlsHandshakeFilter {
|
||||
public:
|
||||
TlsServerHelloVersionSetter(const std::shared_ptr<TlsAgent>& a,
|
||||
uint16_t version)
|
||||
: TlsHandshakeFilter(a, {kTlsHandshakeServerHello}), version_(version) {}
|
||||
|
||||
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
|
||||
const DataBuffer& input,
|
||||
DataBuffer* output);
|
||||
|
||||
private:
|
||||
uint16_t version_;
|
||||
};
|
||||
|
||||
// Damages the last byte of a handshake message.
|
||||
class TlsLastByteDamager : public TlsHandshakeFilter {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -307,31 +307,54 @@ nssUTF8_Length(const NSSUTF8 *s, PRStatus *statusOpt)
|
|||
#endif /* NSSDEBUG */
|
||||
|
||||
/*
|
||||
* From RFC 2044:
|
||||
* From RFC 3629:
|
||||
*
|
||||
* UCS-4 range (hex.) UTF-8 octet sequence (binary)
|
||||
* 0000 0000-0000 007F 0xxxxxxx
|
||||
* 0000 0080-0000 07FF 110xxxxx 10xxxxxx
|
||||
* 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
|
||||
* UTF8-octets = *( UTF8-char )
|
||||
* UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
|
||||
* UTF8-1 = %x00-7F
|
||||
* UTF8-2 = %xC2-DF UTF8-tail
|
||||
* UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
|
||||
* %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
|
||||
* UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
|
||||
* %xF4 %x80-8F 2( UTF8-tail )
|
||||
* UTF8-tail = %x80-BF
|
||||
*/
|
||||
|
||||
while (0 != *c) {
|
||||
PRUint32 incr;
|
||||
if ((*c & 0x80) == 0) {
|
||||
if (*c < 0x80) {
|
||||
incr = 1;
|
||||
} else if ((*c & 0xE0) == 0xC0) {
|
||||
} else if (*c < 0xC2) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
} else if (*c < 0xE0) {
|
||||
incr = 2;
|
||||
} else if ((*c & 0xF0) == 0xE0) {
|
||||
} else if (*c == 0xE0) {
|
||||
if (c[1] < 0xA0) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
incr = 3;
|
||||
} else if ((*c & 0xF8) == 0xF0) {
|
||||
} else if (*c < 0xF0) {
|
||||
if (*c == 0xED && c[1] > 0x9F) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
incr = 3;
|
||||
} else if (*c == 0xF0) {
|
||||
if (c[1] < 0x90) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
incr = 4;
|
||||
} else if (*c < 0xF4) {
|
||||
incr = 4;
|
||||
} else if (*c == 0xF4) {
|
||||
if (c[1] > 0x8F) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
incr = 4;
|
||||
} else if ((*c & 0xFC) == 0xF8) {
|
||||
incr = 5;
|
||||
} else if ((*c & 0xFE) == 0xFC) {
|
||||
incr = 6;
|
||||
} else {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
|
|
@ -345,17 +368,17 @@ nssUTF8_Length(const NSSUTF8 *s, PRStatus *statusOpt)
|
|||
nss_SetError(NSS_ERROR_VALUE_TOO_LARGE);
|
||||
goto loser;
|
||||
}
|
||||
#endif /* PEDANTIC */
|
||||
|
||||
{
|
||||
PRUint8 *d;
|
||||
const PRUint8 *d;
|
||||
for (d = &c[1]; d < &c[incr]; d++) {
|
||||
if ((*d & 0xC0) != 0xF0) {
|
||||
if ((*d & 0xC0) != 0x80) {
|
||||
nss_SetError(NSS_ERROR_INVALID_STRING);
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* PEDANTIC */
|
||||
|
||||
c += incr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1314,6 +1314,21 @@ SECStatus CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
|
|||
*/
|
||||
SECStatus CERT_FilterCertListForUserCerts(CERTCertList *certList);
|
||||
|
||||
/*
|
||||
* Filter a list of certificates, removing those certs that don't match the
|
||||
* nickname.
|
||||
*/
|
||||
SECStatus CERT_FilterCertListByNickname(CERTCertList *certList, char *nickname,
|
||||
void *pwarg);
|
||||
|
||||
/* return true if cert is in cert list */
|
||||
PRBool CERT_IsInList(const CERTCertificate *cert, const CERTCertList *certList);
|
||||
|
||||
/* returned certList is the intersection of the certs on certList and the
|
||||
* certs on filterList */
|
||||
SECStatus CERT_FilterCertListByCertList(CERTCertList *certList,
|
||||
const CERTCertList *filterList);
|
||||
|
||||
/*
|
||||
* Collect the nicknames from all certs in a CertList. If the cert is not
|
||||
* valid, append a string to that nickname.
|
||||
|
|
|
|||
|
|
@ -2552,6 +2552,10 @@ CERT_DestroyCertList(CERTCertList *certs)
|
|||
{
|
||||
PRCList *node;
|
||||
|
||||
if (!certs) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (!PR_CLIST_IS_EMPTY(&certs->list)) {
|
||||
node = PR_LIST_HEAD(&certs->list);
|
||||
CERT_DestroyCertificate(((CERTCertListNode *)node)->cert);
|
||||
|
|
@ -2866,6 +2870,86 @@ CERT_FilterCertListForUserCerts(CERTCertList *certList)
|
|||
return (SECSuccess);
|
||||
}
|
||||
|
||||
/* return true if cert is in the list */
|
||||
PRBool
|
||||
CERT_IsInList(const CERTCertificate *cert, const CERTCertList *certList)
|
||||
{
|
||||
CERTCertListNode *node;
|
||||
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
|
||||
node = CERT_LIST_NEXT(node)) {
|
||||
if (node->cert == cert) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* returned certList is the intersection of the certs on certList and the
|
||||
* certs on filterList */
|
||||
SECStatus
|
||||
CERT_FilterCertListByCertList(CERTCertList *certList,
|
||||
const CERTCertList *filterList)
|
||||
{
|
||||
CERTCertListNode *node, *freenode;
|
||||
CERTCertificate *cert;
|
||||
|
||||
if (!certList) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (!filterList || CERT_LIST_EMPTY(certList)) {
|
||||
/* if the filterList is empty, just clear out certList and return */
|
||||
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);) {
|
||||
freenode = node;
|
||||
node = CERT_LIST_NEXT(node);
|
||||
CERT_RemoveCertListNode(freenode);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
node = CERT_LIST_HEAD(certList);
|
||||
|
||||
while (!CERT_LIST_END(node, certList)) {
|
||||
cert = node->cert;
|
||||
if (!CERT_IsInList(cert, filterList)) {
|
||||
// no matching cert on filter list, remove it from certlist */
|
||||
freenode = node;
|
||||
node = CERT_LIST_NEXT(node);
|
||||
CERT_RemoveCertListNode(freenode);
|
||||
} else {
|
||||
/* matching cert, keep it around */
|
||||
node = CERT_LIST_NEXT(node);
|
||||
}
|
||||
}
|
||||
|
||||
return (SECSuccess);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_FilterCertListByNickname(CERTCertList *certList, char *nickname,
|
||||
void *pwarg)
|
||||
{
|
||||
CERTCertList *nameList;
|
||||
SECStatus rv;
|
||||
|
||||
if (!certList) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* we could try to match the nickname to the individual cert,
|
||||
* but nickname parsing is quite complicated, so it's best just
|
||||
* to use the existing code and get a list of certs that match the
|
||||
* nickname. We can then compare that list with our input cert list
|
||||
* and return only those certs that are on both. */
|
||||
nameList = PK11_FindCertsFromNickname(nickname, pwarg);
|
||||
|
||||
/* namelist could be NULL, this will force certList to become empty */
|
||||
rv = CERT_FilterCertListByCertList(certList, nameList);
|
||||
/* CERT_DestroyCertList can now accept a NULL pointer */
|
||||
CERT_DestroyCertList(nameList);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PZLock *certRefCountLock = NULL;
|
||||
|
||||
/*
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -146,7 +146,6 @@ nssModule_GetCertOrder(
|
|||
* nssSlot_Destroy
|
||||
* nssSlot_AddRef
|
||||
* nssSlot_GetName
|
||||
* nssSlot_GetTokenName
|
||||
* nssSlot_IsTokenPresent
|
||||
* nssSlot_IsPermanent
|
||||
* nssSlot_IsFriendly
|
||||
|
|
@ -176,10 +175,6 @@ NSS_EXTERN NSSUTF8 *
|
|||
nssSlot_GetName(
|
||||
NSSSlot *slot);
|
||||
|
||||
NSS_EXTERN NSSUTF8 *
|
||||
nssSlot_GetTokenName(
|
||||
NSSSlot *slot);
|
||||
|
||||
NSS_EXTERN NSSModule *
|
||||
nssSlot_GetModule(
|
||||
NSSSlot *slot);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
#include "ckhelper.h"
|
||||
#endif /* CKHELPER_H */
|
||||
|
||||
#include "pk11pub.h"
|
||||
#include "pkim.h"
|
||||
#include "dev3hack.h"
|
||||
#include "pk11func.h"
|
||||
|
||||
/* measured in seconds */
|
||||
#define NSSSLOT_TOKEN_DELAY_TIME 1
|
||||
|
|
@ -79,13 +81,6 @@ nssSlot_GetName(
|
|||
return slot->base.name;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT NSSUTF8 *
|
||||
nssSlot_GetTokenName(
|
||||
NSSSlot *slot)
|
||||
{
|
||||
return nssToken_GetName(slot->token);
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void
|
||||
nssSlot_ResetDelay(
|
||||
NSSSlot *slot)
|
||||
|
|
@ -123,11 +118,13 @@ nssSlot_IsTokenPresent(
|
|||
{
|
||||
CK_RV ckrv;
|
||||
PRStatus nssrv;
|
||||
NSSToken *nssToken = NULL;
|
||||
/* XXX */
|
||||
nssSession *session;
|
||||
CK_SLOT_INFO slotInfo;
|
||||
void *epv;
|
||||
PRBool isPresent = PR_FALSE;
|
||||
PRBool doUpdateCachedCerts = PR_FALSE;
|
||||
|
||||
/* permanent slots are always present unless they're disabled */
|
||||
if (nssSlot_IsPermanent(slot)) {
|
||||
|
|
@ -169,23 +166,24 @@ nssSlot_IsTokenPresent(
|
|||
|
||||
PZ_Unlock(slot->isPresentLock);
|
||||
|
||||
nssToken = PK11Slot_GetNSSToken(slot->pk11slot);
|
||||
if (!nssToken) {
|
||||
isPresent = PR_FALSE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nssSlot_EnterMonitor(slot);
|
||||
ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo);
|
||||
nssSlot_ExitMonitor(slot);
|
||||
if (ckrv != CKR_OK) {
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
nssToken->base.name[0] = 0; /* XXX */
|
||||
isPresent = PR_FALSE;
|
||||
goto done;
|
||||
}
|
||||
slot->ckFlags = slotInfo.flags;
|
||||
/* check for the presence of the token */
|
||||
if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
|
||||
if (!slot->token) {
|
||||
/* token was never present */
|
||||
isPresent = PR_FALSE;
|
||||
goto done;
|
||||
}
|
||||
session = nssToken_GetDefaultSession(slot->token);
|
||||
session = nssToken_GetDefaultSession(nssToken);
|
||||
if (session) {
|
||||
nssSession_EnterMonitor(session);
|
||||
/* token is not present */
|
||||
|
|
@ -197,21 +195,21 @@ nssSlot_IsTokenPresent(
|
|||
}
|
||||
nssSession_ExitMonitor(session);
|
||||
}
|
||||
if (slot->token->base.name[0] != 0) {
|
||||
if (nssToken->base.name[0] != 0) {
|
||||
/* notify the high-level cache that the token is removed */
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
nssToken_NotifyCertsNotVisible(slot->token);
|
||||
nssToken->base.name[0] = 0; /* XXX */
|
||||
nssToken_NotifyCertsNotVisible(nssToken);
|
||||
}
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
nssToken->base.name[0] = 0; /* XXX */
|
||||
/* clear the token cache */
|
||||
nssToken_Remove(slot->token);
|
||||
nssToken_Remove(nssToken);
|
||||
isPresent = PR_FALSE;
|
||||
goto done;
|
||||
}
|
||||
/* token is present, use the session info to determine if the card
|
||||
* has been removed and reinserted.
|
||||
*/
|
||||
session = nssToken_GetDefaultSession(slot->token);
|
||||
session = nssToken_GetDefaultSession(nssToken);
|
||||
if (session) {
|
||||
PRBool tokenRemoved;
|
||||
nssSession_EnterMonitor(session);
|
||||
|
|
@ -237,17 +235,31 @@ nssSlot_IsTokenPresent(
|
|||
* a token it doesn't recognize. invalidate all the old
|
||||
* information we had on this token, if we can't refresh, clear
|
||||
* the present flag */
|
||||
nssToken_NotifyCertsNotVisible(slot->token);
|
||||
nssToken_Remove(slot->token);
|
||||
/* token has been removed, need to refresh with new session */
|
||||
nssrv = nssSlot_Refresh(slot);
|
||||
isPresent = PR_TRUE;
|
||||
nssToken_NotifyCertsNotVisible(nssToken);
|
||||
nssToken_Remove(nssToken);
|
||||
if (nssToken->base.name[0] == 0) {
|
||||
doUpdateCachedCerts = PR_TRUE;
|
||||
}
|
||||
if (PK11_InitToken(slot->pk11slot, PR_FALSE) != SECSuccess) {
|
||||
isPresent = PR_FALSE;
|
||||
goto done;
|
||||
}
|
||||
if (doUpdateCachedCerts) {
|
||||
nssTrustDomain_UpdateCachedTokenCerts(nssToken->trustDomain,
|
||||
nssToken);
|
||||
}
|
||||
nssrv = nssToken_Refresh(nssToken);
|
||||
if (nssrv != PR_SUCCESS) {
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
nssToken->base.name[0] = 0; /* XXX */
|
||||
slot->ckFlags &= ~CKF_TOKEN_PRESENT;
|
||||
isPresent = PR_FALSE;
|
||||
goto done;
|
||||
}
|
||||
isPresent = PR_TRUE;
|
||||
done:
|
||||
if (nssToken) {
|
||||
(void)nssToken_Destroy(nssToken);
|
||||
}
|
||||
/* Once we've set up the condition variable,
|
||||
* Before returning, it's necessary to:
|
||||
* 1) Set the lastTokenPingTime so that any other threads waiting on this
|
||||
|
|
@ -283,12 +295,7 @@ nssSlot_GetToken(
|
|||
NSSToken *rvToken = NULL;
|
||||
|
||||
if (nssSlot_IsTokenPresent(slot)) {
|
||||
/* Even if a token should be present, check `slot->token` too as it
|
||||
* might be gone already. This would happen mostly on shutdown. */
|
||||
nssSlot_EnterMonitor(slot);
|
||||
if (slot->token)
|
||||
rvToken = nssToken_AddRef(slot->token);
|
||||
nssSlot_ExitMonitor(slot);
|
||||
rvToken = PK11Slot_GetNSSToken(slot->pk11slot);
|
||||
}
|
||||
|
||||
return rvToken;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ typedef enum {
|
|||
struct NSSSlotStr {
|
||||
struct nssDeviceBaseStr base;
|
||||
NSSModule *module; /* Parent */
|
||||
NSSToken *token; /* Peer */
|
||||
CK_SLOT_ID slotID;
|
||||
CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */
|
||||
struct nssSlotAuthInfoStr authInfo;
|
||||
|
|
|
|||
|
|
@ -32,13 +32,6 @@ nssToken_Destroy(
|
|||
PK11_FreeSlot(tok->pk11slot);
|
||||
PZ_DestroyLock(tok->base.lock);
|
||||
nssTokenObjectCache_Destroy(tok->cache);
|
||||
|
||||
/* We're going away, let the nssSlot know in case it's held
|
||||
* alive by someone else. Usually we should hold the last ref. */
|
||||
nssSlot_EnterMonitor(tok->slot);
|
||||
tok->slot->token = NULL;
|
||||
nssSlot_ExitMonitor(tok->slot);
|
||||
|
||||
(void)nssSlot_Destroy(tok->slot);
|
||||
return nssArena_Destroy(tok->base.arena);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1163,3 +1163,12 @@ PK11_GetCertsMatchingPrivateKey;
|
|||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSS_3.77 { # NSS 3.77 release
|
||||
;+ global:
|
||||
CERT_FilterCertListByCertList;
|
||||
CERT_FilterCertListByNickname;
|
||||
CERT_IsInList;
|
||||
PK11_FindObjectForCert;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
|
|
|||
|
|
@ -179,7 +179,6 @@ nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot)
|
|||
if (!rvToken->slot) {
|
||||
goto loser;
|
||||
}
|
||||
rvToken->slot->token = rvToken;
|
||||
if (rvToken->defaultSession)
|
||||
rvToken->defaultSession->slot = rvToken->slot;
|
||||
return rvToken;
|
||||
|
|
@ -227,24 +226,6 @@ nssToken_Refresh(NSSToken *token)
|
|||
return token->defaultSession ? PR_SUCCESS : PR_FAILURE;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssSlot_Refresh(NSSSlot *slot)
|
||||
{
|
||||
PK11SlotInfo *nss3slot = slot->pk11slot;
|
||||
PRBool doit = PR_FALSE;
|
||||
if (slot->token && slot->token->base.name[0] == 0) {
|
||||
doit = PR_TRUE;
|
||||
}
|
||||
if (PK11_InitToken(nss3slot, PR_FALSE) != SECSuccess) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
if (doit) {
|
||||
nssTrustDomain_UpdateCachedTokenCerts(slot->token->trustDomain,
|
||||
slot->token);
|
||||
}
|
||||
return nssToken_Refresh(slot->token);
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT PRStatus
|
||||
nssToken_GetTrustOrder(NSSToken *tok)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1722,7 +1722,10 @@ PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec,
|
|||
slot = ((PK11SymKey *)objSpec)->slot;
|
||||
handle = ((PK11SymKey *)objSpec)->objectID;
|
||||
break;
|
||||
case PK11_TypeCert: /* don't handle cert case for now */
|
||||
case PK11_TypeCert:
|
||||
handle = PK11_FindObjectForCert((CERTCertificate *)objSpec, NULL,
|
||||
&slot);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -680,6 +680,8 @@ CERTCertificate *PK11_FindBestKEAMatch(CERTCertificate *serverCert, void *wincx)
|
|||
PRBool PK11_FortezzaHasKEA(CERTCertificate *cert);
|
||||
CK_OBJECT_HANDLE PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert,
|
||||
void *wincx);
|
||||
CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert,
|
||||
void *wincx, PK11SlotInfo **pSlot);
|
||||
SECStatus PK11_TraverseCertsForNicknameInSlot(SECItem *nickname,
|
||||
PK11SlotInfo *slot, SECStatus (*callback)(CERTCertificate *, void *),
|
||||
void *arg);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,149 @@
|
|||
#include "pk11func.h" /* for PK11_ function calls */
|
||||
#include "sslimpl.h"
|
||||
|
||||
/* convert a CERTDistNameStr to an array ascii strings.
|
||||
* we ignore caNames which we can't convert, so n could be less than nnames
|
||||
* n is always set, even on failure.
|
||||
* This function allows us to use the existing CERT_FilterCertListByCANames. */
|
||||
static char **
|
||||
ssl_DistNamesToStrings(struct CERTDistNamesStr *caNames, int *n)
|
||||
{
|
||||
char **names;
|
||||
int i;
|
||||
SECStatus rv;
|
||||
PLArenaPool *arena;
|
||||
|
||||
*n = 0;
|
||||
names = PORT_ZNewArray(char *, caNames->nnames);
|
||||
if (names == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
arena = PORT_NewArena(2048);
|
||||
if (arena == NULL) {
|
||||
PORT_Free(names);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < caNames->nnames; ++i) {
|
||||
CERTName dn;
|
||||
rv = SEC_QuickDERDecodeItem(arena, &dn, SEC_ASN1_GET(CERT_NameTemplate),
|
||||
caNames->names + i);
|
||||
if (rv != SECSuccess) {
|
||||
continue;
|
||||
}
|
||||
names[*n] = CERT_NameToAscii(&dn);
|
||||
if (names[*n])
|
||||
(*n)++;
|
||||
}
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
return names;
|
||||
}
|
||||
|
||||
/* free the dist names we allocated in the above function. n must be the
|
||||
* returned n from that function. */
|
||||
static void
|
||||
ssl_FreeDistNamesStrings(char **strings, int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
PORT_Free(strings[i]);
|
||||
}
|
||||
PORT_Free(strings);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ssl_CertIsUsable(sslSocket *ss, CERTCertificate *cert)
|
||||
{
|
||||
SECStatus rv;
|
||||
SSLSignatureScheme scheme;
|
||||
|
||||
if ((ss == NULL) || (cert == NULL)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* There are two ways of handling the old style handshake:
|
||||
* 1) check the actual record we are using and return true,
|
||||
* if (!ss->ssl3.hs.hashType == handshake_hash_record &&
|
||||
* ss->ssl3.hs.hashType == handshake_hash_single) {
|
||||
* return PR_TRUE;
|
||||
* 2) assume if ss->peerSignatureSchemesCount == 0 we are using the
|
||||
* old handshake.
|
||||
* There is one case where using 2 will be wrong: we somehow call this
|
||||
* function outside the case where of out GetClientAuthData context.
|
||||
* In that case we don't know that the 'real' peerScheme list is, so the
|
||||
* best we can do is either always assume good or always assume bad.
|
||||
* I think the best results is to always assume good, so we use
|
||||
* option 2 here to handle that case as well.*/
|
||||
if (ss->peerSignatureSchemeCount == 0) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (ss->peerSignatureSchemes == NULL) {
|
||||
return PR_FALSE; /* should this really be an assert? */
|
||||
}
|
||||
rv = ssl_PickClientSignatureScheme(ss, cert, NULL,
|
||||
ss->peerSignatureSchemes,
|
||||
ss->peerSignatureSchemeCount,
|
||||
&scheme);
|
||||
if (rv != SECSuccess) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl_FilterClientCertListBySSLSocket(sslSocket *ss, CERTCertList *certList)
|
||||
{
|
||||
CERTCertListNode *node;
|
||||
CERTCertificate *cert;
|
||||
|
||||
if (!certList) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
node = CERT_LIST_HEAD(certList);
|
||||
|
||||
while (!CERT_LIST_END(node, certList)) {
|
||||
cert = node->cert;
|
||||
if (PR_TRUE != ssl_CertIsUsable(ss, cert)) {
|
||||
/* cert doesn't match the socket criteria, remove it */
|
||||
CERTCertListNode *freenode = node;
|
||||
node = CERT_LIST_NEXT(node);
|
||||
CERT_RemoveCertListNode(freenode);
|
||||
} else {
|
||||
/* this cert is good, go to the next cert */
|
||||
node = CERT_LIST_NEXT(node);
|
||||
}
|
||||
}
|
||||
|
||||
return (SECSuccess);
|
||||
}
|
||||
|
||||
/* This function can be called by the application's custom GetClientAuthHook
|
||||
* to filter out any certs in the cert list that doesn't match the negotiated
|
||||
* requirements of the current SSL connection.
|
||||
*/
|
||||
SECStatus
|
||||
SSL_FilterClientCertListBySocket(PRFileDesc *fd, CERTCertList *certList)
|
||||
{
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
if (ss == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
return ssl_FilterClientCertListBySSLSocket(ss, certList);
|
||||
}
|
||||
|
||||
/* This function can be called by the application's custom GetClientAuthHook
|
||||
* to determine if a single certificate matches the negotiated requirements of
|
||||
* the current SSL connection.
|
||||
*/
|
||||
PRBool
|
||||
SSL_CertIsUsable(PRFileDesc *fd, CERTCertificate *cert)
|
||||
{
|
||||
sslSocket *ss = ssl_FindSocket(fd);
|
||||
if (ss == NULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return ssl_CertIsUsable(ss, cert);
|
||||
}
|
||||
|
||||
/*
|
||||
* This callback used by SSL to pull client certificate upon
|
||||
* server request
|
||||
|
|
@ -31,6 +174,7 @@ NSS_GetClientAuthData(void *arg,
|
|||
struct SECKEYPrivateKeyStr **pRetKey)
|
||||
{
|
||||
CERTCertificate *cert = NULL;
|
||||
CERTCertList *certList = NULL;
|
||||
SECKEYPrivateKey *privkey = NULL;
|
||||
char *chosenNickName = (char *)arg; /* CONST */
|
||||
SECStatus rv = SECFailure;
|
||||
|
|
@ -39,56 +183,68 @@ NSS_GetClientAuthData(void *arg,
|
|||
if (!ss) {
|
||||
return SECFailure;
|
||||
}
|
||||
void *proto_win = SSL_RevealPinArg(fd);
|
||||
PRTime now = ssl_Time(ss);
|
||||
void *pw_arg = SSL_RevealPinArg(fd);
|
||||
|
||||
if (chosenNickName) {
|
||||
cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
|
||||
chosenNickName, certUsageSSLClient,
|
||||
PR_FALSE, proto_win);
|
||||
if (cert) {
|
||||
privkey = PK11_FindKeyByAnyCert(cert, proto_win);
|
||||
if (privkey) {
|
||||
rv = SECSuccess;
|
||||
} else {
|
||||
CERT_DestroyCertificate(cert);
|
||||
/* first, handle any token authentication that may be needed */
|
||||
if (chosenNickName && pw_arg) {
|
||||
certList = PK11_FindCertsFromNickname(chosenNickName, pw_arg);
|
||||
if (certList) {
|
||||
CERT_FilterCertListForUserCerts(certList);
|
||||
rv = CERT_FilterCertListByUsage(certList, certUsageSSLClient,
|
||||
PR_FALSE);
|
||||
if ((rv != SECSuccess) || CERT_LIST_EMPTY(certList)) {
|
||||
CERT_DestroyCertList(certList);
|
||||
certList = NULL;
|
||||
}
|
||||
}
|
||||
} else { /* no name given, automatically find the right cert. */
|
||||
CERTCertNicknames *names;
|
||||
int i;
|
||||
}
|
||||
|
||||
names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
|
||||
SEC_CERT_NICKNAMES_USER, proto_win);
|
||||
if (names != NULL) {
|
||||
for (i = 0; i < names->numnicknames; i++) {
|
||||
cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(),
|
||||
names->nicknames[i], certUsageSSLClient,
|
||||
PR_FALSE, proto_win);
|
||||
if (!cert)
|
||||
continue;
|
||||
/* Only check unexpired certs */
|
||||
if (CERT_CheckCertValidTimes(cert, now, PR_TRUE) !=
|
||||
secCertTimeValid) {
|
||||
CERT_DestroyCertificate(cert);
|
||||
continue;
|
||||
}
|
||||
rv = NSS_CmpCertChainWCANames(cert, caNames);
|
||||
if (rv == SECSuccess) {
|
||||
privkey =
|
||||
PK11_FindKeyByAnyCert(cert, proto_win);
|
||||
if (privkey)
|
||||
break;
|
||||
}
|
||||
rv = SECFailure;
|
||||
CERT_DestroyCertificate(cert);
|
||||
}
|
||||
CERT_FreeNicknames(names);
|
||||
/* otherwise look through the cache based on usage
|
||||
* if chosenNickname is set, we ignore the expiration date */
|
||||
if (certList == NULL) {
|
||||
certList = CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
|
||||
certUsageSSLClient,
|
||||
PR_FALSE, chosenNickName == NULL,
|
||||
pw_arg);
|
||||
/* filter only the certs that meet the nickname requirements */
|
||||
if (chosenNickName) {
|
||||
rv = CERT_FilterCertListByNickname(certList, chosenNickName,
|
||||
pw_arg);
|
||||
} else {
|
||||
int nnames = 0;
|
||||
char **names = ssl_DistNamesToStrings(caNames, &nnames);
|
||||
rv = CERT_FilterCertListByCANames(certList, nnames, names,
|
||||
certUsageSSLClient);
|
||||
ssl_FreeDistNamesStrings(names, nnames);
|
||||
}
|
||||
if ((rv != SECSuccess) || CERT_LIST_EMPTY(certList)) {
|
||||
CERT_DestroyCertList(certList);
|
||||
certList = NULL;
|
||||
}
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*pRetCert = cert;
|
||||
*pRetKey = privkey;
|
||||
if (certList == NULL) {
|
||||
/* no user certs meeting the nickname/usage requirements found */
|
||||
return SECFailure;
|
||||
}
|
||||
return rv;
|
||||
/* now remove any certs that can't meet the connection requirements */
|
||||
rv = ssl_FilterClientCertListBySSLSocket(ss, certList);
|
||||
if ((rv != SECSuccess) || CERT_LIST_EMPTY(certList)) {
|
||||
// no certs left.
|
||||
CERT_DestroyCertList(certList);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* now return the top cert in the list. We've strived to make the
|
||||
* list ordered by the most likely usable cert, so it should be the best
|
||||
* match. */
|
||||
cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
|
||||
CERT_DestroyCertList(certList);
|
||||
privkey = PK11_FindKeyByAnyCert(cert, pw_arg);
|
||||
if (privkey == NULL) {
|
||||
CERT_DestroyCertificate(cert);
|
||||
return SECFailure;
|
||||
}
|
||||
*pRetCert = cert;
|
||||
*pRetKey = privkey;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,3 +240,10 @@ SSL_GetExperimentalAPI;
|
|||
;+ local:
|
||||
;+*;
|
||||
;+};
|
||||
;+NSS_3.77 { # NSS 3.77 release
|
||||
;+ global:
|
||||
SSL_CertIsUsable;
|
||||
SSL_FilterClientCertListBySocket;
|
||||
;+ local:
|
||||
;+*;
|
||||
;+};
|
||||
|
|
|
|||
|
|
@ -1232,6 +1232,20 @@ NSS_GetClientAuthData(void *arg,
|
|||
struct CERTCertificateStr **pRetCert,
|
||||
struct SECKEYPrivateKeyStr **pRetKey);
|
||||
|
||||
/* This function can be called by the appliation's custom GetClientAuthHook
|
||||
* to filter out any certs in the cert list that doesn't match the negotiated
|
||||
* requirements of the current SSL connection.
|
||||
*/
|
||||
SSL_IMPORT SECStatus
|
||||
SSL_FilterClientCertListBySocket(PRFileDesc *socket, CERTCertList *certlist);
|
||||
|
||||
/* This function can be called by the application's custom GetClientAuthHook
|
||||
* to determine if a single certificate matches the negotiated requirements of
|
||||
* the current SSL connection.
|
||||
*/
|
||||
SSL_IMPORT PRBool
|
||||
SSL_CertIsUsable(PRFileDesc *socket, CERTCertificate *cert);
|
||||
|
||||
/*
|
||||
** Configure DTLS-SRTP (RFC 5764) cipher suite preferences.
|
||||
** Input is a list of ciphers in descending preference order and a length
|
||||
|
|
|
|||
|
|
@ -6334,11 +6334,19 @@ ssl_CanUseSignatureScheme(SSLSignatureScheme scheme,
|
|||
}
|
||||
|
||||
SECStatus
|
||||
ssl_PrivateKeySupportsRsaPss(SECKEYPrivateKey *privKey,
|
||||
PRBool *supportsRsaPss)
|
||||
ssl_PrivateKeySupportsRsaPss(SECKEYPrivateKey *privKey, CERTCertificate *cert,
|
||||
void *pwarg, PRBool *supportsRsaPss)
|
||||
{
|
||||
PK11SlotInfo *slot;
|
||||
slot = PK11_GetSlotFromPrivateKey(privKey);
|
||||
PK11SlotInfo *slot = NULL;
|
||||
if (privKey) {
|
||||
slot = PK11_GetSlotFromPrivateKey(privKey);
|
||||
} else {
|
||||
CK_OBJECT_HANDLE certID = PK11_FindObjectForCert(cert, pwarg, &slot);
|
||||
if (certID == CK_INVALID_HANDLE) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
if (!slot) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
|
|
@ -6355,7 +6363,8 @@ ssl_PickSignatureScheme(sslSocket *ss,
|
|||
SECKEYPrivateKey *privKey,
|
||||
const SSLSignatureScheme *peerSchemes,
|
||||
unsigned int peerSchemeCount,
|
||||
PRBool requireSha1)
|
||||
PRBool requireSha1,
|
||||
SSLSignatureScheme *schemePtr)
|
||||
{
|
||||
unsigned int i;
|
||||
PRBool doesRsaPss;
|
||||
|
|
@ -6366,13 +6375,13 @@ ssl_PickSignatureScheme(sslSocket *ss,
|
|||
|
||||
/* We can't require SHA-1 in TLS 1.3. */
|
||||
PORT_Assert(!(requireSha1 && isTLS13));
|
||||
if (!pubKey || !privKey) {
|
||||
if (!pubKey || !cert) {
|
||||
PORT_Assert(0);
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ssl_PrivateKeySupportsRsaPss(privKey, &doesRsaPss);
|
||||
rv = ssl_PrivateKeySupportsRsaPss(privKey, cert, ss->pkcs11PinArg,
|
||||
&doesRsaPss);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
@ -6390,7 +6399,7 @@ ssl_PickSignatureScheme(sslSocket *ss,
|
|||
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
|
||||
return SECFailure;
|
||||
}
|
||||
ss->ssl3.hs.signatureScheme = scheme;
|
||||
*schemePtr = scheme;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
|
@ -6404,7 +6413,7 @@ ssl_PickSignatureScheme(sslSocket *ss,
|
|||
if (ssl_SignatureSchemeValid(scheme, spkiOid, isTLS13) &&
|
||||
ssl_CanUseSignatureScheme(scheme, peerSchemes, peerSchemeCount,
|
||||
requireSha1, doesRsaPss)) {
|
||||
ss->ssl3.hs.signatureScheme = scheme;
|
||||
*schemePtr = scheme;
|
||||
return SECSuccess;
|
||||
}
|
||||
}
|
||||
|
|
@ -6462,17 +6471,20 @@ ssl3_PickServerSignatureScheme(sslSocket *ss)
|
|||
cert->serverKeyPair->privKey,
|
||||
ss->xtnData.sigSchemes,
|
||||
ss->xtnData.numSigSchemes,
|
||||
PR_FALSE /* requireSha1 */);
|
||||
PR_FALSE /* requireSha1 */,
|
||||
&ss->ssl3.hs.signatureScheme);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
|
||||
unsigned int numSchemes)
|
||||
SECStatus
|
||||
ssl_PickClientSignatureScheme(sslSocket *ss, CERTCertificate *clientCertificate,
|
||||
SECKEYPrivateKey *privKey,
|
||||
const SSLSignatureScheme *schemes,
|
||||
unsigned int numSchemes,
|
||||
SSLSignatureScheme *schemePtr)
|
||||
{
|
||||
SECKEYPrivateKey *privKey = ss->ssl3.clientPrivateKey;
|
||||
SECStatus rv;
|
||||
PRBool isTLS13 = (PRBool)ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
|
||||
SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
|
||||
SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(clientCertificate);
|
||||
|
||||
PORT_Assert(pubKey);
|
||||
|
||||
|
|
@ -6492,9 +6504,9 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
|
|||
* older, DSA key size is at most 1024 bits and the hash function must
|
||||
* be SHA-1.
|
||||
*/
|
||||
rv = ssl_PickSignatureScheme(ss, ss->ssl3.clientCertificate,
|
||||
rv = ssl_PickSignatureScheme(ss, clientCertificate,
|
||||
pubKey, privKey, schemes, numSchemes,
|
||||
PR_TRUE /* requireSha1 */);
|
||||
PR_TRUE /* requireSha1 */, schemePtr);
|
||||
if (rv == SECSuccess) {
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
return SECSuccess;
|
||||
|
|
@ -6502,9 +6514,9 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
|
|||
/* If this fails, that's because the peer doesn't advertise SHA-1,
|
||||
* so fall back to the full negotiation. */
|
||||
}
|
||||
rv = ssl_PickSignatureScheme(ss, ss->ssl3.clientCertificate,
|
||||
rv = ssl_PickSignatureScheme(ss, clientCertificate,
|
||||
pubKey, privKey, schemes, numSchemes,
|
||||
PR_FALSE /* requireSha1 */);
|
||||
PR_FALSE /* requireSha1 */, schemePtr);
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -7690,11 +7702,23 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
|
|||
PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
|
||||
PORT_Assert(ss->ssl3.clientCertificate == NULL);
|
||||
PORT_Assert(ss->ssl3.clientCertChain == NULL);
|
||||
/*
|
||||
* Peer signatures are only available while in the context of
|
||||
* of a getClientAuthData callback. It is required for proper
|
||||
* functioning of SSL_CertIsUsable and SSL_FilterClientCertListBySocket
|
||||
* Calling these functions outside the context of a getClientAuthData
|
||||
* callback will result in no filtering.*/
|
||||
ss->peerSignatureSchemes = signatureSchemes;
|
||||
ss->peerSignatureSchemeCount = signatureSchemeCount;
|
||||
/* XXX Should pass cert_types and algorithms in this call!! */
|
||||
rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg,
|
||||
ss->fd, ca_list,
|
||||
&ss->ssl3.clientCertificate,
|
||||
&ss->ssl3.clientPrivateKey);
|
||||
/* memory for the signature schemes will go away after the request,
|
||||
* so don't leave dangling pointers around */
|
||||
ss->peerSignatureSchemes = NULL;
|
||||
ss->peerSignatureSchemeCount = 0;
|
||||
} else {
|
||||
rv = SECFailure; /* force it to send a no_certificate alert */
|
||||
}
|
||||
|
|
@ -7734,8 +7758,12 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
|
|||
}
|
||||
if (ss->ssl3.hs.hashType == handshake_hash_record ||
|
||||
ss->ssl3.hs.hashType == handshake_hash_single) {
|
||||
rv = ssl_PickClientSignatureScheme(ss, signatureSchemes,
|
||||
signatureSchemeCount);
|
||||
rv = ssl_PickClientSignatureScheme(ss,
|
||||
ss->ssl3.clientCertificate,
|
||||
ss->ssl3.clientPrivateKey,
|
||||
signatureSchemes,
|
||||
signatureSchemeCount,
|
||||
&ss->ssl3.hs.signatureScheme);
|
||||
}
|
||||
break; /* not an error */
|
||||
|
||||
|
|
|
|||
|
|
@ -1100,6 +1100,10 @@ struct sslSocketStr {
|
|||
|
||||
/* Anti-replay for TLS 1.3 0-RTT. */
|
||||
SSLAntiReplayContext *antiReplay;
|
||||
|
||||
/* peer data passed in during getClientAuthData */
|
||||
const SSLSignatureScheme *peerSignatureSchemes;
|
||||
unsigned int peerSignatureSchemeCount;
|
||||
};
|
||||
|
||||
struct sslSelfEncryptKeysStr {
|
||||
|
|
@ -1723,6 +1727,8 @@ PRBool ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite,
|
|||
|
||||
SECStatus ssl3_SelectServerCert(sslSocket *ss);
|
||||
SECStatus ssl_PrivateKeySupportsRsaPss(SECKEYPrivateKey *privKey,
|
||||
CERTCertificate *cert,
|
||||
void *pwArg,
|
||||
PRBool *supportsRsaPss);
|
||||
SECStatus ssl_PickSignatureScheme(sslSocket *ss,
|
||||
CERTCertificate *cert,
|
||||
|
|
@ -1730,7 +1736,14 @@ SECStatus ssl_PickSignatureScheme(sslSocket *ss,
|
|||
SECKEYPrivateKey *privKey,
|
||||
const SSLSignatureScheme *peerSchemes,
|
||||
unsigned int peerSchemeCount,
|
||||
PRBool requireSha1);
|
||||
PRBool requireSha1,
|
||||
SSLSignatureScheme *schemPtr);
|
||||
SECStatus ssl_PickClientSignatureScheme(sslSocket *ss,
|
||||
CERTCertificate *clientCertificate,
|
||||
SECKEYPrivateKey *privKey,
|
||||
const SSLSignatureScheme *schemes,
|
||||
unsigned int numSchemes,
|
||||
SSLSignatureScheme *schemePtr);
|
||||
SECOidTag ssl3_HashTypeToOID(SSLHashType hashType);
|
||||
SSLHashType ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme);
|
||||
SSLAuthType ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme);
|
||||
|
|
|
|||
|
|
@ -381,6 +381,10 @@ ssl_DupSocket(sslSocket *os)
|
|||
goto loser;
|
||||
}
|
||||
}
|
||||
/* The original socket 'owns' the copy of these, so
|
||||
* just set the target copies to zero */
|
||||
ss->peerSignatureSchemes = NULL;
|
||||
ss->peerSignatureSchemeCount = 0;
|
||||
|
||||
/* Create security data */
|
||||
rv = ssl_CopySecurityInfo(ss, os);
|
||||
|
|
@ -468,6 +472,11 @@ ssl_DestroySocketContents(sslSocket *ss)
|
|||
ssl_ClearPRCList(&ss->ssl3.hs.dtlsSentHandshake, NULL);
|
||||
ssl_ClearPRCList(&ss->ssl3.hs.dtlsRcvdHandshake, NULL);
|
||||
|
||||
/* data in peer Signature schemes comes from the buffer system,
|
||||
* so there is nothing to free here. Make sure that's the case */
|
||||
PORT_Assert(ss->peerSignatureSchemes == NULL);
|
||||
PORT_Assert(ss->peerSignatureSchemeCount == 0);
|
||||
|
||||
tls13_DestroyESNIKeys(ss->esniKeys);
|
||||
tls13_ReleaseAntiReplayContext(ss->antiReplay);
|
||||
}
|
||||
|
|
@ -2482,6 +2491,8 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
|
|||
ss->handshakeCallbackData = sm->handshakeCallbackData;
|
||||
if (sm->pkcs11PinArg)
|
||||
ss->pkcs11PinArg = sm->pkcs11PinArg;
|
||||
ss->peerSignatureSchemes = NULL;
|
||||
ss->peerSignatureSchemeCount = 0;
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
@ -4149,6 +4160,8 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
|
|||
|
||||
ss->esniKeys = NULL;
|
||||
ss->antiReplay = NULL;
|
||||
ss->peerSignatureSchemes = NULL;
|
||||
ss->peerSignatureSchemeCount = 0;
|
||||
|
||||
if (makeLocks) {
|
||||
rv = ssl_MakeLocks(ss);
|
||||
|
|
|
|||
|
|
@ -1585,7 +1585,8 @@ tls13_SelectServerCert(sslSocket *ss)
|
|||
cert->serverKeyPair->privKey,
|
||||
ss->xtnData.sigSchemes,
|
||||
ss->xtnData.numSigSchemes,
|
||||
PR_FALSE);
|
||||
PR_FALSE,
|
||||
&ss->ssl3.hs.signatureScheme);
|
||||
if (rv == SECSuccess) {
|
||||
/* Found one. */
|
||||
ss->sec.serverCert = cert;
|
||||
|
|
@ -5808,6 +5809,17 @@ tls13_ClientReadSupportedVersion(sslSocket *ss)
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Any endpoint receiving a Hello message with...ServerHello.legacy_version
|
||||
* set to 0x0300 (SSL3) MUST abort the handshake with a "protocol_version"
|
||||
* alert. [RFC8446, Section D.5]
|
||||
*
|
||||
* The ServerHello.legacy_version is read into the ss->version field by
|
||||
* ssl_ClientReadVersion(). */
|
||||
if (ss->version == SSL_LIBRARY_VERSION_3_0) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, protocol_version);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
ss->version = SSL_LIBRARY_VERSION_TLS_1_3;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ tls13_MaybeSetDelegatedCredential(sslSocket *ss)
|
|||
}
|
||||
|
||||
priv = ss->sec.serverCert->delegCredKeyPair->privKey;
|
||||
rv = ssl_PrivateKeySupportsRsaPss(priv, &doesRsaPss);
|
||||
rv = ssl_PrivateKeySupportsRsaPss(priv, NULL, NULL, &doesRsaPss);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2743,7 +2743,6 @@ SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
|
|||
sec_asn1d_state *state = NULL;
|
||||
unsigned long consumed;
|
||||
SEC_ASN1EncodingPart what;
|
||||
sec_asn1d_state *stateEnd = cx->current;
|
||||
|
||||
if (cx->status == needBytes)
|
||||
cx->status = keepGoing;
|
||||
|
|
@ -2932,7 +2931,7 @@ SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
|
|||
}
|
||||
|
||||
if (cx->status == decodeError) {
|
||||
while (state != NULL && stateEnd->parent != state) {
|
||||
while (state != NULL) {
|
||||
sec_asn1d_free_child(state, PR_TRUE);
|
||||
state = state->parent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -444,7 +444,8 @@ class covAction(argparse.Action):
|
|||
def runSslGtests(self, outdir):
|
||||
env = {
|
||||
"GTESTFILTER": "*", # Prevent parallel test runs.
|
||||
"ASAN_OPTIONS": "coverage=1:coverage_dir=" + outdir
|
||||
"ASAN_OPTIONS": "coverage=1:coverage_dir=" + outdir,
|
||||
"NSS_DISABLE_UNLOAD": "1"
|
||||
}
|
||||
|
||||
run_tests("ssl_gtests", env=env, silent=True)
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@
|
|||
'cmd/vfychain/vfychain.gyp:vfychain',
|
||||
'cmd/vfyserv/vfyserv.gyp:vfyserv',
|
||||
'cmd/mpitests/mpitests.gyp:mpi_tests',
|
||||
'gtests/base_gtest/base_gtest.gyp:base_gtest',
|
||||
'gtests/certhigh_gtest/certhigh_gtest.gyp:certhigh_gtest',
|
||||
'gtests/cryptohi_gtest/cryptohi_gtest.gyp:cryptohi_gtest',
|
||||
'gtests/der_gtest/der_gtest.gyp:der_gtest',
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ gtest_cleanup()
|
|||
}
|
||||
|
||||
################## main #################################################
|
||||
GTESTS="${GTESTS:-prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest softoken_gtest sysinit_gtest blake2b_gtest smime_gtest mozpkix_gtest}"
|
||||
GTESTS="${GTESTS:-base_gtest prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest softoken_gtest sysinit_gtest blake2b_gtest smime_gtest mozpkix_gtest}"
|
||||
SOURCE_DIR="$PWD"/../..
|
||||
gtest_init "$0"
|
||||
gtest_start
|
||||
|
|
|
|||
|
|
@ -723,7 +723,10 @@ ssl_crl_ssl()
|
|||
fi
|
||||
servarg=`echo $sparam | awk '{r=split($0,a,"-r") - 1;print r;}'`
|
||||
pwd=`echo $cparam | grep nss`
|
||||
# did we select TestUser?
|
||||
user=`echo $cparam | grep TestUser`
|
||||
# did we explicitly select a cert?
|
||||
auto=`echo $cparam | grep '\\-n'`
|
||||
_cparam=$cparam
|
||||
case $servarg in
|
||||
1) if [ -z "$pwd" -o -z "$user" ]; then
|
||||
|
|
@ -732,14 +735,24 @@ ssl_crl_ssl()
|
|||
rev_modvalue=254
|
||||
fi
|
||||
;;
|
||||
2) rev_modvalue=254 ;;
|
||||
2) if [ -z "$auto" ]; then
|
||||
rev_modvalue=0
|
||||
else
|
||||
rev_modvalue=254
|
||||
fi
|
||||
;;
|
||||
3) if [ -z "$pwd" -o -z "$user" ]; then
|
||||
rev_modvalue=0
|
||||
else
|
||||
rev_modvalue=1
|
||||
fi
|
||||
;;
|
||||
4) rev_modvalue=1 ;;
|
||||
4) if [ -z "$auto" ]; then
|
||||
rev_modvalue=0
|
||||
else
|
||||
rev_modvalue=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
TEMP_NUM=0
|
||||
while [ $TEMP_NUM -lt $CRL_GROUP_RANGE ]
|
||||
|
|
@ -747,8 +760,8 @@ ssl_crl_ssl()
|
|||
CURR_SER_NUM=`expr ${CRL_GROUP_BEGIN} + ${TEMP_NUM}`
|
||||
TEMP_NUM=`expr $TEMP_NUM + 1`
|
||||
USER_NICKNAME="TestUser${CURR_SER_NUM}"
|
||||
cparam=`echo $_cparam | sed -e 's;_; ;g' -e "s/TestUser/$USER_NICKNAME/g" `
|
||||
start_selfserv `echo "$sparam" | sed -e 's,_, ,g'`
|
||||
cparam=`echo $_cparam | sed -e 's;\([^\\]\)_;\1 ;g' -e 's;\\\\_;_;g' -e "s/TestUser/$USER_NICKNAME/g" `
|
||||
start_selfserv `echo "$sparam" | sed -e 's;\([^\\]\)_;\1 ;g' -e 's;\\\\_;_;g'`
|
||||
|
||||
echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${R_CLIENTDIR} $verbose \\"
|
||||
echo " ${cparam} < ${REQUEST_FILE}"
|
||||
|
|
@ -1130,7 +1143,7 @@ ssl_crl_cache()
|
|||
CURR_SER_NUM=`expr ${CRL_GRP_1_BEGIN} + ${TEMP_NUM}`
|
||||
TEMP_NUM=`expr $TEMP_NUM + 1`
|
||||
USER_NICKNAME="TestUser${CURR_SER_NUM}"
|
||||
cparam=`echo $_cparam | sed -e 's;_; ;g' -e "s/TestUser/$USER_NICKNAME/g" `
|
||||
cparam=`echo $_cparam | sed -e 's;\([^\]\)_;\1 ;g' -e 's;\\_;_;g' -e "s/TestUser/$USER_NICKNAME/g" `
|
||||
|
||||
echo "Server Args: $SERV_ARG"
|
||||
echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${R_CLIENTDIR} $verbose \\"
|
||||
|
|
|
|||
|
|
@ -43,17 +43,18 @@
|
|||
noECC 0 -r_-r_-r_-E -V_tls1.3:tls1.3_-E_-n_none_-w_nss TLS 1.3 Request don't require client auth on post hs (client does not provide auth)
|
||||
noECC 1 -r_-r_-r_-r_-E -V_tls1.3:tls1.3_-E_-n_none_-w_nss TLS 1.3 Require client auth on post hs (client does not provide auth)
|
||||
noECC 0 -r_-r_-r_-E_-u -V_tls1.3:tls1.3_-E_-n_TestUser_-w_nss TLS 1.3 Request don't require client auth on post hs with session ticket (client auth)
|
||||
noECC 0 -r_-r_-J_rsa\\_pkcs1\\_sha256 -V_tls1.2:_-w_nss TLS 1.2 Require client auth auto select(RSA) (client auth)
|
||||
#
|
||||
# Use EC cert for client authentication
|
||||
#
|
||||
ECC 0 -r -V_ssl3:tls1.2_-w_bogus_-n_TestUser-ec TLS Request don't require client auth (EC) (bad password)
|
||||
ECC 0 -r -V_ssl3:tls1.2_-w_nss_-n_TestUser-ec TLS Request don't require client auth (EC) (client auth)
|
||||
ECC 254 -r_-r -V_ssl3:tls1.2_-w_bogus_-n_TestUser-ec TLS Require client auth (EC) (bad password)
|
||||
ECC 0 -r_-r -V_ssl3:tls1.2_-w_nss_-n_TestUser-ec_ TLS Require client auth (EC) (client auth)
|
||||
ECC 0 -r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Request don't require client auth (EC) (bad password)
|
||||
ECC 0 -r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Request don't require client auth (EC) (client auth)
|
||||
ECC 254 -r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Require client auth (EC) (bad password)
|
||||
ECC 0 -r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Require client auth (EC) (client auth)
|
||||
ECC 0 -r -V_ssl3:tls1.2_-w_bogus_-n_TestUser-ec TLS Request don't require client auth (EC) (bad password)
|
||||
ECC 0 -r -V_ssl3:tls1.2_-w_nss_-n_TestUser-ec TLS Request don't require client auth (EC) (client auth)
|
||||
ECC 254 -r_-r -V_ssl3:tls1.2_-w_bogus_-n_TestUser-ec TLS Require client auth (EC) (bad password)
|
||||
ECC 0 -r_-r -V_ssl3:tls1.2_-w_nss_-n_TestUser-ec_ TLS Require client auth (EC) (client auth)
|
||||
ECC 0 -r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Request don't require client auth (EC) (bad password)
|
||||
ECC 0 -r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Request don't require client auth (EC) (client auth)
|
||||
ECC 254 -r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Require client auth (EC) (bad password)
|
||||
ECC 0 -r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Require client auth (EC) (client auth)
|
||||
ECC 0 -r_-r_-r -V_ssl3:tls1.2_-w_bogus_-n_TestUser-ec TLS Request don't require client auth on 2nd hs (EC) (bad password)
|
||||
ECC 0 -r_-r_-r -V_ssl3:tls1.2_-w_nss_-n_TestUser-ec TLS Request don't require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 1 -r_-r_-r_-r -V_ssl3:tls1.2_-w_bogus_-n_TestUser-ec TLS Require client auth on 2nd hs (EC) (bad password)
|
||||
|
|
@ -62,10 +63,12 @@
|
|||
ECC 0 -r_-r_-r -V_ssl3:tls1.0_-w_nss_-n_TestUser-ec TLS 1.0 Request don't require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 1 -r_-r_-r_-r -V_ssl3:tls1.0_-w_bogus_-n_TestUser-ec TLS 1.0 Require client auth on 2nd hs (EC) (bad password)
|
||||
ECC 0 -r_-r_-r_-r -V_ssl3:tls1.0_-w_nss_-n_TestUser-ec_ TLS 1.0 Require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 0 -r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Request don't require client auth on 2nd hs (EC) (bad password)
|
||||
ECC 0 -r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Request don't require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 1 -r_-r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Require client auth on 2nd hs (EC) (bad password)
|
||||
ECC 0 -r_-r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 0 -r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Request don't require client auth on 2nd hs (EC) (bad password)
|
||||
ECC 0 -r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Request don't require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 1 -r_-r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_bogus SSL3 Require client auth on 2nd hs (EC) (bad password)
|
||||
ECC 0 -r_-r_-r_-r -V_ssl3:ssl3_-n_TestUser-ec_-w_nss SSL3 Require client auth on 2nd hs (EC) (client auth)
|
||||
ECC 0 -r_-r_-J_ecdsa\\_secp256r1\\_sha256 -V_tls1.2:_-w_nss TLS 1.2 Require client auth auto select(EC) (client auth)
|
||||
ECC 0 -r_-r_-J_ecdsa\\_secp256r1\\_sha256,ecdsa\\_secp384r1\\_sha384 -V_tls1.3:_-w_nss TLS 1.3 Require client auth auto select (EC) (client auth)
|
||||
#
|
||||
# SNI Tests
|
||||
#
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue