Merge remote-tracking branch 'origin/tizen' into ode
[platform/core/test/security-tests.git] / src / ckm / ckm-common.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 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       ckm-common.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21 #include <string>
22 #include <fstream>
23 #include <sys/smack.h>
24 #include <ckmc/ckmc-type.h>
25 #include <ckm-common.h>
26 #include <tests_common.h>
27 #include <ckm/ckm-control.h>
28 #include <ckm/ckm-manager.h>
29 #include <ckmc/ckmc-control.h>
30 #include <ckmc/ckmc-manager.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 const std::string SMACK_USER_APP_PREFIX = "User::Pkg::";
35 const char *SYSTEM_LABEL = ckmc_owner_id_system;
36 const char *TEST_LABEL = "test_label";
37 const char *TEST_LABEL_2 = "test_label_2";
38 const char *TEST_LABEL_3 = "test_label_3";
39 const char *TEST_LABEL_4 = "test_label_4";
40 const char *TEST_LABEL_5 = "test_label_5";
41
42 void generate_random(size_t random_bytes, char *output)
43 {
44     RUNNER_ASSERT(random_bytes>0 && output);
45
46     std::ifstream is("/dev/urandom", std::ifstream::binary);
47     RUNNER_ASSERT_MSG(is, "Failed to read /dev/urandom");
48     is.read(output, random_bytes);
49     if(static_cast<std::streamsize>(random_bytes) != is.gcount()) {
50         RUNNER_ASSERT_MSG(false,
51                           "Not enough bytes read from /dev/urandom: " << random_bytes << "!=" <<
52                           is.gcount());
53     }
54 }
55
56 std::string getLabel() {
57     int ret;
58     char* myLabel = NULL;
59     RUNNER_ASSERT_MSG(0 <= (ret = smack_new_label_from_self(&myLabel)),
60                          "Failed to get smack label for self. Error: " << ret);
61     RUNNER_ASSERT_MSG(myLabel, "NULL smack label");
62     std::string result = myLabel;
63     free(myLabel);
64     return result;
65 }
66
67 std::string getOwnerIdFromSelf() {
68     const std::string& prefix = SMACK_USER_APP_PREFIX;
69     std::string smack = getLabel();
70     if (0 == smack.compare(0, prefix.size(), prefix))
71         return smack.substr(prefix.size(), std::string::npos);
72     return "/" + smack;
73 }
74
75 std::string aliasWithLabel(const char *label, const char *alias)
76 {
77     if(label)
78     {
79         std::stringstream ss;
80         ss << label << std::string(ckmc_label_name_separator) << alias;
81         return ss.str();
82     }
83     return std::string(alias);
84 }
85
86 std::string aliasWithLabelFromSelf(const char *alias)
87 {
88     std::ostringstream oss;
89     oss << getOwnerIdFromSelf() << ckmc_label_name_separator << alias;
90
91     return oss.str();
92 }
93
94 #define ERRORDESCRIBE(name) case name: return #name
95 const char * CKMCErrorToString(int error) {
96     switch(error) {
97         ERRORDESCRIBE(CKMC_ERROR_NONE);
98         ERRORDESCRIBE(CKMC_ERROR_INVALID_PARAMETER);
99         ERRORDESCRIBE(CKMC_ERROR_OUT_OF_MEMORY);
100         ERRORDESCRIBE(CKMC_ERROR_PERMISSION_DENIED);
101         ERRORDESCRIBE(CKMC_ERROR_SOCKET);
102         ERRORDESCRIBE(CKMC_ERROR_BAD_REQUEST);
103         ERRORDESCRIBE(CKMC_ERROR_BAD_RESPONSE);
104         ERRORDESCRIBE(CKMC_ERROR_SEND_FAILED);
105         ERRORDESCRIBE(CKMC_ERROR_RECV_FAILED);
106         ERRORDESCRIBE(CKMC_ERROR_AUTHENTICATION_FAILED);
107         ERRORDESCRIBE(CKMC_ERROR_BUFFER_TOO_SMALL);
108         ERRORDESCRIBE(CKMC_ERROR_SERVER_ERROR);
109         ERRORDESCRIBE(CKMC_ERROR_DB_LOCKED);
110         ERRORDESCRIBE(CKMC_ERROR_DB_ERROR);
111         ERRORDESCRIBE(CKMC_ERROR_DB_ALIAS_EXISTS);
112         ERRORDESCRIBE(CKMC_ERROR_DB_ALIAS_UNKNOWN);
113         ERRORDESCRIBE(CKMC_ERROR_VERIFICATION_FAILED);
114         ERRORDESCRIBE(CKMC_ERROR_INVALID_FORMAT);
115         ERRORDESCRIBE(CKMC_ERROR_FILE_ACCESS_DENIED);
116         ERRORDESCRIBE(CKMC_ERROR_NOT_EXPORTABLE);
117         ERRORDESCRIBE(CKMC_ERROR_FILE_SYSTEM);
118         ERRORDESCRIBE(CKMC_ERROR_NOT_SUPPORTED);
119         ERRORDESCRIBE(CKMC_ERROR_UNKNOWN);
120         default: return "Error not defined";
121     }
122 }
123
124 const char * CKMErrorToString(int error) {
125     switch (error) {
126         ERRORDESCRIBE(CKM_API_SUCCESS);
127         ERRORDESCRIBE(CKM_API_ERROR_SOCKET);
128         ERRORDESCRIBE(CKM_API_ERROR_BAD_REQUEST);
129         ERRORDESCRIBE(CKM_API_ERROR_BAD_RESPONSE);
130         ERRORDESCRIBE(CKM_API_ERROR_SEND_FAILED);
131         ERRORDESCRIBE(CKM_API_ERROR_RECV_FAILED);
132         ERRORDESCRIBE(CKM_API_ERROR_AUTHENTICATION_FAILED);
133         ERRORDESCRIBE(CKM_API_ERROR_INPUT_PARAM);
134         ERRORDESCRIBE(CKM_API_ERROR_BUFFER_TOO_SMALL);
135         ERRORDESCRIBE(CKM_API_ERROR_OUT_OF_MEMORY);
136         ERRORDESCRIBE(CKM_API_ERROR_ACCESS_DENIED);
137         ERRORDESCRIBE(CKM_API_ERROR_SERVER_ERROR);
138         ERRORDESCRIBE(CKM_API_ERROR_DB_LOCKED);
139         ERRORDESCRIBE(CKM_API_ERROR_DB_ERROR);
140         ERRORDESCRIBE(CKM_API_ERROR_DB_ALIAS_EXISTS);
141         ERRORDESCRIBE(CKM_API_ERROR_DB_ALIAS_UNKNOWN);
142         ERRORDESCRIBE(CKM_API_ERROR_VERIFICATION_FAILED);
143         ERRORDESCRIBE(CKM_API_ERROR_INVALID_FORMAT);
144         ERRORDESCRIBE(CKM_API_ERROR_FILE_ACCESS_DENIED);
145         ERRORDESCRIBE(CKM_API_ERROR_NOT_EXPORTABLE);
146         ERRORDESCRIBE(CKM_API_ERROR_FILE_SYSTEM);
147         ERRORDESCRIBE(CKM_API_ERROR_NOT_SUPPORTED);
148         ERRORDESCRIBE(CKM_API_ERROR_UNKNOWN);
149         default: return "Error not defined";
150     }
151 }
152 #undef ERRORDESCRIBE
153
154 std::string CKMCReadableError(int error) {
155     std::string output("Error: ");
156     output += std::to_string(error);
157     output += " Description: ";
158     output += CKMCErrorToString(error);
159     return output;
160 }
161
162 void save_data(const char* alias, const char *data, int expected_err)
163 {
164     save_data(alias, data, strlen(data), expected_err);
165 }
166
167 void save_data(const char* alias, const char *data, size_t len, int expected_err = CKMC_ERROR_NONE)
168 {
169     RUNNER_ASSERT(alias);
170     RUNNER_ASSERT(data);
171
172     ckmc_raw_buffer_s buffer;
173     buffer.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
174     buffer.size = len;
175     ckmc_policy_s policy;
176     policy.password = NULL;
177     policy.extractable = true;
178
179     int ret = ckmc_save_data(alias, buffer, policy);
180     RUNNER_ASSERT_MSG(expected_err == ret, "Saving data failed. "
181                         << CKMCErrorToString(ret) << " while expected: "
182                         << CKMCErrorToString(expected_err));
183
184 }
185
186 ScopedSaveData::ScopedSaveData(const char* alias, const char *data, int expected_err) : m_alias(alias)
187 {
188     save_data(alias, data, expected_err);
189 }
190
191 ScopedSaveData::~ScopedSaveData()
192 {
193     /*
194      * Let it throw. If we can't remove data then remaining tests results will be
195      * unreliable anyway.
196      */
197     check_remove_allowed(m_alias.c_str());
198 }
199
200 ScopedDBUnlock::ScopedDBUnlock(uid_t user_id, const char* passwd) : m_uid(user_id)
201 {
202     int temp;
203     RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == (temp = ckmc_unlock_user_key(user_id, passwd)), CKMCErrorToString(temp));
204 }
205 ScopedDBUnlock::~ScopedDBUnlock()
206 {
207     int temp;
208     RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == (temp = ckmc_lock_user_key(m_uid)), CKMCErrorToString(temp));
209 }
210
211 void check_remove_allowed(const char* alias)
212 {
213     int ret = ckmc_remove_alias(alias);
214     // remove, but ignore non existing
215     RUNNER_ASSERT_MSG((CKMC_ERROR_NONE == ret) || (CKMC_ERROR_DB_ALIAS_UNKNOWN == ret),
216                          "Removing data failed: " << CKMCErrorToString(ret));
217 }
218
219 void check_remove_denied(const char* alias)
220 {
221     int ret = ckmc_remove_alias(alias);
222     RUNNER_ASSERT_MSG(
223             CKMC_ERROR_PERMISSION_DENIED == ret,
224             "App with different label shouldn't have rights to remove this data. "
225             << CKMCReadableError(ret));
226 }
227
228 void check_remove_not_visible(const char* alias)
229 {
230     int ret = ckmc_remove_alias(alias);
231     RUNNER_ASSERT_MSG(
232             CKMC_ERROR_DB_ALIAS_UNKNOWN == ret,
233             "App with different label shouldn't have rights to see this data. "
234             << CKMCReadableError(ret));
235 }
236
237 void check_read(const char* alias,
238                 const char *label,
239                 const char *test_data,
240                 size_t len,
241                 int expected_code)
242 {
243     ckmc_raw_buffer_s* buffer = NULL;
244     int ret = ckmc_get_data(aliasWithLabel(label, alias).c_str(), NULL, &buffer);
245     RUNNER_ASSERT_MSG(expected_code == ret, "Getting data failed. "
246                       "Expected " << CKMCErrorToString(expected_code) << ", "
247                       "while result " << CKMCErrorToString(ret));
248
249     if(expected_code == CKMC_ERROR_NONE)
250     {
251         // compare data with expected
252         RUNNER_ASSERT_MSG(
253                 buffer->size == len,
254                 "Extracted data length do not match expected data length (encrypted?):" <<
255                 buffer->size << "!=" << len);
256
257         RUNNER_ASSERT_MSG(
258                 memcmp(const_cast<const char*>(reinterpret_cast<char*>(buffer->data)),
259                        test_data, buffer->size) == 0,
260                 "Extracted data do not match expected data (encrypted?).");
261
262         ckmc_buffer_free(buffer);
263     }
264 }
265
266 void check_read(const char* alias, const char *label, const char *test_data, int expected_code)
267 {
268     check_read(alias, label, test_data, strlen(test_data), expected_code);
269 }
270
271 void check_read_allowed(const char* alias, const char *data)
272 {
273     // try to read previously saved data - label taken implicitly
274     check_read(alias, NULL, data);
275 }
276
277 void check_read_not_visible(const char* alias)
278 {
279     // try to read previously saved data - label taken implicitly
280     {
281         ckmc_raw_buffer_s* buffer = NULL;
282         int ret = ckmc_get_data(alias, NULL, &buffer);
283         RUNNER_ASSERT_MSG(CKMC_ERROR_DB_ALIAS_UNKNOWN == ret,
284                             "App with different label shouldn't have rights to see this data. " << CKMCErrorToString(ret));
285         ckmc_buffer_free(buffer);
286     }
287 }
288
289 void check_key(const char *alias, int expected_error, ckmc_key_type_e expected_type)
290 {
291     ckmc_key_s *test_key = NULL;
292     int temp = ckmc_get_key(alias, 0, &test_key);
293     RUNNER_ASSERT_MSG(
294             expected_error == temp,
295             "received: " << CKMCReadableError(temp) << " while expected: " << CKMCReadableError(expected_error));
296     if(expected_type != CKMC_KEY_NONE)
297     {
298         RUNNER_ASSERT_MSG(
299                 test_key->key_type == expected_type,
300                 "received type: " << test_key->key_type << " while expected type: " << expected_type);
301     }
302     ckmc_key_free(test_key);
303 }
304 void check_key_allowed(const char *alias, ckmc_key_type_e expected_type)
305 {
306     check_key(alias, CKMC_ERROR_NONE, expected_type);
307 }
308 void check_key_not_visible(const char *alias)
309 {
310     check_key(alias, CKMC_ERROR_DB_ALIAS_UNKNOWN);
311 }
312 void check_cert_allowed(const char *alias)
313 {
314     ckmc_cert_s *test_cert = NULL;
315     int temp = ckmc_get_cert(alias, 0, &test_cert);
316     ckmc_cert_free(test_cert);
317     RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == temp, CKMCReadableError(temp));
318
319 }
320 void check_cert_not_visible(const char *alias)
321 {
322     ckmc_cert_s *test_cert = NULL;
323     int temp = ckmc_get_cert(alias, 0, &test_cert);
324     ckmc_cert_free(test_cert);
325     RUNNER_ASSERT_MSG(CKMC_ERROR_DB_ALIAS_UNKNOWN == temp,
326                       "App with different label shouldn't have rights to see this cert. " << CKMCErrorToString(temp));
327 }
328
329 void allow_access(const char* alias, const char* accessor, int permissionMask)
330 {
331     // data removal should revoke this access
332     int ret = ckmc_set_permission(alias, accessor, permissionMask);
333     RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == ret, "Trying to allow access returned: "
334                         << CKMCErrorToString(ret));
335 }
336
337 void allow_access_negative(const char* alias, const char* accessor, int permissionMask, int expectedCode)
338 {
339     // data removal should revoke this access
340     int ret = ckmc_set_permission(alias, accessor, permissionMask);
341     RUNNER_ASSERT_MSG(expectedCode == ret, "Trying to allow access returned "
342                         << CKMCErrorToString(ret) << ", while expected: "
343                         << CKMCErrorToString(expectedCode));
344 }
345
346 void deny_access(const char* alias, const char* accessor)
347 {
348     int ret = ckmc_set_permission(alias, accessor, CKMC_PERMISSION_NONE);
349     RUNNER_ASSERT_MSG(CKMC_ERROR_NONE == ret, "Denying access failed. Error: "
350                         << CKMCErrorToString(ret));
351 }
352
353 void deny_access_negative(const char* alias, const char* accessor, int expectedCode)
354 {
355     int ret = ckmc_set_permission(alias, accessor, CKMC_PERMISSION_NONE);
356     RUNNER_ASSERT_MSG(expectedCode == ret, "Denying access failed. "
357                         << CKMCErrorToString(ret) << ", while expected: "
358                         << CKMCErrorToString(expectedCode));
359 }
360
361 void unlock_user_data(uid_t user_id, const char *passwd)
362 {
363     int ret;
364     auto control = CKM::Control::create();
365     RUNNER_ASSERT_MSG(CKM_API_SUCCESS == (ret = control->unlockUserKey(user_id, passwd)),
366                       "Error=" << CKMErrorToString(ret));
367 }
368
369 void remove_user_data(uid_t user_id)
370 {
371     auto control = CKM::Control::create();
372     control->lockUserKey(user_id);
373     control->removeUserData(user_id);
374 }
375
376 void reset_user_data(uid_t user_id, const char *passwd)
377 {
378     remove_user_data(user_id);
379     unlock_user_data(user_id, passwd);
380 }
381
382 ckmc_raw_buffer_s prepare_message_buffer(const char * input)
383 {
384     ckmc_raw_buffer_s retval;
385     retval.data = const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(input));
386     retval.size = strlen(input);
387     return retval;
388 }
389
390 void check_alias_list(const CKM::AliasVector& expected)
391 {
392     ckmc_alias_list_s *aliasList = NULL;
393     int ret = ckmc_get_data_alias_list(&aliasList);
394     RUNNER_ASSERT_MSG(ret == 0, "Failed to get the list of data aliases. " << ret << " / " << CKMCErrorToString(ret));
395
396     CKM::AliasVector actual;
397     ckmc_alias_list_s *plist = aliasList;
398     while(plist)
399     {
400         actual.push_back(plist->alias);
401         plist = plist->next;
402     }
403     ckmc_alias_list_all_free(aliasList);
404
405     RUNNER_ASSERT_MSG(expected == actual, "Actual list of aliases differ from expected list.");
406 }
407
408 size_t count_aliases(alias_type_ type, size_t minimum_initial_element_count)
409 {
410     ckmc_alias_list_s *aliasList = NULL;
411     int ec;
412     switch(type)
413     {
414         case ALIAS_KEY:
415             ec = ckmc_get_key_alias_list(&aliasList);
416             break;
417
418         case ALIAS_CERT:
419             ec = ckmc_get_cert_alias_list(&aliasList);
420             break;
421
422         case ALIAS_DATA:
423             ec = ckmc_get_data_alias_list(&aliasList);
424             break;
425         default:
426             RUNNER_ASSERT_MSG(false, "Unsupported value ALIAS_KEY == " << (int)type);
427     }
428
429     if(ec == CKMC_ERROR_DB_ALIAS_UNKNOWN)
430         return 0;
431
432     RUNNER_ASSERT_MSG(ec == CKMC_ERROR_NONE,
433                       "Error: alias list failed, ec: " << CKMCErrorToString(ec));
434
435     ckmc_alias_list_s *plist = aliasList;
436     size_t return_count = 0;
437     while(plist)
438     {
439         plist = plist->next;
440         return_count ++;
441     }
442     ckmc_alias_list_all_free(aliasList);
443
444     RUNNER_ASSERT_MSG(
445       return_count >= minimum_initial_element_count,
446       "Error: alias list failed, current element count: " << return_count <<
447       " while expected minimal count of " << minimum_initial_element_count <<
448       " elements");
449
450     return return_count;
451 }
452
453 std::string sharedDatabase(const CKM::Alias & alias)
454 {
455     return aliasWithLabel(ckmc_owner_id_system, alias.c_str());
456 }
457
458 ckmc_raw_buffer_s* createRandomBufferCAPI(size_t random_bytes)
459 {
460     ckmc_raw_buffer_s* buffer = NULL;
461     char* data = static_cast<char*>(malloc(random_bytes*sizeof(char)));
462     RUNNER_ASSERT(data);
463     generate_random(random_bytes, data);
464     int ret = ckmc_buffer_new(reinterpret_cast<unsigned char*>(data), random_bytes, &buffer);
465     RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Buffer creation failed: " << CKMCErrorToString(ret));
466     return buffer;
467 }
468
469 CKM::RawBuffer createRandomBuffer(size_t random_bytes)
470 {
471     char buffer[random_bytes];
472     generate_random(random_bytes, buffer);
473     return CKM::RawBuffer(buffer, buffer + random_bytes);
474 }
475
476 ckmc_key_s *generate_AES_key(size_t lengthBits, const char *passwd)
477 {
478     ckmc_key_s *retval = reinterpret_cast<ckmc_key_s *>(malloc(sizeof(ckmc_key_s)));
479     RUNNER_ASSERT(retval != NULL);
480
481     RUNNER_ASSERT(lengthBits%8 == 0);
482     char *char_key_AES = reinterpret_cast<char*>(malloc(lengthBits/8));
483     RUNNER_ASSERT(char_key_AES != NULL);
484     generate_random(lengthBits/8, char_key_AES);
485
486     retval->raw_key  = reinterpret_cast<unsigned char *>(char_key_AES);
487     retval->key_size = lengthBits/8;
488     retval->key_type = CKMC_KEY_AES;
489     retval->password = passwd?strdup(passwd):NULL;
490
491     return retval;
492 }
493
494 void validate_AES_key(ckmc_key_s *analyzed)
495 {
496     RUNNER_ASSERT_MSG(analyzed, "provided key is NULL");
497     RUNNER_ASSERT_MSG(analyzed->raw_key != NULL, "provided key is empty");
498     RUNNER_ASSERT_MSG(analyzed->key_size==(128/8) ||
499                       analyzed->key_size==(192/8) ||
500                       analyzed->key_size==(256/8), "provided key length is invalid");
501     RUNNER_ASSERT_MSG(analyzed->key_type = CKMC_KEY_AES, "expected AES key, while got: " << analyzed->key_type);
502 }
503
504 void compare_AES_keys(ckmc_key_s *first, ckmc_key_s *second)
505 {
506     validate_AES_key(first);
507     validate_AES_key(second);
508     RUNNER_ASSERT_MSG(
509         (first->key_size==second->key_size) &&
510         (memcmp(first->raw_key, second->raw_key, first->key_size)==0),
511         "data has been modified in key manager");
512     // bypassing password intentionally
513 }
514
515 ParamListPtr createParamListPtr()
516 {
517     ckmc_param_list_h list = NULL;
518     assert_positive(ckmc_param_list_new, &list);
519     return ParamListPtr(list, ckmc_param_list_free);
520 }
521
522 void assert_buffers_equal(const ckmc_raw_buffer_s b1, const ckmc_raw_buffer_s b2, bool equal)
523 {
524     if(equal) {
525         RUNNER_ASSERT_MSG(b1.size == b2.size, "Buffer size differs: " << b1.size << "!=" << b2.size);
526         RUNNER_ASSERT_MSG(0 == memcmp(b1.data, b2.data, b1.size), "Buffer contents differ");
527     } else {
528         RUNNER_ASSERT_MSG(b1.size != b2.size || 0 != memcmp(b1.data, b2.data, b1.size),
529                           "Buffers should be different");
530     }
531 }
532
533 RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer)
534 {
535     return RawBufferPtr(buffer, ckmc_buffer_free);
536 }