VirtualBox

Changeset 90316 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jul 23, 2021 3:49:47 PM (4 years ago)
Author:
vboxsync
Message:

Runtime/tools/RTEfiSigDb: Add a sub-command to add new signatures to a particular database, bugref:9580

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/tools/RTEfiSigDb.cpp

    r90297 r90316  
    4141#include <iprt/stream.h>
    4242#include <iprt/string.h>
     43#include <iprt/uuid.h>
    4344#include <iprt/vfs.h>
    4445
     
    5253*   Global Variables                                                                                                             *
    5354*********************************************************************************************************************************/
     55/** Signature type identifier to internal type mapping. */
     56struct
     57{
     58    const char   *pszId;
     59    RTEFISIGTYPE enmType;
     60} g_aId2SigType[] =
     61{
     62    { "sha256",  RTEFISIGTYPE_SHA256  },
     63    { "rsa2048", RTEFISIGTYPE_RSA2048 },
     64    { "x509",    RTEFISIGTYPE_X509    }
     65};
    5466
    5567
     
    8395                 , RTPathFilename(pszArg0));
    8496
     97    if (!pszCommand || !strcmp(pszCommand, "add"))
     98        RTPrintf("Usage: %s add <signature database path> <x509|sha256|rsa2048> <owner uuid> <signature path> ...\n"
     99                 , RTPathFilename(pszArg0));
     100
    85101    return RTEXITCODE_SUCCESS;
     102}
     103
     104
     105static RTEFISIGTYPE rtEfiSigDbGetTypeById(const char *pszId)
     106{
     107    for (uint32_t i = 0; i < RT_ELEMENTS(g_aId2SigType); i++)
     108        if (!strcmp(pszId, g_aId2SigType[i].pszId))
     109            return g_aId2SigType[i].enmType;
     110
     111    return RTEFISIGTYPE_INVALID;
     112}
     113
     114
     115/**
     116 * Opens the specified signature database, returning an VFS file handle on success.
     117 *
     118 * @returns IPRT status code.
     119 * @param   pszPath             Path to the signature database.
     120 * @param   phVfsFile           Where to return the VFS file handle on success.
     121 */
     122static int rtEfiSigDbOpen(const char *pszPath, PRTVFSFILE phVfsFile)
     123{
     124    int rc;
     125
     126    if (RTVfsChainIsSpec(pszPath))
     127    {
     128        RTVFSOBJ hVfsObj;
     129        rc = RTVfsChainOpenObj(pszPath, RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
     130                               RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING | RTPATH_F_ON_LINK,
     131                               &hVfsObj, NULL, NULL);
     132        if (   RT_SUCCESS(rc)
     133            && RTVfsObjGetType(hVfsObj) == RTVFSOBJTYPE_FILE)
     134        {
     135            *phVfsFile = RTVfsObjToFile(hVfsObj);
     136            RTVfsObjRelease(hVfsObj);
     137        }
     138        else
     139        {
     140            RTPrintf("'%s' doesn't point to a file\n", pszPath);
     141            rc = VERR_INVALID_PARAMETER;
     142        }
     143    }
     144    else
     145        rc = RTVfsFileOpenNormal(pszPath, RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
     146                                 phVfsFile);
     147
     148    return rc;
    86149}
    87150
     
    117180    RT_NOREF(pszArg0);
    118181
    119     /*
    120      * Parse arguments.
    121      */
    122     static const RTGETOPTDEF s_aOptions[] =
    123     {
    124         { "--input",    'i', RTGETOPT_REQ_STRING }
    125     };
    126 
    127     int             rc       = VINF_SUCCESS;
    128     RTEXITCODE      rcExit   = RTEXITCODE_SUCCESS;
    129     const char     *pszInput = NULL;
    130 
    131     RTGETOPTUNION   ValueUnion;
    132     RTGETOPTSTATE   GetState;
    133     RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    134     while ((rc = RTGetOpt(&GetState, &ValueUnion)))
    135     {
    136         switch (rc)
    137         {
    138             case 'i':
    139                 pszInput = ValueUnion.psz;
    140                 break;
    141             default:
    142                 return RTGetOptPrintError(rc, &ValueUnion);
    143         }
    144     }
    145 
    146     if (!pszInput)
     182    if (!cArgs)
    147183    {
    148184        RTPrintf("An input path must be given\n");
     
    150186    }
    151187
     188    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    152189    RTVFSFILE hVfsFile = NIL_RTVFSFILE;
    153     if (RTVfsChainIsSpec(pszInput))
    154     {
    155         RTVFSOBJ hVfsObj;
    156         rc = RTVfsChainOpenObj(pszInput, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
    157                                RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING | RTPATH_F_ON_LINK,
    158                                &hVfsObj, NULL, NULL);
    159         if (   RT_SUCCESS(rc)
    160             && RTVfsObjGetType(hVfsObj) == RTVFSOBJTYPE_FILE)
    161         {
    162             hVfsFile = RTVfsObjToFile(hVfsObj);
    163             RTVfsObjRelease(hVfsObj);
     190    int rc = rtEfiSigDbOpen(papszArgs[0], &hVfsFile);
     191    if (RT_SUCCESS(rc))
     192    {
     193        RTEFISIGDB hEfiSigDb;
     194        rc = RTEfiSigDbCreate(&hEfiSigDb);
     195        if (RT_SUCCESS(rc))
     196        {
     197            uint32_t idxSig = 0;
     198
     199            rc = RTEfiSigDbAddFromExistingDb(hEfiSigDb, hVfsFile);
     200            if (RT_SUCCESS(rc))
     201                RTEfiSigDbEnum(hEfiSigDb, rtEfiSgDbEnum, &idxSig);
     202            else
     203            {
     204                RTPrintf("Loading the signature database failed with %Rrc\n", rc);
     205                rcExit = RTEXITCODE_FAILURE;
     206            }
     207
     208            RTEfiSigDbDestroy(hEfiSigDb);
    164209        }
    165210        else
    166211        {
    167             RTPrintf("'%s' doesn't point to a file\n", pszInput);
    168             return RTEXITCODE_FAILURE;
    169         }
     212            RTPrintf("Creating the signature database failed with %Rrc\n", rc);
     213            rcExit = RTEXITCODE_FAILURE;
     214        }
     215
     216        RTVfsFileRelease(hVfsFile);
    170217    }
    171218    else
    172         rc = RTVfsFileOpenNormal(pszInput, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
    173                                  &hVfsFile);
    174 
    175     RTEFISIGDB hEfiSigDb;
    176     rc = RTEfiSigDbCreate(&hEfiSigDb);
     219        rcExit = RTEXITCODE_FAILURE;
     220
     221    return rcExit;
     222}
     223
     224
     225/**
     226 * Handles the 'add' command.
     227 *
     228 * @returns Program exit code.
     229 * @param   pszArg0             The program name.
     230 * @param   cArgs               The number of arguments to the 'add' command.
     231 * @param   papszArgs           The argument vector, starting after 'add'.
     232 */
     233static RTEXITCODE rtEfiSgDbCmdAdd(const char *pszArg0, int cArgs, char **papszArgs)
     234{
     235    RT_NOREF(pszArg0);
     236
     237    if (!cArgs)
     238    {
     239        RTPrintf("The signature database path is missing\n");
     240        return RTEXITCODE_FAILURE;
     241    }
     242
     243    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     244    RTVFSFILE hVfsFile = NIL_RTVFSFILE;
     245    int rc = rtEfiSigDbOpen(papszArgs[0], &hVfsFile);
    177246    if (RT_SUCCESS(rc))
    178247    {
    179         uint32_t idxSig = 0;
    180 
    181         rc = RTEfiSigDbAddFromExistingDb(hEfiSigDb, hVfsFile);
     248        RTEFISIGDB hEfiSigDb;
     249        rc = RTEfiSigDbCreate(&hEfiSigDb);
    182250        if (RT_SUCCESS(rc))
    183             RTEfiSigDbEnum(hEfiSigDb, rtEfiSgDbEnum, &idxSig);
    184 
    185         RTEfiSigDbDestroy(hEfiSigDb);
    186     }
    187 
    188     RTVfsFileRelease(hVfsFile);
     251        {
     252            uint64_t cbSigDb = 0;
     253            rc = RTVfsFileQuerySize(hVfsFile, &cbSigDb);
     254            if (   RT_SUCCESS(rc)
     255                && cbSigDb)
     256                rc = RTEfiSigDbAddFromExistingDb(hEfiSigDb, hVfsFile);
     257            if (RT_SUCCESS(rc))
     258            {
     259                cArgs--;
     260                papszArgs++;
     261
     262                while (cArgs >= 3)
     263                {
     264                    RTEFISIGTYPE enmSigType    = rtEfiSigDbGetTypeById(papszArgs[0]);
     265                    const char *pszUuidOwner   = papszArgs[1];
     266                    const char *pszSigDataPath = papszArgs[2];
     267
     268                    if (enmSigType == RTEFISIGTYPE_INVALID)
     269                    {
     270                        RTPrintf("Signature type '%s' is not known\n", papszArgs[0]);
     271                        break;
     272                    }
     273
     274                    RTUUID UuidOwner;
     275                    rc = RTUuidFromStr(&UuidOwner, pszUuidOwner);
     276                    if (RT_FAILURE(rc))
     277                    {
     278                        RTPrintf("UUID '%s' is malformed\n", pszUuidOwner);
     279                        break;
     280                    }
     281
     282                    RTVFSFILE hVfsFileSigData = NIL_RTVFSFILE;
     283                    rc = rtEfiSigDbOpen(pszSigDataPath, &hVfsFileSigData);
     284                    if (RT_FAILURE(rc))
     285                    {
     286                        RTPrintf("Opening '%s' failed with %Rrc\n", pszSigDataPath);
     287                        break;
     288                    }
     289
     290                    rc = RTEfiSigDbAddSignatureFromFile(hEfiSigDb, enmSigType, &UuidOwner, hVfsFileSigData);
     291                    RTVfsFileRelease(hVfsFileSigData);
     292                    if (RT_FAILURE(rc))
     293                    {
     294                        RTPrintf("Adding signature data from '%s' failed with %Rrc\n", pszSigDataPath, rc);
     295                        break;
     296                    }
     297                    papszArgs += 3;
     298                    cArgs     -= 3;
     299                }
     300
     301                if (RT_SUCCESS(rc))
     302                {
     303                    if (!cArgs)
     304                    {
     305                        rc = RTVfsFileSeek(hVfsFile, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
     306                        AssertRC(rc);
     307
     308                        rc = RTEfiSigDbWriteToFile(hEfiSigDb, hVfsFile);
     309                        if (RT_FAILURE(rc))
     310                        {
     311                            RTPrintf("Writing the updated signature database failed with %Rrc\n", rc);
     312                            rcExit = RTEXITCODE_FAILURE;
     313                        }
     314                    }
     315                    else
     316                    {
     317                        RTPrintf("Incomplete list of entries to add given\n");
     318                        rcExit = RTEXITCODE_FAILURE;
     319                    }
     320                }
     321            }
     322            else
     323            {
     324                RTPrintf("Loading the signature database failed with %Rrc\n", rc);
     325                rcExit = RTEXITCODE_FAILURE;
     326            }
     327
     328            RTEfiSigDbDestroy(hEfiSigDb);
     329        }
     330        else
     331        {
     332            RTPrintf("Creating the signature database failed with %Rrc\n", rc);
     333            rcExit = RTEXITCODE_FAILURE;
     334        }
     335
     336        RTVfsFileRelease(hVfsFile);
     337    }
     338    else
     339        rcExit = RTEXITCODE_FAILURE;
     340
    189341    return rcExit;
    190342}
     
    205357    else if (!strcmp(argv[1], "list"))
    206358        rcExit = rtEfiSgDbCmdList(argv[0], argc - 2, argv + 2);
     359    else if (!strcmp(argv[1], "add"))
     360        rcExit = rtEfiSgDbCmdAdd(argv[0], argc - 2, argv + 2);
    207361    else if (   !strcmp(argv[1], "-h")
    208362             || !strcmp(argv[1], "-?")
Note: See TracChangeset for help on using the changeset viewer.

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