/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * 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.
* See the License for the specific language governing permissions and
* limitations under the License
*/
+#include <fcntl.h>
+#include <openssl/md5.h>
+
+#include <algorithm>
+
#include <klay/filesystem.h>
#include <klay/audit/logger.h>
+#include <klay/exception.h>
+#include "key-generator.h"
#include "key-store.h"
+#ifndef DEBUG
#define FOOTER_FILE_PATH "/opt/etc/.ode_footer"
-#define KEY_SIZE (256 / 8)
+#else
+#define FOOTER_FILE_PATH "/tmp/.ode_footer"
+#endif
+
+#define KEY_SIZE (256 / 8)
+#define KEY_ENTRY_SIZE (KEY_SIZE * 4)
+
+#define KEY_HNAME_OFFSET (KEY_SIZE * 0)
+#define KEY_EDK_OFFSET (KEY_SIZE * 1)
+#define KEY_EMK_OFFSET (KEY_SIZE * 2)
+#define KEY_SALT_OFFSET (KEY_SIZE * 3)
namespace ode {
-KeyStore::KeyStore(const std::string& name) :
- file(FOOTER_FILE_PATH)
+/*
+ * Design: store fixed size 4 elements (NAME, EDK, EMK, Salt)
+ * <------------------ 32 byte --------------------->
+ * 00h |----------- Hashed KeyStore Name ---------------|
+ * 40h |--------------------- EDK ----------------------|
+ * 100h |--------------------- EMK ----------------------|
+ * 140h |--------------------- SALT ---------------------|
+ */
+
+runtime::File file(FOOTER_FILE_PATH);
+int index;
+off_t offset; // Current KeyStore offset
+bool isNewKeyStore; // Current KeyStore has been initialized/saved
+ode::KeyStore::data HNAME(KEY_SIZE); // MD5 Hashed key entry name
+ode::KeyStore::data EDK(KEY_SIZE); // Encrypted Device Encryption Key
+ode::KeyStore::data EMK(KEY_SIZE); // Encrypted Master Key
+ode::KeyStore::data SALT(KEY_SIZE); // Salt
+
+KeyStore::KeyStore(const std::string &name)
{
+ isNewKeyStore = true;
+
+ KeyGenerator keygen(KEY_SIZE);
+ HNAME = keygen.MD5(data(name.begin(), name.end()));
+
+ if (file.exists()) {
+ if (file.size() % KEY_ENTRY_SIZE)
+ throw runtime::Exception("Footer file size couldn't be divided well");
+
+ file.open(O_RDONLY);
+
+ // Try to find the keyStore using hashed store name.
+ // even if we couldn't find offset/index from footer file using the 'name',
+ // we will use final index/offset to store the new store for the given 'name'.
+ int keyCnt = file.size() / KEY_ENTRY_SIZE;
+ for (offset = 0, index = 0; index < keyCnt; offset += KEY_ENTRY_SIZE, index++) {
+ file.lseek(offset, SEEK_SET);
+
+ data CUR_HNAME(KEY_SIZE);
+ file.read(CUR_HNAME.data(), KEY_SIZE);
+
+ if (std::equal(HNAME.begin(), HNAME.begin() + MD5_DIGEST_LENGTH, CUR_HNAME.begin())) {
+ file.read(EDK.data(), KEY_SIZE);
+ file.read(EMK.data(), KEY_SIZE);
+ file.read(SALT.data(), KEY_SIZE);
+ isNewKeyStore = false;
+ break;
+ }
+ }
+
+ file.close();
+ //
+ } else {
+ file.create(0644);
+ index = 0;
+ offset = 0;
+ }
+
+ // expand new key store area
+ if (isNewKeyStore) {
+ file.open(O_WRONLY);
+ file.lseek(offset, SEEK_SET);
+ file.write(HNAME.data(), KEY_SIZE);
+ file.write(EDK.data(), KEY_SIZE);
+ file.write(EMK.data(), KEY_SIZE);
+ file.write(SALT.data(), KEY_SIZE);
+ file.close();
+ }
}
KeyStore::~KeyStore()
return KEY_SIZE;
}
+/*
+ * @brief When KeyStore(name) hasn't been initialized,
+ * User should call getKeySize() and create new keys to store using KeyManager
+ */
bool KeyStore::isInitialized()
{
- //TODO
-
- return false;
+ return (isNewKeyStore != true);
}
KeyStore::data KeyStore::getEDK()
{
- data ret;
-
- //TODO
-
- return ret;
+ return EDK;
}
KeyStore::data KeyStore::getEMK()
{
- data ret;
-
- //TODO
-
- return ret;
+ return EMK;
}
KeyStore::data KeyStore::getSalt()
{
- data ret;
-
- //TODO
-
- return ret;
+ return SALT;
}
-void KeyStore::setEDK(const KeyStore::data& key)
+void KeyStore::setEDK(const KeyStore::data &key)
{
- //TODO
+ EDK = key;
+
+ file.open(O_WRONLY);
+ file.lseek(offset + KEY_EDK_OFFSET, SEEK_SET);
+ file.write(EDK.data(), KEY_SIZE);
+ file.close();
}
-void KeyStore::setEMK(const KeyStore::data& key)
+void KeyStore::setEMK(const KeyStore::data &key)
{
- //TODO
+ EMK = key;
+
+ file.open(O_WRONLY);
+ file.lseek(offset + KEY_EMK_OFFSET, SEEK_SET);
+ file.write(EMK.data(), KEY_SIZE);
+ file.close();
}
-void KeyStore::setSalt(const KeyStore::data& key)
+void KeyStore::setSalt(const KeyStore::data &key)
{
- //TODO
+ SALT = key;
+
+ file.open(O_WRONLY);
+ file.lseek(offset + KEY_SALT_OFFSET, SEEK_SET);
+ file.write(SALT.data(), KEY_SIZE);
+ file.close();
}
} // namespace ode
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * 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.
class KeyStore final {
public:
- KeyStore(const std::string& name);
- KeyStore(const KeyStore&) = delete;
- KeyStore(KeyStore&&) = delete;
+ KeyStore(const std::string &name);
+ KeyStore(const KeyStore &) = delete;
+ KeyStore(KeyStore &&) = delete;
~KeyStore();
- KeyStore& operator=(const KeyStore&) = delete;
- KeyStore& operator=(KeyStore&&) = delete;
+ KeyStore &operator=(const KeyStore &) = delete;
+ KeyStore &operator=(KeyStore &&) = delete;
size_t getKeySize() const;
data getEMK();
data getSalt();
- void setEDK(const data& key);
- void setEMK(const data& key);
- void setSalt(const data& key);
-
-private:
- runtime::File file;
- int index;
+ void setEDK(const data &key);
+ void setEMK(const data &key);
+ void setSalt(const data &key);
};
} // namespace ode