Add an automatically generated OpenSSL backend for the Crypto Refresh and PQC code#2392
Open
kaie wants to merge 45 commits into
Open
Add an automatically generated OpenSSL backend for the Crypto Refresh and PQC code#2392kaie wants to merge 45 commits into
kaie wants to merge 45 commits into
Conversation
... for rnp_generate_key_ex add roundtrip test for PQC certs clang-format
require Botan 3.6.0 for PQC switch to final NIST PQC standards update KMAC Key Combiner
fail gracefully on parsing v6 cleartext sigs
also code formatting
Only compiling PQC support now gives the option to use v4 MLKEM768+X25519 encryption subkeys. Added a v4 ECC + PQC certificate to TUI
…ackend) Each PQC class (ML-KEM, ML-DSA, SLH-DSA, exdsa/ecdh-kem) previously exposed Botan types (Botan::secure_vector, botan_key() methods) in its header, which prevented those headers from compiling without Botan installed. - Add rnp::SecureBytes (secure_bytes.h/cpp): a backend-agnostic drop-in for Botan::secure_vector<uint8_t> that zeroes memory on destruction. - In each header: replace Botan includes with "crypto/secure_bytes.h"; replace Botan::secure_vector<uint8_t> private key members with rnp::SecureBytes; replace Botan::unlock(key_) with key_.unlock(); remove botan_key() / botan_key_*() private method declarations. - In each .cpp: move the Botan includes here; convert the removed class methods to file-scope static functions (e.g. kyber_privkey_from_bytes, x25519_privkey_from_bytes). No behaviour change; Botan build compiles and passes all tests unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
std::make_unique is a C++14 feature; the project builds with -std=c++11. Replace all std::make_unique<T>(...) with std::unique_ptr<T>(new T(...)). (The same issue exists in kyber_ecdh_composite.cpp and is fixed there as part of the OpenSSL AES key-wrap changes in the next commit.) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… SLH-DSA Implements ENABLE_PQC and ENABLE_CRYPTO_REFRESH for the OpenSSL backend (previously guarded by openssl_nope). Requires OpenSSL 3.5+; configure-time algorithm checks disable the feature if any PQC algorithm is absent. New files: - hkdf_ossl.hpp/cpp: HKDF via EVP_KDF "HKDF" - ed25519_ed448_ossl.cpp: Ed25519/Ed448 keygen, sign, verify, validate - x25519_x448_ossl.cpp: X25519/X448 KEM encap/decap for ECDH-KEM - exdsa_ecdhkem_ossl.cpp: ECDH-KEM and ECDSA-exdsa for NIST/brainpool curves (fixes two pre-existing bugs in the OpenSSL EC backend: EVP_PKEY_KEYPAIR -> EVP_PKEY_PRIVATE_KEY in load_nist_privkey, EVP_PKEY_check -> EVP_PKEY_private_check in is_valid for private-key-only objects) - kyber_ossl.cpp: ML-KEM encap/decap using OSSL_PKEY_PARAM_ML_KEM_SEED - dilithium_ossl.cpp: ML-DSA sign/verify using OSSL_PKEY_PARAM_ML_DSA_SEED - sphincsplus_ossl.cpp: SLH-DSA sign/verify via EVP_PKEY_new_raw_private_key_ex Modified: - CMakeLists.txt: resolve_feature_state for ENABLE_CRYPTO_REFRESH and ENABLE_PQC; add new source files; remove openssl_nope guards - hkdf.cpp: route to Hkdf_OpenSSL::create() instead of #error - ec_ossl.cpp: add ECDH encap/decap helpers needed by X25519/X448 KEM - kyber_ecdh_composite.cpp: AES-256 key wrap/unwrap via EVP_aes_256_wrap() for OpenSSL; also fix std::make_unique -> std::unique_ptr<>(new) for C++11 - ffi-enc.cpp: mark non-AES+AEAD and non-AES+PKESKv6 combos as expected-fail under CRYPTO_BACKEND_OPENSSL (OpenSSL only supports AES-OCB/EAX) - cli_tests.py: fall back from EAX to OCB when RNP_AEAD_EAX is unavailable Key format compatibility with Botan: - ML-KEM: 64-byte seed (OSSL_PKEY_PARAM_ML_KEM_SEED) — matches Botan - ML-DSA: 32-byte seed (OSSL_PKEY_PARAM_ML_DSA_SEED) — matches Botan - SLH-DSA: 4n raw bytes via get_raw_private_key — matches Botan All 301 OpenSSL-backend tests pass. Cross-backend round-trip tests pass for all 7 PQC composite key types (algos 25-28, 31-33) in both directions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
src/tests/pqc-crossbackend-test.sh exercises keyring interoperability between the Botan and OpenSSL backends for all seven PQC composite key types (ML-DSA+Ed25519, ML-DSA+Ed448, ML-DSA+ECDSA-P384/P521, and the three SLH-DSA variants). Each algorithm is tested in both directions: Botan generates / OpenSSL decrypts+verifies, and vice versa. Requires build/ (Botan, ENABLE_CRYPTO_REFRESH=ON) and build-ossl/ (OpenSSL 3.5+, same flags) to be present; see the file header for the cmake invocations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- kyber_ossl.cpp, dilithium_ossl.cpp: zero seed_buf[] with secure_wipe() before returning from keygen; Botan used secure_vector which zeroes automatically, leaving the stack buffer un-wiped was a deviation - sphincsplus_ossl.cpp: zero the temporary priv std::vector with secure_wipe() after copying into SecureBytes; same reasoning - exdsa_ecdhkem_ossl.cpp (verify): replace raw ECDSA_SIG * with rnp::ossl::ECDSASig RAII wrapper (already used in the sign path); also check the return value of the encoding i2d_ECDSA_SIG call - kyber_ecdh_composite.cpp: replace raw EVP_CIPHER_CTX * with rnp::ossl::evp::CipherCtx in both AES-256 key wrap and unwrap paths; add ossl_utils.hpp include for the OpenSSL build Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
secure_bytes.cpp was added to the OpenSSL backend's CRYPTO_SOURCES list but omitted from the equivalent Botan section, causing a link error for rnp::secure_wipe when building the Botan backend with ENABLE_PQC or ENABLE_CRYPTO_REFRESH enabled. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2392 +/- ##
=======================================
Coverage 85.46% 85.46%
=======================================
Files 126 126
Lines 22711 22732 +21
=======================================
+ Hits 19409 19428 +19
- Misses 3302 3304 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
These changes are based on top of PR #2355, which provides an implementation that uses the Botan backend, but does not provide a corresponding implementation for using the OpenSSL backend.
The patches that I'm providing here in addition have been machine generated by Claude Code.
The use of automatic generation was chosen by me, because I made the assumption that the human creative work that decided how to use crypto primitives to implement the OpenPGP functionality was already done and is contained in the base pull request, and that the implementation of the OpenSSL backend code could inspect the code that uses Botan, and produce equivalent code that uses OpenSSL.
The first patch removes some botan specific code from code that is shared across backends and replaces it with a new helper class for secure wiping of bytes. I reviewed that code and it looks correct to me.
The code builds and passes the existing RNP tests on Linux. I haven't built nor ran tests on other platforms.
A script is provided that tests the interoperability of data across the two backends.
The additional patch that addresses code review issues weren't based on a human review, but based on a re-review by the AI itself.
I'm hereby providing the code as is, but I want to make it clear that I couldn't have written the code to use OpenSSL myself in the time I have available, as I don't have experience with writing code for OpenSSL.
The code is provided in the hope it is useful, in the hope that the PQC functionality can be made available for all users of RNP regardless of which backend cryptography library is preferred, and I suggest that the code should get reviewed for correctness before considering to adopt it.
Regarding copyright headers, for all files that were newly written, Ribose was added as the only copyright holder.
However, those files were automatically created by using the equivalent code files as a template. So they are derivative work
For all files that were originally contributed by MTG, but which were modified by this work, Ribose was added as an additional copyright holder.
I'd like to leave it to Ribose to decide what the correct copyright section should be and fix those sections, if necessary.