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/types.h>
27 #include <sys/smack.h>
28 #include <ckm/ckm-type.h>
29 #include <ckmc/ckmc-type.h>
30 #include <ckm-common.h>
31 #include <tests_common.h>
32 #include <ckm/ckm-control.h>
33 #include <ckm/ckm-manager.h>
34 #include <ckmc/ckmc-control.h>
35 #include <ckmc/ckmc-manager.h>
38 #include <unordered_map>
39 #include <tzplatform_config.h>
41 const std::string SMACK_USER_APP_PREFIX = "User::Pkg::";
42 const char *SYSTEM_LABEL = ckmc_owner_id_system;
43 const char *TEST_LABEL = "test_label";
44 const char *TEST_LABEL_2 = "test_label_2";
45 const char *TEST_LABEL_3 = "test_label_3";
46 const char *TEST_LABEL_4 = "test_label_4";
47 const char *TEST_LABEL_5 = "test_label_5";
49 void generate_random(size_t random_bytes, char *output)
51 RUNNER_ASSERT(random_bytes>0 && output);
53 std::ifstream is("/dev/urandom", std::ifstream::binary);
54 RUNNER_ASSERT_MSG(is, "Failed to read /dev/urandom");
55 is.read(output, random_bytes);
56 if(static_cast<std::streamsize>(random_bytes) != is.gcount()) {
57 RUNNER_ASSERT_MSG(false,
58 "Not enough bytes read from /dev/urandom: " << random_bytes << "!=" <<
63 std::string getLabel() {
66 RUNNER_ASSERT_MSG(0 <= (ret = smack_new_label_from_self(&myLabel)),
67 "Failed to get smack label for self. Error: " << ret);
68 RUNNER_ASSERT_MSG(myLabel, "NULL smack label");
69 std::string result = myLabel;
74 std::string getOwnerIdFromSelf() {
75 const std::string& prefix = SMACK_USER_APP_PREFIX;
76 std::string smack = getLabel();
77 if (0 == smack.compare(0, prefix.size(), prefix))
78 return smack.substr(prefix.size(), std::string::npos);
82 std::string aliasWithLabel(const char *label, const char *alias)
87 ss << label << std::string(ckmc_label_name_separator) << alias;
90 return std::string(alias);
93 std::string aliasWithLabelFromSelf(const char *alias)
95 std::ostringstream oss;
96 oss << getOwnerIdFromSelf() << ckmc_label_name_separator << alias;
101 #define ERRORDESCRIBE(name) case name: return #name
102 const char * CKMCErrorToString(int error) {
104 ERRORDESCRIBE(CKMC_ERROR_NONE);
105 ERRORDESCRIBE(CKMC_ERROR_INVALID_PARAMETER);
106 ERRORDESCRIBE(CKMC_ERROR_OUT_OF_MEMORY);
107 ERRORDESCRIBE(CKMC_ERROR_PERMISSION_DENIED);
108 ERRORDESCRIBE(CKMC_ERROR_SOCKET);
109 ERRORDESCRIBE(CKMC_ERROR_BAD_REQUEST);
110 ERRORDESCRIBE(CKMC_ERROR_BAD_RESPONSE);
111 ERRORDESCRIBE(CKMC_ERROR_SEND_FAILED);
112 ERRORDESCRIBE(CKMC_ERROR_RECV_FAILED);
113 ERRORDESCRIBE(CKMC_ERROR_AUTHENTICATION_FAILED);
114 ERRORDESCRIBE(CKMC_ERROR_BUFFER_TOO_SMALL);
115 ERRORDESCRIBE(CKMC_ERROR_SERVER_ERROR);
116 ERRORDESCRIBE(CKMC_ERROR_DB_LOCKED);
117 ERRORDESCRIBE(CKMC_ERROR_DB_ERROR);
118 ERRORDESCRIBE(CKMC_ERROR_DB_ALIAS_EXISTS);
119 ERRORDESCRIBE(CKMC_ERROR_DB_ALIAS_UNKNOWN);
120 ERRORDESCRIBE(CKMC_ERROR_VERIFICATION_FAILED);
121 ERRORDESCRIBE(CKMC_ERROR_INVALID_FORMAT);
122 ERRORDESCRIBE(CKMC_ERROR_FILE_ACCESS_DENIED);
123 ERRORDESCRIBE(CKMC_ERROR_NOT_EXPORTABLE);
124 ERRORDESCRIBE(CKMC_ERROR_FILE_SYSTEM);
125 ERRORDESCRIBE(CKMC_ERROR_NOT_SUPPORTED);
126 ERRORDESCRIBE(CKMC_ERROR_UNKNOWN);
127 default: return "Error not defined";
132 std::string CKMCReadableError(int error) {
133 std::string output("Error: ");
134 output += std::to_string(error);
135 output += " Description: ";
136 output += CKMCErrorToString(error);
140 void save_data(const char* alias, const char *data, size_t len, const char* password,
141 int expected_err, bool exportable)
143 RUNNER_ASSERT(alias);
146 ckmc_raw_buffer_s buffer;
147 buffer.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
149 ckmc_policy_s policy;
150 policy.password = const_cast<char*>(password);
151 policy.extractable = exportable;
152 int ret = ckmc_save_data(alias, buffer, policy);
153 RUNNER_ASSERT_MSG(expected_err == ret, "Saving data failed. "
154 << CKMCErrorToString(ret) << " while expected: "
155 << CKMCErrorToString(expected_err));
158 void save_data(const char* alias, const char *data, int expected_err, bool exportable)
160 save_data(alias, data, strlen(data), nullptr, expected_err, exportable);
163 void save_data(const char* alias, const char *data, size_t len, int expected_err, bool exportable)
165 save_data(alias, data, len, nullptr, expected_err, exportable);
168 ScopedSaveData::ScopedSaveData(const char* alias, const char *data, int expected_err) : m_alias(alias)
170 save_data(alias, data, expected_err);
173 ScopedSaveData::~ScopedSaveData()
176 * Let it throw. If we can't remove data then remaining tests results will be
179 check_remove_allowed(m_alias.c_str());
182 ScopedDBUnlock::ScopedDBUnlock(uid_t user_id, const char* passwd) : m_uid(user_id)
185 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == (temp = ckmc_unlock_user_key(user_id, passwd)), CKMCErrorToString(temp));
187 ScopedDBUnlock::~ScopedDBUnlock()
190 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == (temp = ckmc_lock_user_key(m_uid)), CKMCErrorToString(temp));
193 void check_remove_allowed(const char* alias)
195 int ret = ckmc_remove_alias(alias);
196 // remove, but ignore non existing
197 RUNNER_ASSERT_MSG((CKMC_ERROR_NONE == ret) || (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret),
198 "Removing data failed: " << CKMCErrorToString(ret));
201 void check_remove_denied(const char* alias)
203 int ret = ckmc_remove_alias(alias);
205 CKMC_ERROR_PERMISSION_DENIED == ret,
206 "App with different label shouldn't have rights to remove this data. "
207 << CKMCReadableError(ret));
210 void check_remove_not_visible(const char* alias)
212 int ret = ckmc_remove_alias(alias);
214 CKMC_ERROR_DB_ALIAS_UNKNOWN == ret,
215 "App with different label shouldn't have rights to see this data. "
216 << CKMCReadableError(ret));
219 void check_read(const char* alias,
221 const char *test_data,
225 ckmc_raw_buffer_s* buffer = NULL;
226 int ret = ckmc_get_data(aliasWithLabel(label, alias).c_str(), NULL, &buffer);
227 RUNNER_ASSERT_MSG(expected_code == ret, "Getting data failed. "
228 "Expected " << CKMCErrorToString(expected_code) << ", "
229 "while result " << CKMCErrorToString(ret));
231 if(expected_code == CKMC_ERROR_NONE)
233 // compare data with expected
236 "Extracted data length do not match expected data length (encrypted?):" <<
237 buffer->size << "!=" << len);
240 memcmp(const_cast<const char*>(reinterpret_cast<char*>(buffer->data)),
241 test_data, buffer->size) == 0,
242 "Extracted data do not match expected data (encrypted?).");
244 ckmc_buffer_free(buffer);
248 void check_read(const char* alias, const char *label, const char *test_data, int expected_code)
250 check_read(alias, label, test_data, strlen(test_data), expected_code);
253 void check_read_allowed(const char* alias, const char *data)
255 // try to read previously saved data - label taken implicitly
256 check_read(alias, NULL, data);
259 void check_read_not_visible(const char* alias)
261 // try to read previously saved data - label taken implicitly
263 ckmc_raw_buffer_s* buffer = NULL;
264 int ret = ckmc_get_data(alias, NULL, &buffer);
265 RUNNER_ASSERT_MSG(CKMC_ERROR_DB_ALIAS_UNKNOWN == ret,
266 "App with different label shouldn't have rights to see this data. " << CKMCErrorToString(ret));
267 ckmc_buffer_free(buffer);
271 void check_key(const char *alias, int expected_error, ckmc_key_type_e expected_type)
273 ckmc_key_s *test_key = NULL;
274 int temp = ckmc_get_key(alias, 0, &test_key);
276 expected_error == temp,
277 "received: " << CKMCReadableError(temp) << " while expected: " << CKMCReadableError(expected_error));
278 if(expected_type != CKMC_KEY_NONE)
281 test_key->key_type == expected_type,
282 "received type: " << test_key->key_type << " while expected type: " << expected_type);
284 ckmc_key_free(test_key);
286 void check_key_allowed(const char *alias, ckmc_key_type_e expected_type)
288 check_key(alias, CKMC_ERROR_NONE, expected_type);
290 void check_key_not_visible(const char *alias)
292 check_key(alias, CKMC_ERROR_DB_ALIAS_UNKNOWN);
294 void check_cert_allowed(const char *alias)
296 ckmc_cert_s *test_cert = NULL;
297 int temp = ckmc_get_cert(alias, 0, &test_cert);
298 ckmc_cert_free(test_cert);
299 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == temp, CKMCReadableError(temp));
302 void check_cert_not_visible(const char *alias)
304 ckmc_cert_s *test_cert = NULL;
305 int temp = ckmc_get_cert(alias, 0, &test_cert);
306 ckmc_cert_free(test_cert);
307 RUNNER_ASSERT_MSG(CKMC_ERROR_DB_ALIAS_UNKNOWN == temp,
308 "App with different label shouldn't have rights to see this cert. " << CKMCErrorToString(temp));
311 void allow_access(const char* alias, const char* accessor, int permissionMask)
313 // data removal should revoke this access
314 int ret = ckmc_set_permission(alias, accessor, permissionMask);
315 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == ret, "Trying to allow access returned: "
316 << CKMCErrorToString(ret));
319 void allow_access_negative(const char* alias, const char* accessor, int permissionMask, int expectedCode)
321 // data removal should revoke this access
322 int ret = ckmc_set_permission(alias, accessor, permissionMask);
323 RUNNER_ASSERT_MSG(expectedCode == ret, "Trying to allow access returned "
324 << CKMCErrorToString(ret) << ", while expected: "
325 << CKMCErrorToString(expectedCode));
328 void deny_access(const char* alias, const char* accessor)
330 int ret = ckmc_set_permission(alias, accessor, CKMC_PERMISSION_NONE);
331 RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == ret, "Denying access failed. Error: "
332 << CKMCErrorToString(ret));
335 void deny_access_negative(const char* alias, const char* accessor, int expectedCode)
337 int ret = ckmc_set_permission(alias, accessor, CKMC_PERMISSION_NONE);
338 RUNNER_ASSERT_MSG(expectedCode == ret, "Denying access failed. "
339 << CKMCErrorToString(ret) << ", while expected: "
340 << CKMCErrorToString(expectedCode));
343 void unlock_user_data(uid_t user_id, const char *passwd)
346 auto control = CKM::Control::create();
347 RUNNER_ASSERT_MSG(CKM_API_SUCCESS == (ret = control->unlockUserKey(user_id, passwd)),
348 "Error=" << CKM::APICodeToString(ret));
351 void remove_user_data(uid_t user_id)
353 auto control = CKM::Control::create();
354 control->lockUserKey(user_id);
355 control->removeUserData(user_id);
358 void reset_user_data(uid_t user_id, const char *passwd)
360 remove_user_data(user_id);
361 unlock_user_data(user_id, passwd);
364 ckmc_raw_buffer_s prepare_message_buffer(const char * input)
366 ckmc_raw_buffer_s retval;
367 retval.data = const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(input));
368 retval.size = strlen(input);
372 void check_alias_list(const CKM::AliasVector& expected)
374 ckmc_alias_list_s *aliasList = NULL;
375 int ret = ckmc_get_data_alias_list(&aliasList);
376 RUNNER_ASSERT_MSG(ret == 0, "Failed to get the list of data aliases. " << ret << " / " << CKMCErrorToString(ret));
378 CKM::AliasVector actual;
379 ckmc_alias_list_s *plist = aliasList;
382 actual.push_back(plist->alias);
385 ckmc_alias_list_all_free(aliasList);
387 RUNNER_ASSERT_MSG(expected == actual, "Actual list of aliases differ from expected list.");
390 void check_alias_info_list_helper(const CKM::AliasPwdVector& expected, const CKM::AliasPwdVector& actual,
391 const std::string &userSmackLabel)
393 std::string errorLogMsg;
394 std::unordered_map<std::string, bool> aliasPwdMap;
396 RUNNER_ASSERT_MSG(expected.size() == actual.size(), "Aliases item count differs, expected: " <<
397 expected.size() << " actual: " << actual.size());
399 for (const auto &it : actual)
401 aliasPwdMap[std::get<0>(it)] = std::get<1>(it);
405 for (const auto &it : expected)
407 auto aliasPwd = aliasPwdMap.find(userSmackLabel + std::get<0>(it));
408 if (aliasPwd != aliasPwdMap.end()) {
409 if (aliasPwd->second != std::get<1>(it)) {
410 errorLogMsg += "Alias: " + std::get<0>(it) + " has wrong encryption status: "
411 + std::to_string(std::get<1>(it)) + "\n";
415 errorLogMsg += "Expected alias: " + std::get<0>(it) + " not found.\n";
419 if (!errorLogMsg.empty()) {
420 for (const auto &it : actual)
422 errorLogMsg += "Actual alias: " + std::get<0>(it) + " status: "
423 + std::to_string(std::get<1>(it)) + "\n";
425 RUNNER_FAIL_MSG("Actual list of aliases differ from expected list.\n" + errorLogMsg);
429 void check_alias_info_list(const CKM::AliasPwdVector& expected)
431 ckmc_alias_info_list_s *aliasInfoList = NULL;
432 int ret = ckmc_get_data_alias_info_list(&aliasInfoList);
433 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get the list of data aliases. " << ret << " / "
434 << CKMCErrorToString(ret));
436 CKM::AliasPwdVector actual;
437 ckmc_alias_info_list_s *plist = aliasInfoList;
439 bool isPasswordProtected;
443 ret = ckmc_alias_info_get_alias(plist->info, &alias);
444 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get alias. " << ret << " / "
445 << CKMCErrorToString(ret));
446 ret = ckmc_alias_info_is_password_protected(plist->info, &isPasswordProtected);
447 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get password protection status" << ret << " / "
448 << CKMCErrorToString(ret));
449 RUNNER_ASSERT_MSG(alias != nullptr, "Got null alias. Iterator: " << it);
450 actual.push_back(std::make_pair(alias, isPasswordProtected));
454 ckmc_alias_info_list_all_free(aliasInfoList);
455 check_alias_info_list_helper(expected, actual);
458 size_t count_aliases(alias_type_ type, size_t minimum_initial_element_count)
460 ckmc_alias_list_s *aliasList = NULL;
465 ec = ckmc_get_key_alias_list(&aliasList);
469 ec = ckmc_get_cert_alias_list(&aliasList);
473 ec = ckmc_get_data_alias_list(&aliasList);
476 RUNNER_ASSERT_MSG(false, "Unsupported value ALIAS_KEY == " << (int)type);
479 if(ec == CKMC_ERROR_DB_ALIAS_UNKNOWN)
482 RUNNER_ASSERT_MSG(ec == CKMC_ERROR_NONE,
483 "Error: alias list failed, ec: " << CKMCErrorToString(ec));
485 ckmc_alias_list_s *plist = aliasList;
486 size_t return_count = 0;
492 ckmc_alias_list_all_free(aliasList);
495 return_count >= minimum_initial_element_count,
496 "Error: alias list failed, current element count: " << return_count <<
497 " while expected minimal count of " << minimum_initial_element_count <<
503 std::string sharedDatabase(const CKM::Alias & alias)
505 return aliasWithLabel(ckmc_owner_id_system, alias.c_str());
508 ckmc_raw_buffer_s* createRandomBufferCAPI(size_t random_bytes)
510 ckmc_raw_buffer_s* buffer = NULL;
511 char* data = static_cast<char*>(malloc(random_bytes*sizeof(char)));
513 generate_random(random_bytes, data);
514 int ret = ckmc_buffer_new(reinterpret_cast<unsigned char*>(data), random_bytes, &buffer);
515 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Buffer creation failed: " << CKMCErrorToString(ret));
519 CKM::RawBuffer createRandomBuffer(size_t random_bytes)
521 char buffer[random_bytes];
522 generate_random(random_bytes, buffer);
523 return CKM::RawBuffer(buffer, buffer + random_bytes);
526 ckmc_key_s *generate_AES_key(size_t lengthBits, const char *passwd)
528 ckmc_key_s *retval = reinterpret_cast<ckmc_key_s *>(malloc(sizeof(ckmc_key_s)));
529 RUNNER_ASSERT(retval != NULL);
531 RUNNER_ASSERT(lengthBits%8 == 0);
532 char *char_key_AES = reinterpret_cast<char*>(malloc(lengthBits/8));
533 RUNNER_ASSERT(char_key_AES != NULL);
534 generate_random(lengthBits/8, char_key_AES);
536 retval->raw_key = reinterpret_cast<unsigned char *>(char_key_AES);
537 retval->key_size = lengthBits/8;
538 retval->key_type = CKMC_KEY_AES;
539 retval->password = passwd?strdup(passwd):NULL;
544 void validate_AES_key(ckmc_key_s *analyzed)
546 RUNNER_ASSERT_MSG(analyzed, "provided key is NULL");
547 RUNNER_ASSERT_MSG(analyzed->raw_key != NULL, "provided key is empty");
548 RUNNER_ASSERT_MSG(analyzed->key_size==(128/8) ||
549 analyzed->key_size==(192/8) ||
550 analyzed->key_size==(256/8), "provided key length is invalid");
551 RUNNER_ASSERT_MSG(analyzed->key_type = CKMC_KEY_AES, "expected AES key, while got: " << analyzed->key_type);
554 void compare_AES_keys(ckmc_key_s *first, ckmc_key_s *second)
556 validate_AES_key(first);
557 validate_AES_key(second);
559 (first->key_size==second->key_size) &&
560 (memcmp(first->raw_key, second->raw_key, first->key_size)==0),
561 "data has been modified in key manager");
562 // bypassing password intentionally
565 ParamListPtr createParamListPtr()
567 ckmc_param_list_h list = NULL;
568 assert_positive(ckmc_param_list_new, &list);
569 return ParamListPtr(list, ckmc_param_list_free);
572 void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
574 int ret = ckmc_param_list_set_buffer(params.get(), name, buffer);
575 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
576 "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
579 void setParam(ParamListPtr& params, ckmc_param_name_e name, uint64_t integer)
581 int ret = ckmc_param_list_set_integer(params.get(), name, integer);
582 RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
583 "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
586 void assert_buffers_equal(const ckmc_raw_buffer_s* b1, const ckmc_raw_buffer_s* b2, bool equal)
589 RUNNER_ASSERT_MSG(b1->size == b2->size,
590 "Buffer size differs: " << b1->size << "!=" << b2->size);
591 RUNNER_ASSERT_MSG(0 == memcmp(b1->data, b2->data, b1->size), "Buffer contents differ");
593 RUNNER_ASSERT_MSG(b1->size != b2->size || 0 != memcmp(b1->data, b2->data, b1->size),
594 "Buffers should be different");
598 RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer)
600 return RawBufferPtr(buffer, ckmc_buffer_free);
603 CKM::Policy generate_ckm_policy(int iterator_nr) {
604 if (iterator_nr % 2) { // policy with password and with / without extractable flag
605 return CKM::Policy(CKM::Password("test_pwd"), iterator_nr % 4);
607 return CKM::Policy();
610 void require_default_user(char *argv[])
612 uid_t expected_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
613 if (expected_uid != geteuid()) {
614 std::string userStr("owner");
615 const char* user = tzplatform_getenv(TZ_SYS_DEFAULT_USER);
619 std::cerr << argv[0] << " should be executed as " << userStr << ". Aborting" << std::endl;