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/libefi/Makefile =================================================================== --- stand/efi/libefi/Makefile +++ stand/efi/libefi/Makefile @@ -11,7 +11,8 @@ WARNS?= 2 SRCS= delay.c devpath.c efi_console.c efichar.c efinet.c efipart.c env.c errno.c \ - handles.c wchar.c libefi.c efi_driver_utils.c efizfs.c devicename.c + handles.c wchar.c libefi.c efi_driver_utils.c efizfs.c devicename.c \ + key_inject.c efi_main.c .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" SRCS+= time.c Index: stand/efi/loader/bootinfo.c =================================================================== --- stand/efi/loader/bootinfo.c +++ stand/efi/loader/bootinfo.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -42,9 +43,11 @@ #include #include +#include #include "bootstrap.h" #include "loader_efi.h" +#include "key_inject.h" #if defined(__amd64__) #include @@ -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[] = { @@ -236,6 +241,76 @@ return(addr); } +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) { @@ -248,6 +323,7 @@ UINT32 mmver; struct efi_map_header *efihdr; + key_inject_set_client(kfp); #if defined(__amd64__) || defined(__aarch64__) struct efi_fb efifb; @@ -421,8 +497,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 #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[]; @@ -349,6 +350,11 @@ */ bcache_init(32768, 512); + for (i = 0; efi_drivers[i] != NULL; i++) { + if (efi_drivers[i]->init != NULL) + efi_drivers[i]->init(); + } + /* * Parse the args to set the console settings, etc * boot1.efi passes these in, if it can read /boot.config or /boot/config Index: sys/boot/efi/include/efisec.h =================================================================== --- /dev/null +++ sys/boot/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 + +#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: sys/boot/efi/include/key_inject.h =================================================================== --- /dev/null +++ sys/boot/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: sys/boot/efi/libefi/key_inject.c =================================================================== --- /dev/null +++ sys/boot/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 +#include +#include +#include +#include +#include +#include + +#include + +#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, +};