Add unit-tests to hal-api security-certs 37/319337/22
authorJan Wojtkowski <j.wojtkowski@samsung.com>
Fri, 7 Feb 2025 08:34:13 +0000 (09:34 +0100)
committerJan Wojtkowski <j.wojtkowski@samsung.com>
Wed, 19 Feb 2025 13:21:54 +0000 (14:21 +0100)
Change-Id: Ic1372125de800940d7c1159650683b4380770651

CMakeLists.txt
haltest/CMakeLists.txt [new file with mode: 0644]
haltest/main.cpp [new file with mode: 0644]
haltest/security-certs.cpp [new file with mode: 0644]
packaging/hal-api-security.spec

index 2a74b70d3166c50394a94ba4e2e57950af558ea7..8cc24978bc19476f0af458dce67022a882ea1d55 100644 (file)
@@ -44,3 +44,7 @@ INSTALL(
     FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc
     DESTINATION ${LIBDIR}/pkgconfig
 )
+
+IF(HALTEST STREQUAL on)
+    ADD_SUBDIRECTORY(haltest)
+ENDIF()
diff --git a/haltest/CMakeLists.txt b/haltest/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bdf6e68
--- /dev/null
@@ -0,0 +1,29 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
+PROJECT(security-haltests C CXX)
+
+SET(HALAPI_LIBRARY "hal-api-security")
+
+FIND_LIBRARY(
+    HALAPI_LIBRARY
+    NAMES libhal-api-security.so
+    HINTS /usr/lib/hal /usr/lib64/hal
+    REQUIRED)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(TEST_DEPS REQUIRED capi-system-info gmock)
+
+INCLUDE_DIRECTORIES(SYSTEM ${TEST_DEPS_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
+LINK_DIRECTORIES(${TEST_DEPS_LIBRARY_DIRS})
+
+SET(EXTRA_CFLAGS "-Wall -Wextra -Werror")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+SET(SRCS
+    ${CMAKE_SOURCE_DIR}/haltest/main.cpp
+    ${CMAKE_SOURCE_DIR}/haltest/security-certs.cpp)
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${TEST_DEPS_LDFLAGS} ${HALAPI_LIBRARY})
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/hal)
diff --git a/haltest/main.cpp b/haltest/main.cpp
new file mode 100644 (file)
index 0000000..3915055
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+    int ret = -1;
+
+    try {
+        testing::InitGoogleTest(&argc, argv);
+        ret = RUN_ALL_TESTS();
+    } catch (const ::testing::internal::GoogleTestFailureException &e) {
+        std::cout << "GoogleTestFailureException was thrown:" << e.what() << std::endl;
+    } catch (...) {
+        std::cout << "Exception occurred." << std::endl;
+    }
+
+    return ret;
+}
diff --git a/haltest/security-certs.cpp b/haltest/security-certs.cpp
new file mode 100644 (file)
index 0000000..ec95110
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <system_info.h>
+#include <gtest/gtest.h>
+#include <string.h>
+
+#include "hal-security-certs.h"
+
+int check_feature(void)
+{
+    bool is_supported;
+    if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(
+        "http://tizen.org/feature/security.device_certificate", &is_supported))
+        return -1; // error
+    else if (is_supported)
+        return 1; // supported
+    else
+        return 0; // not supported
+}
+
+class SECURITY_CERTS : public testing::Test
+{
+protected:
+    void SetUp() override {
+        int ret;
+        status = check_feature();
+        switch (status) {
+            case 1:
+                ret = hal_security_certs_get_backend();
+                ASSERT_EQ(ret, 0) << "Failed to get security certs backend (" << ret << ")";
+                break;
+            case 0:
+                GTEST_SKIP() << "Device certificate feature not supported, test skipped.";
+                break;
+            case -1:
+                GTEST_FAIL() << "Checking platform feature failed.";
+                break;
+        }
+    };
+
+    void TearDown() override {
+        if (status == 1) {
+            int ret = hal_security_certs_put_backend();
+            EXPECT_EQ(ret, 0) << "Failed to put security certs backend (" << ret << ")";
+        }
+    };
+
+    int status;
+};
+
+TEST_F(SECURITY_CERTS, CreateAndFreeKeyContextPositive)
+{
+    int ret;
+
+    hal_security_certs_context_s context;
+    std::string correct_key_type = "RSA";
+    hal_security_certs_data_s correct_key_type_data_s =
+    {
+        const_cast<char*>(correct_key_type.c_str()),
+        correct_key_type.size()
+    };
+
+    ret = hal_security_certs_create_key_context(&context, correct_key_type_data_s);
+    EXPECT_EQ(ret, 0) << "Failed to create key context (" << ret << ")";
+
+    ret = hal_security_certs_free_key_context(&context);
+    EXPECT_EQ(ret, 0) << "Failed to free key context (" << ret << ")";
+}
+
+TEST_F(SECURITY_CERTS, CreateKeyContextNegative)
+{
+    int ret;
+
+    hal_security_certs_context_s context;
+    std::string wrong_key_type = "error";
+    hal_security_certs_data_s wrong_key_type_data_s =
+    {
+        const_cast<char*>(wrong_key_type.c_str()),
+        wrong_key_type.size()
+    };
+
+    ret = hal_security_certs_create_key_context(&context, wrong_key_type_data_s);
+    EXPECT_EQ(ret, -ENODATA) << "Created wrong key context (" << ret << ")";
+}
+
+TEST_F(SECURITY_CERTS, RequestCertificateChainContextPositive)
+{
+    int ret;
+
+    hal_security_certs_context_s context;
+
+    for (std::string key_type : {"RSA", "ECDSA"})
+    {
+        hal_security_certs_data_s key_type_data_s =
+        {
+            const_cast<char*>(key_type.c_str()),
+            key_type.size()
+        };
+
+        ret = hal_security_certs_create_key_context(&context, key_type_data_s);
+        EXPECT_EQ(ret, 0) << "Failed to create key context (" << ret << ")";
+
+        hal_security_certs_data_s chain;
+        ret = hal_security_certs_request_certificate_chain(&context, &chain);
+        EXPECT_EQ(ret, 0) << "Failed to request certificate chain (" << ret << ")";
+        EXPECT_TRUE(chain.length > 0) << "Certificate chain length is zero";
+        free(chain.buffer);
+
+        ret = hal_security_certs_free_key_context(&context);
+        EXPECT_EQ(ret, 0) << "Failed to free key context (" << ret << ")";
+    }
+}
+
+TEST_F(SECURITY_CERTS, SignCryptoDataPositive)
+{
+    int ret;
+
+    hal_security_certs_context_s context;
+    std::map<hal_security_certs_digest_type_e, int> digest_length_map =
+    {
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_MD2, 128/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_MD4, 128/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_MD5, 128/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_SHA1, 160/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_SHA224, 224/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_SHA256, 256/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_SHA384, 384/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_SHA512, 512/8},
+        {HAL_SECURITY_CERTS_DIGEST_TYPE_RIPEMD160, 160/8}
+    };
+
+    for (std::string key_type : {"RSA", "ECDSA"})
+    {
+
+        hal_security_certs_data_s key_type_data_s =
+        {
+            const_cast<char*>(key_type.c_str()),
+            key_type.size()
+        };
+
+        ret = hal_security_certs_create_key_context(&context, key_type_data_s);
+        EXPECT_EQ(ret, 0) << "Failed to create key context (" << ret << ")";
+
+        for (auto digest : digest_length_map) {
+            char data[digest.second] = {0,};
+            hal_security_certs_data_s message_data_s =
+            {
+                data,
+                sizeof(data)
+            };
+
+            hal_security_certs_data_s signature;
+            hal_security_certs_digest_type_e digest_type = static_cast<hal_security_certs_digest_type_e>(digest.first);
+            ret = hal_security_certs_sign_crypto_data(&context, digest_type, message_data_s, &signature);
+            EXPECT_EQ(ret, 0) << "Failed to sign crypto data (" << ret << ")";
+            EXPECT_TRUE(signature.length > 0) << "Signature length is zero";
+            free(signature.buffer);
+        }
+
+        ret = hal_security_certs_free_key_context(&context);
+        EXPECT_EQ(ret, 0) << "Failed to free key context (" << ret << ")";
+    }
+}
+
+TEST_F(SECURITY_CERTS, SignCryptoDataNegative)
+{
+    int ret;
+
+    hal_security_certs_context_s context;
+    std::string key_type = "RSA";
+    hal_security_certs_data_s key_type_data_s =
+    {
+        const_cast<char*>(key_type.c_str()),
+        key_type.size()
+    };
+
+    ret = hal_security_certs_create_key_context(&context, key_type_data_s);
+    EXPECT_EQ(ret, 0) << "Failed to create key context (" << ret << ")";
+
+    char data[20] = {0,};
+    hal_security_certs_data_s message_data_s =
+    {
+        data,
+        sizeof(data)
+    };
+
+    hal_security_certs_data_s signature;
+    ret = hal_security_certs_sign_crypto_data(
+        &context, HAL_SECURITY_CERTS_DIGEST_TYPE_SHA256, message_data_s, &signature);
+    EXPECT_EQ(ret, -EINVAL) << "Succeded with wrong size of crypto data to sign (" << ret << ")";
+
+    hal_security_certs_digest_type_e wrong_digest_type = static_cast<hal_security_certs_digest_type_e>(-1);
+    ret = hal_security_certs_sign_crypto_data(&context, wrong_digest_type, message_data_s, &signature);
+    EXPECT_EQ(ret, -EINVAL) << "Succeded with wrong digest type to sign crypto data (" << ret << ")";
+
+    ret = hal_security_certs_free_key_context(&context);
+    EXPECT_EQ(ret, 0) << "Failed to free key context (" << ret << ")";
+}
+
+TEST_F(SECURITY_CERTS, GetKeyTypeAndLengthPositive)
+{
+    int ret;
+
+    std::map<std::string, std::pair<hal_security_certs_crypto_key_type_e, unsigned int>> key_map =
+    {
+        {"RSA", {HAL_SECURITY_CERTS_KEY_TYPE_RSA, 1024}},
+        {"ECDSA", {HAL_SECURITY_CERTS_KEY_TYPE_ECDSA, 521}},
+    };
+
+    for (auto key : key_map)
+    {
+        std::string key_type = key.first;
+        hal_security_certs_crypto_key_type_e ret_key_type_enum;
+        unsigned int key_bit_length = key.second.second;
+        hal_security_certs_crypto_key_type_e key_type_enum = key.second.first;
+
+        hal_security_certs_data_s key_type_data_s =
+        {
+            const_cast<char*>(key_type.c_str()),
+            key_type.size()
+        };
+
+        hal_security_certs_context_s context;
+        ret = hal_security_certs_create_key_context(&context, key_type_data_s);
+        EXPECT_EQ(ret, 0) << "Failed to create key context (" << ret << ")";
+
+        ret = hal_security_certs_get_key_type(&context, &ret_key_type_enum);
+        EXPECT_EQ(ret, 0) << "Failed to get key type (" << ret << ")";
+        EXPECT_EQ(ret_key_type_enum, key_type_enum) << "Incorrect key type (" << ret_key_type_enum << ")";
+
+        unsigned int key_length = 0;
+        ret = hal_security_certs_get_key_bit_length(&context, &key_length);
+        EXPECT_EQ(ret, 0) << "Failed to get key bit length (" << ret << ")";
+        EXPECT_EQ(key_length, key_bit_length) << "Incorrect key bit length (" << key_length << ")";
+
+        ret = hal_security_certs_free_key_context(&context);
+        EXPECT_EQ(ret, 0) << "Failed to free key context (" << ret << ")";
+    }
+}
+
+TEST_F(SECURITY_CERTS, ExtCallApiNegative)
+{
+    int ret;
+
+    std::string method_name = "test-method-name";
+    hal_security_certs_data_s method_name_data_s =
+    {
+        const_cast<char*>(method_name.c_str()),
+        method_name.size()
+    };
+
+    hal_security_certs_data_s input_data_s;
+    hal_security_certs_data_s output_data_s;
+
+    ret = hal_security_certs_ext_call_api(method_name_data_s, input_data_s, &output_data_s);
+    EXPECT_EQ(ret, -EINVAL) << "Executesd not exisitng external call api method (" << ret << ")";
+}
+
+TEST_F(SECURITY_CERTS, ExtGetApiPrivilegeNegative)
+{
+    int ret;
+
+    std::string method_name = "test-method-name";
+    hal_security_certs_data_s method_name_data_s =
+    {
+        const_cast<char*>(method_name.c_str()),
+        method_name.size()
+    };
+
+    hal_security_certs_data_s privilege;
+
+    ret = hal_security_certs_ext_get_api_privilege(method_name_data_s, &privilege);
+    EXPECT_EQ(ret, -EINVAL) << "Executesd not exisitng external call api method (" << ret << ")";
+}
index 92dcb099ee2fca42323a105d3ecfdca65671e0e5..38340cf83d58ea0539cec3c3a3266a5cc693ca94 100644 (file)
@@ -26,12 +26,24 @@ Requires:       %{name} = %{version}-%{release}
 %description -n %{name}-devel
 %{name} Interface for product vendor developer
 
+### haltest package #########
+%package -n     %{name}-haltests
+Summary:        %{name} tests
+Group:          Development/Libraries
+Requires:       %{name} = %{version}-%{release}
+BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(gmock)
+
+%description -n %{name}-haltests
+%{name} tests
+
 ### build and install #########
 %prep
 %setup -q
 
 cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
-        -DCMAKE_LIBDIR_PREFIX=%{_libdir}/
+        -DCMAKE_LIBDIR_PREFIX=%{_libdir}/ \
+        -DHALTEST=on
 
 %build
 cp %{SOURCE1} .
@@ -69,3 +81,9 @@ rm -rf %{buildroot}
 %{_includedir}/hal/hal-security-certs*.h
 %{_libdir}/pkgconfig/hal-api-security.pc
 %{_libdir}/hal/lib%{name}.so
+
+%files -n %{name}-haltests
+%defattr(-,root,root,-)
+%manifest %{name}.manifest
+%license LICENSE.Apache-2.0
+%{_bindir}/hal/security-haltests