Support for migration from 3.0 19/182719/6
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 27 Jun 2018 09:08:57 +0000 (11:08 +0200)
committerJaemin Ryu <jm77.ryu@samsung.com>
Thu, 26 Jul 2018 05:12:18 +0000 (05:12 +0000)
There are products based on Tizen 3.0 using different encryption scheme and
footer format. To properly migrate their internal memory encryption key the
flag marking the beginning of an upgrade is left by ode-fota.

During the first device unlock(attempt to mount encrypted partition) after the
upgrade the flag presence is checked. The flag is removed but if it was
present, oded will try to use the product specific key storage plugin to load
the master key for internal encryption.

If it succeeds it will encrypt the master key using given password. Otherwise
it will fall back to normal operation, that is, decrypt the master key using
given password.

Any attempt to decrypt the master key using a password will result in removal
of the upgrade flag.

It is assumed that affected products verify the password prior to passing it to
ode_internal_encryption_set_mount_password().

For unaffected products that do not require the migration it's enough to remove
the flag or the master key stored for the purpose of the upgrade before calling
ode_internal_encryption_set_mount_password(). Note that it is advised to remove
the master key stored for the purpose of the upgrade as soon as possible after
the upgrade due to security reasons. Even if the flag and master key are
present, the encryption introduced in this commit won't break anything as long
as the password is correct.

Change-Id: I86c83366c432aa8ce1d4f25c9beeed98d4f672c3

fota/fota.cpp
server/internal-encryption.cpp
server/key-server.cpp
server/key-server.h
server/upgrade-support.cpp
server/upgrade-support.h

index 499ff946729fdcaa64125533b9c52d9d6e6a7ec6..7c7c46c1c3a2c225b29b64d55ad90a4d06115239 100644 (file)
@@ -157,6 +157,7 @@ int main(int argc, char* argv[])
 
                        // mount options are ignored by mount()
                        dmcrypt.mount(masterKey, 0);
+                       UpgradeSupport::createUpgradeFlag();
                } else if (UMOUNT == argv[1]) {
                        std::string path = INTERNAL_PATH;
                        if (argc == 3)
index bf7cc9929226dc60b2634b3a46374e72888fed23..2791620ea98da1da96e5859feba77e06d2ab0b0e 100644 (file)
@@ -46,6 +46,7 @@
 #include "ext4-tool.h"
 #include "internal-encryption.h"
 #include "internal-encryption-common.h"
+#include "upgrade-support.h"
 
 namespace ode {
 
@@ -395,7 +396,23 @@ InternalEncryptionServer::~InternalEncryptionServer()
 
 int InternalEncryptionServer::setMountPassword(const std::string& password)
 {
-       return keyServer.get(engine->getSource(), password, mountKey);
+       const std::string& dev = engine->getSource();
+
+       // check if upgrade flag exists
+       if(UpgradeSupport::removeUpgradeFlag()) {
+               INFO("Upgrade flag detected.");
+               // try to load the master key
+               try {
+                       mountKey = UpgradeSupport::loadMasterKey(dev);
+
+                       // encrypt the master key with given password
+                       return keyServer.changePassword2(dev, mountKey, password);
+               } catch (const runtime::Exception&) {
+                       INFO("Failed to load the master key stored during upgrade.");
+               }
+       }
+
+       return keyServer.get(dev, password, mountKey);
 }
 
 int InternalEncryptionServer::mount(const std::vector<unsigned char> &mk, unsigned int options)
index 4ab65414258f1f8402e590d61ed6178b25722f19..2dc279bdec4cf4e976339a98b02518875def2d8b 100644 (file)
@@ -123,6 +123,8 @@ int KeyServer::changePassword(const std::string& dev,
                return error::NoSuchFile;
        }
 
+       UpgradeSupport::removeUpgradeFlag();
+
        EncryptedKey ek(FileFooter::read(dev));
 
        auto key = ek.decrypt(curPassword);
@@ -137,6 +139,20 @@ int KeyServer::changePassword(const std::string& dev,
        return error::None;
 }
 
+int KeyServer::changePassword2(const std::string& dev,
+                                                          const BinaryData& masterKey,
+                                                          const std::string& newPassword)
+{
+       if (dev.empty() || masterKey.empty() || newPassword.empty())
+               return error::InvalidParameter;
+
+       std::lock_guard<std::mutex> lock(footerLock);
+       EncryptedKey ek(masterKey, newPassword);
+
+       FileFooter::write(dev, ek.serialize());
+       return error::None;
+}
+
 int KeyServer::verifyPassword(const std::string& dev,
                                                          const std::string& password)
 {
@@ -214,6 +230,8 @@ int KeyServer::internalGet(const std::string& dev,
                return error::NoSuchFile;
        }
 
+       UpgradeSupport::removeUpgradeFlag();
+
        EncryptedKey ek(FileFooter::read(dev));
 
        key = ek.decrypt(password);
index a37f442ce017f96515555ad8da2c54d6f2a2ae82..fbe7ddeef1d71ee97b81c00ffc8774a4915ab6c4 100644 (file)
@@ -40,6 +40,9 @@ public:
        int changePassword(const std::string& dev,
                                           const std::string& curPW,
                                           const std::string& newPW);
+       int changePassword2(const std::string& dev,
+                                               const BinaryData& masterKey,
+                                               const std::string& newPW);
        int verifyPassword(const std::string& dev, const std::string& password);
        int get(const std::string& dev,
                        const std::string& password,
index 2195603e2fa33a6b1271b70c3e3c964b53dd7476..3afad93019a0ff8bb078c8d1583d7751cabda264 100644 (file)
@@ -46,6 +46,8 @@ typedef int(*KeyStoragePluginLoadFn)(const unsigned char*, size_t,
 typedef int(*KeyStoragePluginRemoveFn)(const unsigned char*, size_t);
 }
 
+const std::string UPGRADE_FLAG_PATH = "/opt/etc/.ode_upgrade_started";
+
 std::mutex opGuard;
 
 // not thread-safe because of static member
@@ -248,6 +250,22 @@ void removeMasterKey(const std::string &device)
        }
 }
 
+void createUpgradeFlag()
+{
+       runtime::File file(UPGRADE_FLAG_PATH);
+       file.create(S_IRUSR | S_IWUSR); // 0600
+}
+
+bool removeUpgradeFlag()
+{
+       runtime::File file(UPGRADE_FLAG_PATH);
+       bool exists = file.exists();
+       if (exists)
+               file.remove();
+
+       return exists;
+}
+
 } // namespace UpgradeSupport
 
 } // namespace ode
index 4a029b8b1858ed2856332aed6a046bf7f6d8f1cc..2854072f87c4bce65b6f0ba3078dcb4d86e15c80 100644 (file)
@@ -28,6 +28,8 @@ namespace UpgradeSupport {
 void storeMasterKey(const std::string &device, const BinaryData& key);
 BinaryData loadMasterKey(const std::string &device);
 void removeMasterKey(const std::string &device);
+void createUpgradeFlag();
+bool removeUpgradeFlag();
 
 } // namespace UpgradeSupport