Page MenuHomeFreeBSD

D12698.id43475.diff
No OneTemporary

D12698.id43475.diff

Index: stand/efi/include/efi_drivers.h
===================================================================
--- stand/efi/include/efi_drivers.h
+++ stand/efi/include/efi_drivers.h
@@ -36,10 +36,11 @@
void (*init)(void);
} efi_driver_t;
-extern struct devsw efipart_dev;
+extern const efi_driver_t *efi_drivers[];
+
extern int efipart_getdesc(struct devdesc *dev, char **out);
/* EFI drivers. */
-extern const efi_driver_t fs_driver;
+extern const efi_driver_t key_inject_driver;
#endif
Index: stand/efi/include/efisec.h
===================================================================
--- /dev/null
+++ stand/efi/include/efisec.h
@@ -0,0 +1,294 @@
+/*-
+ * Copyright (c) 2016 Eric McCorkle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <efi.h>
+
+#ifndef _EFISEC_H_
+#define _EFISEC_H_
+
+#define EFI_KMS_PROTOCOL \
+ { 0xec3a978d, 0x7c4e, 0x48fa, { 0x9a, 0xbe, 0x6a, 0xd9, 0x1c, 0xc8, 0xf8, 0x11 } }
+
+#define EFI_KMS_DATA_TYPE_NONE 0
+#define EFI_KMS_DATA_TYPE_BINARY 1
+#define EFI_KMS_DATA_TYPE_ASCII 2
+#define EFI_KMS_DATA_TYPE_UNICODE 4
+#define EFI_KMS_DATA_TYPE_UTF8 8
+
+typedef struct {
+ UINT16 ClientIdSize;
+ VOID *ClientId;
+ UINT8 ClientNameType;
+ UINT8 ClientNameCount;
+ VOID *ClientName;
+} EFI_KMS_CLIENT_INFO;
+
+/* Note: GUIDs for insecure crypto have been omitted */
+#define EFI_KMS_FORMAT_GENERIC_128_GUID \
+ { 0xec8a3d69, 0x6ddf, 0x4108, { 0x94, 0x76, 0x73, 0x37, 0xfc, 0x52, 0x21, 0x36 } }
+
+#define EFI_KMS_FORMAT_GENERIC_160_GUID \
+ { 0xa3b3e6f8, 0xefca, 0x4bc1, { 0x88, 0xfb, 0xcb, 0x87, 0x33, 0x9b, 0x25, 0x79 } }
+
+#define EFI_KMS_FORMAT_GENERIC_256_GUID \
+ { 0x70f64793, 0xc323, 0x4261, { 0xac, 0x2c, 0xd8, 0x76, 0xf2, 0x7c, 0x53, 0x45 } }
+
+#define EFI_KMS_FORMAT_GENERIC_512_GUID \
+ { 0x978fe043, 0xd7af, 0x422e, { 0x8a, 0x92, 0x2b, 0x48, 0xe4, 0x63, 0xbd, 0xe6 } }
+
+#define EFI_KMS_FORMAT_GENERIC_1024_GUID \
+ { 0x43be0b44, 0x874b, 0x4ead, { 0xb0, 0x9c, 0x24, 0x1a, 0x4f, 0xbd, 0x7e, 0xb3 } }
+
+#define EFI_KMS_FORMAT_GENERIC_2048_GUID \
+ { 0x40093f23, 0x630c, 0x4626, { 0x9c, 0x48, 0x40, 0x37, 0x3b, 0x19, 0xcb, 0xbe } }
+
+#define EFI_KMS_FORMAT_GENERIC_3072_GUID \
+ { 0xb9237513, 0x6c44, 0x4411, { 0xa9, 0x90, 0x21, 0xe5, 0x56, 0xe0, 0x5a, 0xde } }
+
+#define EFI_KMS_FORMAT_SHA256_GUID \
+ { 0x6bb4f5cd, 0x8022, 0x448d, { 0xbc, 0x6d, 0x77, 0x1b, 0xae, 0x93, 0x5f, 0xc6 } }
+
+#define EFI_KMS_FORMAT_SHA512_GUID \
+ { 0x2f240e12, 0xe1d4, 0x475c, { 0x83, 0xb0, 0xef, 0xff, 0x22, 0xd7, 0x7b, 0xe7 } }
+
+#define EFI_KMS_FORMAT_AESXTS_128_GUID \
+ { 0x4776e33f, 0xdb47, 0x479a, { 0xa2, 0x5f, 0xa1, 0xcd, 0x0a, 0xfa, 0xb2, 0x8b } }
+
+#define EFI_KMS_FORMAT_AESXTS_256_GUID \
+ { 0xdc7e8613, 0xc4bb, 0x4db0, { 0x84, 0x62, 0x13, 0x51, 0x13, 0x57, 0xab, 0xe2 } }
+
+#define EFI_KMS_FORMAT_AESCBC_128_GUID \
+ { 0xa0e8ee89, 0x0e92, 0x44d4, { 0x86, 0x1b, 0x0e, 0xaa, 0x4a, 0xca, 0x44, 0xa2 } }
+
+#define EFI_KMS_FORMAT_AESCBC_256_GUID \
+ { 0xd7e69789, 0x1f68, 0x45e8, { 0x96, 0xef, 0x3b, 0xe8, 0xbb, 0x17, 0xf8, 0xf9 } }
+
+#define EFI_KMS_FORMAT_RSASHA256_2048_GUID \
+ { 0xa477af13, 0x877d, 0x4060, { 0xba, 0xa1, 0x25, 0xb1, 0xbe, 0xa0, 0x8a, 0xd3 } }
+
+#define EFI_KMS_FORMAT_RSASHA256_3072_GUID \
+ { 0x4e1356c2, 0x0eed, 0x463f, { 0x81, 0x47, 0x99, 0x33, 0xab, 0xdb, 0xc7, 0xd5 } }
+
+#define EFI_KMS_KEY_IDENTIFIER_MAX_SIZE 255
+#define EFI_KMS_KEY_ATTRIBUTE_ID_MAX_SIZE 255
+
+typedef struct {
+ UINT8 KeyIdentifierSize;
+ VOID *KeyIdentifier;
+ EFI_GUID KeyFormat;
+ VOID *KeyValue;
+ EFI_STATUS KeyStatus;
+} EFI_KMS_KEY_DESCRIPTOR;
+
+#define EFI_KMS_ATTRIBUTE_TYPE_NONE 0x00
+#define EFI_KMS_ATTRIBUTE_TYPE_INTEGER 0x01
+#define EFI_KMS_ATTRIBUTE_TYPE_LONG_INTEGER 0x02
+#define EFI_KMS_ATTRIBUTE_TYPE_BIG_INTEGER 0x03
+#define EFI_KMS_ATTRIBUTE_TYPE_ENUMERATION 0x04
+#define EFI_KMS_ATTRIBUTE_TYPE_BOOLEAN 0x05
+#define EFI_KMS_ATTRIBUTE_TYPE_BYTE_STRING 0x06
+#define EFI_KMS_ATTRIBUTE_TYPE_TEXT_STRING 0x07
+#define EFI_KMS_ATTRIBUTE_TYPE_DATE_TIME 0x08
+#define EFI_KMS_ATTRIBUTE_TYPE_INTERVAL 0x09
+#define EFI_KMS_ATTRIBUTE_TYPE_STRUCTURE 0x0a
+#define EFI_KMS_ATTRIBUTE_TYPE_DYNAMIC 0x0b
+
+typedef struct {
+ UINT16 Tag;
+ UINT16 Type;
+ UINT32 Length;
+ UINT8 KeyAttributeData[];
+} EFI_KMS_DYNAMIC_FIELD;
+
+typedef struct {
+ UINT32 FieldCount;
+ EFI_KMS_DYNAMIC_FIELD Field[];
+} EFI_KMS_DYNAMIC_ATTRIBUTE;
+
+typedef struct {
+ UINT8 KeyAttributeIdentifierType;
+ UINT8 KeyAttributeIdentifierCount;
+ VOID *KeyAttributeIdentifier;
+ UINT16 KeyAttributeInstance;
+ UINT16 KeyAttributeType;
+ UINT16 KeyAttributeValueSize;
+ VOID *KeyAttributeValue;
+ EFI_STATUS KeyAttributeStatus;
+} EFI_KMS_KEY_ATTRIBUTE;
+
+INTERFACE_DECL(_EFI_KMS_SERVICE);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_GET_SERVICE_STATUS) (
+ IN struct _EFI_KMS_SERVICE *This
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_REGISTER_CLIENT) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN OUT UINTN *ClientDataState OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_CREATE_KEY) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN OUT UINT16 *KeyDescriptorCount,
+ IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_GET_KEY) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN OUT UINT16 *KeyDescriptorCount,
+ IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_ADD_KEY) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN OUT UINT16 *KeyDescriptorCount,
+ IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_DELETE_KEY) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN OUT UINT16 *KeyDescriptorCount,
+ IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_GET_KEY_ATTRIBUTES) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN UINT8 *KeyIdentifierSize,
+ IN const VOID *KeyIdentifier,
+ IN OUT UINT16 *KeyAttributesCount,
+ IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_ADD_KEY_ATTRIBUTES) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN UINT8 *KeyIdentifierSize,
+ IN const VOID *KeyIdentifier,
+ IN OUT UINT16 *KeyAttributesCount,
+ IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_DELETE_KEY_ATTRIBUTES) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN UINT8 *KeyIdentifierSize,
+ IN const VOID *KeyIdentifier,
+ IN OUT UINT16 *KeyAttributesCount,
+ IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_KMS_GET_KEY_BY_ATTRIBUTES) (
+ IN struct _EFI_KMS_SERVICE *This,
+ IN EFI_KMS_CLIENT_INFO *Client,
+ IN UINTN *KeyAttributeCount,
+ IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes,
+ IN OUT UINTN *KeyDescriptorCount,
+ IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor,
+ IN OUT UINTN *ClientDataSize OPTIONAL,
+ IN OUT VOID **ClientData OPTIONAL
+ );
+
+#define EFI_KMS_PROTOCOL_VERSION 0x00020040
+
+typedef struct _EFI_KMS_SERVICE {
+ EFI_KMS_GET_SERVICE_STATUS GetServiceStatus;
+ EFI_KMS_REGISTER_CLIENT RegisterClient;
+ EFI_KMS_CREATE_KEY CreateKey;
+ EFI_KMS_GET_KEY GetKey;
+ EFI_KMS_ADD_KEY AddKey;
+ EFI_KMS_DELETE_KEY DeleteKey;
+ EFI_KMS_GET_KEY_ATTRIBUTES GetKeyAttributes;
+ EFI_KMS_ADD_KEY_ATTRIBUTES AddKeyAttributes;
+ EFI_KMS_DELETE_KEY_ATTRIBUTES DeleteKeyAttributes;
+ EFI_KMS_GET_KEY_BY_ATTRIBUTES GetKeyByAttributes;
+ UINT32 ProtocolVersion;
+ EFI_GUID ServiceId;
+ CHAR16 *ServiceName;
+ UINT32 ServiceVersion;
+ BOOLEAN ServiceAvailable;
+ BOOLEAN ClientIdSupported;
+ BOOLEAN ClientIdRequired;
+ UINT16 ClientIdMaxSize;
+ UINT8 ClientNameStringTypes;
+ BOOLEAN ClientNameRequired;
+ UINT16 ClientNameMaxCount;
+ BOOLEAN ClientDataSupported;
+ UINTN ClientDataMaxSize;
+ BOOLEAN KeyIdVariableLenSupported;
+ UINTN KeyIdMaxSize;
+ UINTN KeyFormatsCount;
+ EFI_GUID *KeyFormats;
+ BOOLEAN KeyAttributesSupported;
+ UINT8 KeyAttributeIdStringTypes;
+ UINT16 KeyAttributeIdMaxCount;
+ UINTN KeyAttributesCount;
+ EFI_KMS_KEY_ATTRIBUTE *KeyAttributes;
+} EFI_KMS_SERVICE;
+
+#endif
Index: stand/efi/include/key_inject.h
===================================================================
--- /dev/null
+++ stand/efi/include/key_inject.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2016 Eric McCorkle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _KEY_INJECT_H_
+#define _KEY_INJECT_H_
+
+/* Registering a client with the name KERNEL and an ID structure as
+ * shown below sets the injection point for keys into the kernel.
+ */
+#define KERNEL_CLIENT_NAME "KERNEL"
+#define KERNEL_CLIENT_NAME_LEN 6
+
+#define KERNEL_KEY_INJECTOR_GUID \
+ { 0x53badd16, 0x1e9c, 0x493b, { 0x9d, 0x22, 0xe0, 0xab, 0x24, 0xb1, 0xc0, 0x11 } }
+
+extern EFI_KMS_KEY_ATTRIBUTE * const key_attr_service_id_geli;
+extern EFI_KMS_KEY_ATTRIBUTE * const key_attr_service_id_passphrase;
+
+/* Structure used as client ID for the "KERNEL" client */
+typedef struct {
+ void *keybuf;
+ size_t nents;
+} kernel_client_id_t;
+
+#endif
Index: stand/efi/libefi/Makefile
===================================================================
--- stand/efi/libefi/Makefile
+++ stand/efi/libefi/Makefile
@@ -18,6 +18,7 @@
env.c \
errno.c \
handles.c \
+ key_inject.c \
libefi.c \
wchar.c
Index: stand/efi/libefi/key_inject.c
===================================================================
--- /dev/null
+++ stand/efi/libefi/key_inject.c
@@ -0,0 +1,744 @@
+/*-
+ * Copyright (c) 2016 Eric McCorkle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <crypto/intake.h>
+#include <efi.h>
+#include <efilib.h>
+#include <efisec.h>
+#include <stdbool.h>
+#include <string.h>
+#include <bootstrap.h>
+
+#include <sys/linker.h>
+
+#include "efi_drivers.h"
+#include "key_inject.h"
+
+#define MAX_KEYS 64
+
+#define KEY_ATTR_SERVICE_ID_NAME "SERVICE_ID"
+#define KEY_ATTR_SERVICE_ID_NAME_LEN 10
+
+enum key_attr_id_t {
+ KEY_ATTR_SERVICE_ID_GELI,
+ KEY_ATTR_SERVICE_ID_PASSPHRASE
+};
+
+/* Tell who provided the key */
+enum service_id_t {
+ SERVICE_ID_NONE,
+ SERVICE_ID_GELI,
+ SERVICE_ID_PASSPHRASE
+};
+
+typedef struct key_entry_t {
+ UINT8 k_id_size;
+ UINT8 k_id[EFI_KMS_KEY_IDENTIFIER_MAX_SIZE];
+ enum service_id_t k_service;
+ EFI_GUID k_format;
+ char k_data[MAX_KEY_BYTES];
+} key_entry_t;
+
+static key_entry_t keys[MAX_KEYS];
+
+static int service_id_geli = SERVICE_ID_GELI;
+static int service_id_passphrase = SERVICE_ID_PASSPHRASE;
+static EFI_GUID Generic128Guid = EFI_KMS_FORMAT_GENERIC_128_GUID;
+static EFI_GUID Generic256Guid = EFI_KMS_FORMAT_GENERIC_256_GUID;
+static EFI_GUID Generic512Guid = EFI_KMS_FORMAT_GENERIC_512_GUID;
+static EFI_GUID Generic1024Guid = EFI_KMS_FORMAT_GENERIC_1024_GUID;
+static EFI_GUID Generic2048Guid = EFI_KMS_FORMAT_GENERIC_2048_GUID;
+static EFI_GUID Generic3072Guid = EFI_KMS_FORMAT_GENERIC_3072_GUID;
+static EFI_GUID AesXts128Guid = EFI_KMS_FORMAT_AESXTS_128_GUID;
+static EFI_GUID AesXts256Guid = EFI_KMS_FORMAT_AESXTS_256_GUID;
+static EFI_GUID AesCbc128Guid = EFI_KMS_FORMAT_AESCBC_128_GUID;
+static EFI_GUID AesCbc256Guid = EFI_KMS_FORMAT_AESCBC_256_GUID;
+static EFI_GUID RsaSha2048Guid = EFI_KMS_FORMAT_RSASHA256_2048_GUID;
+static EFI_GUID RsaSha3072Guid = EFI_KMS_FORMAT_RSASHA256_3072_GUID;
+static EFI_GUID EfiKmsProtocolGuid = EFI_KMS_PROTOCOL;
+static EFI_GUID KernelKeyInjectorGuid = KERNEL_KEY_INJECTOR_GUID;
+
+static EFI_KMS_SERVICE key_inject_kms;
+
+static void
+fill_keybuf(struct keybuf *keybuf)
+{
+ int i, idx;
+
+ for (i = 0, idx = 0; i < MAX_KEYS; i++) {
+ switch (keys[i].k_service) {
+ default:
+ printf("Unknown service type %u\n", keys[i].k_service);
+
+ case SERVICE_ID_PASSPHRASE:
+ case SERVICE_ID_NONE:
+ break;
+
+ case SERVICE_ID_GELI:
+ keybuf->kb_ents[idx].ke_type = KEYBUF_TYPE_GELI;
+ memcpy(keybuf->kb_ents[idx].ke_data, keys[i].k_data,
+ MAX_KEY_BYTES);
+ idx++;
+ break;
+ }
+ }
+
+ keybuf->kb_nents = idx;
+}
+
+static EFI_STATUS EFIAPI
+register_client_impl(EFI_KMS_SERVICE *This, EFI_KMS_CLIENT_INFO *Client,
+ UINTN *ClientDataState __unused, VOID **ClientData __unused)
+{
+ size_t keybuf_size = sizeof(struct keybuf) +
+ (MAX_KEYS * sizeof(struct keybuf_ent));
+ char buf[keybuf_size];
+ struct preloaded_file *kfp;
+
+ /* Spec compliance */
+ if (This == NULL || Client == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if (Client->ClientIdSize != sizeof(struct preloaded_file *)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ kfp = (struct preloaded_file *)Client->ClientId;
+ fill_keybuf((struct keybuf *)buf);
+ file_addmetadata(kfp, MODINFOMD_KEYBUF, keybuf_size, buf);
+
+ return (EFI_SUCCESS);
+}
+
+/* We don't support secure creation of keys at runtime! */
+static EFI_STATUS EFIAPI
+create_key_impl(EFI_KMS_SERVICE *This __unused,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINT16 *KeyDescriptorCount __unused,
+ EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor __unused,
+ UINTN *ClientDataSize __unused, VOID **ClientData __unused)
+{
+ return (EFI_UNSUPPORTED);
+}
+
+static EFI_STATUS
+key_size(const EFI_GUID *format, size_t *size)
+{
+ if (!memcmp(format, &Generic128Guid, sizeof(EFI_GUID))) {
+ *size = 128 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &Generic256Guid, sizeof(EFI_GUID))) {
+ *size = 256 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &Generic512Guid, sizeof(EFI_GUID))) {
+ *size = 512 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &Generic1024Guid, sizeof(EFI_GUID))) {
+ *size = 1024 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &Generic2048Guid, sizeof(EFI_GUID))) {
+ *size = 2048 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &Generic3072Guid, sizeof(EFI_GUID))) {
+ *size = 3072 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &AesXts128Guid, sizeof(EFI_GUID))) {
+ *size = 128 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &AesXts256Guid, sizeof(EFI_GUID))) {
+ *size = 256 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &AesCbc128Guid, sizeof(EFI_GUID))) {
+ *size = 128 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &AesCbc256Guid, sizeof(EFI_GUID))) {
+ *size = 256 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &RsaSha2048Guid, sizeof(EFI_GUID))) {
+ *size = 2048 / 8;
+ return (EFI_SUCCESS);
+ } else if (!memcmp(format, &RsaSha3072Guid, sizeof(EFI_GUID))) {
+ *size = 3072 / 8;
+ return (EFI_SUCCESS);
+ } else {
+ return (EFI_INVALID_PARAMETER);
+ }
+}
+
+static EFI_STATUS
+copy_key(void *dst, const void *src, const EFI_GUID *format)
+{
+ EFI_STATUS status;
+ size_t size;
+
+ status = key_size(format, &size);
+
+ if (EFI_ERROR(status)) {
+ return (status);
+ }
+
+ memcpy(dst, src, size);
+
+ return (EFI_SUCCESS);
+}
+
+static void
+get_one_key(EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor)
+{
+ EFI_STATUS status;
+ int i;
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ if (keys[i].k_id_size != 0 &&
+ keys[i].k_id_size == KeyDescriptor->KeyIdentifierSize &&
+ !memcmp(keys[i].k_id, KeyDescriptor->KeyIdentifier,
+ keys[i].k_id_size)) {
+ memcpy(&(KeyDescriptor->KeyFormat), &keys[i].k_format,
+ sizeof(EFI_GUID));
+ status = copy_key(KeyDescriptor->KeyValue,
+ keys[i].k_data, &keys[i].k_format);
+ KeyDescriptor->KeyStatus = status;
+
+ return;
+ }
+ }
+
+ KeyDescriptor->KeyStatus = EFI_NOT_FOUND;
+}
+
+static EFI_STATUS EFIAPI
+get_key_impl(EFI_KMS_SERVICE *This, EFI_KMS_CLIENT_INFO *Client,
+ UINT16 *KeyDescriptorCount, EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor,
+ UINTN *ClientDataSize __unused, VOID **ClientData __unused)
+{
+ int i;
+
+ /* Spec compliance */
+ if (This == NULL || KeyDescriptorCount == NULL ||
+ KeyDescriptor == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for(i = 0; i < *KeyDescriptorCount; i++) {
+ get_one_key(KeyDescriptor + i);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+static void
+add_one_key(EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor)
+{
+ EFI_STATUS status;
+ int i;
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ if (keys[i].k_id_size == 0) {
+ keys[i].k_id_size = KeyDescriptor->KeyIdentifierSize;
+ memcpy(keys[i].k_id, KeyDescriptor->KeyIdentifier,
+ keys[i].k_id_size);
+ memcpy(&(keys[i].k_format), &(KeyDescriptor->KeyFormat),
+ sizeof(EFI_GUID));
+ status = copy_key(keys[i].k_data,
+ KeyDescriptor->KeyValue, &(keys[i].k_format));
+ KeyDescriptor->KeyStatus = status;
+
+ return;
+ }
+ }
+
+ KeyDescriptor->KeyStatus = EFI_OUT_OF_RESOURCES;
+}
+
+static EFI_STATUS EFIAPI
+add_key_impl(EFI_KMS_SERVICE *This,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINT16 *KeyDescriptorCount,
+ EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor, UINTN *ClientDataSize __unused,
+ VOID **ClientData __unused)
+{
+ int i;
+
+ /* Spec compliance */
+ if (This == NULL || KeyDescriptorCount == NULL ||
+ KeyDescriptor == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for (i = 0; i < *KeyDescriptorCount; i++) {
+ add_one_key(KeyDescriptor + i);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+static void
+delete_one_key(EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor)
+{
+ int i;
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ if (keys[i].k_id_size != 0 &&
+ keys[i].k_id_size == KeyDescriptor->KeyIdentifierSize &&
+ !memcmp(keys[i].k_id, KeyDescriptor->KeyIdentifier,
+ keys[i].k_id_size)) {
+ memset(keys + i, 0, sizeof(key_entry_t));
+
+ return;
+ }
+ }
+
+ KeyDescriptor->KeyStatus = EFI_NOT_FOUND;
+}
+
+static EFI_STATUS EFIAPI
+delete_key_impl(EFI_KMS_SERVICE *This,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINT16 *KeyDescriptorCount,
+ EFI_KMS_KEY_DESCRIPTOR *KeyDescriptor, UINTN *ClientDataSize __unused,
+ VOID **ClientData __unused)
+{
+ int i;
+
+ /* Spec compliance */
+ if (This == NULL || KeyDescriptorCount == NULL ||
+ KeyDescriptor == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for (i = 0; i < *KeyDescriptorCount; i++) {
+ delete_one_key(KeyDescriptor + i);
+ }
+
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS EFIAPI
+get_service_status_impl(EFI_KMS_SERVICE *This __unused)
+{
+ return (EFI_SUCCESS);
+}
+
+static void
+do_get_key_attributes(key_entry_t *entry, EFI_KMS_KEY_ATTRIBUTE *KeyAttributes)
+{
+ KeyAttributes[0].KeyAttributeIdentifierType = EFI_KMS_DATA_TYPE_UTF8;
+ KeyAttributes[0].KeyAttributeIdentifierCount =
+ sizeof KEY_ATTR_SERVICE_ID_NAME;
+ KeyAttributes[0].KeyAttributeIdentifier = KEY_ATTR_SERVICE_ID_NAME;
+ KeyAttributes[0].KeyAttributeInstance = 1;
+ KeyAttributes[0].KeyAttributeType = EFI_KMS_ATTRIBUTE_TYPE_INTEGER;
+ KeyAttributes[0].KeyAttributeValueSize = sizeof(int);
+ *((int*)(KeyAttributes[0].KeyAttributeValue)) = entry->k_service;
+ KeyAttributes[0].KeyAttributeStatus = EFI_SUCCESS;
+}
+
+static EFI_STATUS EFIAPI
+get_key_attributes_impl(EFI_KMS_SERVICE *This,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINT8 *KeyIdentifierSize,
+ const VOID *KeyIdentifier, UINT16 *KeyAttributesCount,
+ EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, UINTN *ClientDataSize __unused,
+ VOID **ClientData __unused)
+{
+ UINTN i;
+
+ if (This == NULL || KeyIdentifierSize == NULL ||
+ KeyIdentifier == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if (*KeyAttributesCount < 1) {
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ if (keys[i].k_id_size != 0 &&
+ keys[i].k_id_size == *KeyIdentifierSize &&
+ !memcmp(keys[i].k_id, KeyIdentifier, *KeyIdentifierSize)) {
+ do_get_key_attributes(keys + i, KeyAttributes);
+
+ return (EFI_SUCCESS);
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+static void
+do_add_key_attributes(key_entry_t *entry, EFI_KMS_KEY_ATTRIBUTE *KeyAttribute)
+{
+ if (KeyAttribute->KeyAttributeIdentifierCount ==
+ KEY_ATTR_SERVICE_ID_NAME_LEN &&
+ !memcmp(KEY_ATTR_SERVICE_ID_NAME,
+ KeyAttribute->KeyAttributeIdentifier,
+ KEY_ATTR_SERVICE_ID_NAME_LEN)) {
+ entry->k_service = *((int*)(KeyAttribute->KeyAttributeValue));
+ KeyAttribute->KeyAttributeStatus = EFI_SUCCESS;
+ } else {
+ KeyAttribute->KeyAttributeStatus = EFI_INVALID_PARAMETER;
+ }
+}
+
+static EFI_STATUS EFIAPI
+add_key_attributes_impl(EFI_KMS_SERVICE *This,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINT8 *KeyIdentifierSize,
+ const VOID *KeyIdentifier, UINT16 *KeyAttributesCount,
+ EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, UINTN *ClientDataSize __unused,
+ VOID **ClientData __unused)
+{
+ UINTN i, j;
+
+ if (This == NULL || KeyIdentifierSize == NULL ||
+ KeyIdentifier == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ if(keys[i].k_id_size != 0 &&
+ keys[i].k_id_size == *KeyIdentifierSize &&
+ !memcmp(keys[i].k_id, KeyIdentifier, *KeyIdentifierSize)) {
+ for (j = 0; j < *KeyAttributesCount; j++) {
+ do_add_key_attributes(keys + i,
+ KeyAttributes + j);
+
+ }
+
+ return (EFI_SUCCESS);
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+static void
+do_delete_key_attributes(key_entry_t *entry,
+ EFI_KMS_KEY_ATTRIBUTE *KeyAttribute)
+{
+ if (KeyAttribute->KeyAttributeIdentifierCount ==
+ KEY_ATTR_SERVICE_ID_NAME_LEN &&
+ !memcmp(KEY_ATTR_SERVICE_ID_NAME,
+ KeyAttribute->KeyAttributeIdentifier,
+ KEY_ATTR_SERVICE_ID_NAME_LEN)) {
+ entry->k_service = SERVICE_ID_NONE;
+ KeyAttribute->KeyAttributeStatus = EFI_SUCCESS;
+ } else {
+ KeyAttribute->KeyAttributeStatus = EFI_INVALID_PARAMETER;
+ }
+}
+
+static EFI_STATUS EFIAPI
+delete_key_attributes_impl(EFI_KMS_SERVICE *This,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINT8 *KeyIdentifierSize,
+ const VOID *KeyIdentifier, UINT16 *KeyAttributesCount,
+ EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, UINTN *ClientDataSize __unused,
+ VOID **ClientData __unused)
+{
+ UINTN i, j;
+
+ if (This == NULL || KeyIdentifierSize == NULL ||
+ KeyIdentifier == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ if(keys[i].k_id_size != 0 &&
+ keys[i].k_id_size == *KeyIdentifierSize &&
+ !memcmp(keys[i].k_id, KeyIdentifier, *KeyIdentifierSize)) {
+ for (j = 0; j < *KeyAttributesCount; j++) {
+ do_delete_key_attributes(keys + i,
+ KeyAttributes + j);
+ }
+
+ return (EFI_SUCCESS);
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+static EFI_STATUS
+check_match(key_entry_t *entry, EFI_KMS_KEY_ATTRIBUTE *KeyAttribute,
+ bool *match)
+{
+ if (KeyAttribute->KeyAttributeIdentifierCount ==
+ KEY_ATTR_SERVICE_ID_NAME_LEN &&
+ !memcmp(KEY_ATTR_SERVICE_ID_NAME,
+ KeyAttribute->KeyAttributeIdentifier,
+ KEY_ATTR_SERVICE_ID_NAME_LEN)) {
+ *match = (entry->k_service ==
+ *((int*)(KeyAttribute->KeyAttributeValue)));
+
+ return (EFI_SUCCESS);
+ } else {
+ return (EFI_INVALID_PARAMETER);
+ }
+}
+
+static EFI_STATUS EFIAPI
+get_key_by_attributes_impl(EFI_KMS_SERVICE *This,
+ EFI_KMS_CLIENT_INFO *Client __unused, UINTN *KeyAttributesCount,
+ EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, UINTN *KeyDescriptorCount,
+ EFI_KMS_KEY_DESCRIPTOR *KeyDescriptors, UINTN *ClientDataSize __unused,
+ VOID **ClientData __unused)
+{
+ EFI_STATUS status;
+ UINT8 idxs[MAX_KEYS];
+ UINT8 nmatches = 0;
+ UINTN i, j;
+ bool match;
+
+ if (This == NULL || KeyAttributesCount == NULL ||
+ KeyAttributes == NULL || KeyDescriptorCount == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for (i = 0; i < MAX_KEYS; i++) {
+ match = true;
+
+ for (j = 0; j < *KeyAttributesCount && match; j++) {
+ status = check_match(keys + i, KeyAttributes + j,
+ &match);
+
+ if (EFI_ERROR(status)) {
+ return (status);
+ }
+ }
+
+ if (match) {
+ idxs[nmatches] = i;
+ nmatches++;
+ }
+ }
+
+ if (nmatches == 0) {
+ return (EFI_NOT_FOUND);
+ }
+
+ if (*KeyDescriptorCount < nmatches) {
+ *KeyDescriptorCount = nmatches;
+
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+
+ if (KeyDescriptors == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ *KeyDescriptorCount = nmatches;
+
+ for (i = 0; i < nmatches; i++) {
+ KeyDescriptors[i].KeyIdentifierSize = keys[idxs[i]].k_id_size;
+ KeyDescriptors[i].KeyIdentifier = keys[idxs[i]].k_id;
+ memcpy(&(KeyDescriptors[i].KeyFormat),
+ &(keys[idxs[i]].k_format), sizeof(EFI_GUID));
+ status = copy_key(KeyDescriptors[i].KeyValue,
+ keys[idxs[i]].k_data, &keys[idxs[i]].k_format);
+ KeyDescriptors[i].KeyStatus = status;
+ }
+
+ return (EFI_SUCCESS);
+}
+
+static void
+register_kms(void)
+{
+ EFI_STATUS status;
+ EFI_HANDLE handle = NULL;
+
+ status = BS->InstallMultipleProtocolInterfaces(&handle,
+ &EfiKmsProtocolGuid, &key_inject_kms, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Could not register kernel KMS (%lu)\n",
+ EFI_ERROR_CODE(status));
+ }
+}
+
+static void
+init(void)
+{
+ EFI_HANDLE *handles;
+ EFI_KMS_SERVICE *kms;
+ EFI_STATUS status;
+ UINTN sz;
+ u_int n, nin;
+ bool found;
+
+ /* Try and find an instance of our KMS */
+ sz = 0;
+ handles = NULL;
+ status = BS->LocateHandle(ByProtocol, &EfiKmsProtocolGuid, 0, &sz, 0);
+
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ handles = (EFI_HANDLE *)malloc(sz);
+ status = BS->LocateHandle(ByProtocol, &EfiKmsProtocolGuid,
+ 0, &sz, handles);
+
+ if (status == EFI_NOT_FOUND) {
+ /* No handles found, just register our KMS */
+ register_kms();
+
+ return;
+ } else if (EFI_ERROR(status)) {
+ printf("Could not get KMS device handles (%lu)\n",
+ EFI_ERROR_CODE(status));
+ free(handles);
+
+ return;
+ }
+ } else if (status == EFI_NOT_FOUND) {
+ register_kms();
+
+ return;
+ } else {
+ printf("Could not get KMS device handles (%lu)\n",
+ EFI_ERROR_CODE(status));
+
+ return;
+ }
+
+ nin = sz / sizeof(EFI_HANDLE);
+
+ for (n = 0; n < nin && !found; n++) {
+ status = BS->OpenProtocol(handles[n], &KernelKeyInjectorGuid,
+ (void**)&kms, IH, handles[n],
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(status)) {
+ printf("Could not open KMS service (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return;
+ }
+
+ if (!memcmp(&KernelKeyInjectorGuid, &(kms->ServiceId),
+ sizeof(EFI_GUID))) {
+ found = true;
+ }
+
+ BS->CloseProtocol(handles[n], &KernelKeyInjectorGuid,
+ IH, handles[n]);
+ }
+
+ free(handles);
+
+ if (!found) {
+ register_kms();
+ }
+}
+
+static CHAR16 kernel_inject_str[] = {
+ 'F', 'r', 'e', 'e', 'B', 'S', 'D', ' ',
+ 'K', 'e', 'r', 'n', 'e', 'l', ' ',
+ 'I', 'n', 'j', 'e', 'c', 't', 'i', 'o', 'n', ' ',
+ 'K', 'M', 'S', '\0'
+};
+
+static EFI_GUID key_formats[] = {
+ EFI_KMS_FORMAT_GENERIC_128_GUID,
+ EFI_KMS_FORMAT_GENERIC_160_GUID,
+ EFI_KMS_FORMAT_GENERIC_256_GUID,
+ EFI_KMS_FORMAT_GENERIC_512_GUID,
+ EFI_KMS_FORMAT_GENERIC_1024_GUID,
+ EFI_KMS_FORMAT_GENERIC_2048_GUID,
+ EFI_KMS_FORMAT_GENERIC_3072_GUID,
+ EFI_KMS_FORMAT_SHA256_GUID,
+ EFI_KMS_FORMAT_SHA512_GUID,
+ EFI_KMS_FORMAT_AESXTS_128_GUID,
+ EFI_KMS_FORMAT_AESXTS_256_GUID,
+ EFI_KMS_FORMAT_AESCBC_128_GUID,
+ EFI_KMS_FORMAT_AESCBC_256_GUID,
+ EFI_KMS_FORMAT_RSASHA256_2048_GUID,
+ EFI_KMS_FORMAT_RSASHA256_3072_GUID
+};
+
+
+static EFI_KMS_KEY_ATTRIBUTE key_attributes[] = {
+ [KEY_ATTR_SERVICE_ID_GELI] = {
+ .KeyAttributeIdentifierType = EFI_KMS_DATA_TYPE_UTF8,
+ .KeyAttributeIdentifierCount = KEY_ATTR_SERVICE_ID_NAME_LEN,
+ .KeyAttributeIdentifier = KEY_ATTR_SERVICE_ID_NAME,
+ .KeyAttributeInstance = 1,
+ .KeyAttributeType = EFI_KMS_ATTRIBUTE_TYPE_INTEGER,
+ .KeyAttributeValueSize = sizeof(int),
+ .KeyAttributeValue = &service_id_geli,
+ },
+ [KEY_ATTR_SERVICE_ID_PASSPHRASE] = {
+ .KeyAttributeIdentifierType = EFI_KMS_DATA_TYPE_UTF8,
+ .KeyAttributeIdentifierCount = KEY_ATTR_SERVICE_ID_NAME_LEN,
+ .KeyAttributeIdentifier = KEY_ATTR_SERVICE_ID_NAME,
+ .KeyAttributeInstance = 2,
+ .KeyAttributeType = EFI_KMS_ATTRIBUTE_TYPE_INTEGER,
+ .KeyAttributeValueSize = sizeof(int),
+ .KeyAttributeValue = &service_id_passphrase,
+ }
+};
+
+EFI_KMS_KEY_ATTRIBUTE * const key_attr_service_id_geli =
+ &(key_attributes[KEY_ATTR_SERVICE_ID_GELI]);
+
+EFI_KMS_KEY_ATTRIBUTE * const key_attr_service_id_passphrase =
+ &(key_attributes[KEY_ATTR_SERVICE_ID_PASSPHRASE]);
+
+static EFI_KMS_SERVICE key_inject_kms = {
+ .GetServiceStatus = get_service_status_impl,
+ .RegisterClient = register_client_impl,
+ .CreateKey = create_key_impl,
+ .GetKey = get_key_impl,
+ .AddKey = add_key_impl,
+ .DeleteKey = delete_key_impl,
+ .GetKeyAttributes = get_key_attributes_impl,
+ .AddKeyAttributes = add_key_attributes_impl,
+ .DeleteKeyAttributes = delete_key_attributes_impl,
+ .GetKeyByAttributes = get_key_by_attributes_impl,
+ .ProtocolVersion = EFI_KMS_PROTOCOL_VERSION,
+ .ServiceId = KERNEL_KEY_INJECTOR_GUID,
+ .ServiceName = kernel_inject_str,
+ .ServiceVersion = 1,
+ .ServiceAvailable = true,
+ .ClientIdSupported = true,
+ .ClientIdRequired = false,
+ .ClientNameStringTypes = EFI_KMS_DATA_TYPE_UTF8,
+ .ClientNameRequired = true,
+ .ClientNameMaxCount = 255,
+ .ClientDataSupported = true,
+ .ClientDataMaxSize = 0xffffffffffffffff,
+ .KeyIdVariableLenSupported = true,
+ .KeyIdMaxSize = EFI_KMS_KEY_IDENTIFIER_MAX_SIZE,
+ .KeyFormatsCount = sizeof key_formats / sizeof key_formats[0],
+ .KeyFormats = key_formats,
+ .KeyAttributesSupported = true,
+ .KeyAttributeIdStringTypes = EFI_KMS_DATA_TYPE_UTF8,
+ .KeyAttributeIdMaxCount = EFI_KMS_KEY_ATTRIBUTE_ID_MAX_SIZE,
+ .KeyAttributesCount = sizeof key_attributes / sizeof key_attributes[0],
+ .KeyAttributes = key_attributes
+};
+
+const efi_driver_t key_inject_driver =
+{
+ .name = "Key Inject KMS",
+ .init = init,
+};
Index: stand/efi/loader/bootinfo.c
===================================================================
--- stand/efi/loader/bootinfo.c
+++ stand/efi/loader/bootinfo.c
@@ -31,6 +31,7 @@
#include <stand.h>
#include <string.h>
+#include <stdbool.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/linker.h>
@@ -42,9 +43,11 @@
#include <efi.h>
#include <efilib.h>
+#include <efisec.h>
#include "bootstrap.h"
#include "loader_efi.h"
+#include "key_inject.h"
#if defined(__amd64__)
#include <machine/specialreg.h>
@@ -59,6 +62,8 @@
int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp);
extern EFI_SYSTEM_TABLE *ST;
+static EFI_GUID EfiKmsProtocolGuid = EFI_KMS_PROTOCOL;
+static EFI_GUID KernelKeyInjectorGuid = KERNEL_KEY_INJECTOR_GUID;
static const char howto_switches[] = "aCdrgDmphsv";
static int howto_masks[] = {
@@ -265,6 +270,76 @@
return (ret);
}
+static void
+key_inject_set_client(struct preloaded_file *kfp)
+{
+ EFI_KMS_CLIENT_INFO client;
+ EFI_KMS_SERVICE *kms;
+ EFI_HANDLE *handles;
+ EFI_STATUS status;
+ UINTN sz;
+ u_int n, nin;
+
+ /* Try and find a usable KMS instance */
+ sz = 0;
+ handles = NULL;
+ status = BS->LocateHandle(ByProtocol, &EfiKmsProtocolGuid, 0, &sz, 0);
+
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ handles = (EFI_HANDLE *)malloc(sz);
+ status = BS->LocateHandle(ByProtocol, &EfiKmsProtocolGuid,
+ 0, &sz, handles);
+ if (EFI_ERROR(status)) {
+ printf("Error getting handles for kernel KMS %lu\n",
+ EFI_ERROR_CODE(status));
+ free(handles);
+ }
+ } else {
+ printf("Error getting handles for kernel KMS %lu\n",
+ EFI_ERROR_CODE(status));
+ return;
+ }
+
+ nin = sz / sizeof(EFI_HANDLE);
+
+ for (n = 0; n < nin; n++) {
+ status = BS->OpenProtocol(handles[n], &EfiKmsProtocolGuid,
+ (void**)&kms, IH, handles[n],
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(status)) {
+ printf("Error getting protocol for kernel KMS %lu\n",
+ EFI_ERROR_CODE(status));
+ return;
+ }
+
+
+ if (!memcmp(&KernelKeyInjectorGuid, &(kms->ServiceId),
+ sizeof(EFI_GUID))) {
+ client.ClientIdSize = sizeof(struct preloaded_file *);
+ client.ClientId = kfp;
+ client.ClientNameType = EFI_KMS_DATA_TYPE_UTF8;
+ client.ClientNameCount = strlen(kfp->f_name);
+ client.ClientName = kfp->f_name;
+ status = kms->RegisterClient(kms, &client, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Error registering client for kernel KMS %lu\n",
+ EFI_ERROR_CODE(status));
+ }
+
+ BS->CloseProtocol(handles[n], &EfiKmsProtocolGuid,
+ IH, handles[n]);
+ free(handles);
+
+ return;
+ }
+
+ BS->CloseProtocol(handles[n], &EfiKmsProtocolGuid,
+ IH, handles[n]);
+ }
+}
+
static int
bi_load_efi_data(struct preloaded_file *kfp)
{
@@ -279,6 +354,7 @@
struct efi_map_header *efihdr;
bool do_vmap;
+ key_inject_set_client(kfp);
#if defined(__amd64__) || defined(__aarch64__)
struct efi_fb efifb;
@@ -455,7 +531,7 @@
/* Handle device tree blob */
dtbp = addr;
dtb_size = fdt_copy(addr);
-
+
/* Pad to a page boundary */
if (dtb_size)
addr += roundup(dtb_size, PAGE_SIZE);
@@ -464,8 +540,10 @@
kfp = file_findfile(NULL, "elf kernel");
if (kfp == NULL)
kfp = file_findfile(NULL, "elf64 kernel");
- if (kfp == NULL)
- panic("can't find kernel file");
+
+ if (kfp == NULL)
+ panic("can't find kernel file");
+
kernend = 0; /* fill it in later */
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
Index: stand/efi/loader/conf.c
===================================================================
--- stand/efi/loader/conf.c
+++ stand/efi/loader/conf.c
@@ -35,6 +35,13 @@
#include <libzfs.h>
#endif
+#include "efi_drivers.h"
+
+const efi_driver_t *efi_drivers[] = {
+ &key_inject_driver,
+ NULL
+};
+
struct devsw *devsw[] = {
&efipart_fddev,
&efipart_cddev,
Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -52,6 +52,7 @@
#include "efizfs.h"
#endif
+#include "efi_drivers.h"
#include "loader_efi.h"
extern char bootprog_info[];

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 9, 11:42 PM (1 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28588851
Default Alt Text
D12698.id43475.diff (43 KB)

Event Timeline