From 6ea75d4f9cda6034c36d0d832f441d824a5c5dd1 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 1 Sep 2022 15:59:52 +0900 Subject: [PATCH] [ruby/openssl] hmac: use EVP_PKEY_new_raw_private_key() if available Current OpenSSL 3.0.x release has a regression with zero-length MAC keys. While this issue should be fixed in a future release of OpenSSL, we can use EVP_PKEY_new_raw_private_key() in place of the problematic EVP_PKEY_new_mac_key() to avoid the issue. OpenSSL 3.0's man page recommends using it regardless: > EVP_PKEY_new_mac_key() works in the same way as > EVP_PKEY_new_raw_private_key(). New applications should use > EVP_PKEY_new_raw_private_key() instead. Fixes https://github.com/ruby/openssl/issues/369#issuecomment-1224912710 https://github.com/ruby/openssl/commit/4293f18b1f --- ext/openssl/extconf.rb | 1 + ext/openssl/ossl_hmac.c | 8 ++++++++ test/openssl/test_hmac.rb | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index f8be3e9e039058..fd96533569454a 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -174,6 +174,7 @@ def find_openssl_library # added in 1.1.1 have_func("EVP_PKEY_check", evp_h) +have_func("EVP_PKEY_new_raw_private_key", evp_h) have_func("SSL_CTX_set_ciphersuites", ssl_h) # added in 3.0.0 diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index bfe3a74b126b00..1a5f471a27d3f3 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -97,11 +97,19 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) GetHMAC(self, ctx); StringValue(key); +#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + (unsigned char *)RSTRING_PTR(key), + RSTRING_LENINT(key)); + if (!pkey) + ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key"); +#else pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, (unsigned char *)RSTRING_PTR(key), RSTRING_LENINT(key)); if (!pkey) ossl_raise(eHMACError, "EVP_PKEY_new_mac_key"); +#endif if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest), NULL, pkey) != 1) { EVP_PKEY_free(pkey); diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb index 2f53a813e191ec..3cb707448a5f37 100644 --- a/test/openssl/test_hmac.rb +++ b/test/openssl/test_hmac.rb @@ -62,6 +62,14 @@ def test_singleton_methods b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There") assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest end + + def test_zero_length_key + # Empty string as the key + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test") + assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "", "test") + assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest + end end end