#include "key-generator.h"
#include "key-store.h"
-#ifndef DEBUG
#define FOOTER_FILE_PATH "/opt/etc/.ode_footer"
-#else
-#define FOOTER_FILE_PATH "/tmp/.ode_footer"
-#endif
#define KEY_SIZE (256 / 8)
#define KEY_ENTRY_SIZE (KEY_SIZE * 4)
* 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)
+KeyStore::KeyStore(const std::string &name) :
+ edk(KEY_SIZE), emk(KEY_SIZE), salt(KEY_SIZE)
{
- isNewKeyStore = true;
+ runtime::File file(FOOTER_FILE_PATH);
- KeyGenerator keygen(KEY_SIZE);
- HNAME = keygen.MD5(data(name.begin(), name.end()));
+ hname = KeyGenerator(KEY_SIZE).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");
+ if (!file.exists()) {
+ offset = -1;
+ file.create(0600);
+ file.close();
+ return;
+ }
- file.open(O_RDONLY);
+ 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);
+ //find matched block offset
+ int fileSize = file.size();
+ for (offset = 0; offset < fileSize; offset += KEY_ENTRY_SIZE) {
+ file.lseek(offset, SEEK_SET);
- data CUR_HNAME(KEY_SIZE);
- file.read(CUR_HNAME.data(), KEY_SIZE);
+ data current(KEY_SIZE);
+ file.read(current.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;
- }
+ if (std::equal(hname.begin(), hname.end(), current.begin())) {
+ file.read(edk.data(), KEY_SIZE);
+ file.read(emk.data(), KEY_SIZE);
+ file.read(salt.data(), KEY_SIZE);
+ file.close();
+ return;
}
-
- 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();
- }
+ offset = -1;
+ 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()
+bool KeyStore::isInitialized() const
{
- return (isNewKeyStore != true);
+ return offset >= 0;
}
-KeyStore::data KeyStore::getEDK()
+KeyStore::data KeyStore::getEDK() const
{
- return EDK;
+ if (offset < 0) {
+ throw runtime::Exception("Store is empty");
+ }
+ return edk;
}
-KeyStore::data KeyStore::getEMK()
+KeyStore::data KeyStore::getEMK() const
{
- return EMK;
+ if (offset < 0) {
+ throw runtime::Exception("Store is empty");
+ }
+ return emk;
}
-KeyStore::data KeyStore::getSalt()
+KeyStore::data KeyStore::getSalt() const
{
- return SALT;
+ if (offset < 0) {
+ throw runtime::Exception("Store is empty");
+ }
+ return salt;
}
void KeyStore::setEDK(const KeyStore::data &key)
{
- EDK = key;
-
- file.open(O_WRONLY);
- file.lseek(offset + KEY_EDK_OFFSET, SEEK_SET);
- file.write(EDK.data(), KEY_SIZE);
- file.close();
+ edk = key;
}
void KeyStore::setEMK(const KeyStore::data &key)
{
- EMK = key;
+ emk = key;
+}
- file.open(O_WRONLY);
- file.lseek(offset + KEY_EMK_OFFSET, SEEK_SET);
- file.write(EMK.data(), KEY_SIZE);
+void KeyStore::setSalt(const KeyStore::data &key)
+{
+ salt = key;
+}
+
+void KeyStore::flush()
+{
+ runtime::File file(FOOTER_FILE_PATH);
+
+ file.open(O_RDWR);
+
+ if (offset < 0) {
+ //find empty block offset
+ int fileSize = file.size();
+ data empty = KeyGenerator(KEY_SIZE).MD5(data(0));
+
+ for (offset = 0; offset < fileSize; offset += KEY_ENTRY_SIZE) {
+ file.lseek(offset, SEEK_SET);
+
+ data current(KEY_SIZE);
+ file.read(current.data(), KEY_SIZE);
+
+ if (std::equal(empty.begin(), empty.end(), current.begin())) {
+ break;
+ }
+ }
+ }
+
+ 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();
}
-void KeyStore::setSalt(const KeyStore::data &key)
+void KeyStore::remove()
{
- SALT = key;
+ data empty = KeyGenerator(KEY_SIZE).MD5(data(0));
+ runtime::File file(FOOTER_FILE_PATH);
file.open(O_WRONLY);
- file.lseek(offset + KEY_SALT_OFFSET, SEEK_SET);
- file.write(SALT.data(), KEY_SIZE);
+ file.lseek(offset, SEEK_SET);
+ file.write(empty.data(), KEY_SIZE);
file.close();
+
+ offset = -1;
}
} // namespace ode