Page MenuHomeFreeBSD

D10512.id28259.diff
No OneTemporary

D10512.id28259.diff

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

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)

Event Timeline