refraction-networking / utls

Fork of the Go standard TLS library, providing low-level access to the ClientHello for mimicry purposes.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

bug: configuration for GREASE ECH parrot for Chrome 120 doesn't match BoringSSL

hax0r31337 opened this issue · comments

I have read the part of code in BoringSSL which is for GREASE ECH, as BoringSSL is used by Chrome for it's TLS.

Candidate Cipher Suites

BoringSSL only selects AEAD between AEAD_AES_128_GCM and AEAD_CHACHA20_POLY1305 based on hardware support according to code below.

  const EVP_HPKE_AEAD *aead =
      has_aes_hw ? EVP_hpke_aes_128_gcm() : EVP_hpke_chacha20_poly1305();

https://github.com/google/boringssl/blob/8cacbd93b8788cfb46f6a4d7e11b99c29b3752bd/ssl/encrypted_client_hello.cc#L724

I'm wondering about why utls parrot also candidates AEAD_AES_256_GCM. Is this an oversight or something I didn't notice?

{
    KdfId:  dicttls.HKDF_SHA256,
    AeadId: dicttls.AEAD_AES_256_GCM,
},

https://github.com/refraction-networking/utls/blob/ed573b3ab42148ba62b3bbb27ef796075baf4797/u_parrots.go#L735C7-L737

Candidate Payload Lengths

BoringSSL pads payload not only from 128, 160 but 128, 160, 192, 224 according to code below.

  const size_t payload_len =
      32 * random_size(128 / 32, 224 / 32) + aead_overhead(aead);

https://github.com/google/boringssl/blob/8cacbd93b8788cfb46f6a4d7e11b99c29b3752bd/ssl/encrypted_client_hello.cc#L748

Great observation.

why utls parrot also candidates AEAD_AES_256_GCM.

I did not explicitly refer to BoringSSL in terms of adding ECH to Chrome/Firefox parrots, but rather referred to the RFC which mentions GREASE ECH should try to randomly select from all supported combinations. So this is indeed an oversight.

BoringSSL pads payload not only from 128, 160 but 128, 160, 192, 224 according to code below.

Thanks for the observation, I did not go through the code but instead randomly sampled for ~10 GREASE ECH generated by Google Chrome, which did not really include these many possible lengths.

Should you open a pull request to address these problems, it would be wonderful.

Possibly we could add a function in u_ech.go named BoringGREASEECH() which returns the GREASE ECH generated by BoringSSL? (Instead of hard coding them in each parrot based on BoringSSL)

A similar patch, based on either random sampling or code review of Firefox might be needed as well.

I have reviewed the code of NSS, which is the TLS library that Firefox uses.

It also only selects AEAD between AEAD_AES_128_GCM and AEAD_CHACHA20_POLY1305, but randomly.

aead = (rawData->data[0] & 1) ? HpkeAeadAes128Gcm : HpkeAeadChaCha20Poly1305;

https://github.com/mozilla/gecko-dev/blob/8b5d93d099b5b501cf5bd2b606c59afcf88bef1c/security/nss/lib/ssl/tls13ech.c#L2226

And the GREASE ECH Payload size does not have a fixed size, as it was generated based on the outer ClientHello.

By random sampling, the payload size of the GREASE ECH Extension in Firefox would be 223 (+16)

Thanks for doing these. I will take a look. I am pretty sure I saw a shorter ECH payload at some point from my Firefox...

Checked again, did not find sizes other than 239. Seems I made a mistake. Now I think this issue has been fully addressed and can be closed.