2 * Copyright (c) 2019 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
17 * @file sign-verify.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
24 #include <unordered_map>
26 #include <dpl/test/test_runner.h>
27 #include <ckm-common.h>
28 #include <ckmc/ckmc-manager.h>
29 #include <ckmc/ckmc-control.h>
30 #include <ckm/ckm-type.h>
31 #include <ckm/ckm-manager.h>
37 const char* PASSWORD = "test-password";
38 const uid_t UID = 5001;
53 const std::unordered_map<Algo, std::string> ALGO2STR = {
60 std::unordered_map<Algo, std::unordered_map<size_t, std::vector<KeyAliasPair>>> KEYS;
64 PASSWORD_PROTECTED = 1,
70 const std::unordered_map<ckmc_hash_algo_e, std::string> HASH2STR = {
72 // no hash is not supported in TZ
73 { CKMC_HASH_NONE, "NONE" },
75 { CKMC_HASH_SHA1, "SHA1" },
76 { CKMC_HASH_SHA256, "SHA256" },
77 { CKMC_HASH_SHA384, "SHA384" },
78 { CKMC_HASH_SHA512, "SHA512" },
82 const std::unordered_map<ckmc_rsa_padding_algo_e, std::string> PAD2STR = {
84 // no padding is not supported in TZ
85 { CKMC_NONE_PADDING, "NONE" },
87 { CKMC_PKCS1_PADDING, "PKCS1" },
89 // X9.31 is not supported in TZ
90 { CKMC_X931_PADDING, "X931" },
94 const int EC_PRIME192V1 = static_cast<int>(ElipticCurve::prime192v1);
95 const int EC_PRIME256V1 = static_cast<int>(ElipticCurve::prime256v1);
96 const int EC_SECP384R1 = static_cast<int>(ElipticCurve::secp384r1);
99 RawBufferPtr MESSAGE_SHORT;
100 std::unordered_map<size_t, RawBufferPtr> MESSAGES;
101 RawBufferPtr MESSAGE_LONG;
103 class SignVerifyGroupFixture: public DPL::Test::TestGroup
108 remove_user_data(UID);
109 int ret = ckmc_unlock_user_key(UID, "db-pass");
110 if (ret != CKMC_ERROR_NONE)
111 RUNNER_ERROR_MSG("DB unlock failed: " << CKMCErrorToString(ret));
113 // Policy backend to use in subsequent operations (global for each test case)
115 m_backend = PolicyBackend::FORCE_HARDWARE;
117 m_backend = PolicyBackend::FORCE_SOFTWARE;
121 m_manager = Manager::create();
122 generateKeys(RSA, 1024);
123 generateKeys(RSA, 2048);
124 generateKeys(RSA, 4096);
125 generateKeys(DSA, 1024);
128 * For DSA with SHA1 only 1024-bit keys are supported and TZ does not currently support
129 * anything else than SHA1 for DSA.
131 generateKeys(DSA, 2048);
132 generateKeys(DSA, 3072);
133 generateKeys(DSA, 4096);
136 // ECDSA is not yet supported on TZ
137 generateKeys(ECDSA, EC_PRIME192V1);
138 generateKeys(ECDSA, EC_PRIME256V1);
139 generateKeys(ECDSA, EC_SECP384R1);
142 MESSAGE_SHORT = create_raw_buffer(createRandomBufferCAPI(512/8));
144 // Set first byte to 0 to avoid "data too large for modulus" error in unpadded RSA
145 MESSAGES[1024] = create_raw_buffer(createRandomBufferCAPI(1024/8));
146 MESSAGES[1024]->data[0] = 0;
147 MESSAGES[2048] = create_raw_buffer(createRandomBufferCAPI(2048/8));
148 MESSAGES[2048]->data[0] = 0;
149 MESSAGES[3072] = create_raw_buffer(createRandomBufferCAPI(3072/8));
150 MESSAGES[3072]->data[0] = 0;
151 MESSAGES[4096]= create_raw_buffer(createRandomBufferCAPI(4096/8));
152 MESSAGES[4096]->data[0] = 0;
154 MESSAGE_LONG = create_raw_buffer(createRandomBufferCAPI(1000));
157 void generateKeys(Algo type, size_t bitLen)
159 for (int i = 0; i < KEY_IDX_MAX; i++)
161 Policy prvPolicy(Password(), false, m_backend);
162 Policy pubPolicy(Password(), true, m_backend);
163 if (i == PASSWORD_PROTECTED) {
164 prvPolicy.password.assign(PASSWORD);
165 pubPolicy.password.assign(PASSWORD);
169 alias.prv = ALGO2STR.at(type) + std::string("_") + std::to_string(bitLen) +
170 std::string("_") + std::to_string(i);
171 alias.pub = std::string("pub") + alias.prv;
176 ret = m_manager->createKeyPairRSA(bitLen,
177 alias.prv, alias.pub,
178 prvPolicy, pubPolicy);
181 ret = m_manager->createKeyPairDSA(bitLen,
182 alias.prv, alias.pub,
183 prvPolicy, pubPolicy);
186 ret = m_manager->createKeyPairECDSA(static_cast<ElipticCurve>(bitLen),
187 alias.prv, alias.pub,
188 prvPolicy, pubPolicy);
191 ret = CKM_API_ERROR_UNKNOWN;
193 if (ret != CKM_API_SUCCESS)
194 RUNNER_ERROR_MSG("key creation failed. Type: " << ALGO2STR.at(type) <<
195 " bits: " << bitLen << " error: " << APICodeToString(ret));
197 KEYS[type][bitLen].push_back(alias);
201 void Finish() override
203 for (const auto &type : KEYS) {
204 for (const auto &entry : type.second) {
205 for (const auto &keyPair : entry.second) {
206 m_manager->removeAlias(keyPair.prv);
207 m_manager->removeAlias(keyPair.pub);
212 MESSAGE_SHORT.reset();
214 int ret = ckmc_lock_user_key(UID);
215 if (ret != CKMC_ERROR_NONE)
216 RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
217 remove_user_data(UID);
220 ManagerShPtr m_manager;
221 PolicyBackend m_backend;
224 std::string params2str(const Alias& alias,
225 const ckmc_hash_algo_e hash,
226 const ckmc_rsa_padding_algo_e padding,
227 const RawBufferPtr& message)
229 std::stringstream ss;
230 ss << " Alias: " << alias << ", hash algo: " << HASH2STR.at(hash) <<
231 ", padding: " << PAD2STR.at(padding) << ", message len: " << message->size << "B.";
235 void signExpect(int expected,
238 const RawBufferPtr& message,
239 const ckmc_hash_algo_e hash,
240 const ckmc_rsa_padding_algo_e padding,
241 RawBufferPtr& signature)
243 ckmc_raw_buffer_s* cSignature = nullptr;
245 int ret = ckmc_create_signature(alias.c_str(), pw, *message, hash, padding, &cSignature);
246 RUNNER_ASSERT_MSG(ret == expected, "Unexpected result during signature creation." <<
247 params2str(alias, hash, padding, message) <<
248 " Expected: " << CKMCErrorToString(expected) <<
249 " got: " << CKMCErrorToString(ret));
250 if (ret == CKMC_ERROR_NONE) {
251 RUNNER_ASSERT_MSG(cSignature != nullptr && cSignature->size > 0,
252 "Empty signature returned." <<
253 params2str(alias, hash, padding, message));
254 signature = create_raw_buffer(cSignature);
256 RUNNER_ASSERT_MSG(cSignature == nullptr,
257 "Non-empty signature returned." <<
258 params2str(alias, hash, padding, message));
262 void signInvalid(const Alias& alias,
264 const RawBufferPtr& message,
265 const ckmc_hash_algo_e hash,
266 const ckmc_rsa_padding_algo_e padding)
268 RawBufferPtr signature;
269 signExpect(CKMC_ERROR_INVALID_PARAMETER, alias, pw, message, hash, padding, signature);
272 void verifyExpect(int expected,
275 const RawBufferPtr& message,
276 const ckmc_hash_algo_e hash,
277 const ckmc_rsa_padding_algo_e padding,
278 const RawBufferPtr& signature)
280 int ret = ckmc_verify_signature(alias.c_str(), pw, *message, *signature, hash, padding);
281 RUNNER_ASSERT_MSG(ret == expected, "Unexpected result during signature verification." <<
282 params2str(alias, hash, padding, message) <<
283 " Expected: " << CKMCErrorToString(expected) <<
284 " got: " << CKMCErrorToString(ret));
287 void signVerify(const KeyAliasPair& aliasPair,
289 const RawBufferPtr& message,
290 const ckmc_hash_algo_e hash,
291 const ckmc_rsa_padding_algo_e padding)
293 RawBufferPtr signature;
294 signExpect(CKMC_ERROR_NONE, aliasPair.prv, pw, message, hash, padding, signature);
296 RUNNER_ASSERT_MSG(signature->size > 0, "Empty signature returned");
298 verifyExpect(CKMC_ERROR_NONE, aliasPair.pub, pw, message, hash, padding, signature);
300 // modify 1 bit of the signature
301 signature->data[0] ^= 0x01;
303 // expect verification failure
304 verifyExpect(CKMC_ERROR_VERIFICATION_FAILED,
312 // test given key pair against all hash and padding algos
313 void testSignVerify(Algo algo, size_t keyBits, int idx)
316 if (algo == DSA && keyBits > 1024)
317 RUNNER_IGNORED_MSG("For DSA with SHA1 only 1024-bit keys are supported and TZ does not"\
318 " currently support anything else than SHA1 for DSA.");
320 RUNNER_IGNORED_MSG("ECDSA is not yet supported in TZ");
324 if (idx == PASSWORD_PROTECTED)
327 const KeyAliasPair& keys = KEYS[algo][keyBits][idx];
329 // iterate over hash algorithms
330 for (const auto& hash : HASH2STR) {
332 // in case of DSA only SHA1 is supported on TZ
333 if (algo == DSA && hash.first != CKMC_HASH_SHA1)
337 // iterate over padding algorithms
338 for (const auto& pad : PAD2STR) {
339 auto expectSuccess = [&](const RawBufferPtr& msg) {
340 signVerify(keys, pw.c_str(), msg, hash.first, pad.first);
342 auto expectInvalid = [&](const RawBufferPtr& msg) {
343 signInvalid(keys.prv, pw.c_str(), msg, hash.first, pad.first);
346 // padding is for RSA only, other algos should ignore it
347 if (algo == RSA && pad.first == CKMC_NONE_PADDING) {
348 if (hash.first == CKMC_HASH_NONE) {
349 // no hash + no padding + key matching message
350 expectSuccess(MESSAGES.at(keyBits));
352 // no padding + short message
353 expectInvalid(MESSAGE_SHORT);
355 // no padding + long message
356 expectInvalid(MESSAGE_LONG);
359 if (hash.first == CKMC_HASH_NONE) {
360 // no hash + padding + long message
361 expectInvalid(MESSAGE_LONG);
363 // no hash + padding + short message
365 expectSuccess(MESSAGE_SHORT);
367 expectInvalid(MESSAGE_SHORT); // no support for CKMC_HASH_NONE
369 // hash + padding + short message
370 expectSuccess(MESSAGE_SHORT);
372 // hash + padding + long message
373 expectSuccess(MESSAGE_LONG);
380 } // namespace anonymous
382 RUNNER_TEST_GROUP_INIT_ENV(CKM_SIGN_VERIFY, SignVerifyGroupFixture);
386 RUNNER_TEST(TSV_0110_sign_verify_rsa_1024)
388 testSignVerify(RSA, 1024, PRIMARY);
391 RUNNER_TEST(TSV_0120_sign_verify_rsa_1024_pw)
393 testSignVerify(RSA, 1024, PASSWORD_PROTECTED);
396 RUNNER_TEST(TSV_0130_sign_verify_rsa_2048)
398 testSignVerify(RSA, 2048, PRIMARY);
401 RUNNER_TEST(TSV_0140_sign_verify_rsa_2048_pw)
403 testSignVerify(RSA, 2048, PASSWORD_PROTECTED);
406 RUNNER_TEST(TSV_0150_sign_verify_rsa_4096)
408 testSignVerify(RSA, 4096, PRIMARY);
411 RUNNER_TEST(TSV_0160_sign_verify_rsa_4096_pw)
413 testSignVerify(RSA, 4096, PASSWORD_PROTECTED);
418 RUNNER_TEST(TSV_0210_sign_verify_dsa_1024)
420 testSignVerify(DSA, 1024, PRIMARY);
423 RUNNER_TEST(TSV_0220_sign_verify_dsa_1024_pw)
425 testSignVerify(DSA, 1024, PASSWORD_PROTECTED);
428 RUNNER_TEST(TSV_0230_sign_verify_dsa_2048)
430 testSignVerify(DSA, 2048, PRIMARY);
433 RUNNER_TEST(TSV_0240_sign_verify_dsa_2048_pw)
435 testSignVerify(DSA, 2048, PASSWORD_PROTECTED);
438 RUNNER_TEST(TSV_0250_sign_verify_dsa_3072)
440 testSignVerify(DSA, 3072, PRIMARY);
443 RUNNER_TEST(TSV_0260_sign_verify_dsa_3072_pw)
445 testSignVerify(DSA, 3072, PASSWORD_PROTECTED);
448 RUNNER_TEST(TSV_0270_sign_verify_dsa_4096)
450 testSignVerify(DSA, 4096, PRIMARY);
453 RUNNER_TEST(TSV_0280_sign_verify_dsa_4096_pw)
455 testSignVerify(DSA, 4096, PASSWORD_PROTECTED);
460 RUNNER_TEST(TSV_0310_sign_verify_ecdsa_PRIME192V1)
462 testSignVerify(ECDSA, EC_PRIME192V1, PRIMARY);
465 RUNNER_TEST(TSV_0320_sign_verify_ecdsa_PRIME192V1_pw)
467 testSignVerify(ECDSA, EC_PRIME192V1, PASSWORD_PROTECTED);
470 RUNNER_TEST(TSV_0330_sign_verify_ecdsa_PRIME256V1)
472 testSignVerify(ECDSA, EC_PRIME256V1, PRIMARY);
475 RUNNER_TEST(TSV_0340_sign_verify_ecdsa_PRIME256V1_pw)
477 testSignVerify(ECDSA, EC_PRIME256V1, PASSWORD_PROTECTED);
480 RUNNER_TEST(TSV_0350_sign_verify_ecdsa_SECP384R1)
482 testSignVerify(ECDSA, EC_SECP384R1, PRIMARY);
485 RUNNER_TEST(TSV_0360_sign_verify_ecdsa_SECP384R1_pw)
487 testSignVerify(ECDSA, EC_SECP384R1, PASSWORD_PROTECTED);
490 // TODO: border cases for padding
491 // TODO: invalid arguments