-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Signed-off-by: Christian Heimes <[email protected]>
- Loading branch information
Showing
1 changed file
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,349 @@ | ||
PEP: 644 | ||
Title: Require OpenSSL 1.1 or newer | ||
Author: Christian Heimes <[email protected]> | ||
BDFL-Delegate: n/a | ||
Discussions-To: https://discuss.python.org/t/pep-644-require-openssl-1-1-or-newer/5584 | ||
Status: Draft | ||
Type: Standards Track | ||
Content-Type: text/x-rst | ||
Created: 27-Oct-2020 | ||
Python-Version: 3.10 | ||
Post-History: 27-Oct-2020 | ||
|
||
|
||
Abstract | ||
======== | ||
|
||
This PEP proposes for CPython’s standard library to support only OpenSSL | ||
1.1.1 LTS or newer. Support for OpenSSL versions past end-of-lifetime, | ||
incompatible forks, and other TLS libraries are dropped. | ||
|
||
|
||
Motivation | ||
========== | ||
|
||
Python makes use of OpenSSL in `hashlib`, `hmac`, and `ssl` modules. OpenSSL | ||
provides fast implementations of cryptographic primitives and a full TLS | ||
stack including handling of X.509 certificates. The `ssl` module is used by | ||
standard library modules like `urllib` and 3rd party modules like `urllib3` | ||
to implement secure variants of internet protocols. `pip` uses the `ssl` | ||
module to securely download packages from PyPI. Any bug in the ssl module's | ||
bindings to OpenSSL can lead to a severe security issue. | ||
|
||
Over time OpenSSL's public API has evolved and changed. Version 1.0.2 | ||
introduced new APIs to verify and match hostnames. OpenSSL 1.1.0 made | ||
internal structs opaque and introduced new APIs that replace direct access of | ||
struct members. Version 3.0.0 will deprecate more APIs due to internal | ||
reorganization that moves cryptographic algorithms out of the core and into | ||
providers. Forks like LibreSSL and BoringSSL have diverged in different | ||
directions. | ||
|
||
Currently Python versions 3.6 to 3.9 are compatible with OpenSSL 1.0.2, | ||
1.1.0, and 1.1.1. For the most part Python also works with LibreSSL >= 2.7.1 | ||
with some missing features and broken tests. | ||
|
||
Due to limited resources and time it becomes increasingly hard to support | ||
multiple versions and forks as well as test and verify correctness. Besides | ||
multiple incompatible APIs there are build time flags, | ||
distribution-specific patches, and local crypto-policy settings that add to | ||
plethora of combinations. On the other hand, the Python core team has only | ||
a couple of domain experts who are familiar with TLS and OpenSSL internals | ||
and even fewer who are active maintainers. | ||
|
||
Requiring OpenSSL 1.1.1 would allow us to give the vast majority of users a | ||
better experience, reduce our maintenance overhead and thus free resources | ||
to implement new features. Users would be able to rely on the presence of | ||
new features and consistent behavior, ultimately resulting in a more robust | ||
experience. | ||
|
||
|
||
Impact | ||
====== | ||
|
||
OpenSSL 1.1.1 is the default variant and version of OpenSSL on almost all | ||
supported platforms and distributions. It’s also the only version that still | ||
receives security support from upstream [9]_. | ||
|
||
No macOS and Windows user will be affected by the deprecation. The python.org | ||
installer and alternative distributions like Conda ship with most recent | ||
OpenSSL version. | ||
|
||
As of October 2020 and according to DistroWatch [1]_ most current BSD and | ||
Linux distributions ship with OpenSSL 1.1.1 as well. Some older releases of | ||
long term support (LTS) and enterprise distributions have older versions of | ||
OpenSSL or LibreSSL. By the time Python 3.10 will be generally available, | ||
several of these distributions will have reached end of lifetime, end of | ||
general support, or moved from LibreSSL to OpenSSL. | ||
|
||
Other software has dropped support for OpenSSL 1.0.2 as well. For example | ||
PyCA cryptography 3.2 (2020-10-25) removed compatibility with OpenSSL 1.0.2. | ||
|
||
|
||
OpenSSL 1.0.2 LTS | ||
----------------- | ||
|
||
released: 2015-02 | ||
end of lifetime: 2019-12 | ||
|
||
OpenSSL 1.0.2 added hostname verification, ALPN support, and elliptic curves. | ||
|
||
- CentOS 7 (EOL 2024-06) | ||
- Debian 8 Jessie (EOL 2020-07) | ||
- Linux Mint 18.3 (EOL 2021-04) | ||
- RHEL 7 (full support ends 2019-08, maintenance 2 support ends 2024-06) | ||
- SUSE Enterprise Linux 12-SP5 (general supports ends 2024-10) | ||
- Ubuntu 16.04 LTS / Xenial (general support ends 2021-04) | ||
|
||
|
||
OpenSSL 1.1.0 | ||
------------- | ||
|
||
released: 2016-08 | ||
end of lifetime: 2019-09 | ||
|
||
OpenSSL 1.1.0 removed or disabled insecure ciphers by default and added | ||
support for ChaCha20-Poly1305, BLAKE2 (basic features), X25519 and CT. The | ||
majority of structs were made opaque and new APIs were introduced. OpenSSL | ||
1.1.0 is not API compatible with 1.0.2. | ||
|
||
- Debian 9 Stretch (estimated EOL 2022-06) | ||
- Ubuntu 18.04 LTS / Bionic (general support ends 2023-04) | ||
|
||
|
||
OpenSSL 1.1.1 LTS | ||
----------------- | ||
|
||
released: 2018-08 | ||
end of lifetime: 2023-09 (planned) | ||
|
||
OpenSSL 1.1.1 added TLS 1.3, SHA-3, X448 and Ed448. | ||
|
||
- Alpine (switched back to OpenSSL in 2018 [4]_) | ||
- Arch Linux current | ||
- CentOS 8.0+ | ||
- Debian 10 Buster | ||
- Fedora 29+ | ||
- FreeBSD 11.3+ | ||
- Gentoo Linux stable | ||
- HardenedBSD (switched back to OpenSSL in 2018 [3]_) | ||
- Linux Mint 19.3+ | ||
- macOS (python.org installer) | ||
- NetBSD 8.2+ | ||
- openSUSE 15.2+ | ||
- RHEL 8.0+ | ||
- Slackware current | ||
- SUSE Enterprise Linux 15-SP2 | ||
- Ubuntu 18.10+ | ||
- Ubuntu 20.04 LTS / Focal | ||
- Windows (python.org installer, Conda) | ||
|
||
|
||
OpenSSL 3.0.0 | ||
------------- | ||
|
||
released: n/a (planned for early 2021) | ||
|
||
OpenSSL 3.0.0 is currently under development. Major changes include | ||
relicensing to Apache License 2.0 and a new API for cryptographic algorithms | ||
providers. Most changes are internal refactorings and don’t affect public | ||
APIs. [8]_ | ||
|
||
|
||
LibreSSL | ||
-------- | ||
|
||
created: 2014-04 (forked from OpenSSL 1.0.1g) | ||
|
||
- DragonFly BSD | ||
- Hyperbola GNU/Linux-libre | ||
- OpenBSD | ||
- OpenELEC (discontinued) | ||
- TrueOS (discontinued) | ||
- VOID Linux (currently moving back to OpenSSL [5]_) | ||
|
||
Some distributions like FreeBSD, Gentoo, and OPNsense also feature LibreSSL | ||
instead of OpenSSL as non-standard TLS libraries. | ||
|
||
OpenBSD ports has a port `security/openssl/1.1` which is documented as | ||
"[...] is present to provide support for applications which cannot be made | ||
compatible with LibReSSL" [7]_. The package could be used by OpenBSD to | ||
provide a working ssl module. | ||
|
||
|
||
BoringSSL | ||
--------- | ||
|
||
created: 2014-06 | ||
|
||
BoringSSL is Google’s fork of OpenSSL. It’s not intended for general use and | ||
therefore not supported by Python. There are no guarantees of API or ABI | ||
stability. Vendored copies of BoringSSL are used in Chrome/Chromium browser, | ||
Android, and on Apple platforms [6]_. | ||
|
||
|
||
Benefits | ||
======== | ||
|
||
TLS 1.3 | ||
------- | ||
|
||
OpenSSL 1.1.1 introduced support for the new TLS 1.3 version. The latest | ||
version of the TLS protocol has a faster handshake and is more secure than | ||
the previous versions. | ||
|
||
Thread and fork safety | ||
---------------------- | ||
|
||
Starting with release 1.1.0c, OpenSSL is fully fork and thread safe. | ||
Bindings no longer need any workarounds or additional callbacks to support | ||
multithreading. | ||
|
||
SHA-3 | ||
----- | ||
|
||
Since 1.1.0, OpenSSL ships with SHA-3 and SHAKE implementations. | ||
Python's builtin SHA-3 support is based on the reference implementation. The | ||
internal `_sha3` code is fairly large and the resulting shared library close | ||
to 0.5 MB. Python could drop the builtin implementation and rely on OpenSSL's | ||
`libcrypto` instead. | ||
|
||
So far LibreSSL upstream development has refused to add SHA-3 support. [2]_ | ||
|
||
|
||
Compatibility | ||
============= | ||
|
||
OpenSSL downstream patches and options | ||
-------------------------------------- | ||
|
||
OpenSSL features more than 70 configure and build time options in the form | ||
of `OPENSSL_NO_*` macros. Around 60 options affect the presence of features | ||
like cryptographic algorithms and TLS versions. Some distributions apply | ||
patches to alter settings. Furthermore default values for settings like | ||
security level, ciphers, TLS version range, and signature algorithms can | ||
be set in OpenSSL config file. | ||
|
||
The Python core team lacks resources to test all possible combinations. | ||
This PEP proposes that Python only supports OpenSSL builds that have | ||
standard features enabled. Vendors shall disable deprecated or insecure | ||
algorithms and TLS versions with build time options like | ||
`OPENSSL_NO_TLS1_1_METHOD` or OpenSSL config options like | ||
`MinProtocol = TLSv1.2`. | ||
|
||
Python assumes that OpenSSL is built with | ||
|
||
- hashlib’s default algorithms such as MD5, SHA-1, SHA-2 family, | ||
SHA-3/SHAKE family, BLAKE2 | ||
- TLS 1.2 and TLS 1.3 protocols | ||
- current key agreement, signature, and encryption algorithms for TLS 1.2 | ||
and 1.3 (ECDH, RSA, ECDSA, Curve25519, AES, Poly1309-ChaCha20, ...) | ||
- threading, file I/O, socket I/O, and error messages | ||
|
||
Weak algorithms (MD5, SHA-1 signatures) and short keys (RSA < 2024 bits) may | ||
be disabled at runtime. Algorithms may also be blocked when they are | ||
disabled by a crypto policy such as FIPS. The PEP is not more specific on | ||
purpose to give room for new features as well as countermeasures against | ||
vulnerabilities. As a rule of thumb, Python should be able to connect to | ||
PyPI and the test suite should pass. | ||
|
||
LibreSSL support | ||
---------------- | ||
|
||
LibreSSL is a fork of OpenSSL. The fork was created off OpenSSL 1.0.1g by | ||
members of the OpenBSD team in 2014 in light of the heartbleed vulnerability. | ||
Since its inception several features deemed problematic or insecure were | ||
removed or replaced (SSL 2.0, SSL 3.0, improved CPRNG) or backported | ||
from OpenSSL and BoringSSL. | ||
|
||
At the moment LibreSSL is not fully API compatible with OpenSSL 1.1.1. The | ||
latest release LibreSSL 3.3.2 is missing features and behaves differently | ||
in some cases. Mentionable missing or incompatible features include | ||
|
||
- SHA-3, SHAKE, BLAKE2 | ||
- `SSL_CERT_*` environment variables | ||
- security level APIs | ||
- session handling APIs | ||
- key logging API | ||
- verified cert chain APIs | ||
- OPENSSL_VERSION macro | ||
|
||
This PEP proposed to remove any and all LibreSSL related workarounds from | ||
Python. In the future Python will not actively prohibit LibreSSL support | ||
with configure and compile time checks. But Python will not accept patches | ||
that add non-trivial workarounds or disable tests either. | ||
|
||
|
||
BoringSSL | ||
--------- | ||
|
||
There are currently no plans to support BoringSSL. | ||
|
||
|
||
Rejected Ideas | ||
============== | ||
|
||
Formalize supported OpenSSL versions | ||
------------------------------------ | ||
|
||
This PEP does not provide a set of formal rules and conditions under which | ||
an OpenSSL version is supported. | ||
|
||
In general Python aims to be compatible with commonly used and officially | ||
supported OpenSSL versions. Patch releases of Python may not be compatible | ||
with new major releases of OpenSSL. Users should not expect that a new major | ||
or minor release of Python works with an OpenSSL version that is past its | ||
end-of-lifetime. Python core development may backport fixes for new releases | ||
or extend compatibility with EOLed releases as we see fit. | ||
|
||
The new ABI stability and LTS policies of OpenSSL [9]_ should help, too. | ||
|
||
|
||
Backwards Compatibility | ||
======================= | ||
|
||
Python 3.10 will no longer support TLS/SSL and fast hashing on platforms | ||
with OpenSSL 1.0.2 or LibreSSL. This PEP is published at the beginning of | ||
the 3.10 release cycles. It gives vendors like Linux distributors or CI | ||
providers roughly 11 months to react. | ||
|
||
|
||
Disclaimer and special thanks | ||
============================= | ||
|
||
The author of this PEP is a contributor to OpenSSL project and employed by | ||
a major Linux distributor that uses OpenSSL. | ||
|
||
Thanks to Alex Gaynor, Gregory P. Smith, Nathaniel J. Smith, Paul Kehrer, | ||
and Seth Larson for their review and feedback on the initial draft. | ||
|
||
|
||
References | ||
========== | ||
|
||
.. [1] https://distrowatch.com/ | ||
.. [2] https://github.com/libressl-portable/portable/issues/455 | ||
.. [3] https://hardenedbsd.org/article/shawn-webb/2018-04-30/hardenedbsd-switching-back-openssl | ||
.. [4] https://lists.alpinelinux.org/~alpine/devel/%3CCA%2BT2pCGFeh30aEi43hAvJ3yoHBijABy_U62wfjhVmf3FmbNUUg%40mail.gmail.com%3E | ||
.. [5] https://github.com/void-linux/void-packages/issues/20935 | ||
.. [6] https://forums.swift.org/t/rfc-moving-swiftnio-ssl-to-boringssl/18280 | ||
.. [7] https://openports.se/security/openssl/1.1 | ||
.. [8] https://www.openssl.org/docs/OpenSSL300Design.html | ||
.. [9] https://www.openssl.org/policies/releasestrat.html | ||
Copyright | ||
========= | ||
|
||
This document is placed in the public domain or under the | ||
CC0-1.0-Universal license, whichever is more permissive. | ||
|
||
|
||
|
||
.. | ||
Local Variables: | ||
mode: indented-text | ||
indent-tabs-mode: nil | ||
sentence-end-double-space: t | ||
fill-column: 70 | ||
coding: utf-8 | ||
End: |