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:
wolfbeast 2018-08-14 07:52:35 +02:00 committed by Roy Tam
commit d36d4eb674
197 changed files with 4873 additions and 7145 deletions

View file

@ -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;
}