});
}
-__attribute__ ((unused)) static int security_manager_save_fek(
- const std::string &appName,
- const std::string &password,
- const std::vector<char> &fek)
+static int security_manager_get_sensitive_dirs(const std::string &appName,
+ std::vector<std::string>& paths)
{
- ClientRequest request(SecurityModuleCall::APP_SAVE_FEK);
- return request.send(appName, password, fek).getStatus();
+ using namespace SecurityManager;
+ if (appName.empty())
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ return try_catch([&]() -> int {
+ ClientRequest request(SecurityModuleCall::PATHS_GET_SENSITIVE);
+ if (request.send(appName).failed())
+ return request.getStatus();
+
+ request.recv(paths);
+ return SECURITY_MANAGER_SUCCESS;
+ });
}
-__attribute__ ((unused)) static int security_manager_get_fek(
- const std::string &appName,
- const std::string &password,
- std::vector<char> &fek)
+static int security_manager_get_fek(const std::string &appName,
+ const std::string &password,
+ std::vector<char> &fek)
{
ClientRequest request(SecurityModuleCall::APP_GET_FEK);
if (request.send(appName, password).failed())
return SECURITY_MANAGER_SUCCESS;
}
-__attribute__ ((unused)) static int security_manager_remove_fek(
- const std::string &appName)
+SECURITY_MANAGER_API
+int security_manager_app_change_password(const char *app_id,
+ const char *old_pw,
+ const char *new_pw)
{
- ClientRequest request(SecurityModuleCall::APP_REMOVE_FEK);
- return request.send(appName).getStatus();
+ if (app_id == NULL)
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+ if (old_pw == NULL && new_pw == NULL)
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+ std::string oldPw, newPw, appName;
+
+ if (old_pw != NULL)
+ oldPw.assign(old_pw);
+ if (new_pw != NULL)
+ newPw.assign(new_pw);
+ appName.assign(app_id);
+
+ return try_catch([&]() -> int {
+ ClientRequest request(SecurityModuleCall::APP_CHANGE_PW);
+ return request.send(appName, oldPw, newPw).getStatus();
+ });
+}
+
+SECURITY_MANAGER_API
+int security_manager_app_get_encryption_status(const char *app_id,
+ app_encryption_status *status)
+{
+ if (app_id == NULL || status == NULL)
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+ return try_catch([&]() -> int {
+ int tmp_status = SM_APP_ENCR_NONE;
+ std::vector<std::string> paths;
+ int ret = security_manager_get_sensitive_dirs(app_id, paths);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+
+ if (!paths.empty())
+ tmp_status |= SM_APP_ENCR_HAS_SENSITIVE_DIRS;
+
+ std::vector<char> fek;
+
+ // get FEK from key manager using wrong password
+ ret = security_manager_get_fek(app_id, "", fek);
+ if (ret == SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED) {
+ tmp_status |= SM_APP_ENCR_HAS_PASSWORD;
+ } else if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
+ // status is unchanged
+ } else {
+ return ret;
+ }
+
+ *status = static_cast<app_encryption_status>(tmp_status);
+ return SECURITY_MANAGER_SUCCESS;
+ });
+}
+
+SECURITY_MANAGER_API
+int security_manager_app_unlock(const char *app_id, const char *password)
+{
+ if (app_id == NULL)
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+ if (password == NULL)
+ return SECURITY_MANAGER_SUCCESS; // no password, no key, no encryption
+
+ return try_catch([&]() -> int {
+ std::vector<char> fek;
+
+ // get key from key manager
+ int ret = security_manager_get_fek(app_id, password, fek);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+
+ // TODO insert it into process keyring
+
+ return SECURITY_MANAGER_SUCCESS;
+ });
}
APP_SAVE_FEK,
APP_GET_FEK,
APP_REMOVE_FEK,
+ APP_CHANGE_PW,
NOOP = 0x90,
};
int getSensitiveDirs(const Credentials &creds,
const std::string &appName,
std::vector<std::string> &paths);
+
+ /*
+ * Change application's password
+ *
+ * @param[in] creds credentials of the requesting process
+ * @param[in] appName application identifier
+ * @param[in] oldPw old password (can be empty)
+ * @param[in] newPw new password (can be empty)
+ *
+ * @return API return code, as defined in protocols.h
+ */
+ int appChangePassword(const Credentials &creds,
+ const std::string &appName,
+ const std::string &oldPw,
+ const std::string &newPw);
private:
bool authenticate(const Credentials &creds, const std::string &privilege);
ServiceImpl::~ServiceImpl()
{
+ // TODO cleanup yaca if necessary
}
int ServiceImpl::validatePolicy(const Credentials &creds, policy_entry &policyEntry, CynaraAdminPolicy &cyap)
}
}
+int ServiceImpl::appChangePassword(const Credentials &creds,
+ const std::string &appName,
+ const std::string &oldPw,
+ const std::string &newPw)
+{
+ if (appName.empty()) {
+ LogError("Application id is empty");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+
+ if (oldPw.empty() && newPw.empty()) {
+ LogError("Both passwords are empty");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+
+ std::vector<std::string> paths;
+ int ret;
+ ret = getSensitiveDirs(creds, appName, paths);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+
+ try {
+ if (!EncryptionAccess::IsAllowed(creds.label)) {
+ LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label <<
+ " for list of sensitive directories denied");
+ return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
+ }
+
+ if (oldPw.empty()) {
+ // enable encryption
+
+ // generate FEK
+ std::vector<char> fek(64, 0);
+
+ // TODO initialize yaca (on demand)
+
+ // TODO randomize FEK
+
+ // TODO insert FEK into keyring
+
+ for (const auto& p : paths) {
+ (void)p;
+ // TODO set policy for path
+ }
+
+ // TODO remove FEK from keyring
+
+ // store FEK protected with password
+ return FEKmanager::saveFEK(creds.uid, creds.label, appName, newPw, fek);
+ } else if (newPw.empty()) {
+ // disable encryption
+
+ std::vector<char> fek;
+
+ // get FEK from key manager
+ int ret = FEKmanager::getFEK(creds.uid, creds. label, appName, oldPw, fek);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+
+ // insert FEK into keyring to decrypt existing data
+
+ for (const auto& p : paths) {
+ (void)p;
+ // TODO remove/decrypt directory
+ }
+
+ // TODO remove FEK from keyring
+
+ // remove FEK from key manager
+ return FEKmanager::removeFEK(creds.uid, creds.label, appName);
+ } else {
+ // change password
+
+ std::vector<char> fek;
+
+ // get FEK from key manager
+ int ret = FEKmanager::getFEK(creds.uid, creds.label, appName, oldPw, fek);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+
+ // remove FEK from key manager
+ ret = FEKmanager::removeFEK(creds.uid, creds.label, appName);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+
+ // store FEK with new password
+ return FEKmanager::saveFEK(creds.uid, creds.label, appName, newPw, fek);
+ }
+ } catch (const PrivilegeDb::Exception::Base &e) {
+ LogError("Error while querying db for sensitive directories: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ } catch (const std::bad_alloc &e) {
+ LogError("Memory allocation failed: " << e.what());
+ return SECURITY_MANAGER_ERROR_MEMORY;
+ } catch (const std::exception &e) {
+ LogError("Some exception thrown: " << e.what());
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ } catch (...) {
+ LogError("Unknown exception thrown");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+}
+
} /* namespace SecurityManager */
${INCLUDE_PATH}/label-monitor.h
${INCLUDE_PATH}/user-manager.h
${INCLUDE_PATH}/policy-manager.h
+ ${INCLUDE_PATH}/app-encryption.h
DESTINATION ${INCLUDE_INSTALL_DIR}/security-manager
)
--- /dev/null
+/*
+ * Copyright (c) 2017 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 app-encryption.h
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version 1.0
+ */
+
+#pragma once
+
+#include "security-manager-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Function responsible for modification of application key. To enable or
+ * disable sensitive directory encryption the old or new password should be set
+ * to NULL respectively. TODO For now it is assumed that the application is not
+ * running.
+ *
+ * \param[in] app_id Application identifier
+ * \param[in] old_pw Old application password
+ * \param[in] new_pw New application password
+ *
+ * \return API return code or error code
+ */
+int security_manager_app_change_password(const char* app_id,
+ const char* old_pw,
+ const char* new_pw);
+
+/**
+ * Checks application's encryption status.
+ *
+ * \param[in] app_id Application identifier
+ * \param[out] status Application encryption status
+ * \return API return code or error code
+ */
+int security_manager_app_get_encryption_status(const char* app_id,
+ app_encryption_status* status);
+
+/**
+ * Function responsible for inserting an application key into current process
+ * keyring allowing sensitive directories to be accessed (decrypted). It should
+ * be called before security_manager_prepare_app().
+ *
+ * \param[in] app_id Application identifier
+ * \param[in] password Application password
+ * \return API return code or error code
+ */
+int security_manager_app_unlock(const char* app_id, const char* password);
+
+#ifdef __cplusplus
+}
+#endif
+
};
typedef enum security_manager_user_type security_manager_user_type;
+enum app_encryption_status {
+ SM_APP_ENCR_NONE = 0, /*<-0*/
+ SM_APP_ENCR_HAS_SENSITIVE_DIRS = 1 << 0, /*<-1 - application has sensitive dirs*/
+ SM_APP_ENCR_HAS_PASSWORD = 1 << 1, /*<-2 - application has encryption password set*/
+};
+typedef enum app_encryption_status app_encryption_status;
+
/*! \brief data structure responsible for handling informations
* required to install / uninstall application */
struct app_inst_req;
#include "label-monitor.h"
#include "user-manager.h"
#include "policy-manager.h"
+#include "app-encryption.h"
#ifdef __cplusplus
extern "C" {
void processSaveFEK(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds);
void processGetFEK(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds);
void processRemoveFEK(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds);
+
+ void processChangePassword(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds);
};
} // namespace SecurityManager
case SecurityModuleCall::APP_REMOVE_FEK:
processRemoveFEK(buffer, send, creds);
break;
+ case SecurityModuleCall::APP_CHANGE_PW:
+ processChangePassword(buffer, send, creds);
+ break;
default:
LogError("Invalid call: " << call_type_int);
Throw(ServiceException::InvalidAction);
Serialization::Serialize(send, ret);
}
+void Service::processChangePassword(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds)
+{
+ std::string appName, oldPw, newPw;
+ Deserialization::Deserialize(recv, appName, oldPw, newPw);
+
+ int ret = serviceImpl.appChangePassword(creds, appName, oldPw, newPw);
+
+ Serialization::Serialize(send, ret);
+}
+
} // namespace SecurityManager