mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
Update NSS to 3.38
- Added HACL*Poly1305 32-bit (INRIA/Microsoft) - Updated to final TLS 1.3 draft version (28) - Removed TLS 1.3 prerelease draft limit check - Removed NPN code - Enabled dev/urandom-only RNG on Linux with NSS_SEED_ONLY_DEV_URANDOM for non-standard environments - Fixed several bugs with TLS 1.3 negotiation - Updated internal certificate store - Added support for the TLS Record Size Limit Extension. - Fixed CVE-2018-0495 - Various security fixes in the ASN.1 code.
This commit is contained in:
parent
0d5d154158
commit
d36d4eb674
197 changed files with 4873 additions and 7145 deletions
|
|
@ -242,33 +242,11 @@ ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* handle an incoming Next Protocol Negotiation extension. */
|
||||
SECStatus
|
||||
ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
SECItem *data)
|
||||
{
|
||||
PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
|
||||
if (ss->firstHsDone || data->len != 0) {
|
||||
/* Clients MUST send an empty NPN extension, if any. */
|
||||
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
xtnData->negotiated[xtnData->numNegotiated++] = ssl_next_proto_nego_xtn;
|
||||
|
||||
/* TODO: server side NPN support would require calling
|
||||
* ssl3_RegisterServerHelloExtensionSender here in order to echo the
|
||||
* extension back to the client. */
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none
|
||||
/* ssl3_ValidateAppProtocol checks that the given block of data is valid: none
|
||||
* of the lengths may be 0 and the sum of the lengths must equal the length of
|
||||
* the block. */
|
||||
SECStatus
|
||||
ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length)
|
||||
ssl3_ValidateAppProtocol(const unsigned char *data, unsigned int length)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
|
||||
|
|
@ -286,7 +264,7 @@ ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length)
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* protocol selection handler for ALPN (server side) and NPN (client side) */
|
||||
/* Protocol selection handler for ALPN. */
|
||||
static SECStatus
|
||||
ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
PRUint16 extension, SECItem *data)
|
||||
|
|
@ -295,7 +273,7 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
unsigned char resultBuffer[255];
|
||||
SECItem result = { siBuffer, resultBuffer, 0 };
|
||||
|
||||
rv = ssl3_ValidateNextProtoNego(data->data, data->len);
|
||||
rv = ssl3_ValidateAppProtocol(data->data, data->len);
|
||||
if (rv != SECSuccess) {
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
|
||||
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
||||
|
|
@ -303,11 +281,13 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
}
|
||||
|
||||
PORT_Assert(ss->nextProtoCallback);
|
||||
/* For ALPN, the cipher suite isn't selected yet. Note that extensions
|
||||
/* The cipher suite isn't selected yet. Note that extensions
|
||||
* sometimes affect what cipher suite is selected, e.g., for ECC. */
|
||||
PORT_Assert((ss->ssl3.hs.preliminaryInfo &
|
||||
ssl_preinfo_all & ~ssl_preinfo_cipher_suite) ==
|
||||
(ssl_preinfo_all & ~ssl_preinfo_cipher_suite));
|
||||
/* The callback has to make sure that either rv != SECSuccess or that result
|
||||
* is not set if there is no common protocol. */
|
||||
rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
|
||||
result.data, &result.len, sizeof(resultBuffer));
|
||||
if (rv != SECSuccess) {
|
||||
|
|
@ -320,21 +300,20 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
* stack. */
|
||||
if (result.len > sizeof(resultBuffer)) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
/* TODO: crash */
|
||||
PORT_Assert(PR_FALSE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE);
|
||||
|
||||
if (extension == ssl_app_layer_protocol_xtn &&
|
||||
xtnData->nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) {
|
||||
/* The callback might say OK, but then it picks a default value - one
|
||||
* that was not listed. That's OK for NPN, but not ALPN. */
|
||||
if (result.len < 1 || !result.data) {
|
||||
/* Check that we actually got a result. */
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, no_application_protocol);
|
||||
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
xtnData->nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
|
||||
xtnData->negotiated[xtnData->numNegotiated++] = extension;
|
||||
return SECITEM_CopyItem(NULL, &xtnData->nextProto, &result);
|
||||
}
|
||||
|
|
@ -356,7 +335,7 @@ ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Unlike NPN, ALPN has extra redundant length information so that
|
||||
/* ALPN has extra redundant length information so that
|
||||
* the extension is the same in both ClientHello and ServerHello. */
|
||||
rv = ssl3_ExtConsumeHandshakeNumber(ss, &count, 2, &data->data, &data->len);
|
||||
if (rv != SECSuccess || count != data->len) {
|
||||
|
|
@ -388,39 +367,6 @@ ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
SECItem *data)
|
||||
{
|
||||
PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
PORT_Assert(!ss->firstHsDone);
|
||||
|
||||
if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
|
||||
/* If the server negotiated ALPN then it has already told us what
|
||||
* protocol to use, so it doesn't make sense for us to try to negotiate
|
||||
* a different one by sending the NPN handshake message. However, if
|
||||
* we've negotiated NPN then we're required to send the NPN handshake
|
||||
* message. Thus, these two extensions cannot both be negotiated on the
|
||||
* same connection. */
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
|
||||
PORT_SetError(SSL_ERROR_BAD_SERVER);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* We should only get this call if we sent the extension, so
|
||||
* ss->nextProtoCallback needs to be non-NULL. However, it is possible
|
||||
* that an application erroneously cleared the callback between the time
|
||||
* we sent the ClientHello and now. */
|
||||
if (!ss->nextProtoCallback) {
|
||||
PORT_Assert(0);
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, internal_error);
|
||||
PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return ssl3_SelectAppProtocol(ss, xtnData, ssl_next_proto_nego_xtn, data);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
SECItem *data)
|
||||
|
|
@ -474,19 +420,6 @@ ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
return SECITEM_CopyItem(NULL, &xtnData->nextProto, &protocol_name);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
sslBuffer *buf, PRBool *added)
|
||||
{
|
||||
/* Renegotiations do not send this extension. */
|
||||
if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
*added = PR_TRUE;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
sslBuffer *buf, PRBool *added)
|
||||
|
|
@ -499,35 +432,15 @@ ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* NPN requires that the client's fallback protocol is first in the
|
||||
* list. However, ALPN sends protocols in preference order. So move the
|
||||
* first protocol to the end of the list. */
|
||||
|
||||
if (len > 0) {
|
||||
/* Each protocol string is prefixed with a single byte length. */
|
||||
unsigned int i;
|
||||
|
||||
rv = sslBuffer_AppendNumber(buf, len, 2);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
i = ss->opt.nextProtoNego.data[0] + 1;
|
||||
if (i <= len) {
|
||||
rv = sslBuffer_Append(buf, &ss->opt.nextProtoNego.data[i], len - i);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, i);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
/* This seems to be invalid data so we'll send as-is. */
|
||||
rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, len);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, len);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1955,3 +1868,67 @@ ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
|||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl_HandleRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
SECItem *data)
|
||||
{
|
||||
SECStatus rv;
|
||||
PRUint32 limit;
|
||||
PRUint32 maxLimit = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)
|
||||
? (MAX_FRAGMENT_LENGTH + 1)
|
||||
: MAX_FRAGMENT_LENGTH;
|
||||
|
||||
rv = ssl3_ExtConsumeHandshakeNumber(ss, &limit, 2, &data->data, &data->len);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
if (data->len != 0 || limit < 64) {
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (ss->sec.isServer) {
|
||||
rv = ssl3_RegisterExtensionSender(ss, xtnData, ssl_record_size_limit_xtn,
|
||||
&ssl_SendRecordSizeLimitXtn);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure; /* error already set. */
|
||||
}
|
||||
} else if (limit > maxLimit) {
|
||||
/* The client can sensibly check the maximum. */
|
||||
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* We can't enforce the maximum on a server. But we do need to ensure
|
||||
* that we don't apply a limit that is too large. */
|
||||
xtnData->recordSizeLimit = PR_MIN(maxLimit, limit);
|
||||
xtnData->negotiated[xtnData->numNegotiated++] = ssl_record_size_limit_xtn;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl_SendRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData,
|
||||
sslBuffer *buf, PRBool *added)
|
||||
{
|
||||
PRUint32 maxLimit;
|
||||
if (ss->sec.isServer) {
|
||||
maxLimit = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)
|
||||
? (MAX_FRAGMENT_LENGTH + 1)
|
||||
: MAX_FRAGMENT_LENGTH;
|
||||
} else {
|
||||
maxLimit = (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3)
|
||||
? (MAX_FRAGMENT_LENGTH + 1)
|
||||
: MAX_FRAGMENT_LENGTH;
|
||||
}
|
||||
PRUint32 limit = PR_MIN(ss->opt.recordSizeLimit, maxLimit);
|
||||
SECStatus rv = sslBuffer_AppendNumber(buf, limit, 2);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
*added = PR_TRUE;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue