]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fundamental: Add HWID calculation
authoranonymix007 <48598263+anonymix007@users.noreply.github.com>
Thu, 10 Oct 2024 15:35:02 +0000 (18:35 +0300)
committeranonymix007 <48598263+anonymix007@users.noreply.github.com>
Tue, 5 Nov 2024 11:48:43 +0000 (14:48 +0300)
src/fundamental/chid-fundamental.c [new file with mode: 0644]
src/fundamental/chid-fundamental.h [new file with mode: 0644]
src/fundamental/meson.build

diff --git a/src/fundamental/chid-fundamental.c b/src/fundamental/chid-fundamental.c
new file mode 100644 (file)
index 0000000..55b04fa
--- /dev/null
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+/*
+ * Based on Nikita Travkin's dtbloader implementation.
+ * Copyright (c) 2024 Nikita Travkin <nikita@trvn.ru>
+ *
+ * https://github.com/TravMurav/dtbloader/blob/main/src/chid.c
+ */
+
+/*
+ * Based on Linaro dtbloader implementation.
+ * Copyright (c) 2019, Linaro. All rights reserved.
+ *
+ * https://github.com/aarch64-laptops/edk2/blob/dtbloader-app/EmbeddedPkg/Application/ConfigTableLoader/CHID.c
+ */
+
+#if SD_BOOT
+#  include "efi-string.h"
+#  include "util.h"
+#else
+#  include <byteswap.h>
+#  include <string.h>
+#  include <uchar.h>
+#  include <utf8.h>
+#define strsize16(str) ((char16_strlen(str) + 1) * sizeof(char16_t))
+#endif
+
+#include "chid-fundamental.h"
+#include "macro-fundamental.h"
+#include "memory-util-fundamental.h"
+#include "sha1-fundamental.h"
+
+static void get_chid(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], uint32_t mask, EFI_GUID *ret_chid) {
+        assert(mask != 0);
+        assert(ret_chid);
+        const EFI_GUID namespace = { UINT32_C(0x12d8ff70), UINT16_C(0x7f4c), UINT16_C(0x7d4c), {} }; /* Swapped to BE */
+
+        struct sha1_ctx ctx = {};
+        sha1_init_ctx(&ctx);
+
+        sha1_process_bytes(&namespace, sizeof(namespace), &ctx);
+
+        for (unsigned i = 0; i < _CHID_SMBIOS_FIELDS_MAX; i++)
+                if ((mask >> i) & 1) {
+                        if (i > 0)
+                                sha1_process_bytes(L"&", 2, &ctx);
+                        sha1_process_bytes(smbios_fields[i], strsize16(smbios_fields[i]), &ctx);
+                }
+
+        uint8_t hash[SHA1_DIGEST_SIZE];
+        sha1_finish_ctx(&ctx, hash);
+
+        assert_cc(sizeof(hash) >= sizeof(*ret_chid));
+        memcpy(ret_chid, hash, sizeof(*ret_chid));
+
+        /* Convert the resulting CHID back to little-endian: */
+        ret_chid->Data1 = bswap_32(ret_chid->Data1);
+        ret_chid->Data2 = bswap_16(ret_chid->Data2);
+        ret_chid->Data3 = bswap_16(ret_chid->Data3);
+
+        /* set specific bits according to RFC4122 Section 4.1.3 */
+        ret_chid->Data3 = (ret_chid->Data3 & 0x0fff) | (5 << 12);
+        ret_chid->Data4[0] = (ret_chid->Data4[0] & UINT8_C(0x3f)) | UINT8_C(0x80);
+}
+
+static const uint32_t chid_smbios_table[CHID_TYPES_MAX] = {
+        [3] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_FAMILY) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU) |
+              (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT),
+
+        [4] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_FAMILY) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU),
+
+        [5] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_FAMILY) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME),
+
+        [6] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU) |
+              (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT),
+
+        [7] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_SKU),
+
+        [8] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME) |
+              (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT),
+
+        [9] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+              (UINT32_C(1) << CHID_SMBIOS_PRODUCT_NAME),
+
+        [10] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+               (UINT32_C(1) << CHID_SMBIOS_FAMILY) |
+               (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) |
+               (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT),
+
+        [11] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+               (UINT32_C(1) << CHID_SMBIOS_FAMILY),
+
+        [13] = (UINT32_C(1) << CHID_SMBIOS_MANUFACTURER) |
+               (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_MANUFACTURER) |
+               (UINT32_C(1) << CHID_SMBIOS_BASEBOARD_PRODUCT),
+};
+
+void chid_calculate(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], EFI_GUID ret_chids[static CHID_TYPES_MAX]) {
+        assert(smbios_fields);
+        assert(ret_chids);
+        for (size_t i = 0; i < _CHID_SMBIOS_FIELDS_MAX; i++)
+                if (chid_smbios_table[i] != 0)
+                        get_chid(smbios_fields, chid_smbios_table[i], &ret_chids[i]);
+                else
+                        memzero(&ret_chids[i], sizeof(EFI_GUID));
+}
diff --git a/src/fundamental/chid-fundamental.h b/src/fundamental/chid-fundamental.h
new file mode 100644 (file)
index 0000000..e8c5c1a
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#pragma once
+
+#include "efi-fundamental.h"
+#include "string-util-fundamental.h"
+
+#define CHID_TYPES_MAX 15
+
+typedef enum ChidSmbiosFields {
+        CHID_SMBIOS_MANUFACTURER,
+        CHID_SMBIOS_FAMILY,
+        CHID_SMBIOS_PRODUCT_NAME,
+        CHID_SMBIOS_PRODUCT_SKU,
+        CHID_SMBIOS_BASEBOARD_MANUFACTURER,
+        CHID_SMBIOS_BASEBOARD_PRODUCT,
+        _CHID_SMBIOS_FIELDS_MAX,
+} ChidSmbiosFields;
+
+/* CHID (also called HWID by fwupd) is described at https://github.com/fwupd/fwupd/blob/main/docs/hwids.md */
+void chid_calculate(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], EFI_GUID ret_chids[static CHID_TYPES_MAX]);
index b1522a88f8e37c1a2adf7b9c11490c96a97c0895..7b72372e8382d57e557004e680eddd3c50683f44 100644 (file)
@@ -4,6 +4,7 @@ fundamental_include = include_directories('.')
 
 fundamental_sources = files(
         'bootspec-fundamental.c',
+        'chid-fundamental.c',
         'efivars-fundamental.c',
         'iovec-util-fundamental.h',
         'sha1-fundamental.c',