-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
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
bpo-37952: SSL: add support for export_keying_material #25255
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.
Please include a blurb, tests, and more documentation. Documentation should explain what the function does, the meaning of each argument with examples and explain at which point of the handshake the function is available.
IMHO it would be helpfup to include an enum with most common export labels for standard TLS.
Modules/_ssl.c
Outdated
/* export_keying_material is present from 1.0.1 */ | ||
#if OPENSSL_VERSION_NUMBER >= 0x10001000L | ||
# define HAVE_EXPORT_KEYING_MATERIAL 1 | ||
#else | ||
# define HAVE_EXPORT_KEYING_MATERIAL 0 | ||
#endif | ||
|
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.
Python 3.10 will require OpenSSL >= 1.1.1
Modules/_ssl.c
Outdated
if (SSL_export_keying_material(self->ssl, | ||
key, key_len, | ||
label->buf, label->len, | ||
context->buf, context->len, | ||
context->buf != NULL) != 1) { |
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.
Please follow the error checking style of the module:
if (SSL_export_keying_material(self->ssl, | |
key, key_len, | |
label->buf, label->len, | |
context->buf, context->len, | |
context->buf != NULL) != 1) { | |
if (!SSL_export_keying_material(self->ssl, | |
key, key_len, | |
label->buf, label->len, | |
context->buf, context->len, | |
context->buf != NULL)) { |
Modules/_ssl.c
Outdated
Py_DECREF(out); | ||
out = 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.
Py_DECREF(out); | |
out = NULL; | |
Py_CLEAR(out); |
Modules/_ssl.c
Outdated
#if HAVE_EXPORT_KEYING_MATERIAL | ||
addbool(m, "HAS_EXPORT_KEYING_MATERIAL", 1); | ||
#else | ||
addbool(m, "HAS_EXPORT_KEYING_MATERIAL", 0); | ||
#endif | ||
|
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.
Not needed, the feature is always present in OpenSSL 1.1.1
#if HAVE_EXPORT_KEYING_MATERIAL | |
addbool(m, "HAS_EXPORT_KEYING_MATERIAL", 1); | |
#else | |
addbool(m, "HAS_EXPORT_KEYING_MATERIAL", 0); | |
#endif |
Lib/ssl.py
Outdated
@@ -1295,6 +1295,14 @@ def verify_client_post_handshake(self): | |||
else: | |||
raise ValueError("No SSL wrapper around " + str(self)) | |||
|
|||
def export_keying_material(self, label, key_len, context = None): |
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.
def export_keying_material(self, label, key_len, context = None): | |
def export_keying_material(self, label, key_len, context=None): |
Modules/_ssl.c
Outdated
if (key_len < 1) { | ||
PyErr_SetString(PyExc_ValueError, "key_len must be positive"); | ||
return 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.
key_len
should probably be limited, too.
Doc/library/ssl.rst
Outdated
@@ -1293,6 +1293,12 @@ SSL sockets also have the following additional methods and attributes: | |||
|
|||
.. versionadded:: 3.3 | |||
|
|||
.. method:: SSLSocket.export_keying_material(label, key_len, context) |
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.
.. method:: SSLSocket.export_keying_material(label, key_len, context) | |
.. method:: SSLSocket.export_keying_material(label, key_len, context=None) |
Modules/_ssl.c
Outdated
label: Py_buffer(accept={buffer, str, NoneType}) | ||
key_len: int | ||
context: Py_buffer(accept={buffer, str, NoneType}) |
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.
Why do you accept buffer, str, and None? Is this suppose to be optional text or bytes? The method should either accept text or bytes.
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 |
Test scenarios:
Please also include edge cases for label and context values, e.g. embedded NULL byte, non-ASCII, ... |
53c6c8b
to
7725b00
Compare
I've updated the patch and I believe that I've addressed all the review comments now. |
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.
Please fix all tests and then follow the instructions of bedevere-bot.
04f2f2a
to
d20645a
Compare
I was told that Python 3.10 will require OpenSSL 1.1.1. Some of these failures are because the tests are run with OpenSSL 1.1.0l which does not seem to support TLSv1.3. Oh well, I've added a check which skips the test if an older version of OpenSSL is used. And now all tests pass. |
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.
See https://discuss.python.org/t/openssl-3-0-0-support-3-8-to-3-10/8205. I'll drop 1.1.0 and 1.0.2 support next week or the week after.
You need to split the tests and protect each protocol test with @requires_tls_version
decorator for each used TLS version.
And please read and follow the instructions of bedevere-bot. The bot will trigger workflow changes and notify me when everything is ok.
d20645a
to
adb9ead
Compare
All checks pass now. It there anything else that's needed? |
398cd73
to
60f65cd
Compare
I have made the requested changes; please review again |
4e1865f
to
c23bd08
Compare
97884bb
to
c1b14f0
Compare
@tiran Can you please take a look at this patch again? |
I have made the requested changes; please review again |
Thanks for making the requested changes! @tiran: please review the changes made to this pull request. |
@tiran Is there any way to get this pull request accepted? |
Add support for the RFC5705 SSL_export_keying_material function to the Python SSL module.
c1b14f0
to
51a8a5c
Compare
Yet another year, yet another update of my patch. I have made the requested changes; please review again |
Thanks for making the requested changes! @tiran: please review the changes made to this pull request. |
Have I missed anything? It would be nice to get some kind of feedback. |
I no longer think that this feature should land in Python core. The ssl module provides a opinionated and limited API. Exporting key material a special feature for a narrow use case. Python core dev has limited resources. I'm basically the only maintainer of the ssl module and I don't want to burden myself with supporting this feature for the next five to ten years. I would rather move https://bugs.python.org/issue43902 forward so third party developers can use ctypes, cffi, or C code to access and modify raw |
@tiran thanks for your ongoing maintenance of ssl! Although I would like to see this pull request land, https://bugs.python.org/issue43902 would also work fine for my use case. Exporting keying material is being used more and more in IETF standards, and is pretty widely implemented: |
Sad to see that Python still don't have this in its ssl module :( Is there an alternative way to export keying material? |
Add support for the RFC5705 SSL_export_keying_material function to the Python SSL module.
OpenSSL has a function to "SSL_export_keying_material" as described in RFC5705. This functionality is needed to be able to support a bunch of other protocols such as "Network Time Security for the Network Time Protocol" which has now become a proper RFC as RFC8915. There are half a dozen other RFCs which also use this functionality.
This functionality is used in my implementation of the NTS procotol which can also be found on github:
https://github.com/Netnod/nts-poc-python
It would be very nice if mainline Python could support for t his function in the future so that I don't have to maintain a patched version of Python for this.
https://bugs.python.org/issue37952