summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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..e60ded534 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.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}
+
diff --git a/automation/abi-check/expected-report-libssl3.so.txt b/automation/abi-check/expected-report-libssl3.so.txt
index e69de29bb..6c8b7b07d 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.77}
+ 'function SECStatus SSL_FilterClientCertListBySocket(PRFileDesc*, CERTCertList*)' {SSL_FilterClientCertListBySocket@@NSS_3.77}
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..dd352d81a 100644
--- a/lib/nss/nss.def
+++ b/lib/nss/nss.def
@@ -1238,3 +1238,12 @@ PK11_SlotGetLastFIPSStatus;
;+ local:
;+ *;
;+};
+;+NSS_3.77 { # NSS 3.77 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..14fc2b960 100644
--- a/lib/ssl/ssl.def
+++ b/lib/ssl/ssl.def
@@ -240,3 +240,10 @@ SSL_GetExperimentalAPI;
;+ local:
;+*;
;+};
+;+NSS_3.77 { # NSS 3.77 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
#