Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 55181)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 55182)
@@ -301,4 +301,46 @@
     return rcExit;
 }
+
+RTEXITCODE readPasswordFromConsole(com::Utf8Str *pPassword, const char *pszPrompt, ...)
+{
+    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
+    char aszPwdInput[_1K] = { 0 };
+    va_list vaArgs;
+
+    va_start(vaArgs, pszPrompt);
+    int vrc = RTStrmPrintfV(g_pStdOut, pszPrompt, vaArgs);
+    if (RT_SUCCESS(vrc))
+    {
+        bool fEchoOld = false;
+        vrc = RTStrmInputGetEchoChars(g_pStdIn, &fEchoOld);
+        if (RT_SUCCESS(vrc))
+        {
+            vrc = RTStrmInputSetEchoChars(g_pStdIn, false);
+            if (RT_SUCCESS(vrc))
+            {
+                vrc = RTStrmGetLine(g_pStdIn, &aszPwdInput[0], sizeof(aszPwdInput));
+                if (RT_SUCCESS(vrc))
+                    *pPassword = aszPwdInput;
+                else
+                    rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed read password from command line (%Rrc)", vrc);
+
+                int vrc2 = RTStrmInputSetEchoChars(g_pStdIn, fEchoOld);
+                AssertRC(vrc2);
+            }
+            else
+                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to disable echoing typed characters (%Rrc)", vrc);
+        }
+        else
+            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to retrieve echo setting (%Rrc)", vrc);
+
+        RTStrmPutStr(g_pStdOut, "\n");
+    }
+    else
+        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to print prompt (%Rrc)", vrc);
+    va_end(vaArgs);
+
+    return rcExit;
+}
+
 #endif
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 55181)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 55182)
@@ -188,4 +188,5 @@
 #ifndef VBOX_ONLY_DOCS
 RTEXITCODE readPasswordFile(const char *pszFilename, com::Utf8Str *pPasswd);
+RTEXITCODE readPasswordFromConsole(com::Utf8Str *pPassword, const char *pszPrompt, ...);
 
 int handleInternalCommands(HandlerArg *a);
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp	(revision 55181)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp	(revision 55182)
@@ -1202,4 +1202,31 @@
             break;
 
+        /* Query required passwords and supply them to the appliance. */
+        com::SafeArray<BSTR> aIdentifiers;
+
+        CHECK_ERROR_BREAK(pAppliance, GetPasswordIds(ComSafeArrayAsOutParam(aIdentifiers)));
+
+        if (aIdentifiers.size() > 0)
+        {
+            com::SafeArray<BSTR> aPasswords(aIdentifiers.size());
+            RTPrintf("Enter the passwords for the following identifiers to export the apppliance:\n");
+            for (unsigned idxId = 0; idxId < aIdentifiers.size(); idxId++)
+            {
+                com::Utf8Str strPassword;
+                Bstr bstrPassword;
+                Bstr bstrId = aIdentifiers[idxId];
+
+                RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Password ID %s:", Utf8Str(bstrId).c_str());
+                if (rcExit == RTEXITCODE_FAILURE)
+                    return rcExit;
+
+                bstrPassword = strPassword;
+                bstrPassword.detachTo(&aPasswords[idxId]);
+            }
+
+            CHECK_ERROR_BREAK(pAppliance, AddPasswords(ComSafeArrayAsInParam(aIdentifiers),
+                                                       ComSafeArrayAsInParam(aPasswords)));
+        }
+
         if (fManifest)
             options.push_back(ExportOptions_CreateManifest);
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp	(revision 55181)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp	(revision 55182)
@@ -50,32 +50,4 @@
     RTMsgErrorV(pszFormat, va);
     RTMsgError("Error code %Rrc at %s(%u) in function %s", rc, RT_SRC_POS_ARGS);
-}
-
-static int getPassword(const char *pszPrompt, Utf8Str *pPassword)
-{
-    char aszPwdInput[_1K] = { 0 };
-
-    int vrc = RTStrmPutStr(g_pStdOut, pszPrompt);
-    if (RT_SUCCESS(vrc))
-    {
-        bool fEchoOld = false;
-        vrc = RTStrmInputGetEchoChars(g_pStdIn, &fEchoOld);
-        if (RT_SUCCESS(vrc))
-        {
-            vrc = RTStrmInputSetEchoChars(g_pStdIn, false);
-            if (RT_SUCCESS(vrc))
-            {
-                vrc = RTStrmGetLine(g_pStdIn, &aszPwdInput[0], sizeof(aszPwdInput));
-                if (RT_SUCCESS(vrc))
-                    *pPassword = aszPwdInput;
-
-                int vrc2 = RTStrmInputSetEchoChars(g_pStdIn, fEchoOld);
-                AssertRC(vrc2);
-            }
-        }
-        RTStrmPutStr(g_pStdOut, "\n");
-    }
-
-    return vrc;
 }
 
@@ -1767,10 +1739,7 @@
         {
             /* Get password from console. */
-            vrc = getPassword("Enter new password:", &strPasswordNew);
-            if (RT_FAILURE(vrc))
-            {
-                RTMsgError("Failed to read new password from standard input");
-                return 1;
-            }
+            RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordNew, "Enter new password:");
+            if (rcExit == RTEXITCODE_FAILURE)
+                return rcExit;
         }
         else
@@ -1790,10 +1759,7 @@
         {
             /* Get password from console. */
-            vrc = getPassword("Enter old password:", &strPasswordOld);
-            if (RT_FAILURE(vrc))
-            {
-                RTMsgError("Failed to read old password from standard input");
-                return 1;
-            }
+            RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordOld, "Enter old password:");
+            if (rcExit == RTEXITCODE_FAILURE)
+                return rcExit;
         }
         else
@@ -1857,10 +1823,7 @@
     {
         /* Get password from console. */
-        vrc = getPassword("Enter password:", &strPassword);
-        if (RT_FAILURE(vrc))
-        {
-            RTMsgError("Failed to read password from standard input");
-            return 1;
-        }
+        RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter password:");
+        if (rcExit == RTEXITCODE_FAILURE)
+            return rcExit;
     }
     else
Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 55181)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 55182)
@@ -357,4 +357,5 @@
 	src-all/ProgressImpl.cpp \
 	src-all/QMTranslatorImpl.cpp \
+	src-all/SecretKeyStore.cpp \
 	src-all/SharedFolderImpl.cpp \
 	src-all/AutoCaller.cpp \
@@ -716,4 +717,5 @@
 	src-all/PCIDeviceAttachmentImpl.cpp \
 	src-all/ProgressImpl.cpp \
+	src-all/SecretKeyStore.cpp \
 	src-all/SharedFolderImpl.cpp \
 	src-all/AutoCaller.cpp \
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 55181)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 55182)
@@ -2987,5 +2987,5 @@
   <interface
     name="IAppliance" extends="$unknown"
-    uuid="3059cf9e-25c7-4f0b-9fa5-3c42e441670b"
+    uuid="d9432012-2740-499f-b3b3-0991da3679f3"
     wsmap="managed"
     >
@@ -3240,4 +3240,30 @@
       <param name="warnings" type="wstring" dir="return" safearray="yes">
         <desc></desc>
+      </param>
+    </method>
+
+    <method name="getPasswordIds">
+      <desc>
+        Returns a list of password identifiers which must be supplied to import or export
+        encrypted virtual machines.
+      </desc>
+
+      <param name="identifiers" type="wstring" dir="return" safearray="yes">
+        The list of password identifiers required on success.
+      </param>
+    </method>
+
+    <method name="addPasswords">
+      <desc>
+        Adds a list of passwords required to import or export encrypted virtual
+        machines.
+      </desc>
+
+      <param name="identifiers" type="wstring" dir="in" safearray="yes">
+        <desc>List of identifiers.</desc>
+      </param>
+
+      <param name="passwords" type="wstring" dir="in" safearray="yes">
+        <desc>List of matching passwords.</desc>
       </param>
     </method>
Index: /trunk/src/VBox/Main/include/MediumImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MediumImpl.h	(revision 55181)
+++ /trunk/src/VBox/Main/include/MediumImpl.h	(revision 55182)
@@ -24,4 +24,5 @@
 #include "VirtualBoxBase.h"
 #include "AutoCaller.h"
+#include "SecretKeyStore.h"
 class Progress;
 class MediumFormat;
@@ -204,4 +205,5 @@
                          const ComObjPtr<MediumFormat> &aFormat,
                          MediumVariant_T aVariant,
+                         SecretKeyStore *pKeyStore,
                          PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
                          const ComObjPtr<Progress> &aProgress);
@@ -216,4 +218,6 @@
                         const ComObjPtr<Medium> &aParent, IProgress **aProgress,
                         uint32_t idxSrcImageSame, uint32_t idxDstImageSame);
+
+    const Utf8Str& i_getKeyId();
 
 private:
Index: /trunk/src/VBox/Main/include/SecretKeyStore.h
===================================================================
--- /trunk/src/VBox/Main/include/SecretKeyStore.h	(revision 55182)
+++ /trunk/src/VBox/Main/include/SecretKeyStore.h	(revision 55182)
@@ -0,0 +1,189 @@
+/** @file
+ * Main - Secret key interface.
+ */
+
+/*
+ * Copyright (C) 2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_SECRETKEYSTORE
+#define ____H_SECRETKEYSTORE
+
+#include "VirtualBoxBase.h"
+#include "VBox/com/array.h"
+
+class SecretKey
+{
+    public:
+
+        /**
+         * Constructor for a secret key.
+         *
+         * @param pbKey                 The key buffer.
+         * @param cbKey                 Size of the key.
+         * @param fKeyBufNonPageable    Flag whether the key buffer should be non pageable.
+         */
+        SecretKey(const uint8_t *pbKey, size_t cbKey, bool fKeyBufNonPageable);
+
+        /**
+         * Secret key destructor.
+         */
+        ~SecretKey();
+
+        /**
+         * Increments the reference counter of the key.
+         *
+         * @returns The new reference count.
+         */
+        uint32_t retain();
+
+        /**
+         * Releases a reference of the key.
+         * If the reference counter reaches 0 the key buffer might be protected
+         * against further access or the data will become scrambled.
+         *
+         * @returns The new reference count.
+         */
+        uint32_t release();
+
+        /**
+         * Returns the reference count of the secret key.
+         */
+        uint32_t refCount();
+
+        /**
+         * Sets the possible number of users for this key.
+         *
+         * @returns VBox status code.
+         * @param   cUsers              The possible number of user for this key.
+         */
+        int setUsers(uint32_t cUsers);
+
+        /**
+         * Returns the possible amount of users.
+         *
+         * @returns Possible amount of users.
+         */
+        uint32_t getUsers();
+
+        /**
+         * Sets the remove on suspend flag.
+         *
+         * @returns VBox status code.
+         * @param   fRemoveOnSuspend    Flag whether to remove the key on host suspend.
+         */
+        int setRemoveOnSuspend(bool fRemoveOnSuspend);
+
+        /**
+         * Returns whether the key should be destroyed on suspend.
+         */
+        bool getRemoveOnSuspend();
+
+        /**
+         * Returns the buffer to the key.
+         */
+        const void *getKeyBuffer();
+
+        /**
+         * Returns the size of the key.
+         */
+        size_t getKeySize();
+
+    private:
+        /** Reference counter of the key. */
+        volatile uint32_t m_cRefs;
+        /** Key material. */
+        uint8_t          *m_pbKey;
+        /** Size of the key in bytes. */
+        size_t            m_cbKey;
+        /** Flag whether to remove the key on suspend. */
+        bool              m_fRemoveOnSuspend;
+        /** Number of entities which will use this key. */
+        uint32_t          m_cUsers;
+};
+
+class SecretKeyStore
+{
+    public:
+
+        /**
+         * Constructor for a secret key store.
+         *
+         * @param fKeyBufNonPageable    Flag whether the key buffer is required to
+         *                              be non pageable.
+         */
+        SecretKeyStore(bool fKeyBufNonPageable);
+
+        /**
+         * Destructor of a secret key store. This will free all stored secret keys
+         * inluding the key buffers. Make sure there no one accesses one of the keys
+         * stored.
+         */
+        ~SecretKeyStore();
+
+        /**
+         * Add a secret key to the store.
+         *
+         * @returns VBox status code.
+         * @param   strKeyId            The key identifier.
+         * @param   pbKey               The key to store.
+         * @param   cbKey               Size of the key.
+         */
+        int addSecretKey(const com::Utf8Str &strKeyId, const uint8_t *pbKey, size_t cbKey);
+
+        /**
+         * Deletes a key from the key store associated with the given identifier.
+         *
+         * @returns VBox status code.
+         * @param   strKeyId            The key identifier.
+         */
+        int deleteSecretKey(const com::Utf8Str &strKeyId);
+
+        /**
+         * Returns the secret key object associated with the given identifier.
+         * This increments the reference counter of the secret key object.
+         *
+         * @returns VBox status code.
+         * @param   strKeyId            The key identifier.
+         * @param   ppKey               Where to store the secret key object on success.
+         */
+        int retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey);
+
+        /**
+         * Releases a reference to the secret key object.
+         *
+         * @returns VBox status code.
+         * @param   strKeyId            The key identifier.
+         */
+        int releaseSecretKey(const com::Utf8Str &strKeyId);
+
+        /**
+         * Deletes all secret keys from the key store.
+         *
+         * @returns VBox status code.
+         * @param   fSuspend           Flag whether to delete only keys which are
+         *                             marked for deletion during a suspend.
+         * @param   fForce             Flag whether to force deletion if some keys
+         *                             are still in use. Otherwise an error is returned.
+         */
+        int deleteAllSecretKeys(bool fSuspend, bool fForce);
+
+    private:
+
+        typedef std::map<com::Utf8Str, SecretKey *> SecretKeyMap;
+
+        /** The map to map key identifers to secret keys. */
+        SecretKeyMap m_mapSecretKeys;
+        /** Flag whether key buffers should be non pagable. */
+        bool         m_fKeyBufNonPageable;
+};
+
+#endif  /* !____H_SECRETKEYSTORE */
Index: /trunk/src/VBox/Main/src-all/SecretKeyStore.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/SecretKeyStore.cpp	(revision 55182)
+++ /trunk/src/VBox/Main/src-all/SecretKeyStore.cpp	(revision 55182)
@@ -0,0 +1,228 @@
+/* $Id$ */
+/** @file
+ * Main - Secret key interface.
+ */
+
+/*
+ * Copyright (C) 2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/memsafer.h>
+
+#include "SecretKeyStore.h"
+
+SecretKey::SecretKey(const uint8_t *pbKey, size_t cbKey, bool fKeyBufNonPageable)
+{
+    m_cRefs            = 0;
+    m_fRemoveOnSuspend = false;
+    m_cUsers           = 0;
+    m_cbKey            = cbKey;
+
+    int rc = RTMemSaferAllocZEx((void **)&this->m_pbKey, cbKey,
+                                fKeyBufNonPageable ? RTMEMSAFER_F_REQUIRE_NOT_PAGABLE : 0);
+    if (RT_SUCCESS(rc))
+    {
+        memcpy(this->m_pbKey, pbKey, cbKey);
+
+        /* Scramble content to make retrieving the key more difficult. */
+        rc = RTMemSaferScramble(this->m_pbKey, cbKey);
+    }
+    else
+        throw rc;
+}
+
+SecretKey::~SecretKey()
+{
+    Assert(!m_cRefs);
+
+    RTMemSaferFree(m_pbKey, m_cbKey);
+    m_cRefs = 0;
+    m_pbKey = NULL;
+    m_cbKey = 0;
+    m_fRemoveOnSuspend = false;
+    m_cUsers = 0;
+}
+
+uint32_t SecretKey::retain()
+{
+    uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
+    if (cRefs == 1)
+    {
+        int rc = RTMemSaferUnscramble(m_pbKey, m_cbKey);
+        AssertRC(rc);
+    }
+
+    return cRefs;
+}
+
+uint32_t SecretKey::release()
+{
+    uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
+    if (!cRefs)
+    {
+        int rc = RTMemSaferScramble(m_pbKey, m_cbKey);
+        AssertRC(rc);
+    }
+
+    return cRefs;
+}
+
+uint32_t SecretKey::refCount()
+{
+    return m_cRefs;
+}
+
+int SecretKey::setUsers(uint32_t cUsers)
+{
+    m_cUsers = cUsers;
+    return VINF_SUCCESS;
+}
+
+uint32_t SecretKey::getUsers()
+{
+    return m_cUsers;
+}
+
+int SecretKey::setRemoveOnSuspend(bool fRemoveOnSuspend)
+{
+    m_fRemoveOnSuspend = fRemoveOnSuspend;
+    return VINF_SUCCESS;
+}
+
+bool SecretKey::getRemoveOnSuspend()
+{
+    return m_fRemoveOnSuspend;
+}
+
+const void *SecretKey::getKeyBuffer()
+{
+    AssertReturn(m_cRefs > 0, NULL);
+    return m_pbKey;
+}
+
+size_t SecretKey::getKeySize()
+{
+    return m_cbKey;
+}
+
+SecretKeyStore::SecretKeyStore(bool fKeyBufNonPageable)
+{
+    m_fKeyBufNonPageable = fKeyBufNonPageable;
+}
+
+SecretKeyStore::~SecretKeyStore()
+{
+    int rc = deleteAllSecretKeys(false /* fSuspend */, true /* fForce */);
+    AssertRC(rc);
+}
+
+int SecretKeyStore::addSecretKey(const com::Utf8Str &strKeyId, const uint8_t *pbKey, size_t cbKey)
+{
+    /* Check that the ID is not existing already. */
+    SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
+    if (it != m_mapSecretKeys.end())
+        return VERR_ALREADY_EXISTS;
+
+    try
+    {
+        SecretKey *pKey = new SecretKey(pbKey, cbKey, m_fKeyBufNonPageable);
+
+        m_mapSecretKeys.insert(std::make_pair(strKeyId, pKey));
+    }
+    catch (int rc)
+    {
+        return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+
+int SecretKeyStore::deleteSecretKey(const com::Utf8Str &strKeyId)
+{
+    SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
+    if (it == m_mapSecretKeys.end())
+        return VERR_NOT_FOUND;
+
+    SecretKey *pKey = it->second;
+    if (pKey->refCount() != 0)
+        return VERR_RESOURCE_IN_USE;
+
+    m_mapSecretKeys.erase(it);
+    delete pKey;
+
+    return VINF_SUCCESS;
+}
+
+int SecretKeyStore::retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey)
+{
+    SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
+    if (it == m_mapSecretKeys.end())
+        return VERR_NOT_FOUND;
+
+    SecretKey *pKey = it->second;
+    pKey->retain();
+
+    *ppKey = pKey;
+
+    return VINF_SUCCESS;
+}
+
+int SecretKeyStore::releaseSecretKey(const com::Utf8Str &strKeyId)
+{
+    SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
+    if (it == m_mapSecretKeys.end())
+        return VERR_NOT_FOUND;
+
+    SecretKey *pKey = it->second;
+    pKey->release();
+    return VINF_SUCCESS;
+}
+
+int SecretKeyStore::deleteAllSecretKeys(bool fSuspend, bool fForce)
+{
+    /* First check whether a key is still in use. */
+    if (!fForce)
+    {
+        for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
+             it != m_mapSecretKeys.end();
+             it++)
+        {
+            SecretKey *pKey = it->second;
+            if (   pKey->refCount()
+                && (   (   pKey->getRemoveOnSuspend()
+                        && fSuspend)
+                    || !fSuspend))
+                return VERR_RESOURCE_IN_USE;
+        }
+    }
+
+    SecretKeyMap::iterator it = m_mapSecretKeys.begin();
+    while (it != m_mapSecretKeys.end())
+    {
+        SecretKey *pKey = it->second;
+        if (   pKey->getRemoveOnSuspend()
+            || !fSuspend)
+        {
+            AssertMsg(!pKey->refCount(), ("No one should access the stored key at this point anymore!\n"));
+            delete pKey;
+            m_mapSecretKeys.erase(it++);
+        }
+        else
+            it++;
+    }
+
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 55181)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 55182)
@@ -430,4 +430,5 @@
 #endif
     , mBusMgr(NULL)
+    , m_pKeyStore(NULL)
     , mpIfSecKey(NULL)
     , mpIfSecKeyHlp(NULL)
@@ -627,4 +628,7 @@
 #endif
 
+        unconst(m_pKeyStore) = new SecretKeyStore(true /* fKeyBufNonPageable */);
+        AssertReturn(m_pKeyStore, E_FAIL);
+
         /* VirtualBox events registration. */
         {
@@ -768,4 +772,10 @@
     }
 
+    if (m_pKeyStore)
+    {
+        delete m_pKeyStore;
+        unconst(m_pKeyStore) = NULL;
+    }
+
     m_mapGlobalSharedFolders.clear();
     m_mapMachineSharedFolders.clear();
@@ -774,10 +784,4 @@
     mRemoteUSBDevices.clear();
     mUSBDevices.clear();
-
-    for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
-         it != m_mapSecretKeys.end();
-         it++)
-        delete it->second;
-    m_mapSecretKeys.clear();
 
     if (mVRDEServerInfo)
@@ -3368,28 +3372,23 @@
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    /* Check that the ID is not existing already. */
-    SecretKeyMap::const_iterator it = m_mapSecretKeys.find(aId);
-    if (it != m_mapSecretKeys.end())
-        return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
-
     HRESULT hrc = S_OK;
     size_t cbKey = aPassword.length() + 1; /* Include terminator */
-    uint8_t *pbKey = NULL;
-    int rc = RTMemSaferAllocZEx((void **)&pbKey, cbKey, RTMEMSAFER_F_REQUIRE_NOT_PAGABLE);
+    const uint8_t *pbKey = (const uint8_t *)aPassword.c_str();
+
+    int rc = m_pKeyStore->addSecretKey(aId, pbKey, cbKey);
     if (RT_SUCCESS(rc))
     {
         unsigned cDisksConfigured = 0;
-        memcpy(pbKey, aPassword.c_str(), cbKey);
-
-        /* Scramble content to make retrieving the key more difficult. */
-        rc = RTMemSaferScramble(pbKey, cbKey);
-        AssertRC(rc);
-        SecretKey *pKey = new SecretKey(pbKey, cbKey, !!aClearOnSuspend);
-        /* Add the key to the map */
-        m_mapSecretKeys.insert(std::make_pair(aId, pKey));
+
         hrc = i_configureEncryptionForDisk(aId, &cDisksConfigured);
         if (SUCCEEDED(hrc))
         {
-            pKey->m_cDisks = cDisksConfigured;
+            SecretKey *pKey = NULL;
+            rc = m_pKeyStore->retainSecretKey(aId, &pKey);
+            AssertRCReturn(rc, E_FAIL);
+
+            pKey->setUsers(cDisksConfigured);
+            pKey->setRemoveOnSuspend(!!aClearOnSuspend);
+            m_pKeyStore->releaseSecretKey(aId);
             m_cDisksPwProvided += cDisksConfigured;
 
@@ -3411,9 +3410,11 @@
             }
         }
-        else
-            m_mapSecretKeys.erase(aId);
-    }
+    }
+    else if (rc == VERR_ALREADY_EXISTS)
+        hrc = setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
+    else if (rc == VERR_NO_MEMORY)
+        hrc = setError(E_FAIL, tr("Failed to allocate enough secure memory for the key"));
     else
-        return setError(E_FAIL, tr("Failed to allocate secure memory for the password (%Rrc)"), rc);
+        hrc = setError(E_FAIL, tr("Unknown error happened while adding a password (%Rrc)"), rc);
 
     return hrc;
@@ -3437,34 +3438,18 @@
     for (unsigned i = 0; i < aIds.size(); i++)
     {
-        SecretKeyMap::const_iterator it = m_mapSecretKeys.find(aIds[i]);
-        if (it != m_mapSecretKeys.end())
+        SecretKey *pKey = NULL;
+        int rc = m_pKeyStore->retainSecretKey(aIds[i], &pKey);
+        if (rc != VERR_NOT_FOUND)
+        {
+            AssertPtr(pKey);
+            if (pKey)
+                pKey->release();
             return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
+        }
     }
 
     for (unsigned i = 0; i < aIds.size(); i++)
     {
-        size_t cbKey = aPasswords[i].length() + 1; /* Include terminator */
-        uint8_t *pbKey = NULL;
-        int rc = RTMemSaferAllocZEx((void **)&pbKey, cbKey, RTMEMSAFER_F_REQUIRE_NOT_PAGABLE);
-        if (RT_SUCCESS(rc))
-        {
-            unsigned cDisksConfigured = 0;
-            memcpy(pbKey, aPasswords[i].c_str(), cbKey);
-
-            /* Scramble content to make retrieving the key more difficult. */
-            rc = RTMemSaferScramble(pbKey, cbKey);
-            AssertRC(rc);
-            SecretKey *pKey = new SecretKey(pbKey, cbKey, !!aClearOnSuspend);
-            /* Add the key to the map */
-            m_mapSecretKeys.insert(std::make_pair(aIds[i], pKey));
-            hrc = i_configureEncryptionForDisk(aIds[i], &cDisksConfigured);
-            if (FAILED(hrc))
-                m_mapSecretKeys.erase(aIds[i]);
-            else
-                pKey->m_cDisks = cDisksConfigured;
-        }
-        else
-            hrc = setError(E_FAIL, tr("Failed to allocate secure memory for the password (%Rrc)"), rc);
-
+        hrc = addDiskEncryptionPassword(aIds[i], aPasswords[i], aClearOnSuspend);
         if (FAILED(hrc))
         {
@@ -3484,21 +3469,4 @@
     }
 
-    if (   SUCCEEDED(hrc)
-        && m_cDisksPwProvided == m_cDisksEncrypted
-        && mMachineState == MachineState_Paused)
-    {
-        /* get the VM handle. */
-        SafeVMPtr ptrVM(this);
-        if (!ptrVM.isOk())
-            return ptrVM.rc();
-
-        alock.release();
-        int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG);
-
-        hrc = RT_SUCCESS(vrc) ? S_OK :
-                setError(VBOX_E_VM_ERROR,
-                         tr("Could not resume the machine execution (%Rrc)"), vrc);
-    }
-
     return hrc;
 }
@@ -3511,15 +3479,19 @@
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    SecretKeyMap::iterator it = m_mapSecretKeys.find(aId);
-    if (it == m_mapSecretKeys.end())
-        return setError(VBOX_E_OBJECT_NOT_FOUND, tr("A password with the given ID does not exist"));
-
-    SecretKey *pKey = it->second;
-    if (pKey->m_cRefs)
-        return setError(VBOX_E_OBJECT_IN_USE, tr("The password is still in use by the VM"));
-
-    m_cDisksPwProvided -= pKey->m_cDisks;
-    m_mapSecretKeys.erase(it);
-    delete pKey;
+    SecretKey *pKey = NULL;
+    int rc = m_pKeyStore->retainSecretKey(aId, &pKey);
+    if (RT_SUCCESS(rc))
+    {
+        m_cDisksPwProvided -= pKey->getUsers();
+        m_pKeyStore->releaseSecretKey(aId);
+        rc = m_pKeyStore->deleteSecretKey(aId);
+        AssertRCReturn(rc, E_FAIL);
+    }
+    else if (rc == VERR_NOT_FOUND)
+        return setError(VBOX_E_OBJECT_NOT_FOUND, tr("A password with the ID \"%s\" does not exist"),
+                                                 aId.c_str());
+    else
+        return setError(E_FAIL, tr("Failed to remove password with ID \"%s\" (%Rrc)"),
+                                aId.c_str(), rc);
 
     return S_OK;
@@ -3530,22 +3502,11 @@
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    /* First check whether a password is still in use. */
-    for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
-        it != m_mapSecretKeys.end();
-        it++)
-    {
-        SecretKey *pKey = it->second;
-        if (pKey->m_cRefs)
-            return setError(VBOX_E_OBJECT_IN_USE, tr("The password with ID \"%s\" is still in use by the VM"),
-                            it->first.c_str());
-    }
-
-    for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
-        it != m_mapSecretKeys.end();
-        it++)
-        delete it->second;
-    m_mapSecretKeys.clear();
+    int rc = m_pKeyStore->deleteAllSecretKeys(false /* fSuspend */, false /* fForce */);
+    if (rc == VERR_RESOURCE_IN_USE)
+        return setError(VBOX_E_OBJECT_IN_USE, tr("A password is still in use by the VM"));
+    else if (RT_FAILURE(rc))
+        return setError(E_FAIL, tr("Deleting all passwords failed (%Rrc)"));
+
     m_cDisksPwProvided = 0;
-
     return S_OK;
 }
@@ -3598,4 +3559,6 @@
         case StorageControllerType_USB:
             return "Msd";
+        case StorageControllerType_NVMe:
+            return "nvme";
         default:
             return NULL;
@@ -5073,12 +5036,14 @@
                 if (RT_SUCCESS(rc))
                 {
-                    SecretKey *pKey = new SecretKey(pbKey, cbKey, true /* fRemoveOnSuspend */);
-                    /* Add the key to the map */
-                    m_mapSecretKeys.insert(std::make_pair(Utf8Str(pszUuid), pKey));
-                    hrc = i_configureEncryptionForDisk(Utf8Str(pszUuid), NULL);
-                    if (FAILED(hrc))
+                    rc = m_pKeyStore->addSecretKey(Utf8Str(pszUuid), pbKey, cbKey);
+                    if (RT_SUCCESS(rc))
                     {
-                        /* Delete the key from the map. */
-                        m_mapSecretKeys.erase(Utf8Str(pszUuid));
+                        hrc = i_configureEncryptionForDisk(Utf8Str(pszUuid), NULL);
+                        if (FAILED(hrc))
+                        {
+                            /* Delete the key from the map. */
+                            rc = m_pKeyStore->deleteSecretKey(Utf8Str(pszUuid));
+                            AssertRC(rc);
+                        }
                     }
                 }
@@ -5087,4 +5052,6 @@
                                    tr("Failed to decode the key (%Rrc)"),
                                    rc);
+
+                RTMemSaferFree(pbKey, cbKey);
             }
             else
@@ -5133,21 +5100,5 @@
 {
     /* Remove keys which are supposed to be removed on a suspend. */
-    SecretKeyMap::iterator it = m_mapSecretKeys.begin();
-    while (it != m_mapSecretKeys.end())
-    {
-        SecretKey *pKey = it->second;
-        if (pKey->m_fRemoveOnSuspend)
-        {
-            /* Unconfigure disk encryption from all attachments associated with this key. */
-            i_clearDiskEncryptionKeysOnAllAttachmentsWithKeyId(it->first);
-
-            AssertMsg(!pKey->m_cRefs, ("No one should access the stored key at this point anymore!\n"));
-            m_cDisksPwProvided -= pKey->m_cDisks;
-            delete pKey;
-            m_mapSecretKeys.erase(it++);
-        }
-        else
-            it++;
-    }
+    int rc = m_pKeyStore->deleteAllSecretKeys(true /* fSuspend */, true /* fForce */);
 }
 
@@ -10682,16 +10633,14 @@
 
     AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
-    SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
-    if (it != pConsole->m_mapSecretKeys.end())
-    {
-        SecretKey *pKey = (*it).second;
-
-        ASMAtomicIncU32(&pKey->m_cRefs);
-        *ppbKey = pKey->m_pbKey;
-        *pcbKey = pKey->m_cbKey;
-        return VINF_SUCCESS;
-    }
-
-    return VERR_NOT_FOUND;
+    SecretKey *pKey = NULL;
+
+    int rc = pConsole->m_pKeyStore->retainSecretKey(Utf8Str(pszId), &pKey);
+    if (RT_SUCCESS(rc))
+    {
+        *ppbKey = (const uint8_t *)pKey->getKeyBuffer();
+        *pcbKey = pKey->getKeySize();
+    }
+
+    return rc;
 }
 
@@ -10705,13 +10654,5 @@
 
     AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
-    SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
-    if (it != pConsole->m_mapSecretKeys.end())
-    {
-        SecretKey *pKey = (*it).second;
-        ASMAtomicDecU32(&pKey->m_cRefs);
-        return VINF_SUCCESS;
-    }
-
-    return VERR_NOT_FOUND;
+    return pConsole->m_pKeyStore->releaseSecretKey(Utf8Str(pszId));
 }
 
@@ -10725,20 +10666,11 @@
 
     AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
-    SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
-    if (it != pConsole->m_mapSecretKeys.end())
-    {
-        SecretKey *pKey = (*it).second;
-
-        uint32_t cRefs = ASMAtomicIncU32(&pKey->m_cRefs);
-        if (cRefs == 1)
-        {
-            int rc = RTMemSaferUnscramble(pKey->m_pbKey, pKey->m_cbKey);
-            AssertRC(rc);
-        }
-        *ppszPassword = (const char *)pKey->m_pbKey;
-        return VINF_SUCCESS;
-    }
-
-    return VERR_NOT_FOUND;
+    SecretKey *pKey = NULL;
+
+    int rc = pConsole->m_pKeyStore->retainSecretKey(Utf8Str(pszId), &pKey);
+    if (RT_SUCCESS(rc))
+        *ppszPassword = (const char *)pKey->getKeyBuffer();
+
+    return rc;
 }
 
@@ -10752,18 +10684,5 @@
 
     AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
-    SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
-    if (it != pConsole->m_mapSecretKeys.end())
-    {
-        SecretKey *pKey = (*it).second;
-        uint32_t cRefs = ASMAtomicDecU32(&pKey->m_cRefs);
-        if (!cRefs)
-        {
-            int rc = RTMemSaferScramble(pKey->m_pbKey, pKey->m_cbKey);
-            AssertRC(rc);
-        }
-        return VINF_SUCCESS;
-    }
-
-    return VERR_NOT_FOUND;
+    return pConsole->m_pKeyStore->releaseSecretKey(Utf8Str(pszId));
 }
 
Index: /trunk/src/VBox/Main/src-server/ApplianceImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/ApplianceImpl.cpp	(revision 55181)
+++ /trunk/src/VBox/Main/src-server/ApplianceImpl.cpp	(revision 55182)
@@ -404,4 +404,6 @@
     // initialize data
     m = new Data;
+    m->m_pSecretKeyStore = new SecretKeyStore(false /* fRequireNonPageable*/);
+    AssertReturn(m->m_pSecretKeyStore, E_FAIL);
 
     i_initApplianceIONameMap();
@@ -425,4 +427,7 @@
     if (autoUninitSpan.uninitDone())
         return;
+
+    if (m->m_pSecretKeyStore)
+        delete m->m_pSecretKeyStore;
 
     delete m;
@@ -601,4 +606,50 @@
 }
 
+HRESULT Appliance::getPasswordIds(std::vector<com::Utf8Str> &aIdentifiers)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    aIdentifiers = m->m_vecPasswordIdentifiers;
+    return S_OK;
+}
+
+HRESULT Appliance::addPasswords(const std::vector<com::Utf8Str> &aIdentifiers,
+                                const std::vector<com::Utf8Str> &aPasswords)
+{
+    HRESULT hrc = S_OK;
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    /* Check that the IDs do not exist already before changing anything. */
+    for (unsigned i = 0; i < aIdentifiers.size(); i++)
+    {
+        SecretKey *pKey = NULL;
+        int rc = m->m_pSecretKeyStore->retainSecretKey(aIdentifiers[i], &pKey);
+        if (rc != VERR_NOT_FOUND)
+        {
+            AssertPtr(pKey);
+            if (pKey)
+                pKey->release();
+            return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
+        }
+    }
+
+    for (unsigned i = 0; i < aIdentifiers.size() && SUCCEEDED(hrc); i++)
+    {
+        size_t cbKey = aPasswords[i].length() + 1; /* Include terminator */
+        const uint8_t *pbKey = (const uint8_t *)aPasswords[i].c_str();
+
+        int rc = m->m_pSecretKeyStore->addSecretKey(aIdentifiers[i], pbKey, cbKey);
+        if (RT_SUCCESS(rc))
+            m->m_cPwProvided++;
+        else if (rc == VERR_NO_MEMORY)
+            hrc = setError(E_OUTOFMEMORY, tr("Failed to allocate enough secure memory for the key"));
+        else
+            hrc = setError(E_FAIL, tr("Unknown error happened while adding a password (%Rrc)"), rc);
+    }
+
+    return hrc;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //
Index: /trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp	(revision 55181)
+++ /trunk/src/VBox/Main/src-server/ApplianceImplExport.cpp	(revision 55182)
@@ -358,4 +358,26 @@
                 rc = pBaseMedium->COMGETTER(Size)(&llSize);
                 if (FAILED(rc)) throw rc;
+
+                /* If the medium is encrypted add the key identifier to the */
+                IMedium *iBaseMedium = pBaseMedium;
+                Medium *pBase = static_cast<Medium*>(iBaseMedium);
+                const com::Utf8Str strKeyId = pBase->i_getKeyId();
+                if (!strKeyId.isEmpty())
+                {
+                    bool fKnown = false;
+
+                    /* Check whether the ID is already in our sequence, add it otherwise. */
+                    for (unsigned i = 0; i < pAppliance->m->m_vecPasswordIdentifiers.size(); i++)
+                    {
+                        if (strKeyId.equals(pAppliance->m->m_vecPasswordIdentifiers[i]))
+                        {
+                            fKnown = true;
+                            break;
+                        }
+                    }
+
+                    if (!fKnown)
+                        pAppliance->m->m_vecPasswordIdentifiers.push_back(strKeyId);
+                }
             }
             else if (   deviceType == DeviceType_DVD
@@ -649,4 +671,9 @@
         return setError(VBOX_E_FILE_ERROR,
                         tr("Invalid format \"%s\" specified"), aFormat.c_str());
+
+    /* Check whether all passwords are supplied or error out. */
+    if (m->m_cPwProvided < m->m_vecPasswordIdentifiers.size())
+        return setError(VBOX_E_INVALID_OBJECT_STATE,
+                        tr("Appliance export failed because not all passwords were provided for all encrypted media"));
 
     /* as of OVF 2.0 we have to use SHA256 */
@@ -2168,4 +2195,5 @@
                                                    format,
                                                    MediumVariant_VmdkStreamOptimized,
+                                                   m->m_pSecretKeyStore,
                                                    pIfIo,
                                                    pStorage,
Index: /trunk/src/VBox/Main/src-server/MediumImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MediumImpl.cpp	(revision 55181)
+++ /trunk/src/VBox/Main/src-server/MediumImpl.cpp	(revision 55182)
@@ -572,4 +572,5 @@
                MediumFormat *aFormat,
                MediumVariant_T aVariant,
+               SecretKeyStore *pSecretKeyStore,
                VDINTERFACEIO *aVDImageIOIf,
                void *aVDImageIOUser,
@@ -581,4 +582,5 @@
           mFormat(aFormat),
           mVariant(aVariant),
+          m_pSecretKeyStore(pSecretKeyStore),
           mfKeepSourceMediumLockList(fKeepSourceMediumLockList)
     {
@@ -606,4 +608,5 @@
     MediumVariant_T mVariant;
     PVDINTERFACE mVDImageIfaces;
+    SecretKeyStore *m_pSecretKeyStore;
 
 private:
@@ -5587,4 +5590,6 @@
  * @param aVariant              Which exact image format variant to use
  *                              for the destination image.
+ * @param pKeyStore             The optional key store for decrypting the data
+ *                              for encrypted media during the export.
  * @param aVDImageIOCallbacks   Pointer to the callback table for a
  *                              VDINTERFACEIO interface. May be NULL.
@@ -5597,4 +5602,5 @@
                              const ComObjPtr<MediumFormat> &aFormat,
                              MediumVariant_T aVariant,
+                             SecretKeyStore *pKeyStore,
                              PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
                              const ComObjPtr<Progress> &aProgress)
@@ -5638,5 +5644,5 @@
         /* setup task object to carry out the operation asynchronously */
         pTask = new Medium::ExportTask(this, aProgress, aFilename, aFormat,
-                                       aVariant, aVDImageIOIf,
+                                       aVariant, pKeyStore, aVDImageIOIf,
                                        aVDImageIOUser, pSourceMediumLockList);
         rc = pTask->rc();
@@ -5898,4 +5904,22 @@
 
     return rc;
+}
+
+/**
+ * Returns the key identifier for this medium if encryption is configured.
+ *
+ * @returns Key identifier or empty string if no encryption is configured.
+ */
+const Utf8Str& Medium::i_getKeyId()
+{
+    ComObjPtr<Medium> pBase = i_getBase();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    settings::StringsMap::const_iterator it = pBase->m->mapProperties.find("CRYPT/KeyId");
+    if (it == pBase->m->mapProperties.end())
+        return Utf8Str::Empty;
+
+    return it->second;
 }
 
@@ -8728,4 +8752,5 @@
          * signal from the task initiator (which releases it only after
          * RTThreadCreate()) that we can start the job. */
+        ComObjPtr<Medium> pBase = i_getBase();
         AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
 
@@ -8736,4 +8761,79 @@
         try
         {
+            settings::StringsMap::iterator itKeyStore = pBase->m->mapProperties.find("CRYPT/KeyStore");
+            if (itKeyStore != pBase->m->mapProperties.end())
+            {
+                settings::StringsMap::iterator itKeyId = pBase->m->mapProperties.find("CRYPT/KeyId");
+
+#ifdef VBOX_WITH_EXTPACK
+                static const Utf8Str strExtPackPuel("Oracle VM VirtualBox Extension Pack");
+                static const char *s_pszVDPlugin = "VDPluginCrypt";
+                ExtPackManager *pExtPackManager = m->pVirtualBox->i_getExtPackManager();
+                if (pExtPackManager->i_isExtPackUsable(strExtPackPuel.c_str()))
+                {
+                    /* Load the plugin */
+                    Utf8Str strPlugin;
+                    rc = pExtPackManager->i_getLibraryPathForExtPack(s_pszVDPlugin, &strExtPackPuel, &strPlugin);
+                    if (SUCCEEDED(rc))
+                    {
+                        vrc = VDPluginLoadFromFilename(strPlugin.c_str());
+                        if (RT_FAILURE(vrc))
+                            throw setError(VBOX_E_NOT_SUPPORTED,
+                                           tr("Retrieving encryption settings of the image failed because the encryption plugin could not be loaded (%s)"),
+                                           i_vdError(vrc).c_str());
+                    }
+                    else
+                        throw setError(VBOX_E_NOT_SUPPORTED,
+                                       tr("Encryption is not supported because the extension pack '%s' is missing the encryption plugin (old extension pack installed?)"),
+                                       strExtPackPuel.c_str());
+                }
+                else
+                    throw setError(VBOX_E_NOT_SUPPORTED,
+                                   tr("Encryption is not supported because the extension pack '%s' is missing"),
+                                   strExtPackPuel.c_str());
+#else
+                throw setError(VBOX_E_NOT_SUPPORTED,
+                               tr("Encryption is not supported because extension pack support is not built in"));
+#endif
+
+                if (itKeyId == pBase->m->mapProperties.end())
+                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
+                                   tr("Image '%s' is configured for encryption but doesn't has a key identifier set"),
+                                   pBase->m->strLocationFull.c_str());
+
+                /* Find the proper secret key in the key store. */
+                if (!task.m_pSecretKeyStore)
+                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
+                                   tr("Image '%s' is configured for encryption but there is no key store to retrieve the password from"),
+                                   pBase->m->strLocationFull.c_str());
+
+                SecretKey *pKey = NULL;
+                vrc = task.m_pSecretKeyStore->retainSecretKey(itKeyId->second, &pKey);
+                if (RT_FAILURE(vrc))
+                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
+                                   tr("Failed to retrieve the secret key with ID \"%s\" from the store (%Rrc)"),
+                                   itKeyId->second.c_str(), vrc);
+
+                Medium::CryptoFilterSettings CryptoSettingsRead;
+                i_taskEncryptSettingsSetup(&CryptoSettingsRead, NULL, itKeyStore->second.c_str(), (const char *)pKey->getKeyBuffer(),
+                                           false /* fCreateKeyStore */);
+                vrc = VDFilterAdd(hdd, "CRYPT", VD_FILTER_FLAGS_READ, CryptoSettingsRead.vdFilterIfaces);
+                if (vrc == VERR_VD_PASSWORD_INCORRECT)
+                {
+                    task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);
+                    throw setError(VBOX_E_PASSWORD_INCORRECT,
+                                   tr("The password to decrypt the image is incorrect"));
+                }
+                else if (RT_FAILURE(vrc))
+                {
+                    task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);
+                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
+                                   tr("Failed to load the decryption filter: %s"),
+                                   i_vdError(vrc).c_str());
+                }
+
+                task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);
+            }
+
             /* Open all media in the source chain. */
             MediumLockList::Base::const_iterator sourceListBegin =
