VirtualBox

忽略:
時間撮記:
2014-5-22 上午10:24:53 (11 年 以前)
作者:
vboxsync
訊息:

Main,DrvVD: Interface to pass the keys to the disk encryption module from Main

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r51292 r51342  
    9292#include <iprt/string.h>
    9393#include <iprt/system.h>
     94#include <iprt/base64.h>
    9495
    9596#include <VBox/vmm/vmapi.h>
     
    44424443{
    44434444    return mDisplay;
     4445}
     4446
     4447/**
     4448 * Parses one key value pair.
     4449 *
     4450 * @returns VBox status code.
     4451 * @param   psz     Configuration string.
     4452 * @param   ppszEnd Where to store the pointer to the string following the key value pair.
     4453 * @param   ppszKey Where to store the key on success.
     4454 * @param   ppszVal Where to store the value on success.
     4455 */
     4456int Console::consoleParseKeyValue(const char *psz, const char **ppszEnd,
     4457                                  char **ppszKey, char **ppszVal)
     4458{
     4459    int rc = VINF_SUCCESS;
     4460    const char *pszKeyStart = psz;
     4461    const char *pszValStart = NULL;
     4462    size_t cchKey = 0;
     4463    size_t cchVal = 0;
     4464
     4465    while (   *psz != '='
     4466           && *psz)
     4467        psz++;
     4468
     4469    /* End of string at this point is invalid. */
     4470    if (*psz == '\0')
     4471        return VERR_INVALID_PARAMETER;
     4472
     4473    cchKey = psz - pszKeyStart;
     4474    psz++; /* Skip = character */
     4475    pszValStart = psz;
     4476
     4477    while (   *psz != ','
     4478           && *psz != '\n'
     4479           && *psz != '\r'
     4480           && *psz)
     4481        psz++;
     4482
     4483    cchVal = psz - pszValStart;
     4484
     4485    if (cchKey && cchVal)
     4486    {
     4487        *ppszKey = RTStrDupN(pszKeyStart, cchKey);
     4488        if (*ppszKey)
     4489        {
     4490            *ppszVal = RTStrDupN(pszValStart, cchVal);
     4491            if (!*ppszVal)
     4492            {
     4493                RTStrFree(*ppszKey);
     4494                rc = VERR_NO_MEMORY;
     4495            }
     4496        }
     4497        else
     4498            rc = VERR_NO_MEMORY;
     4499    }
     4500    else
     4501        rc = VERR_INVALID_PARAMETER;
     4502
     4503    if (RT_SUCCESS(rc))
     4504        *ppszEnd = psz;
     4505
     4506    return rc;
     4507}
     4508
     4509/**
     4510 * Configures the encryption support for the disk identified by the gien UUID with
     4511 * the given key.
     4512 *
     4513 * @returns COM status code.
     4514 * @param   pszUuid   The UUID of the disk to configure encryption for.
     4515 * @param   pbKey     The key to use
     4516 * @param   cbKey     Size of the key in bytes.
     4517 */
     4518HRESULT Console::configureEncryptionForDisk(const char *pszUuid, const uint8_t *pbKey, size_t cbKey)
     4519{
     4520    HRESULT hrc = S_OK;
     4521    SafeIfaceArray<IMediumAttachment> sfaAttachments;
     4522
     4523    AutoCaller autoCaller(this);
     4524    AssertComRCReturnRC(autoCaller.rc());
     4525
     4526    /* Get the VM - must be done before the read-locking. */
     4527    SafeVMPtr ptrVM(this);
     4528    if (!ptrVM.isOk())
     4529        return ptrVM.rc();
     4530
     4531    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     4532
     4533    hrc = mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
     4534    if (FAILED(hrc))
     4535        return hrc;
     4536
     4537    /* Find the correct attachment. */
     4538    for (unsigned i = 0; i < sfaAttachments.size(); i++)
     4539    {
     4540        const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[i];
     4541        ComPtr<IMedium> pMedium;
     4542        ComPtr<IMedium> pBase;
     4543        Bstr uuid;
     4544
     4545        hrc = pAtt->COMGETTER(Medium)(pMedium.asOutParam());
     4546        if (FAILED(hrc))
     4547            break;
     4548
     4549        /* Skip non hard disk attachments. */
     4550        if (pMedium.isNull())
     4551            continue;
     4552
     4553        /* Get the UUID of the base medium and compare. */
     4554        hrc = pMedium->COMGETTER(Base)(pBase.asOutParam());
     4555        if (FAILED(hrc))
     4556            break;
     4557
     4558        hrc = pBase->COMGETTER(Id)(uuid.asOutParam());
     4559        if (FAILED(hrc))
     4560            break;
     4561
     4562        if (!RTUuidCompare2Strs(Utf8Str(uuid).c_str(), pszUuid))
     4563        {
     4564            /*
     4565             * Found the matching medium, query storage controller, port and device
     4566             * to identify the correct driver.
     4567             */
     4568            ComPtr<IStorageController> pStorageCtrl;
     4569            Bstr storageCtrlName;
     4570            LONG lPort, lDev;
     4571            ULONG ulStorageCtrlInst;
     4572
     4573            hrc = pAtt->COMGETTER(Controller)(storageCtrlName.asOutParam());
     4574            if (FAILED(hrc))
     4575                break;
     4576
     4577            hrc = pAtt->COMGETTER(Port)(&lPort);
     4578            if (FAILED(hrc))
     4579                break;
     4580
     4581            hrc = pAtt->COMGETTER(Device)(&lDev);
     4582            if (FAILED(hrc))
     4583                break;
     4584
     4585            hrc = mMachine->GetStorageControllerByName(storageCtrlName.raw(), pStorageCtrl.asOutParam());
     4586            if (FAILED(hrc))
     4587                break;
     4588
     4589            hrc = pStorageCtrl->COMGETTER(Instance)(&ulStorageCtrlInst);
     4590            if (FAILED(hrc))
     4591                break;
     4592
     4593            StorageControllerType_T enmCtrlType;
     4594            hrc = pStorageCtrl->COMGETTER(ControllerType)(&enmCtrlType);
     4595            AssertComRC(hrc);
     4596            const char *pcszDevice = convertControllerTypeToDev(enmCtrlType);
     4597
     4598            StorageBus_T enmBus;
     4599            hrc = pStorageCtrl->COMGETTER(Bus)(&enmBus);
     4600            AssertComRC(hrc);
     4601
     4602            unsigned uLUN;
     4603            hrc = Console::convertBusPortDeviceToLun(enmBus, lPort, lDev, uLUN);
     4604            AssertComRCReturnRC(hrc);
     4605
     4606            PPDMIBASE pIBase = NULL;
     4607            PPDMIMEDIA pIMedium = NULL;
     4608            int rc = PDMR3QueryDriverOnLun(ptrVM.rawUVM(), pcszDevice, ulStorageCtrlInst, uLUN, "VD", &pIBase);
     4609            if (RT_SUCCESS(rc))
     4610            {
     4611                if (pIBase)
     4612                {
     4613                    pIMedium = (PPDMIMEDIA)pIBase->pfnQueryInterface(pIBase, PDMIMEDIA_IID);
     4614                    if (!pIMedium)
     4615                        return setError(E_FAIL, tr("could not query medium interface of controller"));
     4616                }
     4617                else
     4618                    return setError(E_FAIL, tr("could not query base interface of controller"));
     4619            }
     4620
     4621            rc = pIMedium->pfnSetKey(pIMedium, pbKey, cbKey);
     4622            if (RT_FAILURE(rc))
     4623                return setError(E_FAIL, tr("Failed to set the encryption key (%Rrc)"), rc);
     4624        }
     4625    }
     4626
     4627    return hrc;
     4628}
     4629
     4630/**
     4631 * Parses the encryption configuration for one disk.
     4632 *
     4633 * @returns Pointer to the string following encryption configuration.
     4634 * @param   psz    Pointer to the configuration for the encryption of one disk.
     4635 */
     4636HRESULT Console::consoleParseDiskEncryption(const char *psz, const char **ppszEnd)
     4637{
     4638    char *pszUuid = NULL;
     4639    char *pszKeyEnc = NULL;
     4640    int rc = VINF_SUCCESS;
     4641    HRESULT hrc = S_OK;
     4642
     4643    while (   *psz
     4644           && RT_SUCCESS(rc))
     4645    {
     4646        char *pszKey = NULL;
     4647        char *pszVal = NULL;
     4648        const char *pszEnd = NULL;
     4649
     4650        rc = consoleParseKeyValue(psz, &pszEnd, &pszKey, &pszVal);
     4651        if (RT_SUCCESS(rc))
     4652        {
     4653            if (!RTStrCmp(pszKey, "uuid"))
     4654                pszUuid = pszVal;
     4655            else if (!RTStrCmp(pszKey, "dek"))
     4656                pszKeyEnc = pszVal;
     4657            else
     4658                rc = VERR_INVALID_PARAMETER;
     4659
     4660            RTStrFree(pszKey);
     4661
     4662            if (*pszEnd == ',')
     4663                psz = pszEnd + 1;
     4664            else
     4665            {
     4666                /*
     4667                 * End of the configuration for the current disk, skip linefeed and
     4668                 * carriage returns.
     4669                 */
     4670                while (   *pszEnd == '\n'
     4671                       || *pszEnd == '\r')
     4672                    pszEnd++;
     4673
     4674                psz = pszEnd;
     4675                break; /* Stop parsing */
     4676            }
     4677
     4678        }
     4679    }
     4680
     4681    if (   RT_SUCCESS(rc)
     4682        && pszUuid
     4683        && pszKeyEnc)
     4684    {
     4685        ssize_t cbKey = 0;
     4686
     4687        /* Decode the key. */
     4688        cbKey = RTBase64DecodedSize(pszKeyEnc, NULL);
     4689        if (cbKey != -1)
     4690        {
     4691            uint8_t *pbKey = (uint8_t *)RTMemLockedAlloc(cbKey);
     4692            if (pbKey)
     4693            {
     4694                rc = RTBase64Decode(pszKeyEnc, pbKey, cbKey, NULL, NULL);
     4695                if (RT_SUCCESS(rc))
     4696                    hrc = configureEncryptionForDisk(pszUuid, pbKey, cbKey);
     4697                else
     4698                    hrc = setError(E_FAIL,
     4699                                   tr("Failed to decode the key (%Rrc)"),
     4700                                   rc);
     4701
     4702                RTMemWipeThoroughly(pbKey, cbKey, 10 /* cMinPasses */);
     4703                RTMemLockedFree(pbKey);
     4704            }
     4705            else
     4706                hrc = setError(E_FAIL,
     4707                               tr("Failed to allocate secure memory for the key"));
     4708        }
     4709        else
     4710            hrc = setError(E_FAIL,
     4711                           tr("The base64 encoding of the passed key is incorrect"));
     4712    }
     4713    else if (RT_SUCCESS(rc))
     4714        hrc = setError(E_FAIL,
     4715                       tr("The encryption configuration is incomplete"));
     4716
     4717    if (pszUuid)
     4718        RTStrFree(pszUuid);
     4719    if (pszKeyEnc)
     4720    {
     4721        RTMemWipeThoroughly(pszKeyEnc, strlen(pszKeyEnc), 10 /* cMinPasses */);
     4722        RTStrFree(pszKeyEnc);
     4723    }
     4724
     4725    if (ppszEnd)
     4726        *ppszEnd = psz;
     4727
     4728    return hrc;
     4729}
     4730
     4731HRESULT Console::setDiskEncryptionKeys(const Utf8Str &strCfg)
     4732{
     4733    HRESULT hrc = S_OK;
     4734    const char *pszCfg = strCfg.c_str();
     4735
     4736    while (   *pszCfg
     4737           && SUCCEEDED(hrc))
     4738    {
     4739        const char *pszNext = NULL;
     4740        hrc = consoleParseDiskEncryption(pszCfg, &pszNext);
     4741        pszCfg = pszNext;
     4742    }
     4743
     4744    return hrc;
    44444745}
    44454746
     
    86548955    LogRel(("Console: VM runtime error: fatal=%RTbool, errorID=%s message=\"%s\"\n",
    86558956            fFatal, pszErrorId, message.c_str()));
     8957
     8958    /* Set guest property if the reason of the error is a missing DEK for a disk. */
     8959    if (!RTStrCmp(pszErrorId, "DrvVD_DEKMISSING"))
     8960    {
     8961        that->mMachine->DeleteGuestProperty(Bstr("/VirtualBox/HostInfo/DekMissing").raw());
     8962        that->mMachine->SetGuestProperty(Bstr("/VirtualBox/HostInfo/DekMissing").raw(),
     8963                                         Bstr("1").raw(), Bstr("RDONLYGUEST").raw());
     8964        that->mMachine->SaveSettings();
     8965    }
     8966
    86568967
    86578968    that->onRuntimeError(BOOL(fFatal), Bstr(pszErrorId).raw(), Bstr(message).raw());
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette