forked from mirrors/gecko-dev
2020-11-18 Kevin Jacobs <kjacobs@mozilla.com> * lib/ssl/ssl3con.c, lib/ssl/tls13con.c, lib/ssl/tls13ech.c: Bug 1654332 - Fixup a10493dcfcc9: copy ECHConfig.config_id with socket r=jcj A late review change for ECH was for the server to compute each ECHConfig `config_id` when set to the socket, rather than on each connection. This works, but now we also need to copy that config_id when copying a socket, else the server won't find a matching ECHConfig to use for decryption. [3eacb92e9adf] [tip] 2020-11-17 Kevin Jacobs <kjacobs@mozilla.com> * automation/abi-check/expected-report-libssl3.so.txt, cmd/tstclnt/tstclnt.c, cpputil/tls_parser.h, gtests/ssl_gtest/libssl_internals.c, gtests/ssl_gtest/libssl_internals.h, gtests/ssl_gtest/manifest.mn, gtests/ssl_gtest/ssl_auth_unittest.cc, gtests/ssl_gtest/ssl_custext_unittest.cc, gtests/ssl_gtest/ssl_extension_unittest.cc, gtests/ssl_gtest/ssl_gtest.gyp, gtests/ssl_gtest/ssl_tls13compat_unittest.cc, gtests/ssl_gtest/tls_agent.cc, gtests/ssl_gtest/tls_agent.h, gtests/ssl_gtest/tls_connect.cc, gtests/ssl_gtest/tls_connect.h, gtests/ssl_gtest/tls_ech_unittest.cc, gtests/ssl_gtest/tls_esni_unittest.cc, gtests/ssl_gtest/tls_filter.cc, gtests/ssl_gtest/tls_filter.h, lib/ssl/SSLerrs.h, lib/ssl/manifest.mn, lib/ssl/ssl.gyp, lib/ssl/ssl3con.c, lib/ssl/ssl3ext.c, lib/ssl/ssl3ext.h, lib/ssl/ssl3exthandle.c, lib/ssl/ssl3exthandle.h, lib/ssl/ssl3prot.h, lib/ssl/sslencode.c, lib/ssl/sslencode.h, lib/ssl/sslerr.h, lib/ssl/sslexp.h, lib/ssl/sslimpl.h, lib/ssl/sslinfo.c, lib/ssl/sslsecur.c, lib/ssl/sslsock.c, lib/ssl/sslt.h, lib/ssl/tls13con.c, lib/ssl/tls13con.h, lib/ssl/tls13ech.c, lib/ssl/tls13ech.h, lib/ssl/tls13esni.c, lib/ssl/tls13esni.h, lib/ssl/tls13exthandle.c, lib/ssl/tls13exthandle.h, lib/ssl/tls13hashstate.c, lib/ssl/tls13hashstate.h: Bug 1654332 - Update ESNI to draft-08 (ECH). r=mt This patch adds support for Encrypted Client Hello (draft-ietf-tls- esni-08), replacing the existing ESNI (draft -02) support. There are five new experimental functions to enable this: - SSL_EncodeEchConfig: Generates an encoded (not BASE64) ECHConfig given a set of parameters. - SSL_SetClientEchConfigs: Configures the provided ECHConfig to the given socket. When configured, an ephemeral HPKE keypair will be generated for the CH encryption. - SSL_SetServerEchConfigs: Configures the provided ECHConfig and keypair to the socket. The keypair specified will be used for HPKE operations in order to decrypt encrypted Client Hellos as they are received. - SSL_GetEchRetryConfigs: If ECH is rejected by the server and compatible retry_configs are provided, this API allows the application to extract those retry_configs for use in a new connection. - SSL_EnableTls13GreaseEch: When enabled, non-ECH Client Hellos will have a "GREASE ECH" (i.e. fake) extension appended. GREASE ECH is disabled by default, as there are known compatibility issues that will be addressed in a subsequent draft. The following ESNI experimental functions are deprecated by this update: - SSL_EncodeESNIKeys - SSL_EnableESNI - SSL_SetESNIKeyPair In order to be used, NSS must be compiled with `NSS_ENABLE_DRAFT_HPKE` defined. [a10493dcfcc9] * lib/ssl/ssl3con.c, lib/ssl/sslencode.c, lib/ssl/sslencode.h, lib/ssl/tls13con.c, lib/ssl/tls13con.h: Bug 1654332 - Buffered ClientHello construction. r=mt This patch refactors construction of Client Hello messages. Instead of each component of the message being written separately into `ss->sec.ci.sendBuf`, we now construct the message in its own sslBuffer. Once complete, the entire message is added to the sendBuf via `ssl3_AppendHandshake`. `ssl3_SendServerHello` already uses this approach and it becomes necessary for ECH, where we use the constructed ClientHello to create an inner ClientHello. [d40121ba59ba] 2020-11-13 J.C. Jones <jjones@mozilla.com> * automation/abi-check/expected-report-libnss3.so.txt, automation/abi- check/expected-report-libnssutil3.so.txt, automation/abi-check /previous-nss-release, lib/nss/nss.h, lib/softoken/softkver.h, lib/util/nssutil.h: Set version numbers to 3.60 Beta [5e7b37609f22] Differential Revision: https://phabricator.services.mozilla.com/D97492
177 lines
5.4 KiB
C++
177 lines
5.4 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef tls_parser_h_
|
|
#define tls_parser_h_
|
|
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <memory>
|
|
#if defined(WIN32) || defined(WIN64)
|
|
#include <winsock2.h>
|
|
#else
|
|
#include <arpa/inet.h>
|
|
#endif
|
|
#include "databuffer.h"
|
|
#include "sslt.h"
|
|
|
|
namespace nss_test {
|
|
|
|
const uint8_t kTlsHandshakeClientHello = 1;
|
|
const uint8_t kTlsHandshakeServerHello = 2;
|
|
const uint8_t kTlsHandshakeNewSessionTicket = 4;
|
|
const uint8_t kTlsHandshakeHelloRetryRequest = 6;
|
|
const uint8_t kTlsHandshakeEncryptedExtensions = 8;
|
|
const uint8_t kTlsHandshakeCertificate = 11;
|
|
const uint8_t kTlsHandshakeServerKeyExchange = 12;
|
|
const uint8_t kTlsHandshakeCertificateRequest = 13;
|
|
const uint8_t kTlsHandshakeCertificateVerify = 15;
|
|
const uint8_t kTlsHandshakeClientKeyExchange = 16;
|
|
const uint8_t kTlsHandshakeFinished = 20;
|
|
const uint8_t kTlsHandshakeKeyUpdate = 24;
|
|
|
|
const uint8_t kTlsAlertWarning = 1;
|
|
const uint8_t kTlsAlertFatal = 2;
|
|
|
|
const uint8_t kTlsAlertCloseNotify = 0;
|
|
const uint8_t kTlsAlertUnexpectedMessage = 10;
|
|
const uint8_t kTlsAlertBadRecordMac = 20;
|
|
const uint8_t kTlsAlertRecordOverflow = 22;
|
|
const uint8_t kTlsAlertHandshakeFailure = 40;
|
|
const uint8_t kTlsAlertBadCertificate = 42;
|
|
const uint8_t kTlsAlertCertificateRevoked = 44;
|
|
const uint8_t kTlsAlertCertificateExpired = 45;
|
|
const uint8_t kTlsAlertIllegalParameter = 47;
|
|
const uint8_t kTlsAlertDecodeError = 50;
|
|
const uint8_t kTlsAlertDecryptError = 51;
|
|
const uint8_t kTlsAlertProtocolVersion = 70;
|
|
const uint8_t kTlsAlertInsufficientSecurity = 71;
|
|
const uint8_t kTlsAlertInternalError = 80;
|
|
const uint8_t kTlsAlertInappropriateFallback = 86;
|
|
const uint8_t kTlsAlertMissingExtension = 109;
|
|
const uint8_t kTlsAlertUnsupportedExtension = 110;
|
|
const uint8_t kTlsAlertUnrecognizedName = 112;
|
|
const uint8_t kTlsAlertCertificateRequired = 116;
|
|
const uint8_t kTlsAlertNoApplicationProtocol = 120;
|
|
const uint8_t kTlsAlertEchRequired = 121;
|
|
|
|
const uint8_t kTlsFakeChangeCipherSpec[] = {
|
|
ssl_ct_change_cipher_spec, // Type
|
|
0xfe,
|
|
0xff, // Version
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x10, // Fictitious sequence #
|
|
0x00,
|
|
0x01, // Length
|
|
0x01 // Value
|
|
};
|
|
|
|
const uint8_t kCtDtlsCiphertext = 0x20;
|
|
const uint8_t kCtDtlsCiphertextMask = 0xE0;
|
|
const uint8_t kCtDtlsCiphertext16bSeqno = 0x08;
|
|
const uint8_t kCtDtlsCiphertextLengthPresent = 0x04;
|
|
|
|
static const uint8_t kTls13PskKe = 0;
|
|
static const uint8_t kTls13PskDhKe = 1;
|
|
static const uint8_t kTls13PskAuth = 0;
|
|
static const uint8_t kTls13PskSignAuth = 1;
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, SSLProtocolVariant v) {
|
|
return os << ((v == ssl_variant_stream) ? "TLS" : "DTLS");
|
|
}
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, SSLContentType v) {
|
|
switch (v) {
|
|
case ssl_ct_change_cipher_spec:
|
|
return os << "CCS";
|
|
case ssl_ct_alert:
|
|
return os << "alert";
|
|
case ssl_ct_handshake:
|
|
return os << "handshake";
|
|
case ssl_ct_application_data:
|
|
return os << "application data";
|
|
case ssl_ct_ack:
|
|
return os << "ack";
|
|
}
|
|
return os << "UNKNOWN content type " << static_cast<int>(v);
|
|
}
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, SSLSecretDirection v) {
|
|
switch (v) {
|
|
case ssl_secret_read:
|
|
return os << "read";
|
|
case ssl_secret_write:
|
|
return os << "write";
|
|
}
|
|
return os << "UNKNOWN secret direction " << static_cast<int>(v);
|
|
}
|
|
|
|
inline bool IsDtls(uint16_t version) { return (version & 0x8000) == 0x8000; }
|
|
|
|
inline uint16_t NormalizeTlsVersion(uint16_t version) {
|
|
if (version == 0xfeff) {
|
|
return 0x0302; // special: DTLS 1.0 == TLS 1.1
|
|
}
|
|
if (IsDtls(version)) {
|
|
return (version ^ 0xffff) + 0x0201;
|
|
}
|
|
return version;
|
|
}
|
|
|
|
inline uint16_t TlsVersionToDtlsVersion(uint16_t version) {
|
|
if (version == 0x0302) {
|
|
return 0xfeff;
|
|
}
|
|
if (version == 0x0304) {
|
|
return version;
|
|
}
|
|
return 0xffff - version + 0x0201;
|
|
}
|
|
|
|
inline size_t WriteVariable(DataBuffer* target, size_t index,
|
|
const DataBuffer& buf, size_t len_size) {
|
|
index = target->Write(index, static_cast<uint32_t>(buf.len()), len_size);
|
|
return target->Write(index, buf.data(), buf.len());
|
|
}
|
|
|
|
class TlsParser {
|
|
public:
|
|
TlsParser(const uint8_t* data, size_t len) : buffer_(data, len), offset_(0) {}
|
|
explicit TlsParser(const DataBuffer& buf) : buffer_(buf), offset_(0) {}
|
|
|
|
bool Read(uint8_t* val);
|
|
// Read an integral type of specified width.
|
|
bool Read(uint32_t* val, size_t size);
|
|
// Reads len bytes into dest buffer, overwriting it.
|
|
bool Read(DataBuffer* dest, size_t len);
|
|
bool ReadFromMark(DataBuffer* val, size_t len, size_t mark);
|
|
// Reads bytes into dest buffer, overwriting it. The number of bytes is
|
|
// determined by reading from len_size bytes from the stream first.
|
|
bool ReadVariable(DataBuffer* dest, size_t len_size);
|
|
|
|
bool Skip(size_t len);
|
|
bool SkipVariable(size_t len_size);
|
|
|
|
size_t consumed() const { return offset_; }
|
|
size_t remaining() const { return buffer_.len() - offset_; }
|
|
|
|
private:
|
|
void consume(size_t len) { offset_ += len; }
|
|
const uint8_t* ptr() const { return buffer_.data() + offset_; }
|
|
|
|
DataBuffer buffer_;
|
|
size_t offset_;
|
|
};
|
|
|
|
} // namespace nss_test
|
|
|
|
#endif
|