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 > >