Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F139577514
D10512.id28259.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
118 KB
Referenced Files
None
Subscribers
None
D10512.id28259.diff
View Options
Index: sys/boot/Makefile
===================================================================
--- sys/boot/Makefile
+++ sys/boot/Makefile
@@ -9,6 +9,7 @@
.endif
SUBDIR+= common
+SUBDIR+= boot_crypto
.include <bsd.arch.inc.mk>
Index: sys/boot/boot_crypto/Makefile
===================================================================
--- /dev/null
+++ sys/boot/boot_crypto/Makefile
@@ -0,0 +1,34 @@
+# $FreeBSD$
+# libboot_crypto
+
+MAN=
+
+.include <src.opts.mk>
+MK_SSP= no
+
+LIB= boot_crypto
+INTERNALLIB=
+MK_PROFILE= no
+NO_PIC=
+
+WARNS?= 0
+
+# sha256 and sha512 from sys/crypto
+.PATH: ${.CURDIR}/../../crypto/sha2
+CFLAGS+= -DWEAK_REFS
+SRCS+= sha256c.c sha512c.c
+
+# md5 from libmd
+.PATH: ${.CURDIR}/../../../lib/libmd
+SRCS+= md5c.c
+
+# AES implementation from sys/crypto
+.PATH: ${.CURDIR}/../../crypto/rijndael
+CFLAGS+= -I${.CURDIR}/../../
+# Remove asserts
+CFLAGS+= -DNDEBUG
+SRCS+= rijndael-alg-fst.c rijndael-api-fst.c rijndael-api.c
+SRCS+= boot_crypto.c boot_crypto_aes.c
+
+.include <bsd.stand.mk>
+.include <bsd.lib.mk>
Index: sys/boot/boot_crypto/boot_crypto.h
===================================================================
--- /dev/null
+++ sys/boot/boot_crypto/boot_crypto.h
@@ -0,0 +1,187 @@
+/*-
+ * 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 _BOOT_CRYPTO_H_
+#define _BOOT_CRYPTO_H_
+
+#include "boot_crypto_types.h"
+#include "boot_crypto_aes.h"
+
+/* We want all the codes from cryptodev, but not the defs. Maybe
+ * these should be moved out to a separate file to allow them to be
+ * included separately?
+ */
+
+/* Hash values */
+#define NULL_HASH_LEN 16
+#define MD5_HASH_LEN 16
+#define SHA1_HASH_LEN 20
+#define RIPEMD160_HASH_LEN 20
+#define SHA2_256_HASH_LEN 32
+#define SHA2_384_HASH_LEN 48
+#define SHA2_512_HASH_LEN 64
+#define MD5_KPDK_HASH_LEN 16
+#define SHA1_KPDK_HASH_LEN 20
+#define AES_GMAC_HASH_LEN 16
+/* Maximum hash algorithm result length */
+#define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */
+
+/* HMAC values */
+#define NULL_HMAC_BLOCK_LEN 64
+#define MD5_HMAC_BLOCK_LEN 64
+#define SHA1_HMAC_BLOCK_LEN 64
+#define RIPEMD160_HMAC_BLOCK_LEN 64
+#define SHA2_256_HMAC_BLOCK_LEN 64
+#define SHA2_384_HMAC_BLOCK_LEN 128
+#define SHA2_512_HMAC_BLOCK_LEN 128
+/* Maximum HMAC block length */
+#define HMAC_MAX_BLOCK_LEN SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */
+#define HMAC_IPAD_VAL 0x36
+#define HMAC_OPAD_VAL 0x5C
+/* HMAC Key Length */
+#define NULL_HMAC_KEY_LEN 0
+#define MD5_HMAC_KEY_LEN 16
+#define SHA1_HMAC_KEY_LEN 20
+#define RIPEMD160_HMAC_KEY_LEN 20
+#define SHA2_256_HMAC_KEY_LEN 32
+#define SHA2_384_HMAC_KEY_LEN 48
+#define SHA2_512_HMAC_KEY_LEN 64
+#define AES_128_GMAC_KEY_LEN 16
+#define AES_192_GMAC_KEY_LEN 24
+#define AES_256_GMAC_KEY_LEN 32
+
+/* Encryption algorithm block sizes */
+#define NULL_BLOCK_LEN 4 /* IPsec to maintain alignment */
+#define DES_BLOCK_LEN 8
+#define DES3_BLOCK_LEN 8
+#define BLOWFISH_BLOCK_LEN 8
+#define SKIPJACK_BLOCK_LEN 8
+#define CAST128_BLOCK_LEN 8
+#define RIJNDAEL128_BLOCK_LEN 16
+#define AES_BLOCK_LEN 16
+#define AES_ICM_BLOCK_LEN 1
+#define ARC4_BLOCK_LEN 1
+#define CAMELLIA_BLOCK_LEN 16
+#define EALG_MAX_BLOCK_LEN AES_BLOCK_LEN /* Keep this updated */
+
+/* IV Lengths */
+
+#define ARC4_IV_LEN 1
+#define AES_GCM_IV_LEN 12
+#define AES_XTS_IV_LEN 8
+#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */
+
+/* Min and Max Encryption Key Sizes */
+#define NULL_MIN_KEY 0
+#define NULL_MAX_KEY 256 /* 2048 bits, max key */
+#define DES_MIN_KEY 8
+#define DES_MAX_KEY DES_MIN_KEY
+#define TRIPLE_DES_MIN_KEY 24
+#define TRIPLE_DES_MAX_KEY TRIPLE_DES_MIN_KEY
+#define BLOWFISH_MIN_KEY 5
+#define BLOWFISH_MAX_KEY 56 /* 448 bits, max key */
+#define CAST_MIN_KEY 5
+#define CAST_MAX_KEY 16
+#define SKIPJACK_MIN_KEY 10
+#define SKIPJACK_MAX_KEY SKIPJACK_MIN_KEY
+#define RIJNDAEL_MIN_KEY 16
+#define RIJNDAEL_MAX_KEY 32
+#define AES_MIN_KEY RIJNDAEL_MIN_KEY
+#define AES_MAX_KEY RIJNDAEL_MAX_KEY
+#define AES_XTS_MIN_KEY (2 * AES_MIN_KEY)
+#define AES_XTS_MAX_KEY (2 * AES_MAX_KEY)
+#define ARC4_MIN_KEY 1
+#define ARC4_MAX_KEY 32
+#define CAMELLIA_MIN_KEY 8
+#define CAMELLIA_MAX_KEY 32
+
+/* Maximum hash algorithm result length */
+#define AALG_MAX_RESULT_LEN 64 /* Keep this updated */
+
+#define CRYPTO_ALGORITHM_MIN 1
+#define CRYPTO_DES_CBC 1
+#define CRYPTO_3DES_CBC 2
+#define CRYPTO_BLF_CBC 3
+#define CRYPTO_CAST_CBC 4
+#define CRYPTO_SKIPJACK_CBC 5
+#define CRYPTO_MD5_HMAC 6
+#define CRYPTO_SHA1_HMAC 7
+#define CRYPTO_RIPEMD160_HMAC 8
+#define CRYPTO_MD5_KPDK 9
+#define CRYPTO_SHA1_KPDK 10
+#define CRYPTO_RIJNDAEL128_CBC 11 /* 128 bit blocksize */
+#define CRYPTO_AES_CBC 11 /* 128 bit blocksize -- the same as above */
+#define CRYPTO_ARC4 12
+#define CRYPTO_MD5 13
+#define CRYPTO_SHA1 14
+#define CRYPTO_NULL_HMAC 15
+#define CRYPTO_NULL_CBC 16
+#define CRYPTO_DEFLATE_COMP 17 /* Deflate compression algorithm */
+#define CRYPTO_SHA2_256_HMAC 18
+#define CRYPTO_SHA2_384_HMAC 19
+#define CRYPTO_SHA2_512_HMAC 20
+#define CRYPTO_CAMELLIA_CBC 21
+#define CRYPTO_AES_XTS 22
+#define CRYPTO_AES_ICM 23 /* commonly known as CTR mode */
+#define CRYPTO_AES_NIST_GMAC 24 /* cipher side */
+#define CRYPTO_AES_NIST_GCM_16 25 /* 16 byte ICV */
+#define CRYPTO_AES_128_NIST_GMAC 26 /* auth side */
+#define CRYPTO_AES_192_NIST_GMAC 27 /* auth side */
+#define CRYPTO_AES_256_NIST_GMAC 28 /* auth side */
+#define CRYPTO_ALGORITHM_MAX 28 /* Keep updated - see below */
+
+#define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \
+ (x) <= CRYPTO_ALGORITHM_MAX)
+
+/* Algorithm flags */
+#define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */
+#define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */
+#define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */
+
+struct symmetric_alg_t {
+ int (*ctxinit)(symmetric_alg_ctx_t *ctx, int enc, const u_char *key,
+ size_t keylen, u_char *iv);
+ int (*encrypt)(symmetric_alg_ctx_t *ctx, u_char *data, size_t len);
+ int (*decrypt)(symmetric_alg_ctx_t *ctx, u_char *data, size_t len);
+};
+
+union symmetric_alg_ctx_t {
+ struct aes_xts_ctx aes_xts;
+ struct aes_cbc_ctx aes_cbc;
+};
+
+/* Initalize a key and decrypt data */
+extern int decrypt_symmetric(const symmetric_alg_t *alg, u_char *data,
+ size_t datalen, const u_char *key, size_t keylen,
+ u_char *iv);
+extern int encrypt_symmetric(const symmetric_alg_t *alg, u_char *data,
+ size_t datalen, const u_char *key, size_t keylen,
+ u_char *iv);
+extern const symmetric_alg_t* get_symmetric_alg(int alg);
+
+#endif
Index: sys/boot/boot_crypto/boot_crypto.c
===================================================================
--- /dev/null
+++ sys/boot/boot_crypto/boot_crypto.c
@@ -0,0 +1,71 @@
+/*-
+ * 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 <stddef.h>
+#include <string.h>
+
+#include "boot_crypto.h"
+#include "boot_crypto_aes.h"
+
+int decrypt_symmetric(const symmetric_alg_t *alg, u_char *data, size_t datalen,
+ const u_char *key, size_t keylen, u_char *iv)
+{
+ symmetric_alg_ctx_t ctx;
+ int res;
+
+ res = alg->ctxinit(&ctx, 0, key, keylen, iv);
+
+ if(0 != res) {
+ return (res);
+ } else {
+ return alg->decrypt(&ctx, data, datalen);
+ }
+}
+
+int encrypt_symmetric(const symmetric_alg_t *alg, u_char *data, size_t datalen,
+ const u_char *key, size_t keylen, u_char *iv)
+{
+ symmetric_alg_ctx_t ctx;
+ int res;
+
+ res = alg->ctxinit(&ctx, 1, key, keylen, iv);
+
+ if(0 != res) {
+ return (res);
+ } else {
+ return alg->encrypt(&ctx, data, datalen);
+ }
+}
+
+const symmetric_alg_t* get_symmetric_alg(int alg) {
+ switch(alg) {
+ case CRYPTO_AES_XTS: return &alg_aes_xts;
+ case CRYPTO_AES_CBC: return &alg_aes_cbc;
+ default: return NULL;
+ }
+}
Index: sys/boot/boot_crypto/boot_crypto_aes.h
===================================================================
--- /dev/null
+++ sys/boot/boot_crypto/boot_crypto_aes.h
@@ -0,0 +1,54 @@
+/*-
+ * 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 _BOOT_CRYPTO_AES_H_
+#define _BOOT_CRYPTO_AES_H_
+
+#include "boot_crypto_types.h"
+
+#include <crypto/rijndael/rijndael-api-fst.h>
+
+#define AES_XTS_BLOCKSIZE 16
+#define AES_XTS_IVSIZE 8
+#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */
+
+struct aes_xts_ctx {
+ rijndael_ctx key1;
+ rijndael_ctx key2;
+ u_int8_t tweak[AES_XTS_BLOCKSIZE];
+};
+
+struct aes_cbc_ctx {
+ keyInstance aeskey;
+ cipherInstance cipher;
+};
+
+extern const symmetric_alg_t alg_aes_cbc;
+extern const symmetric_alg_t alg_aes_xts;
+
+#endif
Index: sys/boot/boot_crypto/boot_crypto_aes.c
===================================================================
--- /dev/null
+++ sys/boot/boot_crypto/boot_crypto_aes.c
@@ -0,0 +1,203 @@
+/*-
+ * 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 <stddef.h>
+#include <string.h>
+
+#include "boot_crypto.h"
+#include "boot_crypto_aes.h"
+
+static int
+aes_xts_ctxinit(symmetric_alg_ctx_t *ptr, int enc __unused,
+ const u_char *key, size_t keylen, u_char *iv)
+{
+ struct aes_xts_ctx *ctx = &ptr->aes_xts;
+ u_int64_t blocknum;
+ size_t xts_len = keylen << 1;
+ u_int i;
+
+ rijndael_set_key(&(ctx->key1), key, xts_len / 2);
+ rijndael_set_key(&(ctx->key2), key + (xts_len / 16), xts_len / 2);
+ /*
+ * Prepare tweak as E_k2(IV). IV is specified as LE representation
+ * of a 64-bit block number which we allow to be passed in directly.
+ */
+ bcopy(iv, &blocknum, AES_XTS_IVSIZE);
+ for (i = 0; i < AES_XTS_IVSIZE; i++) {
+ ctx->tweak[i] = blocknum & 0xff;
+ blocknum >>= 8;
+ }
+ /* Last 64 bits of IV are always zero */
+ bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE);
+ rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak);
+
+ return (0);
+}
+
+static int
+aes_xts_decrypt_block(symmetric_alg_ctx_t *ptr, u_char *data)
+{
+ struct aes_xts_ctx *ctx = &ptr->aes_xts;
+ u_int8_t block[AES_XTS_BLOCKSIZE];
+ u_int i, carry_in, carry_out;
+
+ for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
+ block[i] = data[i] ^ ctx->tweak[i];
+
+ rijndael_decrypt(&ctx->key1, block, data);
+
+ for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
+ data[i] ^= ctx->tweak[i];
+
+ /* Exponentiate tweak */
+ carry_in = 0;
+ for (i = 0; i < AES_XTS_BLOCKSIZE; i++) {
+ carry_out = ctx->tweak[i] & 0x80;
+ ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0);
+ carry_in = carry_out;
+ }
+ if (carry_in)
+ ctx->tweak[0] ^= AES_XTS_ALPHA;
+ bzero(block, sizeof(block));
+
+ return (0);
+}
+
+static int
+aes_xts_decrypt(symmetric_alg_ctx_t *ctx, u_char *data, size_t len)
+{
+ u_int i;
+
+ for (i = 0; i < len; i += AES_XTS_BLOCKSIZE) {
+ aes_xts_decrypt_block(ctx, data + i);
+ }
+}
+
+static int
+aes_xts_encrypt_block(symmetric_alg_ctx_t *ptr, u_char *data)
+{
+ struct aes_xts_ctx *ctx = &ptr->aes_xts;
+ u_int8_t block[AES_XTS_BLOCKSIZE];
+ u_int i, carry_in, carry_out;
+
+ for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
+ block[i] = data[i] ^ ctx->tweak[i];
+
+ rijndael_encrypt(&ctx->key1, block, data);
+
+ for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
+ data[i] ^= ctx->tweak[i];
+
+ /* Exponentiate tweak */
+ carry_in = 0;
+ for (i = 0; i < AES_XTS_BLOCKSIZE; i++) {
+ carry_out = ctx->tweak[i] & 0x80;
+ ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0);
+ carry_in = carry_out;
+ }
+ if (carry_in)
+ ctx->tweak[0] ^= AES_XTS_ALPHA;
+ bzero(block, sizeof(block));
+
+ return (0);
+}
+
+static int
+aes_xts_encrypt(symmetric_alg_ctx_t *ctx, u_char *data, size_t len)
+{
+ u_int i;
+
+ for (i = 0; i < len; i += AES_XTS_BLOCKSIZE) {
+ aes_xts_encrypt_block(ctx, data + i);
+ }
+}
+
+static int
+aes_cbc_ctxinit(symmetric_alg_ctx_t *ptr, int enc, const u_char *key,
+ size_t keylen, u_char *iv)
+{
+ struct aes_cbc_ctx *ctx = &ptr->aes_cbc;
+ int err;
+
+ err = rijndael_makeKey(&ctx->aeskey, !enc, keylen,
+ (const char *)key);
+ if (err < 0) {
+ return (err);
+ }
+
+ err = rijndael_cipherInit(&ctx->cipher, MODE_CBC, iv);
+ if (err < 0) {
+ return (err);
+ }
+
+ return (0);
+}
+
+static int
+aes_cbc_decrypt(symmetric_alg_ctx_t *ptr, u_char *data, size_t len)
+{
+ struct aes_cbc_ctx *ctx = &ptr->aes_cbc;
+ int blks;
+
+ blks = rijndael_blockDecrypt(&ctx->cipher, &ctx->aeskey, data,
+ len * 8, data);
+
+ if (len != (blks / 8)) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+static int
+aes_cbc_encrypt(symmetric_alg_ctx_t *ptr, u_char *data, size_t len)
+{
+ struct aes_cbc_ctx *ctx = &ptr->aes_cbc;
+ int blks;
+
+ blks = rijndael_blockEncrypt(&ctx->cipher, &ctx->aeskey, data,
+ len * 8, data);
+
+ if (len != (blks / 8)) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
+const symmetric_alg_t alg_aes_xts = {
+ .ctxinit = aes_xts_ctxinit,
+ .decrypt = aes_xts_decrypt,
+ .encrypt = aes_xts_encrypt
+};
+
+const symmetric_alg_t alg_aes_cbc = {
+ .ctxinit = aes_cbc_ctxinit,
+ .decrypt = aes_cbc_decrypt,
+ .encrypt = aes_cbc_encrypt
+};
Index: sys/boot/boot_crypto/boot_crypto_types.h
===================================================================
--- /dev/null
+++ sys/boot/boot_crypto/boot_crypto_types.h
@@ -0,0 +1,37 @@
+/*-
+ * 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 _BOOT_CRYPTO_TYPES_H_
+#define _BOOT_CRYPTO_TYPES_H_
+
+#include <sys/types.h>
+
+typedef struct symmetric_alg_t symmetric_alg_t;
+typedef union symmetric_alg_ctx_t symmetric_alg_ctx_t;
+
+#endif
Index: sys/boot/efi/boot1/Makefile
===================================================================
--- sys/boot/efi/boot1/Makefile
+++ sys/boot/efi/boot1/Makefile
@@ -13,6 +13,9 @@
# Include bcache code.
HAVE_BCACHE= yes
+# Include bcache code.
+HAVE_BCACHE= yes
+
.if ${MK_ZFS} != "no"
# Disable warnings that are currently incompatible with the zfs boot code
CWARNFLAGS.boot1.c += -Wno-missing-variable-declarations
@@ -61,6 +64,7 @@
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
+CFLAGS+= -I${.CURDIR}/../../boot_crypto
CFLAGS+= -DEFI_UFS_BOOT
.ifdef(EFI_DEBUG)
CFLAGS+= -DEFI_DEBUG
@@ -104,13 +108,15 @@
LDFLAGS+= -Wl,-znocombreloc
.endif
+LIBBOOT_CRYPTO= ${.OBJDIR}/../../boot_crypto/libboot_crypto.a
+
#
# Add libstand for the runtime functions used by the compiler - for example
# __aeabi_* (arm) or __divdi3 (i386).
# as well as required string and memory functions for all platforms.
#
-DPADD+= ${LIBEFI} ${LIBSTAND}
-LDADD+= ${LIBEFI} ${LIBSTAND}
+DPADD+= ${LIBEFI} ${LIBSTAND} ${LIBBOOT_CRYPTO}
+LDADD+= ${LIBEFI} ${LIBSTAND} ${LIBBOOT_CRYPTO}
DPADD+= ${LDSCRIPT}
Index: sys/boot/efi/boot1/boot1.c
===================================================================
--- sys/boot/efi/boot1/boot1.c
+++ sys/boot/efi/boot1/boot1.c
@@ -53,7 +53,9 @@
struct arch_switch archsw; /* MI/MD interface boundary */
-static const efi_driver_t *efi_drivers[] = {
+const efi_driver_t *efi_drivers[] = {
+ &key_inject_driver,
+ &geli_driver,
NULL
};
@@ -482,7 +484,6 @@
currdev.pool_guid = pool_guid;
currdev.root_guid = 0;
devname = efi_fmtdev(&currdev);
-
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
env_nounset);
@@ -506,7 +507,6 @@
currdev.d_slice = -1;
currdev.d_partition = -1;
devname = efi_fmtdev(&currdev);
-
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
env_nounset);
@@ -523,7 +523,6 @@
currdev.d_slice = pp->pd_unit;
currdev.d_partition = 255;
devname = efi_fmtdev(&currdev);
-
env_setenv("currdev", EV_VOLATILE, devname,
efi_setcurrdev, env_nounset);
@@ -621,14 +620,12 @@
currdev.pool_guid = zi->zi_pool_guid;
currdev.root_guid = 0;
devname = efi_fmtdev(&currdev);
-
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
env_nounset);
if (probe_fs(filepath) == 0 &&
do_load(filepath, bufp, bufsize) == EFI_SUCCESS) {
*handlep = zi->zi_handle;
- printf("Succeeded\n");
return (0);
}
@@ -647,7 +644,6 @@
currdev.d_slice = -1;
currdev.d_partition = -1;
devname = efi_fmtdev(&currdev);
-
env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
env_nounset);
@@ -661,7 +657,7 @@
/* Assuming GPT partitioning. */
STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
currdev.d_slice = pp->pd_unit;
- currdev.d_partition = 255;
+ currdev.d_partition = -1;
devname = efi_fmtdev(&currdev);
env_setenv("currdev", EV_VOLATILE, devname,
@@ -894,19 +890,16 @@
archsw.arch_readin = efi_readin;
printf(" Loader path: %s\n\n", PATH_LOADER_EFI);
- printf(" Initializing modules:");
-
- bcache_init(32768, 512);
for (i = 0; efi_drivers[i] != NULL; i++) {
- printf(" %s", efi_drivers[i]->name);
if (efi_drivers[i]->init != NULL)
efi_drivers[i]->init();
}
+ printf("Probing devices:");
for (i = 0; devsw[i] != NULL; i++) {
+ printf(" %s", devsw[i]->dv_name);
if (devsw[i]->dv_init != NULL) {
- printf(" %s", devsw[i]->dv_name);
(devsw[i]->dv_init)();
}
}
Index: sys/boot/efi/include/efi_drivers.h
===================================================================
--- sys/boot/efi/include/efi_drivers.h
+++ sys/boot/efi/include/efi_drivers.h
@@ -36,10 +36,12 @@
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;
+extern const efi_driver_t geli_driver;
#endif
Index: sys/boot/efi/include/efilib.h
===================================================================
--- sys/boot/efi/include/efilib.h
+++ sys/boot/efi/include/efilib.h
@@ -30,6 +30,9 @@
#ifndef _LOADER_EFILIB_H
#define _LOADER_EFILIB_H
+#define FREEBSD_GELI_GUID { 0x516e7cbc, 0x6ecf, 0x11d6, \
+ {0x8f, 0xf8, 0x00, 0x02, 0x2d, 0x09, 0x71, 0x2b } }
+
#include <stand.h>
#include <sys/queue.h>
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 <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: 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/Makefile
===================================================================
--- sys/boot/efi/libefi/Makefile
+++ sys/boot/efi/libefi/Makefile
@@ -12,7 +12,8 @@
WARNS?= 2
SRCS= delay.c devpath.c efi_console.c efinet.c efipart.c env.c errno.c \
- handles.c wchar.c libefi.c efizfs.c devicename.c
+ handles.c wchar.c libefi.c efizfs.c devicename.c key_inject.c \
+ geli_driver.c
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
SRCS+= time.c
@@ -20,6 +21,10 @@
SRCS+= time_event.c
.endif
+.PATH: ${.CURDIR}/../../../geom/eli
+CFLAGS+= -D_STAND
+SRCS+= g_eli_hmac.c g_eli_key.c g_eli_key_cache.c pkcs5v2.c
+
# We implement a slightly non-standard %S in that it always takes a
# CHAR16 that's common in UEFI-land instead of a wchar_t. This only
# seems to matter on arm64 where wchar_t defaults to an int instead
@@ -45,6 +50,9 @@
CFLAGS+= -DEFI_ZFS_BOOT
.endif
+CFLAGS+= -I${.CURDIR}/../../boot_crypto
+CFLAGS+= -I${.CURDIR}/../../..
+
# Pick up the bootstrap header for some interface items
CFLAGS+= -I${.CURDIR}/../../common
@@ -56,4 +64,12 @@
CFLAGS+= -DTERM_EMU
.endif
+beforedepend ${OBJS}: machine
+
+CLEANFILES+= machine
+
+machine: .NOMETA
+ ln -sf ${.CURDIR}/../../../${MACHINE}/include machine
+
+
.include <bsd.lib.mk>
Index: sys/boot/efi/libefi/efipart.c
===================================================================
--- sys/boot/efi/libefi/efipart.c
+++ sys/boot/efi/libefi/efipart.c
@@ -42,6 +42,7 @@
#include <disk.h>
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
+static EFI_GUID FreeBSDGELIGUID = FREEBSD_GELI_GUID;
static int efipart_initfd(void);
static int efipart_initcd(void);
@@ -351,23 +352,80 @@
return (0);
}
+static size_t
+wcslen(const CHAR16 *s)
+{
+ size_t len;
+
+ for(len = 0; s[len] != '\0'; len++);
+
+ return len;
+}
+
+static void
+efifs_dev_print(EFI_DEVICE_PATH *devpath)
+{
+ CHAR16 *name16;
+
+ name16 = efi_devpath_name(devpath);
+ char buf[wcslen(name16) + 1];
+ memset(buf, 0, sizeof buf);
+ cpy16to8(name16, buf, wcslen(name16));
+ printf("%s\n", buf);
+}
+
static int
efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
{
- EFI_DEVICE_PATH *disk_devpath, *part_devpath;
+ EFI_DEVICE_PATH *disk_devpath, *part_devpath, *trimpath, *lastnode;
+ VENDOR_DEVICE_PATH *vendornode;
HARDDRIVE_DEVICE_PATH *node;
int unit;
- pdinfo_t *hd, *pd, *last;
+ pdinfo_t *hd, *pd, *pp, *last;
disk_devpath = efi_lookup_devpath(disk_handle);
part_devpath = efi_lookup_devpath(part_handle);
+
if (disk_devpath == NULL || part_devpath == NULL) {
return (ENOENT);
}
- node = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(part_devpath);
+
+ /* Get the disk partition node */
+ lastnode = efi_devpath_last_node(part_devpath);
if (node == NULL)
return (ENOENT); /* This should not happen. */
+ if (DevicePathType(lastnode) == MEDIA_DEVICE_PATH) {
+ if (DevicePathSubType(lastnode) == MEDIA_VENDOR_DP) {
+ vendornode = (VENDOR_DEVICE_PATH *)lastnode;
+
+ /* We only want GELI partitions */
+ if (memcmp(&(vendornode->Guid), &FreeBSDGELIGUID,
+ sizeof(EFI_GUID))) {
+ return (EINVAL);
+ }
+
+ /* Trim off the vendor node */
+ trimpath = efi_devpath_trim(part_devpath);
+
+ if (trimpath == NULL)
+ return (ENOENT);
+
+ lastnode = efi_devpath_last_node(trimpath);
+
+ if (lastnode == NULL)
+ return (ENOENT);
+
+ node = (HARDDRIVE_DEVICE_PATH *)lastnode;
+ } else if (DevicePathSubType(lastnode) == MEDIA_HARDDRIVE_DP) {
+ node = (HARDDRIVE_DEVICE_PATH *)lastnode;
+ }
+ else
+ return (EINVAL);
+ } else {
+ return (EINVAL);
+ }
+
pd = malloc(sizeof(pdinfo_t));
if (pd == NULL) {
printf("Failed to add disk, out of memory\n");
@@ -378,6 +436,53 @@
STAILQ_FOREACH(hd, &hdinfo, pd_link) {
if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) {
+ /* Check if there's a related device entry
+ * already here.
+ */
+ STAILQ_FOREACH(pp, &hd->pd_part, pd_link) {
+ /* If the new device is a subpath of
+ * an existing device, then the
+ * existing entry subsumes the new
+ * one.
+ */
+ trimpath = efi_devpath_trim(pp->pd_devpath);
+
+ if (trimpath == NULL)
+ return (ENOMEM);
+
+ if (efi_devpath_match(trimpath,
+ part_devpath) != 0) {
+ free(trimpath);
+ free(pd);
+ return (EBUSY);
+ }
+
+ /* If the existing device path is a
+ * subpath of the new one, then the
+ * new entry subsumes the existing
+ * one.
+ */
+ free(trimpath);
+
+ trimpath = efi_devpath_trim(part_devpath);
+
+ if (trimpath == NULL)
+ return (ENOMEM);
+
+ if (efi_devpath_match(trimpath,
+ pp->pd_devpath) != 0) {
+ printf("Replaced device handle %p with %p\n",
+ pp->pd_handle, part_handle);
+ pp->pd_handle = part_handle;
+ pp->pd_devpath = part_devpath;
+ free(trimpath);
+ free(pd);
+ return (0);
+ }
+ free(trimpath);
+
+ }
+
/* Add the partition. */
pd->pd_handle = part_handle;
pd->pd_unit = node->PartitionNumber;
@@ -514,7 +619,6 @@
devpath = efi_lookup_devpath(efipart_handles[i]);
if (devpath == NULL)
continue;
-
if ((node = efi_devpath_last_node(devpath)) == NULL)
continue;
if (efipart_floppy(node) != NULL)
@@ -525,21 +629,47 @@
if (EFI_ERROR(status))
continue;
+ /* Handle GELI volumes */
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_VENDOR_DP) {
+ VENDOR_DEVICE_PATH *vendornode;
+
+ vendornode = (VENDOR_DEVICE_PATH *)node;
+
+ /* We only want GELI partitions */
+ if (memcmp(&(vendornode->Guid), &FreeBSDGELIGUID,
+ sizeof(EFI_GUID))) {
+ continue;
+ }
+
+ /* Trim off the vendor node */
+ devpathcpy = efi_devpath_trim(devpath);
+ if (devpathcpy == NULL)
+ continue;
+ if ((node = efi_devpath_last_node(devpathcpy)) == NULL)
+ continue;
+
+ devpath = devpathcpy;
+ }
+
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) {
devpathcpy = efi_devpath_trim(devpath);
if (devpathcpy == NULL)
continue;
+
tmpdevpath = devpathcpy;
status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
&handle);
free(devpathcpy);
if (EFI_ERROR(status))
continue;
+
/*
* We do not support nested partitions.
*/
devpathcpy = efi_lookup_devpath(handle);
+
if (devpathcpy == NULL)
continue;
if ((node = efi_devpath_last_node(devpathcpy)) == NULL)
@@ -547,6 +677,7 @@
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
DevicePathSubType(node) == MEDIA_HARDDRIVE_DP)
continue;
+
efipart_hdinfo_add(handle, efipart_handles[i]);
continue;
}
@@ -633,18 +764,6 @@
pd_dev.d_slice = -1;
pd_dev.d_partition = -1;
pd_dev.d_opendata = blkio;
- ret = disk_open(&pd_dev, blkio->Media->BlockSize *
- (blkio->Media->LastBlock + 1),
- blkio->Media->BlockSize);
- if (ret == 0) {
- ret = disk_print(&pd_dev, line, verbose);
- disk_close(&pd_dev);
- if (ret != 0)
- return (ret);
- } else {
- /* Do not fail from disk_open() */
- ret = 0;
- }
} else {
if ((ret = pager_output("\n")) != 0)
break;
@@ -674,8 +793,8 @@
pdinfo_list_t *
efiblk_get_pdinfo_list(struct devsw *dev)
{
- if (dev->dv_type == DEVT_DISK)
- return (&hdinfo);
+ if (dev->dv_type == DEVT_DISK)
+ return (&hdinfo);
if (dev->dv_type == DEVT_CD)
return (&cdinfo);
if (dev->dv_type == DEVT_FD)
@@ -684,49 +803,73 @@
}
static int
+efipart_lookupdev(struct disk_devdesc *dev, pdinfo_t **pp)
+{
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd;
+
+ if (dev == NULL) {
+ return (EINVAL);
+ }
+
+ pdi = efiblk_get_pdinfo_list(dev->d_dev);
+ if (pdi == NULL) {
+ return (EINVAL);
+ }
+
+ pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+ if (pd == NULL) {
+ return (EIO);
+ }
+
+ /* If we're looking up a specific partition, get the
+ * IO interface from that devide handle.
+ */
+ if (dev->d_slice != -1) {
+ pd = efiblk_get_pdinfo(&pd->pd_part, dev->d_slice);
+ }
+
+ *pp = pd;
+
+ return (0);
+}
+
+static int
efipart_open(struct open_file *f, ...)
{
va_list args;
struct disk_devdesc *dev;
- pdinfo_list_t *pdi;
pdinfo_t *pd;
EFI_BLOCK_IO *blkio;
EFI_STATUS status;
+ int err;
va_start(args, f);
dev = va_arg(args, struct disk_devdesc*);
va_end(args);
- if (dev == NULL)
- return (EINVAL);
- pdi = efiblk_get_pdinfo_list(dev->d_dev);
- if (pdi == NULL)
- return (EINVAL);
-
- pd = efiblk_get_pdinfo(pdi, dev->d_unit);
- if (pd == NULL)
- return (EIO);
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
if (pd->pd_blkio == NULL) {
- status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
- (void **)&pd->pd_blkio);
- if (EFI_ERROR(status))
- return (efi_status_to_errno(status));
+ status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
+ (void **)&pd->pd_blkio);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
}
blkio = pd->pd_blkio;
- if (!blkio->Media->MediaPresent)
+ if (!blkio->Media->MediaPresent) {
return (EAGAIN);
+ }
pd->pd_open++;
if (pd->pd_bcache == NULL)
pd->pd_bcache = bcache_allocate();
- if (dev->d_dev->dv_type == DEVT_DISK) {
- return (disk_open(dev,
- blkio->Media->BlockSize * (blkio->Media->LastBlock + 1),
- blkio->Media->BlockSize));
- }
+ dev->d_offset = 0;
+
return (0);
}
@@ -734,28 +877,20 @@
efipart_close(struct open_file *f)
{
struct disk_devdesc *dev;
- pdinfo_list_t *pdi;
pdinfo_t *pd;
+ int err;
dev = (struct disk_devdesc *)(f->f_devdata);
- if (dev == NULL)
- return (EINVAL);
- pdi = efiblk_get_pdinfo_list(dev->d_dev);
- if (pdi == NULL)
- return (EINVAL);
-
- pd = efiblk_get_pdinfo(pdi, dev->d_unit);
- if (pd == NULL)
- return (EINVAL);
-
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
pd->pd_open--;
if (pd->pd_open == 0) {
pd->pd_blkio = NULL;
bcache_free(pd->pd_bcache);
pd->pd_bcache = NULL;
}
- if (dev->d_dev->dv_type == DEVT_DISK)
- return (disk_close(dev));
+
return (0);
}
@@ -763,26 +898,13 @@
efipart_ioctl(struct open_file *f, u_long cmd, void *data)
{
struct disk_devdesc *dev;
- pdinfo_list_t *pdi;
pdinfo_t *pd;
- int rc;
+ int err;
dev = (struct disk_devdesc *)(f->f_devdata);
- if (dev == NULL)
- return (EINVAL);
- pdi = efiblk_get_pdinfo_list(dev->d_dev);
- if (pdi == NULL)
- return (EINVAL);
-
- pd = efiblk_get_pdinfo(pdi, dev->d_unit);
- if (pd == NULL)
- return (EINVAL);
-
- if (dev->d_dev->dv_type == DEVT_DISK) {
- rc = disk_ioctl(dev, cmd, data);
- if (rc != ENOTTY)
- return (rc);
- }
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
switch (cmd) {
case DIOCGSECTORSIZE:
@@ -847,20 +969,13 @@
{
struct bcache_devdata bcd;
struct disk_devdesc *dev;
- pdinfo_list_t *pdi;
pdinfo_t *pd;
+ int err;
dev = (struct disk_devdesc *)devdata;
- if (dev == NULL)
- return (EINVAL);
- pdi = efiblk_get_pdinfo_list(dev->d_dev);
- if (pdi == NULL)
- return (EINVAL);
-
- pd = efiblk_get_pdinfo(pdi, dev->d_unit);
- if (pd == NULL)
- return (EINVAL);
-
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
if (pd->pd_blkio->Media->RemovableMedia &&
!pd->pd_blkio->Media->MediaPresent)
return (EIO);
@@ -881,7 +996,6 @@
char *buf, size_t *rsize)
{
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
- pdinfo_list_t *pdi;
pdinfo_t *pd;
EFI_BLOCK_IO *blkio;
uint64_t off, disk_blocks, d_offset = 0;
@@ -889,16 +1003,12 @@
size_t blkoff, blksz;
int error;
- if (dev == NULL || blk < 0)
- return (EINVAL);
-
- pdi = efiblk_get_pdinfo_list(dev->d_dev);
- if (pdi == NULL)
+ if (blk < 0)
return (EINVAL);
- pd = efiblk_get_pdinfo(pdi, dev->d_unit);
- if (pd == NULL)
- return (EINVAL);
+ if ((error = efipart_lookupdev(dev, &pd)) != 0) {
+ return (error);
+ }
blkio = pd->pd_blkio;
if (blkio == NULL)
@@ -908,20 +1018,7 @@
return (EIO);
off = blk * 512;
- /*
- * Get disk blocks, this value is either for whole disk or for
- * partition.
- */
- disk_blocks = 0;
- if (dev->d_dev->dv_type == DEVT_DISK) {
- if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
- /* DIOCGMEDIASIZE does return bytes. */
- disk_blocks /= blkio->Media->BlockSize;
- }
- d_offset = dev->d_offset;
- }
- if (disk_blocks == 0)
- disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
+ disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
/* make sure we don't read past disk end */
if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) {
Index: sys/boot/efi/libefi/geli_driver.c
===================================================================
--- /dev/null
+++ sys/boot/efi/libefi/geli_driver.c
@@ -0,0 +1,1029 @@
+/*-
+ * Copyright (c) 2017 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>
+#include <efilib.h>
+#include <efiprot.h>
+#include <efisec.h>
+#include <sys/endian.h>
+#include <sys/gpt.h>
+#include <stand.h>
+#include <stdbool.h>
+#include <crypto/intake.h>
+
+#include "boot_crypto.h"
+#include "efi_drivers.h"
+#include "key_inject.h"
+
+#define _STRING_H_
+#define _STRINGS_H_
+#define _STDIO_H_
+#include <geom/eli/g_eli.h>
+#include <geom/eli/pkcs5v2.h>
+
+#define MAXPWLEN 256
+
+typedef struct {
+ struct g_eli_metadata md;
+ struct g_eli_softc sc;
+ EFI_DISK_IO *diskio;
+ EFI_BLOCK_IO *blkio;
+ EFI_HANDLE dev;
+} geli_info_t;
+
+static EFI_GUID DiskIOProtocolGUID = DISK_IO_PROTOCOL;
+static EFI_GUID BlockIOProtocolGUID = BLOCK_IO_PROTOCOL;
+static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
+static EFI_GUID DriverBindingProtocolGUID = DRIVER_BINDING_PROTOCOL;
+static EFI_GUID EfiKmsProtocolGuid = EFI_KMS_PROTOCOL;
+static EFI_GUID KernelKeyInjectorGuid = KERNEL_KEY_INJECTOR_GUID;
+static EFI_GUID Generic512Guid = EFI_KMS_FORMAT_GENERIC_512_GUID;
+static EFI_GUID Generic2048Guid = EFI_KMS_FORMAT_GENERIC_2048_GUID;
+static EFI_GUID FreeBSDGELIGUID = FREEBSD_GELI_GUID;
+static EFI_DRIVER_BINDING geli_efi_driver;
+static EFI_KMS_SERVICE *kms;
+
+
+int
+geliboot_crypt(u_int algid, int enc, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize, u_char *iv)
+{
+ const symmetric_alg_t* alg;
+
+ alg = get_symmetric_alg(algid);
+
+ if (alg == NULL) {
+ printf("Unsupported crypto algorithm #%d\n", algid);
+ return (1);
+ }
+
+ if(enc) {
+ return encrypt_symmetric(alg, data, datasize, key, keysize, iv);
+ } else {
+ return decrypt_symmetric(alg, data, datasize, key, keysize, iv);
+ }
+}
+
+static int
+g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize)
+{
+ u_char iv[keysize];
+
+ bzero(iv, sizeof(iv));
+ return (geliboot_crypt(algo, enc, data, datasize, key, keysize, iv));
+}
+
+int
+g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize)
+{
+
+ /* We prefer AES-CBC for metadata protection. */
+ if (algo == CRYPTO_AES_XTS)
+ algo = CRYPTO_AES_CBC;
+
+ return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize));
+}
+
+int
+g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize)
+{
+
+ /* We prefer AES-CBC for metadata protection. */
+ if (algo == CRYPTO_AES_XTS)
+ algo = CRYPTO_AES_CBC;
+
+ return (g_eli_crypto_cipher(algo, 0, data, datasize, key, keysize));
+}
+
+static void
+pwgets(char *buf, int n)
+{
+ int c;
+ char *lp;
+
+ for (lp = buf;;)
+ switch (c = getchar() & 0177) {
+ case '\n':
+ case '\r':
+ *lp = '\0';
+ putchar('\n');
+ return;
+ case '\b':
+ case '\177':
+ if (lp > buf) {
+ lp--;
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ }
+ break;
+ case 'r' & 037: {
+ char *p;
+
+ putchar('\n');
+ for (p = buf; p < lp; ++p)
+ putchar(*p);
+ break;
+ }
+ case 'u' & 037:
+ case 'w' & 037:
+ lp = buf;
+ putchar('\n');
+ break;
+ default:
+ if ((n < 1) || ((lp - buf) < n - 1)) {
+ *lp++ = c;
+ putchar('*');
+ }
+ }
+ /*NOTREACHED*/
+}
+
+static EFI_STATUS
+decrypt(unsigned int algid, u_char *data, size_t datasize, u_char *key,
+ size_t keysize, u_char *iv)
+{
+ const symmetric_alg_t *alg;
+
+ alg = get_symmetric_alg(algid);
+
+ if (alg == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ return decrypt_symmetric(alg, data, datasize, key, keysize, iv);
+}
+
+#define KEY_ID_SIZE 5
+
+static unsigned int keyid = 0;
+
+static EFI_STATUS
+register_key(const struct g_eli_softc *sc, const char *passphrase,
+ const u_char key[G_ELI_USERKEYLEN])
+{
+ EFI_STATUS status;
+ char id_buf[EFI_KMS_KEY_IDENTIFIER_MAX_SIZE + 1];
+ UINT16 count = 1;
+ EFI_KMS_KEY_DESCRIPTOR desc;
+ UINT8 key_id_size;
+
+ snprintf(id_buf, EFI_KMS_KEY_IDENTIFIER_MAX_SIZE, "GELI%u", keyid);
+ key_id_size = strlen(id_buf);
+ desc.KeyIdentifierSize = key_id_size;
+ desc.KeyIdentifier = id_buf;
+ memcpy(&(desc.KeyFormat), &Generic512Guid, sizeof(EFI_GUID));
+ desc.KeyValue = (void*)key;
+
+ status = kms->AddKey(kms, NULL, &count, &desc, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to add key %lu\n", EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ status = kms->AddKeyAttributes(kms, NULL, &key_id_size, id_buf, &count,
+ key_attr_service_id_geli, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to add key attributes %lu\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ if (passphrase != NULL) {
+ snprintf(id_buf, EFI_KMS_KEY_IDENTIFIER_MAX_SIZE, "GELIPASS%u",
+ keyid);
+ key_id_size = strlen(id_buf);
+ desc.KeyIdentifierSize = key_id_size;
+ desc.KeyIdentifier = id_buf;
+ memcpy(&(desc.KeyFormat), &Generic2048Guid, sizeof(EFI_GUID));
+ desc.KeyValue = (void*)passphrase;
+
+ status = kms->AddKey(kms, NULL, &count, &desc, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to add key %lu\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ status = kms->AddKeyAttributes(kms, NULL, &key_id_size, id_buf,
+ &count, key_attr_service_id_passphrase, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to add key attributes %lu\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+ }
+
+ keyid++;
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+try_password(struct g_eli_metadata *md, struct g_eli_softc *sc,
+ char *passphrase, bool register_pw)
+{
+ u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN], *mkp;
+ u_int keynum;
+ struct hmac_ctx ctx;
+ int error;
+
+ g_eli_crypto_hmac_init(&ctx, NULL, 0);
+ /*
+ * Prepare Derived-Key from the user passphrase.
+ */
+ if (md->md_iterations == 0) {
+ g_eli_crypto_hmac_update(&ctx, md->md_salt,
+ sizeof(md->md_salt));
+ g_eli_crypto_hmac_update(&ctx, passphrase,
+ strlen(passphrase));
+ } else if (md->md_iterations > 0) {
+ u_char dkey[G_ELI_USERKEYLEN];
+
+ pkcs5v2_genkey(dkey, sizeof(dkey), md->md_salt,
+ sizeof(md->md_salt), passphrase,
+ md->md_iterations);
+ g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
+ explicit_bzero(&dkey, sizeof(dkey));
+ }
+
+ g_eli_crypto_hmac_final(&ctx, key, 0);
+
+ error = g_eli_mkey_decrypt(md, key, mkey, &keynum);
+ if (error == -1) {
+ bzero(&key, sizeof(key));
+ bzero(&mkey, sizeof(mkey));
+ return (EFI_ACCESS_DENIED);
+ } else if (error != 0) {
+ bzero(&key, sizeof(key));
+ bzero(&mkey, sizeof(mkey));
+ printf("Failed to decrypt GELI master key: %d\n", error);
+ return (EFI_LOAD_ERROR);
+ }
+
+ /* Register the new key */
+ if (register_pw)
+ register_key(sc, passphrase, key);
+ else
+ register_key(sc, NULL, key);
+
+ bzero(&key, sizeof(key));
+
+ /* Store the keys */
+ bcopy(mkey, sc->sc_mkey, sizeof(sc->sc_mkey));
+ bcopy(mkey, sc->sc_ivkey, sizeof(sc->sc_ivkey));
+ mkp = mkey + sizeof(sc->sc_ivkey);
+ if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0) {
+ bcopy(mkp, sc->sc_ekey, G_ELI_DATAKEYLEN);
+ } else {
+ /*
+ * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
+ */
+ g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, "\x10", 1,
+ sc->sc_ekey, 0);
+ }
+ bzero(&mkey, sizeof(mkey));
+
+ /* Initialize the per-sector IV */
+ switch (sc->sc_ealgo) {
+ case CRYPTO_AES_XTS:
+ break;
+ default:
+ SHA256_Init(&sc->sc_ivctx);
+ SHA256_Update(&sc->sc_ivctx, sc->sc_ivkey,
+ sizeof(sc->sc_ivkey));
+ break;
+ }
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+try_cached_passphrases(struct g_eli_metadata *md, struct g_eli_softc *sc)
+{
+ EFI_STATUS status;
+ UINTN i;
+ UINTN count = 1;
+ UINTN nkeydescs = 0;
+ EFI_KMS_KEY_DESCRIPTOR *keydescs;
+
+ status = kms->GetKeyByAttributes(kms, NULL, &count,
+ key_attr_service_id_passphrase, &nkeydescs, NULL, NULL, NULL);
+
+ /* We might get EFI_SUCCESS if there are no keys */
+ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND ||
+ nkeydescs == 0) {
+ return (EFI_ACCESS_DENIED);
+ } else if (status != EFI_BUFFER_TOO_SMALL) {
+ printf("Error getting number of passphrases: %lu\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ keydescs = malloc(nkeydescs * sizeof(EFI_KMS_KEY_DESCRIPTOR));
+
+ for(i = 0; i < nkeydescs; i++) {
+ keydescs[i].KeyValue = malloc(MAX_KEY_BYTES);
+ }
+
+ if(keydescs == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ status = kms->GetKeyByAttributes(kms, NULL, &count,
+ key_attr_service_id_passphrase, &nkeydescs, keydescs, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Error getting passphrases: %lu\n",
+ EFI_ERROR_CODE(status));
+ free(keydescs);
+
+ return (status);
+ }
+
+ for(i = 0; i < nkeydescs; i++) {
+ status = try_password(md, sc, keydescs[i].KeyValue, false);
+
+ if (status != EFI_ACCESS_DENIED) {
+ for(; i < nkeydescs; i++) {
+ memset(keydescs[i].KeyValue, 0, MAX_KEY_BYTES);
+ free(keydescs[i].KeyValue);
+
+ }
+
+ free(keydescs);
+ return (status);
+ }
+
+ memset(keydescs[i].KeyValue, 0, MAX_KEY_BYTES);
+ free(keydescs[i].KeyValue);
+ }
+
+ free(keydescs);
+
+ return (EFI_ACCESS_DENIED);
+}
+
+static EFI_STATUS
+try_keys(struct g_eli_metadata *md, struct g_eli_softc *sc)
+{
+ EFI_STATUS status;
+ UINTN i;
+ UINTN count = 1;
+ UINTN nkeydescs = 0;
+ EFI_KMS_KEY_DESCRIPTOR *keydescs;
+ u_char mkey[G_ELI_DATAIVKEYLEN], *mkp;
+ u_int keynum;
+
+ status = kms->GetKeyByAttributes(kms, NULL, &count,
+ key_attr_service_id_geli, &nkeydescs, NULL, NULL, NULL);
+
+ /* We might get EFI_SUCCESS if there are no keys */
+ if (status == EFI_SUCCESS || status == EFI_NOT_FOUND ||
+ nkeydescs == 0) {
+ return (try_cached_passphrases(md, sc));
+ } else if (status != EFI_BUFFER_TOO_SMALL) {
+ printf("Error getting number of keys: %lu\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ keydescs = malloc(nkeydescs * sizeof(EFI_KMS_KEY_DESCRIPTOR));
+
+ for(i = 0; i < nkeydescs; i++) {
+ keydescs[i].KeyValue = malloc(MAX_KEY_BYTES);
+ }
+
+ if(keydescs == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ status = kms->GetKeyByAttributes(kms, NULL, &count,
+ key_attr_service_id_geli, &nkeydescs, keydescs, NULL, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Error getting keys: %lu\n", EFI_ERROR_CODE(status));
+ free(keydescs);
+
+ return (status);
+ }
+
+ /* Try all keys with the right encryption type */
+ for(i = 0; i < nkeydescs; i++) {
+ if(g_eli_mkey_decrypt(md, keydescs[i].KeyValue,
+ mkey, &keynum) == 0) {
+ for(; i < nkeydescs; i++) {
+ memset(keydescs[i].KeyValue, 0, MAX_KEY_BYTES);
+ free(keydescs[i].KeyValue);
+
+ }
+
+ free(keydescs);
+
+ /* Store the keys */
+ bcopy(mkey, sc->sc_mkey, sizeof(sc->sc_mkey));
+ bcopy(mkey, sc->sc_ivkey, sizeof(sc->sc_ivkey));
+ mkp = mkey + sizeof(sc->sc_ivkey);
+ if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0) {
+ bcopy(mkp, sc->sc_ekey, G_ELI_DATAKEYLEN);
+ } else {
+ /*
+ * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
+ */
+ g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, "\x10", 1,
+ sc->sc_ekey, 0);
+ }
+ bzero(&mkey, sizeof(mkey));
+
+ /* Initialize the per-sector IV */
+ switch (sc->sc_ealgo) {
+ case CRYPTO_AES_XTS:
+ break;
+ default:
+ SHA256_Init(&sc->sc_ivctx);
+ SHA256_Update(&sc->sc_ivctx, sc->sc_ivkey,
+ sizeof(sc->sc_ivkey));
+ break;
+ }
+
+ memset(keydescs, 0,
+ nkeydescs * sizeof(EFI_KMS_KEY_DESCRIPTOR));
+ free(keydescs);
+
+ return (EFI_SUCCESS);
+ } else {
+ memset(keydescs[i].KeyValue, 0, MAX_KEY_BYTES);
+ free(keydescs[i].KeyValue);
+ }
+
+ memset(keydescs[i].KeyValue, 0, MAX_KEY_BYTES);
+ }
+
+ memset(keydescs, 0, nkeydescs * sizeof(EFI_KMS_KEY_DESCRIPTOR));
+ free(keydescs);
+
+ return (try_cached_passphrases(md, sc));
+}
+
+static EFI_STATUS
+ask_password(struct g_eli_metadata *md, struct g_eli_softc *sc) {
+ char pwbuf[MAXPWLEN + 1];
+ EFI_STATUS status;
+ UINTN i;
+
+ for(i = 0, status = EFI_ACCESS_DENIED;
+ i < 5 && status == EFI_ACCESS_DENIED; i++) {
+ printf("Enter passphrase for encrypted volume: ");
+ pwgets(pwbuf, MAXPWLEN);
+ status = try_password(md, sc, pwbuf, true);
+ memset(pwbuf, 0, MAXPWLEN);
+
+ if (status == EFI_SUCCESS) {
+ printf("OK\n");
+ } else if (status == EFI_ACCESS_DENIED) {
+ printf("Incorrect\n");
+ } else {
+ printf("Error!\n");
+ }
+ }
+
+ if (status == EFI_ACCESS_DENIED) {
+ printf("Access denied: too many tries\n");
+ }
+
+ return (status);
+}
+
+static EFI_STATUS
+discover(struct g_eli_metadata *md, struct g_eli_softc *sc, EFI_BLOCK_IO *inner,
+ EFI_HANDLE dev)
+{
+ u_char buf[inner->Media->BlockSize];
+ int error;
+ EFI_STATUS status;
+
+ memset(md, 0, sizeof(struct g_eli_metadata));
+ memset(sc, 0, sizeof(struct g_eli_softc));
+ status = inner->ReadBlocks(inner, inner->Media->MediaId,
+ inner->Media->LastBlock, inner->Media->BlockSize, buf);
+
+ if (status != EFI_SUCCESS) {
+ if (status != EFI_NO_MEDIA && status != EFI_MEDIA_CHANGED) {
+ printf("Failed to read last block (%lu)\n",
+ EFI_ERROR_CODE(status));
+ }
+ return (status);
+ }
+
+ error = eli_metadata_decode(buf, md);
+
+ /* EINVAL means not found */
+ if (error == EINVAL) {
+ return (EFI_NOT_FOUND);
+ } else if (error == EOPNOTSUPP) {
+ return (EFI_UNSUPPORTED);
+ } else if (error != 0) {
+ return (EFI_LOAD_ERROR);
+ }
+
+ if ((md->md_flags & G_ELI_FLAG_ONETIME)) {
+ /* Swap device, skip it */
+ return (EFI_NOT_FOUND);
+ }
+
+ if (!(md->md_flags & G_ELI_FLAG_BOOT)) {
+ /* Disk is not GELI boot device, skip it */
+ return (EFI_NOT_FOUND);
+ }
+
+ /* First, try all the existing keys */
+ status = try_keys(md, sc);
+
+ if (status != EFI_SUCCESS) {
+ /* If none of them work, give the user five tries to input a
+ * new password
+ */
+ if (status == EFI_ACCESS_DENIED) {
+ status = ask_password(md, sc);
+
+ if (status != EFI_SUCCESS) {
+ return (status);
+ }
+ } else {
+ return (status);
+ }
+ }
+
+ eli_metadata_softc(sc, md, inner->Media->BlockSize,
+ (inner->Media->LastBlock * inner->Media->BlockSize) +
+ inner->Media->BlockSize);
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS EFIAPI
+reset_impl(EFI_BLOCK_IO *This, BOOLEAN ev)
+{
+ geli_info_t *info = (geli_info_t*)(This + 1);
+
+ printf("reset_impl\n");
+
+ return info->blkio->Reset(info->blkio, ev);
+}
+
+static EFI_STATUS EFIAPI
+read_impl(EFI_BLOCK_IO *This, UINT32 MediaID, EFI_LBA LBA,
+ UINTN BufferSize, VOID *Buffer)
+{
+ geli_info_t *info = (geli_info_t*)(This + 1);
+ char iv[G_ELI_IVKEYLEN];
+ char *pbuf = Buffer;
+ off_t offset;
+ uint64_t keyno;
+ size_t n, nb;
+ struct g_eli_key gkey;
+ EFI_STATUS status;
+
+ // Read the raw data
+ status = info->blkio->ReadBlocks(info->blkio,
+ info->blkio->Media->MediaId, LBA, BufferSize, Buffer);
+
+ if (EFI_ERROR(status)) {
+ printf("Error reading encrypted blocks (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ nb = BufferSize / info->blkio->Media->BlockSize;
+
+ for (n = 0; n < nb; n++) {
+ offset = (LBA + n) * info->blkio->Media->BlockSize;
+ pbuf = (char*)Buffer + (n * info->blkio->Media->BlockSize);
+
+ g_eli_crypto_ivgen(&(info->sc), offset, iv, G_ELI_IVKEYLEN);
+
+ /* Get the key that corresponds to this offset */
+ keyno = (offset >> G_ELI_KEY_SHIFT) /
+ info->blkio->Media->BlockSize;
+
+ g_eli_key_fill(&(info->sc), &gkey, keyno);
+
+ status = decrypt(info->sc.sc_ealgo, pbuf,
+ info->blkio->Media->BlockSize, gkey.gek_key,
+ info->sc.sc_ekeylen, iv);
+
+ if (status != EFI_SUCCESS) {
+ printf("Error decrypting blocks %lu\n",
+ EFI_ERROR_CODE(status));
+ explicit_bzero(&gkey, sizeof(gkey));
+ return (status);
+ }
+ }
+
+ explicit_bzero(&gkey, sizeof(gkey));
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS EFIAPI
+write_impl(EFI_BLOCK_IO *This __unused, UINT32 MediaID __unused,
+ EFI_LBA LBA __unused, UINTN BufferSize __unused, VOID *Buffer __unused)
+{
+ return (EFI_UNSUPPORTED);
+}
+
+static EFI_STATUS EFIAPI
+flush_impl(EFI_BLOCK_IO *This)
+{
+ geli_info_t *info = (geli_info_t*)(This + 1);
+
+ return info->blkio->FlushBlocks(info->blkio);
+}
+
+static EFI_BLOCK_IO*
+make_block_io_iface(struct g_eli_metadata *md, struct g_eli_softc *sc,
+ EFI_BLOCK_IO *inner, EFI_HANDLE dev)
+{
+ EFI_BLOCK_IO *blkio;
+ geli_info_t *info;
+
+ if ((blkio = malloc(sizeof(EFI_BLOCK_IO) + sizeof(geli_info_t))) ==
+ NULL) {
+ return NULL;
+ }
+
+ if ((blkio->Media = malloc(sizeof(EFI_BLOCK_IO_MEDIA))) == NULL) {
+ free(blkio);
+
+ return NULL;
+ }
+
+ info = (geli_info_t*)(blkio + 1);
+ blkio->Revision = EFI_BLOCK_IO_INTERFACE_REVISION;
+ blkio->Media->MediaId = inner->Media->MediaId;
+ blkio->Media->RemovableMedia = false;
+ blkio->Media->MediaPresent = true;
+ blkio->Media->LogicalPartition = true;
+ blkio->Media->ReadOnly = true;
+ blkio->Media->WriteCaching = false;
+ blkio->Media->BlockSize = inner->Media->BlockSize;
+ blkio->Media->IoAlign = inner->Media->IoAlign;
+ blkio->Media->LastBlock = inner->Media->LastBlock - 1;
+ blkio->Reset = reset_impl;
+ blkio->ReadBlocks = read_impl;
+ blkio->WriteBlocks = write_impl;
+ blkio->FlushBlocks = flush_impl;
+ memcpy(&(info->md), md, sizeof(struct g_eli_metadata));
+ memcpy(&(info->sc), sc, sizeof(struct g_eli_softc));
+ info->dev = dev;
+
+ return blkio;
+}
+
+static EFI_STATUS EFIAPI
+supported_impl(EFI_DRIVER_BINDING *This, EFI_HANDLE handle,
+ EFI_DEVICE_PATH *RemainingDevicePath __unused)
+{
+ return (BS->OpenProtocol(handle, &BlockIOProtocolGUID, NULL,
+ This->DriverBindingHandle, handle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL));
+}
+
+static size_t
+wcslen(const CHAR16 *s)
+{
+ size_t len;
+
+ for(len = 0; s[len] != '\0'; len++);
+
+ return len;
+}
+
+static void
+efifs_dev_print(EFI_DEVICE_PATH *devpath)
+{
+ CHAR16 *name16;
+
+ name16 = efi_devpath_name(devpath);
+ char buf[wcslen(name16) + 1];
+ memset(buf, 0, sizeof (buf));
+ cpy16to8(name16, buf, wcslen(name16));
+ printf("%s\n", buf);
+}
+
+static EFI_STATUS EFIAPI
+start_impl(EFI_DRIVER_BINDING *This, EFI_HANDLE handle,
+ EFI_DEVICE_PATH *RemainingDevicePath __unused)
+{
+ EFI_BLOCK_IO *blkio;
+ EFI_DISK_IO *driver_diskio;
+ EFI_STATUS status;
+ EFI_BLOCK_IO *newio;
+ EFI_HANDLE newhandle = NULL;
+ EFI_DEVICE_PATH *devpath, *newpath, *currpath, *newcurr;
+ VENDOR_DEVICE_PATH *vendornode;
+ struct g_eli_metadata md;
+ struct g_eli_softc sc;
+ UINTN pathlen;
+ geli_info_t *info;
+
+ /* Grab Disk IO to make sure that we don't end up registering
+ * this handle twice.
+ */
+ status = BS->OpenProtocol(handle, &DiskIOProtocolGUID,
+ (void**)&driver_diskio, This->DriverBindingHandle, handle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+ if (EFI_ERROR(status)) {
+ if (status != EFI_ACCESS_DENIED &&
+ status != EFI_ALREADY_STARTED &&
+ status != EFI_UNSUPPORTED) {
+ printf("Could not open device %lu\n",
+ EFI_ERROR_CODE(status));
+ }
+
+ return (status);
+ }
+
+ /* Build device path */
+ status = BS->OpenProtocol(handle, &DevicePathGUID, (void**)&devpath,
+ This->DriverBindingHandle, handle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to obtain device path %lu\n",
+ EFI_ERROR_CODE(status));
+ free(newio);
+
+ return (status);
+ }
+
+ currpath = devpath;
+ pathlen = 0;
+
+ while (!IsDevicePathEnd(currpath)) {
+ pathlen += DevicePathNodeLength(currpath);
+ currpath = NextDevicePathNode(currpath);
+ }
+
+ pathlen += sizeof(EFI_DEVICE_PATH);
+ pathlen += sizeof(VENDOR_DEVICE_PATH);
+ newpath = malloc(pathlen);
+
+ if (newpath == NULL) {
+ printf("Failed to create new device path\n");
+
+ return (status);
+ }
+
+ currpath = devpath;
+ newcurr = newpath;
+
+ while (!IsDevicePathEnd(currpath)) {
+ memcpy(newcurr, currpath, DevicePathNodeLength(currpath));
+ currpath = NextDevicePathNode(currpath);
+ newcurr = NextDevicePathNode(newcurr);
+ }
+
+ vendornode = (VENDOR_DEVICE_PATH *)newcurr;
+ vendornode->Header.Type = MEDIA_DEVICE_PATH;
+ vendornode->Header.SubType = MEDIA_VENDOR_DP;
+ vendornode->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH);
+ vendornode->Header.Length[1] = 0;
+ memcpy(&(vendornode->Guid), &FreeBSDGELIGUID, sizeof(EFI_GUID));
+ newcurr = NextDevicePathNode(newcurr);
+ SetDevicePathEndNode(newcurr);
+ devpath = newpath;
+
+ BS->CloseProtocol(handle, &DevicePathGUID, This->DriverBindingHandle,
+ handle);
+
+ /* Get block IO */
+ status = BS->OpenProtocol(handle, &BlockIOProtocolGUID, (void**)&blkio,
+ This->DriverBindingHandle, handle, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR(status)) {
+ printf("Could not open device %lu\n", EFI_ERROR_CODE(status));
+ free(newpath);
+
+ return (status);
+ }
+
+ /* Test for GELI presence */
+ status = discover(&md, &sc, blkio, handle);
+
+ if (EFI_ERROR(status)) {
+ BS->CloseProtocol(handle, &BlockIOProtocolGUID,
+ This->DriverBindingHandle, handle);
+ free(newpath);
+
+ return (status);
+ }
+
+ /* Make Block IO interface */
+ newio = make_block_io_iface(&md, &sc, blkio, handle);
+ info = (geli_info_t*)(newio + 1);
+ info->diskio = driver_diskio;
+ BS->CloseProtocol(handle, &BlockIOProtocolGUID,
+ This->DriverBindingHandle, handle);
+
+ if (newio == NULL) {
+ free(newpath);
+ printf("Failed to create new IO interface!\n");
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ /* Create device handle and attach interfaces */
+ status = BS->InstallMultipleProtocolInterfaces(&newhandle,
+ &BlockIOProtocolGUID, newio, &DevicePathGUID, newpath, NULL);
+ printf("Created GELI IO interface %p on device %p\n", newio, newhandle);
+
+ if (EFI_ERROR(status)) {
+ printf("Could not create child device %lu\n",
+ EFI_ERROR_CODE(status));
+ free(newio);
+ free(newpath);
+
+ return (status);
+ }
+
+ status = BS->OpenProtocol(handle, &BlockIOProtocolGUID,
+ (void**)&(info->blkio), This->DriverBindingHandle, newhandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+
+ if (EFI_ERROR(status)) {
+ printf("Could not associate child device %lu\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS EFIAPI
+stop_impl(EFI_DRIVER_BINDING *This __unused, EFI_HANDLE handle __unused,
+ UINTN NumberOfChildren __unused, EFI_HANDLE *ChildHandleBuffer __unused)
+{
+ return (EFI_UNSUPPORTED);
+}
+
+static EFI_STATUS
+locate_kms(void)
+{
+ EFI_HANDLE *handles;
+ EFI_STATUS status;
+ UINTN sz;
+ u_int n, nin;
+
+ /* Try and find a usable KMS */
+ sz = 0;
+ handles = NULL;
+ status = BS->LocateHandle(ByProtocol, &EfiKmsProtocolGuid, NULL, &sz,
+ NULL);
+
+ 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 KMS handles (%lu)\n",
+ EFI_ERROR_CODE(status));
+ free(handles);
+
+ return (status);
+ }
+ } else {
+ printf("Error getting size of KMS buffer (%lu)\n",
+ EFI_ERROR_CODE(status));
+
+ return (status);
+ }
+
+ 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("Failed to obtain KMS protocol interface (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ if (!memcmp(&KernelKeyInjectorGuid, &(kms->ServiceId),
+ sizeof(EFI_GUID))) {
+ free(handles);
+
+ return (EFI_SUCCESS);
+ }
+
+ BS->CloseProtocol(handles[n], &KernelKeyInjectorGuid,
+ IH, handles[n]);
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+static void
+init(void)
+{
+ EFI_STATUS status;
+ EFI_HANDLE *handles;
+ UINTN nhandles, i, hsize;
+
+ status = locate_kms();
+
+ if (EFI_ERROR(status)) {
+ printf("Error locating usable KMS (%lu)\n",
+ EFI_ERROR_CODE(status));
+
+ return;
+ }
+
+ geli_efi_driver.ImageHandle = IH;
+ geli_efi_driver.DriverBindingHandle = NULL;
+ status = BS->InstallMultipleProtocolInterfaces(
+ &(geli_efi_driver.DriverBindingHandle), &DriverBindingProtocolGUID,
+ &geli_efi_driver, NULL);
+
+ if (EFI_ERROR(status)) {
+ printf("Failed to install GELI driver (%ld)!\n",
+ EFI_ERROR_CODE(status));
+
+ return;
+ }
+
+ nhandles = 0;
+ hsize = 0;
+ status = BS->LocateHandle(ByProtocol, &BlockIOProtocolGUID, NULL,
+ &hsize, NULL);
+
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ printf("Could not get number of handles! (%ld)\n",
+ EFI_ERROR_CODE(status));
+ return;
+ }
+
+ handles = malloc(hsize);
+ nhandles = hsize / sizeof(EFI_HANDLE);
+
+ status = BS->LocateHandle(ByProtocol, &BlockIOProtocolGUID, NULL,
+ &hsize, handles);
+
+ if (EFI_ERROR(status)) {
+ printf("Could not get handles! (%ld)\n",
+ EFI_ERROR_CODE(status));
+ return;
+ }
+
+ for (i = 0; i < nhandles; i++) {
+ BS->ConnectController(handles[i], NULL, NULL, false);
+ }
+
+ free(handles);
+}
+
+static EFI_DRIVER_BINDING geli_efi_driver = {
+ .Version = 0x10,
+ .Supported = supported_impl,
+ .Start = start_impl,
+ .Stop = stop_impl
+};
+
+const efi_driver_t geli_driver =
+{
+ .name = "GELI",
+ .init = init,
+};
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 <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: sys/boot/efi/loader/Makefile
===================================================================
--- sys/boot/efi/loader/Makefile
+++ sys/boot/efi/loader/Makefile
@@ -100,6 +100,8 @@
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
.endif
+LIBBOOT_CRYPTO= ${.OBJDIR}/../../boot_crypto/libboot_crypto.a
+
# Include bcache code.
HAVE_BCACHE= yes
@@ -151,8 +153,9 @@
LIBEFI= ${.OBJDIR}/../libefi/libefi.a
DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
- ${LDSCRIPT}
-LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
+ ${LDSCRIPT} ${LIBBOOT_CRYPTO}
+LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
+ ${LIBBOOT_CRYPTO}
.include <bsd.prog.mk>
Index: sys/boot/efi/loader/bootinfo.c
===================================================================
--- sys/boot/efi/loader/bootinfo.c
+++ sys/boot/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>
@@ -58,6 +61,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[] = {
@@ -235,6 +240,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)
{
@@ -247,6 +322,7 @@
UINT32 mmver;
struct efi_map_header *efihdr;
+ key_inject_set_client(kfp);
#if defined(__amd64__)
struct efi_fb efifb;
@@ -413,8 +489,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: sys/boot/efi/loader/conf.c
===================================================================
--- sys/boot/efi/loader/conf.c
+++ sys/boot/efi/loader/conf.c
@@ -35,6 +35,14 @@
#include <libzfs.h>
#endif
+#include "efi_drivers.h"
+
+const efi_driver_t *efi_drivers[] = {
+ &key_inject_driver,
+ &geli_driver,
+ NULL
+};
+
struct devsw *devsw[] = {
&efipart_fddev,
&efipart_cddev,
Index: sys/boot/efi/loader/main.c
===================================================================
--- sys/boot/efi/loader/main.c
+++ sys/boot/efi/loader/main.c
@@ -52,6 +52,7 @@
#include "efizfs.h"
#endif
+#include "efi_drivers.h"
#include "loader_efi.h"
extern char bootprog_info[];
@@ -335,6 +336,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/geom/part/g_part.h
===================================================================
--- sys/geom/part/g_part.h
+++ sys/geom/part/g_part.h
@@ -67,6 +67,7 @@
G_PART_ALIAS_FREEBSD_UFS, /* A UFS/UFS2 file system entry. */
G_PART_ALIAS_FREEBSD_VINUM, /* A Vinum partition entry. */
G_PART_ALIAS_FREEBSD_ZFS, /* A ZFS file system entry. */
+ G_PART_ALIAS_FREEBSD_GELI, /* A GELI encrypted partition */
G_PART_ALIAS_LINUX_DATA, /* A Linux data partition entry. */
G_PART_ALIAS_LINUX_LVM, /* A Linux LVM partition entry. */
G_PART_ALIAS_LINUX_RAID, /* A Linux RAID partition entry. */
Index: sys/geom/part/g_part.c
===================================================================
--- sys/geom/part/g_part.c
+++ sys/geom/part/g_part.c
@@ -102,6 +102,7 @@
{ "freebsd-ufs", G_PART_ALIAS_FREEBSD_UFS },
{ "freebsd-vinum", G_PART_ALIAS_FREEBSD_VINUM },
{ "freebsd-zfs", G_PART_ALIAS_FREEBSD_ZFS },
+ { "freebsd-geli", G_PART_ALIAS_FREEBSD_GELI },
{ "linux-data", G_PART_ALIAS_LINUX_DATA },
{ "linux-lvm", G_PART_ALIAS_LINUX_LVM },
{ "linux-raid", G_PART_ALIAS_LINUX_RAID },
Index: sys/geom/part/g_part_gpt.c
===================================================================
--- sys/geom/part/g_part_gpt.c
+++ sys/geom/part/g_part_gpt.c
@@ -176,6 +176,7 @@
static struct uuid gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
static struct uuid gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
static struct uuid gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
+static struct uuid gpt_uuid_freebsd_geli = GPT_ENT_TYPE_FREEBSD_GELI;
static struct uuid gpt_uuid_linux_data = GPT_ENT_TYPE_LINUX_DATA;
static struct uuid gpt_uuid_linux_lvm = GPT_ENT_TYPE_LINUX_LVM;
static struct uuid gpt_uuid_linux_raid = GPT_ENT_TYPE_LINUX_RAID;
@@ -236,6 +237,7 @@
{ &gpt_uuid_freebsd_ufs, G_PART_ALIAS_FREEBSD_UFS, 0 },
{ &gpt_uuid_freebsd_vinum, G_PART_ALIAS_FREEBSD_VINUM, 0 },
{ &gpt_uuid_freebsd_zfs, G_PART_ALIAS_FREEBSD_ZFS, 0 },
+ { &gpt_uuid_freebsd_geli, G_PART_ALIAS_FREEBSD_GELI, 0 },
{ &gpt_uuid_linux_data, G_PART_ALIAS_LINUX_DATA, 0x0b },
{ &gpt_uuid_linux_lvm, G_PART_ALIAS_LINUX_LVM, 0 },
{ &gpt_uuid_linux_raid, G_PART_ALIAS_LINUX_RAID, 0 },
Index: sys/sys/disk/gpt.h
===================================================================
--- sys/sys/disk/gpt.h
+++ sys/sys/disk/gpt.h
@@ -118,6 +118,8 @@
{0x516e7cb8,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
#define GPT_ENT_TYPE_FREEBSD_ZFS \
{0x516e7cba,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
+#define GPT_ENT_TYPE_FREEBSD_GELI \
+ {0x516e7cbc,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
#define GPT_ENT_TYPE_PREP_BOOT \
{0x9e1a2d38,0xc612,0x4316,0xaa,0x26,{0x8b,0x49,0x52,0x1e,0x5a,0x8b}}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 14, 5:48 PM (11 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26964106
Default Alt Text
D10512.id28259.diff (118 KB)
Attached To
Mode
D10512: GELI support for EFI loader
Attached
Detach File
Event Timeline
Log In to Comment