summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Relyea <rrelyea@redhat.com>2022-01-12 08:50:13 -0800
committerRobert Relyea <rrelyea@redhat.com>2022-01-12 08:50:13 -0800
commit1566ba8742d38e046179028662eb353a08a3a5e5 (patch)
treedebbf1a2321c55676ebad296330aa8c7b076ac9c
parentbcf4023a9ab870b83376d1964753124e4489f82a (diff)
downloadnss-hg-1566ba8742d38e046179028662eb353a08a3a5e5.tar.gz
try: -p none -t all
Bug 1552254 internal_error alert on Certificate Request with sha1+ecdsa in TLS 1.3 We need to be able to select Client certificates based on the schemes sent to us from the server. Rather than changing the callback function, this patch adds those schemes to the ssl socket info as suggested by Dana. In addition, two helpful functions have been added to aid User applications in properly selecting the Certificate: PRBool SSL_CertIsUsable(PRFileDesc *fd, CERTCertificate *cert) - returns true if the given cert matches the schemes of the server, the schemes configured on the socket, capability of the token the private key resides on, and the current policy. For future SSL protocol, additional restrictions may be parsed. SSL_FilterCertListBySocket(PRFileDesc *fd, CERTCertList *certlist) - removes the certs from the cert list that doesn't pass the SSL_CertIsUsable() call. In addition the built in cert selection function (NSS_GetClientAuthData) uses the above functions to filter the list. In order to support the NSS_GetClientAuthData three new functions have been added: SECStatus CERT_FilterCertListByNickname(CERTCertList *certList, char *nickname, void *pwarg) -- removes the certs that don't match the 'nickname'. SECStatus CERT_FilterCertListByCertList(CERTCertlist *certList, const CERTCertlist *filterList ) -- removes all the certs on the first cert list that isn't on the second. PRBool CERT_IsInList(CERTCertificate *, const CERTCertList *certList) -- returns true if cert is on certList. In addition * PK11_FindObjectForCert() is exported so the token the cert lives on can be accessed. * the ssle ssl_PickClientSignatureScheme() function (along with several supporing functions) have been modified so it can be used by SSL_CertIsUsable() Differential Revision: https://phabricator.services.mozilla.com/D135715
-rw-r--r--automation/abi-check/expected-report-libnss3.so.txt8
-rw-r--r--automation/abi-check/expected-report-libssl3.so.txt4
-rw-r--r--gtests/ssl_gtest/ssl_auth_unittest.cc120
-rw-r--r--lib/certdb/cert.h15
-rw-r--r--lib/certdb/certdb.c84
-rw-r--r--lib/nss/nss.def9
-rw-r--r--lib/pk11wrap/pk11obj.c5
-rw-r--r--lib/pk11wrap/pk11pub.h2
-rw-r--r--lib/ssl/authcert.c250
-rw-r--r--lib/ssl/ssl.def7
-rw-r--r--lib/ssl/ssl.h14
-rw-r--r--lib/ssl/ssl3con.c72
-rw-r--r--lib/ssl/sslimpl.h15
-rw-r--r--lib/ssl/sslsock.c12
-rw-r--r--lib/ssl/tls13con.c3
-rw-r--r--lib/ssl/tls13subcerts.c2
-rwxr-xr-xmach3
-rwxr-xr-xtests/ssl/ssl.sh27
-rw-r--r--tests/ssl/sslauth.txt27
19 files changed, 586 insertions, 93 deletions
diff --git a/automation/abi-check/expected-report-libnss3.so.txt b/automation/abi-check/expected-report-libnss3.so.txt
index e69de29bb..fcbb2c1bc 100644
--- a/automation/abi-check/expected-report-libnss3.so.txt
+++ b/automation/abi-check/expected-report-libnss3.so.txt
@@ -0,0 +1,8 @@
+
+4 Added functions:
+
+ 'function SECStatus CERT_FilterCertListByCertList(CERTCertList*, const CERTCertList*)' {CERT_FilterCertListByCertList@@NSS_3.76}
+ 'function SECStatus CERT_FilterCertListByNickname(CERTCertList*, char*, void*)' {CERT_FilterCertListByNickname@@NSS_3.76}
+ 'function PRBool CERT_IsInList(const CERTCertificate*, const CERTCertList*)' {CERT_IsInList@@NSS_3.76}
+ 'function CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate*, void*, PK11SlotInfo**)' {PK11_FindObjectForCert@@NSS_3.76}
+
diff --git a/automation/abi-check/expected-report-libssl3.so.txt b/automation/abi-check/expected-report-libssl3.so.txt
index e69de29bb..b309fea1a 100644
--- a/automation/abi-check/expected-report-libssl3.so.txt
+++ b/automation/abi-check/expected-report-libssl3.so.txt
@@ -0,0 +1,4 @@
+2 Added functions:
+
+ 'function PRBool SSL_CertIsUsable(PRFileDesc*, CERTCertificate*)' {SSL_CertIsUsable@@NSS_3.76}
+ 'function SECStatus SSL_FilterClientCertListBySocket(PRFileDesc*, CERTCertList*)' {SSL_FilterClientCertListBySocket@@NSS_3.76}
diff --git a/gtests/ssl_gtest/ssl_auth_unittest.cc b/gtests/ssl_gtest/ssl_auth_unittest.cc
index adb4424c1..925b82721 100644
--- a/gtests/ssl_gtest/ssl_auth_unittest.cc
+++ b/gtests/ssl_gtest/ssl_auth_unittest.cc
@@ -309,6 +309,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(),
diff --git a/lib/certdb/cert.h b/lib/certdb/cert.h
index 1981b8f54..33d37b39a 100644
--- a/lib/certdb/cert.h
+++ b/lib/certdb/cert.h
@@ -1315,6 +1315,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.
*
diff --git a/lib/certdb/certdb.c b/lib/certdb/certdb.c
index 4a713b6d7..e9acbb28d 100644
--- a/lib/certdb/certdb.c
+++ b/lib/certdb/certdb.c
@@ -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;
/*
diff --git a/lib/nss/nss.def b/lib/nss/nss.def
index e87395ba9..f135abd38 100644
--- a/lib/nss/nss.def
+++ b/lib/nss/nss.def
@@ -1238,3 +1238,12 @@ PK11_SlotGetLastFIPSStatus;
;+ local:
;+ *;
;+};
+;+NSS_3.76 { # NSS 3.76 release
+;+ global:
+CERT_FilterCertListByCertList;
+CERT_FilterCertListByNickname;
+CERT_IsInList;
+PK11_FindObjectForCert;
+;+ local:
+;+ *;
+;+};
diff --git a/lib/pk11wrap/pk11obj.c b/lib/pk11wrap/pk11obj.c
index 8ece7a6d4..5dd4d0fc0 100644
--- a/lib/pk11wrap/pk11obj.c
+++ b/lib/pk11wrap/pk11obj.c
@@ -1717,7 +1717,10 @@ PK11_GetObjectHandle(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:
PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
break;
diff --git a/lib/pk11wrap/pk11pub.h b/lib/pk11wrap/pk11pub.h
index a2a647320..6530d42bd 100644
--- a/lib/pk11wrap/pk11pub.h
+++ b/lib/pk11wrap/pk11pub.h
@@ -725,6 +725,8 @@ PRBool PK11_FortezzaHasKEA(CERTCertificate *cert);
CK_OBJECT_HANDLE PK11_FindEncodedCertInSlot(PK11SlotInfo *slot, SECItem *derCert, void *wincx);
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);
diff --git a/lib/ssl/authcert.c b/lib/ssl/authcert.c
index 737b4e797..54b6f5950 100644
--- a/lib/ssl/authcert.c
+++ b/lib/ssl/authcert.c
@@ -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);
-
- 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);
+ void *pw_arg = SSL_RevealPinArg(fd);
+
+ /* 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 (certList == NULL) {
+ /* no user certs meeting the nickname/usage requirements found */
+ return SECFailure;
}
- if (rv == SECSuccess) {
- *pRetCert = cert;
- *pRetKey = privkey;
+ /* 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;
}
- return rv;
+ *pRetCert = cert;
+ *pRetKey = privkey;
+ return SECSuccess;
}
diff --git a/lib/ssl/ssl.def b/lib/ssl/ssl.def
index 9a447dbef..ae5e05552 100644
--- a/lib/ssl/ssl.def
+++ b/lib/ssl/ssl.def
@@ -240,3 +240,10 @@ SSL_GetExperimentalAPI;
;+ local:
;+*;
;+};
+;+NSS_3.76 { # NSS 3.76 release
+;+ global:
+SSL_CertIsUsable;
+SSL_FilterClientCertListBySocket;
+;+ local:
+;+*;
+;+};
diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
index a2c80beaf..e68e24d50 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
@@ -1259,6 +1259,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
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index ea5183962..d7d79e1c8 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -6490,11 +6490,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;
@@ -6511,7 +6519,8 @@ ssl_PickSignatureScheme(sslSocket *ss,
SECKEYPrivateKey *privKey,
const SSLSignatureScheme *peerSchemes,
unsigned int peerSchemeCount,
- PRBool requireSha1)
+ PRBool requireSha1,
+ SSLSignatureScheme *schemePtr)
{
unsigned int i;
PRBool doesRsaPss;
@@ -6522,13 +6531,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;
}
@@ -6546,7 +6555,7 @@ ssl_PickSignatureScheme(sslSocket *ss,
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
return SECFailure;
}
- ss->ssl3.hs.signatureScheme = scheme;
+ *schemePtr = scheme;
return SECSuccess;
}
@@ -6563,7 +6572,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;
}
}
@@ -6621,17 +6630,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);
@@ -6651,9 +6663,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;
@@ -6661,9 +6673,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;
}
@@ -7857,11 +7869,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 */
}
@@ -7887,8 +7911,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);
if (rv != SECSuccess) {
/* This should only happen if our schemes changed or
* if an RSA-PSS cert was selected, but the token
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
index 1ec293138..aeb3b8370 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -1138,6 +1138,10 @@ struct sslSocketStr {
/* An out-of-band PSK. */
sslPsk *psk;
+
+ /* peer data passed in during getClientAuthData */
+ const SSLSignatureScheme *peerSignatureSchemes;
+ unsigned int peerSignatureSchemeCount;
};
struct sslSelfEncryptKeysStr {
@@ -1778,6 +1782,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,
@@ -1785,7 +1791,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);
SECOidTag ssl3_AuthTypeToOID(SSLAuthType hashType);
SSLHashType ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme);
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
index 3a5d7fe45..422d7ae37 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
@@ -399,6 +399,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);
@@ -490,6 +494,10 @@ ssl_DestroySocketContents(sslSocket *ss)
tls13_ReleaseAntiReplayContext(ss->antiReplay);
tls13_DestroyPsk(ss->psk);
+ /* 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_DestroyEchConfigs(&ss->echConfigs);
SECKEY_DestroyPrivateKey(ss->echPrivKey);
@@ -2564,6 +2572,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;
}
@@ -4235,6 +4245,8 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
ss->echPubKey = NULL;
ss->antiReplay = NULL;
ss->psk = NULL;
+ ss->peerSignatureSchemes = NULL;
+ ss->peerSignatureSchemeCount = 0;
if (makeLocks) {
rv = ssl_MakeLocks(ss);
diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c
index 67f89e908..7782760e0 100644
--- a/lib/ssl/tls13con.c
+++ b/lib/ssl/tls13con.c
@@ -1678,7 +1678,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;
diff --git a/lib/ssl/tls13subcerts.c b/lib/ssl/tls13subcerts.c
index 6f164c302..1fd79ae20 100644
--- a/lib/ssl/tls13subcerts.c
+++ b/lib/ssl/tls13subcerts.c
@@ -220,7 +220,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;
}
diff --git a/mach b/mach
index a3ef38dac..f34eb5654 100755
--- a/mach
+++ b/mach
@@ -176,7 +176,8 @@ class covAction(argparse.Action):
env = {
"GTESTFILTER": "*", # Prevent parallel test runs.
"ASAN_OPTIONS": "coverage=1:coverage_dir=" + outdir,
- "NSS_DEFAULT_DB_TYPE": "dbm"
+ "NSS_DEFAULT_DB_TYPE": "sql",
+ "NSS_DISABLE_UNLOAD": "1"
}
run_tests("ssl_gtests", env=env, silent=True)
diff --git a/tests/ssl/ssl.sh b/tests/ssl/ssl.sh
index acd4c8cda..0fa24a2c6 100755
--- a/tests/ssl/ssl.sh
+++ b/tests/ssl/ssl.sh
@@ -471,7 +471,7 @@ ssl_auth()
elif [ "$ectype" = "SNI" -a "$NORM_EXT" = "Extended Test" ] ; then
echo "$SCRIPTNAME: skipping $testname for $NORM_EXT"
else
- 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" `
if [ "$ectype" = "SNI" ]; then
cparam=`echo $cparam | sed -e "s/Host/$HOST/g" -e "s/Dom/$DOMSUF/g" `
sparam=`echo $sparam | sed -e "s/Host/$HOST/g" -e "s/Dom/$DOMSUF/g" `
@@ -483,7 +483,7 @@ ssl_auth()
SERVER_VMIN=tls1.0
SERVER_VMAX=tls1.3
fi
- start_selfserv `echo "$sparam" | sed -e 's,_, ,g'`
+ start_selfserv `echo "$sparam" | sed -e 's;\([^\\]\)_;\1 ;g' -e 's;\\\\_;_;g'`
echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\"
echo " ${cparam} < ${REQUEST_FILE}"
@@ -754,7 +754,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
@@ -763,14 +766,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 ]
@@ -778,8 +791,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}"
@@ -1246,7 +1259,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 \\"
diff --git a/tests/ssl/sslauth.txt b/tests/ssl/sslauth.txt
index 70e498962..61e4a6c6d 100644
--- a/tests/ssl/sslauth.txt
+++ b/tests/ssl/sslauth.txt
@@ -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
#