summaryrefslogtreecommitdiff
path: root/src/manager/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/manager/service')
-rw-r--r--src/manager/service/ckm-logic.cpp41
-rw-r--r--src/manager/service/ckm-logic.h6
-rw-r--r--src/manager/service/ckm-service.cpp5
-rw-r--r--src/manager/service/ss-crypto.cpp134
-rw-r--r--src/manager/service/ss-crypto.h33
-rw-r--r--src/manager/service/ss-migrate.cpp127
-rw-r--r--src/manager/service/ss-migrate.h10
7 files changed, 231 insertions, 125 deletions
diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp
index 2f1a2280..7d322289 100644
--- a/src/manager/service/ckm-logic.cpp
+++ b/src/manager/service/ckm-logic.cpp
@@ -61,6 +61,7 @@ bool isNameValid(const CKM::Name &name)
namespace CKM {
const uid_t CKMLogic::SYSTEM_DB_UID = 0;
+const uid_t CKMLogic::ADMIN_USER_DB_UID = 5001;
CKMLogic::CKMLogic()
{
@@ -95,6 +96,26 @@ void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
}
+void CKMLogic::migrateSecureStorageData(bool isAdminUser)
+{
+ SsMigration::migrate(isAdminUser, [this](const std::string &name,
+ const Crypto::Data &data,
+ bool adminUserFlag) {
+ LogInfo("Migrate data called with name: " << name);
+ auto ownerId = adminUserFlag ? OWNER_ID_ADMIN_USER : OWNER_ID_SYSTEM;
+ auto uid = adminUserFlag ? ADMIN_USER_DB_UID : SYSTEM_DB_UID;
+
+ int ret = verifyAndSaveDataHelper(Credentials(uid, ownerId), name, ownerId, data,
+ PolicySerializable());
+
+ if (ret == CKM_API_ERROR_DB_ALIAS_EXISTS)
+ LogWarning("Alias already exist for migrated name: " << name);
+ else if (ret != CKM_API_SUCCESS)
+ LogError("Failed to migrate secure-storage data. name: " << name <<
+ " ret: " << ret);
+ });
+}
+
int CKMLogic::unlockDatabase(uid_t user, const Password &password)
{
if (0 < m_userDataMap.count(user) &&
@@ -131,22 +152,10 @@ int CKMLogic::unlockDatabase(uid_t user, const Password &password)
}
}
- if (user == SYSTEM_DB_UID && hasMigratableData()) {
- migrateData([this](const std::string &owner,
- const std::string &name,
- const Crypto::Data &data) {
- LogInfo("Saver called with owner: " << owner << " name: " << name);
-
- Credentials cred(0, OWNER_ID_SYSTEM);
-
- int ret = this->verifyAndSaveDataHelper(
- Credentials(0, OWNER_ID_SYSTEM), (owner + "-" + name),
- OWNER_ID_SYSTEM, data, PolicySerializable());
- if (ret != CKM_API_SUCCESS)
- LogError("Failed to migrate secure-storage data. owner: " << owner <<
- " name: " << name << " ret: " << ret);
- });
- }
+ if (user == SYSTEM_DB_UID && SsMigration::hasData())
+ migrateSecureStorageData(false);
+ else if (user == ADMIN_USER_DB_UID && SsMigration::hasData())
+ migrateSecureStorageData(true);
} catch (const Exc::Exception &e) {
retCode = e.error();
} catch (const CKM::Exception &e) {
diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h
index a1182028..b1ab091f 100644
--- a/src/manager/service/ckm-logic.h
+++ b/src/manager/service/ckm-logic.h
@@ -50,6 +50,7 @@ struct UserData {
class CKMLogic {
public:
static const uid_t SYSTEM_DB_UID;
+ static const uid_t ADMIN_USER_DB_UID;
CKMLogic();
CKMLogic(const CKMLogic &) = delete;
@@ -211,7 +212,6 @@ public:
const Crypto::DataEncryption &enc,
const Policy &policy);
-protected:
int unlockSystemDB();
private:
@@ -220,7 +220,7 @@ private:
UserData &selectDatabase(const Credentials &incoming_cred,
const Label &incoming_label);
- int unlockDatabase(uid_t user,
+ int unlockDatabase(uid_t user,
const Password &password);
void loadDKEKFile(
@@ -394,6 +394,8 @@ private:
int loadAppKey(UserData &handle, const Label &appLabel);
+ void migrateSecureStorageData(bool isAdminUser);
+
AccessControl m_accessControl;
Crypto::Decider m_decider;
//FileLock m_lock;
diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp
index c7e8f746..5b39632e 100644
--- a/src/manager/service/ckm-service.cpp
+++ b/src/manager/service/ckm-service.cpp
@@ -49,6 +49,11 @@ CKMService::~CKMService()
void CKMService::Start()
{
+ // unlock system db at first to migrate old ss data earlier than user db unlocked.
+ // Because data should be migrated to both of system db and user(default owner) db
+ // and old data resource will be removed after migrated to user db
+ m_logic->unlockSystemDB();
+
Create();
}
diff --git a/src/manager/service/ss-crypto.cpp b/src/manager/service/ss-crypto.cpp
new file mode 100644
index 00000000..1da144ac
--- /dev/null
+++ b/src/manager/service/ss-crypto.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016 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 ss-crypto.cpp
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Decrypt old secure-storage data for migration
+ */
+#include <ss-crypto.h>
+
+#include <memory>
+#include <cstring>
+
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+#include <dpl/log/log.h>
+
+namespace CKM {
+
+namespace {
+
+const int SALT_SIZE = 32;
+const int KEY_SIZE = 16;
+
+RawBuffer _get_key(const std::string &id)
+{
+ unsigned char salt[SALT_SIZE];
+
+ ::memset(salt, 0xFF, SALT_SIZE);
+
+ RawBuffer duk(KEY_SIZE);
+
+ if (::PKCS5_PBKDF2_HMAC_SHA1(id.c_str(), id.length(), salt, SALT_SIZE, 1, duk.size(),
+ duk.data()) != 1) {
+ LogError("Failed to pkcs5_pkbdf_hmac_sha1.");
+ return RawBuffer();
+ }
+
+ return duk;
+}
+
+RawBuffer _get_iv(const RawBuffer &src)
+{
+ RawBuffer iv(KEY_SIZE);
+ size_t ivlen = iv.size();
+
+ if (::EVP_Digest(src.data(), src.size(), iv.data(), &ivlen, ::EVP_sha1(), nullptr)
+ != 1) {
+ LogError("Failed to get iv");
+ return RawBuffer();
+ }
+
+ return iv;
+}
+
+RawBuffer _decrypt(const RawBuffer &key, const RawBuffer &iv, const RawBuffer &ciphertext)
+{
+ auto algo = ::EVP_aes_128_cbc();
+ int tmp_len = (ciphertext.size() / algo->block_size + 1) * algo->block_size;
+
+ RawBuffer plaintext(tmp_len, 0);
+
+ std::unique_ptr<EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX *)> ctxptr(
+ ::EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
+
+ if (ctxptr == nullptr)
+ throw std::bad_alloc();
+
+ auto ctx = ctxptr.get();
+
+ int ec = ::EVP_CIPHER_CTX_set_padding(ctx, 1);
+ if (ec != 1) {
+ LogError("Failed to evp ctx set padding. ec: " << ec);
+ return RawBuffer();
+ }
+
+ ec = ::EVP_CipherInit(ctx, algo, key.data(), iv.data(), 0 /* decrypt flag */);
+ if (ec != 1) {
+ LogError("Failed to evp cipher init. ec: " << ec);
+ return RawBuffer();
+ }
+
+ int plaintext_len = 0;
+ ec = ::EVP_CipherUpdate(ctx, plaintext.data(), &plaintext_len,
+ ciphertext.data(), ciphertext.size());
+ if (ec != 1) {
+ LogError("Failed to evp cipher update. ec: " << ec);
+ return RawBuffer();
+ }
+
+ int final_len = 0;
+ ec = EVP_CipherFinal(ctx, plaintext.data() + plaintext_len, &final_len);
+ if (ec != 1) {
+ LogError("Failed to evp cipher final. ec: " << ec);
+ return RawBuffer();
+ }
+
+ plaintext_len += final_len;
+
+ plaintext.resize(plaintext_len);
+
+ return plaintext;
+}
+
+} // namespace anonymous
+
+namespace SsMigration {
+
+RawBuffer decrypt(const std::string &seed, const RawBuffer &ciphertext)
+{
+ auto key = _get_key(seed);
+ auto iv = _get_iv(key);
+
+ return _decrypt(key, iv, ciphertext);
+}
+
+} // namespace SsMigration
+
+} // namespace CKM
diff --git a/src/manager/service/ss-crypto.h b/src/manager/service/ss-crypto.h
new file mode 100644
index 00000000..b02c164f
--- /dev/null
+++ b/src/manager/service/ss-crypto.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 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 ss-crypto.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Decrypt old secure-storage data for migration
+ */
+#pragma once
+
+#include <string>
+#include <ckm/ckm-raw-buffer.h>
+
+namespace CKM {
+namespace SsMigration {
+
+RawBuffer decrypt(const std::string &seed, const RawBuffer &ciphertext);
+
+}
+}
diff --git a/src/manager/service/ss-migrate.cpp b/src/manager/service/ss-migrate.cpp
index 5bf01792..efadd2fa 100644
--- a/src/manager/service/ss-migrate.cpp
+++ b/src/manager/service/ss-migrate.cpp
@@ -23,43 +23,21 @@
#include <fstream>
#include <memory>
-#include <cstring>
#include <cerrno>
#include <cstddef>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
-#include <openssl/sha.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-
#include <dpl/log/log.h>
+#include <ss-crypto.h>
namespace CKM {
+namespace SsMigration {
namespace {
const std::string OLD_SS_DIR = RW_DATA_DIR "/secure-storage";
-const std::string OLD_SS_GROUP_PREFIX = "secure-storage::";
-const int SALT_SIZE = 32;
-const int KEY_SIZE = 16;
-
-std::unique_ptr<char[]> get_key(const std::string &id, size_t len)
-{
- unsigned char salt[SALT_SIZE];
-
- ::memset(salt, 0xFF, SALT_SIZE);
-
- std::unique_ptr<char[]> duk(new char[len + 1]);
-
- ::PKCS5_PBKDF2_HMAC_SHA1(id.c_str(), id.length(), salt, SALT_SIZE, 1,
- len, reinterpret_cast<unsigned char *>(duk.get()));
-
- duk[len] = '\0';
-
- return duk;
-}
RawBuffer read_data(const std::string &filepath, const std::string &seed)
{
@@ -87,73 +65,24 @@ RawBuffer read_data(const std::string &filepath, const std::string &seed)
return RawBuffer();
}
- auto key = get_key(seed, KEY_SIZE);
- std::unique_ptr<char[]> iv(new char[KEY_SIZE]);
- size_t ivlen = 0;
- if (::EVP_Digest(key.get(), KEY_SIZE, reinterpret_cast<unsigned char *>(iv.get()),
- &ivlen, ::EVP_sha1(), nullptr) != 1) {
- LogError("Failed to get iv");
- return RawBuffer();
- }
-
- // start decrypt data with key and iv
- auto algo = ::EVP_aes_128_cbc();
- int tmp_len = (ciphertext.size() / algo->block_size + 1) * algo->block_size;
- RawBuffer plaintext(tmp_len, 0);
-
- std::unique_ptr<EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX *)> ctxptr(
- ::EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
-
- if (ctxptr == nullptr)
- throw std::bad_alloc();
-
- auto ctx = ctxptr.get();
-
- int ec = ::EVP_CIPHER_CTX_set_padding(ctx, 1);
- if (ec != 1) {
- LogError("Failed to evp ctx set padding. ec: " << ec);
- return RawBuffer();
- }
-
- ec = ::EVP_CipherInit(ctx, algo, reinterpret_cast<unsigned char *>(key.get()),
- reinterpret_cast<unsigned char *>(iv.get()), 0 /* decrypt flag */);
- if (ec != 1) {
- LogError("Failed to evp cipher init. ec: " << ec);
- return RawBuffer();
- }
-
- int plaintext_len = 0;
- ec = ::EVP_CipherUpdate(ctx, plaintext.data(), &plaintext_len,
- ciphertext.data(), ciphertext.size());
- if (ec != 1) {
- LogError("Failed to evp cipher update. ec: " << ec);
- return RawBuffer();
- }
-
- int final_len = 0;
- ec = EVP_CipherFinal(ctx, plaintext.data() + plaintext_len, &final_len);
- if (ec != 1) {
- LogError("Failed to evp cipher final. ec: " << ec);
- return RawBuffer();
- }
-
- plaintext_len += final_len;
-
- plaintext.resize(plaintext_len);
-
- return plaintext;
+ return SsMigration::decrypt(seed, ciphertext);
}
-inline void remove_path(const std::string &path)
+inline void remove_path(const std::string &path, bool isAdminUser)
{
+ if (!isAdminUser)
+ return;
+
if (::remove(path.c_str()) == -1)
LogError("Failed to remove path: " << path << " with errno: " << errno);
+
+ LogInfo("File removed: " << path);
}
// depth 0 -> OLD_SS_DIR
// 1 -> group dir in OLD_SS_DIR
void visit_dir(const std::string &dirpath, struct dirent *buf, size_t depth,
- const Saver &saver)
+ const Saver &saver, bool isAdminUser)
{
if (depth > 1) {
LogError("Invalid depth in secure-storage subdir... dirpath: " << dirpath);
@@ -174,7 +103,7 @@ void visit_dir(const std::string &dirpath, struct dirent *buf, size_t depth,
" with errno: " << errno);
break;
} else if (result == nullptr) {
- remove_path(dirpath);
+ remove_path(dirpath, isAdminUser);
break;
}
@@ -190,16 +119,15 @@ void visit_dir(const std::string &dirpath, struct dirent *buf, size_t depth,
LogError("Invalid hierarchy of secure-storage dir... "
"Directory(" << name << ") cannot be in "
"group storage: " << dirpath);
- remove_path(path);
} else {
std::string subdir = dirpath + "/" + name;
- visit_dir(subdir, buf, depth + 1, saver);
+ visit_dir(subdir, buf, depth + 1, saver, isAdminUser);
+ continue;
}
} else if (result->d_type == DT_REG) {
if (depth == 0) {
LogError("Invalid hierarchy of secure-storage dir... "
"File(" << name << ") cannot be in secure-storage top dir");
- remove_path(path);
} else {
LogInfo("Meet file(" << path << ") in secure-storage! "
"Let's save it into key-manager.");
@@ -210,32 +138,24 @@ void visit_dir(const std::string &dirpath, struct dirent *buf, size_t depth,
data.type = DataType::BINARY_DATA;
data.data = read_data(path, storage_name);
- if (data.data.empty()) {
+ if (data.data.empty())
LogError("Failed to read data from file: " << path);
- } else if (storage_name == "secure-storage") {
+ else if (storage_name == "secure-storage")
LogInfo("Meet secure-storage storage which contains SALT! skip it!");
- } else if (storage_name.rfind(OLD_SS_GROUP_PREFIX) == std::string::npos) {
- LogInfo("data file(" << path << ") is not in group! "
- "smack-label is used as storage name");
- saver(storage_name, name, data);
- } else {
- LogInfo("data file(" << path << ") is in group! "
- "group id is extracted from dir path");
- saver(storage_name.substr(OLD_SS_GROUP_PREFIX.length()), name, data);
- }
-
- remove_path(path);
+ else
+ saver(name, data, isAdminUser);
}
} else {
LogError("Invalid type(" << result->d_type << ") of file(" << path << ") ");
- remove_path(path);
}
+
+ remove_path(path, isAdminUser);
}
}
} // namespace anonymous
-bool hasMigratableData(void)
+bool hasData(void)
{
if (::access(OLD_SS_DIR.c_str(), R_OK | X_OK) == -1) {
const int err = errno;
@@ -249,7 +169,7 @@ bool hasMigratableData(void)
}
}
-void migrateData(const Saver &saver)
+void migrate(bool isAdminUser, const Saver &saver)
{
if (saver == nullptr) {
LogError("saver cannot be null");
@@ -263,7 +183,8 @@ void migrateData(const Saver &saver)
if (bufptr == nullptr)
throw std::bad_alloc();
- visit_dir(OLD_SS_DIR, bufptr.get(), 0, saver);
+ visit_dir(OLD_SS_DIR, bufptr.get(), 0, saver, isAdminUser);
}
-}
+} // namespace SsMigration
+} // namespace CKM
diff --git a/src/manager/service/ss-migrate.h b/src/manager/service/ss-migrate.h
index 5740aad4..e56b18e1 100644
--- a/src/manager/service/ss-migrate.h
+++ b/src/manager/service/ss-migrate.h
@@ -28,11 +28,13 @@
#include <generic-backend/gstore.h>
namespace CKM {
+namespace SsMigration {
-using Saver = std::function<void(const std::string &owner, const std::string &name,
- const Crypto::Data &data)>;
+using Saver = std::function<void(const std::string &name, const Crypto::Data &data,
+ bool isAdminUser)>;
-bool hasMigratableData(void);
-void migrateData(const Saver &);
+bool hasData(void);
+void migrate(bool isAdminUser, const Saver &);
}
+}