--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ *
+ * @file ode-tests-common.h
+ * @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ * @brief Tests for the ODE API
+ */
+
+#pragma once
+
+#include <utility>
+
+#include <dpl/test/test_runner.h>
+#include <ode/common.h>
+
+const char* ODEErrorToString(int error);
+
+// RUNNER_ASSERT wrappers
+
+template <typename F, typename... Args>
+void assert_result(int expected, F&& func, Args... args)
+{
+ int ret = func(args...);
+ RUNNER_ASSERT_MSG(ret == expected,
+ "Expected: " << ODEErrorToString(expected) << "(" << expected << ")"
+ " got: " << ODEErrorToString(ret) << "(" << ret << ")");
+}
+
+template <typename F, typename... Args>
+void assert_positive(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_NONE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_invalid_parameter(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_INVALID_PARAMETER, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_connection_refused(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_CONNECTION_REFUSED, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_permission_denied(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_PERMISSION_DENIED, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_no_such_file(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_NO_SUCH_FILE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_no_such_device(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_NO_SUCH_DEVICE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_key_rejected(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_KEY_REJECTED, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_no_data(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_NO_DATA, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_resource_busy(F&& func, Args... args)
+{
+ assert_result(ODE_ERROR_RESOURCE_BUSY, std::move(func), args...);
+}
+
+// helper classes
+
+class HelperKeys {
+ const char* dev;
+ const char* pass;
+
+public:
+ HelperKeys(const char* device, const char* password, bool initialize = true);
+ ~HelperKeys();
+};
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* @file ode-tests-keys.cpp
* @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
- * @brief Tests for testing the ODE API
+ * @brief Tests for the ODE API
*/
-#include "dpl/test/test_runner.h"
+#include <memory>
-RUNNER_TEST_GROUP_INIT(T2000_ODE_API_KEYS);
\ No newline at end of file
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <temp_test_user.h>
+#include <app_install_helper.h>
+#include <tests_common.h>
+#include <scoped_installer.h>
+#include <service_manager.h>
+
+#include <ode/keys.h>
+#include "ode-tests-common.h"
+
+namespace OdeTestsKeys {
+
+const std::string PRIVILEGE_INTERNAL_USERMANAGEMENT =
+ "http://tizen.org/privilege/internal/usermanagement";
+const std::string PRIVILEGE_INTERNAL_DEFAULT_PLATFORM =
+ "http://tizen.org/privilege/internal/default/platform";
+
+const char* device1 = "/dev/vda1";
+const char* device2 = "/dev/vda2";
+
+const char* password = "abc123";
+const char* password_new = "def456";
+
+// TODO: obtain existing block devices from /proc/mounts
+
+RUNNER_TEST_GROUP_INIT(T2000_ODE_API_KEYS);
+
+/*
+ * If at least one of the parameters in invalid, then the INVALID_PARAM error
+ * is returned.
+ */
+RUNNER_TEST(T2001_ode_key_is_initialized_1_invalid_parameter)
+{
+ bool result;
+
+ // device set to empty string
+ assert_invalid_parameter(ode_key_is_initialized, "", &result);
+ // device set to NULL
+ assert_invalid_parameter(ode_key_is_initialized, nullptr, &result);
+
+ // result set to NULL
+ assert_invalid_parameter(ode_key_is_initialized, device1, nullptr);
+}
+
+/*
+ * The third argument of the ode_key_init function is the type of key
+ * initialization method used. It may be ODE_KEY_DEFAULT_256BIT (1) or
+ * ODE_KEY_DEFAULT_512BIT (2). So if value different than 1 or 2 is passed,
+ * invalid parameter error is returned by the function.
+ * Invalid parameter error is returned also if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2002_ode_key_init_1_invalid_parameter)
+{
+ // device set to empty string
+ assert_invalid_parameter(ode_key_init, "", password, ODE_KEY_DEFAULT_256BIT);
+ // device set to NULL
+ assert_invalid_parameter(ode_key_init, nullptr, password, ODE_KEY_DEFAULT_256BIT);
+
+ // password set to empty string
+ assert_invalid_parameter(ode_key_init, device1, "", ODE_KEY_DEFAULT_256BIT);
+ // password set to NULL
+ assert_invalid_parameter(ode_key_init, device1, nullptr, ODE_KEY_DEFAULT_256BIT);
+
+ // if the key will be initialized, the helper will remove it after the test execution
+ HelperKeys helper(device1, password, false);
+ // invalid type of key
+ assert_invalid_parameter(ode_key_init, device1, password, static_cast<ode_key_gen_params_e>(0));
+ assert_invalid_parameter(ode_key_init, device1, password, static_cast<ode_key_gen_params_e>(3));
+}
+
+/*
+ * TODO: ode_key_init should return invalid param in case of double init
+ *
+ * Calling ode_key_init() second time for given device should fail (now it just
+ * overwrites the existing key).
+ */
+RUNNER_TEST(T2003_ode_key_init_2_invalid_parameter_double_init)
+{
+ RUNNER_IGNORED_MSG("Test ignored because no error is returned in case of "
+ "the double init, while the ODE_ERROR_INVALID_PARAMETER "
+ "should be returned.");
+
+ HelperKeys helper(device1, password);
+
+ assert_invalid_parameter(ode_key_init, device1, password, ODE_KEY_DEFAULT_256BIT);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2004_ode_key_remove_1_invalid_parameter)
+{
+ HelperKeys helper(device1, password);
+
+ // device set to empty string
+ assert_invalid_parameter(ode_key_remove, "", password);
+ // device set to NULL
+ assert_invalid_parameter(ode_key_remove, nullptr, password);
+
+ // password set to empty string
+ assert_invalid_parameter(ode_key_remove, device1, "");
+ // password set to NULL
+ assert_invalid_parameter(ode_key_remove, device1, nullptr);
+}
+
+/*
+ * If the password is wrong, then the key cannot be removed and the error
+ * should be returned by the ode_key_remove function.
+ */
+RUNNER_TEST(T2005_ode_key_remove_2_rejected)
+{
+ const char* password_wrong = "abc321";
+
+ HelperKeys helper(device1, password);
+
+ assert_key_rejected(ode_key_remove, device1, password_wrong);
+}
+
+/*
+ * If no key exists for the given device, then the error should be returned by
+ * the ode_key_remove function.
+ */
+RUNNER_TEST(T2006_ode_key_remove_3_no_such_file)
+{
+ assert_no_such_file(ode_key_remove, device1, password);
+ assert_no_such_file(ode_key_remove, device2, password);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2007_ode_key_change_password_1_invalid_parameter)
+{
+ HelperKeys helper(device1, password);
+
+ // device set to empty string
+ assert_invalid_parameter(ode_key_change_password, "", password, password_new);
+ // device set to NULL
+ assert_invalid_parameter(ode_key_change_password, nullptr, password, password_new);
+
+ // old password set to empty string
+ assert_invalid_parameter(ode_key_change_password, device1, "", password_new);
+ // old password set to NULL
+ assert_invalid_parameter(ode_key_change_password, device1, nullptr, password_new);
+
+ // new password set to empty string
+ assert_invalid_parameter(ode_key_change_password, device1, password, "");
+ // new password set to NULL
+ assert_invalid_parameter(ode_key_change_password, device1, password, nullptr);
+}
+
+/*
+ * If the current password is wrong (for example the developer mistook the
+ * string with the current password with the new one), then the password cannot
+ * be changed and the error is returned by the ode_key_change_password
+ * function.
+ */
+RUNNER_TEST(T2008_ode_key_change_password_2_key_rejected)
+{
+ HelperKeys helper(device1, password);
+
+ assert_key_rejected(ode_key_change_password, device1, password_new, password);
+}
+
+/*
+ * If no key exists for the given device, then the password cannot be changed
+ * and the error is returned by the ode_key_change_password function.
+ */
+RUNNER_TEST(T2009_ode_key_change_password_3_no_such_file)
+{
+ assert_no_such_file(ode_key_change_password, device1, password, password_new);
+ assert_no_such_file(ode_key_change_password, device2, password, password_new);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2010_ode_key_verify_password_1_invalid_parameter)
+{
+ HelperKeys helper(device1, password);
+
+ bool result;
+
+ // device set to empty string
+ assert_invalid_parameter(ode_key_verify_password, "", password, &result);
+ // device set to NULL
+ assert_invalid_parameter(ode_key_verify_password, nullptr, password, &result);
+
+ // password set to empty string
+ assert_invalid_parameter(ode_key_verify_password, device1, "", &result);
+ // password set to NULL
+ assert_invalid_parameter(ode_key_verify_password, device1, nullptr, &result);
+
+ // result set to NULL
+ assert_invalid_parameter(ode_key_verify_password, device1, password, nullptr);
+}
+
+RUNNER_TEST(T2011_ode_key_verify_password_2_no_such_file)
+{
+ bool result;
+
+ assert_no_such_file(ode_key_verify_password, device1, password, &result);
+ assert_no_such_file(ode_key_verify_password, device2, password, &result);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2012_ode_key_store_master_key_1_invalid_parameter)
+{
+ HelperKeys helper(device1, password);
+
+ // device set to empty string
+ assert_invalid_parameter(ode_key_store_master_key, "", password);
+ // device set to NULL
+ assert_invalid_parameter(ode_key_store_master_key, nullptr, password);
+
+ // password set to empty string
+ assert_invalid_parameter(ode_key_store_master_key, device1, "");
+ // password set to NULL
+ assert_invalid_parameter(ode_key_store_master_key, device1, nullptr);
+}
+
+/*
+ * If the password passed into the ode_key_store_master_key function is wrong,
+ * then the key cannot be stored and ODE_ERROR_KEY_REJECTED should be returned
+ * by the storing function.
+ */
+RUNNER_TEST(T2013_ode_key_store_master_key_2_key_rejected)
+{
+ HelperKeys helper(device1, password);
+
+ assert_key_rejected(ode_key_store_master_key, device1, password_new);
+}
+
+RUNNER_TEST(T2014_ode_key_store_master_key_3_no_such_file)
+{
+ assert_no_such_file(ode_key_store_master_key, device1, password);
+ assert_no_such_file(ode_key_store_master_key, device2, password);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2015_ode_key_remove_master_key_1_invalid_parameter)
+{
+ HelperKeys helper(device1, password);
+
+ assert_positive(ode_key_store_master_key, device1, password);
+
+ // device set to empty string
+ assert_invalid_parameter(ode_key_remove_master_key, "");
+ // device set to NULL
+ assert_invalid_parameter(ode_key_remove_master_key, nullptr);
+}
+
+/*
+ * If the ode service is not active during the try of using the API functions,
+ * then the connection should be refused and the error should be returned by
+ * the API function.
+ */
+RUNNER_TEST(T2016_ode_keys_connection_refused)
+{
+ HelperKeys helper(device1, password);
+
+ auto sm_start = [](ServiceManager* sm) {
+ sm->startService(true);
+ delete sm;
+ };
+ std::unique_ptr<ServiceManager, decltype(sm_start)> sm_stop(new ServiceManager("ode.service"), sm_start);
+ sm_stop->stopService(true);
+
+ bool result;
+
+ assert_connection_refused(ode_key_is_initialized, device1, &result);
+ assert_connection_refused(ode_key_init, device1, password, ODE_KEY_DEFAULT_256BIT);
+ assert_connection_refused(ode_key_remove, device1, password);
+ assert_connection_refused(ode_key_change_password, device1, password, password_new);
+ assert_connection_refused(ode_key_verify_password, device1, password, &result);
+ assert_connection_refused(ode_key_store_master_key, device1, password);
+ assert_connection_refused(ode_key_remove_master_key, device1);
+}
+
+/*
+ * When the unprivileged process (without the privilege internal/default/platform)
+ * tries to use protected API functions, then the PERMISSION_DENIED error is
+ * returned.
+ *
+ * TODO: permission denied should be returned instead of unknown error
+ */
+RUNNER_CHILD_TEST(T2017_ode_keys_permission_denied)
+{
+ RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_UNKNOWN is returned "
+ "instead of the ODE_ERROR_PERMISSION_DENIED.");
+
+ TemporaryTestUser adminUserToSwitch("ode_test_T2016_user", GUM_USERTYPE_ADMIN);
+ adminUserToSwitch.create();
+
+ AppInstallHelper appInstallHelper("ode_test_T2016_app_install_helper",
+ adminUserToSwitch.getUid());
+
+ ScopedInstaller scopedInstaller(appInstallHelper);
+
+ pid_t pid = fork();
+ if (pid != 0) {
+ waitPid(pid);
+ } else { //child process
+ SecurityManagerTest::Api::setProcessLabel(appInstallHelper.getAppId());
+ RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(adminUserToSwitch.getUid(),
+ adminUserToSwitch.getGid()) == 0,
+ "drop_root_privileges failed");
+
+ bool result;
+
+ // check if there is access to unprotected function
+ assert_positive(ode_key_is_initialized, device1, &result);
+
+ // check if there is no access to protected function
+ assert_permission_denied(ode_key_init, device1, password, ODE_KEY_DEFAULT_256BIT);
+ assert_permission_denied(ode_key_remove, device1, password);
+ assert_permission_denied(ode_key_change_password, device1, password, password_new);
+ assert_permission_denied(ode_key_verify_password, device1, password, &result);
+ assert_permission_denied(ode_key_store_master_key, device1, password);
+ assert_permission_denied(ode_key_remove_master_key, device1);
+ }
+}
+
+} // namespace OdeTestsKeys