1 /******************************************************************
3 * Copyright 2017 - 2021 Samsung Electronics All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 ******************************************************************/
19 #include <boost/algorithm/hex.hpp>
23 #include <sys/smack.h> // SMACK_LABEL_LEN
25 #include "dcm_client.h"
26 #include "device_certificate_manager.h"
27 #include "device_certificate_manager_ext.h"
28 #include "device_certificate_manager_ext_types.h"
29 #include "test_macros.h"
32 class allocation_disabler {
34 allocation_disabler(size_t n = 0) { enabled = true; allowed_allocs_n = n; }
35 ~allocation_disabler() { enabled = false; allowed_allocs_n = 0; }
37 static bool alloc_disabled() {
41 if (allowed_allocs_n == 0)
48 inline static bool enabled;
49 inline static size_t allowed_allocs_n;
52 template<typename... Arguments>
53 auto test_no_mem_envir(size_t allowed_allocs, Arguments&&... args) {
54 auto _ = allocation_disabler(allowed_allocs);
55 return std::invoke(std::forward<Arguments>(args)...);
58 extern "C" void *__libc_malloc(size_t size);
60 extern "C" void *malloc(size_t size) {
61 if (allocation_disabler::alloc_disabled())
64 return __libc_malloc(size);
70 explicit Fd(int fd) : fd(fd) { BOOST_REQUIRE_GE(fd, 0); }
71 operator int() const { return fd; }
72 ~Fd() { BOOST_CHECK_EQUAL(close(fd), 0); }
75 class OverrideSmackLabel {
77 char old_label[SMACK_LABEL_LEN];
78 boost::uint_value_t<SMACK_LABEL_LEN>::least old_label_len;
80 explicit OverrideSmackLabel(const char *override_label)
81 : fd(open("/proc/thread-self/attr/current", O_RDWR)) {
82 const auto ret = read(fd, old_label, sizeof old_label);
83 BOOST_REQUIRE_GT(ret, 0);
84 BOOST_REQUIRE_LE(ret, sizeof old_label);
87 // subsequent write()s fail without the seek
88 BOOST_REQUIRE_EQUAL(lseek(fd, 0, SEEK_SET), 0);
90 const auto len = strlen(override_label);
91 BOOST_REQUIRE_EQUAL(write(fd, override_label, len), len);
94 ~OverrideSmackLabel() {
95 BOOST_CHECK_EQUAL(write(fd, old_label, old_label_len), old_label_len);
101 BOOST_AUTO_TEST_SUITE(API_TEST)
103 POSITIVE_TEST_CASE(test01_dcm_create_key_context)
106 int ret = dcm_create_key_context(NULL, NULL, NULL, &ctx);
107 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
109 ret = dcm_free_key_context(ctx);
110 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
113 ret = dcm_create_key_context("", "", NULL, &ctx);
114 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
116 ret = dcm_free_key_context(ctx);
117 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
120 ret = dcm_create_key_context("a", NULL, NULL, &ctx);
121 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
123 ret = dcm_free_key_context(ctx);
124 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
127 ret = dcm_create_key_context(NULL, "a", NULL, &ctx);
128 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
130 ret = dcm_free_key_context(ctx);
131 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
134 ret = dcm_create_key_context("a", "a", NULL, &ctx);
135 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
137 ret = dcm_free_key_context(ctx);
138 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
141 ret = dcm_create_key_context("a", "b", "UNEXISTING", &ctx);
142 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NO_DATA);
144 ret = dcm_free_key_context(ctx);
145 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
148 POSITIVE_TEST_CASE(test02_dcm_get_certificate_chain)
154 int ret = dcm_create_key_context("a", "b", NULL, &ctx);
155 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
158 ret = dcm_get_certificate_chain(ctx, NULL, &cert_len);
159 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
161 ret = dcm_get_certificate_chain(ctx, &cert, NULL);
162 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
164 ret = dcm_get_certificate_chain(NULL, &cert, &cert_len);
165 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
167 ret = dcm_get_certificate_chain(ctx, &cert, &cert_len);
168 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
170 BOOST_REQUIRE(cert_len > 0);
172 ret = dcm_free_key_context(ctx);
173 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
178 POSITIVE_TEST_CASE(test03_dcm_get_key_bit_length)
184 ret = dcm_get_key_bit_length(NULL, &key_len);
185 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
187 ret = dcm_create_key_context("a", "b", "ECDSA", &ctx);
188 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
191 ret = dcm_get_key_bit_length(ctx, &key_len);
192 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
193 BOOST_REQUIRE(key_len > 0);
195 ret = dcm_free_key_context(ctx);
196 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
199 POSITIVE_TEST_CASE(test04_dcm_get_key_type)
205 ret = dcm_get_key_type(NULL, &key_type);
206 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
208 ret = dcm_create_key_context("a", "b", "ECDSA", &ctx);
209 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
212 ret = dcm_get_key_type(ctx, &key_type);
213 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
214 BOOST_CHECK(key_type);
215 BOOST_CHECK(strcmp(key_type, "ECDSA") == 0);
217 ret = dcm_free_key_context(ctx);
218 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
222 POSITIVE_TEST_CASE(test05_dcm_create_signature)
227 size_t signature_len;
228 char data[32] = {0,};
230 ret = dcm_create_signature(NULL, DCM_DIGEST_SHA256, data, sizeof(data), &signature, &signature_len);
231 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
233 ret = dcm_create_key_context("a", "b", "ECDSA", &ctx);
234 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
237 ret = dcm_create_signature(ctx, DCM_DIGEST_SHA256, data, sizeof(data), NULL, &signature_len);
238 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
240 ret = dcm_create_signature(ctx, DCM_DIGEST_SHA256, data, sizeof(data), &signature, NULL);
241 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_INVALID_PARAMETER);
243 std::cout << "Data to sign = ";
244 boost::algorithm::hex(std::begin(data), std::end(data), std::ostream_iterator<char>(std::cout));
245 std::cout << std::endl;
247 ret = dcm_create_signature(ctx, DCM_DIGEST_SHA256, data, sizeof(data), &signature, &signature_len);
248 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
249 BOOST_CHECK(signature);
250 BOOST_REQUIRE(signature_len > 0);
252 std::cout << "Signature = ";
253 boost::algorithm::hex(signature, signature + signature_len, std::ostream_iterator<char>(std::cout));
254 std::cout << std::endl;
256 ret = dcm_free_key_context(ctx);
257 BOOST_REQUIRE_EQUAL(ret, DCM_ERROR_NONE);
262 NEGATIVE_TEST_CASE(test06_dcm_ext_api_invalid_params_on_client_side)
264 int ret = dcm_ext_call_api(NULL, NULL, 0, NULL, NULL);
265 BOOST_REQUIRE_EQUAL(ret, DCM_EXT_ERROR_INVALID_PARAMETER);
268 NEGATIVE_TEST_CASE(test07_dcm_ext_api_invalid_method_name)
270 int ret = dcm_ext_call_api("method-not-existing", NULL, 0, NULL, NULL);
271 BOOST_REQUIRE_EQUAL(ret, DCM_EXT_ERROR_INVALID_PARAMETER);
274 NEGATIVE_TEST_CASE(test08_dcm_ext_api_no_privilege)
276 // This test seems to require the System::Privileged label because it
277 // relies on a particular cynara rule concerning System::Privileged and the
278 // underlying "http://tizen.org/privilege/internal/sysadmin" privilege
279 // checked during the "method-with-a-privilege-not-granted" call.
280 // Grep backend code for /method-with-a-privilege-not-granted/ for details.
282 // Sdb uses User::Shell but one can switch to System::Privileged, then back.
283 OverrideSmackLabel _("System::Privileged");
285 int ret = dcm_ext_call_api("method-with-a-privilege-not-granted", NULL, 0, NULL, NULL);
286 BOOST_REQUIRE_EQUAL(ret, DCM_EXT_ERROR_PERMISSION_DENIED);
289 POSITIVE_TEST_CASE(test09_dcm_ext_api_normal_call)
294 int ret = dcm_ext_call_api("square-int-method", (char*)&input, sizeof(input), &output , &out_size);
295 BOOST_REQUIRE_EQUAL(ret, DCM_EXT_ERROR_NONE);
296 BOOST_REQUIRE_EQUAL(out_size, sizeof(int));
297 BOOST_REQUIRE_EQUAL((int)(*output), 25);
301 NEGATIVE_TEST_CASE(test10_dcm_ext_api_no_buffer_ptr_provided) {
303 int ret = dcm_ext_call_api("square-int-method", (char*)&input, sizeof(input), nullptr, nullptr);
304 BOOST_REQUIRE(ret == DCM_EXT_ERROR_INVALID_PARAMETER);
308 POSITIVE_TEST_CASE(test11_cpp_dcm_client_api_hash_size) {
309 auto conn = dcm_client_connection::create();
310 std::vector<uint8_t> chain, digest;
311 constexpr char hash_data[] = "01234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef";
313 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "RSA") == DCM_ERROR_NONE);
315 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_MD5, hash_data, 16, digest) == DCM_ERROR_NONE);
316 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_SHA1, hash_data, 20, digest) == DCM_ERROR_NONE);
317 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_SHA224, hash_data, 28, digest) == DCM_ERROR_NONE);
318 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_SHA256, hash_data, 32, digest) == DCM_ERROR_NONE);
319 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_SHA384, hash_data, 48, digest) == DCM_ERROR_NONE);
320 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_SHA512, hash_data, 64, digest) == DCM_ERROR_NONE);
321 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_RIPEMD160, hash_data, 20, digest) == DCM_ERROR_NONE);
324 POSITIVE_TEST_CASE(test12_cpp_dcm_client_api_key_type) {
325 auto conn = dcm_client_connection::create();
326 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "RSA") == DCM_ERROR_NONE);
327 BOOST_REQUIRE(conn->key_type() == "RSA");
329 conn = dcm_client_connection::create();
330 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "ECDSA") == DCM_ERROR_NONE);
331 BOOST_REQUIRE(conn->key_type() == "ECDSA");
334 NEGATIVE_TEST_CASE(test13_cpp_dcm_client_api_key_type) {
335 auto conn = dcm_client_connection::create();
336 BOOST_REQUIRE(conn->key_type() == "UNKNOWN");
339 NEGATIVE_TEST_CASE(test14_dcm_client_api_cookie_exists) {
340 auto conn = dcm_client_connection::create();
342 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "RSA") == DCM_ERROR_NONE);
343 // cookie already exists error
344 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "RSA") == DCM_ERROR_SOCKET);
347 NEGATIVE_TEST_CASE(test15_dcm_client_api_no_cookie) {
348 auto conn = dcm_client_connection::create();
349 std::vector<uint8_t> chain, digest;
350 constexpr char hash_data[] = "01234567890abcdef";
353 BOOST_REQUIRE(conn->get_certificate_chain(chain) == DCM_ERROR_SOCKET);
354 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_SHA1, hash_data, sizeof(hash_data), digest) == DCM_ERROR_SOCKET);
357 NEGATIVE_TEST_CASE(test16_dcm_client_api_invalid_hash_size) {
358 auto conn = dcm_client_connection::create();
359 std::vector<uint8_t> chain, digest;
360 constexpr char hash_data[] = "01234567890abcdef";
362 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "RSA") == DCM_ERROR_NONE);
364 // hash_size == 0 and md == DCM_DIGEST_NONE
365 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_NONE, hash_data, 0, digest) == DCM_ERROR_INVALID_PARAMETER);
367 // hash size mismatch
368 BOOST_REQUIRE(conn->sign_data(DCM_DIGEST_MD5, hash_data, 1, digest) == DCM_ERROR_INVALID_PARAMETER);
371 NEGATIVE_TEST_CASE(test17_dcm_ext_api_no_mem) {
376 BOOST_REQUIRE(test_no_mem_envir(2, &dcm_ext_call_api, "square-int-method", (char*)&input,
377 sizeof(input), &output , &out_size) == DCM_EXT_ERROR_SOCKET);
379 BOOST_REQUIRE(test_no_mem_envir(10, &dcm_ext_call_api, "square-int-method", (char*)&input,
380 sizeof(input), &output , &out_size) == DCM_EXT_ERROR_SOCKET);
382 BOOST_REQUIRE(test_no_mem_envir(15, &dcm_ext_call_api, "square-int-method", (char*)&input,
383 sizeof(input), &output , &out_size) == DCM_EXT_ERROR_OUT_OF_MEMORY);
386 NEGATIVE_TEST_CASE(test18_cpp_dcm_client_api_no_mem) {
387 auto conn = dcm_client_connection::create();
388 std::vector<uint8_t> chain, digest;
389 constexpr char hash_data[] = "01234567890abcdef";
391 BOOST_REQUIRE(test_no_mem_envir(0, &dcm_client_connection::create_context, conn,
392 "S", "U", "K") == DCM_ERROR_SOCKET);
394 BOOST_REQUIRE(test_no_mem_envir(10, &dcm_client_connection::create_context, conn,
395 "S", "U", "K") == DCM_ERROR_SOCKET);
397 BOOST_REQUIRE(conn->create_context("TEST", "TEST", "RSA") == DCM_ERROR_NONE);
399 BOOST_REQUIRE(test_no_mem_envir(1, &dcm_client_connection::get_certificate_chain, conn,
400 chain) == DCM_ERROR_OUT_OF_MEMORY);
402 BOOST_REQUIRE(test_no_mem_envir(1, &dcm_client_connection::sign_data, conn,
403 DCM_DIGEST_MD5, hash_data, 0, digest) == DCM_ERROR_OUT_OF_MEMORY);
406 NEGATIVE_TEST_CASE(test19_dcm_api_no_mem) {
409 BOOST_REQUIRE(test_no_mem_envir(0, &dcm_create_key_context,
410 nullptr, nullptr, nullptr, &ctx) == DCM_ERROR_UNKNOWN);
413 BOOST_AUTO_TEST_SUITE_END()