Index: trunk/src/VBox/Devices/Storage/DrvVD.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 54590)
+++ trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 54591)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -664,4 +664,32 @@
     if (pThis->pIfSecKey)
         rc = pThis->pIfSecKey->pfnKeyRelease(pThis->pIfSecKey, pszId);
+    else
+        rc = VERR_NOT_SUPPORTED;
+
+    return rc;
+}
+
+static DECLCALLBACK(int) drvvdCryptoKeyStorePasswordRetain(void *pvUser, const char *pszId, const char **ppszPassword)
+{
+    PVBOXDISK pThis = (PVBOXDISK)pvUser;
+    int rc = VINF_SUCCESS;
+
+    AssertPtr(pThis->pIfSecKey);
+    if (pThis->pIfSecKey)
+        rc = pThis->pIfSecKey->pfnPasswordRetain(pThis->pIfSecKey, pszId, ppszPassword);
+    else
+        rc = VERR_NOT_SUPPORTED;
+
+    return rc;
+}
+
+static DECLCALLBACK(int) drvvdCryptoKeyStorePasswordRelease(void *pvUser, const char *pszId)
+{
+    PVBOXDISK pThis = (PVBOXDISK)pvUser;
+    int rc = VINF_SUCCESS;
+
+    AssertPtr(pThis->pIfSecKey);
+    if (pThis->pIfSecKey)
+        rc = pThis->pIfSecKey->pfnPasswordRelease(pThis->pIfSecKey, pszId);
     else
         rc = VERR_NOT_SUPPORTED;
@@ -2910,6 +2938,8 @@
             pThis->VDIfCfg.pfnQueryBytes    = NULL;
 
-            pThis->VDIfCrypto.pfnKeyRetain  = drvvdCryptoKeyRetain;
-            pThis->VDIfCrypto.pfnKeyRelease = drvvdCryptoKeyRelease;
+            pThis->VDIfCrypto.pfnKeyRetain               = drvvdCryptoKeyRetain;
+            pThis->VDIfCrypto.pfnKeyRelease              = drvvdCryptoKeyRelease;
+            pThis->VDIfCrypto.pfnKeyStorePasswordRetain  = drvvdCryptoKeyStorePasswordRetain;
+            pThis->VDIfCrypto.pfnKeyStorePasswordRelease = drvvdCryptoKeyStorePasswordRelease;
         }
 
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 54590)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 54591)
@@ -1679,5 +1679,44 @@
                 break;
             }
-
+        }
+        else if (!strcmp(a->argv[1], "addencpassword"))
+        {
+            if (   a->argc != 4
+                && a->argc != 6)
+            {
+                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                break;
+            }
+
+            if (   strcmp(a->argv[4], "--removeonsuspend")
+                || (   strcmp(a->argv[5], "yes")
+                    && strcmp(a->argv[5], "no")))
+            {
+                errorSyntax(USAGE_CONTROLVM, "Invalid parameters");
+                break;
+            }
+
+            BOOL fRemoveOnSuspend = FALSE;
+            Bstr bstrPwId(a->argv[2]);
+            Bstr bstrPw(a->argv[3]);
+            if (   a->argc == 6
+                && !strcmp(a->argv[5], "yes"))
+                fRemoveOnSuspend = TRUE;
+
+            CHECK_ERROR_BREAK(console, AddDiskEncryptionPassword(bstrPwId.raw(), bstrPw.raw(), fRemoveOnSuspend));
+        }
+        else if (!strcmp(a->argv[1], "removeencpassword"))
+        {
+            if (a->argc != 3)
+            {
+                errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
+                break;
+            }
+            Bstr bstrPwId(a->argv[2]);
+            CHECK_ERROR_BREAK(console, RemoveDiskEncryptionPassword(bstrPwId.raw()));
+        }
+        else if (!strcmp(a->argv[1], "removeallencpasswords"))
+        {
+            CHECK_ERROR_BREAK(console, ClearAllDiskEncryptionPasswords());
         }
         else
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp	(revision 54590)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp	(revision 54591)
@@ -1641,7 +1641,8 @@
 static const RTGETOPTDEF g_aEncryptMediumOptions[] =
 {
-    { "--newpassword",  'n', RTGETOPT_REQ_STRING },
-    { "--oldpassword",  'o', RTGETOPT_REQ_STRING },
-    { "--cipher",       'c', RTGETOPT_REQ_STRING }
+    { "--newpassword",   'n', RTGETOPT_REQ_STRING },
+    { "--oldpassword",   'o', RTGETOPT_REQ_STRING },
+    { "--cipher",        'c', RTGETOPT_REQ_STRING },
+    { "--newpasswordid", 'i', RTGETOPT_REQ_STRING }
 };
 
@@ -1655,4 +1656,5 @@
     const char *pszCipher = NULL;
     const char *pszFilenameOrUuid = NULL;
+    const char *pszNewPasswordId = NULL;
 
     int c;
@@ -1676,4 +1678,8 @@
             case 'c':   // --cipher
                 pszCipher = ValueUnion.psz;
+                break;
+
+            case 'i':   // --newpasswordid
+                pszNewPasswordId = ValueUnion.psz;
                 break;
 
@@ -1708,4 +1714,8 @@
         return errorSyntax(USAGE_ENCRYPTMEDIUM, "No password specified");
 
+    if (   (pszPasswordNew && !pszNewPasswordId)
+        || (!pszPasswordNew && pszNewPasswordId))
+        return errorSyntax(USAGE_ENCRYPTMEDIUM, "A new password must always have a valid identifier set at the same time");
+
     /* Always open the medium if necessary, there is no other way. */
     rc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk,
@@ -1722,5 +1732,6 @@
     ComPtr<IProgress> progress;
     CHECK_ERROR(hardDisk, ChangeEncryption(Bstr(pszPasswordNew).raw(), Bstr(pszPasswordOld).raw(),
-                                           Bstr(pszCipher).raw(), progress.asOutParam()));
+                                           Bstr(pszCipher).raw(), Bstr(pszNewPasswordId).raw(),
+                                           progress.asOutParam()));
     if (SUCCEEDED(rc))
         rc = showProgress(progress);
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 54590)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 54591)
@@ -495,4 +495,9 @@
                      "                            cpuexecutioncap <1-100>\n"
                      "                            webcam <attach [path [settings]]> | <detach [path]> | <list>\n"
+                     "                            addencpassword <id>\n"
+                     "                                           <password>\n"
+                     "                                           [--removeonsuspend <yes|no>]\n"
+                     "                            removeencpassword <id>\n"
+                     "                            removeallencpasswords\n"
                      "\n", SEP);
     }
@@ -637,4 +642,5 @@
                      "                            [--oldpassword <old password>]\n"
                      "                            [--cipher <cipher identifier>]\n"
+                     "                            [--newpasswordid <password identifier>]\n"
                      "\n", SEP);
 
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 54590)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 54591)
@@ -7530,5 +7530,5 @@
   <interface
     name="IConsole" extends="$unknown"
-    uuid="e51702d7-4f8f-4ebe-ac47-4b77defffd18"
+    uuid="a0059bfc-04e8-4ff0-93d9-2e4d5257d9ee"
     wsmap="managed"
     >
@@ -8354,4 +8354,43 @@
     </method>
 
+    <method name="addDiskEncryptionPassword">
+      <desc>
+        Adds a password used for hard disk encryption/decryption.
+      </desc>
+      <param name="id" type="wstring" dir="in">
+        <desc>
+          The identifier used for the password. Must match the identifier
+          used when the encrypted medium was created.
+        </desc>
+      </param>
+      <param name="password" type="wstring" dir="in">
+        <desc>The password.</desc>
+      </param>
+      <param name="clearOnSuspend" type="boolean" dir="in">
+        <desc>
+          Flag whether to clear the password on VM suspend (due to a suspending host
+          for example). The password must be supplied again before the VM can resume.
+        </desc>
+      </param>
+    </method>
+
+    <method name="removeDiskEncryptionPassword">
+      <desc>
+        Removes a password used for hard disk encryption/decryption from
+        the running VM. As soon as the medium requiring this password
+        is accessed the VM is paused with an error and the password must be
+        provided again.
+      </desc>
+      <param name="id" type="wstring" dir="in">
+        <desc>
+          The identifier used for the password. Must match the identifier
+          used when the encrypted medium was created.
+        </desc>
+      </param>
+    </method>
+
+    <method name="clearAllDiskEncryptionPasswords">
+      <desc>Clears all provided supplied disk encryption passwords.</desc>
+    </method>
   </interface>
 
@@ -13424,5 +13463,5 @@
   <interface
     name="IMedium" extends="$unknown"
-    uuid="e6aa3c67-6f51-4ba6-a012-cf4825069abb"
+    uuid="edf10636-fd4f-4e24-8d24-f38a41721a00"
     wsmap="managed"
     >
@@ -14703,4 +14742,7 @@
       <param name="cipher" type="wstring" dir="in">
         <desc>The cipher to use for encryption.</desc>
+      </param>
+      <param name="newPasswordId" type="wstring" dir="in">
+        <desc>The ID of the new password when unlocking the medium.</desc>
       </param>
       <param name="progress" type="IProgress" dir="return">
Index: trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 54590)
+++ trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 54591)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2005-2014 Oracle Corporation
+ * Copyright (C) 2005-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -351,4 +351,8 @@
                      ULONG aMaxDowntime,
                      ComPtr<IProgress> &aProgress);
+    HRESULT addDiskEncryptionPassword(const com::Utf8Str &aId, const com::Utf8Str &aPassword,
+                                      BOOL aClearOnSuspend);
+    HRESULT removeDiskEncryptionPassword(const com::Utf8Str &aId);
+    HRESULT clearAllDiskEncryptionPasswords();
 
     void notifyNatDnsChange(PUVM pUVM, const char *pszDevice, ULONG ulInstanceMax);
@@ -585,8 +589,9 @@
             SecretKey() { }
 
-            SecretKey(uint8_t *pbKey, size_t cbKey)
+            SecretKey(uint8_t *pbKey, size_t cbKey, bool fRemoveOnSuspend)
                : m_cRefs(0),
                  m_pbKey(pbKey),
-                 m_cbKey(cbKey)
+                 m_cbKey(cbKey),
+                 m_fRemoveOnSuspend(fRemoveOnSuspend)
             { }
 
@@ -597,4 +602,5 @@
                 m_pbKey = NULL;
                 m_cbKey = 0;
+                m_fRemoveOnSuspend = false;
             }
 
@@ -605,4 +611,6 @@
             /** Size of the key in bytes. */
             size_t   m_cbKey;
+            /** Flag whether to remove the key on suspend. */
+            bool     m_fRemoveOnSuspend;
     };
 
@@ -810,4 +818,6 @@
                                                         size_t *pcbKey);
     static DECLCALLBACK(int)    i_pdmIfSecKey_KeyRelease(PPDMISECKEY pInterface, const char *pszId);
+    static DECLCALLBACK(int)    i_pdmIfSecKey_PasswordRetain(PPDMISECKEY pInterface, const char *pszId, const char **ppszPassword);
+    static DECLCALLBACK(int)    i_pdmIfSecKey_PasswordRelease(PPDMISECKEY pInterface, const char *pszId);
 
     static DECLCALLBACK(int)    i_pdmIfSecKeyHlp_KeyMissingNotify(PPDMISECKEYHLP pInterface);
@@ -852,5 +862,5 @@
      * @{ */
     HRESULT i_consoleParseDiskEncryption(const char *psz, const char **ppszEnd);
-    HRESULT i_configureEncryptionForDisk(const char *pszUuid);
+    HRESULT i_configureEncryptionForDisk(const Utf8Str &aId);
     HRESULT i_clearDiskEncryptionKeysOnAllAttachments(void);
     int i_consoleParseKeyValue(const char *psz, const char **ppszEnd,
Index: trunk/src/VBox/Main/include/MediumImpl.h
===================================================================
--- trunk/src/VBox/Main/include/MediumImpl.h	(revision 54590)
+++ trunk/src/VBox/Main/include/MediumImpl.h	(revision 54591)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2008-2014 Oracle Corporation
+ * Copyright (C) 2008-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -276,5 +276,5 @@
     HRESULT reset(ComPtr<IProgress> &aProgress);
     HRESULT changeEncryption(const com::Utf8Str &aNewPassword, const com::Utf8Str &aOldPassword,
-                             const com::Utf8Str &aCipher, ComPtr<IProgress> &aProgress);
+                             const com::Utf8Str &aCipher, const com::Utf8Str &aNewPasswordId, ComPtr<IProgress> &aProgress);
 
     // Private internal nmethods
@@ -324,5 +324,6 @@
                                                  const uint8_t **ppbKey, size_t *pcbKey);
     static DECLCALLBACK(int) i_vdCryptoKeyRelease(void *pvUser, const char *pszId);
-    static DECLCALLBACK(int) i_vdCryptoKeyStoreGetPassword(void *pvUser, const char **ppszPassword);
+    static DECLCALLBACK(int) i_vdCryptoKeyStorePasswordRetain(void *pvUser, const char *pszId, const char **ppszPassword);
+    static DECLCALLBACK(int) i_vdCryptoKeyStorePasswordRelease(void *pvUser, const char *pszId);
     static DECLCALLBACK(int) i_vdCryptoKeyStoreSave(void *pvUser, const void *pvKeyStore, size_t cbKeyStore);
     static DECLCALLBACK(int) i_vdCryptoKeyStoreReturnParameters(void *pvUser, const char *pszCipher,
Index: trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 54590)
+++ trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 54591)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2005-2014 Oracle Corporation
+ * Copyright (C) 2005-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -474,4 +474,6 @@
     pIfSecKey->pfnKeyRetain             = Console::i_pdmIfSecKey_KeyRetain;
     pIfSecKey->pfnKeyRelease            = Console::i_pdmIfSecKey_KeyRelease;
+    pIfSecKey->pfnPasswordRetain        = Console::i_pdmIfSecKey_PasswordRetain;
+    pIfSecKey->pfnPasswordRelease       = Console::i_pdmIfSecKey_PasswordRelease;
     pIfSecKey->pConsole                 = this;
     mpIfSecKey = pIfSecKey;
@@ -3354,4 +3356,83 @@
 
     i_setMachineStateLocally(machineState);
+    return S_OK;
+}
+
+HRESULT Console::addDiskEncryptionPassword(const com::Utf8Str &aId, const com::Utf8Str &aPassword,
+                                           BOOL aClearOnSuspend)
+{
+    if (   aId.isEmpty()
+        || aPassword.isEmpty())
+        return setError(E_FAIL, tr("The ID and password must be both valid"));
+
+    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);
+    if (RT_SUCCESS(rc))
+    {
+        memcpy(pbKey, aPassword.c_str(), cbKey);
+        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);
+        if (FAILED(hrc))
+            m_mapSecretKeys.erase(aId);
+    }
+    else
+        return setError(E_FAIL, tr("Failed to allocate secure memory for the password (%Rrc)"), rc);
+
+    return hrc;
+}
+
+HRESULT Console::removeDiskEncryptionPassword(const com::Utf8Str &aId)
+{
+    if (aId.isEmpty())
+        return setError(E_FAIL, tr("The ID must be valid"));
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    SecretKeyMap::const_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_mapSecretKeys.erase(it);
+    delete pKey;
+
+    return S_OK;
+}
+
+HRESULT Console::clearAllDiskEncryptionPasswords()
+{
+    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();
+
     return S_OK;
 }
@@ -4549,11 +4630,11 @@
 
 /**
- * Configures the encryption support for the disk identified by the gien UUID with
- * the given key.
+ * Configures the encryption support for the disk which have encryption conigured
+ * with the configured key.
  *
  * @returns COM status code.
- * @param   pszUuid   The UUID of the disk to configure encryption for.
+ * @param   aId    The ID of the password.
  */
-HRESULT Console::i_configureEncryptionForDisk(const char *pszUuid)
+HRESULT Console::i_configureEncryptionForDisk(const com::Utf8Str &strId)
 {
     HRESULT hrc = S_OK;
@@ -4580,5 +4661,5 @@
         ComPtr<IMedium> pMedium;
         ComPtr<IMedium> pBase;
-        Bstr uuid;
+        Bstr bstrKeyId;
 
         hrc = pAtt->COMGETTER(Medium)(pMedium.asOutParam());
@@ -4595,9 +4676,11 @@
             break;
 
-        hrc = pBase->COMGETTER(Id)(uuid.asOutParam());
-        if (FAILED(hrc))
+        hrc = pBase->GetProperty(Bstr("CRYPT/KeyId").raw(), bstrKeyId.asOutParam());
+        if (hrc == VBOX_E_OBJECT_NOT_FOUND)
+            continue;
+        else if (FAILED(hrc))
             break;
 
-        if (!RTUuidCompare2Strs(Utf8Str(uuid).c_str(), pszUuid))
+        if (strId.equals(Utf8Str(bstrKeyId)))
         {
             /*
@@ -4737,8 +4820,8 @@
                 if (RT_SUCCESS(rc))
                 {
-                    SecretKey *pKey = new SecretKey(pbKey, cbKey);
+                    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(pszUuid);
+                    hrc = i_configureEncryptionForDisk(Utf8Str(pszUuid));
                     if (FAILED(hrc))
                     {
@@ -10328,4 +10411,5 @@
     Console *pConsole = ((MYPDMISECKEY *)pInterface)->pConsole;
 
+    AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
     SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
     if (it != pConsole->m_mapSecretKeys.end())
@@ -10349,4 +10433,48 @@
 {
     Console *pConsole = ((MYPDMISECKEY *)pInterface)->pConsole;
+
+    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;
+}
+
+/**
+ * @interface_method_impl{PDMISECKEY,pfnPasswordRetain}
+ */
+/*static*/ DECLCALLBACK(int)
+Console::i_pdmIfSecKey_PasswordRetain(PPDMISECKEY pInterface, const char *pszId, const char **ppszPassword)
+{
+    Console *pConsole = ((MYPDMISECKEY *)pInterface)->pConsole;
+
+    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);
+        *ppszPassword = (const char *)pKey->m_pbKey;
+        return VINF_SUCCESS;
+    }
+
+    return VERR_NOT_FOUND;
+}
+
+/**
+ * @interface_method_impl{PDMISECKEY,pfnPasswordRelease}
+ */
+/*static*/ DECLCALLBACK(int)
+Console::i_pdmIfSecKey_PasswordRelease(PPDMISECKEY pInterface, const char *pszId)
+{
+    Console *pConsole = ((MYPDMISECKEY *)pInterface)->pConsole;
+
+    AutoReadLock thatLock(pConsole COMMA_LOCKVAL_SRC_POS);
     SecretKeyMap::const_iterator it = pConsole->m_mapSecretKeys.find(Utf8Str(pszId));
     if (it != pConsole->m_mapSecretKeys.end())
Index: trunk/src/VBox/Main/src-server/MediumImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-server/MediumImpl.cpp	(revision 54590)
+++ trunk/src/VBox/Main/src-server/MediumImpl.cpp	(revision 54591)
@@ -678,4 +678,5 @@
                 const com::Utf8Str &strOldPassword,
                 const com::Utf8Str &strCipher,
+                const com::Utf8Str &strNewPasswordId,
                 Progress *aProgress,
                 MediumLockList *aMediumLockList)
@@ -684,4 +685,5 @@
           mstrOldPassword(strOldPassword),
           mstrCipher(strCipher),
+          mstrNewPasswordId(strNewPasswordId),
           mpMediumLockList(aMediumLockList)
     {
@@ -707,4 +709,5 @@
     Utf8Str mstrOldPassword;
     Utf8Str mstrCipher;
+    Utf8Str mstrNewPasswordId;
     MediumLockList *mpMediumLockList;
     PVDINTERFACE    mVDImageIfaces;
@@ -3027,5 +3030,6 @@
 
 HRESULT Medium::changeEncryption(const com::Utf8Str &aNewPassword, const com::Utf8Str &aOldPassword,
-                                 const com::Utf8Str &aCipher, ComPtr<IProgress> &aProgress)
+                                 const com::Utf8Str &aCipher, const com::Utf8Str &aNewPasswordId,
+                                 ComPtr<IProgress> &aProgress)
 {
     HRESULT rc = S_OK;
@@ -3100,5 +3104,5 @@
         /* setup task object to carry out the operation asynchronously */
         pTask = new Medium::EncryptTask(this, aNewPassword, aOldPassword,
-                                        aCipher, pProgress, pMediumLockList);
+                                        aCipher, aNewPasswordId, pProgress, pMediumLockList);
         rc = pTask->rc();
         AssertComRC(rc);
@@ -6802,6 +6806,12 @@
     if (!strcmp(pszName, "Algorithm"))
         cbValue = strlen(pSettings->pszCipher) + 1;
+    else if (!strcmp(pszName, "KeyId"))
+        cbValue = sizeof("irrelevant");
     else if (!strcmp(pszName, "KeyStore"))
-        cbValue = RTBase64DecodedSize(pSettings->pszKeyStoreLoad, NULL) + 1;
+    {
+        if (!pSettings->pszKeyStoreLoad)
+            return VERR_CFGM_VALUE_NOT_FOUND;
+        cbValue = strlen(pSettings->pszKeyStoreLoad) + 1;
+    }
     else if (!strcmp(pszName, "CreateKeyStore"))
         cbValue = 2; /* Single digit + terminator. */
@@ -6821,28 +6831,26 @@
     AssertReturn(VALID_PTR(pszValue), VERR_INVALID_POINTER);
 
-    if (!strcmp(pszName, "KeyStore"))
-        return RTBase64Decode(pSettings->pszKeyStoreLoad, pszValue, cchValue, NULL, NULL);
+    const char *psz = NULL;
+    if (!strcmp(pszName, "Algorithm"))
+        psz = pSettings->pszCipher;
+    else if (!strcmp(pszName, "KeyId"))
+        psz = "irrelevant";
+    else if (!strcmp(pszName, "KeyStore"))
+        psz = pSettings->pszKeyStoreLoad;
+    else if (!strcmp(pszName, "CreateKeyStore"))
+    {
+        if (pSettings->fCreateKeyStore)
+            psz = "1";
+        else
+            psz = "0";
+    }
     else
-    {
-        const char *psz = NULL;
-        if (!strcmp(pszName, "Algorithm"))
-            psz = pSettings->pszCipher;
-        else if (!strcmp(pszName, "CreateKeyStore"))
-        {
-            if (pSettings->fCreateKeyStore)
-                psz = "1";
-            else
-                psz = "0";
-        }
-        else
-            return VERR_CFGM_VALUE_NOT_FOUND;
-
-        size_t cch = strlen(psz);
-        if (cch >= cchValue)
-            return VERR_CFGM_NOT_ENOUGH_SPACE;
-
-        memcpy(pszValue, psz, cch + 1);
-    }
-
+        return VERR_CFGM_VALUE_NOT_FOUND;
+
+    size_t cch = strlen(psz);
+    if (cch >= cchValue)
+        return VERR_CFGM_NOT_ENOUGH_SPACE;
+
+    memcpy(pszValue, psz, cch + 1);
     return VINF_SUCCESS;
 }
@@ -6863,5 +6871,5 @@
 }
 
-DECLCALLBACK(int) Medium::i_vdCryptoKeyStoreGetPassword(void *pvUser, const char **ppszPassword)
+DECLCALLBACK(int) Medium::i_vdCryptoKeyStorePasswordRetain(void *pvUser, const char *pszId, const char **ppszPassword)
 {
     Medium::CryptoFilterSettings *pSettings = (Medium::CryptoFilterSettings *)pvUser;
@@ -6872,22 +6880,22 @@
 }
 
-DECLCALLBACK(int) Medium::i_vdCryptoKeyStoreSave(void *pvUser, const void *pvKeyStore, size_t cbKeyStore)
+DECLCALLBACK(int) Medium::i_vdCryptoKeyStorePasswordRelease(void *pvUser, const char *pszId)
 {
     Medium::CryptoFilterSettings *pSettings = (Medium::CryptoFilterSettings *)pvUser;
     AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
-
-    size_t cbEnc = RTBase64EncodedLength(cbKeyStore);
-    pSettings->pszKeyStore = (char *)RTMemAllocZ(cbEnc + 1);
+    return VINF_SUCCESS;
+}
+
+DECLCALLBACK(int) Medium::i_vdCryptoKeyStoreSave(void *pvUser, const void *pvKeyStore, size_t cbKeyStore)
+{
+    Medium::CryptoFilterSettings *pSettings = (Medium::CryptoFilterSettings *)pvUser;
+    AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
+
+    pSettings->pszKeyStore = (char *)RTMemAllocZ(cbKeyStore);
     if (!pSettings->pszKeyStore)
         return VERR_NO_MEMORY;
 
-    int rc = RTBase64Encode(pvKeyStore, cbKeyStore, pSettings->pszKeyStore, cbEnc + 1, NULL);
-    if (RT_FAILURE(rc))
-    {
-        RTMemFree(pSettings->pszKeyStore);
-        pSettings->pszKeyStore = NULL;
-    }
-
-    return rc;
+    memcpy(pSettings->pszKeyStore, pvKeyStore, cbKeyStore);
+    return VINF_SUCCESS;
 }
 
@@ -8727,5 +8735,6 @@
     pSettings->vdIfCrypto.pfnKeyRetain                = i_vdCryptoKeyRetain;
     pSettings->vdIfCrypto.pfnKeyRelease               = i_vdCryptoKeyRelease;
-    pSettings->vdIfCrypto.pfnKeyStoreGetPassword      = i_vdCryptoKeyStoreGetPassword;
+    pSettings->vdIfCrypto.pfnKeyStorePasswordRetain   = i_vdCryptoKeyStorePasswordRetain;
+    pSettings->vdIfCrypto.pfnKeyStorePasswordRelease  = i_vdCryptoKeyStorePasswordRelease;
     pSettings->vdIfCrypto.pfnKeyStoreSave             = i_vdCryptoKeyStoreSave;
     pSettings->vdIfCrypto.pfnKeyStoreReturnParameters = i_vdCryptoKeyStoreReturnParameters;
@@ -8745,5 +8754,5 @@
 
 /**
- * Implementation code for the "compact" task.
+ * Implementation code for the "encrypt" task.
  *
  * @param task
@@ -8836,4 +8845,8 @@
                                    tr("No valid cipher identifier was given for encryption"));
 
+                if (task.mstrNewPasswordId.isEmpty())
+                    throw setError(VBOX_E_INVALID_OBJECT_STATE,
+                                   tr("A new password must always have a valid identifier"));
+
                 i_taskEncryptSettingsSetup(&CryptoSettingsWrite, task.mstrCipher.c_str(), NULL,
                                            task.mstrNewPassword.c_str(), true /* fCreateKeyStore */);
@@ -8844,4 +8857,7 @@
                                    i_vdError(vrc).c_str());
             }
+            else if (task.mstrNewPasswordId.isNotEmpty())
+                throw setError(VBOX_E_INVALID_OBJECT_STATE,
+                               tr("The password identifier must be empty if there is no new password set for encryption"));
 
             /* Open all media in the chain. */
@@ -8931,6 +8947,13 @@
                 m->mapProperties.erase(it);
 
+            it = m->mapProperties.find("CRYPT/KeyId");
+            if (it != m->mapProperties.end())
+                m->mapProperties.erase(it);
+
             if (CryptoSettingsWrite.pszKeyStore)
+            {
                 m->mapProperties["CRYPT/KeyStore"] = Utf8Str(CryptoSettingsWrite.pszKeyStore);
+                m->mapProperties["CRYPT/KeyId"] = task.mstrNewPasswordId;
+            }
 
             thisLock.release();
Index: trunk/src/VBox/Storage/VD.cpp
===================================================================
--- trunk/src/VBox/Storage/VD.cpp	(revision 54590)
+++ trunk/src/VBox/Storage/VD.cpp	(revision 54591)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2014 Oracle Corporation
+ * Copyright (C) 2006-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -8827,5 +8827,5 @@
         AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
 
-        AssertMsgBreakStmt(!(fFlags & VD_FILTER_FLAGS_MASK),
+        AssertMsgBreakStmt(!(fFlags & ~VD_FILTER_FLAGS_MASK),
                            ("Invalid flags set (fFlags=%#x)\n", fFlags),
                            rc = VERR_INVALID_PARAMETER);
