diff options
Diffstat (limited to 'security/nss/lib/ssl/sslsecur.c')
-rw-r--r-- | security/nss/lib/ssl/sslsecur.c | 105 |
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; |