#include "extensions/common/crypto/utility_impl.h" #include "common/common/assert.h" #include "extensions/common/crypto/crypto_impl.h" #include "absl/container/fixed_array.h" #include "absl/strings/ascii.h" #include "absl/strings/str_cat.h" namespace Envoy { namespace Common { namespace Crypto { std::vector UtilityImpl::getSha256Digest(const Buffer::Instance& buffer) { std::vector digest(SHA256_DIGEST_LENGTH); bssl::ScopedEVP_MD_CTX ctx; auto rc = EVP_DigestInit(ctx.get(), EVP_sha256()); RELEASE_ASSERT(rc == 1, "Failed to init digest context"); for (const auto& slice : buffer.getRawSlices()) { rc = EVP_DigestUpdate(ctx.get(), slice.mem_, slice.len_); RELEASE_ASSERT(rc == 1, "Failed to update digest"); } rc = EVP_DigestFinal(ctx.get(), digest.data(), nullptr); RELEASE_ASSERT(rc == 1, "Failed to finalize digest"); return digest; } std::vector UtilityImpl::getSha256Hmac(const std::vector& key, absl::string_view message) { std::vector hmac(SHA256_DIGEST_LENGTH); const auto ret = HMAC(EVP_sha256(), key.data(), key.size(), reinterpret_cast(message.data()), message.size(), hmac.data(), nullptr); RELEASE_ASSERT(ret != nullptr, "Failed to create HMAC"); return hmac; } const VerificationOutput UtilityImpl::verifySignature(absl::string_view hash, CryptoObject& key, const std::vector& signature, const std::vector& text) { // Step 1: initialize EVP_MD_CTX bssl::ScopedEVP_MD_CTX ctx; // Step 2: initialize EVP_MD const EVP_MD* md = getHashFunction(hash); if (md == nullptr) { return {false, absl::StrCat(hash, " is not supported.")}; } // Step 3: initialize EVP_DigestVerify auto pkey_wrapper = Common::Crypto::Access::getTyped(key); EVP_PKEY* pkey = pkey_wrapper->getEVP_PKEY(); if (pkey == nullptr) { return {false, "Failed to initialize digest verify."}; } int ok = EVP_DigestVerifyInit(ctx.get(), nullptr, md, nullptr, pkey); if (!ok) { return {false, "Failed to initialize digest verify."}; } // Step 4: verify signature ok = EVP_DigestVerify(ctx.get(), signature.data(), signature.size(), text.data(), text.size()); // Step 5: check result if (ok == 1) { return {true, ""}; } return {false, absl::StrCat("Failed to verify digest. Error code: ", ok)}; } CryptoObjectPtr UtilityImpl::importPublicKey(const std::vector& key) { CBS cbs({key.data(), key.size()}); return std::make_unique(EVP_parse_public_key(&cbs)); } const EVP_MD* UtilityImpl::getHashFunction(absl::string_view name) { const std::string hash = absl::AsciiStrToLower(name); // Hash algorithms set refers // https://github.com/google/boringssl/blob/master/include/openssl/digest.h if (hash == "sha1") { return EVP_sha1(); } else if (hash == "sha224") { return EVP_sha224(); } else if (hash == "sha256") { return EVP_sha256(); } else if (hash == "sha384") { return EVP_sha384(); } else if (hash == "sha512") { return EVP_sha512(); } else { return nullptr; } } // Register the crypto utility singleton. static Crypto::ScopedUtilitySingleton* utility_ = new Crypto::ScopedUtilitySingleton(std::make_unique()); } // namespace Crypto } // namespace Common } // namespace Envoy