2 * Copyright (c) 2000-2020 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 ckm-common.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
23 #include <sys/smack.h>
24 #include <ckm/ckm-type.h>
25 #include <ckmc/ckmc-type.h>
26 #include <ckm-common.h>
27 #include <tests_common.h>
28 #include <ckm/ckm-control.h>
29 #include <ckm/ckm-manager.h>
30 #include <ckmc/ckmc-control.h>
31 #include <ckmc/ckmc-manager.h>
34 #include <unordered_map>
36 const std::string SMACK_USER_APP_PREFIX = "User::Pkg::";
37 const char *SYSTEM_LABEL = ckmc_owner_id_system;
38 const char *TEST_LABEL = "test_label";
39 const char *TEST_LABEL_2 = "test_label_2";
40 const char *TEST_LABEL_3 = "test_label_3";
41 const char *TEST_LABEL_4 = "test_label_4";
42 const char *TEST_LABEL_5 = "test_label_5";
44 void generate_random(size_t random_bytes, char *output)
46 RUNNER_ASSERT(random_bytes>0 && output);
48 std::ifstream is("/dev/urandom", std::ifstream::binary);
49 RUNNER_ASSERT_MSG(is, "Failed to read /dev/urandom");
50 is.read(output, random_bytes);
51 if(static_cast<std::streamsize>(random_bytes) != is.gcount()) {
52 RUNNER_ASSERT_MSG(false,
53 "Not enough bytes read from /dev/urandom: " << random_bytes << "!=" <<
58 std::string getLabel() {
61 RUNNER_ASSERT_MSG(0 <= (ret = smack_new_label_from_self(&myLabel)),
62 "Failed to get smack label for self. Error: " << ret);
63 RUNNER_ASSERT_MSG(myLabel, "NULL smack label");
64 std::string result = myLabel;
69 std::string getOwnerIdFromSelf() {
70 const std::string& prefix = SMACK_USER_APP_PREFIX;
71 std::string smack = getLabel();
72 if (0 == smack.compare(0, prefix.size(), prefix))
73 return smack.substr(prefix.size(), std::string::npos);
77 std::string aliasWithLabel(const char *label, const char *alias)
82 ss << label << std::string(ckmc_label_name_separator) << alias;
85 return std::string(alias);
88 std::string aliasWithLabelFromSelf(const char *alias)
90 std::ostringstream oss;
91 oss << getOwnerIdFromSelf() << ckmc_label_name_separator << alias;
96 #define ERRORDESCRIBE(name) case name: return #name
97 const char * CKMCErrorToString(int error) {
99 ERRORDESCRIBE(CKMC_ERROR_NONE);
100 ERRORDESCRIBE(CKMC_ERROR_INVALID_PARAMETER);
101 ERRORDESCRIBE(CKMC_ERROR_OUT_OF_MEMORY);
102 ERRORDESCRIBE(CKMC_ERROR_PERMISSION_DENIED);
103 ERRORDESCRIBE(CKMC_ERROR_SOCKET);
104 ERRORDESCRIBE(CKMC_ERROR_BAD_REQUEST);
105 ERRORDESCRIBE(CKMC_ERROR_BAD_RESPONSE);
106 ERRORDESCRIBE(CKMC_ERROR_SEND_FAILED);
107 ERRORDESCRIBE(CKMC_ERROR_RECV_FAILED);
108 ERRORDESCRIBE(CKMC_ERROR_AUTHENTICATION_FAILED);
109 ERRORDESCRIBE(CKMC_ERROR_BUFFER_TOO_SMALL);
110 ERRORDESCRIBE(CKMC_ERROR_SERVER_ERROR);
111 ERRORDESCRIBE(CKMC_ERROR_DB_LOCKED);
112 ERRORDESCRIBE(CKMC_ERROR_DB_ERROR);
113 ERRORDESCRIBE(CKMC_ERROR_DB_ALIAS_EXISTS);
114 ERRORDESCRIBE(CKMC_ERROR_DB_ALIAS_UNKNOWN);
115 ERRORDESCRIBE(CKMC_ERROR_VERIFICATION_FAILED);
116 ERRORDESCRIBE(CKMC_ERROR_INVALID_FORMAT);
117 ERRORDESCRIBE(CKMC_ERROR_FILE_ACCESS_DENIED);
118 ERRORDESCRIBE(CKMC_ERROR_NOT_EXPORTABLE);
119 ERRORDESCRIBE(CKMC_ERROR_FILE_SYSTEM);
120 ERRORDESCRIBE(CKMC_ERROR_NOT_SUPPORTED);
121 ERRORDESCRIBE(CKMC_ERROR_UNKNOWN);
122 default: return "Error not defined";
127 std::string CKMCReadableError(int error) {
128 std::string output("Error: ");
129 output += std::to_string(error);
130 output += " Description: ";
131 output += CKMCErrorToString(error);
135 void save_data(const char* alias, const char *data, size_t len, const char* password,
136 int expected_err, bool exportable)
138 RUNNER_ASSERT(alias);
141 ckmc_raw_buffer_s buffer;
142 buffer.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
144 ckmc_policy_s policy;
145 policy.password = const_cast<char*>(password);
146 policy.extractable = exportable;
147 int ret = ckmc_save_data(alias, buffer, policy);
148 RUNNER_ASSERT_MSG(expected_err == ret, "Saving data failed. "
149 << CKMCErrorToString(ret) << " while expected: "
150 << CKMCErrorToString(expected_err));
153 void save_data(const char* alias, const char *data, int expected_err, bool exportable)
155 save_data(alias, data, strlen(data), nullptr, expected_err, exportable);
158 void save_data(const char* alias, const char *data, size_t len, int expected_err, bool exportable)
160 save_data(alias, data, len, nullptr, expected_err, exportable);
163 ScopedSaveData::ScopedSaveData(const char* alias, const char *data, int expected_err) : m_alias(alias)
165 save_data(alias, data, expected_err);
168 ScopedSaveData::~ScopedSaveData()
171 * Let it throw. If we can't remove data then remaining tests results will be
174 check_remove_allowed(m_alias.c_str());
177 ScopedDBUnlock::ScopedDBUnlock(uid_t user_id, const char* passwd) : m_uid(user_id)
180 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == (temp = ckmc_unlock_user_key(user_id, passwd)), CKMCErrorToString(temp));
182 ScopedDBUnlock::~ScopedDBUnlock()
185 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == (temp = ckmc_lock_user_key(m_uid)), CKMCErrorToString(temp));
188 void check_remove_allowed(const char* alias)
190 int ret = ckmc_remove_alias(alias);
191 // remove, but ignore non existing
192 RUNNER_ASSERT_MSG((CKMC_ERROR_NONE == ret) || (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret),
193 "Removing data failed: " << CKMCErrorToString(ret));
196 void check_remove_denied(const char* alias)
198 int ret = ckmc_remove_alias(alias);
200 CKMC_ERROR_PERMISSION_DENIED == ret,
201 "App with different label shouldn't have rights to remove this data. "
202 << CKMCReadableError(ret));
205 void check_remove_not_visible(const char* alias)
207 int ret = ckmc_remove_alias(alias);
209 CKMC_ERROR_DB_ALIAS_UNKNOWN == ret,
210 "App with different label shouldn't have rights to see this data. "
211 << CKMCReadableError(ret));
214 void check_read(const char* alias,
216 const char *test_data,
220 ckmc_raw_buffer_s* buffer = NULL;
221 int ret = ckmc_get_data(aliasWithLabel(label, alias).c_str(), NULL, &buffer);
222 RUNNER_ASSERT_MSG(expected_code == ret, "Getting data failed. "
223 "Expected " << CKMCErrorToString(expected_code) << ", "
224 "while result " << CKMCErrorToString(ret));
226 if(expected_code == CKMC_ERROR_NONE)
228 // compare data with expected
231 "Extracted data length do not match expected data length (encrypted?):" <<
232 buffer->size << "!=" << len);
235 memcmp(const_cast<const char*>(reinterpret_cast<char*>(buffer->data)),
236 test_data, buffer->size) == 0,
237 "Extracted data do not match expected data (encrypted?).");
239 ckmc_buffer_free(buffer);
243 void check_read(const char* alias, const char *label, const char *test_data, int expected_code)
245 check_read(alias, label, test_data, strlen(test_data), expected_code);
248 void check_read_allowed(const char* alias, const char *data)
250 // try to read previously saved data - label taken implicitly
251 check_read(alias, NULL, data);
254 void check_read_not_visible(const char* alias)
256 // try to read previously saved data - label taken implicitly
258 ckmc_raw_buffer_s* buffer = NULL;
259 int ret = ckmc_get_data(alias, NULL, &buffer);
260 RUNNER_ASSERT_MSG(CKMC_ERROR_DB_ALIAS_UNKNOWN == ret,
261 "App with different label shouldn't have rights to see this data. " << CKMCErrorToString(ret));
262 ckmc_buffer_free(buffer);
266 void check_key(const char *alias, int expected_error, ckmc_key_type_e expected_type)
268 ckmc_key_s *test_key = NULL;
269 int temp = ckmc_get_key(alias, 0, &test_key);
271 expected_error == temp,
272 "received: " << CKMCReadableError(temp) << " while expected: " << CKMCReadableError(expected_error));
273 if(expected_type != CKMC_KEY_NONE)
276 test_key->key_type == expected_type,
277 "received type: " << test_key->key_type << " while expected type: " << expected_type);
279 ckmc_key_free(test_key);
281 void check_key_allowed(const char *alias, ckmc_key_type_e expected_type)
283 check_key(alias, CKMC_ERROR_NONE, expected_type);
285 void check_key_not_visible(const char *alias)
287 check_key(alias, CKMC_ERROR_DB_ALIAS_UNKNOWN);
289 void check_cert_allowed(const char *alias)
291 ckmc_cert_s *test_cert = NULL;
292 int temp = ckmc_get_cert(alias, 0, &test_cert);
293 ckmc_cert_free(test_cert);
294 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == temp, CKMCReadableError(temp));
297 void check_cert_not_visible(const char *alias)
299 ckmc_cert_s *test_cert = NULL;
300 int temp = ckmc_get_cert(alias, 0, &test_cert);
301 ckmc_cert_free(test_cert);
302 RUNNER_ASSERT_MSG(CKMC_ERROR_DB_ALIAS_UNKNOWN == temp,
303 "App with different label shouldn't have rights to see this cert. " << CKMCErrorToString(temp));
306 void allow_access(const char* alias, const char* accessor, int permissionMask)
308 // data removal should revoke this access
309 int ret = ckmc_set_permission(alias, accessor, permissionMask);
310 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == ret, "Trying to allow access returned: "
311 << CKMCErrorToString(ret));
314 void allow_access_negative(const char* alias, const char* accessor, int permissionMask, int expectedCode)
316 // data removal should revoke this access
317 int ret = ckmc_set_permission(alias, accessor, permissionMask);
318 RUNNER_ASSERT_MSG(expectedCode == ret, "Trying to allow access returned "
319 << CKMCErrorToString(ret) << ", while expected: "
320 << CKMCErrorToString(expectedCode));
323 void deny_access(const char* alias, const char* accessor)
325 int ret = ckmc_set_permission(alias, accessor, CKMC_PERMISSION_NONE);
326 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == ret, "Denying access failed. Error: "
327 << CKMCErrorToString(ret));
330 void deny_access_negative(const char* alias, const char* accessor, int expectedCode)
332 int ret = ckmc_set_permission(alias, accessor, CKMC_PERMISSION_NONE);
333 RUNNER_ASSERT_MSG(expectedCode == ret, "Denying access failed. "
334 << CKMCErrorToString(ret) << ", while expected: "
335 << CKMCErrorToString(expectedCode));
338 void unlock_user_data(uid_t user_id, const char *passwd)
341 auto control = CKM::Control::create();
342 RUNNER_ASSERT_MSG(CKM_API_SUCCESS == (ret = control->unlockUserKey(user_id, passwd)),
343 "Error=" << CKM::APICodeToString(ret));
346 void remove_user_data(uid_t user_id)
348 auto control = CKM::Control::create();
349 control->lockUserKey(user_id);
350 control->removeUserData(user_id);
353 void reset_user_data(uid_t user_id, const char *passwd)
355 remove_user_data(user_id);
356 unlock_user_data(user_id, passwd);
359 ckmc_raw_buffer_s prepare_message_buffer(const char * input)
361 ckmc_raw_buffer_s retval;
362 retval.data = const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(input));
363 retval.size = strlen(input);
367 void check_alias_list(const CKM::AliasVector& expected)
369 ckmc_alias_list_s *aliasList = NULL;
370 int ret = ckmc_get_data_alias_list(&aliasList);
371 RUNNER_ASSERT_MSG(ret == 0, "Failed to get the list of data aliases. " << ret << " / " << CKMCErrorToString(ret));
373 CKM::AliasVector actual;
374 ckmc_alias_list_s *plist = aliasList;
377 actual.push_back(plist->alias);
380 ckmc_alias_list_all_free(aliasList);
382 RUNNER_ASSERT_MSG(expected == actual, "Actual list of aliases differ from expected list.");
385 void check_alias_info_list_helper(const CKM::AliasPwdVector& expected, const CKM::AliasPwdVector& actual,
386 const std::string &userSmackLabel)
388 std::string errorLogMsg;
389 std::unordered_map<std::string, bool> aliasPwdMap;
391 RUNNER_ASSERT_MSG(expected.size() == actual.size(), "Aliases item count differs, expected: " <<
392 expected.size() << " actual: " << actual.size());
394 for (const auto &it : actual)
396 aliasPwdMap[std::get<0>(it)] = std::get<1>(it);
400 for (const auto &it : expected)
402 auto aliasPwd = aliasPwdMap.find(userSmackLabel + std::get<0>(it));
403 if (aliasPwd != aliasPwdMap.end()) {
404 if (aliasPwd->second != std::get<1>(it)) {
405 errorLogMsg += "Alias: " + std::get<0>(it) + " has wrong encryption status: "
406 + std::to_string(std::get<1>(it)) + "\n";
410 errorLogMsg += "Expected alias: " + std::get<0>(it) + " not found.\n";
414 if (!errorLogMsg.empty()) {
415 for (const auto &it : actual)
417 errorLogMsg += "Actual alias: " + std::get<0>(it) + " status: "
418 + std::to_string(std::get<1>(it)) + "\n";
420 RUNNER_FAIL_MSG("Actual list of aliases differ from expected list.\n" + errorLogMsg);
424 void check_alias_info_list(const CKM::AliasPwdVector& expected)
426 ckmc_alias_info_list_s *aliasInfoList = NULL;
427 int ret = ckmc_get_data_alias_info_list(&aliasInfoList);
428 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get the list of data aliases. " << ret << " / "
429 << CKMCErrorToString(ret));
431 CKM::AliasPwdVector actual;
432 ckmc_alias_info_list_s *plist = aliasInfoList;
434 bool isPasswordProtected;
438 ret = ckmc_alias_info_get_alias(plist->info, &alias);
439 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get alias. " << ret << " / "
440 << CKMCErrorToString(ret));
441 ret = ckmc_alias_info_is_password_protected(plist->info, &isPasswordProtected);
442 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get password protection status" << ret << " / "
443 << CKMCErrorToString(ret));
444 RUNNER_ASSERT_MSG(alias != nullptr, "Got null alias. Iterator: " << it);
445 actual.push_back(std::make_pair(alias, isPasswordProtected));
449 ckmc_alias_info_list_all_free(aliasInfoList);
450 check_alias_info_list_helper(expected, actual);
453 size_t count_aliases(alias_type_ type, size_t minimum_initial_element_count)
455 ckmc_alias_list_s *aliasList = NULL;
460 ec = ckmc_get_key_alias_list(&aliasList);
464 ec = ckmc_get_cert_alias_list(&aliasList);
468 ec = ckmc_get_data_alias_list(&aliasList);
471 RUNNER_ASSERT_MSG(false, "Unsupported value ALIAS_KEY == " << (int)type);
474 if(ec == CKMC_ERROR_DB_ALIAS_UNKNOWN)
477 RUNNER_ASSERT_MSG(ec == CKMC_ERROR_NONE,
478 "Error: alias list failed, ec: " << CKMCErrorToString(ec));
480 ckmc_alias_list_s *plist = aliasList;
481 size_t return_count = 0;
487 ckmc_alias_list_all_free(aliasList);
490 return_count >= minimum_initial_element_count,
491 "Error: alias list failed, current element count: " << return_count <<
492 " while expected minimal count of " << minimum_initial_element_count <<
498 std::string sharedDatabase(const CKM::Alias & alias)
500 return aliasWithLabel(ckmc_owner_id_system, alias.c_str());
503 ckmc_raw_buffer_s* createRandomBufferCAPI(size_t random_bytes)
505 ckmc_raw_buffer_s* buffer = NULL;
506 char* data = static_cast<char*>(malloc(random_bytes*sizeof(char)));
508 generate_random(random_bytes, data);
509 int ret = ckmc_buffer_new(reinterpret_cast<unsigned char*>(data), random_bytes, &buffer);
510 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Buffer creation failed: " << CKMCErrorToString(ret));
514 CKM::RawBuffer createRandomBuffer(size_t random_bytes)
516 char buffer[random_bytes];
517 generate_random(random_bytes, buffer);
518 return CKM::RawBuffer(buffer, buffer + random_bytes);
521 ckmc_key_s *generate_AES_key(size_t lengthBits, const char *passwd)
523 ckmc_key_s *retval = reinterpret_cast<ckmc_key_s *>(malloc(sizeof(ckmc_key_s)));
524 RUNNER_ASSERT(retval != NULL);
526 RUNNER_ASSERT(lengthBits%8 == 0);
527 char *char_key_AES = reinterpret_cast<char*>(malloc(lengthBits/8));
528 RUNNER_ASSERT(char_key_AES != NULL);
529 generate_random(lengthBits/8, char_key_AES);
531 retval->raw_key = reinterpret_cast<unsigned char *>(char_key_AES);
532 retval->key_size = lengthBits/8;
533 retval->key_type = CKMC_KEY_AES;
534 retval->password = passwd?strdup(passwd):NULL;
539 void validate_AES_key(ckmc_key_s *analyzed)
541 RUNNER_ASSERT_MSG(analyzed, "provided key is NULL");
542 RUNNER_ASSERT_MSG(analyzed->raw_key != NULL, "provided key is empty");
543 RUNNER_ASSERT_MSG(analyzed->key_size==(128/8) ||
544 analyzed->key_size==(192/8) ||
545 analyzed->key_size==(256/8), "provided key length is invalid");
546 RUNNER_ASSERT_MSG(analyzed->key_type = CKMC_KEY_AES, "expected AES key, while got: " << analyzed->key_type);
549 void compare_AES_keys(ckmc_key_s *first, ckmc_key_s *second)
551 validate_AES_key(first);
552 validate_AES_key(second);
554 (first->key_size==second->key_size) &&
555 (memcmp(first->raw_key, second->raw_key, first->key_size)==0),
556 "data has been modified in key manager");
557 // bypassing password intentionally
560 ParamListPtr createParamListPtr()
562 ckmc_param_list_h list = NULL;
563 assert_positive(ckmc_param_list_new, &list);
564 return ParamListPtr(list, ckmc_param_list_free);
567 void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
569 int ret = ckmc_param_list_set_buffer(params.get(), name, buffer);
570 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
571 "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
574 void setParam(ParamListPtr& params, ckmc_param_name_e name, uint64_t integer)
576 int ret = ckmc_param_list_set_integer(params.get(), name, integer);
577 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
578 "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
581 void assert_buffers_equal(const ckmc_raw_buffer_s* b1, const ckmc_raw_buffer_s* b2, bool equal)
584 RUNNER_ASSERT_MSG(b1->size == b2->size,
585 "Buffer size differs: " << b1->size << "!=" << b2->size);
586 RUNNER_ASSERT_MSG(0 == memcmp(b1->data, b2->data, b1->size), "Buffer contents differ");
588 RUNNER_ASSERT_MSG(b1->size != b2->size || 0 != memcmp(b1->data, b2->data, b1->size),
589 "Buffers should be different");
593 RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer)
595 return RawBufferPtr(buffer, ckmc_buffer_free);
598 CKM::Policy generate_ckm_policy(int iterator_nr) {
599 if (iterator_nr % 2) { // policy with password and with / without extractable flag
600 return CKM::Policy(CKM::Password("test_pwd"), iterator_nr % 4);
602 return CKM::Policy();