2 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
19 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation
26 #include <unordered_map>
29 #include <openssl/evp.h>
31 #include <boost_macros_wrapper.h>
33 #include <sw-backend/kbkdf.h>
39 unsigned short fromHexChar(char c)
41 unsigned short ret = 0;
42 if (c >= 'a' && c <= 'f')
44 else if (c >= '0' && c <= '9')
48 "Invalid input: 0x" << std::hex << std::setw(2) << static_cast<unsigned short>(c));
53 RawBuffer fromHex(const std::string& hex)
56 ret.reserve(hex.size()/2);
57 for (size_t i=0;i<hex.size();i+=2) {
58 auto byte = (fromHexChar(hex[i]) << 4) + fromHexChar(hex[i+1]);
65 bool map(const std::string& value, T& variable, const std::unordered_map<std::string, T>& mapping)
67 auto handler = mapping.find(value);
68 if (handler == mapping.end())
71 variable = handler->second;
75 const std::string PRF_PREFIX = "[PRF=";
79 BOOST_AUTO_TEST_SUITE(KBKDF_TEST)
81 POSITIVE_TEST_CASE(kbkdf_test_vectors)
83 const EVP_MD* md = nullptr;
85 // test case parameters
95 KbkdfCounterLocation ctr;
96 bool knownLocation = false;
98 std::map<std::string, std::function<void(const std::string&)>> parser = {
99 {"[PRF", [&](const std::string& value) {
100 if (!map(value, md, {
101 {"HMAC_SHA256]", EVP_sha256()},
102 {"HMAC_SHA384]", EVP_sha384()},
103 {"HMAC_SHA512]", EVP_sha512()},
107 {"[CTRLOCATION", [&](const std::string& value) {
108 knownLocation = map(value, ctr, {
109 {"BEFORE_FIXED]", KbkdfCounterLocation::BEFORE_FIXED},
110 {"AFTER_FIXED]", KbkdfCounterLocation::AFTER_FIXED},
111 {"MIDDLE_FIXED]", KbkdfCounterLocation::MIDDLE_FIXED},
114 {"[RLEN", [&](const std::string& value) {
115 if (!map(value, rlen, {
123 {"L", [&](const std::string& value) { length = std::stoul(value); }},
124 {"KI", [&](const std::string& value) { keyBuffer = fromHex(value); }},
125 {"FixedInputDataByteLen", [&](const std::string& value) { fixedLen = std::stoul(value); }},
126 {"FixedInputData", [&](const std::string& value) { fixed = fromHex(value); }},
127 {"DataBeforeCtrLen", [&](const std::string& value) { labelLen = std::stoul(value); }},
128 {"DataBeforeCtrData", [&](const std::string& value) { label = fromHex(value); }},
129 {"DataAfterCtrLen", [&](const std::string& value) { contextLen = std::stoul(value); }},
130 {"DataAfterCtrData", [&](const std::string& value) { context = fromHex(value); }},
131 {"KO", [&](const std::string& value) {
132 if (knownLocation && md != nullptr && rlen > 0)
134 std::cout << '.' << std::flush;
136 auto expectedOutput = fromHex(value);
140 BOOST_REQUIRE(fixedLen == fixed.size());
142 output = deriveKbkdfHmac(keyBuffer, length, md, ctr, rlen, fixed);
144 BOOST_REQUIRE(labelLen > 0);
145 BOOST_REQUIRE(labelLen == label.size());
146 BOOST_REQUIRE(contextLen > 0);
147 BOOST_REQUIRE(contextLen == context.size());
149 output = deriveKbkdfHmac(keyBuffer,
160 BOOST_REQUIRE(output == expectedOutput);
174 std::ifstream testFile(DB_TEST_DIR "/KDFCTR_gen.rsp");
175 for (std::string line; std::getline(testFile, line);) {
176 line.erase(std::remove_if(line.begin(), line.end(), [](char c){ return std::isspace(c); }),
179 if (line.empty() || line.front() == '#')
182 auto separator = line.find('=');
183 if (separator == std::string::npos)
186 if (line.front() == '[') {
187 if (line.compare(0, PRF_PREFIX.size(), PRF_PREFIX) == 0)
192 auto key = line.substr(0, separator);
193 auto value = line.substr(separator+1);
195 auto handler = parser.find(key);
196 if (handler == parser.end())
199 handler->second(value);
203 BOOST_AUTO_TEST_SUITE_END()