boring2/boring-sys/patches/boringssl-old-ciphers.patch

547 lines
19 KiB
Diff

diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 53aa9b453..9d4a5ca2b 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -2378,6 +2378,8 @@ OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
#define SSL_CURVE_SECP521R1 25
#define SSL_CURVE_X25519 29
#define SSL_CURVE_X25519_KYBER768_DRAFT00 0x6399
+#define SSL_CURVE_FFDHE2048 256
+#define SSL_CURVE_FFDHE3072 257
// SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently
// completed handshake or 0 if not applicable.
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index 772fb87a3..4cb6b5667 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -181,6 +181,8 @@ extern "C" {
#define TLS1_AD_NO_APPLICATION_PROTOCOL 120
#define TLS1_AD_ECH_REQUIRED 121 // draft-ietf-tls-esni-13
+#define TLSEXT_TYPE_record_size_limit 28
+
// ExtensionType values from RFC 6066
#define TLSEXT_TYPE_server_name 0
#define TLSEXT_TYPE_status_request 5
diff --git a/src/ssl/extensions.cc b/src/ssl/extensions.cc
index 5ee280221..62d443e4d 100644
--- a/src/ssl/extensions.cc
+++ b/src/ssl/extensions.cc
@@ -2808,9 +2808,28 @@ static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs,
static bool ext_delegated_credential_add_clienthello(
const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
ssl_client_hello_type_t type) {
+ CBB contents, data;
+ static const uint16_t signature_hash_algorithms[] = {
+ SSL_SIGN_ECDSA_SECP256R1_SHA256, SSL_SIGN_ECDSA_SECP384R1_SHA384,
+ SSL_SIGN_ECDSA_SECP521R1_SHA512, SSL_SIGN_ECDSA_SHA1 };
+ if (!CBB_add_u16(out, TLSEXT_TYPE_delegated_credential) ||
+ !CBB_add_u16_length_prefixed(out, &contents) ||
+ !CBB_add_u16_length_prefixed(&contents, &data)) {
+ return false;
+ }
+
+ for (const uint16_t alg : signature_hash_algorithms) {
+ if (!CBB_add_u16(&data, alg)) {
+ return false;
+ }
+ }
+ if (!CBB_flush(out)) {
+ return false;
+ }
return true;
}
+
static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
uint8_t *out_alert,
CBS *contents) {
@@ -3094,6 +3113,35 @@ bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return true;
}
+static bool record_size_limit_add_clienthello(const SSL_HANDSHAKE* hs, CBB* out,
+ CBB* out_compressible,
+ ssl_client_hello_type_t type) {
+ CBB data;
+ const uint16_t data_ = 0x4001;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_record_size_limit) ||
+ !CBB_add_u16_length_prefixed(out, &data) || !CBB_add_u16(&data, data_) ||
+ !CBB_flush(out)) {
+ return false;
+ }
+ return true;
+ }
+
+static bool record_size_limit_parse_serverhello(SSL_HANDSHAKE* hs,
+ uint8_t* out_alert,
+ CBS* contents) {
+ return true;
+}
+
+static bool record_size_limit_parse_clienthello(SSL_HANDSHAKE* hs,
+ uint8_t* out_alert,
+ CBS* contents) {
+ return true;
+}
+
+static bool record_size_limit_add_serverhello(SSL_HANDSHAKE* hs, CBB* out) {
+ return true;
+}
+
// kExtensions contains all the supported extensions.
static const struct tls_extension kExtensions[] = {
{
@@ -3267,6 +3315,13 @@ static const struct tls_extension kExtensions[] = {
ignore_parse_clienthello,
ext_alps_add_serverhello,
},
+ {
+ TLSEXT_TYPE_record_size_limit,
+ record_size_limit_add_clienthello,
+ record_size_limit_parse_serverhello,
+ record_size_limit_parse_clienthello,
+ record_size_limit_add_serverhello,
+ },
};
#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 971ebd0b1..e70e6c868 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -215,13 +215,15 @@ static void ssl_get_client_disabled(const SSL_HANDSHAKE *hs,
}
}
-static bool ssl_add_tls13_cipher(CBB *cbb, uint16_t cipher_id,
- ssl_compliance_policy_t policy) {
- if (ssl_tls13_cipher_meets_policy(cipher_id, policy)) {
- return CBB_add_u16(cbb, cipher_id);
- }
- return true;
-}
+// Comment this part of the code to cancel the device AES encryption cipher sequence priority, which may affect performance.
+// Compatible with some Firefox cipher sequence order
+// static bool ssl_add_tls13_cipher(CBB *cbb, uint16_t cipher_id,
+// ssl_compliance_policy_t policy) {
+// if (ssl_tls13_cipher_meets_policy(cipher_id, policy)) {
+// return CBB_add_u16(cbb, cipher_id);
+// }
+// return true;
+// }
static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
ssl_client_hello_type_t type) {
@@ -242,26 +244,28 @@ static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
// Add TLS 1.3 ciphers. Order ChaCha20-Poly1305 relative to AES-GCM based on
// hardware support.
- if (hs->max_version >= TLS1_3_VERSION) {
- const bool has_aes_hw = ssl->config->aes_hw_override
- ? ssl->config->aes_hw_override_value
- : EVP_has_aes_hardware();
-
- if ((!has_aes_hw && //
- !ssl_add_tls13_cipher(&child,
- TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
- ssl->config->tls13_cipher_policy)) ||
- !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
- ssl->config->tls13_cipher_policy) ||
- !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
- ssl->config->tls13_cipher_policy) ||
- (has_aes_hw && //
- !ssl_add_tls13_cipher(&child,
- TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
- ssl->config->tls13_cipher_policy))) {
- return false;
- }
- }
+ // Comment this part of the code to cancel the device AES encryption cipher sequence priority, which may affect performance.
+ // Compatible with some Firefox cipher sequence order
+ // if (hs->max_version >= TLS1_3_VERSION) {
+ // const bool has_aes_hw = ssl->config->aes_hw_override
+ // ? ssl->config->aes_hw_override_value
+ // : EVP_has_aes_hardware();
+
+ // if ((!has_aes_hw && //
+ // !ssl_add_tls13_cipher(&child,
+ // TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
+ // ssl->config->tls13_cipher_policy)) ||
+ // !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
+ // ssl->config->tls13_cipher_policy) ||
+ // !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
+ // ssl->config->tls13_cipher_policy) ||
+ // (has_aes_hw && //
+ // !ssl_add_tls13_cipher(&child,
+ // TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
+ // ssl->config->tls13_cipher_policy))) {
+ // return false;
+ // }
+ // }
if (hs->min_version < TLS1_3_VERSION && type != ssl_client_hello_inner) {
bool any_enabled = false;
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 1e6da2153..045106263 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -554,8 +554,13 @@ BSSL_NAMESPACE_BEGIN
// Bits for |algorithm_mac| (symmetric authentication).
#define SSL_SHA1 0x00000001u
#define SSL_SHA256 0x00000002u
+//
+// SSL_SHA384 was removed in
+// https://boringssl-review.googlesource.com/c/boringssl/+/27944/
+// but restored to impersonate browsers with older ciphers.
+#define SSL_SHA384 0x00000004u
// SSL_AEAD is set for all AEADs.
-#define SSL_AEAD 0x00000004u
+#define SSL_AEAD 0x00000008u
// Bits for |algorithm_prf| (handshake digest).
#define SSL_HANDSHAKE_MAC_DEFAULT 0x1
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index ebb075351..17fcaa13c 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -197,6 +197,37 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_DEFAULT,
},
+ // Ciphers 3C, 3D were removed in
+ // https://boringssl-review.googlesource.com/c/boringssl/+/27944/
+ // but restored here to impersonate browsers with older ciphers. They are
+ // not expected to actually work; but just to be included in the TLS
+ // Client Hello.
+
+ // TLS v1.2 ciphersuites
+
+ // Cipher 3C
+ {
+ TLS1_TXT_RSA_WITH_AES_128_SHA256,
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ TLS1_CK_RSA_WITH_AES_128_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES128,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+ // Cipher 3D
+ {
+ TLS1_TXT_RSA_WITH_AES_256_SHA256,
+ "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ TLS1_CK_RSA_WITH_AES_256_SHA256,
+ SSL_kRSA,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
// PSK cipher suites.
// Cipher 8C
@@ -287,6 +318,23 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_SHA256,
},
+ // Cipher C008 was missing from BoringSSL,
+ // probably because it is weak. Add it back from OpenSSL (ssl/s3_lib.c)
+ // where it is called ECDHE-ECDSA-DES-CBC3-SHA.
+ // It's not supposed to really work but just appear in the TLS client hello.
+
+ // Cipher C008
+ {
+ "ECDHE-ECDSA-DES-CBC3-SHA",
+ "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ 0x0300C008,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL_HANDSHAKE_MAC_DEFAULT,
+ },
+
// Cipher C009
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
@@ -311,6 +359,21 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_DEFAULT,
},
+ // Cipher C012 was missing from BoringSSL,
+ // probably because it is weak. Add it back from OpenSSL (ssl/s3_lib.c)
+ // where it is called ECDHE-RSA-DES-CBC3-SHA
+ // It's not supposed to really work but just appear in the TLS client hello.
+ {
+ "ECDHE-RSA-DES-CBC3-SHA",
+ "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ 0x0300C012,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_3DES,
+ SSL_SHA1,
+ SSL_HANDSHAKE_MAC_DEFAULT,
+ },
+
// Cipher C013
{
TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
@@ -335,6 +398,37 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_DEFAULT,
},
+ // Ciphers C023, C024, C028 were removed in
+ // https://boringssl-review.googlesource.com/c/boringssl/+/27944/
+ // but restored here to impersonate browsers with older ciphers. They are
+ // not expected to actually work; but just to be included in the TLS
+ // Client Hello.
+
+ // HMAC based TLS v1.2 ciphersuites from RFC5289
+
+ // Cipher C023
+ {
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES128,
+ SSL_SHA256,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+ // Cipher C024
+ {
+ TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_AES256,
+ SSL_SHA384,
+ SSL_HANDSHAKE_MAC_SHA384,
+ },
+
// Cipher C027
{
TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
@@ -347,6 +441,18 @@ static constexpr SSL_CIPHER kCiphers[] = {
SSL_HANDSHAKE_MAC_SHA256,
},
+ // Cipher C028
+ {
+ TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_AES256,
+ SSL_SHA384,
+ SSL_HANDSHAKE_MAC_SHA384,
+ },
+
// GCM based TLS v1.2 ciphersuites from RFC 5289
// Cipher C02B
@@ -467,15 +573,17 @@ Span<const SSL_CIPHER> AllCiphers() {
return MakeConstSpan(kCiphers, OPENSSL_ARRAY_SIZE(kCiphers));
}
-static constexpr size_t NumTLS13Ciphers() {
- size_t num = 0;
- for (const auto &cipher : kCiphers) {
- if (cipher.algorithm_mkey == SSL_kGENERIC) {
- num++;
- }
- }
- return num;
-}
+// Comment this part of the code to cancel the device AES encryption cipher sequence priority, which may affect performance.
+// Compatible with some Firefox cipher sequence order
+// static constexpr size_t NumTLS13Ciphers() {
+// size_t num = 0;
+// for (const auto &cipher : kCiphers) {
+// if (cipher.algorithm_mkey == SSL_kGENERIC) {
+// num++;
+// }
+// }
+// return num;
+// }
#define CIPHER_ADD 1
#define CIPHER_KILL 2
@@ -549,6 +657,11 @@ static const CIPHER_ALIAS kCipherAliases[] = {
// MAC aliases
{"SHA1", ~0u, ~0u, ~0u, SSL_SHA1, 0},
+ //
+ // Removed in https://boringssl-review.googlesource.com/c/boringssl/+/27944/
+ // but restored to impersonate browsers with older ciphers.
+ {"SHA256", ~0u, ~0u, ~0u, SSL_SHA256, 0},
+ {"SHA384", ~0u, ~0u, ~0u, SSL_SHA384, 0},
{"SHA", ~0u, ~0u, ~0u, SSL_SHA1, 0},
// Legacy protocol minimum version aliases. "TLSv1" is intentionally the
@@ -1166,12 +1279,30 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
TLS1_CK_RSA_WITH_AES_256_SHA & 0xffff,
TLS1_CK_PSK_WITH_AES_256_CBC_SHA & 0xffff,
SSL3_CK_RSA_DES_192_CBC3_SHA & 0xffff,
+ // add legacy cipehrs.
+ TLS1_CK_RSA_WITH_AES_128_SHA256 & 0xffff,
+ TLS1_CK_RSA_WITH_AES_256_SHA256 & 0xffff,
+ 0x0300C008 & 0xffff,
+ 0x0300C012 & 0xffff,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 & 0xffff,
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 & 0xffff,
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 & 0xffff,
+ };
+ // Comment this part of the code to cancel the device AES encryption cipher sequence priority, which may affect performance.
+ // Compatible with some Firefox cipher sequence order
+ static const uint16_t kTLS13Ciphers[] = {
+ TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
+ TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
+ TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
};
// Set up a linked list of ciphers.
- CIPHER_ORDER co_list[OPENSSL_ARRAY_SIZE(kAESCiphers) +
- OPENSSL_ARRAY_SIZE(kChaChaCiphers) +
- OPENSSL_ARRAY_SIZE(kLegacyCiphers)];
+ // Comment this part of the code to cancel the device AES encryption cipher sequence priority, which may affect performance.
+ // Compatible with some Firefox cipher sequence order
+ // CIPHER_ORDER co_list[OPENSSL_ARRAY_SIZE(kAESCiphers) +
+ // OPENSSL_ARRAY_SIZE(kChaChaCiphers) +
+ // OPENSSL_ARRAY_SIZE(kLegacyCiphers)];
+ CIPHER_ORDER co_list[OPENSSL_ARRAY_SIZE(kCiphers)];
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(co_list); i++) {
co_list[i].next =
i + 1 < OPENSSL_ARRAY_SIZE(co_list) ? &co_list[i + 1] : nullptr;
@@ -1207,8 +1338,17 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
co_list[num++].cipher = SSL_get_cipher_by_value(id);
assert(co_list[num - 1].cipher != nullptr);
}
+ for (uint16_t id: kTLS13Ciphers) {
+ co_list[num++].cipher = SSL_get_cipher_by_value(id);
+ assert(co_list[num - 1].cipher != nullptr);
+ }
assert(num == OPENSSL_ARRAY_SIZE(co_list));
- static_assert(OPENSSL_ARRAY_SIZE(co_list) + NumTLS13Ciphers() ==
+ // Comment this part of the code to cancel the device AES encryption cipher sequence priority, which may affect performance.
+ // Compatible with some Firefox cipher sequence order
+ // static_assert(OPENSSL_ARRAY_SIZE(co_list) + NumTLS13Ciphers() ==
+ // OPENSSL_ARRAY_SIZE(kCiphers),
+ // "Not all ciphers are included in the cipher order");
+ static_assert(OPENSSL_ARRAY_SIZE(co_list) ==
OPENSSL_ARRAY_SIZE(kCiphers),
"Not all ciphers are included in the cipher order");
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 09a9ad380..6574cebcb 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -292,6 +292,10 @@ constexpr NamedGroup kNamedGroups[] = {
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
{NID_X25519Kyber768Draft00, SSL_CURVE_X25519_KYBER768_DRAFT00,
"X25519Kyber768Draft00", ""},
+
+ //unspport group but add them
+ {NID_secp224r1, SSL_CURVE_FFDHE2048, "dhe2048", "ffdhe2048"},
+ {NID_secp224r1, SSL_CURVE_FFDHE3072, "dhe3072", "ffdhe3072"},
};
} // namespace
diff --git a/src/ssl/ssl_privkey.cc b/src/ssl/ssl_privkey.cc
index 46bef32e8..a3f0c05bb 100644
--- a/src/ssl/ssl_privkey.cc
+++ b/src/ssl/ssl_privkey.cc
@@ -567,44 +567,49 @@ int SSL_is_signature_algorithm_rsa_pss(uint16_t sigalg) {
return alg != nullptr && alg->is_rsa_pss;
}
-static int compare_uint16_t(const void *p1, const void *p2) {
- uint16_t u1 = *((const uint16_t *)p1);
- uint16_t u2 = *((const uint16_t *)p2);
- if (u1 < u2) {
- return -1;
- } else if (u1 > u2) {
- return 1;
- } else {
- return 0;
- }
-}
-
-static bool sigalgs_unique(Span<const uint16_t> in_sigalgs) {
- if (in_sigalgs.size() < 2) {
- return true;
- }
-
- Array<uint16_t> sigalgs;
- if (!sigalgs.CopyFrom(in_sigalgs)) {
- return false;
- }
-
- qsort(sigalgs.data(), sigalgs.size(), sizeof(uint16_t), compare_uint16_t);
-
- for (size_t i = 1; i < sigalgs.size(); i++) {
- if (sigalgs[i - 1] == sigalgs[i]) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_SIGNATURE_ALGORITHM);
- return false;
- }
- }
-
- return true;
-}
+// Remove the uniqueness check. Older Safari versions (15)
+// send out duplicated algorithm prefs.
+// static int compare_uint16_t(const void *p1, const void *p2) {
+// uint16_t u1 = *((const uint16_t *)p1);
+// uint16_t u2 = *((const uint16_t *)p2);
+// if (u1 < u2) {
+// return -1;
+// } else if (u1 > u2) {
+// return 1;
+// } else {
+// return 0;
+// }
+// }
+
+// static bool sigalgs_unique(Span<const uint16_t> in_sigalgs) {
+// if (in_sigalgs.size() < 2) {
+// return true;
+// }
+//
+// Array<uint16_t> sigalgs;
+// if (!sigalgs.CopyFrom(in_sigalgs)) {
+// return false;
+// }
+//
+// qsort(sigalgs.data(), sigalgs.size(), sizeof(uint16_t), compare_uint16_t);
+//
+// for (size_t i = 1; i < sigalgs.size(); i++) {
+// if (sigalgs[i - 1] == sigalgs[i]) {
+// OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_SIGNATURE_ALGORITHM);
+// return false;
+// }
+// }
+//
+// return true;
+// }
static bool set_sigalg_prefs(Array<uint16_t> *out, Span<const uint16_t> prefs) {
- if (!sigalgs_unique(prefs)) {
- return false;
- }
+ // Remove the uniqueness check. Older Safari versions (15)
+ // send out duplicated algorithm prefs.
+
+ // if (!sigalgs_unique(prefs)) {
+ // return false;
+ // }
// Check for invalid algorithms, and filter out |SSL_SIGN_RSA_PKCS1_MD5_SHA1|.
Array<uint16_t> filtered;