• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "crypto/kdf.h"
6 
7 #include <array>
8 #include <string>
9 
10 #include "base/containers/span.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 using KDFTest = ::testing::Test;
15 
TEST(KDFTest,Pbkdf2HmacSha1KnownAnswers)16 TEST(KDFTest, Pbkdf2HmacSha1KnownAnswers) {
17   struct TestCase {
18     std::string password;
19     std::string salt;
20     crypto::kdf::Pbkdf2HmacSha1Params params;
21     size_t len;
22     const char* result;
23   };
24 
25   // RFC 6070 test vectors:
26   constexpr auto cases = std::to_array<TestCase>({
27       {"password", "salt", {1}, 20, "0c60c80f961f0e71f3a9b524af6012062fe037a6"},
28       {"password", "salt", {2}, 20, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"},
29   });
30 
31   for (const auto& c : cases) {
32     std::vector<uint8_t> key(c.len);
33     crypto::kdf::DeriveKeyPbkdf2HmacSha1(
34         c.params, base::as_byte_span(c.password), base::as_byte_span(c.salt),
35         key, crypto::SubtlePassKey::ForTesting());
36 
37     std::vector<uint8_t> result_bytes(c.len);
38     ASSERT_TRUE(base::HexStringToSpan(c.result, result_bytes));
39     EXPECT_EQ(key, result_bytes);
40   }
41 }
42 
TEST(KDFTest,ScryptKnownAnswers)43 TEST(KDFTest, ScryptKnownAnswers) {
44   struct TestCase {
45     std::string password;
46     std::string salt;
47     crypto::kdf::ScryptParams params;
48     size_t len;
49     const char* result;
50   };
51 
52   // RFC 7914 test vectors - note that RFC 7914 does not specify
53   // max_memory_bytes so we just pass 0 here and let BoringSSL figure it out for
54   // us.
55   constexpr auto cases = std::to_array<TestCase>({
56       {"password",
57        "NaCl",
58        {.cost = 1024, .block_size = 8, .parallelization = 16},
59        64,
60        "fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b373162"
61        "2eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640"},
62   });
63 
64   for (const auto& c : cases) {
65     std::vector<uint8_t> key(c.len);
66     crypto::kdf::DeriveKeyScrypt(c.params, base::as_byte_span(c.password),
67                                  base::as_byte_span(c.salt), key,
68                                  crypto::SubtlePassKey::ForTesting());
69 
70     std::vector<uint8_t> result_bytes(c.len);
71     ASSERT_TRUE(base::HexStringToSpan(c.result, result_bytes));
72     EXPECT_EQ(key, result_bytes);
73   }
74 }
75 
TEST(KDFTest,InvalidScryptParameters)76 TEST(KDFTest, InvalidScryptParameters) {
77   constexpr auto cases = std::to_array<crypto::kdf::ScryptParams>({
78       // cost parameter is not a power of 2
79       {.cost = 1023, .block_size = 8, .parallelization = 16},
80       // TODO: others, after we document the exact constraints
81   });
82 
83   for (const auto& c : cases) {
84     std::vector<uint8_t> key(64);
85     EXPECT_DEATH_IF_SUPPORTED(
86         crypto::kdf::DeriveKeyScrypt(c, base::as_byte_span("password"),
87                                      base::as_byte_span("NaCl"), key,
88                                      crypto::SubtlePassKey::ForTesting()),
89         "");
90   }
91 }
92