From f8e33e5e449a1bee122eef6821878ee0e929fd5a Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sat, 22 Aug 2026 11:12:42 +0200 Subject: [PATCH 1/2] crypto: enable SM4-GCM, SM4-CCM, and SM4-XTS ciphers Signed-off-by: Filip Skokan --- deps/ncrypto/ncrypto.cc | 40 ++++++++++++++----- deps/ncrypto/ncrypto.h | 17 +++++++- doc/api/crypto.md | 6 +++ test/fixtures/aead-vectors.js | 32 +++++++++++++++ test/parallel/test-crypto-authenticated.js | 2 +- .../test-crypto-cipheriv-decipheriv.js | 38 ++++++++++++++++++ test/parallel/test-crypto-getcipherinfo.js | 17 ++++++++ 7 files changed, 139 insertions(+), 13 deletions(-) diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index 7fee21198c18..a5e7bebe1bad 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -4481,13 +4481,13 @@ bool SSLCtxPointer::setCipherSuites(const char* ciphers) { // ============================================================================ -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS Cipher::Cipher(DeleteFnPtr cipher) : cipher_(cipher.get()), fetched_cipher_(std::move(cipher)) {} #endif Cipher::Cipher(const Cipher& other) : cipher_(other.cipher_) { -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS if (other.fetched_cipher_ != nullptr) { if (EVP_CIPHER_up_ref(other.fetched_cipher_.get()) == 1) { fetched_cipher_.reset(other.fetched_cipher_.get()); @@ -4500,7 +4500,7 @@ Cipher::Cipher(const Cipher& other) : cipher_(other.cipher_) { Cipher& Cipher::operator=(const Cipher& other) { if (this == &other) return *this; -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS if (other.fetched_cipher_ != nullptr) { if (EVP_CIPHER_up_ref(other.fetched_cipher_.get()) == 1) { fetched_cipher_.reset(other.fetched_cipher_.get()); @@ -4521,7 +4521,7 @@ const Cipher Cipher::FromName(const char* name) { const EVP_CIPHER* cipher = EVP_get_cipherbyname(name); if (cipher != nullptr) return Cipher(cipher); -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS MarkPopErrorOnReturn mark_pop_error_on_return; DeleteFnPtr fetched( EVP_CIPHER_fetch(nullptr, name, nullptr)); @@ -4536,7 +4536,14 @@ const Cipher Cipher::FromName(const char* name) { mode == EVP_CIPH_GCM_SIV_MODE || #endif false; - if (is_siv_mode) return Cipher(std::move(fetched)); + const bool is_sm4_cipher = +#if OPENSSL_WITH_SM4_PROVIDER_CIPHERS + EVP_CIPHER_is_a(fetched.get(), "SM4-GCM") || + EVP_CIPHER_is_a(fetched.get(), "SM4-CCM") || + EVP_CIPHER_is_a(fetched.get(), "SM4-XTS") || +#endif + false; + if (is_siv_mode || is_sm4_cipher) return Cipher(std::move(fetched)); return Cipher(); #else @@ -4548,7 +4555,7 @@ const Cipher Cipher::FromNid(int nid) { const EVP_CIPHER* cipher = EVP_get_cipherbynid(nid); if (cipher != nullptr) return Cipher(cipher); -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS const char* name = OBJ_nid2sn(nid); if (name != nullptr) return FromName(name); #endif @@ -4706,7 +4713,7 @@ const char* Cipher::getName() const { const char* name = OBJ_nid2sn(nid); if (name != nullptr) return name; } -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS return EVP_CIPHER_get0_name(cipher_); #else return {}; @@ -6320,6 +6327,14 @@ constexpr const char* kProviderOnlyAesGcmSivCiphers[] = { }; #endif +#if OPENSSL_WITH_SM4_PROVIDER_CIPHERS +constexpr const char* kProviderOnlySm4Ciphers[] = { + "sm4-gcm", + "sm4-ccm", + "sm4-xts", +}; +#endif + #if OPENSSL_VERSION_MAJOR >= 3 template , #endif &context); -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS auto maybe_push_provider_only_cipher = [&](const char* name) { - EVP_CIPHER* cipher = EVP_CIPHER_fetch(nullptr, name, nullptr); + DeleteFnPtr cipher( + EVP_CIPHER_fetch(nullptr, name, nullptr)); if (cipher == nullptr) return; - EVP_CIPHER_free(cipher); context.cb(name); }; #endif @@ -6404,6 +6419,11 @@ void Cipher::ForEach(Cipher::CipherNameCallback callback) { maybe_push_provider_only_cipher(name); } #endif +#if OPENSSL_WITH_SM4_PROVIDER_CIPHERS + for (const char* name : kProviderOnlySm4Ciphers) { + maybe_push_provider_only_cipher(name); + } +#endif #endif } diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 34352ffceb16..d7c7efdac759 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -117,6 +117,19 @@ #define OPENSSL_WITH_AES_GCM_SIV 0 #endif +#if !defined(OPENSSL_IS_BORINGSSL) && OPENSSL_VERSION_PREREQ(3, 0) +#define OPENSSL_WITH_SM4_PROVIDER_CIPHERS 1 +#else +#define OPENSSL_WITH_SM4_PROVIDER_CIPHERS 0 +#endif + +#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV || \ + OPENSSL_WITH_SM4_PROVIDER_CIPHERS +#define OPENSSL_WITH_FETCHED_CIPHERS 1 +#else +#define OPENSSL_WITH_FETCHED_CIPHERS 0 +#endif + #if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_PREREQ(3, 2) #define OPENSSL_WITH_SIGNATURE_CONTEXT_STRING 1 #else @@ -452,7 +465,7 @@ class Cipher final { Cipher(const Cipher& other); Cipher& operator=(const Cipher& other); inline Cipher& operator=(const EVP_CIPHER* cipher) { -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS fetched_cipher_.reset(); #endif cipher_ = cipher; @@ -550,7 +563,7 @@ class Cipher final { private: const EVP_CIPHER* cipher_ = nullptr; -#if OPENSSL_WITH_AES_SIV || OPENSSL_WITH_AES_GCM_SIV +#if OPENSSL_WITH_FETCHED_CIPHERS explicit Cipher(DeleteFnPtr cipher); DeleteFnPtr fetched_cipher_; #endif diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 4c61a34a0030..5f2f4a5779db 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -3566,6 +3566,9 @@ operations. The specific constants currently defined are described in