--- /dev/null
+# Copyright (c) 2017 - 2025 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.
+#
+
+PROJECT(hal-backend-security-auth LANGUAGES C CXX)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
+
+INCLUDE(GNUInstallDirs)
+INCLUDE(CheckLibraryExists)
+
+IF(NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE "RELEASE")
+ENDIF(NOT CMAKE_BUILD_TYPE)
+
+SET(CMAKE_C_FLAGS_DEBUG "-std=c11 -O0 -ggdb -Wp,-U_FORTIFY_SOURCE")
+SET(CMAKE_CXX_FLAGS_DEBUG "-std=c++17 -O0 -ggdb -Wp,-U_FORTIFY_SOURCE")
+SET(CMAKE_C_FLAGS_RELEASE "-std=c11 -O2 -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELEASE "-std=c++17 -O2 -DNDEBUG")
+
+ADD_DEFINITIONS("-Werror -Wall -Wextra -Wno-deprecated-declarations")
+
+SET(CMAKE_POSITION_INDEPENDENT_CODE "True")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
+
+ADD_SUBDIRECTORY(src)
--- /dev/null
+Copyright (c) 2000 - 2025 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+Name: hal-backend-security-auth
+Summary: Security Auth backend library
+Version: 1.0.0
+Release: 0
+Group: Security/Development
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source1001: hal-backend-security-auth.manifest
+BuildRequires: cmake
+BuildRequires: pkgconfig(hal-rootstrap)
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description
+Security Auth backend library
+
+%global rw_data_dir %{?TZ_SYS_DATA:%TZ_SYS_DATA/%name}%{!?TZ_SYS_DATA:/opt/data/auth-fw}
+
+%prep
+%setup -q
+cp -a %{SOURCE1001} .
+
+%build
+%cmake ./ -DHAL_LIB_DIR=%{_hal_libdir} \
+ -DRW_DATA_DIR:PATH=%{rw_data_dir} \
+ -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:Release}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%files
+%manifest hal-backend-security-auth.manifest
+%license LICENSE
+%{_hal_libdir}/lib%{name}.so*
\ No newline at end of file
--- /dev/null
+# Copyright (c) 2017 - 2025 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.
+#
+
+PROJECT(hal-backend-security-auth LANGUAGES C CXX)
+SET(PROJECT_VERSION "1.0.0")
+
+SET(_LIB_VERSION_ "${PROJECT_VERSION}")
+SET(_LIB_SOVERSION_ "0")
+
+FIND_PACKAGE(PkgConfig REQUIRED)
+PKG_CHECK_MODULES(ROOTSTRAP REQUIRED hal-rootstrap)
+
+INCLUDE_DIRECTORIES(SYSTEM ${ROOTSTRAP_INCLUDE_DIRS})
+LINK_DIRECTORIES(${ROOTSTRAP_LIBRARY_DIRS})
+
+FILE(GLOB SRCS ${SRCS} util/*.cpp)
+FILE(GLOB SRCS ${SRCS} *.cpp)
+
+ADD_DEFINITIONS("-DRW_DATA_DIR=\"${RW_DATA_DIR}\"")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${ROOTSTRAP_LIBRARIES} -lcrypto -lssl -ldlog -ldl)
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME}
+ PROPERTIES
+ VERSION ${_LIB_VERSION_}
+ SOVERSION ${_LIB_SOVERSION_}
+ VISIBILITY_INLINES_HIDDEN TRUE
+ C_VISIBILITY_PRESET hidden
+ CXX_VISIBILITY_PRESET hidden)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${HAL_LIB_DIR} COMPONENT RuntimeLibraries)
--- /dev/null
+/******************************************************************
+ * Copyright 2017 - 2025 Samsung Electronics 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.
+ *
+ ******************************************************************/
+
+#include <chrono>
+#include <fstream>
+#include <algorithm>
+#include <fcntl.h>
+#include <ratio>
+#include <string>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <hal/hal-security-auth-error.h>
+
+#include "util/ipassword.h"
+#include "util/log.h"
+#include "util/fstream_accessors.h"
+#include "util/error-description.h"
+#include "util/password-file-buffer.h"
+#include "hal_backend_security_auth.h"
+
+namespace {
+ const unsigned int PASSWORD_INFINITE_ATTEMPT_COUNT = 0;
+ const unsigned int PASSWORD_INFINITE_EXPIRATION_DAYS = 0;
+ const std::string PASSWORD_FILE = "/password";
+ const std::string OLD_VERSION_PASSWORD_FILE = "/password.old";
+ const std::string ATTEMPT_FILE = "/attempt";
+ const double RETRY_TIMEOUT = 0.5;
+ const mode_t FILE_MODE = S_IRUSR | S_IWUSR;
+ const unsigned int CURRENT_FILE_VERSION = 5;
+ const unsigned int PASSWORD_API_NO_EXPIRATION = 0xFFFFFFFF;
+} // namespace anonymous
+
+hal_backend_security_auth::hal_backend_security_auth(uid_t user_id, hal_security_auth_password_type_e password_type):
+ m_user(user_id),
+ m_passwordType(password_type),
+ m_passwordCurrent(new NoPassword()),
+ m_maxHistorySize(0),
+ m_expireTime(PASSWORD_INFINITE_EXPIRATION_DAYS),
+ m_expireTimeLeft(PASSWORD_INFINITE_EXPIRATION_TIME),
+ m_passwordActive(false),
+ m_passwordRcvActive(false),
+ m_attempt(0)
+{
+ m_maxAttempt = PASSWORD_INFINITE_ATTEMPT_COUNT;
+
+ LOGD("hal_backend_security_auth constructor user_id : "<< user_id << ", password_type : " << password_type);
+ LOGD(" default value max_attempt : "<< m_maxAttempt << ", max_history_size : " << m_maxHistorySize);
+ LOGD(" expire_time : "<< m_expireTime << ", expire_time_left : " << m_expireTimeLeft << ", password_is_active : " << m_passwordActive);
+ LOGD(" password_is_rcv_active : "<< m_passwordRcvActive << ", attempt : " << m_attempt);
+
+ std::string userDir = create_dir(RW_DATA_DIR, m_user);
+
+ if (!dir_exists(RW_DATA_DIR)) {
+ if (mkdir(RW_DATA_DIR, 0700)) {
+ LOGE(" Failed to create directory for files. Error: " << errnoToString());
+ }
+ }
+
+ if (!dir_exists(userDir.c_str())) {
+ if (mkdir(userDir.c_str(), 0700)) {
+ LOGE(" Failed to create directory for files. Error: " << errnoToString());
+ }
+ }
+
+ prepare_password_file();
+ prepare_attempt_file();
+ reset_timer();
+}
+
+bool hal_backend_security_auth::file_exists(const std::string &filename) const
+{
+ struct stat buf;
+ return ((stat(filename.c_str(), &buf) == 0));
+}
+
+bool hal_backend_security_auth::dir_exists(const std::string &dirpath) const
+{
+ struct stat buf;
+ return ((stat(dirpath.c_str(), &buf) == 0) && (((buf.st_mode) & S_IFMT) == S_IFDIR));
+}
+
+std::string hal_backend_security_auth::create_dir(const std::string &dir, unsigned int user) const
+{
+ std::string User = std::to_string(user);
+ return dir + "/" + User;
+}
+
+void hal_backend_security_auth::reset_state()
+{
+ m_maxAttempt = PASSWORD_INFINITE_ATTEMPT_COUNT;
+ m_maxHistorySize = 0;
+ m_expireTime = PASSWORD_INFINITE_EXPIRATION_DAYS;
+ m_expireTimeLeft = PASSWORD_INFINITE_EXPIRATION_TIME;
+ m_passwordRcvActive = false;
+ m_passwordActive = false;
+ m_passwordCurrent.reset(new NoPassword());
+}
+
+
+void hal_backend_security_auth::reset_timer()
+{
+ m_retryTimerStart = ClockType::now();
+ m_retryTimerStart -= TimeDiff(RETRY_TIMEOUT);
+}
+
+bool hal_backend_security_auth::load_memory_from_file(const std::string& passwdFilePath)
+{
+ struct stat fileStat;
+
+ if (stat(passwdFilePath.c_str(), &fileStat) != 0)
+ return false;
+
+ PasswordFileBuffer pwdBuffer;
+ pwdBuffer.Load(passwdFilePath);
+ unsigned int fileVersion = 0;
+ Deserialization::Deserialize(pwdBuffer, fileVersion);
+
+ switch (fileVersion) {
+ case 1:
+ case 2:
+ case 3:
+ Deserialization::Deserialize(pwdBuffer, m_maxAttempt);
+ Deserialization::Deserialize(pwdBuffer, m_maxHistorySize);
+ Deserialization::Deserialize(pwdBuffer, m_expireTimeLeft);
+ Deserialization::Deserialize(pwdBuffer, m_passwordActive);
+ Deserialization::Deserialize(pwdBuffer, m_passwordCurrent);
+ Deserialization::Deserialize(pwdBuffer, m_passwordHistory);
+ m_expireTime = PASSWORD_INFINITE_EXPIRATION_DAYS;
+ m_passwordRcvActive = false;
+ m_passwordType = hal_security_auth_password_type_e::HAL_SECURITY_AUTH_PASSWORD_NORMAL; // Normal
+ // update file to new format
+ write_memory_to_file(m_user);
+ break;
+ case 4:
+ Deserialization::Deserialize(pwdBuffer, m_maxAttempt);
+ Deserialization::Deserialize(pwdBuffer, m_maxHistorySize);
+ Deserialization::Deserialize(pwdBuffer, m_expireTime);
+ Deserialization::Deserialize(pwdBuffer, m_expireTimeLeft);
+ Deserialization::Deserialize(pwdBuffer, m_passwordRcvActive);
+ Deserialization::Deserialize(pwdBuffer, m_passwordActive);
+ Deserialization::Deserialize(pwdBuffer, m_passwordCurrent);
+ Deserialization::Deserialize(pwdBuffer, m_passwordHistory);
+ m_passwordType = hal_security_auth_password_type_e::HAL_SECURITY_AUTH_PASSWORD_NORMAL; // Normal
+ break;
+ default:
+ LOGE("Invaild password version: " << fileVersion);
+ }
+
+ LOGD("loadMemoryFromFile: File=" << passwdFilePath <<
+ ":: User: " << m_user << ", loaded max_att: " << m_maxAttempt <<
+ ", history_size: " << m_maxHistorySize << ", m_expireTime: " <<
+ m_expireTime << ", m_expireTimeLeft: " << m_expireTimeLeft <<
+ ", isActive: " << m_passwordActive << ", isRcvActive: " <<
+ m_passwordRcvActive<< ", m_passwordType: " << m_passwordType);
+ return true;
+}
+
+void hal_backend_security_auth::prepare_password_file()
+{
+ std::string pwdFile = create_dir(RW_DATA_DIR, m_user) + PASSWORD_FILE;
+ std::string oldVersionPwdFile = create_dir(RW_DATA_DIR, m_user) + OLD_VERSION_PASSWORD_FILE;
+
+ // check if password file exists
+ if (!file_exists(pwdFile)) {
+ // if old format file exist - load it
+ if (load_memory_from_file(oldVersionPwdFile)) {
+ // save in new format
+ write_memory_to_file(m_user);
+
+ // and remove old file
+ if (remove(oldVersionPwdFile.c_str())) {
+ LOGE("Failed to remove file" << oldVersionPwdFile <<
+ " Error: " << errnoToString());
+ }
+ return;
+ }
+
+ LOGE("PWD_DBG not found " << m_user << " password file. Creating.");
+ //create file
+ write_memory_to_file(m_user);
+ } else { //if file exists, load data
+ LOGE("PWD_DBG found " << m_user << " password file. Opening.");
+
+ try {
+ load_memory_from_file(oldVersionPwdFile);
+ } catch (...) {
+ LOGE("Invalid " << pwdFile << " file format");
+ reset_state();
+ write_memory_to_file(m_user);
+ }
+ }
+}
+
+void hal_backend_security_auth::prepare_attempt_file()
+{
+ std::string attemptFile = create_dir(RW_DATA_DIR, m_user) + ATTEMPT_FILE;
+
+ // check if attempt file exists
+ if (!file_exists(attemptFile)) {
+ LOGE("PWD_DBG not found " << m_user << " attempt file. Creating.");
+ write_attempt_to_file(m_user);
+ } else {
+ LOGE("PWD_DBG found " << m_user << " attempt file. Opening.");
+ std::ifstream AttemptFile(attemptFile);
+
+ if (!AttemptFile) {
+ LOGE("Failed to open " << m_user << " attempt file.");
+ // ignore error
+ return;
+ }
+
+ AttemptFile.read(reinterpret_cast<char *>(&m_attempt), sizeof(unsigned int));
+
+ if (!AttemptFile) {
+ LOGE("Failed to read " << m_user << " attempt count.");
+ // ignore error
+ reset_attempt(m_user);
+ }
+ }
+}
+
+int hal_backend_security_auth::write_memory_to_file(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::write_memory_to_file");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ std::string pwdFile = create_dir(RW_DATA_DIR, m_user) + PASSWORD_FILE;
+ PasswordFileBuffer pwdBuffer;
+ LOGD(" user: " << m_user << ", max_attempt: " << m_maxAttempt <<
+ ", history_size: " << m_maxHistorySize << ", m_expireTime: " <<
+ m_expireTime << ", m_expireTimeLeft: " << m_expireTimeLeft <<
+ ", isActive: " << m_passwordActive << ", isRcvActive: " <<
+ m_passwordRcvActive << ", m_passwordType: " << m_passwordType);
+ //serialize password attributes
+ Serialization::Serialize(pwdBuffer, CURRENT_FILE_VERSION);
+ Serialization::Serialize(pwdBuffer, m_maxAttempt);
+ Serialization::Serialize(pwdBuffer, m_maxHistorySize);
+ Serialization::Serialize(pwdBuffer, m_expireTime);
+ Serialization::Serialize(pwdBuffer, m_expireTimeLeft);
+ Serialization::Serialize(pwdBuffer, m_passwordRcvActive);
+ Serialization::Serialize(pwdBuffer, m_passwordActive);
+ Serialization::Serialize(pwdBuffer, m_passwordCurrent);
+ Serialization::Serialize(pwdBuffer, m_passwordHistory);
+ Serialization::Serialize(pwdBuffer, m_passwordType);
+
+ pwdBuffer.Save(pwdFile);
+ if (chmod(pwdFile.c_str(), FILE_MODE)) {
+ LOGE(" Failed to chmod for " << pwdFile << " Error: " << errnoToString());
+ }
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::write_attempt_to_file(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::write_attempt_to_file");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ std::string attemptFile = create_dir(RW_DATA_DIR, m_user) + ATTEMPT_FILE;
+ std::ofstream AttemptFile(attemptFile, std::ofstream::trunc);
+
+ if (!AttemptFile.good()) {
+ LOGE(" Failed to open " << m_user << " attempt file.");
+ }
+
+ AttemptFile.write(reinterpret_cast<const char *>(&m_attempt), sizeof(unsigned int));
+
+ if (!AttemptFile) {
+ LOGE(" Failed to write " << m_user << " attempt count.");
+ }
+
+ AttemptFile.flush();
+ if (::fsync(FstreamAccessors<std::ofstream>::GetFd(AttemptFile)) != 0)
+ LOGE(" Failed to synchronize a file's state.");
+ AttemptFile.close();
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::set_password(uid_t user_id, const char* password)
+{
+ LOGD("hal_backend_security_auth::set_password");
+ if(user_id != m_user || password == nullptr)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ if (password[0] == '\0') {
+ m_passwordCurrent.reset(new NoPassword());
+ m_passwordActive = false;
+ } else {
+ std::string password_str = std::string(password);
+ m_passwordCurrent.reset(new SHA256Password(password_str));
+ //put current password to history
+ m_passwordHistory.push_front(m_passwordCurrent);
+
+ //erase last password if we exceed max history size
+ if (m_passwordHistory.size() > m_maxHistorySize)
+ m_passwordHistory.pop_back();
+
+ m_passwordActive = true;
+ }
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::check_password(uid_t user_id, const char* password)
+{
+ LOGD("hal_backend_security_auth::check_password");
+ if(user_id != m_user || password == nullptr)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ return m_passwordCurrent->match(password) ? AUTH_PASSWD_API_SUCCESS : AUTH_PASSWD_API_ERROR_PASSWORD_MISMATCH;
+}
+
+int hal_backend_security_auth::set_max_history_size(uid_t user_id, unsigned int history_size)
+{
+ LOGD("hal_backend_security_auth::set_max_history_size");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ // put current password in history
+ if (m_maxHistorySize == 0 && history_size > 0)
+ m_passwordHistory.push_front(m_passwordCurrent);
+
+ //setting history should be independent from password being set
+ m_maxHistorySize = history_size;
+
+ while (m_passwordHistory.size() > history_size)
+ m_passwordHistory.pop_back();
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::get_max_history_size(uid_t user_id, unsigned int *history_size) const
+{
+ LOGD("hal_backend_security_auth::get_max_history_size");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ *history_size = m_maxHistorySize;
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::get_expire_time(uid_t user_id, unsigned int *expire_time) const
+{
+ LOGD("hal_backend_security_auth::get_expire_time");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ *expire_time = m_expireTime;
+ LOGE(" *expire_time : "<<m_expireTime);
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::set_expire_time(uid_t user_id, unsigned int expire_time)
+{
+ LOGD("hal_backend_security_auth::set_expire_time m_expireTime: " << m_expireTime);
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ m_expireTime = expire_time;
+ LOGD(" expire_time : "<< m_expireTime);
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::get_attempt(uid_t user_id, unsigned int *attempt) const
+{
+ LOGD("hal_backend_security_auth::get_attempt");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ *attempt = m_attempt;
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::set_expire_time_left(uid_t user_id, unsigned int expire_time_left)
+{
+ LOGD("hal_backend_security_auth::set_expire_time_left");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ m_expireTimeLeft = expire_time_left;
+ LOGD(" expire_time_left : "<<m_expireTimeLeft);
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::get_expire_time_left(uid_t user_id, unsigned int *expire_time_left) const
+{
+ LOGD("hal_backend_security_auth::get_expire_time_left");
+ //calculate left secs by the time of password expiration
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ if (m_expireTimeLeft != PASSWORD_INFINITE_EXPIRATION_TIME) {
+ LOGD(" not eq m_expireTimeLeft : " << m_expireTimeLeft << " PIET : " << PASSWORD_INFINITE_EXPIRATION_TIME);
+
+ time_t timeLeft = m_expireTimeLeft - time(NULL);
+ *expire_time_left = (timeLeft < 0) ? 0 : static_cast<unsigned int>(timeLeft);
+ LOGD(" not eq expire_time_left : " << *expire_time_left << " timeLeft : " << timeLeft);
+
+ } else {
+ *expire_time_left = PASSWORD_API_NO_EXPIRATION;
+ LOGD(" expire_time_left : " << *expire_time_left);
+
+ }
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::reset_attempt(uid_t user_id)
+{
+ LOGD("hal_backend_security_auth::reset_attempt");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ m_attempt = 0;
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::increment_attempt(uid_t user_id)
+{
+ LOGD("hal_backend_security_auth::increment_attempt");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ m_attempt++;
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::get_max_attempt(uid_t user_id, unsigned int *max_attempt) const
+{
+ LOGD("hal_backend_security_auth::get_max_attempt");
+
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ *max_attempt = m_maxAttempt;
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::set_max_attempt(uid_t user_id, unsigned int max_attempt)
+{
+ LOGD("hal_backend_security_auth::set_max_attempt");
+
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ m_maxAttempt = max_attempt;
+
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::is_password_active(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::is_password_active");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ return m_passwordActive ? AUTH_PASSWD_API_SUCCESS : AUTH_PASSWD_API_ERROR_STATUS;
+}
+
+int hal_backend_security_auth::is_password_reused(uid_t user_id, const char* password) const
+{
+ LOGD("hal_backend_security_auth::is_password_reused");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ LOGD(" user_id : "<< m_user << " history_size: " <<
+ m_passwordHistory.size() << ", max_history_size: " << m_maxHistorySize);
+
+ // go through history and check if password existed earlier
+ if (std::any_of(
+ m_passwordHistory.begin(),
+ m_passwordHistory.end(),
+ [&password](const IPasswordPtr & pwd) {
+ return pwd->match(password);
+ })) {
+ LOGE(" password match!");
+ return AUTH_PASSWD_API_SUCCESS;
+ }
+
+ LOGE(" Failed isPasswordReused: No passwords match");
+ return AUTH_PASSWD_API_ERROR_STATUS;
+}
+
+int hal_backend_security_auth::check_expiration(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::check_expiration");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ LOGD(" m_expireTimeLeft : " << m_expireTimeLeft << " PIET : "<< PASSWORD_INFINITE_EXPIRATION_TIME << " time: " << time(NULL) << " m_eTLeft : " << m_expireTimeLeft);
+ return ((m_expireTimeLeft != PASSWORD_INFINITE_EXPIRATION_TIME) && (time(NULL) > m_expireTimeLeft)) ? AUTH_PASSWD_API_ERROR_PASSWORD_EXPIRED : AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::check_attempt_exceeded(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::check_attempt_exceeded");
+ LOGD(" m_maxAttempt : " << m_maxAttempt << " P_I_A_C : " << PASSWORD_INFINITE_ATTEMPT_COUNT << " m_attempt : " << m_attempt);
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ return ((m_maxAttempt != PASSWORD_INFINITE_ATTEMPT_COUNT) && (m_attempt > m_maxAttempt)) ? AUTH_PASSWD_API_ERROR_PASSWORD_MAX_ATTEMPTS_EXCEEDED : AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::is_ignore_period(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::is_ignore_period");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ TimePoint retryTimerStop = ClockType::now();
+ TimeDiff diff = retryTimerStop - m_retryTimerStart;
+
+ m_retryTimerStart = retryTimerStop;
+ return (diff.count() < RETRY_TIMEOUT) ? AUTH_PASSWD_API_SUCCESS : AUTH_PASSWD_API_ERROR_PASSWORD_RETRY_TIMER;
+}
+
+int hal_backend_security_auth::is_history_active(uid_t user_id) const
+{
+ LOGD("hal_backend_security_auth::is_history_active");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ return (m_maxHistorySize != 0) ? AUTH_PASSWD_API_SUCCESS : AUTH_PASSWD_API_ERROR_STATUS;
+}
+
+int hal_backend_security_auth::get_password_type(uid_t user_id,
+ hal_security_auth_password_type_e *password_type) const
+{
+ LOGD("hal_backend_security_auth::get_password_type");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ *password_type = m_passwordType;
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+int hal_backend_security_auth::set_password_type(uid_t user_id,
+ hal_security_auth_password_type_e password_type)
+{
+ LOGD("hal_backend_security_auth::set_password_type");
+ if(user_id != m_user)
+ return AUTH_PASSWD_API_ERROR_INPUT_PARAM;
+ m_passwordType = password_type;
+ return AUTH_PASSWD_API_SUCCESS;
+}
+
+uid_t hal_backend_security_auth::get_user_id() const
+{
+ LOGD("hal_backend_security_auth::get_user_id");
+ uid_t user_id = getuid();
+ return user_id;
+}
+
+hal_backend_security_auth::~hal_backend_security_auth()
+{
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static std::map<uid_t, hal_backend_security_auth*> hal_backend_security_auth_instance_map;
+
+hal_backend_security_auth* get_hal_backend_security_auth_instance(uid_t user_id, hal_security_auth_password_type_e password_type)
+{
+ hal_security_auth_password_type_e current_password_type;
+ auto itAuth = hal_backend_security_auth_instance_map.find(user_id);
+ LOGD("get_hal_backend_security_auth_instance");
+
+ if (itAuth != hal_backend_security_auth_instance_map.end()){
+ hal_backend_security_auth *authInstance = itAuth->second;
+ authInstance->get_password_type(user_id, ¤t_password_type);
+ if(current_password_type == password_type){
+ LOGD(" found the user and the same type");
+ return authInstance;
+ }
+ else{
+ authInstance->set_password_type(user_id, password_type);
+ LOGD(" found the user and the diffent type, so changed.");
+ return authInstance;
+ }
+ }
+
+ LOGD(" Not found and created a new instance");
+ hal_backend_security_auth* new_security_auth = new hal_backend_security_auth(user_id,password_type);
+ hal_backend_security_auth_instance_map[user_id] = new_security_auth;
+ return new_security_auth;
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ * Copyright 2017 - 2025 Samsung Electronics 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.
+ *
+ ******************************************************************/
+
+#ifndef BACKEND_HAL_BACKEND_SECURITY_AUTH_H_
+#define BACKEND_HAL_BACKEND_SECURITY_AUTH_H_
+
+#include <string>
+#include <map>
+#include <memory>
+#include <chrono>
+#include <time.h>
+#include <hal/hal-security-auth-interface.h>
+#include <hal/hal-security-auth-types.h>
+
+#include "util/ipassword-file.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+class hal_backend_security_auth : public IPasswordFile {
+ public:
+ hal_backend_security_auth(uid_t user_id, hal_security_auth_password_type_e password_type);
+ ~hal_backend_security_auth();
+
+ hal_backend_security_auth(const hal_backend_security_auth&) = delete;
+ hal_backend_security_auth& operator=(const hal_backend_security_auth&) = delete;
+
+ int write_memory_to_file(uid_t user_id) const override;
+
+ int write_attempt_to_file(uid_t user_id) const override;
+
+ int set_password(uid_t user_id, const char* password) override;
+
+ int check_password(uid_t user_id, const char* password) override;
+
+ int set_max_history_size(uid_t user_id, unsigned int history_size) override;
+
+ int get_max_history_size(uid_t user_id, unsigned int *history_size) const override;
+
+ int get_expire_time(uid_t user_id, unsigned int *expire_time) const override;
+
+ int set_expire_time(uid_t user_id, unsigned int expire_time) override;
+
+ int get_attempt(uid_t user_id, unsigned int *attempt) const override;
+
+ int reset_attempt(uid_t user_id) override;
+
+ int increment_attempt(uid_t user_id) override;
+
+ int get_max_attempt(uid_t user_id, unsigned int *max_attempt) const override;
+
+ int set_max_attempt(uid_t user_id, unsigned int max_attempt) override;
+
+ int get_expire_time_left(uid_t user_id, unsigned int *expire_time_left) const override;
+
+ int set_expire_time_left(uid_t user_id, unsigned int expire_time_left) override;
+
+ int is_password_active(uid_t user_id) const override;
+
+ int is_password_reused(uid_t user_id, const char* password)const override;
+
+ int check_expiration(uid_t user_id) const override;
+
+ int check_attempt_exceeded(uid_t user_id) const override;
+
+ int is_ignore_period(uid_t user_id) const override;
+
+ int is_history_active(uid_t user_id) const override;
+
+ int get_password_type(uid_t user_id, hal_security_auth_password_type_e *password_type) const override;
+
+ uid_t get_user_id() const override;
+
+ int set_password_type(uid_t user_id, hal_security_auth_password_type_e password_type);
+
+ int reset_password(uid_t user_id);
+
+ private:
+ hal_security_auth_password_type_e password_type;
+ uid_t user_id;
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7))
+ typedef std::chrono::steady_clock ClockType;
+#else
+ typedef std::chrono::monotonic_clock ClockType;
+#endif
+ typedef std::chrono::duration<double> TimeDiff;
+ typedef std::chrono::time_point<ClockType, TimeDiff> TimePoint;
+
+ bool load_memory_from_file(const std::string &passwdFilePath);
+ void reset_timer();
+ void prepare_password_file();
+ void prepare_attempt_file();
+ void reset_state();
+ bool file_exists(const std::string &filename) const;
+ bool dir_exists(const std::string &dirpath) const;
+ unsigned int get_max_history_size() const;
+ std::string create_dir(const std::string &dir, unsigned int user) const;
+
+ mutable TimePoint m_retryTimerStart;
+
+ const uid_t m_user;
+ hal_security_auth_password_type_e m_passwordType;
+ IPasswordPtr m_passwordCurrent;
+ PasswordList m_passwordHistory;
+ unsigned int m_maxAttempt;
+ unsigned int m_maxHistorySize;
+ unsigned int m_expireTime;
+ time_t m_expireTimeLeft;
+ bool m_passwordActive;
+ bool m_passwordRcvActive;
+ unsigned int m_attempt;
+};
+
+hal_backend_security_auth* get_hal_backend_security_auth_instance(uid_t user_id, hal_security_auth_password_type_e password_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BACKEND_HAL_BACKEND_SECURITY_AUTH_H_ */
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ * Copyright 2019 - 2025 Samsung Electronics 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.
+ *
+ ******************************************************************/
+
+#include <hal/hal-common-interface.h>
+
+#include "util/log.h"
+#include "hal_backend_security_auth.h"
+
+#define EXPORT __attribute__ ((visibility("default")))
+
+static hal_backend_security_auth *g_auth_instance = nullptr;
+
+int security_auth_create_password_file(uid_t user_id,
+ hal_security_auth_password_type_e password_type)
+{
+ LOGD("security_auth_create_password_file");
+ g_auth_instance = get_hal_backend_security_auth_instance(user_id, password_type);
+ return g_auth_instance ? 0: -ENOTSUP;
+}
+
+int security_auth_write_memory_to_file(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->write_memory_to_file(user_id) : -ENOTSUP;
+}
+
+int security_auth_write_attempt_to_file(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->write_attempt_to_file(user_id) : -ENOTSUP;
+}
+
+int security_auth_set_password(uid_t user_id, const char* password)
+{
+ return g_auth_instance ? g_auth_instance->set_password(user_id, password) : -ENOTSUP;
+}
+
+int security_auth_check_password(uid_t user_id, const char* password)
+{
+ return g_auth_instance ? g_auth_instance->check_password(user_id, password) : -ENOTSUP;
+}
+
+int security_auth_set_max_history_size(uid_t user_id, unsigned int history_size)
+{
+ return g_auth_instance ? g_auth_instance->set_max_history_size(user_id, history_size) : -ENOTSUP;
+}
+
+int security_auth_get_max_history_size(uid_t user_id, unsigned int *history_size)
+{
+ return g_auth_instance ? g_auth_instance->get_max_history_size(user_id, history_size) : -ENOTSUP;
+}
+
+int security_auth_get_expire_time(uid_t user_id, unsigned int *expire_time)
+{
+ return g_auth_instance ? g_auth_instance->get_expire_time(user_id, expire_time) : -ENOTSUP;
+}
+
+int security_auth_set_expire_time(uid_t user_id, unsigned int expire_time)
+{
+ return g_auth_instance ? g_auth_instance->set_expire_time(user_id, expire_time) : -ENOTSUP;
+}
+
+int security_auth_get_attempt(uid_t user_id, unsigned int *attempt)
+{
+ return g_auth_instance ? g_auth_instance->get_attempt(user_id, attempt) : -ENOTSUP;
+}
+
+int security_auth_reset_attempt(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->reset_attempt(user_id) : -ENOTSUP;
+}
+
+int security_auth_increment_attempt(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->increment_attempt(user_id) : -ENOTSUP;
+}
+
+int security_auth_get_max_attempt(uid_t user_id, unsigned int *max_attempt)
+{
+ return g_auth_instance ? g_auth_instance->get_max_attempt(user_id, max_attempt) : -ENOTSUP;
+}
+
+int security_auth_set_max_attempt(uid_t user_id, unsigned int max_attempt)
+{
+ return g_auth_instance ? g_auth_instance->set_max_attempt(user_id, max_attempt) : -ENOTSUP;
+}
+
+int security_auth_get_expire_time_left(uid_t user_id, unsigned int *expire_time_left)
+{
+ return g_auth_instance ? g_auth_instance->get_expire_time_left(user_id, expire_time_left) : -ENOTSUP;
+}
+
+int security_auth_set_expire_time_left(uid_t user_id, unsigned int expire_time_left)
+{
+ return g_auth_instance ? g_auth_instance->set_expire_time_left(user_id, expire_time_left) : -ENOTSUP;
+}
+
+int security_auth_is_password_active(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->is_password_active(user_id) : -ENOTSUP;
+}
+
+int security_auth_is_password_reused(uid_t user_id, const char* password)
+{
+ return g_auth_instance ? g_auth_instance->is_password_reused(user_id, password) : -ENOTSUP;
+}
+
+int security_auth_check_expiration(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->check_expiration(user_id) : -ENOTSUP;
+}
+
+int security_auth_check_attempt_exceeded(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->check_attempt_exceeded(user_id) : -ENOTSUP;
+}
+
+int security_auth_is_ignore_period(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->is_ignore_period(user_id) : -ENOTSUP;
+}
+
+int security_auth_is_history_active(uid_t user_id)
+{
+ return g_auth_instance ? g_auth_instance->is_history_active(user_id) : -ENOTSUP;
+}
+
+int security_auth_get_password_type(uid_t user_id,
+ hal_security_auth_password_type_e *password_type)
+{
+ return g_auth_instance ? g_auth_instance->get_password_type(user_id, password_type) : -ENOTSUP;
+}
+
+static int security_auth_backend_init(void **data)
+{
+ hal_backend_security_auth_funcs *security_auth_funcs;
+
+ if (!data) {
+ return -EINVAL;
+ }
+
+ security_auth_funcs = *(hal_backend_security_auth_funcs **)data;
+ if (!security_auth_funcs)
+ return -EINVAL;
+
+ security_auth_funcs->create_password_file = security_auth_create_password_file;
+ security_auth_funcs->write_memory_to_file = security_auth_write_memory_to_file;
+ security_auth_funcs->write_attempt_to_file = security_auth_write_attempt_to_file;
+ security_auth_funcs->set_password = security_auth_set_password;
+ security_auth_funcs->check_password = security_auth_check_password;
+ security_auth_funcs->set_max_history_size = security_auth_set_max_history_size;
+ security_auth_funcs->get_max_history_size = security_auth_get_max_history_size;
+ security_auth_funcs->get_expire_time = security_auth_get_expire_time;
+ security_auth_funcs->set_expire_time = security_auth_set_expire_time;
+ security_auth_funcs->get_attempt = security_auth_get_attempt;
+ security_auth_funcs->reset_attempt = security_auth_reset_attempt;
+ security_auth_funcs->increment_attempt = security_auth_increment_attempt;
+ security_auth_funcs->get_max_attempt = security_auth_get_max_attempt;
+ security_auth_funcs->get_expire_time_left = security_auth_get_expire_time_left;
+ security_auth_funcs->set_expire_time_left = security_auth_set_expire_time_left;
+ security_auth_funcs->set_max_attempt = security_auth_set_max_attempt;
+ security_auth_funcs->check_attempt_exceeded = security_auth_check_attempt_exceeded;
+ security_auth_funcs->is_password_active = security_auth_is_password_active;
+ security_auth_funcs->is_history_active = security_auth_is_history_active;
+ security_auth_funcs->is_password_reused = security_auth_is_password_reused;
+ security_auth_funcs->check_expiration = security_auth_check_expiration;
+ security_auth_funcs->is_ignore_period = security_auth_is_ignore_period;
+ security_auth_funcs->get_password_type = security_auth_get_password_type;
+
+ return 0;
+}
+
+static int security_auth_backend_exit(void *data)
+{
+ (void)data;
+ return 0;
+}
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+hal_backend EXPORT hal_backend_security_auth_data = {
+ .name = "backend_security_auth",
+ .vendor = "Samsung",
+ .init = security_auth_backend_init,
+ .exit = security_auth_backend_exit,
+ .major_version = 1,
+ .minor_version = 0,
+};
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2025 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 error-description.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Implementatin of errorToString function.
+ */
+
+#include <string.h>
+
+#include "error-description.h"
+#include "symbol-visibility.h"
+
+#define MAX_BUF 256
+
+COMMON_API
+std::string errnoToString(int err)
+{
+ char buffer[MAX_BUF] = {};
+#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
+
+ if (0 == strerror_r(err, buffer, MAX_BUF))
+ return std::string(buffer);
+
+#else
+ char *result = strerror_r(err, buffer, MAX_BUF);
+
+ if (result)
+ return std::string(result);
+
+#endif
+ return std::string();
+}
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2025 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 error-description.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Implementatin of errorToString function.
+ */
+#ifndef _AUTH_PASSWD_ERROR_DESCRIPTION_
+#define _AUTH_PASSWD_ERROR_DESCRIPTION_
+
+#include <string>
+#include <cerrno>
+
+std::string errnoToString(int err = errno);
+
+#endif // _AUTH_PASSWD_ERROR_DESCRIPTION_
--- /dev/null
+/*
+ * Copyright (c) 2025 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 exception.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief Header file for base exception
+ */
+
+#ifndef AUTH_PASSWD_EXCEPTION_H
+#define AUTH_PASSWD_EXCEPTION_H
+
+#include <string>
+#include <cstring>
+#include <cstdio>
+#include <exception>
+#include <cstdlib>
+#include <sstream>
+#include "symbol-visibility.h"
+
+
+void LogUnhandledException(const std::string &str);
+void LogUnhandledException(const std::string &str,
+ const char *filename,
+ int line,
+ const char *function);
+
+class COMMON_API Exception {
+ private:
+ static unsigned int m_exceptionCount;
+ static Exception *m_lastException;
+ static void (*m_terminateHandler)();
+
+ static void AddRef(Exception *exception) {
+ if (!m_exceptionCount)
+ m_terminateHandler = std::set_terminate(&TerminateHandler);
+
+ ++m_exceptionCount;
+ m_lastException = exception;
+ }
+
+ static void UnRef(Exception *e) {
+ if (m_lastException == e)
+ m_lastException = NULL;
+
+ --m_exceptionCount;
+
+ if (!m_exceptionCount) {
+ std::set_terminate(m_terminateHandler);
+ m_terminateHandler = NULL;
+ }
+ }
+
+ static void TerminateHandler() {
+ if (m_lastException != NULL) {
+ DisplayKnownException(*m_lastException);
+ abort();
+ } else {
+ DisplayUnknownException();
+ abort();
+ }
+ }
+
+ Exception *m_reason;
+ std::string m_path;
+ std::string m_function;
+ int m_line;
+
+ protected:
+ std::string m_message;
+ std::string m_className;
+
+ public:
+ static std::string KnownExceptionToString(const Exception &e) {
+ std::ostringstream message;
+ message <<
+ "\033[1;5;31m\n=== Unhandled Exception occurred ===\033[m\n\n";
+ message << "\033[1;33mException trace:\033[m\n\n";
+ message << e.DumpToString();
+ message << "\033[1;31m\n=== Will now abort ===\033[m\n";
+ return message.str();
+ }
+
+ static std::string UnknownExceptionToString() {
+ std::ostringstream message;
+ message <<
+ "\033[1;5;31m\n=== Unhandled Non-exception occurred ===\033[m\n\n";
+ message << "\033[1;31m\n=== Will now abort ===\033[m\n";
+ return message.str();
+ }
+
+ static void DisplayKnownException(const Exception &e) {
+ LogUnhandledException(KnownExceptionToString(e).c_str());
+ }
+
+ static void DisplayUnknownException() {
+ LogUnhandledException(UnknownExceptionToString().c_str());
+ }
+
+ Exception(const Exception &other) {
+ // Deep copy
+ if (other.m_reason != NULL)
+ m_reason = new Exception(*other.m_reason);
+ else
+ m_reason = NULL;
+
+ m_message = other.m_message;
+ m_path = other.m_path;
+ m_function = other.m_function;
+ m_line = other.m_line;
+ m_className = other.m_className;
+ AddRef(this);
+ }
+
+ Exception &operator =(const Exception &other) {
+ if (this == &other)
+ return *this;
+
+ // Deep copy
+ if (other.m_reason != NULL)
+ m_reason = new Exception(*other.m_reason);
+ else
+ m_reason = NULL;
+
+ m_message = other.m_message;
+ m_path = other.m_path;
+ m_function = other.m_function;
+ m_line = other.m_line;
+ m_className = other.m_className;
+ AddRef(this);
+ return *this;
+ }
+
+ Exception(const char *path,
+ const char *function,
+ int line,
+ const std::string &message) :
+ m_reason(NULL),
+ m_path(path),
+ m_function(function),
+ m_line(line),
+ m_message(message) {
+ AddRef(this);
+ }
+
+ Exception(const char *path,
+ const char *function,
+ int line,
+ const Exception &reason,
+ const std::string &message) :
+ m_reason(new Exception(reason)),
+ m_path(path),
+ m_function(function),
+ m_line(line),
+ m_message(message) {
+ AddRef(this);
+ }
+
+ virtual ~Exception() throw() {
+ if (m_reason != NULL) {
+ delete m_reason;
+ m_reason = NULL;
+ }
+
+ UnRef(this);
+ }
+
+ void Dump() const {
+ // Show reason first
+ if (m_reason != NULL)
+ m_reason->Dump();
+
+ // Afterward, dump exception
+ const char *file = strchr(m_path.c_str(), '/');
+
+ if (file == NULL)
+ file = m_path.c_str();
+ else
+ ++file;
+
+ printf("\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
+ file, m_line,
+ m_function.c_str(),
+ m_className.c_str(),
+ m_message.empty() ? "<EMPTY>" : m_message.c_str());
+ }
+
+ std::string DumpToString() const {
+ std::string ret;
+
+ if (m_reason != NULL)
+ ret = m_reason->DumpToString();
+
+ const char *file = strchr(m_path.c_str(), '/');
+
+ if (file == NULL)
+ file = m_path.c_str();
+ else
+ ++file;
+
+ char buf[1024];
+ snprintf(buf,
+ sizeof(buf),
+ "\033[0;36m[%s:%i]\033[m %s() \033[4;35m%s\033[m: %s\033[m\n",
+ file,
+ m_line,
+ m_function.c_str(),
+ m_className.c_str(),
+ m_message.empty() ? "<EMPTY>" : m_message.c_str());
+ buf[sizeof(buf) - 1] = '\n';
+ ret += buf;
+ return ret;
+ }
+
+ Exception *GetReason() const {
+ return m_reason;
+ }
+
+ std::string GetPath() const {
+ return m_path;
+ }
+
+ std::string GetFunction() const {
+ return m_function;
+ }
+
+ int GetLine() const {
+ return m_line;
+ }
+
+ std::string GetMessage() const {
+ return m_message;
+ }
+
+ std::string GetClassName() const {
+ return m_className;
+ }
+};
+
+
+#define Try try
+
+#define Throw(ClassName) \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__)
+
+#define ThrowMsg(ClassName, Message) \
+ do { \
+ std::ostringstream dplLoggingStream; \
+ dplLoggingStream << Message; \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__, dplLoggingStream.str()); \
+ } while (0)
+
+#define ReThrow(ClassName) \
+ throw ClassName(__FILE__, __FUNCTION__, __LINE__, _rethrown_exception)
+
+#define ReThrowMsg(ClassName, Message) \
+ throw ClassName(__FILE__, \
+ __FUNCTION__, \
+ __LINE__, \
+ _rethrown_exception, \
+ Message)
+
+#define Catch(ClassName) \
+ catch (const ClassName &_rethrown_exception)
+
+#define DECLARE_EXCEPTION_TYPE(BaseClass, Class) \
+ class Class : public BaseClass { \
+ public: \
+ Class(const char *path, \
+ const char *function, \
+ int line, \
+ const std::string & message = std::string()) : \
+ BaseClass(path, function, line, message) { \
+ BaseClass::m_className = #Class; \
+ } \
+ Class(const char *path, \
+ const char *function, \
+ int line, \
+ const Exception & reason, \
+ const std::string & message = std::string()) : \
+ BaseClass(path, function, line, reason, message) { \
+ BaseClass::m_className = #Class; \
+ } \
+ };
+
+#define UNHANDLED_EXCEPTION_HANDLER_BEGIN try
+
+#define UNHANDLED_EXCEPTION_HANDLER_END \
+ catch (const Exception &exception) { \
+ std::ostringstream msg; \
+ msg << Exception::KnownExceptionToString(exception); \
+ LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } catch (std::exception& e) { \
+ std::ostringstream msg; \
+ msg << e.what(); \
+ msg << "\n"; \
+ msg << Exception::UnknownExceptionToString(); \
+ LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ } catch (...) { \
+ std::ostringstream msg; \
+ msg << Exception::UnknownExceptionToString(); \
+ LogUnhandledException(msg.str(), __FILE__, __LINE__, __FUNCTION__); \
+ abort(); \
+ }
+
+/**
+ * Internal exception definitions
+ *
+ * These should normally not happen.
+ * Usually, exception trace with internal error includes
+ * important messages.
+ */
+DECLARE_EXCEPTION_TYPE(Exception, InternalError) ///< Unexpected error from
+// underlying libraries or
+// kernel
+
+
+#endif // AUTH_PASSWD_EXCEPTION_H
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jooseong Lee <jooseong.lee@samsung.com>
+ *
+ * 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 fstream-helper.h
+ * @author Marek Smolinski (m.smolinski@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of fstream-helper
+ *
+ */
+
+#ifndef AUTH_PASSWD_FSTREAM_ACCESSORS_H
+#define AUTH_PASSWD_FSTREAM_ACCESSORS_H
+
+/*
+ * Bypass lack of public member function to get file
+ * descriptor from fstream objects in std
+ * This feature is needed for flushing data from kernel space buffer to
+ * physical device [fsync(int fd) - syscall] on opened fstream object
+*/
+ template<typename T>
+ class FstreamAccessors : T::__filebuf_type {
+ typedef FstreamAccessors<T> MyType;
+ public:
+ static int GetFd(T &strm)
+ {
+ return static_cast<MyType *>(strm.rdbuf())->_M_file.fd();
+ }
+ };
+
+#endif // AUTH_PASSWD_FSTREAM_ACCESSORS_H
--- /dev/null
+/*
+ * Copyright (c) 2025 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
+ */
+#ifndef _IPASSWORD_FILE_H_
+#define _IPASSWORD_FILE_H_
+
+#include <string>
+#include <time.h>
+#include <hal/hal-security-auth-error.h>
+
+#include "ipassword.h"
+
+struct IPasswordFile {
+ IPasswordFile() = default;
+ virtual ~IPasswordFile() = default;
+
+ IPasswordFile(const IPasswordFile&) = delete;
+ IPasswordFile& operator=(const IPasswordFile&) = delete;
+
+ IPasswordFile(IPasswordFile&&) = delete;
+ IPasswordFile& operator=(IPasswordFile&&) = delete;
+
+ virtual int write_memory_to_file(uid_t user_id) const = 0;
+ virtual int write_attempt_to_file(uid_t user_id) const = 0;
+
+ virtual int set_password(uid_t user_id, const char* password) = 0;
+ virtual int check_password(uid_t user_id, const char* password) = 0;
+
+ virtual int is_password_active(uid_t user_id) const = 0;
+
+ virtual int get_password_type(uid_t user_id, hal_security_auth_password_type_e *password_type) const = 0;
+ virtual int set_max_history_size(uid_t user_id, unsigned int history_size) = 0;
+
+ virtual int get_max_history_size(uid_t user_id, unsigned int *history_size) const = 0;
+
+ virtual int get_expire_time(uid_t user_id, unsigned int *expire_time) const = 0;
+ virtual int set_expire_time(uid_t user_id, unsigned int expire_time) = 0;
+
+ virtual int get_expire_time_left(uid_t user_id, unsigned int *expire_time_left) const = 0;
+ virtual int set_expire_time_left(uid_t user_id, unsigned int expire_time_left) = 0;
+
+ virtual int get_attempt(uid_t user_id, unsigned int *attempt) const = 0;
+ virtual int reset_attempt(uid_t user_id) = 0;
+ virtual int increment_attempt(uid_t user_id) = 0;
+ virtual int get_max_attempt(uid_t user_id, unsigned int *max_attempt) const = 0;
+ virtual int set_max_attempt(uid_t user_id, unsigned int max_attempt) = 0;
+
+ virtual int is_password_reused(uid_t user_id, const char* password) const = 0;
+
+ virtual int check_expiration(uid_t user_id) const = 0;
+ virtual int check_attempt_exceeded(uid_t user_id) const = 0;
+ virtual int is_ignore_period(uid_t user_id) const = 0;
+
+ virtual int is_history_active(uid_t user_id) const = 0;
+ virtual uid_t get_user_id() const = 0;
+};
+
+using PasswordFileFactory = IPasswordFile* (*)(unsigned int);
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2025 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
+ */
+#include <openssl/sha.h>
+
+#include "ipassword.h"
+#include "log.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+NoPassword::NoPassword(IStream&)
+{
+}
+
+void NoPassword::Serialize(IStream &stream) const
+{
+ Serialization::Serialize(stream, static_cast<unsigned int>(PasswordType::NONE));
+}
+
+bool NoPassword::match(const std::string &pass) const
+{
+ return pass.empty();
+}
+
+SHA256Password::SHA256Password(IStream &stream)
+{
+ Deserialization::Deserialize(stream, m_hash);
+}
+
+SHA256Password::SHA256Password(const std::string &password) : m_hash(hash(password))
+{
+}
+
+SHA256Password::SHA256Password(const RawHash ¶mHash) : m_hash(paramHash)
+{
+}
+
+void SHA256Password::Serialize(IStream &stream) const
+{
+ Serialization::Serialize(stream, static_cast<unsigned int>(PasswordType::SHA256));
+ Serialization::Serialize(stream, m_hash);
+}
+
+bool SHA256Password::match(const std::string &password) const
+{
+ return m_hash == hash(password);
+}
+
+RawHash SHA256Password::hash(const std::string &password)
+{
+ RawHash result(SHA256_DIGEST_LENGTH);
+ SHA256_CTX context;
+ SHA256_Init(&context);
+ SHA256_Update(&context, reinterpret_cast<const unsigned char *>(password.c_str()),
+ password.size());
+ SHA256_Final(result.data(), &context);
+ return result;
+}
+#ifdef __cplusplus
+}
+#endif
+
+template <>
+void Deserialization::Deserialize(IStream &stream, IPasswordPtr &ptr)
+{
+ unsigned int algorithm;
+ Deserialization::Deserialize(stream, algorithm);
+
+ switch (algorithm) {
+ case (unsigned int)IPassword::PasswordType::NONE:
+ ptr.reset(new NoPassword());
+ break;
+
+ case (unsigned int)IPassword::PasswordType::SHA256:
+ ptr.reset(new SHA256Password(stream));
+ break;
+
+ default:
+ LOGE("FStreamReadError");
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2025 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
+ */
+#ifndef _IPASSWORD_H_
+#define _IPASSWORD_H_
+
+#include <string>
+#include <memory>
+#include <limits>
+#include <time.h>
+
+#include "serialization.h"
+
+constexpr time_t PASSWORD_INFINITE_EXPIRATION_TIME = std::numeric_limits<time_t>::max();
+
+struct IPassword;
+using RawHash = std::vector<unsigned char>;
+using IPasswordPtr = std::shared_ptr<IPassword>;
+using PasswordList = std::list<IPasswordPtr>;
+
+struct IPassword: public ISerializable {
+
+ enum class PasswordType : unsigned int {
+ NONE = 0,
+ SHA256 = 1,
+ };
+
+ virtual bool match(const std::string &password) const = 0;
+};
+
+class NoPassword: public IPassword {
+public:
+ NoPassword() = default;
+ NoPassword(IStream &);
+
+ void Serialize(IStream &stream) const;
+ bool match(const std::string &pass) const;
+};
+
+class SHA256Password: public IPassword {
+public:
+ SHA256Password(IStream &stream);
+ SHA256Password(const std::string &password);
+ SHA256Password(const RawHash ¶mHash);
+
+ void Serialize(IStream &stream) const;
+ bool match(const std::string &password) const;
+
+private:
+ static RawHash hash(const std::string &password);
+
+ RawHash m_hash;
+};
+
+template <>
+void Deserialization::Deserialize(IStream &stream, IPasswordPtr &ptr);
+
+#endif
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2025 Samsung Electronics 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.
+ *
+ ******************************************************************/
+
+#include <dlog.h>
+#include <syslog.h>
+
+#ifdef NDEBUG
+int __log_level = LOG_ERR;
+#else
+int __log_level = LOG_DEBUG;
+#endif
+
+#define SECURITY_AUTH_LOG_TAG "SECURITY_AUTH_BACKEND"
+
+void security_auth_print(int priority, char const *fmt, ...)
+{
+ log_priority dlog_prio;
+
+ switch (priority) {
+ case LOG_EMERG:
+ dlog_prio = DLOG_FATAL;
+ break;
+ case LOG_ERR:
+ dlog_prio = DLOG_ERROR;
+ break;
+ case LOG_WARNING:
+ dlog_prio = DLOG_WARN;
+ break;
+ case LOG_INFO:
+ dlog_prio = DLOG_INFO;
+ break;
+ case LOG_DEBUG:
+ dlog_prio = DLOG_DEBUG;
+ break;
+ default:
+ dlog_prio = DLOG_DEFAULT;
+ }
+
+ va_list ap;
+ va_start(ap, fmt);
+ (void) dlog_vprint(dlog_prio, SECURITY_AUTH_LOG_TAG, fmt, ap);
+ va_end(ap);
+}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2025 Samsung Electronics 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.
+ *
+ ******************************************************************/
+#ifndef SHARED_LOG_H_
+#define SHARED_LOG_H_
+
+#include <stdlib.h>
+#include <syslog.h>
+#include <sstream>
+
+#define UNUSED __attribute__((unused))
+
+extern int __log_level;
+extern void security_auth_print(int priority, char const *fmt, ...);
+
+namespace {
+ template <typename ...Args>
+ void UNUSED __LOG_FUN(int level, const std::stringstream &format, Args&&... args) {
+ security_auth_print(level, format.str().c_str(), std::forward<Args>(args)...);
+ }
+
+ template <>
+ void UNUSED __LOG_FUN(int level, const std::stringstream &format) {
+ security_auth_print(level, "%s", format.str().c_str());
+ }
+
+ template <typename ...Args>
+ void UNUSED __LOG_FUN(int level, const char *format, Args&&... args) {
+ security_auth_print(level, format, std::forward<Args>(args)...);
+ }
+
+ template <>
+ void UNUSED __LOG_FUN(int level, const char *format) {
+ security_auth_print(level, "%s", format);
+ }
+
+} // namespace anonymous
+
+#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#define __LOG(LEVEL, FORMAT, ...) \
+ do { \
+ if (LEVEL <= __log_level) { \
+ std::stringstream __LOG_FORMAT; \
+ __LOG_FORMAT << __FILENAME__ << ": " << __func__ << "(" << __LINE__ << ") > " << FORMAT; \
+ __LOG_FUN(LEVEL, __LOG_FORMAT, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define LOGM(...) __LOG(LOG_EMERG, __VA_ARGS__) /* system is unusable */
+#define LOGE(...) __LOG(LOG_ERR, __VA_ARGS__) /* error conditions */
+#define LOGW(...) __LOG(LOG_WARNING, __VA_ARGS__) /* warning conditions */
+#define LOGI(...) __LOG(LOG_INFO, __VA_ARGS__) /* informational */
+#define LOGD(...) __LOG(LOG_DEBUG, __VA_ARGS__) /* debug-level messages */
+
+#endif /* SHARED_LOG_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jooseong Lee <jooseong.lee@samsung.com>
+ *
+ * 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 password-file-buffer.cpp
+ * @author Lukasz Kostyra (l.kostyra@partner.samsung.com)
+ * @version 1.0
+ * @brief Implementation of PasswordFileBuffer, used for serialization in PasswordFile class
+ */
+
+
+#include <fstream>
+#include <iterator>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "fstream_accessors.h"
+#include "password-file-buffer.h"
+#include "log.h"
+
+PasswordFileBuffer::PasswordFileBuffer(): m_bufferReadBytes(0) {}
+
+void PasswordFileBuffer::Read(size_t num, void *bytes)
+{
+ if (m_buffer.empty())
+ LOGE("Buffer doesn't contain any data.");
+
+ if ((m_bufferReadBytes + num) > m_buffer.size())
+ LOGE("Not enough buffer to read " << num << " data.");
+
+ void *ret = memcpy(bytes, &m_buffer[m_bufferReadBytes], num);
+
+ if (ret == 0)
+ LOGE("Failed to read " << num << " bytes.");
+
+ m_bufferReadBytes += num;
+}
+
+void PasswordFileBuffer::Write(size_t num, const void *bytes)
+{
+ const char *buffer = static_cast<const char *>(bytes);
+ std::copy(buffer, buffer + num, std::back_inserter(m_buffer));
+}
+
+void PasswordFileBuffer::Save(const std::string &path)
+{
+ std::ofstream file(path, std::ofstream::trunc);
+
+ if (!file.good())
+ LOGE("Error while opening file stream. file=" << path);
+
+ file.write(m_buffer.data(), m_buffer.size());
+
+ if (!file)
+ LOGE("Failed to write data. file=" << path);
+
+ file.flush();
+ if (::fsync(FstreamAccessors<std::ofstream>::GetFd(file)) != 0)
+ LOGE("Failed to synchronize a file's state. file=" << path);
+ file.close();
+}
+
+void PasswordFileBuffer::Load(const std::string &path)
+{
+ std::ifstream file(path, std::ifstream::binary);
+
+ if (!file.good())
+ LOGE("Error while opening file stream. file=" << path);
+
+ //reset read bytes counter
+ m_bufferReadBytes = 0;
+ m_buffer.assign(std::istreambuf_iterator<char>(file),
+ std::istreambuf_iterator<char>());
+
+ if (!file)
+ LOGE("Failed to read data. Failbit: " << file.fail() << ", Badbit: " << file.bad() << ", file=" << path);
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2025 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jooseong Lee <jooseong.lee@samsung.com>
+ *
+ * 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 password-file-buffer.h
+ * @author Zbigniew Jasinski (z.jasinski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@partner.samsung.com)
+ * @version 1.0
+ * @brief Implementation of password file buffer, used for serialization in password-manager.h
+ */
+
+#ifndef _PASSWORD_FILE_BUFFER_H_
+#define _PASSWORD_FILE_BUFFER_H_
+
+#include <stddef.h>
+#include <vector>
+#include <string>
+
+#include "serialization.h"
+
+class PasswordFileBuffer: public IStream {
+ public:
+ PasswordFileBuffer();
+
+ virtual void Read(size_t num, void *bytes);
+ virtual void Write(size_t num, const void *bytes);
+
+ void Save(const std::string &path);
+ void Load(const std::string &path);
+
+ private:
+ typedef std::vector<char> DataBuffer;
+
+ DataBuffer m_buffer;
+ size_t m_bufferReadBytes;
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2011 - 2025 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 serialization.h
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 1.0
+ * @brief Interfaces and templates used for data serialization.
+ */
+#ifndef SERIALIZATION_H
+#define SERIALIZATION_H
+
+#include <string>
+#include <vector>
+#include <set>
+#include <list>
+#include <map>
+#include <memory>
+
+#include "log.h"
+
+// Abstract data stream buffer
+class IStream {
+ public:
+ virtual void Read(size_t num, void *bytes) = 0;
+ virtual void Write(size_t num, const void *bytes) = 0;
+ virtual ~IStream() {}
+};
+
+// Serializable interface
+class ISerializable {
+ public:
+ ISerializable() {}
+ ISerializable(IStream &) {}
+ virtual void Serialize(IStream &) const = 0;
+ virtual ~ISerializable() {}
+};
+
+struct Serialization {
+ // serialization
+ // normal functions
+
+ // ISerializable objects
+ static void Serialize(IStream &stream, const ISerializable &object) {
+ object.Serialize(stream);
+ }
+ static void Serialize(IStream &stream, const ISerializable *const object) {
+ object->Serialize(stream);
+ }
+
+ // char
+ static void Serialize(IStream &stream, const char value) {
+ stream.Write(sizeof(value), &value);
+ }
+ static void Serialize(IStream &stream, const char *const value) {
+ stream.Write(sizeof(*value), value);
+ }
+
+ // unsigned char
+ static void Serialize(IStream &stream, const unsigned char value) {
+ stream.Write(sizeof(value), &value);
+ }
+ static void Serialize(IStream &stream, const unsigned char *const value) {
+ stream.Write(sizeof(*value), value);
+ }
+
+ // unsigned int
+ static void Serialize(IStream &stream, const unsigned value) {
+ stream.Write(sizeof(value), &value);
+ }
+ static void Serialize(IStream &stream, const unsigned *const value) {
+ stream.Write(sizeof(*value), value);
+ }
+
+ // int
+ static void Serialize(IStream &stream, const int value) {
+ stream.Write(sizeof(value), &value);
+ }
+ static void Serialize(IStream &stream, const int *const value) {
+ stream.Write(sizeof(*value), value);
+ }
+
+ // bool
+ static void Serialize(IStream &stream, const bool value) {
+ stream.Write(sizeof(value), &value);
+ }
+ static void Serialize(IStream &stream, const bool *const value) {
+ stream.Write(sizeof(*value), value);
+ }
+
+ // time_t
+ static void Serialize(IStream &stream, const time_t value) {
+ stream.Write(sizeof(value), &value);
+ }
+ static void Serialize(IStream &stream, const time_t *const value) {
+ stream.Write(sizeof(*value), value);
+ }
+
+ // std::string
+ static void Serialize(IStream &stream, const std::string &str) {
+ int length = str.size();
+ stream.Write(sizeof(length), &length);
+ stream.Write(length, str.c_str());
+ }
+ static void Serialize(IStream &stream, const std::string *const str) {
+ int length = str->size();
+ stream.Write(sizeof(length), &length);
+ stream.Write(length, str->c_str());
+ }
+
+ // STL templates
+
+ // std::list
+ template <typename T>
+ static void Serialize(IStream &stream, const std::list<T> &list) {
+ int length = list.size();
+ stream.Write(sizeof(length), &length);
+
+ for (typename std::list<T>::const_iterator list_iter = list.begin();
+ list_iter != list.end(); list_iter++)
+ Serialize(stream, *list_iter);
+ }
+ template <typename T>
+ static void Serialize(IStream &stream, const std::list<T> *const list) {
+ Serialize(stream, *list);
+ }
+
+ // std::vector
+ template <typename T>
+ static void Serialize(IStream &stream, const std::vector<T> &vec) {
+ int length = vec.size();
+ stream.Write(sizeof(length), &length);
+
+ for (typename std::vector<T>::const_iterator vec_iter = vec.begin();
+ vec_iter != vec.end(); vec_iter++)
+ Serialize(stream, *vec_iter);
+ }
+ template <typename T>
+ static void Serialize(IStream &stream, const std::vector<T> *const vec) {
+ Serialize(stream, *vec);
+ }
+
+ // std::set
+ template <typename T>
+ static void Serialize(IStream &stream, const std::set<T> &set) {
+ size_t length = set.size();
+ stream.Write(sizeof(length), &length);
+
+ for (const auto &item : set)
+ Serialize(stream, item);
+ }
+
+ // std::pair
+ template <typename A, typename B>
+ static void Serialize(IStream &stream, const std::pair<A, B> &p) {
+ Serialize(stream, p.first);
+ Serialize(stream, p.second);
+ }
+ template <typename A, typename B>
+ static void Serialize(IStream &stream, const std::pair<A, B> *const p) {
+ Serialize(stream, *p);
+ }
+
+ // std::map
+ template <typename K, typename T>
+ static void Serialize(IStream &stream, const std::map<K, T> &map) {
+ int length = map.size();
+ stream.Write(sizeof(length), &length);
+ typename std::map<K, T>::const_iterator it;
+
+ for (it = map.begin(); it != map.end(); ++it) {
+ Serialize(stream, (*it).first);
+ Serialize(stream, (*it).second);
+ }
+ }
+ template <typename K, typename T>
+ static void Serialize(IStream &stream, const std::map<K, T> *const map) {
+ Serialize(stream, *map);
+ }
+
+ // std::unique_ptr
+ template <typename T>
+ static void Serialize(IStream &stream, const std::unique_ptr<T> &p) {
+ Serialize(stream, *p);
+ }
+
+ // std::shared_ptr
+ template <typename T>
+ static void Serialize(IStream &stream, const std::shared_ptr<T> &p) {
+ Serialize(stream, *p);
+ }
+}; // struct Serialization
+
+struct Deserialization {
+ // deserialization
+ // normal functions
+
+ // ISerializable objects
+ // T instead of ISerializable is needed to call proper constructor
+ template <typename T>
+ static void Deserialize(IStream &stream, T &object) {
+ object = T(stream);
+ }
+ template <typename T>
+ static void Deserialize(IStream &stream, T *&object) {
+ object = new T(stream);
+ }
+
+ // char
+ static void Deserialize(IStream &stream, char &value) {
+ stream.Read(sizeof(value), &value);
+ }
+ static void Deserialize(IStream &stream, char *&value) {
+ value = new char;
+ std::unique_ptr<char> ptr(value);
+ stream.Read(sizeof(*value), value);
+ ptr.release();
+ }
+
+ // unsigned char
+ static void Deserialize(IStream &stream, unsigned char &value) {
+ stream.Read(sizeof(value), &value);
+ }
+ static void Deserialize(IStream &stream, unsigned char *&value) {
+ value = new unsigned char;
+ std::unique_ptr<unsigned char> ptr(value);
+ stream.Read(sizeof(*value), value);
+ ptr.release();
+ }
+
+ // unsigned int
+ static void Deserialize(IStream &stream, unsigned &value) {
+ stream.Read(sizeof(value), &value);
+ }
+ static void Deserialize(IStream &stream, unsigned *&value) {
+ value = new unsigned;
+ std::unique_ptr<unsigned> ptr(value);
+ stream.Read(sizeof(*value), value);
+ ptr.release();
+ }
+
+ // int
+ static void Deserialize(IStream &stream, int &value) {
+ stream.Read(sizeof(value), &value);
+ }
+ static void Deserialize(IStream &stream, int *&value) {
+ value = new int;
+ std::unique_ptr<int> ptr(value);
+ stream.Read(sizeof(*value), value);
+ ptr.release();
+ }
+
+ // bool
+ static void Deserialize(IStream &stream, bool &value) {
+ stream.Read(sizeof(value), &value);
+ }
+ static void Deserialize(IStream &stream, bool *&value) {
+ value = new bool;
+ std::unique_ptr<bool> ptr(value);
+ stream.Read(sizeof(*value), value);
+ ptr.release();
+ }
+
+ // time_t
+ static void Deserialize(IStream &stream, time_t &value) {
+ stream.Read(sizeof(value), &value);
+ }
+ static void Deserialize(IStream &stream, time_t *&value) {
+ value = new time_t;
+ std::unique_ptr<time_t> ptr(value);
+ stream.Read(sizeof(*value), value);
+ ptr.release();
+ }
+
+ // std::string
+ static void Deserialize(IStream &stream, std::string &str) {
+ int length;
+ stream.Read(sizeof(length), &length);
+ if (length < 0)
+ LOGE("Invalid length of std::string (less than 0)");
+
+ char * buf = new char[length + 1];
+ std::unique_ptr<char[]> ptr(buf);
+ stream.Read(length, buf);
+ buf[length] = 0;
+ str = std::string(buf);
+ }
+ static void Deserialize(IStream &stream, std::string *&str) {
+ int length;
+ stream.Read(sizeof(length), &length);
+ if (length < 0)
+ LOGE("Invalid length of std::string (less than 0)");
+
+ char * buf = new char[length + 1];
+ std::unique_ptr<char[]> ptr(buf);
+ stream.Read(length, buf);
+ buf[length] = 0;
+ str = new std::string(buf);
+ }
+
+ // STL templates
+
+ // std::list
+ template <typename T>
+ static void Deserialize(IStream &stream, std::list<T> &list) {
+ int length;
+ stream.Read(sizeof(length), &length);
+ if (length < 0)
+ LOGE("Invalid length of std::list (less than 0)");
+
+ for (int i = 0; i < length; ++i) {
+ T obj;
+ Deserialize(stream, obj);
+ list.push_back(std::move(obj));
+ }
+ }
+ template <typename T>
+ static void Deserialize(IStream &stream, std::list<T> *&list) {
+ list = new std::list<T>;
+ std::unique_ptr<std::list<T>> ptr(list);
+ Deserialize(stream, *list);
+ ptr.release();
+ }
+
+ // std::vector
+ template <typename T>
+ static void Deserialize(IStream &stream, std::vector<T> &vec) {
+ int length;
+ stream.Read(sizeof(length), &length);
+ if (length < 0)
+ LOGE("Invalid length of std::vector (less than 0)");
+
+ for (int i = 0; i < length; ++i) {
+ T obj;
+ Deserialize(stream, obj);
+ vec.push_back(std::move(obj));
+ }
+ }
+ template <typename T>
+ static void Deserialize(IStream &stream, std::vector<T> *&vec) {
+ vec = new std::vector<T>;
+ std::unique_ptr<std::vector<T>> ptr(vec);
+ Deserialize(stream, *vec);
+ ptr.release();
+ }
+
+ // std::set
+ template <typename T>
+ static void Deserialize(IStream &stream, std::set<T> &set) {
+ size_t length;
+ stream.Read(sizeof(length), &length);
+ for (size_t i = 0; i < length; ++i) {
+ T obj;
+ Deserialize(stream, obj);
+ set.insert(std::move(obj));
+ }
+ }
+
+ // std::pair
+ template <typename A, typename B>
+ static void Deserialize(IStream &stream, std::pair<A, B> &p) {
+ Deserialize(stream, p.first);
+ Deserialize(stream, p.second);
+ }
+ template <typename A, typename B>
+ static void Deserialize(IStream &stream, std::pair<A, B> *&p) {
+ p = new std::pair<A, B>;
+ std::unique_ptr<std::pair<A, B>> ptr(p);
+ Deserialize(stream, *p);
+ ptr.release();
+ }
+
+ // std::tuple
+ template <std::size_t I = 0, typename... Tp>
+ static inline typename std::enable_if<I == sizeof...(Tp), void>::type
+ Deserialize(IStream&, std::tuple<Tp...>&)
+ {}
+
+ template <std::size_t I = 0, typename... Tp>
+ static inline typename std::enable_if<I < sizeof...(Tp), void>::type
+ Deserialize(IStream& stream, std::tuple<Tp...>& t) {
+ Deserialize(stream, std::get<I>(t));
+ Deserialize<I+1>(stream, t);
+ }
+
+ template <typename... Tp>
+ static void Deserialize(IStream &stream, std::tuple<Tp...> *&t) {
+ t = new std::tuple<Tp...>;
+ std::unique_ptr<std::tuple<Tp...>> ptr(t);
+ Deserialize(stream, *t);
+ ptr.release();
+ }
+
+ // std::map
+ template <typename K, typename T>
+ static void Deserialize(IStream &stream, std::map<K, T> &map) {
+ int length;
+ stream.Read(sizeof(length), &length);
+ if (length < 0)
+ LOGE("Invalid size of std::map (less than 0)");
+
+ for (int i = 0; i < length; ++i) {
+ K key;
+ T obj;
+ Deserialize(stream, key);
+ Deserialize(stream, obj);
+ map[key] = std::move(obj);
+ }
+ }
+ template <typename K, typename T>
+ static void Deserialize(IStream &stream, std::map<K, T> *&map) {
+ map = new std::map<K, T>;
+ std::unique_ptr<std::map<K, T>> ptr(map);
+ Deserialize(stream, *map);
+ ptr.release();
+ }
+
+ template<typename T1, typename T2, typename... Tail>
+ static void Deserialize(IStream &stream, T1 &first, T2 &second, Tail&... tail) {
+ Deserialization::Deserialize(stream, first);
+ Deserialization::Deserialize(stream, second, tail...);
+ }
+}; // struct Deserialization
+
+#endif // SERIALIZATION_H
--- /dev/null
+/*
+ * Copyright (c) 2025 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 symbol-visibility.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief define symbol visiblity for common library.
+ */
+
+#define COMMON_API __attribute__((visibility("default")))