зеркало из https://github.com/microsoft/CCF.git
4a364317cb
* Implement TLS in OpenSSL, support TLS 1.3 This is a large commit, implementing the TLS layer in OpenSSL, together with mbedTLS, and is part of a transition to eliminate mbedTLS from the codebase. The src/crypto part is done already and this is a similar effort on src/tls. The last part is src/clients (used for testing) and will be done as a future patch, with extensive testing separate than this work. This commit has a temporary structure, to allow a compiler flag to switch between OpenSSL and mbedTLS. Unlike src/crypto, we want the transition to be as short lived as possible, so we didn't try to create common classes, just an include trick to use the right library. The main changes, in order from most generic to most specific, are: 1. The CMake flag `TLS_PROVIDER_IS_MBEDTLS` was introduced, turned OFF by default, to build CCF with mbedTLS instead of OpenSSL. This is for testing, in case we find issues with the new implementation. This is in addition to `CRYPTO_PROVIDER_IS_MBEDTLS` so we can set each flag independently. 2. The OpenSSL library (`libssl`) that we use is from the same place we pick the Crypto library (`libcrypto`). Either the system or OpenEnclave, decided elsewhere. No new libraries are needed. 3. Some of the existing mbedTLS headers were moved to src/clients to isolate that migration from the server side. So far, it only needed `ca.h` and `cert.h`, which are self-conatined. Those will be removed with the mbedTLS cleanup. 4. A number of `#ifdef TLS_PROVIDER_IS_MBEDTLS` were added where there was no other way to common up implementation. Most notably in the previous TLS headers (`src/tls/*.h`) that are now just wrappers to the actual headers (`src/tls/{mbedtls,openssl}/*.h`). 5. All TLS errors on both mbedTLS and OpenSSL have been #defined to a common set of `TLS_ERR_` errors, to allow for common error handlind, including `WANT_READ` and `WANT_WRITE`. To keep the mbedTLS way, OpenSSL has a hack to return the negative counterparts of the error codes, so that we can treat them as errors, like mbedTLS. 6. To keep the current CCF implementation intact, we had to keep the callback mechanism in OpenSSL. This isn't the most natural way of handling BIOs but it works. Both `tls_endpoint` and `tls_test` have a similar implementation, handling asynchronous I/O. This should disappear later (probably well after removing mbedTLS from the codebase), once we manage to get BIOs directly to the users, from the OpenSSL implementation. 7. A number of mbedTLS functionality, most notably in `context.h`, has been adapted to allow a common implementation between the two libraries, for example `peer_cert()` and `get_verify_error`. 8. A copy of `crypto::error_string()` is present in the TLS side so that we can more easily control each (crypto/tls) with the CMake flags. 9. A number of log messages were added or changed to convey more information to help diagnose TLS issues. Not all development log messages survived into the production patch, but those that did can still convey most of the information and help at least zero in on where you need to add more logs later. 10. Removed two unused methods in `Context`: `available_bytes` and `set_require_auth`. Those were never called and had no easy equivalent in OpenSSL. Added exceptions for some unused parameters in OpenSSL's `CA` and `Cert` to make sure we never use them. If those never hit on any further testing or benchmarking, then we're safe to remove them when we clean up mbedTLS. 11. Added a number of `FIXME` comments, highlighting the assumptions from reading the mbedTLS code and what the tests have shown it does/needs. Some of them may be wrong, and if so, we need to fix them before we start with the mbedTLS cleanup. 12. Added a very large `get_verify_error` in `OpenSSL::Context` with all errors the `verify_result` can throw. This wasn't really necessary but was added as a debugging tool. Once we're happy none of those weird corner cases happen on our code, we should really remove all unused ones and common up in a `case default:`, where developers can add specific ones later for debugging purposes again. 13. Updated the `tls_test` to handle multi-part messages (past 16K), supporting large messages, like `tls_endpoint`. Also truncated the large messages to make it easier to read the test logs. 14. Changed the e2e_logging.py large message range from 2^10 (instead of 2^14), to help developers see some messages pass before the 16K threshold, which helped me realise what the problem was. 15. Added a long README document with all core issues with the port, and discussions on how to clean up in the future. * Trying to fix the ubsan error * Remove unnecessary FIXMEs * Add FIXME to check-todo.sh * We don't need MbedTLS entropy for OpenSSL The entropy source isn't a generic implementation, but one based on mbedTLS, which we don't need for OpenSSL. This removes the last FIXME. * Restrict SSL cipher to TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 To improve security and keep the same behaviour, this commit forces specific TLS1.2 and TLS1.3 ciphers that were used in the mbedTLS implementation. This fixes all problems in the tls_report but one: Secure Client-Initiated Renegotiation -> VULNERABLE (NOT ok), DoS threat (6 attempts) This will be looked at on the next patch. * Disable renegotiation to avoid DoS attacks This makes the tls_report identical to previous mbedTLS. * Free temporary BIOs in CA/Cert c-tors Detected by leak sanitizers, but I should have known better... * Use Unique_BIO|X509 in peer_cert to avoid leaks Following the C-style code in OpenSSL's documentation was a bad idea. Using unique_ptr wrappers to guarantee nothing leaks. * Simplify get_verify_error to avoid UB on memcpy Same as previous UB, writing at the end of a string. Using std::string to avoid any memory manipulation by hand. * Fix typos |
||
---|---|---|
.. | ||
infra | ||
js-app-bundle | ||
js-authentication | ||
js-content-types | ||
js-custom-authorization | ||
js-launch-host-process | ||
js-limits | ||
js-modules | ||
npm-app | ||
raft_scenarios | ||
sandbox | ||
suite | ||
ca_certs.py | ||
certs.py | ||
cimetrics_env.sh | ||
cleanup_iptables.py | ||
code_update.py | ||
committable.py | ||
config.jinja | ||
connections.py | ||
docker_wrap.sh | ||
e2e_batched.py | ||
e2e_common_endpoints.py | ||
e2e_logging.py | ||
e2e_operations.py | ||
e2e_suite.py | ||
e2e_tutorial.py | ||
election.py | ||
generate_vegeta_targets.py | ||
governance.py | ||
governance_history.py | ||
governance_js.py | ||
historical_query_perf.py | ||
jwt_test.py | ||
lts_compatibility.py | ||
memberclient.py | ||
membership.py | ||
nobuiltins.py | ||
partitions_test.py | ||
perf_logging_scenario_100txs.json | ||
plot_node_load.py | ||
raft_scenarios_gen.py | ||
raft_scenarios_runner.py | ||
reconfiguration.py | ||
recovery.py | ||
requirements.txt | ||
rotation.py | ||
schema.py | ||
sgxinfo.sh | ||
start_network.py | ||
test_install.sh | ||
test_install_build.sh | ||
test_python_cli.sh | ||
tests.sh | ||
tlstest.py | ||
upload_pico_metrics.py | ||
vegeta_stress.py |