summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/sslsecur.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/sslsecur.c')
-rw-r--r--security/nss/lib/ssl/sslsecur.c105
1 files changed, 57 insertions, 48 deletions
diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c
index c011b66a1..14320fa19 100644
--- a/security/nss/lib/ssl/sslsecur.c
+++ b/security/nss/lib/ssl/sslsecur.c
@@ -16,32 +16,7 @@
#include "nss.h" /* for NSS_RegisterShutdown */
#include "prinit.h" /* for PR_CallOnceWithArg */
-/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock.
- *
- * Currently, the list of functions called through ss->handshake is:
- *
- * In sslsocks.c:
- * SocksGatherRecord
- * SocksHandleReply
- * SocksStartGather
- *
- * In sslcon.c:
- * ssl_GatherRecord1stHandshake
- * ssl_BeginClientHandshake
- * ssl_BeginServerHandshake
- *
- * The ss->handshake function returns SECWouldBlock if it was returned by
- * one of the callback functions, via one of these paths:
- *
- * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
- * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
- * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() ->
- * ss->handleBadCert()
- *
- * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() ->
- * ssl3_HandleRecord() -> ssl3_HandleHandshake() ->
- * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() ->
- * ss->getClientAuthData()
+/* Step through the handshake functions.
*
* Called from: SSL_ForceHandshake (below),
* ssl_SecureRecv (below) and
@@ -52,10 +27,10 @@
*
* Caller must hold the (write) handshakeLock.
*/
-int
+SECStatus
ssl_Do1stHandshake(sslSocket *ss)
{
- int rv = SECSuccess;
+ SECStatus rv = SECSuccess;
while (ss->handshake && rv == SECSuccess) {
PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
@@ -70,10 +45,6 @@ ssl_Do1stHandshake(sslSocket *ss)
PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss));
- if (rv == SECWouldBlock) {
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
- rv = SECFailure;
- }
return rv;
}
@@ -106,8 +77,8 @@ ssl_FinishHandshake(sslSocket *ss)
static SECStatus
ssl3_AlwaysBlock(sslSocket *ss)
{
- PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */
- return SECWouldBlock;
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ return SECFailure;
}
/*
@@ -400,10 +371,13 @@ SSL_ForceHandshake(PRFileDesc *fd)
ssl_ReleaseRecvBufLock(ss);
if (gatherResult > 0) {
rv = SECSuccess;
- } else if (gatherResult == 0) {
- PORT_SetError(PR_END_OF_FILE_ERROR);
- } else if (gatherResult == SECWouldBlock) {
- PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ } else {
+ if (gatherResult == 0) {
+ PORT_SetError(PR_END_OF_FILE_ERROR);
+ }
+ /* We can rely on ssl3_GatherCompleteHandshake to set
+ * PR_WOULD_BLOCK_ERROR as needed here. */
+ rv = SECFailure;
}
} else {
PORT_Assert(!ss->firstHsDone);
@@ -515,8 +489,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
SSL_GETPID(), ss->fd));
goto done;
}
- if ((rv != SECWouldBlock) &&
- (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
/* Some random error */
goto done;
}
@@ -741,13 +714,14 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow)
/************************************************************************/
static SECStatus
-tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir)
+tls13_CheckKeyUpdate(sslSocket *ss, SSLSecretDirection dir)
{
PRBool keyUpdate;
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)) {
@@ -765,7 +739,7 @@ tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir)
* having the write margin larger reduces the number of times that a
* KeyUpdate is sent by a reader. */
ssl_GetSpecReadLock(ss);
- if (dir == CipherSpecRead) {
+ if (dir == ssl_secret_read) {
spec = ss->ssl3.crSpec;
margin = spec->cipherDef->max_records / 8;
} else {
@@ -781,10 +755,16 @@ tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir)
SSL_TRC(5, ("%d: SSL[%d]: automatic key update at %llx for %s cipher spec",
SSL_GETPID(), ss->fd, seqNum,
- (dir == CipherSpecRead) ? "read" : "write"));
+ (dir == ssl_secret_read) ? "read" : "write"));
+ keyUpdateRequest = (dir == ssl_secret_read) ? update_requested : update_not_requested;
ssl_GetSSL3HandshakeLock(ss);
- rv = tls13_SendKeyUpdate(ss, (dir == CipherSpecRead) ? update_requested : update_not_requested,
- dir == CipherSpecWrite /* 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;
}
@@ -829,7 +809,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
}
ssl_Release1stHandshakeLock(ss);
} else {
- if (tls13_CheckKeyUpdate(ss, CipherSpecRead) != SECSuccess) {
+ if (tls13_CheckKeyUpdate(ss, ssl_secret_read) != SECSuccess) {
rv = PR_FAILURE;
}
}
@@ -955,7 +935,7 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
}
if (ss->firstHsDone) {
- if (tls13_CheckKeyUpdate(ss, CipherSpecWrite) != SECSuccess) {
+ if (tls13_CheckKeyUpdate(ss, ssl_secret_write) != SECSuccess) {
rv = PR_FAILURE;
goto done;
}
@@ -1011,6 +991,35 @@ ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len)
}
SECStatus
+SSLExp_RecordLayerWriteCallback(PRFileDesc *fd, SSLRecordWriteCallback cb,
+ void *arg)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: invalid socket for SSL_RecordLayerWriteCallback",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+ if (IS_DTLS(ss)) {
+ SSL_DBG(("%d: SSL[%d]: DTLS socket for SSL_RecordLayerWriteCallback",
+ SSL_GETPID(), fd));
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* This needs both HS and Xmit locks because this value is checked under
+ * both locks. HS to disable reading from the underlying IO layer; Xmit to
+ * prevent writing. */
+ ssl_GetSSL3HandshakeLock(ss);
+ ssl_GetXmitBufLock(ss);
+ ss->recordWriteCallback = cb;
+ ss->recordWriteCallbackArg = arg;
+ ssl_ReleaseXmitBufLock(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ return SECSuccess;
+}
+
+SECStatus
SSL_AlertReceivedCallback(PRFileDesc *fd, SSLAlertCallback cb, void *arg)
{
sslSocket *ss;