-
-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
Python SSL stack doesn't support Elliptic Curve ciphers #57836
Comments
Python SSL doesn't support Elliptic Curve ciphers in in all version tested. This is a serious performance issue because it's not possible to use as a server or as client the performance improvement provided by ECC based ciphers. ECC provide a strong performance improvements (even x3) also when used with Perfect Forward Secrecy enabled ciphers like described on: In order to enable ECC ciphers (and eventually ECC keys) the SSL implementation the in the file Modules/_ssl.c must be modified. For example apache had several modifications to support ECC on their SSL (openssl based) stack: So Python SSL module should introduce similar modifications to fully support Elliptic Curve ciphers for SSL in order to:
|
Other example for DH and ECC from: #ifndef OPENSSL_NO_DH
static int init_dh(SSL_CTX *ctx, const char *cert) {
DH *dh;
BIO *bio;
bio = BIO_new_file(cert, "r");
if (!bio) {
ERR_print_errors_fp(stderr);
return -1;
}
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
if (!dh) {
ERR("{core} Note: no DH parameters found in %s\n", cert);
return -1;
}
#ifdef NID_X9_62_prime256v1
EC_KEY *ecdh = NULL;
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
SSL_CTX_set_tmp_ecdh(ctx,ecdh);
EC_KEY_free(ecdh);
LOG("{core} ECDH Initialized with NIST P-256\n");
#endif
return 0;
}
#endif /* OPENSSL_NO_DH */
#ifndef OPENSSL_NO_DH
init_dh(ctx, OPTIONS.CERT_FILE);
#endif /* OPENSSL_NO_DH */ |
It's not obvious to me which APIs should be used to provide such support. Python mostly uses high-level OpenSSL APIs, and lets OpenSSL load certificates. Do you want to try writing a patch? General instructions on how to contribute can be found at http://docs.python.org/devguide/ |
Have a look also at DH related ticket: http://bugs.python.org/issue13626 There is a code example on how PHP manage the DH parameter setup with high level OpenSSL. The code must check if the ciphers is EC or DH and in that case setup appropriate parameters by generating random data for DH operations. |
Ok, so you are talking specifically about ECDH? Or is there something to be done for generic EC support? OpenSSL has a SSL_CTX_set_tmp_dh() function (macro, actually), but it's undocumented. Best bet is probably to follow ssl/ssltest.c (OpenSSL source tree), lines 825 and following, under "#ifndef OPENSSL_NO_ECDH". |
This is how the Stud software enable also the use of ECC in OpenSSL TLS |
Here is a patch adding a set_ecdh_curve() method on SSL contexts, and a ssl.OP_SINGLE_ECDH_USE option flag. This is enough to enable ECDH with compatible clients (I've tested with Firefox and openssl s_client). |
So, with this patch it should be possible to strictly enable ciphers such as: Which ciphers did you negotiated succesfully? While with the implementation of http://bugs.python.org/issue13627 (DH/DHE ciphers) we should be able to negotiate: Do you expect it would be a difficult step to handle also the DH/DHE (non ECC) negotiation? Additionally it would be imho very important if the Python language would provide a "default ciphers setup" that look at maximum compatibility, performance and security. If it sounds fine for you, i would open another ticket to create a default cipherlist. |
I didn't try to negotiate a specific cipher, I just saw that the
You mean bpo-13626.
No, but that's bpo-13626 :)
You have the set_ciphers() method which allows you to set a "cipher For example the following setting gives you only ECDH ciphers with $ openssl ciphers -v 'kEECDH:!NULL:!aNULL'
ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
ECDHE-RSA-DES-CBC3-SHA SSLv3 Kx=ECDH Au=RSA Enc=3DES(168) Mac=SHA1
ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=3DES(168) Mac=SHA1
ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1
ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1
ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1
ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1 We are not cryptography experts and I don't think it would be a good (furthermore, I don't think "maximum compatibility, performance and |
The Tor Project is composed of Cryptography experts, thus i am opening that ticket cause with our group we're implementing Tor2web based on Python that require *strict* security requirements for crypto. The Tor Project heavily use Python for most of tools. If you want we can open a discussion within Tor Project to have a "rationale method" to define a set of "default ciphers" considering the ration of security/performance/compatibility. That way anyone using Python SSL/TLS will be sure in using a "Secure system" without the risk of legacy protocol such as SSLv2 or insecure ciphers like Export 40bit DES that are nowdays enabled by default. Today a Python coder approaching SSL/TLS will have an insecurely configured TLS connection that can be hijacked via SSLv2 protocol or cracked via 40bit DES. Even Firefox, Chrome, IE, Opera disable by default certain protocols and certain ciphers, so imho it would be valuable to have a "Secure default", obviously considering and maintaining compatibility. What do you think? |
Why don't you simple define your own default ciphers and call the That said, we could perhaps call set_ciphers("HIGH") by default. This |
Created a ticket there for a default-setting: Python SSL Stack doesn't have a Secure Default set of ciphers |
New changeset 8b729d65cfd2 by Antoine Pitrou in branch 'default': |
Patch now committed in 3.3. |
ECC is *not* available in the OpenSSL package provided on RedHat systems. RedHat intentionally strips it due to patent concerns (http://en.wikipedia.org/wiki/ECC_patents). Therefore committing this work made it much more difficult to build the ssl module on RedHat systems. I couldn't find a clear statement of this in any RedHat documentation, but I did find a few references to the stripping in these places:
Perhaps we should make these algorithms build conditional? Are these patent issues of concern to us? |
Well, if RedHat used the "standard" OPENSSL_NO_ECDH flag, it's easy |
Can you post the exact compiler errors you encountered? |
Nevermind, I've found them on the Fedora buildbot. |
New changeset ec44f2e82707 by Antoine Pitrou in branch 'default': |
Since we're at it, do you know if Redhat also disables regular Diffie-Hellman? See bpo-13626. |
ec44f2e82707 fixed compilation on Fedora and test_ssl passed fine. |
Awesome, thanks Antoine. I will checkout the DH patch from bpo-13626 on Fedora today. |
I'm getting a failure building on Mac OS X Leopard (10.5.8) relating to ECDH: /Users/vinay/projects/pythonv/Modules/_ssl.c: In function ""PyInit__ssl": The relevant line PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE); isn't bracketed with #ifndef OPENSSL_NO_ECDH/#endif - shouldn't it be? |
Thanks for reporting. It should be fixed in c1a07c8092f7. Can you try? |
That error goes away, but there are others. Sorry, I missed them in amongst the warnings, or I would have posted all of them. Here's the complete console output for the _ssl extension: building '_ssl' extension Failed to build these modules: |
Uh, what is the OpenSSL version there? |
It looks like it's OpenSSL 0.9.7. It's an old machine which I can't change things on - it's got MacPorts OpenSSL which is 1.0.0g, and I thought it was using that. On closer investigation, the version in /usr/include (0.9.7l) is actually being included. Presumably, even if only an old version of OpenSSL is available, Python should still build cleanly, even if it's without Elliptic Curve cipher support? If you'd like me to try anything else, just ask. |
Oh - and, ECDH is not matched by any file in that OpenSSL include directory/hierarchy. |
Also, if it's OK for the Elliptic Curve code to be optional in builds, the failure to import OP_SINGLE_ECDH_USE into ssl.py from _ssl should not cause "import ssl" to fail. |
Ok, can you try again? 06ed9b3f02af |
Almost there. The file now compiles, but a failure occurs in a later step due to compression functionality being unavailable: building '_ssl' extension Failed to build these modules: It looks as if OPENSSL_NO_COMP needs to be defined in _ssl.c if the OpenSSL version is too old and not already defined. With this change: #if OPENSSL_VERSION_NUMBER < 0x0090800fL && !defined(OPENSSL_NO_COMP)
# define OPENSSL_NO_COMP
#endif the ssl library builds without errors. However, test_ssl fails because it still expects OP_SINGLE_ECDH_USE to be defined. With this change in test_constants: if ssl.HAS_ECDH:
ssl.OP_SINGLE_ECDH_USE all tests pass. I notice that the test there for OP_NO_COMPRESSION is version-based rather than capability-based, and it might be a good idea to change this too. |
Could you provide a patch with those proposed changes? Le samedi 18 février 2012 à 00:45 +0000, Vinay Sajip a écrit :
|
Attached. |
Thanks. Should be fixed in 1a06f0a8120f. Can you check? :) |
Good news: the _ssl module builds OK, the ssl module can be imported, and test_ssl now has no failures on Mac OS X 10.5.8 / OpenSSL 0.9.7 :-) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: