diff --git a/.github/sync-node-ncrypto.json b/.github/sync-node-ncrypto.json index a9596c7..7c8001c 100644 --- a/.github/sync-node-ncrypto.json +++ b/.github/sync-node-ncrypto.json @@ -1,3 +1,3 @@ { - "node_commit": "cfd7920d5a2d84905c4292362d01d07870047e93" + "node_commit": "2022edf3e32ce28ee08b17f8566243a090dacd95" } diff --git a/.github/workflows/visual-studio.yml b/.github/workflows/visual-studio.yml index 0eb78f8..3acc0db 100644 --- a/.github/workflows/visual-studio.yml +++ b/.github/workflows/visual-studio.yml @@ -22,7 +22,7 @@ concurrency: jobs: build: - runs-on: windows-2025 + runs-on: windows-2022 strategy: fail-fast: false matrix: diff --git a/include/ncrypto.h b/include/ncrypto.h index b6b6ac6..8a817c1 100644 --- a/include/ncrypto.h +++ b/include/ncrypto.h @@ -75,9 +75,9 @@ #endif #if OPENSSL_VERSION_PREREQ(3, 0) -#define OPENSSL_WITH_KMAC 1 +#define OPENSSL_WITH_EVP_MAC 1 #else -#define OPENSSL_WITH_KMAC 0 +#define OPENSSL_WITH_EVP_MAC 0 #endif #if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_PREREQ(3, 2) @@ -616,8 +616,8 @@ class BignumPointer final { bool isZero() const; bool isOne() const; - bool setWord(unsigned long w); // NOLINT(runtime/int) - unsigned long getWord() const; // NOLINT(runtime/int) + bool setWord(unsigned long w); // NOLINT(runtime/int) + std::optional getWord() const; // NOLINT(runtime/int) size_t byteLength() const; size_t bitLength() const; @@ -657,7 +657,8 @@ class BignumPointer final { 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 std::optional GetWord( // NOLINT(runtime/int) + const BIGNUM* bn); static const BIGNUM* One(); BignumPointer clone(); @@ -1569,6 +1570,7 @@ class EVPMDCtxPointer final { DeleteFnPtr ctx_; }; +#if !OPENSSL_WITH_EVP_MAC class HMACCtxPointer final { public: HMACCtxPointer(); @@ -1595,8 +1597,9 @@ class HMACCtxPointer final { private: DeleteFnPtr ctx_; }; +#endif // !OPENSSL_WITH_EVP_MAC -#if OPENSSL_WITH_KMAC +#if OPENSSL_WITH_EVP_MAC class EVPMacPointer final { public: EVPMacPointer() = default; @@ -1644,7 +1647,34 @@ class EVPMacCtxPointer final { private: DeleteFnPtr ctx_; }; -#endif // OPENSSL_WITH_KMAC + +class HMACCtxPointer final { + public: + HMACCtxPointer(); + HMACCtxPointer(HMACCtxPointer&& other) noexcept; + HMACCtxPointer& operator=(HMACCtxPointer&& other) noexcept; + NCRYPTO_DISALLOW_COPY(HMACCtxPointer) + ~HMACCtxPointer(); + + inline bool operator==(std::nullptr_t) noexcept { return ctx_ == nullptr; } + inline operator bool() const { return ctx_ != nullptr; } + void reset(); + + bool init(const Buffer& buf, const Digest& md); + bool update(const Buffer& buf); + DataPointer digest(); + bool digestInto(Buffer* buf); + + static HMACCtxPointer New(); + + private: + HMACCtxPointer(EVPMacPointer&& mac, EVPMacCtxPointer&& ctx); + + EVPMacPointer mac_; + EVPMacCtxPointer ctx_; + size_t md_size_ = 0; +}; +#endif // OPENSSL_WITH_EVP_MAC #ifndef OPENSSL_NO_ENGINE class EnginePointer final { diff --git a/src/ncrypto.cpp b/src/ncrypto.cpp index 2e6020a..16d9d89 100644 --- a/src/ncrypto.cpp +++ b/src/ncrypto.cpp @@ -431,12 +431,16 @@ bool BignumPointer::setWord(unsigned long w) { // NOLINT(runtime/int) return BN_set_word(bn_.get(), w) == 1; } -unsigned long BignumPointer::GetWord(const BIGNUM* bn) { // NOLINT(runtime/int) - return BN_get_word(bn); +std::optional BignumPointer::GetWord( // NOLINT(runtime/int) + const BIGNUM* bn) { + BN_ULONG ret = BN_get_word(bn); + if (ret == static_cast(-1)) return std::nullopt; + return ret; } -unsigned long BignumPointer::getWord() const { // NOLINT(runtime/int) - if (!bn_) return 0; +std::optional BignumPointer::getWord() // NOLINT(runtime/int) + const { + if (!bn_) return std::nullopt; return GetWord(bn_.get()); } @@ -4805,6 +4809,7 @@ bool extractP1363(const Buffer& buf, // ============================================================================ +#if !OPENSSL_WITH_EVP_MAC HMACCtxPointer::HMACCtxPointer() : ctx_(nullptr) {} HMACCtxPointer::HMACCtxPointer(HMAC_CTX* ctx) : ctx_(ctx) {} @@ -4864,8 +4869,9 @@ bool HMACCtxPointer::digestInto(Buffer* buf) { HMACCtxPointer HMACCtxPointer::New() { return HMACCtxPointer(HMAC_CTX_new()); } +#endif // !OPENSSL_WITH_EVP_MAC -#if OPENSSL_WITH_KMAC +#if OPENSSL_WITH_EVP_MAC EVPMacPointer::EVPMacPointer(EVP_MAC* mac) : mac_(mac) {} EVPMacPointer::EVPMacPointer(EVPMacPointer&& other) noexcept @@ -4953,7 +4959,92 @@ EVPMacCtxPointer EVPMacCtxPointer::New(EVP_MAC* mac) { if (!mac) return EVPMacCtxPointer(); return EVPMacCtxPointer(EVP_MAC_CTX_new(mac)); } -#endif // OPENSSL_WITH_KMAC + +HMACCtxPointer::HMACCtxPointer() = default; + +HMACCtxPointer::HMACCtxPointer(EVPMacPointer&& mac, EVPMacCtxPointer&& ctx) + : mac_(std::move(mac)), ctx_(std::move(ctx)) {} + +HMACCtxPointer::HMACCtxPointer(HMACCtxPointer&& other) noexcept + : mac_(std::move(other.mac_)), + ctx_(std::move(other.ctx_)), + md_size_(other.md_size_) { + other.md_size_ = 0; +} + +HMACCtxPointer& HMACCtxPointer::operator=(HMACCtxPointer&& other) noexcept { + if (this == &other) return *this; + mac_ = std::move(other.mac_); + ctx_ = std::move(other.ctx_); + md_size_ = other.md_size_; + other.md_size_ = 0; + return *this; +} + +HMACCtxPointer::~HMACCtxPointer() { + reset(); +} + +void HMACCtxPointer::reset() { + ctx_.reset(); + mac_.reset(); + md_size_ = 0; +} + +bool HMACCtxPointer::init(const Buffer& buf, const Digest& md) { + if (!ctx_ || !md) return false; + + const char* md_name = EVP_MD_get0_name(md); + if (md_name == nullptr) return false; + + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string( + OSSL_MAC_PARAM_DIGEST, const_cast(md_name), 0), + OSSL_PARAM_construct_end(), + }; + + if (!ctx_.init(buf, params)) return false; + md_size_ = md.size(); + return true; +} + +bool HMACCtxPointer::update(const Buffer& buf) { + if (!ctx_) return false; + return ctx_.update(buf); +} + +DataPointer HMACCtxPointer::digest() { + if (md_size_ == 0) return {}; + auto data = DataPointer::Alloc(md_size_); + if (!data) return {}; + Buffer buf = data; + if (!digestInto(&buf)) return {}; + return data.resize(buf.len); +} + +bool HMACCtxPointer::digestInto(Buffer* buf) { + if (!ctx_) return false; + + size_t len = buf->len; + if (EVP_MAC_final( + ctx_.get(), static_cast(buf->data), &len, buf->len) != + 1) + return false; + + buf->len = len; + return true; +} + +HMACCtxPointer HMACCtxPointer::New() { + auto mac = EVPMacPointer::Fetch(OSSL_MAC_NAME_HMAC); + if (!mac) return {}; + + auto ctx = EVPMacCtxPointer::New(mac.get()); + if (!ctx) return {}; + + return HMACCtxPointer(std::move(mac), std::move(ctx)); +} +#endif // OPENSSL_WITH_EVP_MAC DataPointer hashDigest(const Buffer& buf, const EVP_MD* md) {