[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v5] isa-applesmc: provide OSK forwarding on Apple hosts
From: |
Vladislav Yaroshchuk |
Subject: |
[PATCH v5] isa-applesmc: provide OSK forwarding on Apple hosts |
Date: |
Mon, 25 Oct 2021 17:21:38 +0300 |
On Apple hosts we can read AppleSMC OSK key directly from host's
SMC and forward this value to QEMU Guest.
Usage:
`-device isa-applesmc,osk=host`
Apple licence allows use and run up to two additional copies
or instances of macOS operating 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.
Enable this feature by default on Apple devices
Based on
https://web.archive.org/web/20200103161737/osxbook.com/book/bonus/chapter7/tpmdrmmyth/
Signed-off-by: Vladislav Yaroshchuk <yaroshchuk2000@gmail.com>
---
hw/misc/applesmc.c | 121 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 1b9acaf1d3..6bd2584ca0 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 */
@@ -312,9 +317,106 @@ 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, "isa-applesmc.osk=host ignored: "
+ "unsupported on non-Apple hosts");
+ return false;
+}
+#endif
+
static void applesmc_isa_realize(DeviceState *dev, Error **errp)
{
AppleSMCState *s = APPLE_SMC(dev);
+ Error *err = NULL;
memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s,
"applesmc-data", 1);
@@ -331,6 +433,25 @@ static void applesmc_isa_realize(DeviceState *dev, Error
**errp)
isa_register_ioport(&s->parent_obj, &s->io_err,
s->iobase + APPLESMC_ERR_PORT);
+#if defined(__APPLE__) && defined(__MACH__)
+ /* Enable osk='host' on Apple devices by default */
+ if (!s->osk) {
+ s->osk = g_strdup("host");
+ }
+#endif
+
+ /* Overloaded property: osk='host' forces OSK reading from host AppleSMC */
+ if (s->osk && !strcmp(s->osk, "host")) {
+ g_free(s->osk);
+ s->osk = g_malloc0(65);
+
+ if (!applesmc_read_host_osk(s->osk, &err)) {
+ /* host OSK retrieval error only causes a warning, not a failure */
+ error_report_err(err);
+ s->osk = default_osk;
+ }
+ }
+
if (!s->osk || (strlen(s->osk) != 64)) {
warn_report("Using AppleSMC with invalid key");
s->osk = default_osk;
--
2.23.0
- [PATCH v5] isa-applesmc: provide OSK forwarding on Apple hosts,
Vladislav Yaroshchuk <=