diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c index 1784c9ee3a..6c00d3a15d 100644 --- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -233,7 +233,9 @@ PrintParameterUsage() " ecdsa_secp521r1_sha512,\n" " rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n" " rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n" - "-Z enable 0-RTT (for TLS 1.3; also use -u)\n", + "-Z enable 0-RTT (for TLS 1.3; also use -u)\n" + "-E enable post-handshake authentication\n" + " (for TLS 1.3; only has an effect with 3 or more -r options)\n", stderr); } @@ -804,6 +806,7 @@ PRBool failedToNegotiateName = PR_FALSE; PRBool enableExtendedMasterSecret = PR_FALSE; PRBool zeroRTT = PR_FALSE; PRBool enableALPN = PR_FALSE; +PRBool enablePostHandshakeAuth = PR_FALSE; SSLNamedGroup *enabledGroups = NULL; unsigned int enabledGroupsCount = 0; const SSLSignatureScheme *enabledSigSchemes = NULL; @@ -1431,15 +1434,28 @@ handle_connection(PRFileDesc *tcp_sock, PRFileDesc *model_sock) errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE"); break; } - rv = SSL_ReHandshake(ssl_sock, PR_TRUE); - if (rv != 0) { - errWarn("SSL_ReHandshake"); - break; - } - rv = SSL_ForceHandshake(ssl_sock); - if (rv < 0) { - errWarn("SSL_ForceHandshake"); - break; + if (enablePostHandshakeAuth) { + rv = SSL_SendCertificateRequest(ssl_sock); + if (rv != SECSuccess) { + errWarn("SSL_SendCertificateRequest"); + break; + } + rv = SSL_ForceHandshake(ssl_sock); + if (rv != SECSuccess) { + errWarn("SSL_ForceHandshake"); + break; + } + } else { + rv = SSL_ReHandshake(ssl_sock, PR_TRUE); + if (rv != 0) { + errWarn("SSL_ReHandshake"); + break; + } + rv = SSL_ForceHandshake(ssl_sock); + if (rv < 0) { + errWarn("SSL_ForceHandshake"); + break; + } } } } @@ -1948,6 +1964,16 @@ server_main( } } + if (enablePostHandshakeAuth) { + if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) { + errExit("You tried enabling post-handshake auth without enabling TLS 1.3!"); + } + rv = SSL_OptionSet(model_sock, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); + if (rv != SECSuccess) { + errExit("error enabling post-handshake auth"); + } + } + if (enableALPN) { PRUint8 alpnVal[] = { 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 }; @@ -2223,7 +2249,7 @@ main(int argc, char **argv) ** in 3.28, please leave some time before resuing those. ** 'z' was removed in 3.39. */ optstate = PL_CreateOptState(argc, argv, - "2:A:C:DGH:I:J:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:y"); + "2:A:C:DEGH:I:J:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:y"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { ++optionsFound; switch (optstate->option) { @@ -2243,6 +2269,11 @@ main(int argc, char **argv) case 'D': noDelay = PR_TRUE; break; + + case 'E': + enablePostHandshakeAuth = PR_TRUE; + break; + case 'H': configureDHE = (PORT_Atoi(optstate->value) != 0); break; diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index 520eeff648..bc0cbfa76e 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -221,7 +221,7 @@ PrintUsageHeader() fprintf(stderr, "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n" " [-D | -d certdir] [-C] [-b | -R root-module] \n" - " [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n" + " [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z] [-E]\n" " [-V [min-version]:[max-version]] [-K] [-T] [-U]\n" " [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n" " [-I groups] [-J signatureschemes]\n" @@ -311,6 +311,9 @@ PrintParameterUsage() fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}"); fprintf(stderr, "%-20s Exit after handshake\n", "-Q"); fprintf(stderr, "%-20s Encrypted SNI Keys\n", "-N"); + fprintf(stderr, "%-20s Enable post-handshake authentication\n" + "%-20s for TLS 1.3; need to specify -n\n", + "-E", ""); } static void @@ -989,6 +992,7 @@ PRBool requestToExit = PR_FALSE; char *versionString = NULL; PRBool handshakeComplete = PR_FALSE; char *encryptedSNIKeys = NULL; +PRBool enablePostHandshakeAuth = PR_FALSE; static int writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb) @@ -1410,6 +1414,15 @@ run() goto done; } + if (enablePostHandshakeAuth) { + rv = SSL_OptionSet(s, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); + if (rv != SECSuccess) { + SECU_PrintError(progName, "error enabling post-handshake auth"); + error = 1; + goto done; + } + } + if (enabledGroups) { rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount); if (rv < 0) { @@ -1707,7 +1720,7 @@ main(int argc, char **argv) * Please leave some time before reusing these. */ optstate = PL_CreateOptState(argc, argv, - "46A:CDFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:"); + "46A:CDEFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:"); while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': @@ -1738,6 +1751,10 @@ main(int argc, char **argv) openDB = PR_FALSE; break; + case 'E': + enablePostHandshakeAuth = PR_TRUE; + break; + case 'F': if (serverCertAuth.testFreshStatusFromSideChannel) { /* parameter given twice or more */ @@ -1988,6 +2005,11 @@ main(int argc, char **argv) exit(1); } + if (enablePostHandshakeAuth && !nickname) { + fprintf(stderr, "%s: -E requires the use of -n\n", progName); + exit(1); + } + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); PK11_SetPasswordFunc(SECU_GetModulePassword); diff --git a/security/nss/cpputil/tls_parser.h b/security/nss/cpputil/tls_parser.h index 881c5268ec..2aa7a0ecdc 100644 --- a/security/nss/cpputil/tls_parser.h +++ b/security/nss/cpputil/tls_parser.h @@ -52,6 +52,7 @@ const uint8_t kTlsAlertInappropriateFallback = 86; const uint8_t kTlsAlertMissingExtension = 109; const uint8_t kTlsAlertUnsupportedExtension = 110; const uint8_t kTlsAlertUnrecognizedName = 112; +const uint8_t kTlsAlertCertificateRequired = 116; const uint8_t kTlsAlertNoApplicationProtocol = 120; const uint8_t kTlsFakeChangeCipherSpec[] = { diff --git a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc index 8db23e74e1..473932655f 100644 --- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc @@ -320,6 +320,46 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) { EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); } +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBeforeKeyUpdate) { + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + Connect(); + // Send CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + // Send KeyUpdate. + EXPECT_EQ(SECFailure, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE)); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); +} + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDuringClientKeyUpdate) { + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + Connect(); + CheckEpochs(3, 3); + // Send CertificateRequest from server. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + // Send KeyUpdate from client. + EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_TRUE)); + server_->SendData(50); // server sends CertificateRequest + client_->SendData(50); // client sends KeyUpdate + server_->ReadBytes(50); // server receives KeyUpdate and defers response + CheckEpochs(4, 3); + client_->ReadBytes(50); // client receives CertificateRequest + client_->SendData( + 50); // client sends Certificate, CertificateVerify, Finished + server_->ReadBytes( + 50); // server receives Certificate, CertificateVerify, Finished + client_->CheckEpochs(3, 4); + server_->CheckEpochs(4, 4); + server_->SendData(50); // server sends KeyUpdate + client_->ReadBytes(50); // client receives KeyUpdate + client_->CheckEpochs(4, 4); +} + TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) { client_->SetupClientAuth(); Connect(); @@ -454,6 +494,9 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) { client_->SetupClientAuth(); EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + EXPECT_EQ(SECSuccess, + SSL_OptionSet(server_->ssl_fd(), SSL_REQUIRE_CERTIFICATE, + SSL_REQUIRE_ALWAYS)); // Client to decline the certificate request. EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook( @@ -472,10 +515,13 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) { // Send CertificateRequest. EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); - server_->SendData(50); - client_->ReadBytes(50); - client_->SendData(50); - server_->ReadBytes(50); + server_->SendData(50); // send Certificate Request + client_->ReadBytes(50); // read Certificate Request + client_->SendData(50); // send empty Certificate+Finished + server_->ExpectSendAlert(kTlsAlertCertificateRequired); + server_->ReadBytes(50); // read empty Certificate+Finished + server_->ExpectReadWriteError(); + server_->SendData(50); // send alert // AuthCertificateCallback is not called, because the client sends // an empty certificate_list. EXPECT_EQ(0U, called); diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c index 4830bc111f..142cb5ddaa 100644 --- a/security/nss/lib/softoken/sdb.c +++ b/security/nss/lib/softoken/sdb.c @@ -941,9 +941,12 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, blobSize = sqlite3_column_bytes(stmt, i); blobData = sqlite3_column_blob(stmt, i); if (blobData == NULL) { + /* PKCS 11 requires that get attributes process all the + * attributes in the template, marking the attributes with + * issues with -1. Mark the error but continue */ template[i].ulValueLen = -1; error = CKR_ATTRIBUTE_TYPE_INVALID; - break; + continue; } /* If the blob equals our explicit NULL value, then the * attribute is a NULL. */ @@ -954,9 +957,10 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, } if (template[i].pValue) { if (template[i].ulValueLen < blobSize) { + /* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */ template[i].ulValueLen = -1; error = CKR_BUFFER_TOO_SMALL; - break; + continue; } PORT_Memcpy(template[i].pValue, blobData, blobSize); } diff --git a/security/nss/lib/ssl/SSLerrs.h b/security/nss/lib/ssl/SSLerrs.h index 5e428406a2..a6047e6dbb 100644 --- a/security/nss/lib/ssl/SSLerrs.h +++ b/security/nss/lib/ssl/SSLerrs.h @@ -564,3 +564,6 @@ ER3(SSL_ERROR_MISSING_ESNI_EXTENSION, (SSL_ERROR_BASE + 178), ER3(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, (SSL_ERROR_BASE + 179), "SSL received an unexpected record type.") + +ER3(SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT, (SSL_ERROR_BASE + 181), + "SSL received a certificate_required alert.") diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 9385e52638..142c8bccf1 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -2683,7 +2683,12 @@ ssl3_HandleNoCertificate(sslSocket *ss) PRFileDesc *lower; ssl_UncacheSessionID(ss); - SSL3_SendAlert(ss, alert_fatal, bad_certificate); + + if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { + SSL3_SendAlert(ss, alert_fatal, certificate_required); + } else { + SSL3_SendAlert(ss, alert_fatal, bad_certificate); + } lower = ss->fd->lower; #ifdef _WIN32 @@ -2919,6 +2924,9 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) case no_certificate: error = SSL_ERROR_NO_CERTIFICATE; break; + case certificate_required: + error = SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT; + break; case bad_certificate: error = SSL_ERROR_BAD_CERT_ALERT; break; @@ -3719,6 +3727,10 @@ ssl3_RestartHandshakeHashes(sslSocket *ss) PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE); ss->ssl3.hs.sha = NULL; } + if (ss->ssl3.hs.shaPostHandshake) { + PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE); + ss->ssl3.hs.shaPostHandshake = NULL; + } } /* @@ -3778,6 +3790,24 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l return rv; } +SECStatus +ssl3_UpdatePostHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l) +{ + SECStatus rv = SECSuccess; + + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + + PRINT_BUF(90, (ss, "post handshake hash input:", b, l)); + + PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_single); + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); + rv = PK11_DigestOp(ss->ssl3.hs.shaPostHandshake, b, l); + if (rv != SECSuccess) { + PORT_SetError(SSL_ERROR_DIGEST_FAILURE); + } + return rv; +} + SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss, SSLHandshakeType t, PRUint32 length) { @@ -11623,7 +11653,8 @@ ssl3_FinishHandshake(sslSocket *ss) SECStatus ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct, PRUint32 dtlsSeq, - const PRUint8 *b, PRUint32 length) + const PRUint8 *b, PRUint32 length, + sslUpdateHandshakeHashes updateHashes) { PRUint8 hdr[4]; PRUint8 dtlsData[8]; @@ -11636,7 +11667,7 @@ ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct, hdr[2] = (PRUint8)(length >> 8); hdr[3] = (PRUint8)(length); - rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)hdr, 4); + rv = updateHashes(ss, (unsigned char *)hdr, 4); if (rv != SECSuccess) return rv; /* err code already set. */ @@ -11656,14 +11687,13 @@ ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct, dtlsData[6] = (PRUint8)(length >> 8); dtlsData[7] = (PRUint8)(length); - rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)dtlsData, - sizeof(dtlsData)); + rv = updateHashes(ss, (unsigned char *)dtlsData, sizeof(dtlsData)); if (rv != SECSuccess) return rv; /* err code already set. */ } /* The message body */ - rv = ssl3_UpdateHandshakeHashes(ss, b, length); + rv = updateHashes(ss, b, length); if (rv != SECSuccess) return rv; /* err code already set. */ @@ -11675,7 +11705,15 @@ ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType ct, const PRUint8 *b, PRUint32 length) { return ssl_HashHandshakeMessageInt(ss, ct, ss->ssl3.hs.recvMessageSeq, - b, length); + b, length, ssl3_UpdateHandshakeHashes); +} + +SECStatus +ssl_HashPostHandshakeMessage(sslSocket *ss, SSLHandshakeType ct, + const PRUint8 *b, PRUint32 length) +{ + return ssl_HashHandshakeMessageInt(ss, ct, ss->ssl3.hs.recvMessageSeq, + b, length, ssl3_UpdatePostHandshakeHashes); } /* Called from ssl3_HandleHandshake() when it has gathered a complete ssl3 @@ -11714,9 +11752,11 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, break; default: - rv = ssl_HashHandshakeMessage(ss, ss->ssl3.hs.msg_type, b, length); - if (rv != SECSuccess) { - return SECFailure; + if (!tls13_IsPostHandshake(ss)) { + rv = ssl_HashHandshakeMessage(ss, ss->ssl3.hs.msg_type, b, length); + if (rv != SECSuccess) { + return SECFailure; + } } } @@ -13129,6 +13169,9 @@ ssl3_DestroySSL3Info(sslSocket *ss) if (ss->ssl3.hs.sha) { PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE); } + if (ss->ssl3.hs.shaPostHandshake) { + PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE); + } if (ss->ssl3.hs.messages.buf) { sslBuffer_Clear(&ss->ssl3.hs.messages); } diff --git a/security/nss/lib/ssl/ssl3prot.h b/security/nss/lib/ssl/ssl3prot.h index bfaa10d3fb..ffe8373011 100644 --- a/security/nss/lib/ssl/ssl3prot.h +++ b/security/nss/lib/ssl/ssl3prot.h @@ -74,6 +74,7 @@ typedef enum { unrecognized_name = 112, bad_certificate_status_response = 113, bad_certificate_hash_value = 114, + certificate_required = 116, no_application_protocol = 120, /* invalid alert */ diff --git a/security/nss/lib/ssl/sslencode.c b/security/nss/lib/ssl/sslencode.c index e508804515..e59e758ff9 100644 --- a/security/nss/lib/ssl/sslencode.c +++ b/security/nss/lib/ssl/sslencode.c @@ -10,6 +10,7 @@ #include "prnetdb.h" #include "ssl.h" #include "sslimpl.h" +#include "sslproto.h" /* Helper function to encode an unsigned integer into a buffer. */ static void @@ -263,9 +264,11 @@ ssl3_AppendHandshake(sslSocket *ss, const void *void_src, unsigned int bytes) } PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char *)void_src, bytes)); - rv = ssl3_UpdateHandshakeHashes(ss, src, bytes); - if (rv != SECSuccess) - return SECFailure; /* error code set by ssl3_UpdateHandshakeHashes */ + if (!ss->firstHsDone || ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { + rv = ssl3_UpdateHandshakeHashes(ss, src, bytes); + if (rv != SECSuccess) + return SECFailure; /* error code set by ssl3_UpdateHandshakeHashes */ + } while (bytes > room) { if (room > 0) diff --git a/security/nss/lib/ssl/sslerr.h b/security/nss/lib/ssl/sslerr.h index b8f4e30eaf..9e72da28fe 100644 --- a/security/nss/lib/ssl/sslerr.h +++ b/security/nss/lib/ssl/sslerr.h @@ -269,6 +269,7 @@ typedef enum { SSL_ERROR_MISSING_ESNI_EXTENSION = (SSL_ERROR_BASE + 178), SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE = (SSL_ERROR_BASE + 179), SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION = (SSL_ERROR_BASE + 180), + SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT = (SSL_ERROR_BASE + 181), SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 575f4964a4..b70ddc9558 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -144,6 +144,11 @@ typedef enum { ticket_allow_psk_sign_auth = 16 } TLS13SessionTicketFlags; +typedef enum { + update_not_requested = 0, + update_requested = 1 +} tls13KeyUpdateRequest; + struct sslNamedGroupDefStr { /* The name is the value that is encoded on the wire in TLS. */ SSLNamedGroup name; @@ -610,6 +615,7 @@ typedef struct SSL3HandshakeStateStr { * TLS 1.2 and later use only |sha|, for SHA-256. */ PK11Context *md5; PK11Context *sha; + PK11Context *shaPostHandshake; SSLSignatureScheme signatureScheme; const ssl3KEADef *kea_def; ssl3CipherSuite cipher_suite; @@ -743,6 +749,11 @@ struct ssl3StateStr { * update is initiated locally. */ PRBool peerRequestedKeyUpdate; + /* This is true if we deferred sending a key update as + * post-handshake auth is in progress. */ + PRBool keyUpdateDeferred; + tls13KeyUpdateRequest deferredKeyUpdateRequest; + /* This is true after the server requests client certificate; * false after the client certificate is received. Used by the * server. */ @@ -1213,15 +1224,24 @@ extern SECStatus Null_Cipher(void *ctx, unsigned char *output, unsigned int *out unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen); extern void ssl3_RestartHandshakeHashes(sslSocket *ss); +typedef SECStatus (*sslUpdateHandshakeHashes)(sslSocket *ss, + const unsigned char *b, + unsigned int l); extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l); +extern SECStatus ssl3_UpdatePostHandshakeHashes(sslSocket *ss, + const unsigned char *b, + unsigned int l); SECStatus ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type, PRUint32 dtlsSeq, - const PRUint8 *b, PRUint32 length); + const PRUint8 *b, PRUint32 length, + sslUpdateHandshakeHashes cb); SECStatus ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type, const PRUint8 *b, PRUint32 length); +SECStatus ssl_HashPostHandshakeMessage(sslSocket *ss, SSLHandshakeType type, + const PRUint8 *b, PRUint32 length); /* Returns PR_TRUE if we are still waiting for the server to complete its * response to our client second round. Once we've received the Finished from diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index 79634e4039..14320fa190 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -720,7 +720,8 @@ tls13_CheckKeyUpdate(sslSocket *ss, SSLSecretDirection dir) ssl3CipherSpec *spec; sslSequenceNumber seqNum; sslSequenceNumber margin; - SECStatus rv; + tls13KeyUpdateRequest keyUpdateRequest; + SECStatus rv = SECSuccess; /* Bug 1413368: enable for DTLS */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 || IS_DTLS(ss)) { @@ -755,9 +756,15 @@ tls13_CheckKeyUpdate(sslSocket *ss, SSLSecretDirection dir) SSL_TRC(5, ("%d: SSL[%d]: automatic key update at %llx for %s cipher spec", SSL_GETPID(), ss->fd, seqNum, (dir == ssl_secret_read) ? "read" : "write")); + keyUpdateRequest = (dir == ssl_secret_read) ? update_requested : update_not_requested; ssl_GetSSL3HandshakeLock(ss); - rv = tls13_SendKeyUpdate(ss, (dir == ssl_secret_read) ? update_requested : update_not_requested, - dir == ssl_secret_write /* buffer */); + if (ss->ssl3.clientCertRequested) { + ss->ssl3.keyUpdateDeferred = PR_TRUE; + ss->ssl3.deferredKeyUpdateRequest = keyUpdateRequest; + } else { + rv = tls13_SendKeyUpdate(ss, keyUpdateRequest, + dir == ssl_secret_write /* buffer */); + } ssl_ReleaseSSL3HandshakeLock(ss); return rv; } diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index 7046180700..88bc618b34 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -259,6 +259,12 @@ tls13_CheckHsState(sslSocket *ss, int err, const char *error_name, return SECFailure; } +PRBool +tls13_IsPostHandshake(const sslSocket *ss) +{ + return ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && ss->firstHsDone; +} + SSLHashType tls13_GetHashForCipherSuite(ssl3CipherSuite suite) { @@ -682,8 +688,9 @@ tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, PRBool buffer) : "not requested")); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert(!ss->sec.isServer || !ss->ssl3.clientCertRequested); - if (!ss->firstHsDone) { + if (!tls13_IsPostHandshake(ss)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } @@ -741,11 +748,16 @@ SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate) return SECFailure; } - if (!ss->firstHsDone) { + if (!tls13_IsPostHandshake(ss)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } + if (ss->ssl3.clientCertRequested) { + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; + } + rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS, idle_handshake); if (rv != SECSuccess) { @@ -786,7 +798,7 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->firstHsDone); - if (!ss->firstHsDone) { + if (!tls13_IsPostHandshake(ss)) { FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE, unexpected_message); return SECFailure; } @@ -820,7 +832,12 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) if (update == update_requested) { PRBool sendUpdate; - if (ss->ssl3.peerRequestedKeyUpdate) { + if (ss->ssl3.clientCertRequested) { + /* Post-handshake auth is in progress; defer sending a key update. */ + ss->ssl3.keyUpdateDeferred = PR_TRUE; + ss->ssl3.deferredKeyUpdateRequest = update_not_requested; + sendUpdate = PR_FALSE; + } else if (ss->ssl3.peerRequestedKeyUpdate) { /* Only send an update if we have sent with the current spec. This * prevents us from being forced to crank forward pointlessly. */ ssl_GetSpecReadLock(ss); @@ -857,7 +874,7 @@ SSLExp_SendCertificateRequest(PRFileDesc *fd) return SECFailure; } - if (!ss->firstHsDone || ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { + if (!tls13_IsPostHandshake(ss)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -2195,10 +2212,20 @@ tls13_SendCertificateRequest(sslSocket *ss) { SECStatus rv; sslBuffer extensionBuf = SSL_BUFFER_EMPTY; + unsigned int offset = 0; SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request", SSL_GETPID(), ss->fd)); + if (ss->firstHsDone) { + PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL); + ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha); + if (ss->ssl3.hs.shaPostHandshake == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } + } + rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate_request); if (rv != SECSuccess) { return SECFailure; /* Code already set. */ @@ -2222,6 +2249,8 @@ tls13_SendCertificateRequest(sslSocket *ss) FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error); goto loser; } + + offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf); } rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_request, @@ -2245,6 +2274,15 @@ tls13_SendCertificateRequest(sslSocket *ss) goto loser; /* err set by AppendHandshake. */ } + if (ss->firstHsDone) { + rv = ssl3_UpdatePostHandshakeHashes(ss, + SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset, + SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); + if (rv != SECSuccess) { + goto loser; + } + } + sslBuffer_Clear(&extensionBuf); return SECSuccess; @@ -2410,7 +2448,19 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - if (ss->firstHsDone) { + if (tls13_IsPostHandshake(ss)) { + PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL); + ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha); + if (ss->ssl3.hs.shaPostHandshake == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate_request, b, length); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + return SECFailure; + } + /* clean up anything left from previous handshake. */ if (ss->ssl3.clientCertChain != NULL) { CERT_DestroyCertificateList(ss->ssl3.clientCertChain); @@ -2441,7 +2491,7 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) /* Unless it is a post-handshake client auth, the certificate * request context must be empty. */ - if (!ss->firstHsDone && context.len > 0) { + if (!tls13_IsPostHandshake(ss) && context.len > 0) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter); return SECFailure; } @@ -2501,6 +2551,9 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } PORT_Assert(ss->ssl3.hs.ws == idle_handshake); + PORT_Assert(ss->ssl3.hs.shaPostHandshake != NULL); + PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE); + ss->ssl3.hs.shaPostHandshake = NULL; } else { TLS13_SET_HS_STATE(ss, wait_server_cert); } @@ -3058,6 +3111,15 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); dtls_ReceivedFirstMessageInFlight(ss); } + + if (ss->firstHsDone) { + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate, b, length); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + /* Process the context string */ rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); if (rv != SECSuccess) @@ -3615,7 +3677,11 @@ tls13_ComputeHandshakeHashes(sslSocket *ss, SSL3Hashes *hashes) goto loser; } } else { - ctx = PK11_CloneContext(ss->ssl3.hs.sha); + if (ss->firstHsDone) { + ctx = PK11_CloneContext(ss->ssl3.hs.shaPostHandshake); + } else { + ctx = PK11_CloneContext(ss->ssl3.hs.sha); + } if (!ctx) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); return SECFailure; @@ -4069,7 +4135,11 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - rv = ssl_HashHandshakeMessage(ss, ssl_hs_certificate_verify, b, length); + if (ss->firstHsDone) { + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate_verify, b, length); + } else { + rv = ssl_HashHandshakeMessage(ss, ssl_hs_certificate_verify, b, length); + } if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -4129,10 +4199,6 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) } } - if (ss->ssl3.clientCertRequested) { - PORT_Assert(ss->sec.isServer); - ss->ssl3.clientCertRequested = PR_FALSE; - } TLS13_SET_HS_STATE(ss, wait_finished); return SECSuccess; @@ -4393,7 +4459,11 @@ tls13_CommonHandleFinished(sslSocket *ss, PK11SymKey *key, return SECFailure; } - rv = ssl_HashHandshakeMessage(ss, ssl_hs_finished, b, length); + if (ss->firstHsDone) { + rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_finished, b, length); + } else { + rv = ssl_HashHandshakeMessage(ss, ssl_hs_finished, b, length); + } if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -4443,6 +4513,22 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) if (ss->firstHsDone) { TLS13_SET_HS_STATE(ss, idle_handshake); + + PORT_Assert(ss->ssl3.hs.shaPostHandshake != NULL); + PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE); + ss->ssl3.hs.shaPostHandshake = NULL; + + ss->ssl3.clientCertRequested = PR_FALSE; + + if (ss->ssl3.keyUpdateDeferred) { + rv = tls13_SendKeyUpdate(ss, ss->ssl3.deferredKeyUpdateRequest, + PR_FALSE); + if (rv != SECSuccess) { + return SECFailure; /* error is set. */ + } + ss->ssl3.keyUpdateDeferred = PR_FALSE; + } + return SECSuccess; } @@ -4525,11 +4611,16 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, SSL3AlertDescription *sendAlert) { SECStatus rv; + unsigned int offset = 0; PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); *sendAlert = internal_error; + if (ss->firstHsDone) { + offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf); + } + if (ss->ssl3.sendEmptyCert) { ss->ssl3.sendEmptyCert = PR_FALSE; rv = ssl3_SendEmptyCertificate(ss); @@ -4543,6 +4634,16 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, return SECFailure; /* error code is set. */ } } + + if (ss->firstHsDone) { + rv = ssl3_UpdatePostHandshakeHashes(ss, + SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset, + SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); + if (rv != SECSuccess) { + return SECFailure; /* error code is set. */ + } + } + if (ss->ssl3.hs.clientCertRequested) { SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); if (ss->xtnData.certReqAuthorities.arena) { @@ -4555,12 +4656,25 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, } if (sendClientCert) { + if (ss->firstHsDone) { + offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf); + } + rv = tls13_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey); SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); ss->ssl3.clientPrivateKey = NULL; if (rv != SECSuccess) { return SECFailure; /* err is set. */ } + + if (ss->firstHsDone) { + rv = ssl3_UpdatePostHandshakeHashes(ss, + SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset, + SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); + if (rv != SECSuccess) { + return SECFailure; /* error is set. */ + } + } } rv = tls13_SendFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret); @@ -4825,8 +4939,7 @@ SSLExp_SendSessionTicket(PRFileDesc *fd, const PRUint8 *token, return SECFailure; } - if (!ss->sec.isServer || !ss->firstHsDone || - ss->version < SSL_LIBRARY_VERSION_TLS_1_3 || + if (!ss->sec.isServer || !tls13_IsPostHandshake(ss) || tokenLen > 0xffff) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -4862,7 +4975,7 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) if (rv != SECSuccess) { return SECFailure; } - if (!ss->firstHsDone || ss->sec.isServer) { + if (!tls13_IsPostHandshake(ss) || ss->sec.isServer) { FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET, unexpected_message); return SECFailure; diff --git a/security/nss/lib/ssl/tls13con.h b/security/nss/lib/ssl/tls13con.h index ed4c4ec787..4968ac3619 100644 --- a/security/nss/lib/ssl/tls13con.h +++ b/security/nss/lib/ssl/tls13con.h @@ -18,11 +18,6 @@ typedef enum { tls13_extension_unknown } tls13ExtensionStatus; -typedef enum { - update_not_requested = 0, - update_requested = 1 -} tls13KeyUpdateRequest; - #define TLS13_MAX_FINISHED_SIZE 64 SECStatus tls13_UnprotectRecord( @@ -47,6 +42,8 @@ PRBool tls13_InHsState(sslSocket *ss, ...); #define TLS13_IN_HS_STATE(ss, ...) \ tls13_InHsState(ss, __VA_ARGS__, wait_invalid) +PRBool tls13_IsPostHandshake(const sslSocket *ss); + SSLHashType tls13_GetHashForCipherSuite(ssl3CipherSuite suite); SSLHashType tls13_GetHash(const sslSocket *ss); unsigned int tls13_GetHashSizeForHash(SSLHashType hash); diff --git a/security/nss/lib/ssl/tls13hashstate.c b/security/nss/lib/ssl/tls13hashstate.c index cc0ed286b0..53d3738f0c 100644 --- a/security/nss/lib/ssl/tls13hashstate.c +++ b/security/nss/lib/ssl/tls13hashstate.c @@ -157,7 +157,8 @@ tls13_RecoverHashState(sslSocket *ss, /* Now reinject the message. */ SSL_ASSERT_HASHES_EMPTY(ss); rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0, - SSL_READER_CURRENT(&reader), hashLen); + SSL_READER_CURRENT(&reader), hashLen, + ssl3_UpdateHandshakeHashes); if (rv != SECSuccess) { return SECFailure; } @@ -173,7 +174,8 @@ tls13_RecoverHashState(sslSocket *ss, rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_server_hello, 0, SSL_BUFFER_BASE(&messageBuf), - SSL_BUFFER_LEN(&messageBuf)); + SSL_BUFFER_LEN(&messageBuf), + ssl3_UpdateHandshakeHashes); sslBuffer_Clear(&messageBuf); if (rv != SECSuccess) { return SECFailure; diff --git a/security/nss/tests/ssl/ssl.sh b/security/nss/tests/ssl/ssl.sh index 525855e100..3c3d4206b2 100644 --- a/security/nss/tests/ssl/ssl.sh +++ b/security/nss/tests/ssl/ssl.sh @@ -220,18 +220,20 @@ start_selfserv() else RSA_OPTIONS="-n ${HOSTADDR}-rsa-pss" fi + SERVER_VMIN=${SERVER_VMIN-ssl3} + SERVER_VMAX=${SERVER_VMAX-tls1.2} echo "selfserv starting at `date`" echo "selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \\" echo " ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID}\\" - echo " -V ssl3:tls1.2 $verbose -H 1 &" + echo " -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 &" if [ ${fileout} -eq 1 ]; then ${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \ - ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ssl3:tls1.2 $verbose -H 1 \ + ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 \ > ${SERVEROUTFILE} 2>&1 & RET=$? else ${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \ - ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ssl3:tls1.2 $verbose -H 1 & + ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 & RET=$? fi @@ -388,6 +390,8 @@ ssl_auth() do echo "${testname}" | grep "don't require client auth" > /dev/null CAUTH=$? + echo "${testname}" | grep "TLS 1.3" > /dev/null + TLS13=$? if [ "${CLIENT_MODE}" = "fips" -a "${CAUTH}" -eq 0 ] ; then echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" @@ -399,6 +403,13 @@ ssl_auth() 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" ` fi + # SSL3 cannot be used with TLS 1.3 + unset SERVER_VMIN + unset SERVER_VMAX + if [ $TLS13 -eq 0 ] ; then + SERVER_VMIN=tls1.0 + SERVER_VMAX=tls1.3 + fi start_selfserv `echo "$sparam" | sed -e 's,_, ,g'` echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" @@ -669,9 +680,18 @@ ssl_crl_ssl() ignore_blank_lines ${SSLAUTH} | \ while read ectype value sparam cparam testname do + echo "${testname}" | grep "TLS 1.3" > /dev/null + TLS13=$? if [ "$ectype" = "SNI" ]; then continue else + # SSL3 cannot be used with TLS 1.3 + unset SERVER_VMIN + unset SERVER_VMAX + if [ $TLS13 -eq 0 ] ; then + SERVER_VMIN=tls1.0 + SERVER_VMAX=tls1.3 + fi servarg=`echo $sparam | awk '{r=split($0,a,"-r") - 1;print r;}'` pwd=`echo $cparam | grep nss` user=`echo $cparam | grep TestUser` @@ -1039,7 +1059,7 @@ ssl_crl_cache() rm -f ${SSLAUTH_TMP} echo ${SSLAUTH_TMP} - grep -- " $SERV_ARG " ${SSLAUTH} | grep -v "^#" | grep -v none | grep -v bogus > ${SSLAUTH_TMP} + grep -- " $SERV_ARG " ${SSLAUTH} | grep -v "^#" | grep -v none | grep -v bogus | grep -v 'post hs' > ${SSLAUTH_TMP} echo $? while [ $? -eq 0 -a -f ${SSLAUTH_TMP} ] do diff --git a/security/nss/tests/ssl/sslauth.txt b/security/nss/tests/ssl/sslauth.txt index 82d1ddea48..a84630f066 100644 --- a/security/nss/tests/ssl/sslauth.txt +++ b/security/nss/tests/ssl/sslauth.txt @@ -38,6 +38,10 @@ noECC 1 -r_-r_-r_-r -V_ssl3:ssl3_-w_nss_-n_none SSL3 Require client auth on 2nd hs (client does not provide auth) noECC 1 -r_-r_-r_-r -V_ssl3:ssl3_-n_TestUser_-w_bogus SSL3 Require client auth on 2nd hs (bad password) noECC 0 -r_-r_-r_-r -V_ssl3:ssl3_-n_TestUser_-w_nss SSL3 Require client auth on 2nd hs (client auth) + noECC 0 -r_-r_-r_-E -V_tls1.3:tls1.3_-E_-n_TestUser_-w_nss TLS 1.3 Request don't require client auth on post hs (client auth) + noECC 0 -r_-r_-r_-r_-E -V_tls1.3:tls1.3_-E_-n_TestUser_-w_nss TLS 1.3 Require client auth on post hs (client auth) + 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) # # Use EC cert for client authentication #