Release 0.1.66
[platform/core/security/key-manager.git] / unit-tests / test_kbkdf.cpp
1 /*
2  *  Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16
17 /*
18  * KBKDF test vectors:
19  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation
20  */
21
22 #include <fstream>
23 #include <string>
24 #include <algorithm>
25 #include <iomanip>
26 #include <unordered_map>
27 #include <iostream>
28
29 #include <openssl/evp.h>
30
31 #include <boost_macros_wrapper.h>
32
33 #include <sw-backend/kbkdf.h>
34
35 using namespace CKM;
36
37 namespace {
38
39 unsigned short fromHexChar(char c)
40 {
41         unsigned short ret = 0;
42         if (c >= 'a' && c <= 'f')
43                 ret = 10 + c - 'a';
44         else if (c >= '0' && c <= '9')
45                 ret = c - '0';
46         else
47                 BOOST_FAIL(
48                     "Invalid input: 0x" << std::hex << std::setw(2) << static_cast<unsigned short>(c));
49
50         return ret;
51 }
52
53 RawBuffer fromHex(const std::string& hex)
54 {
55         RawBuffer ret;
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]);
59                 ret.push_back(byte);
60         }
61         return ret;
62 }
63
64 template <typename T>
65 bool map(const std::string& value, T& variable, const std::unordered_map<std::string, T>& mapping)
66 {
67         auto handler = mapping.find(value);
68         if (handler == mapping.end())
69                 return false;
70
71         variable = handler->second;
72         return true;
73 }
74
75 const std::string PRF_PREFIX = "[PRF=";
76
77 } // namespace
78
79 BOOST_AUTO_TEST_SUITE(KBKDF_TEST)
80
81 POSITIVE_TEST_CASE(kbkdf_test_vectors)
82 {
83         const EVP_MD* md = nullptr;
84
85         // test case parameters
86         size_t length;
87         RawBuffer keyBuffer;
88         size_t fixedLen;
89         RawBuffer fixed;
90         size_t labelLen;
91         RawBuffer label;
92         size_t contextLen;
93         RawBuffer context;
94         size_t rlen;
95         KbkdfCounterLocation ctr;
96         bool knownLocation = false;
97
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()},
104                         }))
105                                 md = nullptr;
106                 }},
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},
112                         });
113                 }},
114                 {"[RLEN", [&](const std::string& value) {
115                         if (!map(value, rlen, {
116                                 {"8_BITS]", 8},
117                                 {"16_BITS]", 16},
118                                 {"24_BITS]", 24},
119                                 {"32_BITS]", 32},
120                         }))
121                                 rlen = 0;
122                 }},
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)
133                         {
134                                 std::cout << '.' << std::flush;
135
136                                 auto expectedOutput = fromHex(value);
137
138                                 RawBuffer output;
139                                 if (fixedLen > 0) {
140                                         BOOST_REQUIRE(fixedLen == fixed.size());
141
142                                         output = deriveKbkdfHmac(keyBuffer, length, md, ctr, rlen, fixed);
143                                 } else {
144                                         BOOST_REQUIRE(labelLen > 0);
145                                         BOOST_REQUIRE(labelLen == label.size());
146                                         BOOST_REQUIRE(contextLen > 0);
147                                         BOOST_REQUIRE(contextLen == context.size());
148
149                                         output = deriveKbkdfHmac(keyBuffer,
150                                                                  length,
151                                                                  md,
152                                                                  ctr,
153                                                                  rlen,
154                                                                  0,
155                                                                  label,
156                                                                  context,
157                                                                  false);
158                                 }
159
160                                 BOOST_REQUIRE(output == expectedOutput);
161                         }
162
163                         fixed.clear();
164                         fixedLen = 0;
165                         label.clear();
166                         labelLen = 0;
167                         context.clear();
168                         contextLen = 0;
169                         keyBuffer.clear();
170                         length = 0;
171                 }},
172         };
173
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); }),
177                            line.end());
178
179                 if (line.empty() || line.front() == '#')
180                         continue;
181
182                 auto separator = line.find('=');
183                 if (separator == std::string::npos)
184                         continue;
185
186                 if (line.front() == '[') {
187                         if (line.compare(0, PRF_PREFIX.size(), PRF_PREFIX) == 0)
188                                 std::cout << "\n";
189                         std::cout << line;
190                 }
191
192                 auto key = line.substr(0, separator);
193                 auto value = line.substr(separator+1);
194
195                 auto handler = parser.find(key);
196                 if (handler == parser.end())
197                         continue;
198
199                 handler->second(value);
200         }
201 }
202
203 BOOST_AUTO_TEST_SUITE_END()