From 8812fd2690381b548e292ea59bbfc4f4623c364f Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 15 Aug 2016 12:00:52 +0200 Subject: [PATCH] Add ChaCha20 Poly1305 to SSL ciphers https://bugs.python.org/issue27766 --- Doc/library/ssl.rst | 7 +++++++ Lib/ssl.py | 35 ++++++++++++++++++++++++++++++----- Modules/_ssl.c | 21 +++++++++++++++++++++ Modules/clinic/_ssl.c.h | 20 +++++++++++++++++++- 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 5792d0d407ba224bc4b42c78af613630f341ff51..95e3cf596dd0382d1a2da77c836ddf748e01a7a1 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -279,6 +279,13 @@ purposes. RC4 was dropped from the default cipher string. + .. versionchanged:: 3.6 + + ChaCha20/Poly1305 was added to the default cipher string. On machines + with CPU instructions for AES and GCM (AES-NI, PCLMULQDQ), AESGCM + is prefered over CHACHA20. Otherwise CHACHA20 is prefered over AESGCM. + CHACHA20 is available in OpenSSL >= 1.1.0. + Random generation ^^^^^^^^^^^^^^^^^ diff --git a/Lib/ssl.py b/Lib/ssl.py index 560cfef77661a0300447f0b102eb060585ab5861..3d4480dac0ca77c0e410fbdcf2c4ab77c6991d4c 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -155,6 +155,21 @@ if _ssl.HAS_TLS_UNIQUE: else: CHANNEL_BINDING_TYPES = [] + +def _fast_aesgcm(): + """Check for AES-NI and PCLMULQDQ CPU instructions + """ + ia32cap = _ssl.ia32cap() + if not ia32cap: + return False + # AES native instructions + aesni = (ia32cap & (1<<57)) == (1<<57) + # PCLMULQDQ, carry-less multiplication + clmul = (ia32cap & (1<<33)) == (1<<33) + return aesni and clmul + +_FAST_AESGCM = _fast_aesgcm() + # Disable weak or insecure ciphers by default # (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL') # Enable a better set of ciphers by default @@ -162,27 +177,37 @@ else: # * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) # * Prefer ECDHE over DHE for better performance # * Prefer any AES-GCM over any AES-CBC for better performance and security +# * Prefer any AES-GCM over ChaCha20 on platforms with AES-NI and CLMUL +# * Otherwise prefer ChaCha20 over AES-GCM # * Then Use HIGH cipher suites as a fallback # * Then Use 3DES as fallback which is secure but slow # * Disable NULL authentication, NULL encryption, and MD5 MACs for security # reasons + +if _FAST_AESGCM: + _FAST_CIPHERS = 'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20' +else: + _FAST_CIPHERS = 'ECDH+CHACHA20:ECDH+AESGCM:DH+CHACHA20:DH+AESGCM' + _DEFAULT_CIPHERS = ( - 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' - 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:' - '!eNULL:!MD5' -) + _FAST_CIPHERS + ':ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' + 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:' + '!aNULL:!eNULL:!MD5' + ) # Restricted and more secure ciphers for the server side # This list has been explicitly chosen to: # * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) # * Prefer ECDHE over DHE for better performance # * Prefer any AES-GCM over any AES-CBC for better performance and security +# * Prefer any AES-GCM over any AES-CBC for better performance and security +# * Prefer any AES-GCM over ChaCha20 on platforms with AES-NI and CLMUL # * Then Use HIGH cipher suites as a fallback # * Then Use 3DES as fallback which is secure but slow # * Disable NULL authentication, NULL encryption, MD5 MACs, DSS, and RC4 for # security reasons _RESTRICTED_SERVER_CIPHERS = ( - 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' + _FAST_CIPHERS + ':ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:' '!eNULL:!MD5:!DSS:!RC4' ) diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 8a4654a7be5c405bb612b36208e6c152c9c88453..95b158098305dbd65e81494d5dbb168b12fca06b 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -4106,6 +4106,26 @@ _ssl_nid2obj_impl(PyObject *module, int nid) return result; } + +/*[clinic input] +_ssl.ia32cap + +Get IA-32 processor capabilities vector +[clinic start generated code]*/ + +static PyObject * +_ssl_ia32cap_impl(PyObject *module) +/*[clinic end generated code: output=cb1e821264548c89 input=47e36d7a8d40e5b6]*/ +{ + unsigned long *ia32cap = OPENSSL_ia32cap_loc(); + if (ia32cap == NULL) { + Py_RETURN_NONE; + } else { + return PyLong_FromUnsignedLong(*ia32cap); + } +} + + #ifdef _MSC_VER static PyObject* @@ -4372,6 +4392,7 @@ static PyMethodDef PySSL_methods[] = { _SSL_ENUM_CRLS_METHODDEF _SSL_TXT2OBJ_METHODDEF _SSL_NID2OBJ_METHODDEF + _SSL_IA32CAP_METHODDEF {NULL, NULL} /* Sentinel */ }; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 0bdc35e5f9cdaf8f1966025e397c22ccbb6b57b3..8e068ba93b6c6bbaf23b5ef202184a35c037cb97 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -1041,6 +1041,24 @@ exit: return return_value; } +PyDoc_STRVAR(_ssl_ia32cap__doc__, +"ia32cap($module, /)\n" +"--\n" +"\n" +"Get IA-32 processor capabilities vector"); + +#define _SSL_IA32CAP_METHODDEF \ + {"ia32cap", (PyCFunction)_ssl_ia32cap, METH_NOARGS, _ssl_ia32cap__doc__}, + +static PyObject * +_ssl_ia32cap_impl(PyObject *module); + +static PyObject * +_ssl_ia32cap(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _ssl_ia32cap_impl(module); +} + #if defined(_MSC_VER) PyDoc_STRVAR(_ssl_enum_certificates__doc__, @@ -1143,4 +1161,4 @@ exit: #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=6057f95343369849 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b40f8e3200dd4035 input=a9049054013a1b77]*/ -- 2.7.4