diff options
Diffstat (limited to 'security/nss/lib/ssl/sslsecur.c')
-rw-r--r-- | security/nss/lib/ssl/sslsecur.c | 141 |
1 files changed, 71 insertions, 70 deletions
diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index 8bec3d327..3f7060f22 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * Various SSL functions. * @@ -200,7 +201,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer) ssl_Release1stHandshakeLock(ss); ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); - ssl3_ResetExtensionData(&ss->xtnData); + ssl3_ResetExtensionData(&ss->xtnData, ss); if (!ss->TCPconnected) ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr)); @@ -342,11 +343,6 @@ SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart) return SECFailure; } - if (!ss->ssl3.initialized) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - /* Require a forward-secret key exchange. */ *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss || ss->ssl3.hs.kea_def->kea == kea_dhe_rsa || @@ -435,58 +431,6 @@ SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, /************************************************************************/ /* -** Grow a buffer to hold newLen bytes of data. -** Called for both recv buffers and xmit buffers. -** Caller must hold xmitBufLock or recvBufLock, as appropriate. -*/ -SECStatus -sslBuffer_Grow(sslBuffer *b, unsigned int newLen) -{ - newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048); - if (newLen > b->space) { - unsigned char *newBuf; - if (b->buf) { - newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen); - } else { - newBuf = (unsigned char *)PORT_Alloc(newLen); - } - if (!newBuf) { - return SECFailure; - } - SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d", - SSL_GETPID(), b->space, newLen)); - b->buf = newBuf; - b->space = newLen; - } - return SECSuccess; -} - -SECStatus -sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len) -{ - unsigned int newLen = b->len + len; - SECStatus rv; - - rv = sslBuffer_Grow(b, newLen); - if (rv != SECSuccess) - return rv; - PORT_Memcpy(b->buf + b->len, data, len); - b->len += len; - return SECSuccess; -} - -void -sslBuffer_Clear(sslBuffer *b) -{ - if (b->buf) { - PORT_Free(b->buf); - b->buf = NULL; - b->len = 0; - b->space = 0; - } -} - -/* ** Save away write data that is trying to be written before the security ** handshake has been completed. When the handshake is completed, we will ** flush this data out. @@ -774,8 +718,7 @@ ssl_SecureClose(sslSocket *ss) if (!(ss->shutdownHow & ssl_SHUTDOWN_SEND) && ss->firstHsDone && - !ss->recvdCloseNotify && - ss->ssl3.initialized) { + !ss->recvdCloseNotify) { /* We don't want the final alert to be Nagle delayed. */ if (!ss->delayDisabled) { @@ -805,8 +748,7 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow) if ((sslHow & ssl_SHUTDOWN_SEND) != 0 && !(ss->shutdownHow & ssl_SHUTDOWN_SEND) && ss->firstHsDone && - !ss->recvdCloseNotify && - ss->ssl3.initialized) { + !ss->recvdCloseNotify) { (void)SSL3_SendAlert(ss, alert_warning, close_notify); } @@ -820,6 +762,55 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow) /************************************************************************/ +static SECStatus +tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir) +{ + PRBool keyUpdate; + ssl3CipherSpec *spec; + sslSequenceNumber seqNum; + sslSequenceNumber margin; + SECStatus rv; + + /* Bug 1413368: enable for DTLS */ + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 || IS_DTLS(ss)) { + return SECSuccess; + } + + /* If both sides update at the same number, then this will cause two updates + * to happen at once. The problem is that the KeyUpdate itself consumes a + * sequence number, and that will trigger the reading side to request an + * update. + * + * If we have the writing side update first, the writer will be the one that + * drives the update. An update by the writer doesn't need a response, so + * it is more efficient overall. The margins here are pretty arbitrary, but + * having the write margin larger reduces the number of times that a + * KeyUpdate is sent by a reader. */ + ssl_GetSpecReadLock(ss); + if (dir == CipherSpecRead) { + spec = ss->ssl3.crSpec; + margin = spec->cipherDef->max_records / 8; + } else { + spec = ss->ssl3.cwSpec; + margin = spec->cipherDef->max_records / 4; + } + seqNum = spec->seqNum; + keyUpdate = seqNum > spec->cipherDef->max_records - margin; + ssl_ReleaseSpecReadLock(ss); + if (!keyUpdate) { + return SECSuccess; + } + + SSL_TRC(5, ("%d: SSL[%d]: automatic key update at %llx for %s cipher spec", + SSL_GETPID(), ss->fd, seqNum, + (dir == CipherSpecRead) ? "read" : "write")); + ssl_GetSSL3HandshakeLock(ss); + rv = tls13_SendKeyUpdate(ss, (dir == CipherSpecRead) ? update_requested : update_not_requested, + dir == CipherSpecWrite /* buffer */); + ssl_ReleaseSSL3HandshakeLock(ss); + return rv; +} + int ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) { @@ -859,8 +850,17 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) rv = ssl_Do1stHandshake(ss); } ssl_Release1stHandshakeLock(ss); + } else { + if (tls13_CheckKeyUpdate(ss, CipherSpecRead) != SECSuccess) { + rv = PR_FAILURE; + } } if (rv < 0) { + if (PORT_GetError() == PR_WOULD_BLOCK_ERROR && + !PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)) { + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); + return tls13_Read0RttData(ss, buf, len); + } return rv; } @@ -942,11 +942,19 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) } ssl_Release1stHandshakeLock(ss); } + if (rv < 0) { ss->writerThread = NULL; goto done; } + if (ss->firstHsDone) { + if (tls13_CheckKeyUpdate(ss, CipherSpecWrite) != SECSuccess) { + rv = PR_FAILURE; + goto done; + } + } + if (zeroRtt) { /* There's a limit to the number of early data octets we can send. * @@ -1241,14 +1249,7 @@ SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error) } ssl_Get1stHandshakeLock(ss); - - if (!ss->ssl3.initialized) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; - } else { - rv = ssl3_AuthCertificateComplete(ss, error); - } - + rv = ssl3_AuthCertificateComplete(ss, error); ssl_Release1stHandshakeLock(ss); return rv; |