From 5f9b8b334968f76db76910a4b4e308b50dae935e Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 11 Jan 2026 01:19:52 +0100 Subject: [PATCH 1/2] feat: sync source code with nodejs/node --- include/ncrypto.h | 248 +++++-------- src/ncrypto.cpp | 920 +++++++++++----------------------------------- tests/basic.cpp | 6 +- 3 files changed, 323 insertions(+), 851 deletions(-) diff --git a/include/ncrypto.h b/include/ncrypto.h index 263c4dc..970e766 100644 --- a/include/ncrypto.h +++ b/include/ncrypto.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -16,17 +17,13 @@ #include #endif -#include #include -#include #include #include #include #include #include #include -#include -#include #if NCRYPTO_DEVELOPMENT_CHECKS #include @@ -92,7 +89,10 @@ inline bool EqualNoCase(const std::string_view a, const std::string_view b) { #define NCRYPTO_STR(x) #x #define NCRYPTO_REQUIRE(EXPR) \ { \ - if (!(EXPR) { abort(); }) } + if (!(EXPR)) { \ + abort(); \ + } \ + } #define NCRYPTO_FAIL(MESSAGE) \ do { \ @@ -269,8 +269,6 @@ class ECKeyPointer; class Dsa; class Rsa; class Ec; -class Aead; -class AeadCtxPointer; struct StackOfXASN1Deleter { void operator()(STACK_OF(ASN1_OBJECT) * p) const { @@ -325,25 +323,7 @@ DataPointer xofHashDigest(const Buffer& data, const EVP_MD* md, size_t length); -template -class ModeMixin { - public: - std::string_view getModeLabel() const; - - bool isGcmMode() const { return self().getMode() == EVP_CIPH_GCM_MODE; } - bool isWrapMode() const { return self().getMode() == EVP_CIPH_WRAP_MODE; } - bool isCtrMode() const { return self().getMode() == EVP_CIPH_CTR_MODE; } - bool isCcmMode() const { return self().getMode() == EVP_CIPH_CCM_MODE; } - bool isOcbMode() const { return self().getMode() == EVP_CIPH_OCB_MODE; } - bool isStreamMode() const { - return self().getMode() == EVP_CIPH_STREAM_CIPHER; - } - - private: - const T& self() const { return static_cast(*this); } -}; - -class Cipher final : public ModeMixin { +class Cipher final { public: static constexpr size_t MAX_KEY_LENGTH = EVP_MAX_KEY_LENGTH; static constexpr size_t MAX_IV_LENGTH = EVP_MAX_IV_LENGTH; @@ -352,10 +332,12 @@ class Cipher final : public ModeMixin { #else static constexpr size_t MAX_AUTH_TAG_LENGTH = 16; #endif - // FIXME: These constants are not available in all OpenSSL/BoringSSL versions - // static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && - // EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && - // EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH); + static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH +#ifndef OPENSSL_IS_BORINGSSL + && EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && + EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH +#endif + ); Cipher() = default; Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {} @@ -376,9 +358,15 @@ class Cipher final : public ModeMixin { int getIvLength() const; int getKeyLength() const; int getBlockSize() const; - + std::string_view getModeLabel() const; const char* getName() const; + bool isGcmMode() const; + bool isWrapMode() const; + bool isCtrMode() const; + bool isCcmMode() const; + bool isOcbMode() const; + bool isStreamMode() const; bool isChaCha20Poly1305() const; bool isSupportedAuthenticatedMode() const; @@ -471,78 +459,8 @@ class Dsa final { OSSL3_CONST DSA* dsa_; }; -class BignumPointer final { - public: - BignumPointer() = default; - explicit BignumPointer(BIGNUM* bignum); - explicit BignumPointer(const unsigned char* data, size_t len); - BignumPointer(BignumPointer&& other) noexcept; - BignumPointer& operator=(BignumPointer&& other) noexcept; - NCRYPTO_DISALLOW_COPY(BignumPointer) - ~BignumPointer(); - - int operator<=>(const BignumPointer& other) const noexcept; - int operator<=>(const BIGNUM* other) const noexcept; - inline operator bool() const { return bn_ != nullptr; } - inline BIGNUM* get() const noexcept { return bn_.get(); } - void reset(BIGNUM* bn = nullptr); - void reset(const unsigned char* data, size_t len); - BIGNUM* release(); - - bool isZero() const; - bool isOne() const; - - bool setWord(unsigned long w); // NOLINT(runtime/int) - unsigned long getWord() const; // NOLINT(runtime/int) - - size_t byteLength() const; - size_t bitLength() const; - - DataPointer toHex() const; - DataPointer encode() const; - DataPointer encodePadded(size_t size) const; - size_t encodeInto(unsigned char* out) const; - size_t encodePaddedInto(unsigned char* out, size_t size) const; - - using PrimeCheckCallback = std::function; - int isPrime(int checks, - PrimeCheckCallback cb = defaultPrimeCheckCallback) const; - struct PrimeConfig { - int bits; - bool safe = false; - const BignumPointer& add; - const BignumPointer& rem; - }; - - static BignumPointer NewPrime( - const PrimeConfig& params, - PrimeCheckCallback cb = defaultPrimeCheckCallback); - - bool generate(const PrimeConfig& params, - PrimeCheckCallback cb = defaultPrimeCheckCallback) const; - - static BignumPointer New(); - static BignumPointer NewSecure(); - static BignumPointer NewSub(const BignumPointer& a, const BignumPointer& b); - static BignumPointer NewLShift(size_t length); - - static DataPointer Encode(const BIGNUM* bn); - static DataPointer EncodePadded(const BIGNUM* bn, size_t size); - static size_t EncodePaddedInto(const BIGNUM* bn, - unsigned char* out, - size_t size); - static int GetBitCount(const BIGNUM* bn); - static int GetByteCount(const BIGNUM* bn); - static unsigned long GetWord(const BIGNUM* bn); // NOLINT(runtime/int) - static const BIGNUM* One(); - - BignumPointer clone(); - - private: - DeleteFnPtr bn_; - - static bool defaultPrimeCheckCallback(int, int) { return 1; } -}; +// ============================================================================ +// RSA class Rsa final { public: @@ -604,10 +522,6 @@ class Ec final { const EC_GROUP* getGroup() const; int getCurve() const; - uint32_t getDegree() const; - std::string getCurveName() const; - const EC_POINT* getPublicKey() const; - const BIGNUM* getPrivateKey() const; inline operator bool() const { return ec_ != nullptr; } inline operator OSSL3_CONST EC_KEY*() const { return ec_; } @@ -617,16 +531,8 @@ class Ec final { using GetCurveCallback = std::function; static bool GetCurves(GetCurveCallback callback); - inline const BignumPointer& getX() const { return x_; } - inline const BignumPointer& getY() const { return y_; } - inline const BignumPointer& getD() const { return d_; } - private: OSSL3_CONST EC_KEY* ec_ = nullptr; - // Affine coordinates for the EC_KEY. - BignumPointer x_; - BignumPointer y_; - BignumPointer d_; }; // A managed pointer to a buffer of data. When destroyed the underlying @@ -757,6 +663,78 @@ class BIOPointer final { mutable DeleteFnPtr bio_; }; +class BignumPointer final { + public: + BignumPointer() = default; + explicit BignumPointer(BIGNUM* bignum); + explicit BignumPointer(const unsigned char* data, size_t len); + BignumPointer(BignumPointer&& other) noexcept; + BignumPointer& operator=(BignumPointer&& other) noexcept; + NCRYPTO_DISALLOW_COPY(BignumPointer) + ~BignumPointer(); + + int operator<=>(const BignumPointer& other) const noexcept; + int operator<=>(const BIGNUM* other) const noexcept; + inline operator bool() const { return bn_ != nullptr; } + inline BIGNUM* get() const noexcept { return bn_.get(); } + void reset(BIGNUM* bn = nullptr); + void reset(const unsigned char* data, size_t len); + BIGNUM* release(); + + bool isZero() const; + bool isOne() const; + + bool setWord(unsigned long w); // NOLINT(runtime/int) + unsigned long getWord() const; // NOLINT(runtime/int) + + size_t byteLength() const; + + DataPointer toHex() const; + DataPointer encode() const; + DataPointer encodePadded(size_t size) const; + size_t encodeInto(unsigned char* out) const; + size_t encodePaddedInto(unsigned char* out, size_t size) const; + + using PrimeCheckCallback = std::function; + int isPrime(int checks, + PrimeCheckCallback cb = defaultPrimeCheckCallback) const; + struct PrimeConfig { + int bits; + bool safe = false; + const BignumPointer& add; + const BignumPointer& rem; + }; + + static BignumPointer NewPrime( + const PrimeConfig& params, + PrimeCheckCallback cb = defaultPrimeCheckCallback); + + bool generate(const PrimeConfig& params, + PrimeCheckCallback cb = defaultPrimeCheckCallback) const; + + static BignumPointer New(); + static BignumPointer NewSecure(); + static BignumPointer NewSub(const BignumPointer& a, const BignumPointer& b); + static BignumPointer NewLShift(size_t length); + + static DataPointer Encode(const BIGNUM* bn); + static DataPointer EncodePadded(const BIGNUM* bn, size_t size); + static size_t EncodePaddedInto(const BIGNUM* bn, + unsigned char* out, + size_t size); + static int GetBitCount(const BIGNUM* bn); + static int GetByteCount(const BIGNUM* bn); + static unsigned long GetWord(const BIGNUM* bn); // NOLINT(runtime/int) + static const BIGNUM* One(); + + BignumPointer clone(); + + private: + DeleteFnPtr bn_; + + static bool defaultPrimeCheckCallback(int, int) { return 1; } +}; + class CipherCtxPointer final { public: static CipherCtxPointer New(); @@ -998,15 +976,12 @@ class EVPKeyPointer final { int getDefaultSignPadding() const; operator Rsa() const; operator Dsa() const; - operator Ec() const; bool isRsaVariant() const; bool isOneShotVariant() const; bool isSigVariant() const; bool validateDsaParameters() const; - EVPKeyPointer clone() const; - private: DeleteFnPtr pkey_; }; @@ -1635,19 +1610,11 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext); // ============================================================================ // SPKAC -[[deprecated("Use the version that takes a Buffer")]] bool VerifySpkac( - const char* input, size_t length); - -[[deprecated("Use the version that takes a Buffer")]] BIOPointer -ExportPublicKey(const char* input, size_t length); +bool VerifySpkac(const char* input, size_t length); +BIOPointer ExportPublicKey(const char* input, size_t length); // The caller takes ownership of the returned Buffer -[[deprecated("Use the version that takes a Buffer")]] Buffer -ExportChallenge(const char* input, size_t length); - -bool VerifySpkac(const Buffer& buf); -BIOPointer ExportPublicKey(const Buffer& buf); -DataPointer ExportChallenge(const Buffer& buf); +Buffer ExportChallenge(const char* input, size_t length); // ============================================================================ // KDF @@ -1664,13 +1631,6 @@ bool extractP1363(const Buffer& buf, unsigned char* dest, size_t n); -bool hkdfInfo(const Digest& md, - const Buffer& key, - const Buffer& info, - const Buffer& salt, - size_t length, - Buffer* out); - DataPointer hkdf(const Digest& md, const Buffer& key, const Buffer& info, @@ -1679,15 +1639,6 @@ DataPointer hkdf(const Digest& md, bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem); -bool scryptInto(const Buffer& pass, - const Buffer& salt, - uint64_t N, - uint64_t r, - uint64_t p, - uint64_t maxmem, - size_t length, - Buffer* out); - DataPointer scrypt(const Buffer& pass, const Buffer& salt, uint64_t N, @@ -1696,13 +1647,6 @@ DataPointer scrypt(const Buffer& pass, uint64_t maxmem, size_t length); -bool pbkdf2Into(const Digest& md, - const Buffer& pass, - const Buffer& salt, - uint32_t iterations, - size_t length, - Buffer* out); - DataPointer pbkdf2(const Digest& md, const Buffer& pass, const Buffer& salt, diff --git a/src/ncrypto.cpp b/src/ncrypto.cpp index bcd2536..4f9fb02 100644 --- a/src/ncrypto.cpp +++ b/src/ncrypto.cpp @@ -1,5 +1,4 @@ #include "ncrypto.h" - #include #include #include @@ -17,12 +16,8 @@ #include #include -#include -#include #include #include -#include - #if OPENSSL_VERSION_MAJOR >= 3 #include #include @@ -71,8 +66,6 @@ constexpr static PQCMapping pqc_mappings[] = { nullptr) #endif -// ============================================================================ - namespace ncrypto { namespace { using BignumCtxPointer = DeleteFnPtr; @@ -261,7 +254,7 @@ Buffer DataPointer::release() { DataPointer DataPointer::resize(size_t len) { size_t actual_len = std::min(len_, len); auto buf = release(); - if (actual_len == len_) return DataPointer(buf); + if (actual_len == len_) return DataPointer(buf.data, actual_len); buf.data = OPENSSL_realloc(buf.data, actual_len); buf.len = actual_len; return DataPointer(buf); @@ -354,15 +347,10 @@ BIGNUM* BignumPointer::release() { } size_t BignumPointer::byteLength() const { - if (!bn_) return 0; + if (bn_ == nullptr) return 0; return BN_num_bytes(bn_.get()); } -size_t BignumPointer::bitLength() const { - if (!bn_) return 0; - return BN_num_bits(bn_.get()); -} - DataPointer BignumPointer::encode() const { return EncodePadded(bn_.get(), byteLength()); } @@ -635,9 +623,7 @@ int64_t PortableTimeGM(struct tm* t) { // ============================================================================ // SPKAC -namespace { -bool VerifySpkacImpl(const char* input, size_t length) { - ClearErrorOnReturn clearErrorOnReturn; +bool VerifySpkac(const char* input, size_t length) { #ifdef OPENSSL_IS_BORINGSSL // OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters, // while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not. @@ -655,11 +641,9 @@ bool VerifySpkacImpl(const char* input, size_t length) { return pkey ? NETSCAPE_SPKI_verify(spki.get(), pkey.get()) > 0 : false; } -BIOPointer ExportPublicKeyImpl(const char* input, size_t length) { - ClearErrorOnReturn clearErrorOnReturn; - auto bio = BIOPointer::NewMem(); - if (!bio) [[unlikely]] - return {}; +BIOPointer ExportPublicKey(const char* input, size_t length) { + BIOPointer bio(BIO_new(BIO_s_mem())); + if (!bio) return {}; #ifdef OPENSSL_IS_BORINGSSL // OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters, @@ -668,21 +652,17 @@ BIOPointer ExportPublicKeyImpl(const char* input, size_t length) { length = std::string_view(input, length).find_last_not_of(" \n\r\t") + 1; #endif NetscapeSPKIPointer spki(NETSCAPE_SPKI_b64_decode(input, length)); - if (!spki) [[unlikely]] { - return {}; - } + if (!spki) return {}; EVPKeyPointer pkey(NETSCAPE_SPKI_get_pubkey(spki.get())); + if (!pkey) return {}; - if (!pkey || PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) [[unlikely]] { - return {}; - } + if (PEM_write_bio_PUBKEY(bio.get(), pkey.get()) <= 0) return {}; return bio; } -DataPointer ExportChallengeImpl(const char* input, size_t length) { - ClearErrorOnReturn clearErrorOnReturn; +Buffer ExportChallenge(const char* input, size_t length) { #ifdef OPENSSL_IS_BORINGSSL // OpenSSL uses EVP_DecodeBlock, which explicitly removes trailing characters, // while BoringSSL uses EVP_DecodedLength and EVP_DecodeBase64, which do not. @@ -695,44 +675,12 @@ DataPointer ExportChallengeImpl(const char* input, size_t length) { unsigned char* buf = nullptr; int buf_size = ASN1_STRING_to_UTF8(&buf, sp->spkac->challenge); if (buf_size >= 0) { - return DataPointer({ + return { .data = reinterpret_cast(buf), .len = static_cast(buf_size), - }); - } - - return {}; -} -} // namespace - -bool VerifySpkac(const Buffer& input) { - return VerifySpkacImpl(input.data, input.len); -} - -BIOPointer ExportPublicKey(const Buffer& input) { - return ExportPublicKeyImpl(input.data, input.len); -} - -DataPointer ExportChallenge(const Buffer& input) { - return ExportChallengeImpl(input.data, input.len); -} - -bool VerifySpkac(const char* input, size_t length) { - return VerifySpkacImpl(input, length); -} - -BIOPointer ExportPublicKey(const char* input, size_t length) { - return ExportPublicKeyImpl(input, length); -} - -Buffer ExportChallenge(const char* input, size_t length) { - if (auto dp = ExportChallengeImpl(input, length)) { - auto released = dp.release(); - return Buffer{ - .data = static_cast(released.data), - .len = released.len, }; } + return {}; } @@ -1182,7 +1130,6 @@ std::optional X509View::getSignatureAlgorithmOID() const { int64_t X509View::getValidToTime() const { #ifdef OPENSSL_IS_BORINGSSL -#ifndef NCRYPTO_NO_ASN1_TIME // Boringssl does not implement ASN1_TIME_to_tm in a public way, // and only recently added ASN1_TIME_to_posix. Some boringssl // users on older version may still need to patch around this @@ -1191,11 +1138,6 @@ int64_t X509View::getValidToTime() const { ASN1_TIME_to_posix(X509_get0_notAfter(cert_), &tp); return tp; #else - // Older versions of Boringssl do not implement the ASN1_TIME_to_* - // version functions. For now, neither shall we. - return 0LL; -#endif // NCRYPTO_NO_ASN1_TIME -#else // OPENSSL_IS_BORINGSSL struct tm tp; ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp); return PortableTimeGM(&tp); @@ -1204,15 +1146,9 @@ int64_t X509View::getValidToTime() const { int64_t X509View::getValidFromTime() const { #ifdef OPENSSL_IS_BORINGSSL -#ifndef NCRYPTO_NO_ASN1_TIME int64_t tp; ASN1_TIME_to_posix(X509_get0_notBefore(cert_), &tp); return tp; -#else - // Older versions of Boringssl do not implement the ASN1_TIME_to_* - // version functions. For now, neither shall we. - return 0LL; -#endif // NCRYPTO_NO_ASN1_TIME #else struct tm tp; ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp); @@ -1406,16 +1342,10 @@ bool X509View::enumUsages(UsageCallback callback) const { bool X509View::ifRsa(KeyCallback callback) const { if (cert_ == nullptr) return true; - // The const_cast is a bit unfortunate. The X509_get_pubkey API accepts - // a const X509* in newer versions of openssl and boringssl but a non-const - // X509* in older versions. By removing the const if it exists we can - // support both. - EVPKeyPointer pkey(X509_get_pubkey(const_cast(cert_))); - if (!pkey) [[unlikely]] - return true; - auto id = pkey.id(); + OSSL3_CONST EVP_PKEY* pkey = X509_get0_pubkey(cert_); + auto id = EVP_PKEY_id(pkey); if (id == EVP_PKEY_RSA || id == EVP_PKEY_RSA2 || id == EVP_PKEY_RSA_PSS) { - Rsa rsa = pkey; + Rsa rsa(EVP_PKEY_get0_RSA(pkey)); if (!rsa) [[unlikely]] return true; return callback(rsa); @@ -1425,16 +1355,10 @@ bool X509View::ifRsa(KeyCallback callback) const { bool X509View::ifEc(KeyCallback callback) const { if (cert_ == nullptr) return true; - // The const_cast is a bit unfortunate. The X509_get_pubkey API accepts - // a const X509* in newer versions of openssl and boringssl but a non-const - // X509* in older versions. By removing the const if it exists we can - // support both. - EVPKeyPointer pkey(X509_get_pubkey(const_cast(cert_))); - if (!pkey) [[unlikely]] - return true; - auto id = pkey.id(); + OSSL3_CONST EVP_PKEY* pkey = X509_get0_pubkey(cert_); + auto id = EVP_PKEY_id(pkey); if (id == EVP_PKEY_EC) { - Ec ec = pkey; + Ec ec(EVP_PKEY_get0_EC_KEY(pkey)); if (!ec) [[unlikely]] return true; return callback(ec); @@ -1859,28 +1783,18 @@ bool checkHkdfLength(const Digest& md, size_t length) { return true; } -bool hkdfInfo(const Digest& md, - const Buffer& key, - const Buffer& info, - const Buffer& salt, - size_t length, - Buffer* out) { +DataPointer hkdf(const Digest& md, + const Buffer& key, + const Buffer& info, + const Buffer& salt, + size_t length) { ClearErrorOnReturn clearErrorOnReturn; if (!checkHkdfLength(md, length) || info.len > INT_MAX || salt.len > INT_MAX) { - return false; - } - - std::string_view actual_salt; - static const char default_salt[EVP_MAX_MD_SIZE] = {0}; - if (salt.len > 0) { - actual_salt = {reinterpret_cast(salt.data), salt.len}; - } else { - actual_salt = {default_salt, static_cast(md.size())}; + return {}; } -#ifndef NCRYPTO_NO_KDF_H auto ctx = EVPKeyCtxPointer::NewFromID(EVP_PKEY_HKDF); // OpenSSL < 3.0.0 accepted only a void* as the argument of // EVP_PKEY_CTX_set_hkdf_md. @@ -1888,14 +1802,22 @@ bool hkdfInfo(const Digest& md, if (!ctx || !EVP_PKEY_derive_init(ctx.get()) || !EVP_PKEY_CTX_set_hkdf_md(ctx.get(), md_ptr) || !EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data, info.len)) { - return false; + return {}; + } + + std::string_view actual_salt; + static const char default_salt[EVP_MAX_MD_SIZE] = {0}; + if (salt.len > 0) { + actual_salt = {reinterpret_cast(salt.data), salt.len}; + } else { + actual_salt = {default_salt, static_cast(md.size())}; } // We do not use EVP_PKEY_HKDF_MODE_EXTRACT_AND_EXPAND because and instead // implement the extraction step ourselves because EVP_PKEY_derive does not // handle zero-length keys, which are required for Web Crypto. // TODO(jasnell): Once OpenSSL 1.1.1 support is dropped completely, and once - // BoringSSL is confirmed to support it, we can hopefully drop this and use + // BoringSSL is confirmed to support it, wen can hopefully drop this and use // EVP_KDF directly which does support zero length keys. unsigned char pseudorandom_key[EVP_MAX_MD_SIZE]; unsigned pseudorandom_key_len = sizeof(pseudorandom_key); @@ -1907,41 +1829,23 @@ bool hkdfInfo(const Digest& md, key.len, pseudorandom_key, &pseudorandom_key_len) == nullptr) { - return false; + return {}; } if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) || !EVP_PKEY_CTX_set1_hkdf_key( ctx.get(), pseudorandom_key, pseudorandom_key_len)) { - return false; + return {}; } - if (out == nullptr || out->len != length) return false; - - return EVP_PKEY_derive(ctx.get(), out->data, &length) > 0; -#else - return HKDF(out->data, - length, - md, - key.data, - key.len, - salt.data, - salt.len, - info.data, - info.len); -#endif -} - -DataPointer hkdf(const Digest& md, - const Buffer& key, - const Buffer& info, - const Buffer& salt, - size_t length) { auto buf = DataPointer::Alloc(length); if (!buf) return {}; - Buffer out = buf; - return hkdfInfo(md, key, info, salt, length, &out) ? std::move(buf) - : DataPointer(); + if (EVP_PKEY_derive( + ctx.get(), static_cast(buf.get()), &length) <= 0) { + return {}; + } + + return buf; } bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem) { @@ -1949,36 +1853,6 @@ bool checkScryptParams(uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem) { 1; } -bool scryptInto(const Buffer& pass, - const Buffer& salt, - uint64_t N, - uint64_t r, - uint64_t p, - uint64_t maxmem, - size_t length, - Buffer* out) { - ClearErrorOnReturn clearErrorOnReturn; - - if (pass.len > INT_MAX || salt.len > INT_MAX || out == nullptr) { - return false; - } - - if (auto dp = DataPointer::Alloc(length)) { - return EVP_PBE_scrypt(pass.data, - pass.len, - salt.data, - salt.len, - N, - r, - p, - maxmem, - out->data, - length); - } - - return false; -} - DataPointer scrypt(const Buffer& pass, const Buffer& salt, uint64_t N, @@ -1986,42 +1860,27 @@ DataPointer scrypt(const Buffer& pass, uint64_t p, uint64_t maxmem, size_t length) { - if (auto dp = DataPointer::Alloc(length)) { - Buffer buf = dp; - if (scryptInto(pass, salt, N, r, p, maxmem, length, &buf)) { - return dp; - } - } - - return {}; -} - -bool pbkdf2Into(const Digest& md, - const Buffer& pass, - const Buffer& salt, - uint32_t iterations, - size_t length, - Buffer* out) { ClearErrorOnReturn clearErrorOnReturn; - if (pass.len > INT_MAX || salt.len > INT_MAX || length > INT_MAX || - out == nullptr) { - return false; + if (pass.len > INT_MAX || salt.len > INT_MAX) { + return {}; } - const EVP_MD* md_ptr = md; - if (PKCS5_PBKDF2_HMAC(pass.data, - pass.len, - salt.data, - salt.len, - iterations, - md_ptr, - length, - out->data)) { - return true; + auto dp = DataPointer::Alloc(length); + if (dp && EVP_PBE_scrypt(pass.data, + pass.len, + salt.data, + salt.len, + N, + r, + p, + maxmem, + reinterpret_cast(dp.get()), + length)) { + return dp; } - return false; + return {}; } DataPointer pbkdf2(const Digest& md, @@ -2029,11 +1888,23 @@ DataPointer pbkdf2(const Digest& md, const Buffer& salt, uint32_t iterations, size_t length) { - if (auto dp = DataPointer::Alloc(length)) { - Buffer buf = dp; - if (pbkdf2Into(md, pass, salt, iterations, length, &buf)) { - return dp; - } + ClearErrorOnReturn clearErrorOnReturn; + + if (pass.len > INT_MAX || salt.len > INT_MAX || length > INT_MAX) { + return {}; + } + + auto dp = DataPointer::Alloc(length); + const EVP_MD* md_ptr = md; + if (dp && PKCS5_PBKDF2_HMAC(pass.data, + pass.len, + salt.data, + salt.len, + iterations, + md_ptr, + length, + reinterpret_cast(dp.get()))) { + return dp; } return {}; @@ -2206,7 +2077,6 @@ EVPKeyPointer EVPKeyPointer::NewRawSeed( #endif EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) { -#ifndef NCRYPTO_NO_EVP_DH if (!dh) return {}; auto key = New(); if (!key) return {}; @@ -2214,11 +2084,6 @@ EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) { dh.release(); } return key; -#else - // Older versions of openssl/boringssl do not implement the EVP_PKEY_*_DH - // APIs - return {}; -#endif } EVPKeyPointer EVPKeyPointer::NewRSA(RSAPointer&& rsa) { @@ -2236,12 +2101,6 @@ EVPKeyPointer::EVPKeyPointer(EVP_PKEY* pkey) : pkey_(pkey) {} EVPKeyPointer::EVPKeyPointer(EVPKeyPointer&& other) noexcept : pkey_(other.release()) {} -EVPKeyPointer EVPKeyPointer::clone() const { - if (!pkey_) return {}; - if (!EVP_PKEY_up_ref(pkey_.get())) return {}; - return EVPKeyPointer(pkey_.get()); -} - EVPKeyPointer& EVPKeyPointer::operator=(EVPKeyPointer&& other) noexcept { if (this == &other) return *this; this->~EVPKeyPointer(); @@ -2590,7 +2449,6 @@ EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePrivateKey( ERR_GET_REASON(err) == PEM_R_BAD_PASSWORD_READ && !had_passphrase) { return ParseKeyResult(PKParseError::NEED_PASSPHRASE); } - return ParseKeyResult(PKParseError::FAILED, err); } if (!pkey) return ParseKeyResult(PKParseError::FAILED); @@ -2666,8 +2524,11 @@ Result EVPKeyPointer::writePrivateKey( // PKCS1 is only permitted for RSA keys. if (id() != EVP_PKEY_RSA) return Result(false); - OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(get()); - +#if OPENSSL_VERSION_MAJOR >= 3 + const RSA* rsa = EVP_PKEY_get0_RSA(get()); +#else + RSA* rsa = EVP_PKEY_get0_RSA(get()); +#endif switch (config.format) { case PKFormatType::PEM: { err = PEM_write_bio_RSAPrivateKey( @@ -2726,8 +2587,11 @@ Result EVPKeyPointer::writePrivateKey( // SEC1 is only permitted for EC keys if (id() != EVP_PKEY_EC) return Result(false); - OSSL3_CONST EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); - +#if OPENSSL_VERSION_MAJOR >= 3 + const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); +#else + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); +#endif switch (config.format) { case PKFormatType::PEM: { err = PEM_write_bio_ECPrivateKey( @@ -2903,15 +2767,6 @@ EVPKeyPointer::operator Dsa() const { return Dsa(dsa); } -EVPKeyPointer::operator Ec() const { - int type = id(); - if (type != EVP_PKEY_EC) return {}; - - OSSL3_CONST EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get()); - if (ec == nullptr) return {}; - return Ec(ec); -} - bool EVPKeyPointer::validateDsaParameters() const { if (!pkey_) return false; /* Validate DSA2 parameters from FIPS 186-4 */ @@ -3194,13 +3049,7 @@ SSLCtxPointer SSLCtxPointer::New(const SSL_METHOD* method) { } bool SSLCtxPointer::setGroups(const char* groups) { -#ifndef NCRYPTO_NO_SSL_GROUP_LIST return SSL_CTX_set1_groups_list(get(), groups) == 1; -#else - // Older versions of openssl/boringssl do not implement the - // SSL_CTX_set1_groups_list API - return false; -#endif } bool SSLCtxPointer::setCipherSuites(const char* ciphers) { @@ -3213,36 +3062,6 @@ bool SSLCtxPointer::setCipherSuites(const char* ciphers) { return true; #endif } -// ============================================================================ - -template -std::string_view ModeMixin::getModeLabel() const { - switch (self().getMode()) { - case EVP_CIPH_CCM_MODE: - return "ccm"; - case EVP_CIPH_CFB_MODE: - return "cfb"; - case EVP_CIPH_CBC_MODE: - return "cbc"; - case EVP_CIPH_CTR_MODE: - return "ctr"; - case EVP_CIPH_ECB_MODE: - return "ecb"; - case EVP_CIPH_GCM_MODE: - return "gcm"; - case EVP_CIPH_OCB_MODE: - return "ocb"; - case EVP_CIPH_OFB_MODE: - return "ofb"; - case EVP_CIPH_WRAP_MODE: - return "wrap"; - case EVP_CIPH_XTS_MODE: - return "xts"; - case EVP_CIPH_STREAM_CIPHER: - return "stream"; - } - return "{unknown}"; -} // ============================================================================ @@ -3280,13 +3099,43 @@ const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); +bool Cipher::isGcmMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_GCM_MODE; +} + +bool Cipher::isWrapMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_WRAP_MODE; +} + +bool Cipher::isCtrMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_CTR_MODE; +} + +bool Cipher::isCcmMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_CCM_MODE; +} + +bool Cipher::isOcbMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_OCB_MODE; +} + +bool Cipher::isStreamMode() const { + if (!cipher_) return false; + return getMode() == EVP_CIPH_STREAM_CIPHER; +} + bool Cipher::isChaCha20Poly1305() const { if (!cipher_) return false; return getNid() == NID_chacha20_poly1305; } int Cipher::getMode() const { - if (!cipher_) return -1; + if (!cipher_) return 0; return EVP_CIPHER_mode(cipher_); } @@ -3310,6 +3159,35 @@ int Cipher::getNid() const { return EVP_CIPHER_nid(cipher_); } +std::string_view Cipher::getModeLabel() const { + if (!cipher_) return {}; + switch (getMode()) { + case EVP_CIPH_CCM_MODE: + return "ccm"; + case EVP_CIPH_CFB_MODE: + return "cfb"; + case EVP_CIPH_CBC_MODE: + return "cbc"; + case EVP_CIPH_CTR_MODE: + return "ctr"; + case EVP_CIPH_ECB_MODE: + return "ecb"; + case EVP_CIPH_GCM_MODE: + return "gcm"; + case EVP_CIPH_OCB_MODE: + return "ocb"; + case EVP_CIPH_OFB_MODE: + return "ofb"; + case EVP_CIPH_WRAP_MODE: + return "wrap"; + case EVP_CIPH_XTS_MODE: + return "xts"; + case EVP_CIPH_STREAM_CIPHER: + return "stream"; + } + return "{unknown}"; +} + const char* Cipher::getName() const { if (!cipher_) return {}; // OBJ_nid2sn(EVP_CIPHER_nid(cipher)) is used here instead of @@ -3340,76 +3218,6 @@ int Cipher::bytesToKey(const Digest& digest, *this, Digest::MD5, nullptr, input.data, input.len, 1, key, iv); } -template class ModeMixin; - -namespace { -struct CipherCallbackContext { - Cipher::CipherNameCallback cb; - void operator()(const char* name) { cb(name); } -}; - -#if OPENSSL_VERSION_MAJOR >= 3 -template -void array_push_back(const TypeName* evp_ref, - const char* from, - const char* to, - void* arg) { - if (from == nullptr) return; - - const TypeName* real_instance = getbyname(from); - if (!real_instance) return; - - const char* real_name = getname(real_instance); - if (!real_name) return; - - // EVP_*_fetch() does not support alias names, so we need to pass it the - // real/original algorithm name. - // We use EVP_*_fetch() as a filter here because it will only return an - // instance if the algorithm is supported by the public OpenSSL APIs (some - // algorithms are used internally by OpenSSL and are also passed to this - // callback). - TypeName* fetched = fetch_type(nullptr, real_name, nullptr); - if (fetched == nullptr) return; - - free_type(fetched); - auto& cb = *(static_cast(arg)); - cb(from); -} -#else -template -void array_push_back(const TypeName* evp_ref, - const char* from, - const char* to, - void* arg) { - if (!from) return; - auto& cb = *(static_cast(arg)); - cb(from); -} -#endif -} // namespace - -void Cipher::ForEach(Cipher::CipherNameCallback callback) { - ClearErrorOnReturn clearErrorOnReturn; - CipherCallbackContext context; - context.cb = std::move(callback); - - EVP_CIPHER_do_all_sorted( -#if OPENSSL_VERSION_MAJOR >= 3 - array_push_back, -#else - array_push_back, -#endif - &context); -} - // ============================================================================ CipherCtxPointer CipherCtxPointer::New() { @@ -3486,11 +3294,6 @@ int CipherCtxPointer::getMode() const { return EVP_CIPHER_CTX_mode(ctx_.get()); } -int CipherCtxPointer::getNid() const { - if (!ctx_) return 0; - return EVP_CIPHER_CTX_nid(ctx_.get()); -} - bool CipherCtxPointer::isGcmMode() const { if (!ctx_) return false; return getMode() == EVP_CIPH_GCM_MODE; @@ -3516,6 +3319,11 @@ bool CipherCtxPointer::isChaCha20Poly1305() const { return getNid() == NID_chacha20_poly1305; } +int CipherCtxPointer::getNid() const { + if (!ctx_) return 0; + return EVP_CIPHER_CTX_nid(ctx_.get()); +} + bool CipherCtxPointer::init(const Cipher& cipher, bool encrypt, const unsigned char* key, @@ -3862,7 +3670,6 @@ bool EVPKeyCtxPointer::setDhParameters(int prime_size, uint32_t generator) { bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits, std::optional q_bits) { -#ifndef NCRYPTO_NO_DSA_KEYGEN if (!ctx_) return false; if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_.get(), bits) != 1) { return false; @@ -3872,10 +3679,6 @@ bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits, return false; } return true; -#else - // Older versions of openssl/boringssl do not implement the DSA keygen. - return false; -#endif } bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) { @@ -4216,14 +4019,9 @@ const std::optional Rsa::getPssParams() const { } if (params->saltLength != nullptr) { - // Older versions of openssl/boringssl do not implement - // ASN1_INTEGER_get_int64, which the salt length here technically - // is. Let's walk it through uint64_t with a conversion. - uint64_t temp; - if (ASN1_INTEGER_get_uint64(&temp, params->saltLength) != 1) { + if (ASN1_INTEGER_get_int64(&ret.salt_length, params->saltLength) != 1) { return std::nullopt; } - ret.salt_length = static_cast(temp); } return ret; } @@ -4308,18 +4106,79 @@ DataPointer Cipher::recover(const EVPKeyPointer& key, key, params, in); } +namespace { +struct CipherCallbackContext { + Cipher::CipherNameCallback cb; + void operator()(const char* name) { cb(name); } +}; + +#if OPENSSL_VERSION_MAJOR >= 3 +template +void array_push_back(const TypeName* evp_ref, + const char* from, + const char* to, + void* arg) { + if (from == nullptr) return; + + const TypeName* real_instance = getbyname(from); + if (!real_instance) return; + + const char* real_name = getname(real_instance); + if (!real_name) return; + + // EVP_*_fetch() does not support alias names, so we need to pass it the + // real/original algorithm name. + // We use EVP_*_fetch() as a filter here because it will only return an + // instance if the algorithm is supported by the public OpenSSL APIs (some + // algorithms are used internally by OpenSSL and are also passed to this + // callback). + TypeName* fetched = fetch_type(nullptr, real_name, nullptr); + if (fetched == nullptr) return; + + free_type(fetched); + auto& cb = *(static_cast(arg)); + cb(from); +} +#else +template +void array_push_back(const TypeName* evp_ref, + const char* from, + const char* to, + void* arg) { + if (!from) return; + auto& cb = *(static_cast(arg)); + cb(from); +} +#endif +} // namespace + +void Cipher::ForEach(Cipher::CipherNameCallback callback) { + ClearErrorOnReturn clearErrorOnReturn; + CipherCallbackContext context; + context.cb = std::move(callback); + + EVP_CIPHER_do_all_sorted( +#if OPENSSL_VERSION_MAJOR >= 3 + array_push_back, +#else + array_push_back, +#endif + &context); +} + // ============================================================================ Ec::Ec() : ec_(nullptr) {} -Ec::Ec(OSSL3_CONST EC_KEY* key) - : ec_(key), x_(BignumPointer::New()), y_(BignumPointer::New()) { - if (ec_ != nullptr) { - MarkPopErrorOnReturn mark_pop_error_on_return; - EC_POINT_get_affine_coordinates( - getGroup(), getPublicKey(), x_.get(), y_.get(), nullptr); - } -} +Ec::Ec(OSSL3_CONST EC_KEY* key) : ec_(key) {} const EC_GROUP* Ec::getGroup() const { return ECKeyPointer::GetGroup(ec_); @@ -4349,22 +4208,6 @@ bool Ec::GetCurves(Ec::GetCurveCallback callback) { return true; } -uint32_t Ec::getDegree() const { - return EC_GROUP_get_degree(getGroup()); -} - -std::string Ec::getCurveName() const { - return std::string(OBJ_nid2sn(getCurve())); -} - -const EC_POINT* Ec::getPublicKey() const { - return EC_KEY_get0_public_key(ec_); -} - -const BIGNUM* Ec::getPrivateKey() const { - return EC_KEY_get0_private_key(ec_); -} - // ============================================================================ EVPMDCtxPointer::EVPMDCtxPointer() : ctx_(nullptr) {} @@ -4827,9 +4670,10 @@ std::pair X509Name::Iterator::operator*() const { unsigned char* value_str; int value_str_size = ASN1_STRING_to_UTF8(&value_str, value); - return { - std::move(name_str), - std::string(reinterpret_cast(value_str), value_str_size)}; + std::string out(reinterpret_cast(value_str), value_str_size); + OPENSSL_free(value_str); // free after copy + + return {std::move(name_str), std::move(out)}; } // ============================================================================ @@ -5001,321 +4845,3 @@ DataPointer KEM::Decapsulate(const EVPKeyPointer& private_key, #endif // OPENSSL_VERSION_MAJOR >= 3 } // namespace ncrypto - -// =========================================================================== -#ifdef NCRYPTO_BSSL_NEEDS_DH_PRIMES -// While newer versions of BoringSSL have these primes, older versions do not, -// in particular older versions that conform to fips. We conditionally add -// them here only if the NCRYPTO_BSSL_NEEDS_DH_PRIMES define is set. Their -// implementations are defined here to prevent duplicating the symbols. -extern "C" int bn_set_words(BIGNUM* bn, const BN_ULONG* words, size_t num); - -// Backporting primes that may not be supported in earlier boringssl versions. -// Intentionally keeping the existing C-style formatting. - -#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) - -#if defined(OPENSSL_64_BIT) -#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo)) -#elif defined(OPENSSL_32_BIT) -#define TOBN(hi, lo) (lo), (hi) -#else -#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" -#endif - -static BIGNUM* get_params(BIGNUM* ret, - const BN_ULONG* words, - size_t num_words) { - BIGNUM* alloc = nullptr; - if (ret == nullptr) { - alloc = BN_new(); - if (alloc == nullptr) { - return nullptr; - } - ret = alloc; - } - - if (!bn_set_words(ret, words, num_words)) { - BN_free(alloc); - return nullptr; - } - - return ret; -} - -BIGNUM* BN_get_rfc3526_prime_2048(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x15728e5a, 0x8aacaa68), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_3072(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x4b82d120, 0xa93ad2ca), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_4096(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x4df435c9, 0x34063199), - TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), - TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), - TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), - TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), - TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), - TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), - TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), - TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_6144(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0xe694f91e, 0x6dcc4024), - TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), - TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), - TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), - TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), - TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), - TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), - TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), - TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), - TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), - TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), - TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), - TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), - TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), - TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), - TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), - TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), - TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), - TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), - TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), - TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), - TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), - TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), - TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), - TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} - -BIGNUM* BN_get_rfc3526_prime_8192(BIGNUM* ret) { - static const BN_ULONG kWords[] = { - TOBN(0xffffffff, 0xffffffff), TOBN(0x60c980dd, 0x98edd3df), - TOBN(0xc81f56e8, 0x80b96e71), TOBN(0x9e3050e2, 0x765694df), - TOBN(0x9558e447, 0x5677e9aa), TOBN(0xc9190da6, 0xfc026e47), - TOBN(0x889a002e, 0xd5ee382b), TOBN(0x4009438b, 0x481c6cd7), - TOBN(0x359046f4, 0xeb879f92), TOBN(0xfaf36bc3, 0x1ecfa268), - TOBN(0xb1d510bd, 0x7ee74d73), TOBN(0xf9ab4819, 0x5ded7ea1), - TOBN(0x64f31cc5, 0x0846851d), TOBN(0x4597e899, 0xa0255dc1), - TOBN(0xdf310ee0, 0x74ab6a36), TOBN(0x6d2a13f8, 0x3f44f82d), - TOBN(0x062b3cf5, 0xb3a278a6), TOBN(0x79683303, 0xed5bdd3a), - TOBN(0xfa9d4b7f, 0xa2c087e8), TOBN(0x4bcbc886, 0x2f8385dd), - TOBN(0x3473fc64, 0x6cea306b), TOBN(0x13eb57a8, 0x1a23f0c7), - TOBN(0x22222e04, 0xa4037c07), TOBN(0xe3fdb8be, 0xfc848ad9), - TOBN(0x238f16cb, 0xe39d652d), TOBN(0x3423b474, 0x2bf1c978), - TOBN(0x3aab639c, 0x5ae4f568), TOBN(0x2576f693, 0x6ba42466), - TOBN(0x741fa7bf, 0x8afc47ed), TOBN(0x3bc832b6, 0x8d9dd300), - TOBN(0xd8bec4d0, 0x73b931ba), TOBN(0x38777cb6, 0xa932df8c), - TOBN(0x74a3926f, 0x12fee5e4), TOBN(0xe694f91e, 0x6dbe1159), - TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), - TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), - TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), - TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), - TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), - TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), - TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), - TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), - TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), - TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), - TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), - TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), - TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), - TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), - TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), - TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), - TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), - TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), - TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), - TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), - TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), - TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), - TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), - TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), - TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), - TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), - TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), - TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), - TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), - TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), - TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), - TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), - TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), - TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), - TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), - TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), - TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), - TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), - TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), - TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), - TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), - TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), - TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), - TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), - TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), - TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), - TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), - }; - return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); -} -#endif - -// =========================================================================== -#if NCRYPTO_BSSL_LIBDECREPIT_MISSING -// While BoringSSL implements EVP_CIPHER_do_all_sorted, it includes this -// inplementation in a library called "libdecrepit", which might not be included -// depending on how boringssl was built. In such cases, a copy of the function -// is provided here: - -extern "C" void EVP_CIPHER_do_all_sorted( - void (*callback)(const EVP_CIPHER* cipher, - const char* name, - const char* unused, - void* arg), - void* arg) { - callback(EVP_aes_128_cbc(), "AES-128-CBC", NULL, arg); - callback(EVP_aes_192_cbc(), "AES-192-CBC", NULL, arg); - callback(EVP_aes_256_cbc(), "AES-256-CBC", NULL, arg); - callback(EVP_aes_128_ctr(), "AES-128-CTR", NULL, arg); - callback(EVP_aes_192_ctr(), "AES-192-CTR", NULL, arg); - callback(EVP_aes_256_ctr(), "AES-256-CTR", NULL, arg); - callback(EVP_aes_128_ecb(), "AES-128-ECB", NULL, arg); - callback(EVP_aes_192_ecb(), "AES-192-ECB", NULL, arg); - callback(EVP_aes_256_ecb(), "AES-256-ECB", NULL, arg); - callback(EVP_aes_128_ofb(), "AES-128-OFB", NULL, arg); - callback(EVP_aes_192_ofb(), "AES-192-OFB", NULL, arg); - callback(EVP_aes_256_ofb(), "AES-256-OFB", NULL, arg); - callback(EVP_aes_128_gcm(), "AES-128-GCM", NULL, arg); - callback(EVP_aes_192_gcm(), "AES-192-GCM", NULL, arg); - callback(EVP_aes_256_gcm(), "AES-256-GCM", NULL, arg); - callback(EVP_des_cbc(), "DES-CBC", NULL, arg); - callback(EVP_des_ecb(), "DES-ECB", NULL, arg); - callback(EVP_des_ede(), "DES-EDE", NULL, arg); - callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg); - callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg); - callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg); - callback(EVP_rc4(), "RC4", NULL, arg); - - // OpenSSL returns everything twice, the second time in lower case. - callback(EVP_aes_128_cbc(), "aes-128-cbc", NULL, arg); - callback(EVP_aes_192_cbc(), "aes-192-cbc", NULL, arg); - callback(EVP_aes_256_cbc(), "aes-256-cbc", NULL, arg); - callback(EVP_aes_128_ctr(), "aes-128-ctr", NULL, arg); - callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg); - callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg); - callback(EVP_aes_128_ecb(), "aes-128-ecb", NULL, arg); - callback(EVP_aes_192_ecb(), "aes-192-ecb", NULL, arg); - callback(EVP_aes_256_ecb(), "aes-256-ecb", NULL, arg); - callback(EVP_aes_128_ofb(), "aes-128-ofb", NULL, arg); - callback(EVP_aes_192_ofb(), "aes-192-ofb", NULL, arg); - callback(EVP_aes_256_ofb(), "aes-256-ofb", NULL, arg); - callback(EVP_aes_128_gcm(), "aes-128-gcm", NULL, arg); - callback(EVP_aes_192_gcm(), "aes-192-gcm", NULL, arg); - callback(EVP_aes_256_gcm(), "aes-256-gcm", NULL, arg); - callback(EVP_des_cbc(), "des-cbc", NULL, arg); - callback(EVP_des_ecb(), "des-ecb", NULL, arg); - callback(EVP_des_ede(), "des-ede", NULL, arg); - callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg); - callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg); - callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg); - callback(EVP_rc4(), "rc4", NULL, arg); -} -#endif diff --git a/tests/basic.cpp b/tests/basic.cpp index d8c7f11..6742e05 100644 --- a/tests/basic.cpp +++ b/tests/basic.cpp @@ -38,8 +38,10 @@ TEST(basic, cipher_foreach) { // as that depends on openssl vs boringssl, versions, configuration, etc. // Instead, we look for a couple of very common ciphers that should always be // present. - ASSERT_TRUE(foundCiphers.count("AES-128-CTR")); - ASSERT_TRUE(foundCiphers.count("AES-256-CBC")); + ASSERT_TRUE(foundCiphers.count("aes-128-ctr") || + foundCiphers.count("AES-128-CTR")); + ASSERT_TRUE(foundCiphers.count("aes-256-cbc") || + foundCiphers.count("AES-256-CBC")); } #ifdef OPENSSL_IS_BORINGSSL From 572fc6a9993aaf522f3ef6ed8046a7ac8f6c3b39 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 20 Jan 2026 20:15:17 +0100 Subject: [PATCH 2/2] squash! reintroduce `NCRYPTO_NO_` fallbacks when possible --- src/ncrypto.cpp | 349 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 348 insertions(+), 1 deletion(-) diff --git a/src/ncrypto.cpp b/src/ncrypto.cpp index 4f9fb02..3a32813 100644 --- a/src/ncrypto.cpp +++ b/src/ncrypto.cpp @@ -1130,6 +1130,7 @@ std::optional X509View::getSignatureAlgorithmOID() const { int64_t X509View::getValidToTime() const { #ifdef OPENSSL_IS_BORINGSSL +#ifndef NCRYPTO_NO_ASN1_TIME // Boringssl does not implement ASN1_TIME_to_tm in a public way, // and only recently added ASN1_TIME_to_posix. Some boringssl // users on older version may still need to patch around this @@ -1138,6 +1139,11 @@ int64_t X509View::getValidToTime() const { ASN1_TIME_to_posix(X509_get0_notAfter(cert_), &tp); return tp; #else + // Older versions of Boringssl do not implement the ASN1_TIME_to_* + // version functions. For now, neither shall we. + return 0LL; +#endif // NCRYPTO_NO_ASN1_TIME +#else // OPENSSL_IS_BORINGSSL struct tm tp; ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp); return PortableTimeGM(&tp); @@ -1146,9 +1152,15 @@ int64_t X509View::getValidToTime() const { int64_t X509View::getValidFromTime() const { #ifdef OPENSSL_IS_BORINGSSL +#ifndef NCRYPTO_NO_ASN1_TIME int64_t tp; ASN1_TIME_to_posix(X509_get0_notBefore(cert_), &tp); return tp; +#else + // Older versions of Boringssl do not implement the ASN1_TIME_to_* + // version functions. For now, neither shall we. + return 0LL; +#endif // NCRYPTO_NO_ASN1_TIME #else struct tm tp; ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp); @@ -1817,7 +1829,7 @@ DataPointer hkdf(const Digest& md, // implement the extraction step ourselves because EVP_PKEY_derive does not // handle zero-length keys, which are required for Web Crypto. // TODO(jasnell): Once OpenSSL 1.1.1 support is dropped completely, and once - // BoringSSL is confirmed to support it, wen can hopefully drop this and use + // BoringSSL is confirmed to support it, we can hopefully drop this and use // EVP_KDF directly which does support zero length keys. unsigned char pseudorandom_key[EVP_MAX_MD_SIZE]; unsigned pseudorandom_key_len = sizeof(pseudorandom_key); @@ -2077,6 +2089,7 @@ EVPKeyPointer EVPKeyPointer::NewRawSeed( #endif EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) { +#ifndef NCRYPTO_NO_EVP_DH if (!dh) return {}; auto key = New(); if (!key) return {}; @@ -2084,6 +2097,11 @@ EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) { dh.release(); } return key; +#else + // Older versions of openssl/boringssl do not implement the EVP_PKEY_*_DH + // APIs + return {}; +#endif } EVPKeyPointer EVPKeyPointer::NewRSA(RSAPointer&& rsa) { @@ -3049,7 +3067,13 @@ SSLCtxPointer SSLCtxPointer::New(const SSL_METHOD* method) { } bool SSLCtxPointer::setGroups(const char* groups) { +#ifndef NCRYPTO_NO_SSL_GROUP_LIST return SSL_CTX_set1_groups_list(get(), groups) == 1; +#else + // Older versions of openssl/boringssl do not implement the + // SSL_CTX_set1_groups_list API + return false; +#endif } bool SSLCtxPointer::setCipherSuites(const char* ciphers) { @@ -3670,6 +3694,7 @@ bool EVPKeyCtxPointer::setDhParameters(int prime_size, uint32_t generator) { bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits, std::optional q_bits) { +#ifndef NCRYPTO_NO_DSA_KEYGEN if (!ctx_) return false; if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_.get(), bits) != 1) { return false; @@ -3679,6 +3704,10 @@ bool EVPKeyCtxPointer::setDsaParameters(uint32_t bits, return false; } return true; +#else + // Older versions of openssl/boringssl do not implement the DSA keygen. + return false; +#endif } bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) { @@ -4845,3 +4874,321 @@ DataPointer KEM::Decapsulate(const EVPKeyPointer& private_key, #endif // OPENSSL_VERSION_MAJOR >= 3 } // namespace ncrypto + +// =========================================================================== +#ifdef NCRYPTO_BSSL_NEEDS_DH_PRIMES +// While newer versions of BoringSSL have these primes, older versions do not, +// in particular older versions that conform to fips. We conditionally add +// them here only if the NCRYPTO_BSSL_NEEDS_DH_PRIMES define is set. Their +// implementations are defined here to prevent duplicating the symbols. +extern "C" int bn_set_words(BIGNUM* bn, const BN_ULONG* words, size_t num); + +// Backporting primes that may not be supported in earlier boringssl versions. +// Intentionally keeping the existing C-style formatting. + +#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +#if defined(OPENSSL_64_BIT) +#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo)) +#elif defined(OPENSSL_32_BIT) +#define TOBN(hi, lo) (lo), (hi) +#else +#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT" +#endif + +static BIGNUM* get_params(BIGNUM* ret, + const BN_ULONG* words, + size_t num_words) { + BIGNUM* alloc = nullptr; + if (ret == nullptr) { + alloc = BN_new(); + if (alloc == nullptr) { + return nullptr; + } + ret = alloc; + } + + if (!bn_set_words(ret, words, num_words)) { + BN_free(alloc); + return nullptr; + } + + return ret; +} + +BIGNUM* BN_get_rfc3526_prime_2048(BIGNUM* ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x15728e5a, 0x8aacaa68), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM* BN_get_rfc3526_prime_3072(BIGNUM* ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x4b82d120, 0xa93ad2ca), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM* BN_get_rfc3526_prime_4096(BIGNUM* ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x4df435c9, 0x34063199), + TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), + TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), + TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), + TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), + TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), + TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), + TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), + TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM* BN_get_rfc3526_prime_6144(BIGNUM* ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0xe694f91e, 0x6dcc4024), + TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), + TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), + TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), + TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), + TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), + TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), + TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), + TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), + TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), + TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), + TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), + TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), + TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), + TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), + TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), + TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), + TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), + TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), + TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), + TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), + TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), + TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), + TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), + TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} + +BIGNUM* BN_get_rfc3526_prime_8192(BIGNUM* ret) { + static const BN_ULONG kWords[] = { + TOBN(0xffffffff, 0xffffffff), TOBN(0x60c980dd, 0x98edd3df), + TOBN(0xc81f56e8, 0x80b96e71), TOBN(0x9e3050e2, 0x765694df), + TOBN(0x9558e447, 0x5677e9aa), TOBN(0xc9190da6, 0xfc026e47), + TOBN(0x889a002e, 0xd5ee382b), TOBN(0x4009438b, 0x481c6cd7), + TOBN(0x359046f4, 0xeb879f92), TOBN(0xfaf36bc3, 0x1ecfa268), + TOBN(0xb1d510bd, 0x7ee74d73), TOBN(0xf9ab4819, 0x5ded7ea1), + TOBN(0x64f31cc5, 0x0846851d), TOBN(0x4597e899, 0xa0255dc1), + TOBN(0xdf310ee0, 0x74ab6a36), TOBN(0x6d2a13f8, 0x3f44f82d), + TOBN(0x062b3cf5, 0xb3a278a6), TOBN(0x79683303, 0xed5bdd3a), + TOBN(0xfa9d4b7f, 0xa2c087e8), TOBN(0x4bcbc886, 0x2f8385dd), + TOBN(0x3473fc64, 0x6cea306b), TOBN(0x13eb57a8, 0x1a23f0c7), + TOBN(0x22222e04, 0xa4037c07), TOBN(0xe3fdb8be, 0xfc848ad9), + TOBN(0x238f16cb, 0xe39d652d), TOBN(0x3423b474, 0x2bf1c978), + TOBN(0x3aab639c, 0x5ae4f568), TOBN(0x2576f693, 0x6ba42466), + TOBN(0x741fa7bf, 0x8afc47ed), TOBN(0x3bc832b6, 0x8d9dd300), + TOBN(0xd8bec4d0, 0x73b931ba), TOBN(0x38777cb6, 0xa932df8c), + TOBN(0x74a3926f, 0x12fee5e4), TOBN(0xe694f91e, 0x6dbe1159), + TOBN(0x12bf2d5b, 0x0b7474d6), TOBN(0x043e8f66, 0x3f4860ee), + TOBN(0x387fe8d7, 0x6e3c0468), TOBN(0xda56c9ec, 0x2ef29632), + TOBN(0xeb19ccb1, 0xa313d55c), TOBN(0xf550aa3d, 0x8a1fbff0), + TOBN(0x06a1d58b, 0xb7c5da76), TOBN(0xa79715ee, 0xf29be328), + TOBN(0x14cc5ed2, 0x0f8037e0), TOBN(0xcc8f6d7e, 0xbf48e1d8), + TOBN(0x4bd407b2, 0x2b4154aa), TOBN(0x0f1d45b7, 0xff585ac5), + TOBN(0x23a97a7e, 0x36cc88be), TOBN(0x59e7c97f, 0xbec7e8f3), + TOBN(0xb5a84031, 0x900b1c9e), TOBN(0xd55e702f, 0x46980c82), + TOBN(0xf482d7ce, 0x6e74fef6), TOBN(0xf032ea15, 0xd1721d03), + TOBN(0x5983ca01, 0xc64b92ec), TOBN(0x6fb8f401, 0x378cd2bf), + TOBN(0x33205151, 0x2bd7af42), TOBN(0xdb7f1447, 0xe6cc254b), + TOBN(0x44ce6cba, 0xced4bb1b), TOBN(0xda3edbeb, 0xcf9b14ed), + TOBN(0x179727b0, 0x865a8918), TOBN(0xb06a53ed, 0x9027d831), + TOBN(0xe5db382f, 0x413001ae), TOBN(0xf8ff9406, 0xad9e530e), + TOBN(0xc9751e76, 0x3dba37bd), TOBN(0xc1d4dcb2, 0x602646de), + TOBN(0x36c3fab4, 0xd27c7026), TOBN(0x4df435c9, 0x34028492), + TOBN(0x86ffb7dc, 0x90a6c08f), TOBN(0x93b4ea98, 0x8d8fddc1), + TOBN(0xd0069127, 0xd5b05aa9), TOBN(0xb81bdd76, 0x2170481c), + TOBN(0x1f612970, 0xcee2d7af), TOBN(0x233ba186, 0x515be7ed), + TOBN(0x99b2964f, 0xa090c3a2), TOBN(0x287c5947, 0x4e6bc05d), + TOBN(0x2e8efc14, 0x1fbecaa6), TOBN(0xdbbbc2db, 0x04de8ef9), + TOBN(0x2583e9ca, 0x2ad44ce8), TOBN(0x1a946834, 0xb6150bda), + TOBN(0x99c32718, 0x6af4e23c), TOBN(0x88719a10, 0xbdba5b26), + TOBN(0x1a723c12, 0xa787e6d7), TOBN(0x4b82d120, 0xa9210801), + TOBN(0x43db5bfc, 0xe0fd108e), TOBN(0x08e24fa0, 0x74e5ab31), + TOBN(0x770988c0, 0xbad946e2), TOBN(0xbbe11757, 0x7a615d6c), + TOBN(0x521f2b18, 0x177b200c), TOBN(0xd8760273, 0x3ec86a64), + TOBN(0xf12ffa06, 0xd98a0864), TOBN(0xcee3d226, 0x1ad2ee6b), + TOBN(0x1e8c94e0, 0x4a25619d), TOBN(0xabf5ae8c, 0xdb0933d7), + TOBN(0xb3970f85, 0xa6e1e4c7), TOBN(0x8aea7157, 0x5d060c7d), + TOBN(0xecfb8504, 0x58dbef0a), TOBN(0xa85521ab, 0xdf1cba64), + TOBN(0xad33170d, 0x04507a33), TOBN(0x15728e5a, 0x8aaac42d), + TOBN(0x15d22618, 0x98fa0510), TOBN(0x3995497c, 0xea956ae5), + TOBN(0xde2bcbf6, 0x95581718), TOBN(0xb5c55df0, 0x6f4c52c9), + TOBN(0x9b2783a2, 0xec07a28f), TOBN(0xe39e772c, 0x180e8603), + TOBN(0x32905e46, 0x2e36ce3b), TOBN(0xf1746c08, 0xca18217c), + TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d), + TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96), + TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a), + TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d), + TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5), + TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b), + TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245), + TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b), + TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22), + TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1), + TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff), + }; + return get_params(ret, kWords, OPENSSL_ARRAY_SIZE(kWords)); +} +#endif + +// =========================================================================== +#if NCRYPTO_BSSL_LIBDECREPIT_MISSING +// While BoringSSL implements EVP_CIPHER_do_all_sorted, it includes this +// inplementation in a library called "libdecrepit", which might not be included +// depending on how boringssl was built. In such cases, a copy of the function +// is provided here: + +extern "C" void EVP_CIPHER_do_all_sorted( + void (*callback)(const EVP_CIPHER* cipher, + const char* name, + const char* unused, + void* arg), + void* arg) { + callback(EVP_aes_128_cbc(), "AES-128-CBC", NULL, arg); + callback(EVP_aes_192_cbc(), "AES-192-CBC", NULL, arg); + callback(EVP_aes_256_cbc(), "AES-256-CBC", NULL, arg); + callback(EVP_aes_128_ctr(), "AES-128-CTR", NULL, arg); + callback(EVP_aes_192_ctr(), "AES-192-CTR", NULL, arg); + callback(EVP_aes_256_ctr(), "AES-256-CTR", NULL, arg); + callback(EVP_aes_128_ecb(), "AES-128-ECB", NULL, arg); + callback(EVP_aes_192_ecb(), "AES-192-ECB", NULL, arg); + callback(EVP_aes_256_ecb(), "AES-256-ECB", NULL, arg); + callback(EVP_aes_128_ofb(), "AES-128-OFB", NULL, arg); + callback(EVP_aes_192_ofb(), "AES-192-OFB", NULL, arg); + callback(EVP_aes_256_ofb(), "AES-256-OFB", NULL, arg); + callback(EVP_aes_128_gcm(), "AES-128-GCM", NULL, arg); + callback(EVP_aes_192_gcm(), "AES-192-GCM", NULL, arg); + callback(EVP_aes_256_gcm(), "AES-256-GCM", NULL, arg); + callback(EVP_des_cbc(), "DES-CBC", NULL, arg); + callback(EVP_des_ecb(), "DES-ECB", NULL, arg); + callback(EVP_des_ede(), "DES-EDE", NULL, arg); + callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg); + callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg); + callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg); + callback(EVP_rc4(), "RC4", NULL, arg); + + // OpenSSL returns everything twice, the second time in lower case. + callback(EVP_aes_128_cbc(), "aes-128-cbc", NULL, arg); + callback(EVP_aes_192_cbc(), "aes-192-cbc", NULL, arg); + callback(EVP_aes_256_cbc(), "aes-256-cbc", NULL, arg); + callback(EVP_aes_128_ctr(), "aes-128-ctr", NULL, arg); + callback(EVP_aes_192_ctr(), "aes-192-ctr", NULL, arg); + callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg); + callback(EVP_aes_128_ecb(), "aes-128-ecb", NULL, arg); + callback(EVP_aes_192_ecb(), "aes-192-ecb", NULL, arg); + callback(EVP_aes_256_ecb(), "aes-256-ecb", NULL, arg); + callback(EVP_aes_128_ofb(), "aes-128-ofb", NULL, arg); + callback(EVP_aes_192_ofb(), "aes-192-ofb", NULL, arg); + callback(EVP_aes_256_ofb(), "aes-256-ofb", NULL, arg); + callback(EVP_aes_128_gcm(), "aes-128-gcm", NULL, arg); + callback(EVP_aes_192_gcm(), "aes-192-gcm", NULL, arg); + callback(EVP_aes_256_gcm(), "aes-256-gcm", NULL, arg); + callback(EVP_des_cbc(), "des-cbc", NULL, arg); + callback(EVP_des_ecb(), "des-ecb", NULL, arg); + callback(EVP_des_ede(), "des-ede", NULL, arg); + callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg); + callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg); + callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg); + callback(EVP_rc4(), "rc4", NULL, arg); +} +#endif