From e3d78359a1169a9e4914faf2d5eed7fbc3735f1b Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 30 Apr 2021 12:00:40 -0700 Subject: [PATCH] crypto: add HMAC to crypto.timingSafeEqual() Add HMAC to crypto.timingSafeEqual(). This makes things slower but also makes them far more timing safe. Refs: https://github.com/nodejs/node/issues/38226#issuecomment-829468646 Fixes: https://github.com/nodejs/node/issues/38226 --- src/crypto/crypto_timing.cc | 43 ++++++++++++++++++++++++++++++++++++- src/crypto/crypto_timing.h | 3 +++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/crypto/crypto_timing.cc b/src/crypto/crypto_timing.cc index 3cc1a12ec009d6..97e1fedfa69a80 100644 --- a/src/crypto/crypto_timing.cc +++ b/src/crypto/crypto_timing.cc @@ -6,6 +6,8 @@ #include "node.h" #include +#include +#include namespace node { @@ -42,8 +44,47 @@ void TimingSafeEqual(const FunctionCallbackInfo& args) { return; } + uint16_t bufKey[8]; + CHECK(crypto::EntropySource(reinterpret_cast(bufKey), + sizeof(bufKey))); + char key[kKeySize]; + snprintf(key, + sizeof(key), + "%04x%04x%04x%04x%04x%04x%04x%04x", + bufKey[0], + bufKey[1], + bufKey[2], + bufKey[3], + bufKey[4], + bufKey[5], + bufKey[6], + bufKey[7]); + + std::array hash1; + std::array hash2; + unsigned int hash1Len; + unsigned int hash2Len; + + HMAC(EVP_sha256(), + key, + kKeySize, + reinterpret_cast(buf1.data()), + static_cast(buf1.size()), + hash1.data(), + &hash1Len); + + HMAC(EVP_sha256(), + key, + kKeySize, + reinterpret_cast(buf2.data()), + static_cast(buf2.size()), + hash2.data(), + &hash2Len); + + assert(hash1Len == hash2Len); + return args.GetReturnValue().Set( - CRYPTO_memcmp(buf1.data(), buf2.data(), buf1.size()) == 0); + CRYPTO_memcmp(hash1.data(), hash2.data(), hash1Len) == 0); } void Initialize(Environment* env, Local target) { diff --git a/src/crypto/crypto_timing.h b/src/crypto/crypto_timing.h index 3e0594ce3ecc51..8975ba8f2bf8a0 100644 --- a/src/crypto/crypto_timing.h +++ b/src/crypto/crypto_timing.h @@ -11,6 +11,9 @@ namespace crypto { namespace Timing { void Initialize(Environment* env, v8::Local target); void RegisterExternalReferences(ExternalReferenceRegistry* registry); + +static const int kKeySize = 256; + } // namespace Timing } // namespace crypto } // namespace node