cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

desc-msos.c (7038B)


      1#include "qemu/osdep.h"
      2#include "hw/usb.h"
      3#include "desc.h"
      4
      5/*
      6 * Microsoft OS Descriptors
      7 *
      8 * Windows tries to fetch some special descriptors with information
      9 * specifically for windows.  Presence is indicated using a special
     10 * string @ index 0xee.  There are two kinds of descriptors:
     11 *
     12 * compatid descriptor
     13 *   Used to bind drivers, if usb class isn't specific enough.
     14 *   Used for PTP/MTP for example (both share the same usb class).
     15 *
     16 * properties descriptor
     17 *   Does carry registry entries.  They show up in
     18 *   HLM\SYSTEM\CurrentControlSet\Enum\USB\<devid>\<serial>\Device Parameters
     19 *
     20 * Note that Windows caches the stuff it got in the registry, so when
     21 * playing with this you have to delete registry subtrees to make
     22 * windows query the device again:
     23 *   HLM\SYSTEM\CurrentControlSet\Control\usbflags
     24 *   HLM\SYSTEM\CurrentControlSet\Enum\USB
     25 * Windows will complain it can't delete entries on the second one.
     26 * It has deleted everything it had permissions too, which is enough
     27 * as this includes "Device Parameters".
     28 *
     29 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff537430.aspx
     30 *
     31 */
     32
     33/* ------------------------------------------------------------------ */
     34
     35typedef struct msos_compat_hdr {
     36    uint32_t dwLength;
     37    uint8_t  bcdVersion_lo;
     38    uint8_t  bcdVersion_hi;
     39    uint8_t  wIndex_lo;
     40    uint8_t  wIndex_hi;
     41    uint8_t  bCount;
     42    uint8_t  reserved[7];
     43} QEMU_PACKED msos_compat_hdr;
     44
     45typedef struct msos_compat_func {
     46    uint8_t  bFirstInterfaceNumber;
     47    uint8_t  reserved_1;
     48    char     compatibleId[8];
     49    uint8_t  subCompatibleId[8];
     50    uint8_t  reserved_2[6];
     51} QEMU_PACKED msos_compat_func;
     52
     53static int usb_desc_msos_compat(const USBDesc *desc, uint8_t *dest)
     54{
     55    msos_compat_hdr *hdr = (void *)dest;
     56    msos_compat_func *func;
     57    int length = sizeof(*hdr);
     58    int count = 0;
     59
     60    func = (void *)(dest + length);
     61    func->bFirstInterfaceNumber = 0;
     62    func->reserved_1 = 0x01;
     63    if (desc->msos->CompatibleID) {
     64        snprintf(func->compatibleId, sizeof(func->compatibleId),
     65                 "%s", desc->msos->CompatibleID);
     66    }
     67    length += sizeof(*func);
     68    count++;
     69
     70    hdr->dwLength      = cpu_to_le32(length);
     71    hdr->bcdVersion_lo = 0x00;
     72    hdr->bcdVersion_hi = 0x01;
     73    hdr->wIndex_lo     = 0x04;
     74    hdr->wIndex_hi     = 0x00;
     75    hdr->bCount        = count;
     76    return length;
     77}
     78
     79/* ------------------------------------------------------------------ */
     80
     81typedef struct msos_prop_hdr {
     82    uint32_t dwLength;
     83    uint8_t  bcdVersion_lo;
     84    uint8_t  bcdVersion_hi;
     85    uint8_t  wIndex_lo;
     86    uint8_t  wIndex_hi;
     87    uint8_t  wCount_lo;
     88    uint8_t  wCount_hi;
     89} QEMU_PACKED msos_prop_hdr;
     90
     91typedef struct msos_prop {
     92    uint32_t dwLength;
     93    uint32_t dwPropertyDataType;
     94    uint8_t  dwPropertyNameLength_lo;
     95    uint8_t  dwPropertyNameLength_hi;
     96    uint8_t  bPropertyName[];
     97} QEMU_PACKED msos_prop;
     98
     99typedef struct msos_prop_data {
    100    uint32_t dwPropertyDataLength;
    101    uint8_t  bPropertyData[];
    102} QEMU_PACKED msos_prop_data;
    103
    104typedef enum msos_prop_type {
    105    MSOS_REG_SZ        = 1,
    106    MSOS_REG_EXPAND_SZ = 2,
    107    MSOS_REG_BINARY    = 3,
    108    MSOS_REG_DWORD_LE  = 4,
    109    MSOS_REG_DWORD_BE  = 5,
    110    MSOS_REG_LINK      = 6,
    111    MSOS_REG_MULTI_SZ  = 7,
    112} msos_prop_type;
    113
    114static int usb_desc_msos_prop_name(struct msos_prop *prop,
    115                                   const wchar_t *name)
    116{
    117    int length = wcslen(name) + 1;
    118    int i;
    119
    120    prop->dwPropertyNameLength_lo = usb_lo(length*2);
    121    prop->dwPropertyNameLength_hi = usb_hi(length*2);
    122    for (i = 0; i < length; i++) {
    123        prop->bPropertyName[i*2]   = usb_lo(name[i]);
    124        prop->bPropertyName[i*2+1] = usb_hi(name[i]);
    125    }
    126    return length*2;
    127}
    128
    129static int usb_desc_msos_prop_str(uint8_t *dest, msos_prop_type type,
    130                                  const wchar_t *name, const wchar_t *value)
    131{
    132    struct msos_prop *prop = (void *)dest;
    133    struct msos_prop_data *data;
    134    int length = sizeof(*prop);
    135    int i, vlen = wcslen(value) + 1;
    136
    137    prop->dwPropertyDataType = cpu_to_le32(type);
    138    length += usb_desc_msos_prop_name(prop, name);
    139    data = (void *)(dest + length);
    140
    141    data->dwPropertyDataLength = cpu_to_le32(vlen*2);
    142    length += sizeof(*prop);
    143
    144    for (i = 0; i < vlen; i++) {
    145        data->bPropertyData[i*2]   = usb_lo(value[i]);
    146        data->bPropertyData[i*2+1] = usb_hi(value[i]);
    147    }
    148    length += vlen*2;
    149
    150    prop->dwLength = cpu_to_le32(length);
    151    return length;
    152}
    153
    154static int usb_desc_msos_prop_dword(uint8_t *dest, const wchar_t *name,
    155                                    uint32_t value)
    156{
    157    struct msos_prop *prop = (void *)dest;
    158    struct msos_prop_data *data;
    159    int length = sizeof(*prop);
    160
    161    prop->dwPropertyDataType = cpu_to_le32(MSOS_REG_DWORD_LE);
    162    length += usb_desc_msos_prop_name(prop, name);
    163    data = (void *)(dest + length);
    164
    165    data->dwPropertyDataLength = cpu_to_le32(4);
    166    data->bPropertyData[0] = (value)       & 0xff;
    167    data->bPropertyData[1] = (value >>  8) & 0xff;
    168    data->bPropertyData[2] = (value >> 16) & 0xff;
    169    data->bPropertyData[3] = (value >> 24) & 0xff;
    170    length += sizeof(*prop) + 4;
    171
    172    prop->dwLength = cpu_to_le32(length);
    173    return length;
    174}
    175
    176static int usb_desc_msos_prop(const USBDesc *desc, uint8_t *dest)
    177{
    178    msos_prop_hdr *hdr = (void *)dest;
    179    int length = sizeof(*hdr);
    180    int count = 0;
    181
    182    if (desc->msos->Label) {
    183        /*
    184         * Given as example in the specs.  Haven't figured yet where
    185         * this label shows up in the windows gui.
    186         */
    187        length += usb_desc_msos_prop_str(dest+length, MSOS_REG_SZ,
    188                                         L"Label", desc->msos->Label);
    189        count++;
    190    }
    191
    192    if (desc->msos->SelectiveSuspendEnabled) {
    193        /*
    194         * Signaling remote wakeup capability in the standard usb
    195         * descriptors isn't enough to make windows actually use it.
    196         * This is the "Yes, we really mean it" registry entry to flip
    197         * the switch in the windows drivers.
    198         */
    199        length += usb_desc_msos_prop_dword(dest+length,
    200                                           L"SelectiveSuspendEnabled", 1);
    201        count++;
    202    }
    203
    204    hdr->dwLength      = cpu_to_le32(length);
    205    hdr->bcdVersion_lo = 0x00;
    206    hdr->bcdVersion_hi = 0x01;
    207    hdr->wIndex_lo     = 0x05;
    208    hdr->wIndex_hi     = 0x00;
    209    hdr->wCount_lo     = usb_lo(count);
    210    hdr->wCount_hi     = usb_hi(count);
    211    return length;
    212}
    213
    214/* ------------------------------------------------------------------ */
    215
    216int usb_desc_msos(const USBDesc *desc,  USBPacket *p,
    217                  int index, uint8_t *dest, size_t len)
    218{
    219    void *buf = g_malloc0(4096);
    220    int length = 0;
    221
    222    switch (index) {
    223    case 0x0004:
    224        length = usb_desc_msos_compat(desc, buf);
    225        break;
    226    case 0x0005:
    227        length = usb_desc_msos_prop(desc, buf);
    228        break;
    229    }
    230
    231    if (length > len) {
    232        length = len;
    233    }
    234    memcpy(dest, buf, length);
    235    g_free(buf);
    236
    237    p->actual_length = length;
    238    return 0;
    239}