ping
https://patchew.org/QEMU/20220113152836.60398-1-yaroshchuk2...@gmail.com/

чт, 13 янв. 2022 г. в 18:28, Vladislav Yaroshchuk <yaroshchuk2...@gmail.com
>:

> On Apple hosts we can read AppleSMC OSK key directly from host's
> SMC and forward this value to QEMU Guest.
>
> New 'hostosk' property is added:
> * `-device isa-applesmc,hostosk=on`
> The property is set to 'on' by default for machine version > 6.2
>
> Apple licence allows use and run up to two additional copies
> or instances of macOS operating system within virtual operating system
> environments on each Apple-branded computer that is already running
> the Apple Software, for purposes of:
>  * software development
>  * testing during software development
>  * using macOS Server
>  * personal, non-commercial use
>
> Guest macOS requires AppleSMC with correct OSK. The most legal
> way to pass it to the Guest is to forward the key from host SMC
> without any value exposion.
>
> Based on
> https://web.archive.org/web/20200103161737/osxbook.com/book/bonus/chapter7/tpmdrmmyth/
>
> Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2...@gmail.com>
> ---
>  hw/core/machine.c  |   4 +-
>  hw/misc/applesmc.c | 125 +++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 125 insertions(+), 4 deletions(-)
>
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index debcdc0e70..ea70be0270 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -37,7 +37,9 @@
>  #include "hw/virtio/virtio.h"
>  #include "hw/virtio/virtio-pci.h"
>
> -GlobalProperty hw_compat_6_2[] = {};
> +GlobalProperty hw_compat_6_2[] = {
> +    { "isa-applesmc", "hostosk", "off" }
> +};
>  const size_t hw_compat_6_2_len = G_N_ELEMENTS(hw_compat_6_2);
>
>  GlobalProperty hw_compat_6_1[] = {
> diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
> index 1b9acaf1d3..99bcc937f9 100644
> --- a/hw/misc/applesmc.c
> +++ b/hw/misc/applesmc.c
> @@ -37,6 +37,11 @@
>  #include "qemu/module.h"
>  #include "qemu/timer.h"
>  #include "qom/object.h"
> +#include "qapi/error.h"
> +
> +#if defined(__APPLE__) && defined(__MACH__)
> +#include <IOKit/IOKitLib.h>
> +#endif
>
>  /* #define DEBUG_SMC */
>
> @@ -80,7 +85,7 @@ enum {
>  #define smc_debug(...) do { } while (0)
>  #endif
>
> -static char default_osk[64] = "This is a dummy key. Enter the real key "
> +static char default_osk[65] = "This is a dummy key. Enter the real key "
>                                "using the -osk parameter";
>
>  struct AppleSMCData {
> @@ -109,6 +114,7 @@ struct AppleSMCState {
>      uint8_t data_pos;
>      uint8_t data[255];
>      char *osk;
> +    bool hostosk;
>      QLIST_HEAD(, AppleSMCData) data_def;
>  };
>
> @@ -312,6 +318,101 @@ static const MemoryRegionOps applesmc_err_io_ops = {
>      },
>  };
>
> +#if defined(__APPLE__) && defined(__MACH__)
> +/*
> + * Based on
> + *
> https://web.archive.org/web/20200103161737/osxbook.com/book/bonus/chapter7/tpmdrmmyth/
> + */
> +enum {
> +    SMC_HANDLE_EVENT     = 2,
> +    SMC_READ_KEY         = 5
> +};
> +
> +struct AppleSMCParam {
> +    uint32_t key;
> +    uint8_t pad0[22];
> +    IOByteCount data_size;
> +    uint8_t pad1[10];
> +    uint8_t command;
> +    uint32_t pad2;
> +    uint8_t bytes[32];
> +};
> +
> +static bool applesmc_read_host_osk(char *host_osk, Error **errp)
> +{
> +    assert(host_osk != NULL);
> +
> +    io_service_t hostsmc_service = IO_OBJECT_NULL;
> +    io_connect_t hostsmc_connect = IO_OBJECT_NULL;
> +    size_t smc_param_size = sizeof(struct AppleSMCParam);
> +    IOReturn status = kIOReturnError;
> +    int i;
> +
> +    struct AppleSMCParam smc_param[2] = {
> +         {
> +             .key = ('OSK0'),
> +             .data_size = sizeof(smc_param[0].bytes),
> +             .command = SMC_READ_KEY,
> +         }, {
> +             .key = ('OSK1'),
> +             .data_size = sizeof(smc_param[0].bytes),
> +             .command = SMC_READ_KEY,
> +         },
> +    };
> +
> +    hostsmc_service = IOServiceGetMatchingService(
> +        kIOMasterPortDefault,
> +        IOServiceMatching("AppleSMC"));
> +    if (hostsmc_service == IO_OBJECT_NULL) {
> +        error_setg(errp, "Unable to get host-AppleSMC service");
> +        goto error;
> +    }
> +
> +    status = IOServiceOpen(hostsmc_service,
> +                           mach_task_self(),
> +                           0,
> +                           &hostsmc_connect);
> +    if (status != kIOReturnSuccess || hostsmc_connect == IO_OBJECT_NULL) {
> +        error_setg(errp, "Unable to open host-AppleSMC service");
> +        goto error;
> +    }
> +
> +    for (i = 0; i < ARRAY_SIZE(smc_param); ++i) {
> +        status = IOConnectCallStructMethod(
> +                hostsmc_connect,
> +                SMC_HANDLE_EVENT,
> +                &smc_param[i],
> +                sizeof(struct AppleSMCParam),
> +                &smc_param[i],
> +                &smc_param_size
> +            );
> +
> +        if (status != kIOReturnSuccess) {
> +            error_setg(errp, "Unable to read OSK from host-AppleSMC");
> +            goto error;
> +        }
> +    }
> +
> +    memcpy(host_osk, smc_param[0].bytes, 32);
> +    memcpy(host_osk + 32, smc_param[1].bytes, 32);
> +
> +    IOServiceClose(hostsmc_connect);
> +    IOObjectRelease(hostsmc_service);
> +    return true;
> +
> +error:
> +    IOServiceClose(hostsmc_connect);
> +    IOObjectRelease(hostsmc_service);
> +    return false;
> +}
> +#else
> +static bool applesmc_read_host_osk(char *host_osk, Error **errp)
> +{
> +    error_setg(errp, "OSK read is not supported on this host");
> +    return false;
> +}
> +#endif
> +
>  static void applesmc_isa_realize(DeviceState *dev, Error **errp)
>  {
>      AppleSMCState *s = APPLE_SMC(dev);
> @@ -331,9 +432,26 @@ static void applesmc_isa_realize(DeviceState *dev,
> Error **errp)
>      isa_register_ioport(&s->parent_obj, &s->io_err,
>                          s->iobase + APPLESMC_ERR_PORT);
>
> -    if (!s->osk || (strlen(s->osk) != 64)) {
> -        warn_report("Using AppleSMC with invalid key");
> +    if (s->osk && s->hostosk) {
> +        error_setg(errp, "-osk property cannot be used with -hostosk=on");
> +    }
> +
> +    if (!s->osk && !s->hostosk) {
>          s->osk = default_osk;
> +        warn_report("Using AppleSMC with default (dummy) OSK");
> +    }
> +
> +    if (s->hostosk) {
> +        s->osk = g_malloc0(65);
> +        /* Fail hard if we cannot read requested host OSK */
> +        if (!applesmc_read_host_osk(s->osk, errp)) {
> +            g_assert_not_reached();
> +        }
> +    }
> +
> +    if (s->osk && strlen(s->osk) != 64) {
> +        /* Only valid OSK is accepted within 'osk' property */
> +        error_setg(errp, "Using AppleSMC with key of invalid length");
>      }
>
>      QLIST_INIT(&s->data_def);
> @@ -344,6 +462,7 @@ static Property applesmc_isa_properties[] = {
>      DEFINE_PROP_UINT32(APPLESMC_PROP_IO_BASE, AppleSMCState, iobase,
>                         APPLESMC_DEFAULT_IOBASE),
>      DEFINE_PROP_STRING("osk", AppleSMCState, osk),
> +    DEFINE_PROP_BOOL("hostosk", AppleSMCState, hostosk, true),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>
> --
> 2.23.0
>
>

Reply via email to