// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "crypto/kdf.h" #include #include #include "base/containers/span.h" #include "base/strings/string_number_conversions.h" #include "testing/gtest/include/gtest/gtest.h" using KDFTest = ::testing::Test; TEST(KDFTest, Pbkdf2HmacSha1KnownAnswers) { struct TestCase { std::string password; std::string salt; crypto::kdf::Pbkdf2HmacSha1Params params; size_t len; const char* result; }; // RFC 6070 test vectors: constexpr auto cases = std::to_array({ {"password", "salt", {1}, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6"}, {"password", "salt", {2}, 20, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"}, }); for (const auto& c : cases) { std::vector key(c.len); crypto::kdf::DeriveKeyPbkdf2HmacSha1( c.params, base::as_byte_span(c.password), base::as_byte_span(c.salt), key, crypto::SubtlePassKey::ForTesting()); std::vector result_bytes(c.len); ASSERT_TRUE(base::HexStringToSpan(c.result, result_bytes)); EXPECT_EQ(key, result_bytes); } } TEST(KDFTest, ScryptKnownAnswers) { struct TestCase { std::string password; std::string salt; crypto::kdf::ScryptParams params; size_t len; const char* result; }; // RFC 7914 test vectors - note that RFC 7914 does not specify // max_memory_bytes so we just pass 0 here and let BoringSSL figure it out for // us. constexpr auto cases = std::to_array({ {"password", "NaCl", {.cost = 1024, .block_size = 8, .parallelization = 16}, 64, "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b373162" "2eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640"}, }); for (const auto& c : cases) { std::vector key(c.len); crypto::kdf::DeriveKeyScrypt(c.params, base::as_byte_span(c.password), base::as_byte_span(c.salt), key, crypto::SubtlePassKey::ForTesting()); std::vector result_bytes(c.len); ASSERT_TRUE(base::HexStringToSpan(c.result, result_bytes)); EXPECT_EQ(key, result_bytes); } } TEST(KDFTest, InvalidScryptParameters) { constexpr auto cases = std::to_array({ // cost parameter is not a power of 2 {.cost = 1023, .block_size = 8, .parallelization = 16}, // TODO: others, after we document the exact constraints }); for (const auto& c : cases) { std::vector key(64); EXPECT_DEATH_IF_SUPPORTED( crypto::kdf::DeriveKeyScrypt(c, base::as_byte_span("password"), base::as_byte_span("NaCl"), key, crypto::SubtlePassKey::ForTesting()), ""); } }