-
-
Notifications
You must be signed in to change notification settings - Fork 34k
gh-89730: EncryptedClientHello support in ssl module #135435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you mentioned, the ECH feature is not yet available in OpenSSL (https://github.com/openssl/openssl/tree/feature/ech). I would like to defer this until it's released.
In addition:
- please remove blank lines as much as possile. Too many blank lines hinder the reading flow.
- check return codes from OpenSSL (SSL_ech_get1_retry_config may fail for instance, so you should check if it succeeded, and if not, correctly handle the return code)
- we need tests
| Adds support for Encrypted Client Hello (ECH) to the ssl module. Clients may | ||
| use the options exposed to establish TLS connections using ECH. Third-party | ||
| libraries like dnspython can be used to query for HTTPS and SVCB records | ||
| that contain the public keys required to use ECH with specific servers. If | ||
| no public key is available, an option is available to "GREASE" the | ||
| connection, and it is possible to retrieve the public key from the retry | ||
| configuration sent by servers that support ECH as they terminate the initial | ||
| connection. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This description should also be put in What's New rather here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what this means.
Misc/NEWS.d/next/Library/2025-06-12-15-39-48.gh-issue-89730.Lu35Fu.rst
Outdated
Show resolved
Hide resolved
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
27dcb2f to
7092144
Compare
Exposes options for clients to use Encrypted Client Hello (ECH) when establishing TLS connections. It is up to the user to source the ECH public keys before making use of these options.
| if (es_in == NULL) { | ||
| goto fail; | ||
| } | ||
| es = OSSL_ECHSTORE_new(NULL, NULL)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double closing parenthesis looks like a typo.
| if (retval == NULL) { | ||
| goto fail; | ||
| } | ||
| PyTuple_SET_ITEM(retval, 0, PyLong_FromLong(status)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: PyLong_FromLong can return NULL. Should execution continue in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No indeed, so this should be checked.
| Py_INCREF(Py_None); | ||
| } | ||
| return retval; | ||
| fail: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWICS retval needs to be free'd to in fail.
| context.set_ech_config(ech_config) | ||
| with socket.create_connection((hostname, 443)) as sock: | ||
| with context.wrap_socket(sock, server_hostname=hostname) as ssock: | ||
| if (ssock.get_ech_status == ECHStatus.ECH_STATUS_GREASE_ECH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will always resolve to False because it is checking ssock.get_ech_status as a bound method object and not the result of the method. It should be ssock.get_ech_status().
picnixz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering it's still not released in OpenSSL, I prefer that we close this PR and re-open it once it's shipped. There are also conflicts to solve and the implementation is lacking tests and there is no ETA for that feature (we also need to find another way to configure this, because I'm not really happy with the configure check, we may need more checks with OPENSSL_VERSION for instance).
| if (retval == NULL) { | ||
| goto fail; | ||
| } | ||
| PyTuple_SET_ITEM(retval, 0, PyLong_FromLong(status)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No indeed, so this should be checked.
| /*[clinic end generated code: output=cea53188b338cf80 input=3ef0514cae6ab6ee]*/ | ||
| { | ||
| #ifdef HAVE_OPENSSL_ECH | ||
| BIO *es_in = BIO_new_mem_buf(ech_config->buf, ech_config->len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we avoid cryptic variable names please?
| Py_RETURN_NONE; | ||
| fail: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Py_RETURN_NONE; | |
| fail: | |
| Py_RETURN_NONE; | |
| fail: |
| } | ||
| OSSL_ECHSTORE_free(es); | ||
| BIO_free_all(es_in); | ||
| PyBuffer_Release(ech_config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIR, there is no need for that. The caller handles it implicitly.
Exposes options for clients to use Encrypted Client Hello (ECH) when establishing TLS connections. It is up to the user to source the ECH public keys before making use of these options.
To use these options requires a version of openssl that includes these options, which currently are on a feature branch:
https://github.com/openssl/openssl/tree/feature/ech
We do not expect that the API here will have any substaintial changes when it is merged.
For testing, clone the above repository, checkout the
feature/echbranch, and build. Then use this openssl installation when building cPython:Additionally I have added to the documentation an example of the use of these options, which is built at: https://irl.github.io/cpython/library/ssl.html#encrypted-client-hello
📚 Documentation preview 📚: https://cpython-previews--135435.org.readthedocs.build/