Merge branch 'tizen' into ode 32/207532/1
authorDariusz Michaluk <d.michaluk@samsung.com>
Thu, 6 Jun 2019 11:33:21 +0000 (13:33 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Thu, 6 Jun 2019 11:33:21 +0000 (13:33 +0200)
Change-Id: Ic562abbef0de256d5f0f0697709de296d7d8c986

13 files changed:
CMakeLists.txt
README
packaging/security-tests.spec
src/CMakeLists.txt
src/ode/CMakeLists.txt [new file with mode: 0644]
src/ode/ode-tests-common.cpp [new file with mode: 0644]
src/ode/ode-tests-common.h [new file with mode: 0644]
src/ode/ode-tests-external-encryption.cpp [new file with mode: 0644]
src/ode/ode-tests-internal-encryption.cpp [new file with mode: 0644]
src/ode/ode-tests-keys.cpp [new file with mode: 0644]
src/ode/ode-tests-luks.cpp [new file with mode: 0644]
src/ode/ode-tests-secure-erase.cpp [new file with mode: 0644]
src/ode/ode-tests.cpp [new file with mode: 0644]

index 01ce9fb..ce88a43 100644 (file)
@@ -64,6 +64,7 @@ IF(BUILD_ALL_TESTS)
     SET(BUILD_CYNARA ON)
     SET(BUILD_WEB ON)
     SET(BUILD_YACA ON)
+    SET(BUILD_ODE ON)
 ENDIF(BUILD_ALL_TESTS)
 
 # If supported for the target machine, emit position-independent code,suitable
diff --git a/README b/README
index c94a739..ea2b291 100644 (file)
--- a/README
+++ b/README
@@ -15,6 +15,8 @@ security-manager
   security-manager-tests
 cynara
   cynara-test
+ode
+  ode-tests
 
 There are also inner-tests for testing complex security-tests framework
 mechanisms with binary:
index 9809e03..efe5a96 100644 (file)
@@ -16,6 +16,7 @@ BuildRequires: pkgconfig(key-manager)
 BuildRequires: key-manager-initial-values
 BuildRequires: util-linux
 BuildRequires: pkgconfig(yaca)
+BuildRequires: pkgconfig(ode)
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(dbus-1)
@@ -52,6 +53,9 @@ Security tests repository - for tests that can't be kept together with code.
 export LDFLAGS+="-Wl,--rpath=%{_prefix}/lib"
 
 cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+%if "%{_with_emulator}" == "1"
+        -DEMULATOR="ON"                   \
+%endif
 %if %{tz_backend_enabled} == ON
         -DTZ_BACKEND="ON"                 \
 %endif
@@ -110,6 +114,7 @@ echo "security-tests postinst done ..."
 %caps(cap_mac_admin=ep) /usr/bin/ckm-privileged-tests
 %caps(cap_mac_admin=ep) /usr/bin/ckm-integration-tests
 /usr/bin/yaca-test
+/usr/bin/ode-tests
 %{ckm_test_dir}/*
 /etc/security-tests
 /usr/lib/security-tests/cynara-tests/plugins/single-policy/*
index 471c28e..93c862c 100644 (file)
@@ -110,3 +110,7 @@ ENDIF(BUILD_WEB)
 IF(BUILD_YACA)
     ADD_SUBDIRECTORY(yaca)
 ENDIF(BUILD_YACA)
+
+IF(BUILD_ODE)
+    ADD_SUBDIRECTORY(ode)
+ENDIF(BUILD_ODE)
\ No newline at end of file
diff --git a/src/ode/CMakeLists.txt b/src/ode/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f7fd464
--- /dev/null
@@ -0,0 +1,55 @@
+#
+#  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.
+#  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   CMakeLists.txt
+#  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+#
+
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Generating makefile for the ODE tests...")
+
+FILE(GLOB  ode_tests_SRCS *.cpp)
+
+OPTION("EMULATOR" ON)
+IF(EMULATOR)
+    ADD_DEFINITIONS("-DEMULATOR")
+ENDIF(EMULATOR)
+
+## Setup target ################################################################
+SET(ODE_TESTS "ode-tests")
+ADD_EXECUTABLE(${ODE_TESTS} ${ode_tests_SRCS})
+
+## Link libraries ##############################################################
+PKG_CHECK_MODULES(ODE_TESTS_DEPS REQUIRED
+    ode
+    security-manager
+    dbus-1
+    libgum
+)
+
+INCLUDE_DIRECTORIES(SYSTEM
+    ${ODE_TESTS_DEPS_INCLUDE_DIRS}
+    ${PROJECT_SOURCE_DIR}/src/common/
+)
+
+TARGET_LINK_LIBRARIES(
+    ${ODE_TESTS}
+    ${ODE_TESTS_DEPS_LIBRARIES}
+    dpl-test-framework
+    tests-common
+)
+
+## Install #####################################################################
+INSTALL(TARGETS ${ODE_TESTS} DESTINATION bin)
diff --git a/src/ode/ode-tests-common.cpp b/src/ode/ode-tests-common.cpp
new file mode 100644 (file)
index 0000000..651ded7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ *  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.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <iostream>
+#include <string>
+
+#include <dpl/log/log.h>
+
+#include <ode/keys.h>
+#include <ode/internal-encryption.h>
+#include "ode-tests-common.h"
+
+#define ERRORDESCRIBE(name) case name: return #name
+
+const char* ODEErrorToString(int error) {
+    switch(error) {
+        ERRORDESCRIBE(ODE_ERROR_NONE);
+        ERRORDESCRIBE(ODE_ERROR_INVALID_PARAMETER);
+        ERRORDESCRIBE(ODE_ERROR_CONNECTION_REFUSED);
+        ERRORDESCRIBE(ODE_ERROR_PERMISSION_DENIED);
+        ERRORDESCRIBE(ODE_ERROR_NO_SUCH_FILE);
+        ERRORDESCRIBE(ODE_ERROR_NO_SUCH_DEVICE);
+        ERRORDESCRIBE(ODE_ERROR_KEY_REJECTED);
+        ERRORDESCRIBE(ODE_ERROR_NO_DATA);
+        ERRORDESCRIBE(ODE_ERROR_RESOURCE_BUSY);
+        ERRORDESCRIBE(ODE_ERROR_UNKNOWN);
+        default: return "Error not defined";
+    }
+}
+
+#undef ERRORDESCRIBE
+
+// helper classes
+
+HelperKeys::HelperKeys(const char* device, const char* password, bool initialize) {
+    dev = device;
+    pass = password;
+
+    if (initialize) {
+        bool result;
+        assert_positive(ode_key_is_initialized, dev, &result);
+
+        if (!result) {
+            assert_positive(ode_key_init, dev, pass, ODE_KEY_DEFAULT_256BIT);
+        }
+    }
+}
+
+HelperKeys::~HelperKeys() {
+    ode_key_remove_master_key(dev);
+    ode_key_remove(dev, pass);
+}
+
+HelperInternalEncryption::HelperInternalEncryption(const char* password) {
+    pass = password;
+
+    bool result;
+    assert_positive(ode_internal_encryption_is_password_initialized, &result);
+
+    if (!result) {
+        assert_positive(ode_internal_encryption_init_password, pass);
+    }
+}
+
+HelperInternalEncryption::~HelperInternalEncryption() {
+    ode_internal_encryption_umount();
+    ode_internal_encryption_clean_password(pass);
+}
diff --git a/src/ode/ode-tests-common.h b/src/ode/ode-tests-common.h
new file mode 100644 (file)
index 0000000..b15440c
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  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>
+
+#define RUNNER_TEST_DUMMY(Proc, ...) \
+    void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#ifndef EMULATOR
+#define RUNNER_TEST_DEVICE(...) RUNNER_TEST(__VA_ARGS__)
+#else
+#define RUNNER_TEST_DEVICE(...) RUNNER_TEST_DUMMY(__VA_ARGS__)
+#endif
+
+#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();
+};
+
+class HelperInternalEncryption {
+    const char* pass;
+
+public:
+    HelperInternalEncryption(const char* password);
+    ~HelperInternalEncryption();
+};
diff --git a/src/ode/ode-tests-external-encryption.cpp b/src/ode/ode-tests-external-encryption.cpp
new file mode 100644 (file)
index 0000000..1e5d55a
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *  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-external-encryption.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include "dpl/test/test_runner.h"
+
+RUNNER_TEST_GROUP_INIT(T0000_ODE_API_EXTERNAL_ENCRYPTION);
\ No newline at end of file
diff --git a/src/ode/ode-tests-internal-encryption.cpp b/src/ode/ode-tests-internal-encryption.cpp
new file mode 100644 (file)
index 0000000..61559ed
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ *  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.
+ *  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-internal-encryption.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <memory>
+#include <string>
+
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <dpl/log/log.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/internal-encryption.h>
+#include "ode-tests-common.h"
+
+namespace OdeTestsInternalEncryption {
+
+const char * password = "abc123";
+const char * password_new = "def456";
+
+RUNNER_TEST_GROUP_INIT(T1000_ODE_API_INTERNAL_ENCRYPTION);
+
+RUNNER_TEST_DEVICE(T1001_internal_encryption_set_mount_password_1_invalid_parameter)
+{
+    HelperInternalEncryption helper(password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_set_mount_password, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_set_mount_password, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1002_internal_encryption_set_mount_password_2_key_rejected)
+{
+    HelperInternalEncryption helper(password);
+
+    // try to set the mount password different than the init password
+    assert_key_rejected(ode_internal_encryption_set_mount_password, password_new);
+}
+
+RUNNER_TEST_DEVICE(T1003_internal_encryption_mount_1_no_such_device)
+{
+    HelperInternalEncryption helper(password);
+
+    // set mount password
+    assert_positive(ode_internal_encryption_set_mount_password, password);
+
+    assert_no_such_device(ode_internal_encryption_mount);
+}
+
+RUNNER_TEST(T1004_internal_encryption_mount_2_no_data)
+{
+    assert_no_data(ode_internal_encryption_mount);
+}
+
+RUNNER_TEST_DEVICE(T1005_internal_encryption_umount_1_no_such_device)
+{
+    HelperInternalEncryption helper(password);
+
+    // set mount password
+    assert_positive(ode_internal_encryption_set_mount_password, password);
+
+    assert_no_such_device(ode_internal_encryption_umount);
+}
+
+RUNNER_TEST_DEVICE(T1006_internal_encryption_encrypt_1_invalid_parameter)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NONE is returned "
+                       "instead of the ODE_ERROR_INVALID_PARAMETER in case "
+                       "when options are set to NULL. Because no error is "
+                       "returned, the device is encrypted. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_encrypt, "", 0);
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_encrypt, nullptr, 0);
+
+    // options set to NULL
+    assert_invalid_parameter(ode_internal_encryption_encrypt, password, NULL);
+    /*
+     * TODO:
+     * Maybe also value of the options (even if it is uint) should be checked
+     * and only 0 or 1 should be available. Alternatively options should be bool
+     * or if more options may be available in the future - enum. Currently, if
+     * options is set to any value different than 0, fast encryption is enabled.
+     * Otherwise it is disabled. Needs improvement in ode.
+     */
+}
+
+RUNNER_TEST_DEVICE(T1007_internal_encryption_encrypt_2_key_rejected)
+{
+    HelperInternalEncryption helper(password);
+
+    // try to encrypt using the password different than the init password
+    assert_key_rejected(ode_internal_encryption_encrypt, password_new, 0);
+}
+
+RUNNER_TEST(T1008_internal_encryption_encrypt_3_no_such_device)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NO_SUCH_FILE is returned "
+                       "instead of the ODE_ERROR_NO_SUCH_DEVICE. "
+                       "Needs improvement in ode module.");
+
+    assert_no_such_device(ode_internal_encryption_encrypt, password, 0);
+}
+
+RUNNER_TEST_DEVICE(T1009_internal_encryption_decrypt_1_invalid_parameter)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NO_SUCH_DEVICE is returned "
+                       "instead of the ODE_ERROR_INVALID_PARAMETER. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_decrypt, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_decrypt, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1010_internal_encryption_decrypt_2_key_rejected)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NO_SUCH_DEVICE is returned "
+                       "instead of the ODE_ERROR_KEY_REJECTED. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    // try to decrypt using the password different than the init password
+    assert_key_rejected(ode_internal_encryption_decrypt, password_new);
+}
+
+RUNNER_TEST_DEVICE(T1011_internal_encryption_decrypt_3_no_such_device)
+{
+    HelperInternalEncryption helper(password);
+
+    assert_no_such_device(ode_internal_encryption_decrypt, password);
+}
+
+RUNNER_TEST_DEVICE(T1012_internal_encryption_recovery_1_no_such_device)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_UNKNOWN is returned "
+                       "instead of the ODE_ERROR_NO_SUCH_DEVICE. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    assert_no_such_device(ode_internal_encryption_recovery);
+}
+
+RUNNER_TEST(T1013_internal_encryption_is_password_initialized_1_invalid_parameter)
+{
+    // result set to NULL
+    assert_invalid_parameter(ode_internal_encryption_is_password_initialized, nullptr);
+}
+
+RUNNER_TEST(T1014_internal_encryption_init_password_1_invalid_parameter)
+{
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_init_password, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_init_password, nullptr);
+}
+
+RUNNER_TEST(T1015_internal_encryption_clean_password_1_invalid_parameter)
+{
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_clean_password, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_clean_password, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1016_internal_encryption_change_password_1_invalid_parameter)
+{
+    HelperInternalEncryption helper(password);
+
+    // old password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_change_password, "", password_new);
+    // old password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_change_password, nullptr, password_new);
+
+    // new password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_change_password, password_new, "");
+    // new password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_change_password, password_new, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1017_internal_encryption_change_password_2_key_rejected)
+{
+    HelperInternalEncryption helper(password);
+
+    assert_key_rejected(ode_internal_encryption_change_password, password_new, password);
+}
+
+RUNNER_TEST(T1018_internal_encryption_verify_password_1_invalid_parameter)
+{
+    bool result;
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_verify_password, "", &result);
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_verify_password, nullptr, &result);
+
+    // result set to NULL
+    assert_invalid_parameter(ode_internal_encryption_verify_password, password, nullptr);
+    assert_invalid_parameter(ode_internal_encryption_verify_password, password_new, nullptr);
+}
+
+RUNNER_TEST(T1019_internal_encryption_get_state_1_invalid_parameter)
+{
+    // state set to NULL
+    assert_invalid_parameter(ode_internal_encryption_get_state, nullptr);
+}
+
+RUNNER_TEST(T1020_internal_encryption_connection_refused)
+{
+    auto sm_start = [](ServiceManager* sm) {
+        sm->startService(true);
+        delete sm;
+        sleep(1);
+        //TODO: startService should wait until the sm is really started but it does not
+        // because of that the sleep is needed
+    };
+    std::unique_ptr<ServiceManager, decltype(sm_start)> sm_stop(new ServiceManager("ode.service"), sm_start);
+    sm_stop->stopService(true);
+
+    unsigned int options = 0;
+    bool result;
+    int state;
+
+    assert_connection_refused(ode_internal_encryption_set_mount_password, password);
+    assert_connection_refused(ode_internal_encryption_mount);
+    assert_connection_refused(ode_internal_encryption_umount);
+    assert_connection_refused(ode_internal_encryption_encrypt, password, options);
+    assert_connection_refused(ode_internal_encryption_decrypt, password);
+    assert_connection_refused(ode_internal_encryption_recovery);
+    assert_connection_refused(ode_internal_encryption_is_password_initialized, &result);
+    assert_connection_refused(ode_internal_encryption_init_password, password);
+    assert_connection_refused(ode_internal_encryption_clean_password, password);
+    assert_connection_refused(ode_internal_encryption_change_password, password, password_new);
+    assert_connection_refused(ode_internal_encryption_verify_password, password, &result);
+    assert_connection_refused(ode_internal_encryption_get_state, &state);
+}
+
+RUNNER_CHILD_TEST(T1021_internal_encryption_permission_denied)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_UNKNOWN is returned "
+                       "instead of the ODE_ERROR_PERMISSION_DENIED. "
+                       "Needs improvement in ode module.");
+
+    TemporaryTestUser adminUserToSwitch("ode_test_T1021_user", GUM_USERTYPE_ADMIN);
+    adminUserToSwitch.create();
+
+    AppInstallHelper appInstallHelper("ode_test_T1021_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");
+
+        unsigned int options = 0;
+        bool result;
+        int state;
+
+        // check if there is access to unprotected function
+        assert_positive(ode_internal_encryption_is_password_initialized, &result);
+        assert_positive(ode_internal_encryption_get_state, &state);
+
+        // check if there is no access to protected function
+        assert_permission_denied(ode_internal_encryption_set_mount_password, password);
+        assert_permission_denied(ode_internal_encryption_mount);
+        assert_permission_denied(ode_internal_encryption_umount);
+        assert_permission_denied(ode_internal_encryption_encrypt, password, options);
+        assert_permission_denied(ode_internal_encryption_decrypt, password);
+        assert_permission_denied(ode_internal_encryption_recovery);
+        assert_permission_denied(ode_internal_encryption_init_password, password);
+        assert_permission_denied(ode_internal_encryption_clean_password, password);
+        assert_permission_denied(ode_internal_encryption_change_password, password, password_new);
+        assert_permission_denied(ode_internal_encryption_verify_password, password, &result);
+    }
+}
+
+} // namespace OdeTestsInternalEncryption
diff --git a/src/ode/ode-tests-keys.cpp b/src/ode/ode-tests-keys.cpp
new file mode 100644 (file)
index 0000000..0fd8d7b
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ *  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.
+ *  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-keys.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <memory>
+
+#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
diff --git a/src/ode/ode-tests-luks.cpp b/src/ode/ode-tests-luks.cpp
new file mode 100644 (file)
index 0000000..6e79858
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *  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-luks.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include "dpl/test/test_runner.h"
+
+RUNNER_TEST_GROUP_INIT(T3000_ODE_API_LUKS);
\ No newline at end of file
diff --git a/src/ode/ode-tests-secure-erase.cpp b/src/ode/ode-tests-secure-erase.cpp
new file mode 100644 (file)
index 0000000..19b62ec
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *  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-secure-erase.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include "dpl/test/test_runner.h"
+
+RUNNER_TEST_GROUP_INIT(T4000_ODE_API_SECURE_ERASE);
\ No newline at end of file
diff --git a/src/ode/ode-tests.cpp b/src/ode/ode-tests.cpp
new file mode 100644 (file)
index 0000000..040d7a9
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  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.
+ *  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-test.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <dpl/test/test_runner.h>
+#include <dpl/log/log.h>
+
+int main (int argc, char *argv[])
+{
+    DPL::Log::LogSystemSingleton::Instance().SetTag("SECURITY_TESTS_ODE");
+    int status = DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
+    return status;
+}