Merge branch 'tizen' into yaca
[platform/core/test/security-tests.git] / src / ckm / unprivileged / sign-verify.cpp
1 /*
2  *  Copyright (c) 2019 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  * @file       sign-verify.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <string>
23 #include <vector>
24 #include <unordered_map>
25
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>
32
33 using namespace CKM;
34
35 namespace {
36
37 const char* PASSWORD = "test-password";
38 const uid_t UID = 5001;
39
40 struct KeyAliasPair
41 {
42     Alias prv;
43     Alias pub;
44 };
45
46 enum Algo {
47     RSA,
48     DSA,
49     ECDSA
50 };
51
52 // algo names
53 const std::unordered_map<Algo, std::string> ALGO2STR = {
54         { RSA,   "RSA" },
55         { DSA,   "DSA" },
56         { ECDSA, "ECDSA" },
57 };
58
59 // keys
60 std::unordered_map<Algo, std::unordered_map<size_t, std::vector<KeyAliasPair>>> KEYS;
61
62 enum KeyIdx {
63     PRIMARY = 0,
64     PASSWORD_PROTECTED = 1,
65
66     KEY_IDX_MAX
67 };
68
69 // hash algo names
70 const std::unordered_map<ckmc_hash_algo_e, std::string> HASH2STR = {
71 #ifndef TZ_BACKEND
72         // no hash is not supported in TZ
73         { CKMC_HASH_NONE,   "NONE" },
74 #endif
75         { CKMC_HASH_SHA1,   "SHA1" },
76         { CKMC_HASH_SHA256, "SHA256" },
77         { CKMC_HASH_SHA384, "SHA384" },
78         { CKMC_HASH_SHA512, "SHA512" },
79 };
80
81 // padding names
82 const std::unordered_map<ckmc_rsa_padding_algo_e, std::string> PAD2STR = {
83 #ifndef TZ_BACKEND
84         // no padding is not supported in TZ
85         { CKMC_NONE_PADDING,    "NONE" },
86 #endif
87         { CKMC_PKCS1_PADDING,   "PKCS1" },
88 #ifndef TZ_BACKEND
89         // X9.31 is not supported in TZ
90         { CKMC_X931_PADDING,    "X931" },
91 #endif
92 };
93
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);
97
98 // test  messages
99 RawBufferPtr MESSAGE_SHORT;
100 std::unordered_map<size_t, RawBufferPtr> MESSAGES;
101 RawBufferPtr MESSAGE_LONG;
102
103 class SignVerifyGroupFixture: public DPL::Test::TestGroup
104 {
105 public:
106     void Init() override
107     {
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));
112
113         // Policy backend to use in subsequent operations (global for each test case)
114 #ifdef TZ_BACKEND
115         m_backend = PolicyBackend::FORCE_HARDWARE;
116 #else
117         m_backend = PolicyBackend::FORCE_SOFTWARE;
118 #endif
119
120         // generate keys
121         m_manager = Manager::create();
122         generateKeys(RSA, 1024);
123         generateKeys(RSA, 2048);
124         generateKeys(RSA, 4096);
125         generateKeys(DSA, 1024);
126 #ifndef TZ_BACKEND
127         /*
128          * For DSA with SHA1 only 1024-bit keys are supported and TZ does not currently support
129          * anything else than SHA1 for DSA.
130          */
131         generateKeys(DSA, 2048);
132         generateKeys(DSA, 3072);
133         generateKeys(DSA, 4096);
134 #endif
135 #ifndef TZ_BACKEND
136         // ECDSA is not yet supported on TZ
137         generateKeys(ECDSA, EC_PRIME192V1);
138         generateKeys(ECDSA, EC_PRIME256V1);
139         generateKeys(ECDSA, EC_SECP384R1);
140 #endif
141
142         MESSAGE_SHORT = create_raw_buffer(createRandomBufferCAPI(512/8));
143
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;
153
154         MESSAGE_LONG = create_raw_buffer(createRandomBufferCAPI(1000));
155     }
156
157     void generateKeys(Algo type, size_t bitLen)
158     {
159         for (int i = 0; i < KEY_IDX_MAX; i++)
160         {
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);
166             }
167
168             KeyAliasPair alias;
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;
172             int ret;
173             switch (type)
174             {
175             case RSA:
176                 ret = m_manager->createKeyPairRSA(bitLen,
177                                                   alias.prv, alias.pub,
178                                                   prvPolicy, pubPolicy);
179                 break;
180             case DSA:
181                 ret = m_manager->createKeyPairDSA(bitLen,
182                                                   alias.prv, alias.pub,
183                                                   prvPolicy, pubPolicy);
184                 break;
185             case ECDSA:
186                 ret = m_manager->createKeyPairECDSA(static_cast<ElipticCurve>(bitLen),
187                                                     alias.prv, alias.pub,
188                                                     prvPolicy, pubPolicy);
189                 break;
190             default:
191                 ret = CKM_API_ERROR_UNKNOWN;
192             }
193             if (ret != CKM_API_SUCCESS)
194                 RUNNER_ERROR_MSG("key creation failed. Type: " << ALGO2STR.at(type) <<
195                                  " bits: " << bitLen << " error: " <<  APICodeToString(ret));
196
197             KEYS[type][bitLen].push_back(alias);
198         }
199     }
200
201     void Finish() override
202     {
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);
208                 }
209             }
210         }
211
212         MESSAGE_SHORT.reset();
213
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);
218     }
219 private:
220     ManagerShPtr m_manager;
221     PolicyBackend m_backend;
222 };
223
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)
228 {
229     std::stringstream ss;
230     ss << " Alias: " <<  alias << ", hash algo: " << HASH2STR.at(hash) <<
231           ", padding: " << PAD2STR.at(padding) << ", message len: " << message->size << "B.";
232     return ss.str();
233 }
234
235 void signExpect(int expected,
236                 const Alias& alias,
237                 const char* pw,
238                 const RawBufferPtr& message,
239                 const ckmc_hash_algo_e hash,
240                 const ckmc_rsa_padding_algo_e padding,
241                 RawBufferPtr& signature)
242 {
243     ckmc_raw_buffer_s* cSignature = nullptr;
244
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);
255     } else {
256         RUNNER_ASSERT_MSG(cSignature == nullptr,
257                           "Non-empty signature returned." <<
258                           params2str(alias, hash, padding, message));
259     }
260 }
261
262 void signInvalid(const Alias& alias,
263                  const char* pw,
264                  const RawBufferPtr& message,
265                  const ckmc_hash_algo_e hash,
266                  const ckmc_rsa_padding_algo_e padding)
267 {
268     RawBufferPtr signature;
269     signExpect(CKMC_ERROR_INVALID_PARAMETER, alias, pw, message, hash, padding, signature);
270 }
271
272 void verifyExpect(int expected,
273                   const Alias& alias,
274                   const char* pw,
275                   const RawBufferPtr& message,
276                   const ckmc_hash_algo_e hash,
277                   const ckmc_rsa_padding_algo_e padding,
278                   const RawBufferPtr& signature)
279 {
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));
285 }
286
287 void signVerify(const KeyAliasPair& aliasPair,
288                 const char* pw,
289                 const RawBufferPtr& message,
290                 const ckmc_hash_algo_e hash,
291                 const ckmc_rsa_padding_algo_e padding)
292 {
293     RawBufferPtr signature;
294     signExpect(CKMC_ERROR_NONE, aliasPair.prv, pw, message, hash, padding, signature);
295
296     RUNNER_ASSERT_MSG(signature->size > 0, "Empty signature returned");
297
298     verifyExpect(CKMC_ERROR_NONE, aliasPair.pub, pw, message, hash, padding, signature);
299
300     // modify 1 bit of the signature
301     signature->data[0] ^= 0x01;
302
303     // expect verification failure
304     verifyExpect(CKMC_ERROR_VERIFICATION_FAILED,
305                  aliasPair.pub,
306                  pw,
307                  message,
308                  hash,
309                  padding,
310                  signature);
311 }
312 // test given key pair against all hash and padding algos
313 void testSignVerify(Algo algo, size_t keyBits, int idx)
314 {
315 #ifdef TZ_BACKEND
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.");
319     if (algo == ECDSA)
320         RUNNER_IGNORED_MSG("ECDSA is not yet supported in TZ");
321 #endif
322
323     std::string pw;
324     if (idx == PASSWORD_PROTECTED)
325         pw = PASSWORD;
326
327     const KeyAliasPair& keys = KEYS[algo][keyBits][idx];
328
329     // iterate over hash algorithms
330     for (const auto& hash : HASH2STR) {
331 #ifdef TZ_BACKEND
332         // in case of DSA only SHA1 is supported on TZ
333         if (algo == DSA && hash.first != CKMC_HASH_SHA1)
334             continue;
335 #endif
336
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);
341             };
342             auto expectInvalid = [&](const RawBufferPtr& msg) {
343                 signInvalid(keys.prv, pw.c_str(), msg, hash.first, pad.first);
344             };
345
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));
351                 }
352                 // no padding + short message
353                 expectInvalid(MESSAGE_SHORT);
354
355                 // no padding + long message
356                 expectInvalid(MESSAGE_LONG);
357
358             } else {
359                 if (hash.first == CKMC_HASH_NONE) {
360                     // no hash + padding + long message
361                     expectInvalid(MESSAGE_LONG);
362
363                     // no hash + padding + short message
364                     if (algo == RSA)
365                         expectSuccess(MESSAGE_SHORT);
366                     else
367                         expectInvalid(MESSAGE_SHORT); // no support for CKMC_HASH_NONE
368                 } else {
369                     // hash + padding + short message
370                     expectSuccess(MESSAGE_SHORT);
371
372                     // hash + padding + long message
373                     expectSuccess(MESSAGE_LONG);
374                 }
375             }
376         }
377     }
378 }
379
380 } // namespace anonymous
381
382 RUNNER_TEST_GROUP_INIT_ENV(CKM_SIGN_VERIFY, SignVerifyGroupFixture);
383
384
385 // RSA
386 RUNNER_TEST(TSV_0110_sign_verify_rsa_1024)
387 {
388     testSignVerify(RSA, 1024, PRIMARY);
389 }
390
391 RUNNER_TEST(TSV_0120_sign_verify_rsa_1024_pw)
392 {
393     testSignVerify(RSA, 1024, PASSWORD_PROTECTED);
394 }
395
396 RUNNER_TEST(TSV_0130_sign_verify_rsa_2048)
397 {
398     testSignVerify(RSA, 2048, PRIMARY);
399 }
400
401 RUNNER_TEST(TSV_0140_sign_verify_rsa_2048_pw)
402 {
403     testSignVerify(RSA, 2048, PASSWORD_PROTECTED);
404 }
405
406 RUNNER_TEST(TSV_0150_sign_verify_rsa_4096)
407 {
408     testSignVerify(RSA, 4096, PRIMARY);
409 }
410
411 RUNNER_TEST(TSV_0160_sign_verify_rsa_4096_pw)
412 {
413     testSignVerify(RSA, 4096, PASSWORD_PROTECTED);
414 }
415
416
417 // DSA
418 RUNNER_TEST(TSV_0210_sign_verify_dsa_1024)
419 {
420     testSignVerify(DSA, 1024, PRIMARY);
421 }
422
423 RUNNER_TEST(TSV_0220_sign_verify_dsa_1024_pw)
424 {
425     testSignVerify(DSA, 1024, PASSWORD_PROTECTED);
426 }
427
428 RUNNER_TEST(TSV_0230_sign_verify_dsa_2048)
429 {
430     testSignVerify(DSA, 2048, PRIMARY);
431 }
432
433 RUNNER_TEST(TSV_0240_sign_verify_dsa_2048_pw)
434 {
435     testSignVerify(DSA, 2048, PASSWORD_PROTECTED);
436 }
437
438 RUNNER_TEST(TSV_0250_sign_verify_dsa_3072)
439 {
440     testSignVerify(DSA, 3072, PRIMARY);
441 }
442
443 RUNNER_TEST(TSV_0260_sign_verify_dsa_3072_pw)
444 {
445     testSignVerify(DSA, 3072, PASSWORD_PROTECTED);
446 }
447
448 RUNNER_TEST(TSV_0270_sign_verify_dsa_4096)
449 {
450     testSignVerify(DSA, 4096, PRIMARY);
451 }
452
453 RUNNER_TEST(TSV_0280_sign_verify_dsa_4096_pw)
454 {
455     testSignVerify(DSA, 4096, PASSWORD_PROTECTED);
456 }
457
458
459 // ECDSA
460 RUNNER_TEST(TSV_0310_sign_verify_ecdsa_PRIME192V1)
461 {
462     testSignVerify(ECDSA, EC_PRIME192V1, PRIMARY);
463 }
464
465 RUNNER_TEST(TSV_0320_sign_verify_ecdsa_PRIME192V1_pw)
466 {
467     testSignVerify(ECDSA, EC_PRIME192V1, PASSWORD_PROTECTED);
468 }
469
470 RUNNER_TEST(TSV_0330_sign_verify_ecdsa_PRIME256V1)
471 {
472     testSignVerify(ECDSA, EC_PRIME256V1, PRIMARY);
473 }
474
475 RUNNER_TEST(TSV_0340_sign_verify_ecdsa_PRIME256V1_pw)
476 {
477     testSignVerify(ECDSA, EC_PRIME256V1, PASSWORD_PROTECTED);
478 }
479
480 RUNNER_TEST(TSV_0350_sign_verify_ecdsa_SECP384R1)
481 {
482     testSignVerify(ECDSA, EC_SECP384R1, PRIMARY);
483 }
484
485 RUNNER_TEST(TSV_0360_sign_verify_ecdsa_SECP384R1_pw)
486 {
487     testSignVerify(ECDSA, EC_SECP384R1, PASSWORD_PROTECTED);
488 }
489
490 // TODO: border cases for padding
491 // TODO: invalid arguments
492 // TODO: Big data