[Glibc-bsd-commits] r3898 - in trunk/freebsd-utils/debian: . patches

Robert Millan rmh at alioth.debian.org
Fri Nov 25 18:33:44 UTC 2011


Author: rmh
Date: 2011-11-25 18:33:26 +0000 (Fri, 25 Nov 2011)
New Revision: 3898

Removed:
   trunk/freebsd-utils/debian/patches/000_sys_geom.diff
Modified:
   trunk/freebsd-utils/debian/changelog
   trunk/freebsd-utils/debian/patches/series
   trunk/freebsd-utils/debian/rules
Log:
New snapshot (include powerd, move GEOM from 000_sys_geom.diff to orig tarball).

Modified: trunk/freebsd-utils/debian/changelog
===================================================================
--- trunk/freebsd-utils/debian/changelog	2011-11-23 21:22:02 UTC (rev 3897)
+++ trunk/freebsd-utils/debian/changelog	2011-11-25 18:33:26 UTC (rev 3898)
@@ -1,3 +1,10 @@
+freebsd-utils (8.2+ds3-13) UNRELEASED; urgency=low
+
+  * New snapshot (include powerd, move GEOM from 000_sys_geom.diff to orig
+    tarball).
+
+ -- Robert Millan <rmh at debian.org>  Fri, 25 Nov 2011 19:17:03 +0100
+
 freebsd-utils (8.2+ds2-12) unstable; urgency=low
 
   [ Robert Millan ]

Deleted: trunk/freebsd-utils/debian/patches/000_sys_geom.diff
===================================================================
--- trunk/freebsd-utils/debian/patches/000_sys_geom.diff	2011-11-23 21:22:02 UTC (rev 3897)
+++ trunk/freebsd-utils/debian/patches/000_sys_geom.diff	2011-11-25 18:33:26 UTC (rev 3898)
@@ -1,5743 +0,0 @@
---- /dev/null
-+++ b/sys/crypto/sha2/sha2.c
-@@ -0,0 +1,1052 @@
-+/*	$KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $	*/
-+
-+/*
-+ * sha2.c
-+ *
-+ * Version 1.0.0beta1
-+ *
-+ * Written by Aaron D. Gifford <me at aarongifford.com>
-+ *
-+ * Copyright 2000 Aaron D. Gifford.  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.
-+ * 3. Neither the name of the copyright holder nor the names of contributors
-+ *    may be used to endorse or promote products derived from this software
-+ *    without specific prior written permission.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``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(S) OR CONTRIBUTOR(S) 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/types.h>
-+#include <sys/time.h>
-+#ifdef _KERNEL
-+#include <sys/systm.h>
-+#else
-+#include <string.h>
-+#endif
-+#include <machine/endian.h>
-+#include <crypto/sha2/sha2.h>
-+
-+/*
-+ * ASSERT NOTE:
-+ * Some sanity checking code is included using assert().  On my FreeBSD
-+ * system, this additional code can be removed by compiling with NDEBUG
-+ * defined.  Check your own systems manpage on assert() to see how to
-+ * compile WITHOUT the sanity checking code on your system.
-+ *
-+ * UNROLLED TRANSFORM LOOP NOTE:
-+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
-+ * loop version for the hash transform rounds (defined using macros
-+ * later in this file).  Either define on the command line, for example:
-+ *
-+ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
-+ *
-+ * or define below:
-+ *
-+ *   #define SHA2_UNROLL_TRANSFORM
-+ *
-+ */
-+
-+#if defined(__bsdi__) || defined(__FreeBSD__)
-+#define assert(x)
-+#endif
-+
-+
-+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
-+/*
-+ * BYTE_ORDER NOTE:
-+ *
-+ * Please make sure that your system defines BYTE_ORDER.  If your
-+ * architecture is little-endian, make sure it also defines
-+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
-+ * equivilent.
-+ *
-+ * If your system does not define the above, then you can do so by
-+ * hand like this:
-+ *
-+ *   #define LITTLE_ENDIAN 1234
-+ *   #define BIG_ENDIAN    4321
-+ *
-+ * And for little-endian machines, add:
-+ *
-+ *   #define BYTE_ORDER LITTLE_ENDIAN 
-+ *
-+ * Or for big-endian machines:
-+ *
-+ *   #define BYTE_ORDER BIG_ENDIAN
-+ *
-+ * The FreeBSD machine this was written on defines BYTE_ORDER
-+ * appropriately by including <sys/types.h> (which in turn includes
-+ * <machine/endian.h> where the appropriate definitions are actually
-+ * made).
-+ */
-+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
-+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
-+#endif
-+
-+/*
-+ * Define the followingsha2_* types to types of the correct length on
-+ * the native archtecture.   Most BSD systems and Linux define u_intXX_t
-+ * types.  Machines with very recent ANSI C headers, can use the
-+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
-+ * during compile or in the sha.h header file.
-+ *
-+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
-+ * will need to define these three typedefs below (and the appropriate
-+ * ones in sha.h too) by hand according to their system architecture.
-+ *
-+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
-+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
-+ */
-+#if 0 /*def SHA2_USE_INTTYPES_H*/
-+
-+typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
-+typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
-+typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
-+
-+#else /* SHA2_USE_INTTYPES_H */
-+
-+typedef u_int8_t  sha2_byte;	/* Exactly 1 byte */
-+typedef u_int32_t sha2_word32;	/* Exactly 4 bytes */
-+typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
-+
-+#endif /* SHA2_USE_INTTYPES_H */
-+
-+
-+/*** SHA-256/384/512 Various Length Definitions ***********************/
-+/* NOTE: Most of these are in sha2.h */
-+#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
-+#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
-+#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
-+
-+
-+/*** ENDIAN REVERSAL MACROS *******************************************/
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+#define REVERSE32(w,x)	{ \
-+	sha2_word32 tmp = (w); \
-+	tmp = (tmp >> 16) | (tmp << 16); \
-+	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
-+}
-+#define REVERSE64(w,x)	{ \
-+	sha2_word64 tmp = (w); \
-+	tmp = (tmp >> 32) | (tmp << 32); \
-+	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
-+	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
-+	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
-+	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
-+}
-+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-+
-+/*
-+ * Macro for incrementally adding the unsigned 64-bit integer n to the
-+ * unsigned 128-bit integer (represented using a two-element array of
-+ * 64-bit words):
-+ */
-+#define ADDINC128(w,n)	{ \
-+	(w)[0] += (sha2_word64)(n); \
-+	if ((w)[0] < (n)) { \
-+		(w)[1]++; \
-+	} \
-+}
-+
-+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
-+/*
-+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
-+ *
-+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
-+ *   S is a ROTATION) because the SHA-256/384/512 description document
-+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
-+ *   same "backwards" definition.
-+ */
-+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
-+#define R(b,x) 		((x) >> (b))
-+/* 32-bit Rotate-right (used in SHA-256): */
-+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
-+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
-+#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
-+
-+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
-+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
-+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
-+
-+/* Four of six logical functions used in SHA-256: */
-+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
-+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
-+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
-+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
-+
-+/* Four of six logical functions used in SHA-384 and SHA-512: */
-+#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
-+#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
-+#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
-+#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
-+
-+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
-+/* NOTE: These should not be accessed directly from outside this
-+ * library -- they are intended for private internal visibility/use
-+ * only.
-+ */
-+void SHA512_Last(SHA512_CTX*);
-+void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
-+void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
-+
-+
-+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
-+/* Hash constant words K for SHA-256: */
-+static const sha2_word32 K256[64] = {
-+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
-+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
-+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
-+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
-+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
-+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
-+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
-+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
-+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
-+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
-+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
-+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
-+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
-+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
-+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
-+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
-+};
-+
-+/* Initial hash value H for SHA-256: */
-+static const sha2_word32 sha256_initial_hash_value[8] = {
-+	0x6a09e667UL,
-+	0xbb67ae85UL,
-+	0x3c6ef372UL,
-+	0xa54ff53aUL,
-+	0x510e527fUL,
-+	0x9b05688cUL,
-+	0x1f83d9abUL,
-+	0x5be0cd19UL
-+};
-+
-+/* Hash constant words K for SHA-384 and SHA-512: */
-+static const sha2_word64 K512[80] = {
-+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
-+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
-+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
-+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
-+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
-+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
-+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
-+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
-+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
-+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
-+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
-+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
-+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
-+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
-+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
-+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
-+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
-+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
-+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
-+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
-+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
-+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
-+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
-+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
-+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
-+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
-+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
-+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
-+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
-+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
-+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
-+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
-+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
-+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
-+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
-+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
-+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
-+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
-+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
-+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
-+};
-+
-+/* Initial hash value H for SHA-384 */
-+static const sha2_word64 sha384_initial_hash_value[8] = {
-+	0xcbbb9d5dc1059ed8ULL,
-+	0x629a292a367cd507ULL,
-+	0x9159015a3070dd17ULL,
-+	0x152fecd8f70e5939ULL,
-+	0x67332667ffc00b31ULL,
-+	0x8eb44a8768581511ULL,
-+	0xdb0c2e0d64f98fa7ULL,
-+	0x47b5481dbefa4fa4ULL
-+};
-+
-+/* Initial hash value H for SHA-512 */
-+static const sha2_word64 sha512_initial_hash_value[8] = {
-+	0x6a09e667f3bcc908ULL,
-+	0xbb67ae8584caa73bULL,
-+	0x3c6ef372fe94f82bULL,
-+	0xa54ff53a5f1d36f1ULL,
-+	0x510e527fade682d1ULL,
-+	0x9b05688c2b3e6c1fULL,
-+	0x1f83d9abfb41bd6bULL,
-+	0x5be0cd19137e2179ULL
-+};
-+
-+/*
-+ * Constant used by SHA256/384/512_End() functions for converting the
-+ * digest to a readable hexadecimal character string:
-+ */
-+static const char *sha2_hex_digits = "0123456789abcdef";
-+
-+
-+/*** SHA-256: *********************************************************/
-+void SHA256_Init(SHA256_CTX* context) {
-+	if (context == (SHA256_CTX*)0) {
-+		return;
-+	}
-+	bcopy(sha256_initial_hash_value, context->state, SHA256_DIGEST_LENGTH);
-+	bzero(context->buffer, SHA256_BLOCK_LENGTH);
-+	context->bitcount = 0;
-+}
-+
-+#ifdef SHA2_UNROLL_TRANSFORM
-+
-+/* Unrolled SHA-256 round macros: */
-+
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+
-+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
-+	REVERSE32(*data++, W256[j]); \
-+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
-+             K256[j] + W256[j]; \
-+	(d) += T1; \
-+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
-+	j++
-+
-+
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+
-+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
-+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
-+	     K256[j] + (W256[j] = *data++); \
-+	(d) += T1; \
-+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
-+	j++
-+
-+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-+
-+#define ROUND256(a,b,c,d,e,f,g,h)	\
-+	s0 = W256[(j+1)&0x0f]; \
-+	s0 = sigma0_256(s0); \
-+	s1 = W256[(j+14)&0x0f]; \
-+	s1 = sigma1_256(s1); \
-+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
-+	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
-+	(d) += T1; \
-+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
-+	j++
-+
-+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
-+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
-+	sha2_word32	T1, *W256;
-+	int		j;
-+
-+	W256 = (sha2_word32*)context->buffer;
-+
-+	/* Initialize registers with the prev. intermediate value */
-+	a = context->state[0];
-+	b = context->state[1];
-+	c = context->state[2];
-+	d = context->state[3];
-+	e = context->state[4];
-+	f = context->state[5];
-+	g = context->state[6];
-+	h = context->state[7];
-+
-+	j = 0;
-+	do {
-+		/* Rounds 0 to 15 (unrolled): */
-+		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
-+		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
-+		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
-+		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
-+		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
-+		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
-+		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
-+		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
-+	} while (j < 16);
-+
-+	/* Now for the remaining rounds to 64: */
-+	do {
-+		ROUND256(a,b,c,d,e,f,g,h);
-+		ROUND256(h,a,b,c,d,e,f,g);
-+		ROUND256(g,h,a,b,c,d,e,f);
-+		ROUND256(f,g,h,a,b,c,d,e);
-+		ROUND256(e,f,g,h,a,b,c,d);
-+		ROUND256(d,e,f,g,h,a,b,c);
-+		ROUND256(c,d,e,f,g,h,a,b);
-+		ROUND256(b,c,d,e,f,g,h,a);
-+	} while (j < 64);
-+
-+	/* Compute the current intermediate hash value */
-+	context->state[0] += a;
-+	context->state[1] += b;
-+	context->state[2] += c;
-+	context->state[3] += d;
-+	context->state[4] += e;
-+	context->state[5] += f;
-+	context->state[6] += g;
-+	context->state[7] += h;
-+
-+	/* Clean up */
-+	a = b = c = d = e = f = g = h = T1 = 0;
-+}
-+
-+#else /* SHA2_UNROLL_TRANSFORM */
-+
-+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
-+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
-+	sha2_word32	T1, T2, *W256;
-+	int		j;
-+
-+	W256 = (sha2_word32*)context->buffer;
-+
-+	/* Initialize registers with the prev. intermediate value */
-+	a = context->state[0];
-+	b = context->state[1];
-+	c = context->state[2];
-+	d = context->state[3];
-+	e = context->state[4];
-+	f = context->state[5];
-+	g = context->state[6];
-+	h = context->state[7];
-+
-+	j = 0;
-+	do {
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+		/* Copy data while converting to host byte order */
-+		REVERSE32(*data++,W256[j]);
-+		/* Apply the SHA-256 compression function to update a..h */
-+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+		/* Apply the SHA-256 compression function to update a..h with copy */
-+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
-+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-+		T2 = Sigma0_256(a) + Maj(a, b, c);
-+		h = g;
-+		g = f;
-+		f = e;
-+		e = d + T1;
-+		d = c;
-+		c = b;
-+		b = a;
-+		a = T1 + T2;
-+
-+		j++;
-+	} while (j < 16);
-+
-+	do {
-+		/* Part of the message block expansion: */
-+		s0 = W256[(j+1)&0x0f];
-+		s0 = sigma0_256(s0);
-+		s1 = W256[(j+14)&0x0f];	
-+		s1 = sigma1_256(s1);
-+
-+		/* Apply the SHA-256 compression function to update a..h */
-+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
-+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
-+		T2 = Sigma0_256(a) + Maj(a, b, c);
-+		h = g;
-+		g = f;
-+		f = e;
-+		e = d + T1;
-+		d = c;
-+		c = b;
-+		b = a;
-+		a = T1 + T2;
-+
-+		j++;
-+	} while (j < 64);
-+
-+	/* Compute the current intermediate hash value */
-+	context->state[0] += a;
-+	context->state[1] += b;
-+	context->state[2] += c;
-+	context->state[3] += d;
-+	context->state[4] += e;
-+	context->state[5] += f;
-+	context->state[6] += g;
-+	context->state[7] += h;
-+
-+	/* Clean up */
-+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
-+}
-+
-+#endif /* SHA2_UNROLL_TRANSFORM */
-+
-+void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
-+	unsigned int	freespace, usedspace;
-+
-+	if (len == 0) {
-+		/* Calling with no data is valid - we do nothing */
-+		return;
-+	}
-+
-+	/* Sanity check: */
-+	assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
-+
-+	usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-+	if (usedspace > 0) {
-+		/* Calculate how much free space is available in the buffer */
-+		freespace = SHA256_BLOCK_LENGTH - usedspace;
-+
-+		if (len >= freespace) {
-+			/* Fill the buffer completely and process it */
-+			bcopy(data, &context->buffer[usedspace], freespace);
-+			context->bitcount += freespace << 3;
-+			len -= freespace;
-+			data += freespace;
-+			SHA256_Transform(context, (sha2_word32*)context->buffer);
-+		} else {
-+			/* The buffer is not yet full */
-+			bcopy(data, &context->buffer[usedspace], len);
-+			context->bitcount += len << 3;
-+			/* Clean up: */
-+			usedspace = freespace = 0;
-+			return;
-+		}
-+	}
-+	while (len >= SHA256_BLOCK_LENGTH) {
-+		/* Process as many complete blocks as we can */
-+		SHA256_Transform(context, (const sha2_word32*)data);
-+		context->bitcount += SHA256_BLOCK_LENGTH << 3;
-+		len -= SHA256_BLOCK_LENGTH;
-+		data += SHA256_BLOCK_LENGTH;
-+	}
-+	if (len > 0) {
-+		/* There's left-overs, so save 'em */
-+		bcopy(data, context->buffer, len);
-+		context->bitcount += len << 3;
-+	}
-+	/* Clean up: */
-+	usedspace = freespace = 0;
-+}
-+
-+void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
-+	sha2_word32	*d = (sha2_word32*)digest;
-+	unsigned int	usedspace;
-+
-+	/* Sanity check: */
-+	assert(context != (SHA256_CTX*)0);
-+
-+	/* If no digest buffer is passed, we don't bother doing this: */
-+	if (digest != (sha2_byte*)0) {
-+		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+		/* Convert FROM host byte order */
-+		REVERSE64(context->bitcount,context->bitcount);
-+#endif
-+		if (usedspace > 0) {
-+			/* Begin padding with a 1 bit: */
-+			context->buffer[usedspace++] = 0x80;
-+
-+			if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
-+				/* Set-up for the last transform: */
-+				bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
-+			} else {
-+				if (usedspace < SHA256_BLOCK_LENGTH) {
-+					bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
-+				}
-+				/* Do second-to-last transform: */
-+				SHA256_Transform(context, (sha2_word32*)context->buffer);
-+
-+				/* And set-up for the last transform: */
-+				bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
-+			}
-+		} else {
-+			/* Set-up for the last transform: */
-+			bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
-+
-+			/* Begin padding with a 1 bit: */
-+			*context->buffer = 0x80;
-+		}
-+		/* Set the bit count: */
-+		*(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
-+
-+		/* Final transform: */
-+		SHA256_Transform(context, (sha2_word32*)context->buffer);
-+
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+		{
-+			/* Convert TO host byte order */
-+			int	j;
-+			for (j = 0; j < 8; j++) {
-+				REVERSE32(context->state[j],context->state[j]);
-+				*d++ = context->state[j];
-+			}
-+		}
-+#else
-+		bcopy(context->state, d, SHA256_DIGEST_LENGTH);
-+#endif
-+	}
-+
-+	/* Clean up state data: */
-+	bzero(context, sizeof(*context));
-+	usedspace = 0;
-+}
-+
-+char *SHA256_End(SHA256_CTX* context, char buffer[]) {
-+	sha2_byte	digest[SHA256_DIGEST_LENGTH], *d = digest;
-+	int		i;
-+
-+	/* Sanity check: */
-+	assert(context != (SHA256_CTX*)0);
-+
-+	if (buffer != (char*)0) {
-+		SHA256_Final(digest, context);
-+
-+		for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
-+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-+			*buffer++ = sha2_hex_digits[*d & 0x0f];
-+			d++;
-+		}
-+		*buffer = (char)0;
-+	} else {
-+		bzero(context, sizeof(*context));
-+	}
-+	bzero(digest, SHA256_DIGEST_LENGTH);
-+	return buffer;
-+}
-+
-+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
-+	SHA256_CTX	context;
-+
-+	SHA256_Init(&context);
-+	SHA256_Update(&context, data, len);
-+	return SHA256_End(&context, digest);
-+}
-+
-+
-+/*** SHA-512: *********************************************************/
-+void SHA512_Init(SHA512_CTX* context) {
-+	if (context == (SHA512_CTX*)0) {
-+		return;
-+	}
-+	bcopy(sha512_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
-+	bzero(context->buffer, SHA512_BLOCK_LENGTH);
-+	context->bitcount[0] = context->bitcount[1] =  0;
-+}
-+
-+#ifdef SHA2_UNROLL_TRANSFORM
-+
-+/* Unrolled SHA-512 round macros: */
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+
-+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
-+	REVERSE64(*data++, W512[j]); \
-+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
-+             K512[j] + W512[j]; \
-+	(d) += T1, \
-+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
-+	j++
-+
-+
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+
-+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
-+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
-+             K512[j] + (W512[j] = *data++); \
-+	(d) += T1; \
-+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
-+	j++
-+
-+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-+
-+#define ROUND512(a,b,c,d,e,f,g,h)	\
-+	s0 = W512[(j+1)&0x0f]; \
-+	s0 = sigma0_512(s0); \
-+	s1 = W512[(j+14)&0x0f]; \
-+	s1 = sigma1_512(s1); \
-+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
-+             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
-+	(d) += T1; \
-+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
-+	j++
-+
-+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
-+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
-+	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
-+	int		j;
-+
-+	/* Initialize registers with the prev. intermediate value */
-+	a = context->state[0];
-+	b = context->state[1];
-+	c = context->state[2];
-+	d = context->state[3];
-+	e = context->state[4];
-+	f = context->state[5];
-+	g = context->state[6];
-+	h = context->state[7];
-+
-+	j = 0;
-+	do {
-+		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
-+		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
-+		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
-+		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
-+		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
-+		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
-+		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
-+		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
-+	} while (j < 16);
-+
-+	/* Now for the remaining rounds up to 79: */
-+	do {
-+		ROUND512(a,b,c,d,e,f,g,h);
-+		ROUND512(h,a,b,c,d,e,f,g);
-+		ROUND512(g,h,a,b,c,d,e,f);
-+		ROUND512(f,g,h,a,b,c,d,e);
-+		ROUND512(e,f,g,h,a,b,c,d);
-+		ROUND512(d,e,f,g,h,a,b,c);
-+		ROUND512(c,d,e,f,g,h,a,b);
-+		ROUND512(b,c,d,e,f,g,h,a);
-+	} while (j < 80);
-+
-+	/* Compute the current intermediate hash value */
-+	context->state[0] += a;
-+	context->state[1] += b;
-+	context->state[2] += c;
-+	context->state[3] += d;
-+	context->state[4] += e;
-+	context->state[5] += f;
-+	context->state[6] += g;
-+	context->state[7] += h;
-+
-+	/* Clean up */
-+	a = b = c = d = e = f = g = h = T1 = 0;
-+}
-+
-+#else /* SHA2_UNROLL_TRANSFORM */
-+
-+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
-+	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
-+	sha2_word64	T1 = 0, T2 = 0, *W512 = (sha2_word64*)context->buffer;
-+	int		j;
-+
-+	/* Initialize registers with the prev. intermediate value */
-+	a = context->state[0];
-+	b = context->state[1];
-+	c = context->state[2];
-+	d = context->state[3];
-+	e = context->state[4];
-+	f = context->state[5];
-+	g = context->state[6];
-+	h = context->state[7];
-+
-+	j = 0;
-+	do {
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+		/* Convert TO host byte order */
-+		REVERSE64(*data++, W512[j]);
-+		/* Apply the SHA-512 compression function to update a..h */
-+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+		/* Apply the SHA-512 compression function to update a..h with copy */
-+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
-+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-+		T2 = Sigma0_512(a) + Maj(a, b, c);
-+		h = g;
-+		g = f;
-+		f = e;
-+		e = d + T1;
-+		d = c;
-+		c = b;
-+		b = a;
-+		a = T1 + T2;
-+
-+		j++;
-+	} while (j < 16);
-+
-+	do {
-+		/* Part of the message block expansion: */
-+		s0 = W512[(j+1)&0x0f];
-+		s0 = sigma0_512(s0);
-+		s1 = W512[(j+14)&0x0f];
-+		s1 =  sigma1_512(s1);
-+
-+		/* Apply the SHA-512 compression function to update a..h */
-+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
-+		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
-+		T2 = Sigma0_512(a) + Maj(a, b, c);
-+		h = g;
-+		g = f;
-+		f = e;
-+		e = d + T1;
-+		d = c;
-+		c = b;
-+		b = a;
-+		a = T1 + T2;
-+
-+		j++;
-+	} while (j < 80);
-+
-+	/* Compute the current intermediate hash value */
-+	context->state[0] += a;
-+	context->state[1] += b;
-+	context->state[2] += c;
-+	context->state[3] += d;
-+	context->state[4] += e;
-+	context->state[5] += f;
-+	context->state[6] += g;
-+	context->state[7] += h;
-+
-+	/* Clean up */
-+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
-+}
-+
-+#endif /* SHA2_UNROLL_TRANSFORM */
-+
-+void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
-+	unsigned int	freespace, usedspace;
-+
-+	if (len == 0) {
-+		/* Calling with no data is valid - we do nothing */
-+		return;
-+	}
-+
-+	/* Sanity check: */
-+	assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
-+
-+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-+	if (usedspace > 0) {
-+		/* Calculate how much free space is available in the buffer */
-+		freespace = SHA512_BLOCK_LENGTH - usedspace;
-+
-+		if (len >= freespace) {
-+			/* Fill the buffer completely and process it */
-+			bcopy(data, &context->buffer[usedspace], freespace);
-+			ADDINC128(context->bitcount, freespace << 3);
-+			len -= freespace;
-+			data += freespace;
-+			SHA512_Transform(context, (sha2_word64*)context->buffer);
-+		} else {
-+			/* The buffer is not yet full */
-+			bcopy(data, &context->buffer[usedspace], len);
-+			ADDINC128(context->bitcount, len << 3);
-+			/* Clean up: */
-+			usedspace = freespace = 0;
-+			return;
-+		}
-+	}
-+	while (len >= SHA512_BLOCK_LENGTH) {
-+		/* Process as many complete blocks as we can */
-+		SHA512_Transform(context, (const sha2_word64*)data);
-+		ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
-+		len -= SHA512_BLOCK_LENGTH;
-+		data += SHA512_BLOCK_LENGTH;
-+	}
-+	if (len > 0) {
-+		/* There's left-overs, so save 'em */
-+		bcopy(data, context->buffer, len);
-+		ADDINC128(context->bitcount, len << 3);
-+	}
-+	/* Clean up: */
-+	usedspace = freespace = 0;
-+}
-+
-+void SHA512_Last(SHA512_CTX* context) {
-+	unsigned int	usedspace;
-+
-+	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+	/* Convert FROM host byte order */
-+	REVERSE64(context->bitcount[0],context->bitcount[0]);
-+	REVERSE64(context->bitcount[1],context->bitcount[1]);
-+#endif
-+	if (usedspace > 0) {
-+		/* Begin padding with a 1 bit: */
-+		context->buffer[usedspace++] = 0x80;
-+
-+		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
-+			/* Set-up for the last transform: */
-+			bzero(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
-+		} else {
-+			if (usedspace < SHA512_BLOCK_LENGTH) {
-+				bzero(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
-+			}
-+			/* Do second-to-last transform: */
-+			SHA512_Transform(context, (sha2_word64*)context->buffer);
-+
-+			/* And set-up for the last transform: */
-+			bzero(context->buffer, SHA512_BLOCK_LENGTH - 2);
-+		}
-+	} else {
-+		/* Prepare for final transform: */
-+		bzero(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
-+
-+		/* Begin padding with a 1 bit: */
-+		*context->buffer = 0x80;
-+	}
-+	/* Store the length of input data (in bits): */
-+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
-+	*(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
-+
-+	/* Final transform: */
-+	SHA512_Transform(context, (sha2_word64*)context->buffer);
-+}
-+
-+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
-+	sha2_word64	*d = (sha2_word64*)digest;
-+
-+	/* Sanity check: */
-+	assert(context != (SHA512_CTX*)0);
-+
-+	/* If no digest buffer is passed, we don't bother doing this: */
-+	if (digest != (sha2_byte*)0) {
-+		SHA512_Last(context);
-+
-+		/* Save the hash data for output: */
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+		{
-+			/* Convert TO host byte order */
-+			int	j;
-+			for (j = 0; j < 8; j++) {
-+				REVERSE64(context->state[j],context->state[j]);
-+				*d++ = context->state[j];
-+			}
-+		}
-+#else
-+		bcopy(context->state, d, SHA512_DIGEST_LENGTH);
-+#endif
-+	}
-+
-+	/* Zero out state data */
-+	bzero(context, sizeof(*context));
-+}
-+
-+char *SHA512_End(SHA512_CTX* context, char buffer[]) {
-+	sha2_byte	digest[SHA512_DIGEST_LENGTH], *d = digest;
-+	int		i;
-+
-+	/* Sanity check: */
-+	assert(context != (SHA512_CTX*)0);
-+
-+	if (buffer != (char*)0) {
-+		SHA512_Final(digest, context);
-+
-+		for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
-+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-+			*buffer++ = sha2_hex_digits[*d & 0x0f];
-+			d++;
-+		}
-+		*buffer = (char)0;
-+	} else {
-+		bzero(context, sizeof(*context));
-+	}
-+	bzero(digest, SHA512_DIGEST_LENGTH);
-+	return buffer;
-+}
-+
-+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
-+	SHA512_CTX	context;
-+
-+	SHA512_Init(&context);
-+	SHA512_Update(&context, data, len);
-+	return SHA512_End(&context, digest);
-+}
-+
-+
-+/*** SHA-384: *********************************************************/
-+void SHA384_Init(SHA384_CTX* context) {
-+	if (context == (SHA384_CTX*)0) {
-+		return;
-+	}
-+	bcopy(sha384_initial_hash_value, context->state, SHA512_DIGEST_LENGTH);
-+	bzero(context->buffer, SHA384_BLOCK_LENGTH);
-+	context->bitcount[0] = context->bitcount[1] = 0;
-+}
-+
-+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
-+	SHA512_Update((SHA512_CTX*)context, data, len);
-+}
-+
-+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
-+	sha2_word64	*d = (sha2_word64*)digest;
-+
-+	/* Sanity check: */
-+	assert(context != (SHA384_CTX*)0);
-+
-+	/* If no digest buffer is passed, we don't bother doing this: */
-+	if (digest != (sha2_byte*)0) {
-+		SHA512_Last((SHA512_CTX*)context);
-+
-+		/* Save the hash data for output: */
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+		{
-+			/* Convert TO host byte order */
-+			int	j;
-+			for (j = 0; j < 6; j++) {
-+				REVERSE64(context->state[j],context->state[j]);
-+				*d++ = context->state[j];
-+			}
-+		}
-+#else
-+		bcopy(context->state, d, SHA384_DIGEST_LENGTH);
-+#endif
-+	}
-+
-+	/* Zero out state data */
-+	bzero(context, sizeof(*context));
-+}
-+
-+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
-+	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
-+	int		i;
-+
-+	/* Sanity check: */
-+	assert(context != (SHA384_CTX*)0);
-+
-+	if (buffer != (char*)0) {
-+		SHA384_Final(digest, context);
-+
-+		for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
-+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-+			*buffer++ = sha2_hex_digits[*d & 0x0f];
-+			d++;
-+		}
-+		*buffer = (char)0;
-+	} else {
-+		bzero(context, sizeof(*context));
-+	}
-+	bzero(digest, SHA384_DIGEST_LENGTH);
-+	return buffer;
-+}
-+
-+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
-+	SHA384_CTX	context;
-+
-+	SHA384_Init(&context);
-+	SHA384_Update(&context, data, len);
-+	return SHA384_End(&context, digest);
-+}
-+
---- /dev/null
-+++ b/sys/crypto/sha2/sha2.h
-@@ -0,0 +1,141 @@
-+/*	$FreeBSD$	*/
-+/*	$KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $	*/
-+
-+/*
-+ * sha2.h
-+ *
-+ * Version 1.0.0beta1
-+ *
-+ * Written by Aaron D. Gifford <me at aarongifford.com>
-+ *
-+ * Copyright 2000 Aaron D. Gifford.  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.
-+ * 3. Neither the name of the copyright holder nor the names of contributors
-+ *    may be used to endorse or promote products derived from this software
-+ *    without specific prior written permission.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``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(S) OR CONTRIBUTOR(S) 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.
-+ *
-+ */
-+
-+#ifndef __SHA2_H__
-+#define __SHA2_H__
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+/*** SHA-256/384/512 Various Length Definitions ***********************/
-+#define SHA256_BLOCK_LENGTH		64
-+#define SHA256_DIGEST_LENGTH		32
-+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
-+#define SHA384_BLOCK_LENGTH		128
-+#define SHA384_DIGEST_LENGTH		48
-+#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
-+#define SHA512_BLOCK_LENGTH		128
-+#define SHA512_DIGEST_LENGTH		64
-+#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
-+
-+
-+/*** SHA-256/384/512 Context Structures *******************************/
-+/* NOTE: If your architecture does not define either u_intXX_t types or
-+ * uintXX_t (from inttypes.h), you may need to define things by hand
-+ * for your system:
-+ */
-+#if 0
-+typedef unsigned char u_int8_t;		/* 1-byte  (8-bits)  */
-+typedef unsigned int u_int32_t;		/* 4-bytes (32-bits) */
-+typedef unsigned long long u_int64_t;	/* 8-bytes (64-bits) */
-+#endif
-+/*
-+ * Most BSD systems already define u_intXX_t types, as does Linux.
-+ * Some systems, however, like Compaq's Tru64 Unix instead can use
-+ * uintXX_t types defined by very recent ANSI C standards and included
-+ * in the file:
-+ *
-+ *   #include <inttypes.h>
-+ *
-+ * If you choose to use <inttypes.h> then please define: 
-+ *
-+ *   #define SHA2_USE_INTTYPES_H
-+ *
-+ * Or on the command line during compile:
-+ *
-+ *   cc -DSHA2_USE_INTTYPES_H ...
-+ */
-+#if 0 /*def SHA2_USE_INTTYPES_H*/
-+
-+typedef struct _SHA256_CTX {
-+	uint32_t	state[8];
-+	uint64_t	bitcount;
-+	uint8_t	buffer[SHA256_BLOCK_LENGTH];
-+} SHA256_CTX;
-+typedef struct _SHA512_CTX {
-+	uint64_t	state[8];
-+	uint64_t	bitcount[2];
-+	uint8_t	buffer[SHA512_BLOCK_LENGTH];
-+} SHA512_CTX;
-+
-+#else /* SHA2_USE_INTTYPES_H */
-+
-+typedef struct _SHA256_CTX {
-+	u_int32_t	state[8];
-+	u_int64_t	bitcount;
-+	u_int8_t	buffer[SHA256_BLOCK_LENGTH];
-+} SHA256_CTX;
-+typedef struct _SHA512_CTX {
-+	u_int64_t	state[8];
-+	u_int64_t	bitcount[2];
-+	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
-+} SHA512_CTX;
-+
-+#endif /* SHA2_USE_INTTYPES_H */
-+
-+typedef SHA512_CTX SHA384_CTX;
-+
-+
-+/*** SHA-256/384/512 Function Prototypes ******************************/
-+
-+void SHA256_Init(SHA256_CTX *);
-+void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t);
-+void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
-+char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
-+char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
-+
-+void SHA384_Init(SHA384_CTX*);
-+void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
-+void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
-+char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
-+char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
-+
-+void SHA512_Init(SHA512_CTX*);
-+void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
-+void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
-+char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
-+char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
-+
-+#ifdef	__cplusplus
-+}
-+#endif /* __cplusplus */
-+
-+#endif /* __SHA2_H__ */
-+
---- /dev/null
-+++ b/sys/geom/eli/g_eli.h
-@@ -0,0 +1,542 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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	_G_ELI_H_
-+#define	_G_ELI_H_
-+
-+#include <sys/endian.h>
-+#include <sys/errno.h>
-+#include <sys/malloc.h>
-+#include <crypto/sha2/sha2.h>
-+#include <opencrypto/cryptodev.h>
-+#ifdef _KERNEL
-+#include <sys/bio.h>
-+#include <sys/libkern.h>
-+#include <geom/geom.h>
-+#else
-+#include <stdio.h>
-+#include <string.h>
-+#include <strings.h>
-+#endif
-+#ifndef _OpenSSL_
-+#include <sys/md5.h>
-+#endif
-+
-+#define	G_ELI_CLASS_NAME	"ELI"
-+#define	G_ELI_MAGIC		"GEOM::ELI"
-+#define	G_ELI_SUFFIX		".eli"
-+
-+/*
-+ * Version history:
-+ * 0 - Initial version number.
-+ * 1 - Added data authentication support (md_aalgo field and
-+ *     G_ELI_FLAG_AUTH flag).
-+ * 2 - Added G_ELI_FLAG_READONLY.
-+ * 3 - Added 'configure' subcommand.
-+ * 4 - IV is generated from offset converted to little-endian
-+ *     (flag G_ELI_FLAG_NATIVE_BYTE_ORDER will be set for older versions).
-+ * 5 - Added multiple encrypton keys and AES-XTS support.
-+ */
-+#define	G_ELI_VERSION		5
-+
-+/* ON DISK FLAGS. */
-+/* Use random, onetime keys. */
-+#define	G_ELI_FLAG_ONETIME		0x00000001
-+/* Ask for the passphrase from the kernel, before mounting root. */
-+#define	G_ELI_FLAG_BOOT			0x00000002
-+/* Detach on last close, if we were open for writing. */
-+#define	G_ELI_FLAG_WO_DETACH		0x00000004
-+/* Detach on last close. */
-+#define	G_ELI_FLAG_RW_DETACH		0x00000008
-+/* Provide data authentication. */
-+#define	G_ELI_FLAG_AUTH			0x00000010
-+/* Provider is read-only, we should deny all write attempts. */
-+#define	G_ELI_FLAG_RO			0x00000020
-+/* RUNTIME FLAGS. */
-+/* Provider was open for writing. */
-+#define	G_ELI_FLAG_WOPEN		0x00010000
-+/* Destroy device. */
-+#define	G_ELI_FLAG_DESTROY		0x00020000
-+/* Provider uses native byte-order for IV generation. */
-+#define	G_ELI_FLAG_NATIVE_BYTE_ORDER	0x00040000
-+/* Provider uses single encryption key. */
-+#define	G_ELI_FLAG_SINGLE_KEY		0x00080000
-+/* Device suspended. */
-+#define	G_ELI_FLAG_SUSPEND		0x00100000
-+
-+#define	G_ELI_NEW_BIO	255
-+
-+#define	SHA512_MDLEN		64
-+#define	G_ELI_AUTH_SECKEYLEN	SHA256_DIGEST_LENGTH
-+
-+#define	G_ELI_MAXMKEYS		2
-+#define	G_ELI_MAXKEYLEN		64
-+#define	G_ELI_USERKEYLEN	G_ELI_MAXKEYLEN
-+#define	G_ELI_DATAKEYLEN	G_ELI_MAXKEYLEN
-+#define	G_ELI_AUTHKEYLEN	G_ELI_MAXKEYLEN
-+#define	G_ELI_IVKEYLEN		G_ELI_MAXKEYLEN
-+#define	G_ELI_SALTLEN		64
-+#define	G_ELI_DATAIVKEYLEN	(G_ELI_DATAKEYLEN + G_ELI_IVKEYLEN)
-+/* Data-Key, IV-Key, HMAC_SHA512(Derived-Key, Data-Key+IV-Key) */
-+#define	G_ELI_MKEYLEN		(G_ELI_DATAIVKEYLEN + SHA512_MDLEN)
-+#define	G_ELI_OVERWRITES	5
-+/* Switch data encryption key every 2^20 blocks. */
-+#define	G_ELI_KEY_SHIFT		20
-+
-+#ifdef _KERNEL
-+extern int g_eli_debug;
-+extern u_int g_eli_overwrites;
-+extern u_int g_eli_batch;
-+
-+#define	G_ELI_CRYPTO_UNKNOWN	0
-+#define	G_ELI_CRYPTO_HW		1
-+#define	G_ELI_CRYPTO_SW		2
-+
-+#define	G_ELI_DEBUG(lvl, ...)	do {					\
-+	if (g_eli_debug >= (lvl)) {					\
-+		printf("GEOM_ELI");					\
-+		if (g_eli_debug > 0)					\
-+			printf("[%u]", lvl);				\
-+		printf(": ");						\
-+		printf(__VA_ARGS__);					\
-+		printf("\n");						\
-+	}								\
-+} while (0)
-+#define	G_ELI_LOGREQ(lvl, bp, ...)	do {				\
-+	if (g_eli_debug >= (lvl)) {					\
-+		printf("GEOM_ELI");					\
-+		if (g_eli_debug > 0)					\
-+			printf("[%u]", lvl);				\
-+		printf(": ");						\
-+		printf(__VA_ARGS__);					\
-+		printf(" ");						\
-+		g_print_bio(bp);					\
-+		printf("\n");						\
-+	}								\
-+} while (0)
-+
-+struct g_eli_worker {
-+	struct g_eli_softc	*w_softc;
-+	struct proc		*w_proc;
-+	u_int			 w_number;
-+	uint64_t		 w_sid;
-+	boolean_t		 w_active;
-+	LIST_ENTRY(g_eli_worker) w_next;
-+};
-+
-+struct g_eli_softc {
-+	struct g_geom	 *sc_geom;
-+	u_int		  sc_crypto;
-+	uint8_t		  sc_mkey[G_ELI_DATAIVKEYLEN];
-+	uint8_t		**sc_ekeys;
-+	u_int		  sc_nekeys;
-+	u_int		  sc_ealgo;
-+	u_int		  sc_ekeylen;
-+	uint8_t		  sc_akey[G_ELI_AUTHKEYLEN];
-+	u_int		  sc_aalgo;
-+	u_int		  sc_akeylen;
-+	u_int		  sc_alen;
-+	SHA256_CTX	  sc_akeyctx;
-+	uint8_t		  sc_ivkey[G_ELI_IVKEYLEN];
-+	SHA256_CTX	  sc_ivctx;
-+	int		  sc_nkey;
-+	uint32_t	  sc_flags;
-+	int		  sc_inflight;
-+	off_t		  sc_mediasize;
-+	size_t		  sc_sectorsize;
-+	u_int		  sc_bytes_per_sector;
-+	u_int		  sc_data_per_sector;
-+
-+	/* Only for software cryptography. */
-+	struct bio_queue_head sc_queue;
-+	struct mtx	  sc_queue_mtx;
-+	LIST_HEAD(, g_eli_worker) sc_workers;
-+};
-+#define	sc_name		 sc_geom->name
-+#endif	/* _KERNEL */
-+
-+struct g_eli_metadata {
-+	char		md_magic[16];	/* Magic value. */
-+	uint32_t	md_version;	/* Version number. */
-+	uint32_t	md_flags;	/* Additional flags. */
-+	uint16_t	md_ealgo;	/* Encryption algorithm. */
-+	uint16_t	md_keylen;	/* Key length. */
-+	uint16_t	md_aalgo;	/* Authentication algorithm. */
-+	uint64_t	md_provsize;	/* Provider's size. */
-+	uint32_t	md_sectorsize;	/* Sector size. */
-+	uint8_t		md_keys;	/* Available keys. */
-+	int32_t		md_iterations;	/* Number of iterations for PKCS#5v2. */
-+	uint8_t		md_salt[G_ELI_SALTLEN]; /* Salt. */
-+			/* Encrypted master key (IV-key, Data-key, HMAC). */
-+	uint8_t		md_mkeys[G_ELI_MAXMKEYS * G_ELI_MKEYLEN];
-+	u_char		md_hash[16];	/* MD5 hash. */
-+} __packed;
-+#ifndef _OpenSSL_
-+static __inline void
-+eli_metadata_encode(struct g_eli_metadata *md, u_char *data)
-+{
-+	MD5_CTX ctx;
-+	u_char *p;
-+
-+	p = data;
-+	bcopy(md->md_magic, p, sizeof(md->md_magic)); p += sizeof(md->md_magic);
-+	le32enc(p, md->md_version);	p += sizeof(md->md_version);
-+	le32enc(p, md->md_flags);	p += sizeof(md->md_flags);
-+	le16enc(p, md->md_ealgo);	p += sizeof(md->md_ealgo);
-+	le16enc(p, md->md_keylen);	p += sizeof(md->md_keylen);
-+	le16enc(p, md->md_aalgo);	p += sizeof(md->md_aalgo);
-+	le64enc(p, md->md_provsize);	p += sizeof(md->md_provsize);
-+	le32enc(p, md->md_sectorsize);	p += sizeof(md->md_sectorsize);
-+	*p = md->md_keys;		p += sizeof(md->md_keys);
-+	le32enc(p, md->md_iterations);	p += sizeof(md->md_iterations);
-+	bcopy(md->md_salt, p, sizeof(md->md_salt)); p += sizeof(md->md_salt);
-+	bcopy(md->md_mkeys, p, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
-+	MD5Init(&ctx);
-+	MD5Update(&ctx, data, p - data);
-+	MD5Final(md->md_hash, &ctx);
-+	bcopy(md->md_hash, p, sizeof(md->md_hash));
-+}
-+static __inline int
-+eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
-+{
-+	MD5_CTX ctx;
-+	const u_char *p;
-+
-+	p = data + sizeof(md->md_magic) + sizeof(md->md_version);
-+	md->md_flags = le32dec(p);	p += sizeof(md->md_flags);
-+	md->md_ealgo = le16dec(p);	p += sizeof(md->md_ealgo);
-+	md->md_keylen = le16dec(p);	p += sizeof(md->md_keylen);
-+	md->md_provsize = le64dec(p);	p += sizeof(md->md_provsize);
-+	md->md_sectorsize = le32dec(p);	p += sizeof(md->md_sectorsize);
-+	md->md_keys = *p;		p += sizeof(md->md_keys);
-+	md->md_iterations = le32dec(p);	p += sizeof(md->md_iterations);
-+	bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
-+	bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
-+	MD5Init(&ctx);
-+	MD5Update(&ctx, data, p - data);
-+	MD5Final(md->md_hash, &ctx);
-+	if (bcmp(md->md_hash, p, 16) != 0)
-+		return (EINVAL);
-+	return (0);
-+}
-+
-+static __inline int
-+eli_metadata_decode_v1v2v3v4v5(const u_char *data, struct g_eli_metadata *md)
-+{
-+	MD5_CTX ctx;
-+	const u_char *p;
-+
-+	p = data + sizeof(md->md_magic) + sizeof(md->md_version);
-+	md->md_flags = le32dec(p);	p += sizeof(md->md_flags);
-+	md->md_ealgo = le16dec(p);	p += sizeof(md->md_ealgo);
-+	md->md_keylen = le16dec(p);	p += sizeof(md->md_keylen);
-+	md->md_aalgo = le16dec(p);	p += sizeof(md->md_aalgo);
-+	md->md_provsize = le64dec(p);	p += sizeof(md->md_provsize);
-+	md->md_sectorsize = le32dec(p);	p += sizeof(md->md_sectorsize);
-+	md->md_keys = *p;		p += sizeof(md->md_keys);
-+	md->md_iterations = le32dec(p);	p += sizeof(md->md_iterations);
-+	bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
-+	bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
-+	MD5Init(&ctx);
-+	MD5Update(&ctx, data, p - data);
-+	MD5Final(md->md_hash, &ctx);
-+	if (bcmp(md->md_hash, p, 16) != 0)
-+		return (EINVAL);
-+	return (0);
-+}
-+static __inline int
-+eli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
-+{
-+	int error;
-+
-+	bcopy(data, md->md_magic, sizeof(md->md_magic));
-+	md->md_version = le32dec(data + sizeof(md->md_magic));
-+	switch (md->md_version) {
-+	case 0:
-+		error = eli_metadata_decode_v0(data, md);
-+		break;
-+	case 1:
-+	case 2:
-+	case 3:
-+	case 4:
-+	case 5:
-+		error = eli_metadata_decode_v1v2v3v4v5(data, md);
-+		break;
-+	default:
-+		error = EINVAL;
-+		break;
-+	}
-+	return (error);
-+}
-+#endif	/* !_OpenSSL */
-+
-+static __inline u_int
-+g_eli_str2ealgo(const char *name)
-+{
-+
-+	if (strcasecmp("null", name) == 0)
-+		return (CRYPTO_NULL_CBC);
-+	else if (strcasecmp("null-cbc", name) == 0)
-+		return (CRYPTO_NULL_CBC);
-+	else if (strcasecmp("aes", name) == 0)
-+		return (CRYPTO_AES_XTS);
-+	else if (strcasecmp("aes-cbc", name) == 0)
-+		return (CRYPTO_AES_CBC);
-+	else if (strcasecmp("aes-xts", name) == 0)
-+		return (CRYPTO_AES_XTS);
-+	else if (strcasecmp("blowfish", name) == 0)
-+		return (CRYPTO_BLF_CBC);
-+	else if (strcasecmp("blowfish-cbc", name) == 0)
-+		return (CRYPTO_BLF_CBC);
-+	else if (strcasecmp("camellia", name) == 0)
-+		return (CRYPTO_CAMELLIA_CBC);
-+	else if (strcasecmp("camellia-cbc", name) == 0)
-+		return (CRYPTO_CAMELLIA_CBC);
-+	else if (strcasecmp("3des", name) == 0)
-+		return (CRYPTO_3DES_CBC);
-+	else if (strcasecmp("3des-cbc", name) == 0)
-+		return (CRYPTO_3DES_CBC);
-+	return (CRYPTO_ALGORITHM_MIN - 1);
-+}
-+
-+static __inline u_int
-+g_eli_str2aalgo(const char *name)
-+{
-+
-+	if (strcasecmp("hmac/md5", name) == 0)
-+		return (CRYPTO_MD5_HMAC);
-+	else if (strcasecmp("hmac/sha1", name) == 0)
-+		return (CRYPTO_SHA1_HMAC);
-+	else if (strcasecmp("hmac/ripemd160", name) == 0)
-+		return (CRYPTO_RIPEMD160_HMAC);
-+	else if (strcasecmp("hmac/sha256", name) == 0)
-+		return (CRYPTO_SHA2_256_HMAC);
-+	else if (strcasecmp("hmac/sha384", name) == 0)
-+		return (CRYPTO_SHA2_384_HMAC);
-+	else if (strcasecmp("hmac/sha512", name) == 0)
-+		return (CRYPTO_SHA2_512_HMAC);
-+	return (CRYPTO_ALGORITHM_MIN - 1);
-+}
-+
-+static __inline const char *
-+g_eli_algo2str(u_int algo)
-+{
-+
-+	switch (algo) {
-+	case CRYPTO_NULL_CBC:
-+		return ("NULL");
-+	case CRYPTO_AES_CBC:
-+		return ("AES-CBC");
-+	case CRYPTO_AES_XTS:
-+		return ("AES-XTS");
-+	case CRYPTO_BLF_CBC:
-+		return ("Blowfish-CBC");
-+	case CRYPTO_CAMELLIA_CBC:
-+		return ("CAMELLIA-CBC");
-+	case CRYPTO_3DES_CBC:
-+		return ("3DES-CBC");
-+	case CRYPTO_MD5_HMAC:
-+		return ("HMAC/MD5");
-+	case CRYPTO_SHA1_HMAC:
-+		return ("HMAC/SHA1");
-+	case CRYPTO_RIPEMD160_HMAC:
-+		return ("HMAC/RIPEMD160");
-+	case CRYPTO_SHA2_256_HMAC:
-+		return ("HMAC/SHA256");
-+	case CRYPTO_SHA2_384_HMAC:
-+		return ("HMAC/SHA384");
-+	case CRYPTO_SHA2_512_HMAC:
-+		return ("HMAC/SHA512");
-+	}
-+	return ("unknown");
-+}
-+
-+static __inline void
-+eli_metadata_dump(const struct g_eli_metadata *md)
-+{
-+	static const char hex[] = "0123456789abcdef";
-+	char str[sizeof(md->md_mkeys) * 2 + 1];
-+	u_int i;
-+
-+	printf("     magic: %s\n", md->md_magic);
-+	printf("   version: %u\n", (u_int)md->md_version);
-+	printf("     flags: 0x%x\n", (u_int)md->md_flags);
-+	printf("     ealgo: %s\n", g_eli_algo2str(md->md_ealgo));
-+	printf("    keylen: %u\n", (u_int)md->md_keylen);
-+	if (md->md_flags & G_ELI_FLAG_AUTH)
-+		printf("     aalgo: %s\n", g_eli_algo2str(md->md_aalgo));
-+	printf("  provsize: %ju\n", (uintmax_t)md->md_provsize);
-+	printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
-+	printf("      keys: 0x%02x\n", (u_int)md->md_keys);
-+	printf("iterations: %u\n", (u_int)md->md_iterations);
-+	bzero(str, sizeof(str));
-+	for (i = 0; i < sizeof(md->md_salt); i++) {
-+		str[i * 2] = hex[md->md_salt[i] >> 4];
-+		str[i * 2 + 1] = hex[md->md_salt[i] & 0x0f];
-+	}
-+	printf("      Salt: %s\n", str);
-+	bzero(str, sizeof(str));
-+	for (i = 0; i < sizeof(md->md_mkeys); i++) {
-+		str[i * 2] = hex[md->md_mkeys[i] >> 4];
-+		str[i * 2 + 1] = hex[md->md_mkeys[i] & 0x0f];
-+	}
-+	printf("Master Key: %s\n", str);
-+	bzero(str, sizeof(str));
-+	for (i = 0; i < 16; i++) {
-+		str[i * 2] = hex[md->md_hash[i] >> 4];
-+		str[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
-+	}
-+	printf("  MD5 hash: %s\n", str);
-+}
-+
-+static __inline u_int
-+g_eli_keylen(u_int algo, u_int keylen)
-+{
-+
-+	switch (algo) {
-+	case CRYPTO_NULL_CBC:
-+		if (keylen == 0)
-+			keylen = 64 * 8;
-+		else {
-+			if (keylen > 64 * 8)
-+				keylen = 0;
-+		}
-+		return (keylen);
-+	case CRYPTO_AES_CBC:
-+	case CRYPTO_CAMELLIA_CBC:
-+		switch (keylen) {
-+		case 0:
-+			return (128);
-+		case 128:
-+		case 192:
-+		case 256:
-+			return (keylen);
-+		default:
-+			return (0);
-+		}
-+	case CRYPTO_AES_XTS:
-+		switch (keylen) {
-+		case 0:
-+			return (128);
-+		case 128:
-+		case 256:
-+			return (keylen);
-+		default:
-+			return (0);
-+		}
-+	case CRYPTO_BLF_CBC:
-+		if (keylen == 0)
-+			return (128);
-+		if (keylen < 128 || keylen > 448)
-+			return (0);
-+		if ((keylen % 32) != 0)
-+			return (0);
-+		return (keylen);
-+	case CRYPTO_3DES_CBC:
-+		if (keylen == 0 || keylen == 192)
-+			return (192);
-+		return (0);
-+	default:
-+		return (0);
-+	}
-+}
-+
-+static __inline u_int
-+g_eli_hashlen(u_int algo)
-+{
-+
-+	switch (algo) {
-+	case CRYPTO_MD5_HMAC:
-+		return (16);
-+	case CRYPTO_SHA1_HMAC:
-+		return (20);
-+	case CRYPTO_RIPEMD160_HMAC:
-+		return (20);
-+	case CRYPTO_SHA2_256_HMAC:
-+		return (32);
-+	case CRYPTO_SHA2_384_HMAC:
-+		return (48);
-+	case CRYPTO_SHA2_512_HMAC:
-+		return (64);
-+	}
-+	return (0);
-+}
-+
-+#ifdef _KERNEL
-+int g_eli_read_metadata(struct g_class *mp, struct g_provider *pp,
-+    struct g_eli_metadata *md);
-+struct g_geom *g_eli_create(struct gctl_req *req, struct g_class *mp,
-+    struct g_provider *bpp, const struct g_eli_metadata *md,
-+    const u_char *mkey, int nkey);
-+int g_eli_destroy(struct g_eli_softc *sc, boolean_t force);
-+
-+int g_eli_access(struct g_provider *pp, int dr, int dw, int de);
-+void g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb);
-+
-+void g_eli_read_done(struct bio *bp);
-+void g_eli_write_done(struct bio *bp);
-+int g_eli_crypto_rerun(struct cryptop *crp);
-+uint8_t *g_eli_crypto_key(struct g_eli_softc *sc, off_t offset,
-+    size_t blocksize);
-+void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
-+    size_t size);
-+
-+void g_eli_crypto_read(struct g_eli_softc *sc, struct bio *bp, boolean_t fromworker);
-+void g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp);
-+
-+void g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp);
-+void g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp);
-+#endif
-+
-+void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key);
-+int g_eli_mkey_decrypt(const struct g_eli_metadata *md,
-+    const unsigned char *key, unsigned char *mkey, unsigned *nkeyp);
-+int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
-+    unsigned char *mkey);
-+#ifdef _KERNEL
-+void g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey);
-+#endif
-+
-+int g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
-+    const u_char *key, size_t keysize);
-+int g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
-+    const u_char *key, size_t keysize);
-+
-+struct hmac_ctx {
-+	SHA512_CTX	shactx;
-+	u_char		k_opad[128];
-+};
-+
-+void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
-+    size_t hkeylen);
-+void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
-+    size_t datasize);
-+void g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize);
-+void g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize,
-+    const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize);
-+#endif	/* !_G_ELI_H_ */
---- /dev/null
-+++ b/sys/geom/eli/pkcs5v2.h
-@@ -0,0 +1,36 @@
-+/*-
-+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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 _PKCS5V2_H_
-+#define	_PKCS5V2_H_
-+void pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
-+    size_t saltsize, const char *passphrase, u_int iterations);
-+#ifndef _KERNEL
-+int pkcs5v2_calculate(int usecs);
-+#endif
-+#endif	/* !_PKCS5V2_H_ */
---- /dev/null
-+++ b/sys/geom/eli/g_eli_key.c
-@@ -0,0 +1,293 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#ifdef _KERNEL
-+#include <sys/malloc.h>
-+#include <sys/systm.h>
-+#include <geom/geom.h>
-+#else
-+#include <stdio.h>
-+#include <stdint.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <strings.h>
-+#include <errno.h>
-+#endif
-+
-+#include <geom/eli/g_eli.h>
-+
-+#ifdef _KERNEL
-+MALLOC_DECLARE(M_ELI);
-+#endif
-+
-+/*
-+ * Verify if the given 'key' is correct.
-+ * Return 1 if it is correct and 0 otherwise.
-+ */
-+static int
-+g_eli_mkey_verify(const unsigned char *mkey, const unsigned char *key)
-+{
-+	const unsigned char *odhmac;	/* On-disk HMAC. */
-+	unsigned char chmac[SHA512_MDLEN];	/* Calculated HMAC. */
-+	unsigned char hmkey[SHA512_MDLEN];	/* Key for HMAC. */
-+
-+	/*
-+	 * The key for HMAC calculations is: hmkey = HMAC_SHA512(Derived-Key, 0)
-+	 */
-+	g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x00", 1, hmkey, 0);
-+
-+	odhmac = mkey + G_ELI_DATAIVKEYLEN;
-+
-+	/* Calculate HMAC from Data-Key and IV-Key. */
-+	g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
-+	    chmac, 0);
-+
-+	bzero(hmkey, sizeof(hmkey));
-+
-+	/*
-+	 * Compare calculated HMAC with HMAC from metadata.
-+	 * If two HMACs are equal, 'key' is correct.
-+	 */
-+	return (!bcmp(odhmac, chmac, SHA512_MDLEN));
-+}
-+
-+/*
-+ * Calculate HMAC from Data-Key and IV-Key.
-+ */
-+void
-+g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key)
-+{
-+	unsigned char hmkey[SHA512_MDLEN];	/* Key for HMAC. */
-+	unsigned char *odhmac;	/* On-disk HMAC. */
-+
-+	/*
-+	 * The key for HMAC calculations is: hmkey = HMAC_SHA512(Derived-Key, 0)
-+	 */
-+	g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x00", 1, hmkey, 0);
-+
-+	odhmac = mkey + G_ELI_DATAIVKEYLEN;
-+	/* Calculate HMAC from Data-Key and IV-Key. */
-+	g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
-+	    odhmac, 0);
-+
-+	bzero(hmkey, sizeof(hmkey));
-+}
-+
-+/*
-+ * Find and decrypt Master Key encrypted with 'key'.
-+ * Return decrypted Master Key number in 'nkeyp' if not NULL.
-+ * Return 0 on success, > 0 on failure, -1 on bad key.
-+ */
-+int
-+g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key,
-+    unsigned char *mkey, unsigned *nkeyp)
-+{
-+	unsigned char tmpmkey[G_ELI_MKEYLEN];
-+	unsigned char enckey[SHA512_MDLEN];	/* Key for encryption. */
-+	const unsigned char *mmkey;
-+	int bit, error, nkey;
-+
-+	if (nkeyp != NULL)
-+		*nkeyp = -1;
-+
-+	/*
-+	 * The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
-+	 */
-+	g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
-+
-+	mmkey = md->md_mkeys;
-+	for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) {
-+		bit = (1 << nkey);
-+		if (!(md->md_keys & bit))
-+			continue;
-+		bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
-+		error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
-+		    G_ELI_MKEYLEN, enckey, md->md_keylen);
-+		if (error != 0) {
-+			bzero(tmpmkey, sizeof(tmpmkey));
-+			bzero(enckey, sizeof(enckey));
-+			return (error);
-+		}
-+		if (g_eli_mkey_verify(tmpmkey, key)) {
-+			bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
-+			bzero(tmpmkey, sizeof(tmpmkey));
-+			bzero(enckey, sizeof(enckey));
-+			if (nkeyp != NULL)
-+				*nkeyp = nkey;
-+			return (0);
-+		}
-+	}
-+	bzero(enckey, sizeof(enckey));
-+	bzero(tmpmkey, sizeof(tmpmkey));
-+	return (-1);
-+}
-+
-+/*
-+ * Encrypt the Master-Key and calculate HMAC to be able to verify it in the
-+ * future.
-+ */
-+int
-+g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
-+    unsigned char *mkey)
-+{
-+	unsigned char enckey[SHA512_MDLEN];	/* Key for encryption. */
-+	int error;
-+
-+	/*
-+	 * To calculate HMAC, the whole key (G_ELI_USERKEYLEN bytes long) will
-+	 * be used.
-+	 */
-+	g_eli_mkey_hmac(mkey, key);
-+	/*
-+	 * The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
-+	 */
-+	g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
-+	/*
-+	 * Encrypt the Master-Key and HMAC() result with the given key (this
-+	 * time only 'keylen' bits from the key are used).
-+	 */
-+	error = g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, keylen);
-+
-+	bzero(enckey, sizeof(enckey));
-+
-+	return (error);
-+}
-+
-+#ifdef _KERNEL
-+static void
-+g_eli_ekeys_generate(struct g_eli_softc *sc)
-+{
-+	uint8_t *keys;
-+	u_int kno;
-+	off_t mediasize;
-+	size_t blocksize;
-+	struct {
-+		char magic[4];
-+		uint8_t keyno[8];
-+	} __packed hmacdata;
-+
-+	KASSERT((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) == 0,
-+	    ("%s: G_ELI_FLAG_SINGLE_KEY flag present", __func__));
-+
-+	if ((sc->sc_flags & G_ELI_FLAG_AUTH) != 0) {
-+		struct g_provider *pp;
-+
-+		pp = LIST_FIRST(&sc->sc_geom->consumer)->provider;
-+		mediasize = pp->mediasize;
-+		blocksize = pp->sectorsize;
-+	} else {
-+		mediasize = sc->sc_mediasize;
-+		blocksize = sc->sc_sectorsize;
-+	}
-+	sc->sc_nekeys = ((mediasize - 1) >> G_ELI_KEY_SHIFT) / blocksize + 1;
-+	sc->sc_ekeys =
-+	    malloc(sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN),
-+	    M_ELI, M_WAITOK);
-+	keys = (uint8_t *)(sc->sc_ekeys + sc->sc_nekeys);
-+	bcopy("ekey", hmacdata.magic, 4);
-+	for (kno = 0; kno < sc->sc_nekeys; kno++, keys += G_ELI_DATAKEYLEN) {
-+		sc->sc_ekeys[kno] = keys;
-+		le64enc(hmacdata.keyno, (uint64_t)kno);
-+		g_eli_crypto_hmac(sc->sc_mkey, G_ELI_MAXKEYLEN,
-+		    (uint8_t *)&hmacdata, sizeof(hmacdata),
-+		    sc->sc_ekeys[kno], 0);
-+	}
-+}
-+
-+/*
-+ * When doing encryption only, copy IV key and encryption key.
-+ * When doing encryption and authentication, copy IV key, generate encryption
-+ * key and generate authentication key.
-+ */
-+void
-+g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey)
-+{
-+
-+	/* Remember the Master Key. */
-+	bcopy(mkey, sc->sc_mkey, sizeof(sc->sc_mkey));
-+
-+	bcopy(mkey, sc->sc_ivkey, sizeof(sc->sc_ivkey));
-+	mkey += sizeof(sc->sc_ivkey);
-+
-+	/*
-+	 * The authentication key is: akey = HMAC_SHA512(Master-Key, 0x11)
-+	 */
-+	if ((sc->sc_flags & G_ELI_FLAG_AUTH) != 0) {
-+		g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x11", 1,
-+		    sc->sc_akey, 0);
-+	} else {
-+		arc4rand(sc->sc_akey, sizeof(sc->sc_akey), 0);
-+	}
-+
-+	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) {
-+		sc->sc_nekeys = 1;
-+		sc->sc_ekeys = malloc(sc->sc_nekeys *
-+		    (sizeof(uint8_t *) + G_ELI_DATAKEYLEN), M_ELI, M_WAITOK);
-+		sc->sc_ekeys[0] = (uint8_t *)(sc->sc_ekeys + sc->sc_nekeys);
-+		if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0)
-+			bcopy(mkey, sc->sc_ekeys[0], G_ELI_DATAKEYLEN);
-+		else {
-+			/*
-+			 * The encryption key is: ekey = HMAC_SHA512(Master-Key, 0x10)
-+			 */
-+			g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x10", 1,
-+			    sc->sc_ekeys[0], 0);
-+		}
-+	} else {
-+		/* Generate all encryption keys. */
-+		g_eli_ekeys_generate(sc);
-+	}
-+
-+	if (sc->sc_flags & G_ELI_FLAG_AUTH) {
-+		/*
-+		 * Precalculate SHA256 for HMAC key generation.
-+		 * This is expensive operation and we can do it only once now or
-+		 * for every access to sector, so now will be much better.
-+		 */
-+		SHA256_Init(&sc->sc_akeyctx);
-+		SHA256_Update(&sc->sc_akeyctx, sc->sc_akey,
-+		    sizeof(sc->sc_akey));
-+	}
-+	/*
-+	 * Precalculate SHA256 for IV generation.
-+	 * This is expensive operation and we can do it only once now or for
-+	 * every access to sector, so now will be much better.
-+	 */
-+	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;
-+	}
-+}
-+#endif
---- /dev/null
-+++ b/sys/geom/eli/g_eli_ctl.c
-@@ -0,0 +1,1045 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/module.h>
-+#include <sys/lock.h>
-+#include <sys/mutex.h>
-+#include <sys/bio.h>
-+#include <sys/sysctl.h>
-+#include <sys/malloc.h>
-+#include <sys/kthread.h>
-+#include <sys/proc.h>
-+#include <sys/sched.h>
-+#include <sys/uio.h>
-+
-+#include <vm/uma.h>
-+
-+#include <geom/geom.h>
-+#include <geom/eli/g_eli.h>
-+
-+
-+MALLOC_DECLARE(M_ELI);
-+
-+
-+static void
-+g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_metadata md;
-+	struct g_provider *pp;
-+	const char *name;
-+	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
-+	int *nargs, *detach, *readonly;
-+	int keysize, error;
-+	u_int nkey;
-+
-+	g_topology_assert();
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	if (*nargs != 1) {
-+		gctl_error(req, "Invalid number of arguments.");
-+		return;
-+	}
-+
-+	detach = gctl_get_paraml(req, "detach", sizeof(*detach));
-+	if (detach == NULL) {
-+		gctl_error(req, "No '%s' argument.", "detach");
-+		return;
-+	}
-+
-+	readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
-+	if (readonly == NULL) {
-+		gctl_error(req, "No '%s' argument.", "readonly");
-+		return;
-+	}
-+
-+	name = gctl_get_asciiparam(req, "arg0");
-+	if (name == NULL) {
-+		gctl_error(req, "No 'arg%u' argument.", 0);
-+		return;
-+	}
-+	if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
-+		name += strlen("/dev/");
-+	pp = g_provider_by_name(name);
-+	if (pp == NULL) {
-+		gctl_error(req, "Provider %s is invalid.", name);
-+		return;
-+	}
-+	error = g_eli_read_metadata(mp, pp, &md);
-+	if (error != 0) {
-+		gctl_error(req, "Cannot read metadata from %s (error=%d).",
-+		    name, error);
-+		return;
-+	}
-+	if (md.md_keys == 0x00) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "No valid keys on %s.", pp->name);
-+		return;
-+	}
-+
-+	key = gctl_get_param(req, "key", &keysize);
-+	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "No '%s' argument.", "key");
-+		return;
-+	}
-+
-+	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
-+	bzero(key, keysize);
-+	if (error == -1) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "Wrong key for %s.", pp->name);
-+		return;
-+	} else if (error > 0) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
-+		    pp->name, error);
-+		return;
-+	}
-+	G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
-+
-+	if (*detach && *readonly) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "Options -d and -r are mutually exclusive.");
-+		return;
-+	}
-+	if (*detach)
-+		md.md_flags |= G_ELI_FLAG_WO_DETACH;
-+	if (*readonly)
-+		md.md_flags |= G_ELI_FLAG_RO;
-+	g_eli_create(req, mp, pp, &md, mkey, nkey);
-+	bzero(mkey, sizeof(mkey));
-+	bzero(&md, sizeof(md));
-+}
-+
-+static struct g_eli_softc *
-+g_eli_find_device(struct g_class *mp, const char *prov)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_geom *gp;
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+
-+	if (strncmp(prov, "/dev/", strlen("/dev/")) == 0)
-+		prov += strlen("/dev/");
-+	LIST_FOREACH(gp, &mp->geom, geom) {
-+		sc = gp->softc;
-+		if (sc == NULL)
-+			continue;
-+		pp = LIST_FIRST(&gp->provider);
-+		if (pp != NULL && strcmp(pp->name, prov) == 0)
-+			return (sc);
-+		cp = LIST_FIRST(&gp->consumer);
-+		if (cp != NULL && cp->provider != NULL &&
-+		    strcmp(cp->provider->name, prov) == 0) {
-+			return (sc);
-+		}
-+	}
-+	return (NULL);
-+}
-+
-+static void
-+g_eli_ctl_detach(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_softc *sc;
-+	int *force, *last, *nargs, error;
-+	const char *prov;
-+	char param[16];
-+	int i;
-+
-+	g_topology_assert();
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	if (*nargs <= 0) {
-+		gctl_error(req, "Missing device(s).");
-+		return;
-+	}
-+	force = gctl_get_paraml(req, "force", sizeof(*force));
-+	if (force == NULL) {
-+		gctl_error(req, "No '%s' argument.", "force");
-+		return;
-+	}
-+	last = gctl_get_paraml(req, "last", sizeof(*last));
-+	if (last == NULL) {
-+		gctl_error(req, "No '%s' argument.", "last");
-+		return;
-+	}
-+
-+	for (i = 0; i < *nargs; i++) {
-+		snprintf(param, sizeof(param), "arg%d", i);
-+		prov = gctl_get_asciiparam(req, param);
-+		if (prov == NULL) {
-+			gctl_error(req, "No 'arg%d' argument.", i);
-+			return;
-+		}
-+		sc = g_eli_find_device(mp, prov);
-+		if (sc == NULL) {
-+			gctl_error(req, "No such device: %s.", prov);
-+			return;
-+		}
-+		if (*last) {
-+			sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
-+			sc->sc_geom->access = g_eli_access;
-+		} else {
-+			error = g_eli_destroy(sc, *force ? TRUE : FALSE);
-+			if (error != 0) {
-+				gctl_error(req,
-+				    "Cannot destroy device %s (error=%d).",
-+				    sc->sc_name, error);
-+				return;
-+			}
-+		}
-+	}
-+}
-+
-+static void
-+g_eli_ctl_onetime(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_metadata md;
-+	struct g_provider *pp;
-+	const char *name;
-+	intmax_t *keylen, *sectorsize;
-+	u_char mkey[G_ELI_DATAIVKEYLEN];
-+	int *nargs, *detach;
-+
-+	g_topology_assert();
-+	bzero(&md, sizeof(md));
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	if (*nargs != 1) {
-+		gctl_error(req, "Invalid number of arguments.");
-+		return;
-+	}
-+
-+	detach = gctl_get_paraml(req, "detach", sizeof(*detach));
-+	if (detach == NULL) {
-+		gctl_error(req, "No '%s' argument.", "detach");
-+		return;
-+	}
-+
-+	strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
-+	md.md_version = G_ELI_VERSION;
-+	md.md_flags |= G_ELI_FLAG_ONETIME;
-+	if (*detach)
-+		md.md_flags |= G_ELI_FLAG_WO_DETACH;
-+
-+	md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
-+	name = gctl_get_asciiparam(req, "aalgo");
-+	if (name == NULL) {
-+		gctl_error(req, "No '%s' argument.", "aalgo");
-+		return;
-+	}
-+	if (strcmp(name, "none") != 0) {
-+		md.md_aalgo = g_eli_str2aalgo(name);
-+		if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN &&
-+		    md.md_aalgo <= CRYPTO_ALGORITHM_MAX) {
-+			md.md_flags |= G_ELI_FLAG_AUTH;
-+		} else {
-+			/*
-+			 * For backward compatibility, check if the -a option
-+			 * was used to provide encryption algorithm.
-+			 */
-+			md.md_ealgo = g_eli_str2ealgo(name);
-+			if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
-+			    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
-+				gctl_error(req,
-+				    "Invalid authentication algorithm.");
-+				return;
-+			} else {
-+				gctl_error(req, "warning: The -e option, not "
-+				    "the -a option is now used to specify "
-+				    "encryption algorithm to use.");
-+			}
-+		}
-+	}
-+
-+	if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
-+	    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
-+		name = gctl_get_asciiparam(req, "ealgo");
-+		if (name == NULL) {
-+			gctl_error(req, "No '%s' argument.", "ealgo");
-+			return;
-+		}
-+		md.md_ealgo = g_eli_str2ealgo(name);
-+		if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
-+		    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
-+			gctl_error(req, "Invalid encryption algorithm.");
-+			return;
-+		}
-+	}
-+
-+	keylen = gctl_get_paraml(req, "keylen", sizeof(*keylen));
-+	if (keylen == NULL) {
-+		gctl_error(req, "No '%s' argument.", "keylen");
-+		return;
-+	}
-+	md.md_keylen = g_eli_keylen(md.md_ealgo, *keylen);
-+	if (md.md_keylen == 0) {
-+		gctl_error(req, "Invalid '%s' argument.", "keylen");
-+		return;
-+	}
-+
-+	/* Not important here. */
-+	md.md_provsize = 0;
-+	/* Not important here. */
-+	bzero(md.md_salt, sizeof(md.md_salt));
-+
-+	md.md_keys = 0x01;
-+	arc4rand(mkey, sizeof(mkey), 0);
-+
-+	/* Not important here. */
-+	bzero(md.md_hash, sizeof(md.md_hash));
-+
-+	name = gctl_get_asciiparam(req, "arg0");
-+	if (name == NULL) {
-+		gctl_error(req, "No 'arg%u' argument.", 0);
-+		return;
-+	}
-+	if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
-+		name += strlen("/dev/");
-+	pp = g_provider_by_name(name);
-+	if (pp == NULL) {
-+		gctl_error(req, "Provider %s is invalid.", name);
-+		return;
-+	}
-+
-+	sectorsize = gctl_get_paraml(req, "sectorsize", sizeof(*sectorsize));
-+	if (sectorsize == NULL) {
-+		gctl_error(req, "No '%s' argument.", "sectorsize");
-+		return;
-+	}
-+	if (*sectorsize == 0)
-+		md.md_sectorsize = pp->sectorsize;
-+	else {
-+		if (*sectorsize < 0 || (*sectorsize % pp->sectorsize) != 0) {
-+			gctl_error(req, "Invalid sector size.");
-+			return;
-+		}
-+		if (*sectorsize > PAGE_SIZE) {
-+			gctl_error(req, "warning: Using sectorsize bigger than "
-+			    "the page size!");
-+		}
-+		md.md_sectorsize = *sectorsize;
-+	}
-+
-+	g_eli_create(req, mp, pp, &md, mkey, -1);
-+	bzero(mkey, sizeof(mkey));
-+	bzero(&md, sizeof(md));
-+}
-+
-+static void
-+g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_eli_metadata md;
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+	char param[16];
-+	const char *prov;
-+	u_char *sector;
-+	int *nargs, *boot, *noboot;
-+	int error;
-+	u_int i;
-+
-+	g_topology_assert();
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	if (*nargs <= 0) {
-+		gctl_error(req, "Missing device(s).");
-+		return;
-+	}
-+
-+	boot = gctl_get_paraml(req, "boot", sizeof(*boot));
-+	if (boot == NULL) {
-+		gctl_error(req, "No '%s' argument.", "boot");
-+		return;
-+	}
-+	noboot = gctl_get_paraml(req, "noboot", sizeof(*noboot));
-+	if (noboot == NULL) {
-+		gctl_error(req, "No '%s' argument.", "noboot");
-+		return;
-+	}
-+	if (*boot && *noboot) {
-+		gctl_error(req, "Options -b and -B are mutually exclusive.");
-+		return;
-+	}
-+	if (!*boot && !*noboot) {
-+		gctl_error(req, "No option given.");
-+		return;
-+	}
-+
-+	for (i = 0; i < *nargs; i++) {
-+		snprintf(param, sizeof(param), "arg%d", i);
-+		prov = gctl_get_asciiparam(req, param);
-+		if (prov == NULL) {
-+			gctl_error(req, "No 'arg%d' argument.", i);
-+			return;
-+		}
-+		sc = g_eli_find_device(mp, prov);
-+		if (sc == NULL) {
-+			/*
-+			 * We ignore not attached providers, userland part will
-+			 * take care of them.
-+			 */
-+			G_ELI_DEBUG(1, "Skipping configuration of not attached "
-+			    "provider %s.", prov);
-+			continue;
-+		}
-+		if (*boot && (sc->sc_flags & G_ELI_FLAG_BOOT)) {
-+			G_ELI_DEBUG(1, "BOOT flag already configured for %s.",
-+			    prov);
-+			continue;
-+		} else if (!*boot && !(sc->sc_flags & G_ELI_FLAG_BOOT)) {
-+			G_ELI_DEBUG(1, "BOOT flag not configured for %s.",
-+			    prov);
-+			continue;
-+		}
-+		if (sc->sc_flags & G_ELI_FLAG_RO) {
-+			gctl_error(req, "Cannot change configuration of "
-+			    "read-only provider %s.", prov);
-+			continue;
-+		}
-+		cp = LIST_FIRST(&sc->sc_geom->consumer);
-+		pp = cp->provider;
-+		error = g_eli_read_metadata(mp, pp, &md);
-+		if (error != 0) {
-+			gctl_error(req,
-+			    "Cannot read metadata from %s (error=%d).",
-+			    prov, error);
-+			continue;
-+		}
-+
-+		if (*boot) {
-+			md.md_flags |= G_ELI_FLAG_BOOT;
-+			sc->sc_flags |= G_ELI_FLAG_BOOT;
-+		} else {
-+			md.md_flags &= ~G_ELI_FLAG_BOOT;
-+			sc->sc_flags &= ~G_ELI_FLAG_BOOT;
-+		}
-+
-+		sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
-+		eli_metadata_encode(&md, sector);
-+		error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
-+		    pp->sectorsize);
-+		if (error != 0) {
-+			gctl_error(req,
-+			    "Cannot store metadata on %s (error=%d).",
-+			    prov, error);
-+		}
-+		bzero(&md, sizeof(md));
-+		bzero(sector, sizeof(sector));
-+		free(sector, M_ELI);
-+	}
-+}
-+
-+static void
-+g_eli_ctl_setkey(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_eli_metadata md;
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+	const char *name;
-+	u_char *key, *mkeydst, *sector;
-+	intmax_t *valp;
-+	int keysize, nkey, error;
-+
-+	g_topology_assert();
-+
-+	name = gctl_get_asciiparam(req, "arg0");
-+	if (name == NULL) {
-+		gctl_error(req, "No 'arg%u' argument.", 0);
-+		return;
-+	}
-+	sc = g_eli_find_device(mp, name);
-+	if (sc == NULL) {
-+		gctl_error(req, "Provider %s is invalid.", name);
-+		return;
-+	}
-+	if (sc->sc_flags & G_ELI_FLAG_RO) {
-+		gctl_error(req, "Cannot change keys for read-only provider.");
-+		return;
-+	}
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	pp = cp->provider;
-+
-+	error = g_eli_read_metadata(mp, pp, &md);
-+	if (error != 0) {
-+		gctl_error(req, "Cannot read metadata from %s (error=%d).",
-+		    name, error);
-+		return;
-+	}
-+
-+	valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
-+	if (valp == NULL) {
-+		gctl_error(req, "No '%s' argument.", "keyno");
-+		return;
-+	}
-+	if (*valp != -1)
-+		nkey = *valp;
-+	else
-+		nkey = sc->sc_nkey;
-+	if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
-+		gctl_error(req, "Invalid '%s' argument.", "keyno");
-+		return;
-+	}
-+
-+	valp = gctl_get_paraml(req, "iterations", sizeof(*valp));
-+	if (valp == NULL) {
-+		gctl_error(req, "No '%s' argument.", "iterations");
-+		return;
-+	}
-+	/* Check if iterations number should and can be changed. */
-+	if (*valp != -1) {
-+		if (bitcount32(md.md_keys) != 1) {
-+			gctl_error(req, "To be able to use '-i' option, only "
-+			    "one key can be defined.");
-+			return;
-+		}
-+		if (md.md_keys != (1 << nkey)) {
-+			gctl_error(req, "Only already defined key can be "
-+			    "changed when '-i' option is used.");
-+			return;
-+		}
-+		md.md_iterations = *valp;
-+	}
-+
-+	key = gctl_get_param(req, "key", &keysize);
-+	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "No '%s' argument.", "key");
-+		return;
-+	}
-+
-+	mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
-+	md.md_keys |= (1 << nkey);
-+
-+	bcopy(sc->sc_mkey, mkeydst, sizeof(sc->sc_mkey));
-+
-+	/* Encrypt Master Key with the new key. */
-+	error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
-+	bzero(key, sizeof(key));
-+	if (error != 0) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
-+		return;
-+	}
-+
-+	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
-+	/* Store metadata with fresh key. */
-+	eli_metadata_encode(&md, sector);
-+	bzero(&md, sizeof(md));
-+	error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
-+	    pp->sectorsize);
-+	bzero(sector, sizeof(sector));
-+	free(sector, M_ELI);
-+	if (error != 0) {
-+		gctl_error(req, "Cannot store metadata on %s (error=%d).",
-+		    pp->name, error);
-+		return;
-+	}
-+	G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
-+}
-+
-+static void
-+g_eli_ctl_delkey(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_eli_metadata md;
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+	const char *name;
-+	u_char *mkeydst, *sector;
-+	intmax_t *valp;
-+	size_t keysize;
-+	int error, nkey, *all, *force;
-+	u_int i;
-+
-+	g_topology_assert();
-+
-+	nkey = 0;	/* fixes causeless gcc warning */
-+
-+	name = gctl_get_asciiparam(req, "arg0");
-+	if (name == NULL) {
-+		gctl_error(req, "No 'arg%u' argument.", 0);
-+		return;
-+	}
-+	sc = g_eli_find_device(mp, name);
-+	if (sc == NULL) {
-+		gctl_error(req, "Provider %s is invalid.", name);
-+		return;
-+	}
-+	if (sc->sc_flags & G_ELI_FLAG_RO) {
-+		gctl_error(req, "Cannot delete keys for read-only provider.");
-+		return;
-+	}
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	pp = cp->provider;
-+
-+	error = g_eli_read_metadata(mp, pp, &md);
-+	if (error != 0) {
-+		gctl_error(req, "Cannot read metadata from %s (error=%d).",
-+		    name, error);
-+		return;
-+	}
-+
-+	all = gctl_get_paraml(req, "all", sizeof(*all));
-+	if (all == NULL) {
-+		gctl_error(req, "No '%s' argument.", "all");
-+		return;
-+	}
-+
-+	if (*all) {
-+		mkeydst = md.md_mkeys;
-+		keysize = sizeof(md.md_mkeys);
-+	} else {
-+		force = gctl_get_paraml(req, "force", sizeof(*force));
-+		if (force == NULL) {
-+			gctl_error(req, "No '%s' argument.", "force");
-+			return;
-+		}
-+
-+		valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
-+		if (valp == NULL) {
-+			gctl_error(req, "No '%s' argument.", "keyno");
-+			return;
-+		}
-+		if (*valp != -1)
-+			nkey = *valp;
-+		else
-+			nkey = sc->sc_nkey;
-+		if (nkey < 0 || nkey >= G_ELI_MAXMKEYS) {
-+			gctl_error(req, "Invalid '%s' argument.", "keyno");
-+			return;
-+		}
-+		if (!(md.md_keys & (1 << nkey)) && !*force) {
-+			gctl_error(req, "Master Key %u is not set.", nkey);
-+			return;
-+		}
-+		md.md_keys &= ~(1 << nkey);
-+		if (md.md_keys == 0 && !*force) {
-+			gctl_error(req, "This is the last Master Key. Use '-f' "
-+			    "flag if you really want to remove it.");
-+			return;
-+		}
-+		mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
-+		keysize = G_ELI_MKEYLEN;
-+	}
-+
-+	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
-+	for (i = 0; i <= g_eli_overwrites; i++) {
-+		if (i == g_eli_overwrites)
-+			bzero(mkeydst, keysize);
-+		else
-+			arc4rand(mkeydst, keysize, 0);
-+		/* Store metadata with destroyed key. */
-+		eli_metadata_encode(&md, sector);
-+		error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
-+		    pp->sectorsize);
-+		if (error != 0) {
-+			G_ELI_DEBUG(0, "Cannot store metadata on %s "
-+			    "(error=%d).", pp->name, error);
-+		}
-+		/*
-+		 * Flush write cache so we don't overwrite data N times in cache
-+		 * and only once on disk.
-+		 */
-+		(void)g_io_flush(cp);
-+	}
-+	bzero(&md, sizeof(md));
-+	bzero(sector, sizeof(sector));
-+	free(sector, M_ELI);
-+	if (*all)
-+		G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
-+	else
-+		G_ELI_DEBUG(1, "Key %d removed from %s.", nkey, pp->name);
-+}
-+
-+static void
-+g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_req *req)
-+{
-+	struct g_eli_worker *wr;
-+
-+	g_topology_assert();
-+
-+	KASSERT(sc != NULL, ("NULL sc"));
-+
-+	if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
-+		gctl_error(req,
-+		    "Device %s is using one-time key, suspend not supported.",
-+		    sc->sc_name);
-+		return;
-+	}
-+
-+	mtx_lock(&sc->sc_queue_mtx);
-+	if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
-+		mtx_unlock(&sc->sc_queue_mtx);
-+		gctl_error(req, "Device %s already suspended.",
-+		    sc->sc_name);
-+		return;
-+	}
-+	sc->sc_flags |= G_ELI_FLAG_SUSPEND;
-+	wakeup(sc);
-+	for (;;) {
-+		LIST_FOREACH(wr, &sc->sc_workers, w_next) {
-+			if (wr->w_active)
-+				break;
-+		}
-+		if (wr == NULL)
-+			break;
-+		/* Not all threads suspended. */
-+		msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
-+		    "geli:suspend", 0);
-+	}
-+	/*
-+	 * Clear sensitive data on suspend, they will be recovered on resume.
-+	 */
-+	bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
-+	bzero(sc->sc_ekeys,
-+	    sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN));
-+	free(sc->sc_ekeys, M_ELI);
-+	sc->sc_ekeys = NULL;
-+	bzero(sc->sc_akey, sizeof(sc->sc_akey));
-+	bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
-+	bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
-+	bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
-+	mtx_unlock(&sc->sc_queue_mtx);
-+	G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
-+}
-+
-+static void
-+g_eli_ctl_suspend(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_softc *sc;
-+	int *all, *nargs;
-+
-+	g_topology_assert();
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	all = gctl_get_paraml(req, "all", sizeof(*all));
-+	if (all == NULL) {
-+		gctl_error(req, "No '%s' argument.", "all");
-+		return;
-+	}
-+	if (!*all && *nargs == 0) {
-+		gctl_error(req, "Too few arguments.");
-+		return;
-+	}
-+
-+	if (*all) {
-+		struct g_geom *gp, *gp2;
-+
-+		LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
-+			sc = gp->softc;
-+			if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
-+				G_ELI_DEBUG(0,
-+				    "Device %s is using one-time key, suspend not supported, skipping.",
-+				    sc->sc_name);
-+				continue;
-+			}
-+			g_eli_suspend_one(sc, req);
-+		}
-+	} else {
-+		const char *prov;
-+		char param[16];
-+		int i;
-+
-+		for (i = 0; i < *nargs; i++) {
-+			snprintf(param, sizeof(param), "arg%d", i);
-+			prov = gctl_get_asciiparam(req, param);
-+			if (prov == NULL) {
-+				G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
-+				continue;
-+			}
-+
-+			sc = g_eli_find_device(mp, prov);
-+			if (sc == NULL) {
-+				G_ELI_DEBUG(0, "No such provider: %s.", prov);
-+				continue;
-+			}
-+			g_eli_suspend_one(sc, req);
-+		}
-+	}
-+}
-+
-+static void
-+g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
-+{
-+	struct g_eli_metadata md;
-+	struct g_eli_softc *sc;
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+	const char *name;
-+	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
-+	int *nargs, keysize, error;
-+	u_int nkey;
-+
-+	g_topology_assert();
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	if (*nargs != 1) {
-+		gctl_error(req, "Invalid number of arguments.");
-+		return;
-+	}
-+
-+	name = gctl_get_asciiparam(req, "arg0");
-+	if (name == NULL) {
-+		gctl_error(req, "No 'arg%u' argument.", 0);
-+		return;
-+	}
-+	sc = g_eli_find_device(mp, name);
-+	if (sc == NULL) {
-+		gctl_error(req, "Provider %s is invalid.", name);
-+		return;
-+	}
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	pp = cp->provider;
-+	error = g_eli_read_metadata(mp, pp, &md);
-+	if (error != 0) {
-+		gctl_error(req, "Cannot read metadata from %s (error=%d).",
-+		    name, error);
-+		return;
-+	}
-+	if (md.md_keys == 0x00) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "No valid keys on %s.", pp->name);
-+		return;
-+	}
-+
-+	key = gctl_get_param(req, "key", &keysize);
-+	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "No '%s' argument.", "key");
-+		return;
-+	}
-+
-+	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
-+	bzero(key, keysize);
-+	if (error == -1) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "Wrong key for %s.", pp->name);
-+		return;
-+	} else if (error > 0) {
-+		bzero(&md, sizeof(md));
-+		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
-+		    pp->name, error);
-+		return;
-+	}
-+	G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
-+
-+	mtx_lock(&sc->sc_queue_mtx);
-+	if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
-+		gctl_error(req, "Device %s is not suspended.", name);
-+	else {
-+		/* Restore sc_mkey, sc_ekeys, sc_akey and sc_ivkey. */
-+		g_eli_mkey_propagate(sc, mkey);
-+		sc->sc_flags &= ~G_ELI_FLAG_SUSPEND;
-+		G_ELI_DEBUG(1, "Resumed %s.", pp->name);
-+		wakeup(sc);
-+	}
-+	mtx_unlock(&sc->sc_queue_mtx);
-+	bzero(mkey, sizeof(mkey));
-+	bzero(&md, sizeof(md));
-+}
-+
-+static int
-+g_eli_kill_one(struct g_eli_softc *sc)
-+{
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+	int error = 0;
-+
-+	g_topology_assert();
-+
-+	if (sc == NULL)
-+		return (ENOENT);
-+
-+	pp = LIST_FIRST(&sc->sc_geom->provider);
-+	g_error_provider(pp, ENXIO);
-+
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	pp = cp->provider;
-+
-+	if (sc->sc_flags & G_ELI_FLAG_RO) {
-+		G_ELI_DEBUG(0, "WARNING: Metadata won't be erased on read-only "
-+		    "provider: %s.", pp->name);
-+	} else {
-+		u_char *sector;
-+		u_int i;
-+		int err;
-+
-+		sector = malloc(pp->sectorsize, M_ELI, M_WAITOK);
-+		for (i = 0; i <= g_eli_overwrites; i++) {
-+			if (i == g_eli_overwrites)
-+				bzero(sector, pp->sectorsize);
-+			else
-+				arc4rand(sector, pp->sectorsize, 0);
-+			err = g_write_data(cp, pp->mediasize - pp->sectorsize,
-+			    sector, pp->sectorsize);
-+			if (err != 0) {
-+				G_ELI_DEBUG(0, "Cannot erase metadata on %s "
-+				    "(error=%d).", pp->name, err);
-+				if (error == 0)
-+					error = err;
-+			}
-+			/*
-+			 * Flush write cache so we don't overwrite data N times
-+			 * in cache and only once on disk.
-+			 */
-+			(void)g_io_flush(cp);
-+		}
-+		free(sector, M_ELI);
-+	}
-+	if (error == 0)
-+		G_ELI_DEBUG(0, "%s has been killed.", pp->name);
-+	g_eli_destroy(sc, TRUE);
-+	return (error);
-+}
-+
-+static void
-+g_eli_ctl_kill(struct gctl_req *req, struct g_class *mp)
-+{
-+	int *all, *nargs;
-+	int error;
-+
-+	g_topology_assert();
-+
-+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
-+	if (nargs == NULL) {
-+		gctl_error(req, "No '%s' argument.", "nargs");
-+		return;
-+	}
-+	all = gctl_get_paraml(req, "all", sizeof(*all));
-+	if (all == NULL) {
-+		gctl_error(req, "No '%s' argument.", "all");
-+		return;
-+	}
-+	if (!*all && *nargs == 0) {
-+		gctl_error(req, "Too few arguments.");
-+		return;
-+	}
-+
-+	if (*all) {
-+		struct g_geom *gp, *gp2;
-+
-+		LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
-+			error = g_eli_kill_one(gp->softc);
-+			if (error != 0)
-+				gctl_error(req, "Not fully done.");
-+		}
-+	} else {
-+		struct g_eli_softc *sc;
-+		const char *prov;
-+		char param[16];
-+		int i;
-+
-+		for (i = 0; i < *nargs; i++) {
-+			snprintf(param, sizeof(param), "arg%d", i);
-+			prov = gctl_get_asciiparam(req, param);
-+			if (prov == NULL) {
-+				G_ELI_DEBUG(0, "No 'arg%d' argument.", i);
-+				continue;
-+			}
-+
-+			sc = g_eli_find_device(mp, prov);
-+			if (sc == NULL) {
-+				G_ELI_DEBUG(0, "No such provider: %s.", prov);
-+				continue;
-+			}
-+			error = g_eli_kill_one(sc);
-+			if (error != 0)
-+				gctl_error(req, "Not fully done.");
-+		}
-+	}
-+}
-+
-+void
-+g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
-+{
-+	uint32_t *version;
-+
-+	g_topology_assert();
-+
-+	version = gctl_get_paraml(req, "version", sizeof(*version));
-+	if (version == NULL) {
-+		gctl_error(req, "No '%s' argument.", "version");
-+		return;
-+	}
-+	if (*version != G_ELI_VERSION) {
-+		gctl_error(req, "Userland and kernel parts are out of sync.");
-+		return;
-+	}
-+
-+	if (strcmp(verb, "attach") == 0)
-+		g_eli_ctl_attach(req, mp);
-+	else if (strcmp(verb, "detach") == 0 || strcmp(verb, "stop") == 0)
-+		g_eli_ctl_detach(req, mp);
-+	else if (strcmp(verb, "onetime") == 0)
-+		g_eli_ctl_onetime(req, mp);
-+	else if (strcmp(verb, "configure") == 0)
-+		g_eli_ctl_configure(req, mp);
-+	else if (strcmp(verb, "setkey") == 0)
-+		g_eli_ctl_setkey(req, mp);
-+	else if (strcmp(verb, "delkey") == 0)
-+		g_eli_ctl_delkey(req, mp);
-+	else if (strcmp(verb, "suspend") == 0)
-+		g_eli_ctl_suspend(req, mp);
-+	else if (strcmp(verb, "resume") == 0)
-+		g_eli_ctl_resume(req, mp);
-+	else if (strcmp(verb, "kill") == 0)
-+		g_eli_ctl_kill(req, mp);
-+	else
-+		gctl_error(req, "Unknown verb.");
-+}
---- /dev/null
-+++ b/sys/geom/eli/pkcs5v2.c
-@@ -0,0 +1,123 @@
-+/*-
-+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#ifdef _KERNEL
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#else
-+#include <sys/resource.h>
-+#include <stdint.h>
-+#include <strings.h>
-+#endif
-+
-+#include <geom/eli/g_eli.h>
-+#include <geom/eli/pkcs5v2.h>
-+
-+static __inline void
-+xor(uint8_t *dst, const uint8_t *src, size_t size)
-+{
-+
-+	for (; size > 0; size--)
-+		*dst++ ^= *src++;
-+}
-+
-+void
-+pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
-+    size_t saltsize, const char *passphrase, u_int iterations)
-+{
-+	uint8_t md[SHA512_MDLEN], saltcount[saltsize + sizeof(uint32_t)];
-+	uint8_t *counter, *keyp;
-+	u_int i, bsize, passlen;
-+	uint32_t count;
-+
-+	passlen = strlen(passphrase);
-+	bzero(key, keylen);
-+	bcopy(salt, saltcount, saltsize);
-+	counter = saltcount + saltsize;
-+
-+	keyp = key;
-+	for (count = 1; keylen > 0; count++, keylen -= bsize, keyp += bsize) {
-+		bsize = MIN(keylen, sizeof(md));
-+
-+		counter[0] = (count >> 24) & 0xff;
-+		counter[1] = (count >> 16) & 0xff;
-+		counter[2] = (count >> 8) & 0xff;
-+		counter[3] = count & 0xff;
-+		g_eli_crypto_hmac(passphrase, passlen, saltcount,
-+		    sizeof(saltcount), md, 0);
-+		xor(keyp, md, bsize);
-+
-+		for(i = 1; i < iterations; i++) {
-+			g_eli_crypto_hmac(passphrase, passlen, md, sizeof(md),
-+			    md, 0);
-+			xor(keyp, md, bsize);
-+		}
-+	}
-+}
-+
-+#ifndef _KERNEL
-+/*
-+ * Return the number of microseconds needed for 'interations' iterations.
-+ */
-+static int
-+pkcs5v2_probe(int iterations)
-+{
-+	uint8_t	key[G_ELI_USERKEYLEN], salt[G_ELI_SALTLEN];
-+	uint8_t passphrase[] = "passphrase";
-+	struct rusage start, end;
-+	int usecs;
-+
-+	getrusage(RUSAGE_SELF, &start);
-+	pkcs5v2_genkey(key, sizeof(key), salt, sizeof(salt), passphrase,
-+	    iterations);
-+	getrusage(RUSAGE_SELF, &end);
-+
-+	usecs = end.ru_utime.tv_sec - start.ru_utime.tv_sec;
-+	usecs *= 1000000;
-+	usecs += end.ru_utime.tv_usec - start.ru_utime.tv_usec;
-+	return (usecs);
-+}
-+
-+/*
-+ * Return the number of iterations which takes 'usecs' microseconds.
-+ */
-+int
-+pkcs5v2_calculate(int usecs)
-+{
-+	int iterations, v;
-+
-+	for (iterations = 1; ; iterations <<= 1) {
-+		v = pkcs5v2_probe(iterations);
-+		if (v > 2000000)
-+			break;
-+	}
-+	return (((intmax_t)iterations * (intmax_t)usecs) / v);
-+}
-+#endif	/* !_KERNEL */
---- /dev/null
-+++ b/sys/geom/eli/g_eli_integrity.c
-@@ -0,0 +1,540 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/linker.h>
-+#include <sys/module.h>
-+#include <sys/lock.h>
-+#include <sys/mutex.h>
-+#include <sys/bio.h>
-+#include <sys/sysctl.h>
-+#include <sys/malloc.h>
-+#include <sys/kthread.h>
-+#include <sys/proc.h>
-+#include <sys/sched.h>
-+#include <sys/smp.h>
-+#include <sys/uio.h>
-+#include <sys/vnode.h>
-+
-+#include <vm/uma.h>
-+
-+#include <geom/geom.h>
-+#include <geom/eli/g_eli.h>
-+#include <geom/eli/pkcs5v2.h>
-+
-+/*
-+ * The data layout description when integrity verification is configured.
-+ *
-+ * One of the most important assumption here is that authenticated data and its
-+ * HMAC has to be stored in the same place (namely in the same sector) to make
-+ * it work reliable.
-+ * The problem is that file systems work only with sectors that are multiple of
-+ * 512 bytes and a power of two number.
-+ * My idea to implement it is as follows.
-+ * Let's store HMAC in sector. This is a must. This leaves us 480 bytes for
-+ * data. We can't use that directly (ie. we can't create provider with 480 bytes
-+ * sector size). We need another sector from where we take only 32 bytes of data
-+ * and we store HMAC of this data as well. This takes two sectors from the
-+ * original provider at the input and leaves us one sector of authenticated data
-+ * at the output. Not very efficient, but you got the idea.
-+ * Now, let's assume, we want to create provider with 4096 bytes sector.
-+ * To output 4096 bytes of authenticated data we need 8x480 plus 1x256, so we
-+ * need nine 512-bytes sectors at the input to get one 4096-bytes sector at the
-+ * output. That's better. With 4096 bytes sector we can use 89% of size of the
-+ * original provider. I find it as an acceptable cost.
-+ * The reliability comes from the fact, that every HMAC stored inside the sector
-+ * is calculated only for the data in the same sector, so its impossible to
-+ * write new data and leave old HMAC or vice versa.
-+ *
-+ * And here is the picture:
-+ *
-+ * da0: +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+-----+
-+ *      |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |256b |
-+ *      |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data |
-+ *      +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+-----+
-+ *      |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |288 bytes |
-+ *      +---------+ +---------+ +---------+ +---------+ +---------+ +---------+ +---------+ +---------+ |224 unused|
-+ *                                                                                                      +----------+
-+ * da0.eli: +----+----+----+----+----+----+----+----+----+
-+ *          |480b|480b|480b|480b|480b|480b|480b|480b|256b|
-+ *          +----+----+----+----+----+----+----+----+----+
-+ *          |                 4096 bytes                 |
-+ *          +--------------------------------------------+
-+ *
-+ * PS. You can use any sector size with geli(8). My example is using 4kB,
-+ *     because it's most efficient. For 8kB sectors you need 2 extra sectors,
-+ *     so the cost is the same as for 4kB sectors.
-+ */
-+
-+/*
-+ * Code paths:
-+ * BIO_READ:
-+ *	g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> g_eli_auth_run -> g_eli_auth_read_done -> g_io_deliver
-+ * BIO_WRITE:
-+ *	g_eli_start -> g_eli_auth_run -> g_eli_auth_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+
-+MALLOC_DECLARE(M_ELI);
-+
-+/*
-+ * Here we generate key for HMAC. Every sector has its own HMAC key, so it is
-+ * not possible to copy sectors.
-+ * We cannot depend on fact, that every sector has its own IV, because different
-+ * IV doesn't change HMAC, when we use encrypt-then-authenticate method.
-+ */
-+static void
-+g_eli_auth_keygen(struct g_eli_softc *sc, off_t offset, u_char *key)
-+{
-+	SHA256_CTX ctx;
-+
-+	/* Copy precalculated SHA256 context. */
-+	bcopy(&sc->sc_akeyctx, &ctx, sizeof(ctx));
-+	SHA256_Update(&ctx, (uint8_t *)&offset, sizeof(offset));
-+	SHA256_Final(key, &ctx);
-+}
-+
-+/*
-+ * The function is called after we read and decrypt data.
-+ *
-+ * g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> g_eli_auth_run -> G_ELI_AUTH_READ_DONE -> g_io_deliver
-+ */
-+static int
-+g_eli_auth_read_done(struct cryptop *crp)
-+{
-+	struct g_eli_softc *sc;
-+	struct bio *bp;
-+
-+	if (crp->crp_etype == EAGAIN) {
-+		if (g_eli_crypto_rerun(crp) == 0)
-+			return (0);
-+	}
-+	bp = (struct bio *)crp->crp_opaque;
-+	bp->bio_inbed++;
-+	if (crp->crp_etype == 0) {
-+		bp->bio_completed += crp->crp_olen;
-+		G_ELI_DEBUG(3, "Crypto READ request done (%d/%d) (add=%jd completed=%jd).",
-+		    bp->bio_inbed, bp->bio_children, (intmax_t)crp->crp_olen, (intmax_t)bp->bio_completed);
-+	} else {
-+		G_ELI_DEBUG(1, "Crypto READ request failed (%d/%d) error=%d.",
-+		    bp->bio_inbed, bp->bio_children, crp->crp_etype);
-+		if (bp->bio_error == 0)
-+			bp->bio_error = crp->crp_etype;
-+	}
-+	/*
-+	 * Do we have all sectors already?
-+	 */
-+	if (bp->bio_inbed < bp->bio_children)
-+		return (0);
-+	sc = bp->bio_to->geom->softc;
-+	if (bp->bio_error == 0) {
-+		u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
-+		u_char *srcdata, *dstdata, *auth;
-+		off_t coroff, corsize;
-+
-+		/*
-+		 * Verify data integrity based on calculated and read HMACs.
-+		 */
-+		/* Sectorsize of decrypted provider eg. 4096. */
-+		decr_secsize = bp->bio_to->sectorsize;
-+		/* The real sectorsize of encrypted provider, eg. 512. */
-+		encr_secsize = LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize;
-+		/* Number of data bytes in one encrypted sector, eg. 480. */
-+		data_secsize = sc->sc_data_per_sector;
-+		/* Number of sectors from decrypted provider, eg. 2. */
-+		nsec = bp->bio_length / decr_secsize;
-+		/* Number of sectors from encrypted provider, eg. 18. */
-+		nsec = (nsec * sc->sc_bytes_per_sector) / encr_secsize;
-+		/* Last sector number in every big sector, eg. 9. */
-+		lsec = sc->sc_bytes_per_sector / encr_secsize;
-+
-+		srcdata = bp->bio_driver2;
-+		dstdata = bp->bio_data;
-+		auth = srcdata + encr_secsize * nsec;
-+		coroff = -1;
-+		corsize = 0;
-+
-+		for (i = 1; i <= nsec; i++) {
-+			data_secsize = sc->sc_data_per_sector;
-+			if ((i % lsec) == 0)
-+				data_secsize = decr_secsize % data_secsize;
-+			if (bcmp(srcdata, auth, sc->sc_alen) != 0) {
-+				/*
-+				 * Curruption detected, remember the offset if
-+				 * this is the first corrupted sector and
-+				 * increase size.
-+				 */
-+				if (bp->bio_error == 0)
-+					bp->bio_error = -1;
-+				if (coroff == -1) {
-+					coroff = bp->bio_offset +
-+					    (dstdata - (u_char *)bp->bio_data);
-+				}
-+				corsize += data_secsize;
-+			} else {
-+				/*
-+				 * No curruption, good.
-+				 * Report previous corruption if there was one.
-+				 */
-+				if (coroff != -1) {
-+					G_ELI_DEBUG(0, "%s: %jd bytes "
-+					    "corrupted at offset %jd.",
-+					    sc->sc_name, (intmax_t)corsize,
-+					    (intmax_t)coroff);
-+					coroff = -1;
-+					corsize = 0;
-+				}
-+				bcopy(srcdata + sc->sc_alen, dstdata,
-+				    data_secsize);
-+			}
-+			srcdata += encr_secsize;
-+			dstdata += data_secsize;
-+			auth += sc->sc_alen;
-+		}
-+		/* Report previous corruption if there was one. */
-+		if (coroff != -1) {
-+			G_ELI_DEBUG(0, "%s: %jd bytes corrupted at offset %jd.",
-+			    sc->sc_name, (intmax_t)corsize, (intmax_t)coroff);
-+		}
-+	}
-+	free(bp->bio_driver2, M_ELI);
-+	bp->bio_driver2 = NULL;
-+	if (bp->bio_error != 0) {
-+		if (bp->bio_error == -1)
-+			bp->bio_error = EINVAL;
-+		else {
-+			G_ELI_LOGREQ(0, bp,
-+			    "Crypto READ request failed (error=%d).",
-+			    bp->bio_error);
-+		}
-+		bp->bio_completed = 0;
-+	}
-+	/*
-+	 * Read is finished, send it up.
-+	 */
-+	g_io_deliver(bp, bp->bio_error);
-+	atomic_subtract_int(&sc->sc_inflight, 1);
-+	return (0);
-+}
-+
-+/*
-+ * The function is called after data encryption.
-+ *
-+ * g_eli_start -> g_eli_auth_run -> G_ELI_AUTH_WRITE_DONE -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+static int
-+g_eli_auth_write_done(struct cryptop *crp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_consumer *cp;
-+	struct bio *bp, *cbp, *cbp2;
-+	u_int nsec;
-+
-+	if (crp->crp_etype == EAGAIN) {
-+		if (g_eli_crypto_rerun(crp) == 0)
-+			return (0);
-+	}
-+	bp = (struct bio *)crp->crp_opaque;
-+	bp->bio_inbed++;
-+	if (crp->crp_etype == 0) {
-+		G_ELI_DEBUG(3, "Crypto WRITE request done (%d/%d).",
-+		    bp->bio_inbed, bp->bio_children);
-+	} else {
-+		G_ELI_DEBUG(1, "Crypto WRITE request failed (%d/%d) error=%d.",
-+		    bp->bio_inbed, bp->bio_children, crp->crp_etype);
-+		if (bp->bio_error == 0)
-+			bp->bio_error = crp->crp_etype;
-+	}
-+	/*
-+	 * All sectors are already encrypted?
-+	 */
-+	if (bp->bio_inbed < bp->bio_children)
-+		return (0);
-+	sc = bp->bio_to->geom->softc;
-+	if (bp->bio_error != 0) {
-+		G_ELI_LOGREQ(0, bp, "Crypto WRITE request failed (error=%d).",
-+		    bp->bio_error);
-+		free(bp->bio_driver2, M_ELI);
-+		bp->bio_driver2 = NULL;
-+		cbp = bp->bio_driver1;
-+		bp->bio_driver1 = NULL;
-+		g_destroy_bio(cbp);
-+		g_io_deliver(bp, bp->bio_error);
-+		atomic_subtract_int(&sc->sc_inflight, 1);
-+		return (0);
-+	}
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	cbp = bp->bio_driver1;
-+	bp->bio_driver1 = NULL;
-+	cbp->bio_to = cp->provider;
-+	cbp->bio_done = g_eli_write_done;
-+
-+	/* Number of sectors from decrypted provider, eg. 1. */
-+	nsec = bp->bio_length / bp->bio_to->sectorsize;
-+	/* Number of sectors from encrypted provider, eg. 9. */
-+	nsec = (nsec * sc->sc_bytes_per_sector) / cp->provider->sectorsize;
-+
-+	cbp->bio_length = cp->provider->sectorsize * nsec;
-+	cbp->bio_offset = (bp->bio_offset / bp->bio_to->sectorsize) * sc->sc_bytes_per_sector;
-+	cbp->bio_data = bp->bio_driver2;
-+
-+	/*
-+	 * We write more than what is requested, so we have to be ready to write
-+	 * more than MAXPHYS.
-+	 */
-+	cbp2 = NULL;
-+	if (cbp->bio_length > MAXPHYS) {
-+		cbp2 = g_duplicate_bio(bp);
-+		cbp2->bio_length = cbp->bio_length - MAXPHYS;
-+		cbp2->bio_data = cbp->bio_data + MAXPHYS;
-+		cbp2->bio_offset = cbp->bio_offset + MAXPHYS;
-+		cbp2->bio_to = cp->provider;
-+		cbp2->bio_done = g_eli_write_done;
-+		cbp->bio_length = MAXPHYS;
-+	}
-+	/*
-+	 * Send encrypted data to the provider.
-+	 */
-+	G_ELI_LOGREQ(2, cbp, "Sending request.");
-+	bp->bio_inbed = 0;
-+	bp->bio_children = (cbp2 != NULL ? 2 : 1);
-+	g_io_request(cbp, cp);
-+	if (cbp2 != NULL) {
-+		G_ELI_LOGREQ(2, cbp2, "Sending request.");
-+		g_io_request(cbp2, cp);
-+	}
-+	return (0);
-+}
-+
-+void
-+g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp)
-+{
-+	struct g_consumer *cp;
-+	struct bio *cbp, *cbp2;
-+	size_t size;
-+	off_t nsec;
-+
-+	bp->bio_pflags = 0;
-+
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	cbp = bp->bio_driver1;
-+	bp->bio_driver1 = NULL;
-+	cbp->bio_to = cp->provider;
-+	cbp->bio_done = g_eli_read_done;
-+
-+	/* Number of sectors from decrypted provider, eg. 1. */
-+	nsec = bp->bio_length / bp->bio_to->sectorsize;
-+	/* Number of sectors from encrypted provider, eg. 9. */
-+	nsec = (nsec * sc->sc_bytes_per_sector) / cp->provider->sectorsize;
-+
-+	cbp->bio_length = cp->provider->sectorsize * nsec;
-+	size = cbp->bio_length;
-+	size += sc->sc_alen * nsec;
-+	size += sizeof(struct cryptop) * nsec;
-+	size += sizeof(struct cryptodesc) * nsec * 2;
-+	size += G_ELI_AUTH_SECKEYLEN * nsec;
-+	size += sizeof(struct uio) * nsec;
-+	size += sizeof(struct iovec) * nsec;
-+	cbp->bio_offset = (bp->bio_offset / bp->bio_to->sectorsize) * sc->sc_bytes_per_sector;
-+	bp->bio_driver2 = malloc(size, M_ELI, M_WAITOK);
-+	cbp->bio_data = bp->bio_driver2;
-+
-+	/*
-+	 * We read more than what is requested, so we have to be ready to read
-+	 * more than MAXPHYS.
-+	 */
-+	cbp2 = NULL;
-+	if (cbp->bio_length > MAXPHYS) {
-+		cbp2 = g_duplicate_bio(bp);
-+		cbp2->bio_length = cbp->bio_length - MAXPHYS;
-+		cbp2->bio_data = cbp->bio_data + MAXPHYS;
-+		cbp2->bio_offset = cbp->bio_offset + MAXPHYS;
-+		cbp2->bio_to = cp->provider;
-+		cbp2->bio_done = g_eli_read_done;
-+		cbp->bio_length = MAXPHYS;
-+	}
-+	/*
-+	 * Read encrypted data from provider.
-+	 */
-+	G_ELI_LOGREQ(2, cbp, "Sending request.");
-+	g_io_request(cbp, cp);
-+	if (cbp2 != NULL) {
-+		G_ELI_LOGREQ(2, cbp2, "Sending request.");
-+		g_io_request(cbp2, cp);
-+	}
-+}
-+
-+/*
-+ * This is the main function responsible for cryptography (ie. communication
-+ * with crypto(9) subsystem).
-+ *
-+ * BIO_READ:
-+ *	g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> G_ELI_AUTH_RUN -> g_eli_auth_read_done -> g_io_deliver
-+ * BIO_WRITE:
-+ *	g_eli_start -> G_ELI_AUTH_RUN -> g_eli_auth_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+void
-+g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp)
-+{
-+	struct g_eli_softc *sc;
-+	struct cryptop *crp;
-+	struct cryptodesc *crde, *crda;
-+	struct uio *uio;
-+	struct iovec *iov;
-+	u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
-+	off_t dstoff;
-+	int err, error;
-+	u_char *p, *data, *auth, *authkey, *plaindata;
-+
-+	G_ELI_LOGREQ(3, bp, "%s", __func__);
-+
-+	bp->bio_pflags = wr->w_number;
-+	sc = wr->w_softc;
-+	/* Sectorsize of decrypted provider eg. 4096. */
-+	decr_secsize = bp->bio_to->sectorsize;
-+	/* The real sectorsize of encrypted provider, eg. 512. */
-+	encr_secsize = LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize;
-+	/* Number of data bytes in one encrypted sector, eg. 480. */
-+	data_secsize = sc->sc_data_per_sector;
-+	/* Number of sectors from decrypted provider, eg. 2. */
-+	nsec = bp->bio_length / decr_secsize;
-+	/* Number of sectors from encrypted provider, eg. 18. */
-+	nsec = (nsec * sc->sc_bytes_per_sector) / encr_secsize;
-+	/* Last sector number in every big sector, eg. 9. */
-+	lsec = sc->sc_bytes_per_sector / encr_secsize;
-+	/* Destination offset, used for IV generation. */
-+	dstoff = (bp->bio_offset / bp->bio_to->sectorsize) * sc->sc_bytes_per_sector;
-+
-+	auth = NULL;	/* Silence compiler warning. */
-+	plaindata = bp->bio_data;
-+	if (bp->bio_cmd == BIO_READ) {
-+		data = bp->bio_driver2;
-+		auth = data + encr_secsize * nsec;
-+		p = auth + sc->sc_alen * nsec;
-+	} else {
-+		size_t size;
-+
-+		size = encr_secsize * nsec;
-+		size += sizeof(*crp) * nsec;
-+		size += sizeof(*crde) * nsec;
-+		size += sizeof(*crda) * nsec;
-+		size += G_ELI_AUTH_SECKEYLEN * nsec;
-+		size += sizeof(*uio) * nsec;
-+		size += sizeof(*iov) * nsec;
-+		data = malloc(size, M_ELI, M_WAITOK);
-+		bp->bio_driver2 = data;
-+		p = data + encr_secsize * nsec;
-+	}
-+	bp->bio_inbed = 0;
-+	bp->bio_children = nsec;
-+
-+	error = 0;
-+	for (i = 1; i <= nsec; i++, dstoff += encr_secsize) {
-+		crp = (struct cryptop *)p;	p += sizeof(*crp);
-+		crde = (struct cryptodesc *)p;	p += sizeof(*crde);
-+		crda = (struct cryptodesc *)p;	p += sizeof(*crda);
-+		authkey = (u_char *)p;		p += G_ELI_AUTH_SECKEYLEN;
-+		uio = (struct uio *)p;		p += sizeof(*uio);
-+		iov = (struct iovec *)p;	p += sizeof(*iov);
-+
-+		data_secsize = sc->sc_data_per_sector;
-+		if ((i % lsec) == 0)
-+			data_secsize = decr_secsize % data_secsize;
-+
-+		if (bp->bio_cmd == BIO_READ) {
-+			/* Remember read HMAC. */
-+			bcopy(data, auth, sc->sc_alen);
-+			auth += sc->sc_alen;
-+			/* TODO: bzero(9) can be commented out later. */
-+			bzero(data, sc->sc_alen);
-+		} else {
-+			bcopy(plaindata, data + sc->sc_alen, data_secsize);
-+			plaindata += data_secsize;
-+		}
-+
-+		iov->iov_len = sc->sc_alen + data_secsize;
-+		iov->iov_base = data;
-+		data += encr_secsize;
-+
-+		uio->uio_iov = iov;
-+		uio->uio_iovcnt = 1;
-+		uio->uio_segflg = UIO_SYSSPACE;
-+		uio->uio_resid = iov->iov_len;
-+
-+		crp->crp_sid = wr->w_sid;
-+		crp->crp_ilen = uio->uio_resid;
-+		crp->crp_olen = data_secsize;
-+		crp->crp_opaque = (void *)bp;
-+		crp->crp_buf = (void *)uio;
-+		crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
-+		if (g_eli_batch)
-+			crp->crp_flags |= CRYPTO_F_BATCH;
-+		if (bp->bio_cmd == BIO_WRITE) {
-+			crp->crp_callback = g_eli_auth_write_done;
-+			crp->crp_desc = crde;
-+			crde->crd_next = crda;
-+			crda->crd_next = NULL;
-+		} else {
-+			crp->crp_callback = g_eli_auth_read_done;
-+			crp->crp_desc = crda;
-+			crda->crd_next = crde;
-+			crde->crd_next = NULL;
-+		}
-+
-+		crde->crd_skip = sc->sc_alen;
-+		crde->crd_len = data_secsize;
-+		crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
-+		if (bp->bio_cmd == BIO_WRITE)
-+			crde->crd_flags |= CRD_F_ENCRYPT;
-+		crde->crd_alg = sc->sc_ealgo;
-+		crde->crd_key = g_eli_crypto_key(sc, dstoff, encr_secsize);
-+		crde->crd_klen = sc->sc_ekeylen;
-+		if (sc->sc_ealgo == CRYPTO_AES_XTS)
-+			crde->crd_klen <<= 1;
-+		g_eli_crypto_ivgen(sc, dstoff, crde->crd_iv,
-+		    sizeof(crde->crd_iv));
-+
-+		crda->crd_skip = sc->sc_alen;
-+		crda->crd_len = data_secsize;
-+		crda->crd_inject = 0;
-+		crda->crd_flags = CRD_F_KEY_EXPLICIT;
-+		crda->crd_alg = sc->sc_aalgo;
-+		g_eli_auth_keygen(sc, dstoff, authkey);
-+		crda->crd_key = authkey;
-+		crda->crd_klen = G_ELI_AUTH_SECKEYLEN * 8;
-+
-+		crp->crp_etype = 0;
-+		err = crypto_dispatch(crp);
-+		if (err != 0 && error == 0)
-+			error = err;
-+	}
-+	if (bp->bio_error == 0)
-+		bp->bio_error = error;
-+}
---- /dev/null
-+++ b/sys/geom/eli/g_eli_crypto.c
-@@ -0,0 +1,306 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#ifdef _KERNEL
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/malloc.h>
-+#include <sys/uio.h>
-+#else
-+#include <stdint.h>
-+#include <string.h>
-+#include <strings.h>
-+#include <errno.h>
-+#include <assert.h>
-+#include <openssl/evp.h>
-+#define	_OpenSSL_
-+#endif
-+#include <geom/eli/g_eli.h>
-+
-+#ifdef _KERNEL
-+MALLOC_DECLARE(M_ELI);
-+
-+static int
-+g_eli_crypto_done(struct cryptop *crp)
-+{
-+
-+	crp->crp_opaque = (void *)crp;
-+	wakeup(crp);
-+	return (0);
-+}
-+
-+static int
-+g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
-+    const u_char *key, size_t keysize)
-+{
-+	struct cryptoini cri;
-+	struct cryptop *crp;
-+	struct cryptodesc *crd;
-+	struct uio *uio;
-+	struct iovec *iov;
-+	uint64_t sid;
-+	u_char *p;
-+	int error;
-+
-+	KASSERT(algo != CRYPTO_AES_XTS,
-+	    ("%s: CRYPTO_AES_XTS unexpected here", __func__));
-+
-+	bzero(&cri, sizeof(cri));
-+	cri.cri_alg = algo;
-+	cri.cri_key = __DECONST(void *, key);
-+	cri.cri_klen = keysize;
-+	error = crypto_newsession(&sid, &cri, CRYPTOCAP_F_SOFTWARE);
-+	if (error != 0)
-+		return (error);
-+	p = malloc(sizeof(*crp) + sizeof(*crd) + sizeof(*uio) + sizeof(*iov),
-+	    M_ELI, M_NOWAIT | M_ZERO);
-+	if (p == NULL) {
-+		crypto_freesession(sid);
-+		return (ENOMEM);
-+	}
-+	crp = (struct cryptop *)p;	p += sizeof(*crp);
-+	crd = (struct cryptodesc *)p;	p += sizeof(*crd);
-+	uio = (struct uio *)p;		p += sizeof(*uio);
-+	iov = (struct iovec *)p;	p += sizeof(*iov);
-+
-+	iov->iov_len = datasize;
-+	iov->iov_base = data;
-+
-+	uio->uio_iov = iov;
-+	uio->uio_iovcnt = 1;
-+	uio->uio_segflg = UIO_SYSSPACE;
-+	uio->uio_resid = datasize;
-+
-+	crd->crd_skip = 0;
-+	crd->crd_len = datasize;
-+	crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
-+	if (enc)
-+		crd->crd_flags |= CRD_F_ENCRYPT;
-+	crd->crd_alg = algo;
-+	crd->crd_key = __DECONST(void *, key);
-+	crd->crd_klen = keysize;
-+	bzero(crd->crd_iv, sizeof(crd->crd_iv));
-+	crd->crd_next = NULL;
-+
-+	crp->crp_sid = sid;
-+	crp->crp_ilen = datasize;
-+	crp->crp_olen = datasize;
-+	crp->crp_opaque = NULL;
-+	crp->crp_callback = g_eli_crypto_done;
-+	crp->crp_buf = (void *)uio;
-+	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
-+	crp->crp_desc = crd;
-+
-+	error = crypto_dispatch(crp);
-+	if (error == 0) {
-+		while (crp->crp_opaque == NULL)
-+			tsleep(crp, PRIBIO, "geli", hz / 5);
-+		error = crp->crp_etype;
-+	}
-+
-+	free(crp, M_ELI);
-+	crypto_freesession(sid);
-+	return (error);
-+}
-+#else	/* !_KERNEL */
-+static int
-+g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
-+    const u_char *key, size_t keysize)
-+{
-+	EVP_CIPHER_CTX ctx;
-+	const EVP_CIPHER *type;
-+	u_char iv[keysize];
-+	int outsize;
-+
-+	assert(algo != CRYPTO_AES_XTS);
-+
-+	switch (algo) {
-+	case CRYPTO_NULL_CBC:
-+		type = EVP_enc_null();
-+		break;
-+	case CRYPTO_AES_CBC:
-+		switch (keysize) {
-+		case 128:
-+			type = EVP_aes_128_cbc();
-+			break;
-+		case 192:
-+			type = EVP_aes_192_cbc();
-+			break;
-+		case 256:
-+			type = EVP_aes_256_cbc();
-+			break;
-+		default:
-+			return (EINVAL);
-+		}
-+		break;
-+	case CRYPTO_BLF_CBC:
-+		type = EVP_bf_cbc();
-+		break;
-+#ifndef OPENSSL_NO_CAMELLIA
-+	case CRYPTO_CAMELLIA_CBC:
-+		switch (keysize) {
-+		case 128:
-+			type = EVP_camellia_128_cbc();
-+			break;
-+		case 192:
-+			type = EVP_camellia_192_cbc();
-+			break;
-+		case 256:
-+			type = EVP_camellia_256_cbc();
-+			break;
-+		default:
-+			return (EINVAL);
-+		}
-+		break;
-+#endif
-+	case CRYPTO_3DES_CBC:
-+		type = EVP_des_ede3_cbc();
-+		break;
-+	default:
-+		return (EINVAL);
-+	}
-+
-+	EVP_CIPHER_CTX_init(&ctx);
-+
-+	EVP_CipherInit_ex(&ctx, type, NULL, NULL, NULL, enc);
-+	EVP_CIPHER_CTX_set_key_length(&ctx, keysize / 8);
-+	EVP_CIPHER_CTX_set_padding(&ctx, 0);
-+	bzero(iv, sizeof(iv));
-+	EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc);
-+
-+	if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) {
-+		EVP_CIPHER_CTX_cleanup(&ctx);
-+		return (EINVAL);
-+	}
-+	assert(outsize == (int)datasize);
-+
-+	if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) {
-+		EVP_CIPHER_CTX_cleanup(&ctx);
-+		return (EINVAL);
-+	}
-+	assert(outsize == 0);
-+
-+	EVP_CIPHER_CTX_cleanup(&ctx);
-+	return (0);
-+}
-+#endif	/* !_KERNEL */
-+
-+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));
-+}
-+
-+void
-+g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
-+    size_t hkeylen)
-+{
-+	u_char k_ipad[128], key[128];
-+	SHA512_CTX lctx;
-+	u_int i;
-+
-+	bzero(key, sizeof(key));
-+	if (hkeylen == 0)
-+		; /* do nothing */
-+	else if (hkeylen <= 128)
-+		bcopy(hkey, key, hkeylen);
-+	else {
-+		/* If key is longer than 128 bytes reset it to key = SHA512(key). */
-+		SHA512_Init(&lctx);
-+		SHA512_Update(&lctx, hkey, hkeylen);
-+		SHA512_Final(key, &lctx);
-+	}
-+
-+	/* XOR key with ipad and opad values. */
-+	for (i = 0; i < sizeof(key); i++) {
-+		k_ipad[i] = key[i] ^ 0x36;
-+		ctx->k_opad[i] = key[i] ^ 0x5c;
-+	}
-+	bzero(key, sizeof(key));
-+	/* Perform inner SHA512. */
-+	SHA512_Init(&ctx->shactx);
-+	SHA512_Update(&ctx->shactx, k_ipad, sizeof(k_ipad));
-+}
-+
-+void
-+g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
-+    size_t datasize)
-+{
-+
-+	SHA512_Update(&ctx->shactx, data, datasize);
-+}
-+
-+void
-+g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize)
-+{
-+	u_char digest[SHA512_MDLEN];
-+	SHA512_CTX lctx;
-+
-+	SHA512_Final(digest, &ctx->shactx);
-+	/* Perform outer SHA512. */
-+	SHA512_Init(&lctx);
-+	SHA512_Update(&lctx, ctx->k_opad, sizeof(ctx->k_opad));
-+	bzero(ctx, sizeof(*ctx));
-+	SHA512_Update(&lctx, digest, sizeof(digest));
-+	SHA512_Final(digest, &lctx);
-+	/* mdsize == 0 means "Give me the whole hash!" */
-+	if (mdsize == 0)
-+		mdsize = SHA512_MDLEN;
-+	bcopy(digest, md, mdsize);
-+}
-+
-+void
-+g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize, const uint8_t *data,
-+    size_t datasize, uint8_t *md, size_t mdsize)
-+{
-+	struct hmac_ctx ctx;
-+
-+	g_eli_crypto_hmac_init(&ctx, hkey, hkeysize);
-+	g_eli_crypto_hmac_update(&ctx, data, datasize);
-+	g_eli_crypto_hmac_final(&ctx, md, mdsize);
-+}
---- /dev/null
-+++ b/sys/geom/eli/g_eli.c
-@@ -0,0 +1,1302 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/linker.h>
-+#include <sys/module.h>
-+#include <sys/lock.h>
-+#include <sys/mutex.h>
-+#include <sys/bio.h>
-+#include <sys/sysctl.h>
-+#include <sys/malloc.h>
-+#include <sys/eventhandler.h>
-+#include <sys/kthread.h>
-+#include <sys/proc.h>
-+#include <sys/sched.h>
-+#include <sys/smp.h>
-+#include <sys/uio.h>
-+#include <sys/vnode.h>
-+
-+#include <vm/uma.h>
-+
-+#include <geom/geom.h>
-+#include <geom/eli/g_eli.h>
-+#include <geom/eli/pkcs5v2.h>
-+
-+
-+MALLOC_DEFINE(M_ELI, "eli data", "GEOM_ELI Data");
-+
-+SYSCTL_DECL(_kern_geom);
-+SYSCTL_NODE(_kern_geom, OID_AUTO, eli, CTLFLAG_RW, 0, "GEOM_ELI stuff");
-+int g_eli_debug = 0;
-+TUNABLE_INT("kern.geom.eli.debug", &g_eli_debug);
-+SYSCTL_INT(_kern_geom_eli, OID_AUTO, debug, CTLFLAG_RW, &g_eli_debug, 0,
-+    "Debug level");
-+static u_int g_eli_tries = 3;
-+TUNABLE_INT("kern.geom.eli.tries", &g_eli_tries);
-+SYSCTL_UINT(_kern_geom_eli, OID_AUTO, tries, CTLFLAG_RW, &g_eli_tries, 0,
-+    "Number of tries for entering the passphrase");
-+static u_int g_eli_visible_passphrase = 0;
-+TUNABLE_INT("kern.geom.eli.visible_passphrase", &g_eli_visible_passphrase);
-+SYSCTL_UINT(_kern_geom_eli, OID_AUTO, visible_passphrase, CTLFLAG_RW,
-+    &g_eli_visible_passphrase, 0,
-+    "Turn on echo when entering the passphrase (for debug purposes only!!)");
-+u_int g_eli_overwrites = G_ELI_OVERWRITES;
-+TUNABLE_INT("kern.geom.eli.overwrites", &g_eli_overwrites);
-+SYSCTL_UINT(_kern_geom_eli, OID_AUTO, overwrites, CTLFLAG_RW, &g_eli_overwrites,
-+    0, "Number of times on-disk keys should be overwritten when destroying them");
-+static u_int g_eli_threads = 0;
-+TUNABLE_INT("kern.geom.eli.threads", &g_eli_threads);
-+SYSCTL_UINT(_kern_geom_eli, OID_AUTO, threads, CTLFLAG_RW, &g_eli_threads, 0,
-+    "Number of threads doing crypto work");
-+u_int g_eli_batch = 0;
-+TUNABLE_INT("kern.geom.eli.batch", &g_eli_batch);
-+SYSCTL_UINT(_kern_geom_eli, OID_AUTO, batch, CTLFLAG_RW, &g_eli_batch, 0,
-+    "Use crypto operations batching");
-+
-+static eventhandler_tag g_eli_pre_sync = NULL;
-+
-+static int g_eli_destroy_geom(struct gctl_req *req, struct g_class *mp,
-+    struct g_geom *gp);
-+static void g_eli_init(struct g_class *mp);
-+static void g_eli_fini(struct g_class *mp);
-+
-+static g_taste_t g_eli_taste;
-+static g_dumpconf_t g_eli_dumpconf;
-+
-+struct g_class g_eli_class = {
-+	.name = G_ELI_CLASS_NAME,
-+	.version = G_VERSION,
-+	.ctlreq = g_eli_config,
-+	.taste = g_eli_taste,
-+	.destroy_geom = g_eli_destroy_geom,
-+	.init = g_eli_init,
-+	.fini = g_eli_fini
-+};
-+
-+
-+/*
-+ * Code paths:
-+ * BIO_READ:
-+ *	g_eli_start -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
-+ * BIO_WRITE:
-+ *	g_eli_start -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+
-+
-+/*
-+ * EAGAIN from crypto(9) means, that we were probably balanced to another crypto
-+ * accelerator or something like this.
-+ * The function updates the SID and rerun the operation.
-+ */
-+int
-+g_eli_crypto_rerun(struct cryptop *crp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_eli_worker *wr;
-+	struct bio *bp;
-+	int error;
-+
-+	bp = (struct bio *)crp->crp_opaque;
-+	sc = bp->bio_to->geom->softc;
-+	LIST_FOREACH(wr, &sc->sc_workers, w_next) {
-+		if (wr->w_number == bp->bio_pflags)
-+			break;
-+	}
-+	KASSERT(wr != NULL, ("Invalid worker (%u).", bp->bio_pflags));
-+	G_ELI_DEBUG(1, "Rerunning crypto %s request (sid: %ju -> %ju).",
-+	    bp->bio_cmd == BIO_READ ? "READ" : "WRITE", (uintmax_t)wr->w_sid,
-+	    (uintmax_t)crp->crp_sid);
-+	wr->w_sid = crp->crp_sid;
-+	crp->crp_etype = 0;
-+	error = crypto_dispatch(crp);
-+	if (error == 0)
-+		return (0);
-+	G_ELI_DEBUG(1, "%s: crypto_dispatch() returned %d.", __func__, error);
-+	crp->crp_etype = error;
-+	return (error);
-+}
-+
-+/*
-+ * The function is called afer reading encrypted data from the provider.
-+ *
-+ * g_eli_start -> g_eli_crypto_read -> g_io_request -> G_ELI_READ_DONE -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
-+ */
-+void
-+g_eli_read_done(struct bio *bp)
-+{
-+	struct g_eli_softc *sc;
-+	struct bio *pbp;
-+
-+	G_ELI_LOGREQ(2, bp, "Request done.");
-+	pbp = bp->bio_parent;
-+	if (pbp->bio_error == 0)
-+		pbp->bio_error = bp->bio_error;
-+	/*
-+	 * Do we have all sectors already?
-+	 */
-+	pbp->bio_inbed++;
-+	if (pbp->bio_inbed < pbp->bio_children)
-+		return;
-+	g_destroy_bio(bp);
-+	sc = pbp->bio_to->geom->softc;
-+	if (pbp->bio_error != 0) {
-+		G_ELI_LOGREQ(0, pbp, "%s() failed", __func__);
-+		pbp->bio_completed = 0;
-+		if (pbp->bio_driver2 != NULL) {
-+			free(pbp->bio_driver2, M_ELI);
-+			pbp->bio_driver2 = NULL;
-+		}
-+		g_io_deliver(pbp, pbp->bio_error);
-+		atomic_subtract_int(&sc->sc_inflight, 1);
-+		return;
-+	}
-+	mtx_lock(&sc->sc_queue_mtx);
-+	bioq_insert_tail(&sc->sc_queue, pbp);
-+	mtx_unlock(&sc->sc_queue_mtx);
-+	wakeup(sc);
-+}
-+
-+/*
-+ * The function is called after we encrypt and write data.
-+ *
-+ * g_eli_start -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> G_ELI_WRITE_DONE -> g_io_deliver
-+ */
-+void
-+g_eli_write_done(struct bio *bp)
-+{
-+	struct g_eli_softc *sc;
-+	struct bio *pbp;
-+
-+	G_ELI_LOGREQ(2, bp, "Request done.");
-+	pbp = bp->bio_parent;
-+	if (pbp->bio_error == 0) {
-+		if (bp->bio_error != 0)
-+			pbp->bio_error = bp->bio_error;
-+	}
-+	/*
-+	 * Do we have all sectors already?
-+	 */
-+	pbp->bio_inbed++;
-+	if (pbp->bio_inbed < pbp->bio_children)
-+		return;
-+	free(pbp->bio_driver2, M_ELI);
-+	pbp->bio_driver2 = NULL;
-+	if (pbp->bio_error != 0) {
-+		G_ELI_LOGREQ(0, pbp, "Crypto WRITE request failed (error=%d).",
-+		    pbp->bio_error);
-+		pbp->bio_completed = 0;
-+	}
-+	g_destroy_bio(bp);
-+	/*
-+	 * Write is finished, send it up.
-+	 */
-+	pbp->bio_completed = pbp->bio_length;
-+	sc = pbp->bio_to->geom->softc;
-+	g_io_deliver(pbp, pbp->bio_error);
-+	atomic_subtract_int(&sc->sc_inflight, 1);
-+}
-+
-+/*
-+ * This function should never be called, but GEOM made as it set ->orphan()
-+ * method for every geom.
-+ */
-+static void
-+g_eli_orphan_spoil_assert(struct g_consumer *cp)
-+{
-+
-+	panic("Function %s() called for %s.", __func__, cp->geom->name);
-+}
-+
-+static void
-+g_eli_orphan(struct g_consumer *cp)
-+{
-+	struct g_eli_softc *sc;
-+
-+	g_topology_assert();
-+	sc = cp->geom->softc;
-+	if (sc == NULL)
-+		return;
-+	g_eli_destroy(sc, TRUE);
-+}
-+
-+/*
-+ * BIO_READ:
-+ *	G_ELI_START -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
-+ * BIO_WRITE:
-+ *	G_ELI_START -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+static void
-+g_eli_start(struct bio *bp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_consumer *cp;
-+	struct bio *cbp;
-+
-+	sc = bp->bio_to->geom->softc;
-+	KASSERT(sc != NULL,
-+	    ("Provider's error should be set (error=%d)(device=%s).",
-+	    bp->bio_to->error, bp->bio_to->name));
-+	G_ELI_LOGREQ(2, bp, "Request received.");
-+
-+	switch (bp->bio_cmd) {
-+	case BIO_READ:
-+	case BIO_WRITE:
-+	case BIO_GETATTR:
-+	case BIO_FLUSH:
-+		break;
-+	case BIO_DELETE:
-+		/*
-+		 * We could eventually support BIO_DELETE request.
-+		 * It could be done by overwritting requested sector with
-+		 * random data g_eli_overwrites number of times.
-+		 */
-+	default:
-+		g_io_deliver(bp, EOPNOTSUPP);
-+		return;
-+	}
-+	cbp = g_clone_bio(bp);
-+	if (cbp == NULL) {
-+		g_io_deliver(bp, ENOMEM);
-+		return;
-+	}
-+	bp->bio_driver1 = cbp;
-+	bp->bio_pflags = G_ELI_NEW_BIO;
-+	switch (bp->bio_cmd) {
-+	case BIO_READ:
-+		if (!(sc->sc_flags & G_ELI_FLAG_AUTH)) {
-+			g_eli_crypto_read(sc, bp, 0);
-+			break;
-+		}
-+		/* FALLTHROUGH */
-+	case BIO_WRITE:
-+		mtx_lock(&sc->sc_queue_mtx);
-+		bioq_insert_tail(&sc->sc_queue, bp);
-+		mtx_unlock(&sc->sc_queue_mtx);
-+		wakeup(sc);
-+		break;
-+	case BIO_GETATTR:
-+	case BIO_FLUSH:
-+		cbp->bio_done = g_std_done;
-+		cp = LIST_FIRST(&sc->sc_geom->consumer);
-+		cbp->bio_to = cp->provider;
-+		G_ELI_LOGREQ(2, cbp, "Sending request.");
-+		g_io_request(cbp, cp);
-+		break;
-+	}
-+}
-+
-+static int
-+g_eli_newsession(struct g_eli_worker *wr)
-+{
-+	struct g_eli_softc *sc;
-+	struct cryptoini crie, cria;
-+	int error;
-+
-+	sc = wr->w_softc;
-+
-+	bzero(&crie, sizeof(crie));
-+	crie.cri_alg = sc->sc_ealgo;
-+	crie.cri_klen = sc->sc_ekeylen;
-+	if (sc->sc_ealgo == CRYPTO_AES_XTS)
-+		crie.cri_klen <<= 1;
-+	crie.cri_key = sc->sc_ekeys[0];
-+	if (sc->sc_flags & G_ELI_FLAG_AUTH) {
-+		bzero(&cria, sizeof(cria));
-+		cria.cri_alg = sc->sc_aalgo;
-+		cria.cri_klen = sc->sc_akeylen;
-+		cria.cri_key = sc->sc_akey;
-+		crie.cri_next = &cria;
-+	}
-+
-+	switch (sc->sc_crypto) {
-+	case G_ELI_CRYPTO_SW:
-+		error = crypto_newsession(&wr->w_sid, &crie,
-+		    CRYPTOCAP_F_SOFTWARE);
-+		break;
-+	case G_ELI_CRYPTO_HW:
-+		error = crypto_newsession(&wr->w_sid, &crie,
-+		    CRYPTOCAP_F_HARDWARE);
-+		break;
-+	case G_ELI_CRYPTO_UNKNOWN:
-+		error = crypto_newsession(&wr->w_sid, &crie,
-+		    CRYPTOCAP_F_HARDWARE);
-+		if (error == 0) {
-+			mtx_lock(&sc->sc_queue_mtx);
-+			if (sc->sc_crypto == G_ELI_CRYPTO_UNKNOWN)
-+				sc->sc_crypto = G_ELI_CRYPTO_HW;
-+			mtx_unlock(&sc->sc_queue_mtx);
-+		} else {
-+			error = crypto_newsession(&wr->w_sid, &crie,
-+			    CRYPTOCAP_F_SOFTWARE);
-+			mtx_lock(&sc->sc_queue_mtx);
-+			if (sc->sc_crypto == G_ELI_CRYPTO_UNKNOWN)
-+				sc->sc_crypto = G_ELI_CRYPTO_SW;
-+			mtx_unlock(&sc->sc_queue_mtx);
-+		}
-+		break;
-+	default:
-+		panic("%s: invalid condition", __func__);
-+	}
-+
-+	return (error);
-+}
-+
-+static void
-+g_eli_freesession(struct g_eli_worker *wr)
-+{
-+
-+	crypto_freesession(wr->w_sid);
-+}
-+
-+static void
-+g_eli_cancel(struct g_eli_softc *sc)
-+{
-+	struct bio *bp;
-+
-+	mtx_assert(&sc->sc_queue_mtx, MA_OWNED);
-+
-+	while ((bp = bioq_takefirst(&sc->sc_queue)) != NULL) {
-+		KASSERT(bp->bio_pflags == G_ELI_NEW_BIO,
-+		    ("Not new bio when canceling (bp=%p).", bp));
-+		g_io_deliver(bp, ENXIO);
-+	}
-+}
-+
-+static struct bio *
-+g_eli_takefirst(struct g_eli_softc *sc)
-+{
-+	struct bio *bp;
-+
-+	mtx_assert(&sc->sc_queue_mtx, MA_OWNED);
-+
-+	if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
-+		return (bioq_takefirst(&sc->sc_queue));
-+	/*
-+	 * Device suspended, so we skip new I/O requests.
-+	 */
-+	TAILQ_FOREACH(bp, &sc->sc_queue.queue, bio_queue) {
-+		if (bp->bio_pflags != G_ELI_NEW_BIO)
-+			break;
-+	}
-+	if (bp != NULL)
-+		bioq_remove(&sc->sc_queue, bp);
-+	return (bp);
-+}
-+
-+/*
-+ * This is the main function for kernel worker thread when we don't have
-+ * hardware acceleration and we have to do cryptography in software.
-+ * Dedicated thread is needed, so we don't slow down g_up/g_down GEOM
-+ * threads with crypto work.
-+ */
-+static void
-+g_eli_worker(void *arg)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_eli_worker *wr;
-+	struct bio *bp;
-+	int error;
-+
-+	wr = arg;
-+	sc = wr->w_softc;
-+#ifdef SMP
-+	/* Before sched_bind() to a CPU, wait for all CPUs to go on-line. */
-+	if (mp_ncpus > 1 && sc->sc_crypto == G_ELI_CRYPTO_SW &&
-+	    g_eli_threads == 0) {
-+		while (!smp_started)
-+			tsleep(wr, 0, "geli:smp", hz / 4);
-+	}
-+#endif
-+	thread_lock(curthread);
-+	sched_prio(curthread, PUSER);
-+	if (sc->sc_crypto == G_ELI_CRYPTO_SW && g_eli_threads == 0)
-+		sched_bind(curthread, wr->w_number);
-+	thread_unlock(curthread);
-+
-+	G_ELI_DEBUG(1, "Thread %s started.", curthread->td_proc->p_comm);
-+
-+	for (;;) {
-+		mtx_lock(&sc->sc_queue_mtx);
-+again:
-+		bp = g_eli_takefirst(sc);
-+		if (bp == NULL) {
-+			if (sc->sc_flags & G_ELI_FLAG_DESTROY) {
-+				g_eli_cancel(sc);
-+				LIST_REMOVE(wr, w_next);
-+				g_eli_freesession(wr);
-+				free(wr, M_ELI);
-+				G_ELI_DEBUG(1, "Thread %s exiting.",
-+				    curthread->td_proc->p_comm);
-+				wakeup(&sc->sc_workers);
-+				mtx_unlock(&sc->sc_queue_mtx);
-+				kproc_exit(0);
-+			}
-+			while (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
-+				if (sc->sc_inflight > 0) {
-+					G_ELI_DEBUG(0, "inflight=%d", sc->sc_inflight);
-+					/*
-+					 * We still have inflight BIOs, so
-+					 * sleep and retry.
-+					 */
-+					msleep(sc, &sc->sc_queue_mtx, PRIBIO,
-+					    "geli:inf", hz / 5);
-+					goto again;
-+				}
-+				/*
-+				 * Suspend requested, mark the worker as
-+				 * suspended and go to sleep.
-+				 */
-+				if (wr->w_active) {
-+					g_eli_freesession(wr);
-+					wr->w_active = FALSE;
-+				}
-+				wakeup(&sc->sc_workers);
-+				msleep(sc, &sc->sc_queue_mtx, PRIBIO,
-+				    "geli:suspend", 0);
-+				if (!wr->w_active &&
-+				    !(sc->sc_flags & G_ELI_FLAG_SUSPEND)) {
-+					error = g_eli_newsession(wr);
-+					KASSERT(error == 0,
-+					    ("g_eli_newsession() failed on resume (error=%d)",
-+					    error));
-+					wr->w_active = TRUE;
-+				}
-+				goto again;
-+			}
-+			msleep(sc, &sc->sc_queue_mtx, PDROP, "geli:w", 0);
-+			continue;
-+		}
-+		if (bp->bio_pflags == G_ELI_NEW_BIO)
-+			atomic_add_int(&sc->sc_inflight, 1);
-+		mtx_unlock(&sc->sc_queue_mtx);
-+		if (bp->bio_pflags == G_ELI_NEW_BIO) {
-+			bp->bio_pflags = 0;
-+			if (sc->sc_flags & G_ELI_FLAG_AUTH) {
-+				if (bp->bio_cmd == BIO_READ)
-+					g_eli_auth_read(sc, bp);
-+				else
-+					g_eli_auth_run(wr, bp);
-+			} else {
-+				if (bp->bio_cmd == BIO_READ)
-+					g_eli_crypto_read(sc, bp, 1);
-+				else
-+					g_eli_crypto_run(wr, bp);
-+			}
-+		} else {
-+			if (sc->sc_flags & G_ELI_FLAG_AUTH)
-+				g_eli_auth_run(wr, bp);
-+			else
-+				g_eli_crypto_run(wr, bp);
-+		}
-+	}
-+}
-+
-+/*
-+ * Select encryption key. If G_ELI_FLAG_SINGLE_KEY is present we only have one
-+ * key available for all the data. If the flag is not present select the key
-+ * based on data offset.
-+ */
-+uint8_t *
-+g_eli_crypto_key(struct g_eli_softc *sc, off_t offset, size_t blocksize)
-+{
-+	u_int nkey;
-+
-+	if (sc->sc_nekeys == 1)
-+		return (sc->sc_ekeys[0]);
-+
-+	KASSERT(sc->sc_nekeys > 1, ("%s: sc_nekeys=%u", __func__,
-+	    sc->sc_nekeys));
-+	KASSERT((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) == 0,
-+	    ("%s: SINGLE_KEY flag set, but sc_nekeys=%u", __func__,
-+	    sc->sc_nekeys));
-+
-+	/* We switch key every 2^G_ELI_KEY_SHIFT blocks. */
-+	nkey = (offset >> G_ELI_KEY_SHIFT) / blocksize;
-+
-+	KASSERT(nkey < sc->sc_nekeys, ("%s: nkey=%u >= sc_nekeys=%u", __func__,
-+	    nkey, sc->sc_nekeys));
-+
-+	return (sc->sc_ekeys[nkey]);
-+}
-+
-+/*
-+ * Here we generate IV. It is unique for every sector.
-+ */
-+void
-+g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
-+    size_t size)
-+{
-+	uint8_t off[8];
-+
-+	if ((sc->sc_flags & G_ELI_FLAG_NATIVE_BYTE_ORDER) != 0)
-+		bcopy(&offset, off, sizeof(off));
-+	else
-+		le64enc(off, (uint64_t)offset);
-+
-+	switch (sc->sc_ealgo) {
-+	case CRYPTO_AES_XTS:
-+		bcopy(off, iv, sizeof(off));
-+		bzero(iv + sizeof(off), size - sizeof(off));
-+		break;
-+	default:
-+	    {
-+		u_char hash[SHA256_DIGEST_LENGTH];
-+		SHA256_CTX ctx;
-+
-+		/* Copy precalculated SHA256 context for IV-Key. */
-+		bcopy(&sc->sc_ivctx, &ctx, sizeof(ctx));
-+		SHA256_Update(&ctx, off, sizeof(off));
-+		SHA256_Final(hash, &ctx);
-+		bcopy(hash, iv, MIN(sizeof(hash), size));
-+		break;
-+	    }
-+	}
-+}
-+
-+int
-+g_eli_read_metadata(struct g_class *mp, struct g_provider *pp,
-+    struct g_eli_metadata *md)
-+{
-+	struct g_geom *gp;
-+	struct g_consumer *cp;
-+	u_char *buf = NULL;
-+	int error;
-+
-+	g_topology_assert();
-+
-+	gp = g_new_geomf(mp, "eli:taste");
-+	gp->start = g_eli_start;
-+	gp->access = g_std_access;
-+	/*
-+	 * g_eli_read_metadata() is always called from the event thread.
-+	 * Our geom is created and destroyed in the same event, so there
-+	 * could be no orphan nor spoil event in the meantime.
-+	 */
-+	gp->orphan = g_eli_orphan_spoil_assert;
-+	gp->spoiled = g_eli_orphan_spoil_assert;
-+	cp = g_new_consumer(gp);
-+	error = g_attach(cp, pp);
-+	if (error != 0)
-+		goto end;
-+	error = g_access(cp, 1, 0, 0);
-+	if (error != 0)
-+		goto end;
-+	g_topology_unlock();
-+	buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize,
-+	    &error);
-+	g_topology_lock();
-+	if (buf == NULL)
-+		goto end;
-+	eli_metadata_decode(buf, md);
-+end:
-+	if (buf != NULL)
-+		g_free(buf);
-+	if (cp->provider != NULL) {
-+		if (cp->acr == 1)
-+			g_access(cp, -1, 0, 0);
-+		g_detach(cp);
-+	}
-+	g_destroy_consumer(cp);
-+	g_destroy_geom(gp);
-+	return (error);
-+}
-+
-+/*
-+ * The function is called when we had last close on provider and user requested
-+ * to close it when this situation occur.
-+ */
-+static void
-+g_eli_last_close(struct g_eli_softc *sc)
-+{
-+	struct g_geom *gp;
-+	struct g_provider *pp;
-+	char ppname[64];
-+	int error;
-+
-+	g_topology_assert();
-+	gp = sc->sc_geom;
-+	pp = LIST_FIRST(&gp->provider);
-+	strlcpy(ppname, pp->name, sizeof(ppname));
-+	error = g_eli_destroy(sc, TRUE);
-+	KASSERT(error == 0, ("Cannot detach %s on last close (error=%d).",
-+	    ppname, error));
-+	G_ELI_DEBUG(0, "Detached %s on last close.", ppname);
-+}
-+
-+int
-+g_eli_access(struct g_provider *pp, int dr, int dw, int de)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_geom *gp;
-+
-+	gp = pp->geom;
-+	sc = gp->softc;
-+
-+	if (dw > 0) {
-+		if (sc->sc_flags & G_ELI_FLAG_RO) {
-+			/* Deny write attempts. */
-+			return (EROFS);
-+		}
-+		/* Someone is opening us for write, we need to remember that. */
-+		sc->sc_flags |= G_ELI_FLAG_WOPEN;
-+		return (0);
-+	}
-+	/* Is this the last close? */
-+	if (pp->acr + dr > 0 || pp->acw + dw > 0 || pp->ace + de > 0)
-+		return (0);
-+
-+	/*
-+	 * Automatically detach on last close if requested.
-+	 */
-+	if ((sc->sc_flags & G_ELI_FLAG_RW_DETACH) ||
-+	    (sc->sc_flags & G_ELI_FLAG_WOPEN)) {
-+		g_eli_last_close(sc);
-+	}
-+	return (0);
-+}
-+
-+static int
-+g_eli_cpu_is_disabled(int cpu)
-+{
-+#ifdef SMP
-+	return ((hlt_cpus_mask & (1 << cpu)) != 0);
-+#else
-+	return (0);
-+#endif
-+}
-+
-+struct g_geom *
-+g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
-+    const struct g_eli_metadata *md, const u_char *mkey, int nkey)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_eli_worker *wr;
-+	struct g_geom *gp;
-+	struct g_provider *pp;
-+	struct g_consumer *cp;
-+	u_int i, threads;
-+	int error;
-+
-+	G_ELI_DEBUG(1, "Creating device %s%s.", bpp->name, G_ELI_SUFFIX);
-+
-+	gp = g_new_geomf(mp, "%s%s", bpp->name, G_ELI_SUFFIX);
-+	gp->softc = NULL;	/* for a moment */
-+
-+	sc = malloc(sizeof(*sc), M_ELI, M_WAITOK | M_ZERO);
-+	gp->start = g_eli_start;
-+	/*
-+	 * Spoiling cannot happen actually, because we keep provider open for
-+	 * writing all the time or provider is read-only.
-+	 */
-+	gp->spoiled = g_eli_orphan_spoil_assert;
-+	gp->orphan = g_eli_orphan;
-+	gp->dumpconf = g_eli_dumpconf;
-+	/*
-+	 * If detach-on-last-close feature is not enabled and we don't operate
-+	 * on read-only provider, we can simply use g_std_access().
-+	 */
-+	if (md->md_flags & (G_ELI_FLAG_WO_DETACH | G_ELI_FLAG_RO))
-+		gp->access = g_eli_access;
-+	else
-+		gp->access = g_std_access;
-+
-+	sc->sc_inflight = 0;
-+	sc->sc_crypto = G_ELI_CRYPTO_UNKNOWN;
-+	sc->sc_flags = md->md_flags;
-+	/* Backward compatibility. */
-+	if (md->md_version < 4)
-+		sc->sc_flags |= G_ELI_FLAG_NATIVE_BYTE_ORDER;
-+	if (md->md_version < 5)
-+		sc->sc_flags |= G_ELI_FLAG_SINGLE_KEY;
-+	sc->sc_ealgo = md->md_ealgo;
-+	sc->sc_nkey = nkey;
-+
-+	if (sc->sc_flags & G_ELI_FLAG_AUTH) {
-+		sc->sc_akeylen = sizeof(sc->sc_akey) * 8;
-+		sc->sc_aalgo = md->md_aalgo;
-+		sc->sc_alen = g_eli_hashlen(sc->sc_aalgo);
-+
-+		sc->sc_data_per_sector = bpp->sectorsize - sc->sc_alen;
-+		/*
-+		 * Some hash functions (like SHA1 and RIPEMD160) generates hash
-+		 * which length is not multiple of 128 bits, but we want data
-+		 * length to be multiple of 128, so we can encrypt without
-+		 * padding. The line below rounds down data length to multiple
-+		 * of 128 bits.
-+		 */
-+		sc->sc_data_per_sector -= sc->sc_data_per_sector % 16;
-+
-+		sc->sc_bytes_per_sector =
-+		    (md->md_sectorsize - 1) / sc->sc_data_per_sector + 1;
-+		sc->sc_bytes_per_sector *= bpp->sectorsize;
-+	}
-+
-+	gp->softc = sc;
-+	sc->sc_geom = gp;
-+
-+	bioq_init(&sc->sc_queue);
-+	mtx_init(&sc->sc_queue_mtx, "geli:queue", NULL, MTX_DEF);
-+
-+	pp = NULL;
-+	cp = g_new_consumer(gp);
-+	error = g_attach(cp, bpp);
-+	if (error != 0) {
-+		if (req != NULL) {
-+			gctl_error(req, "Cannot attach to %s (error=%d).",
-+			    bpp->name, error);
-+		} else {
-+			G_ELI_DEBUG(1, "Cannot attach to %s (error=%d).",
-+			    bpp->name, error);
-+		}
-+		goto failed;
-+	}
-+	/*
-+	 * Keep provider open all the time, so we can run critical tasks,
-+	 * like Master Keys deletion, without wondering if we can open
-+	 * provider or not.
-+	 * We don't open provider for writing only when user requested read-only
-+	 * access.
-+	 */
-+	if (sc->sc_flags & G_ELI_FLAG_RO)
-+		error = g_access(cp, 1, 0, 1);
-+	else
-+		error = g_access(cp, 1, 1, 1);
-+	if (error != 0) {
-+		if (req != NULL) {
-+			gctl_error(req, "Cannot access %s (error=%d).",
-+			    bpp->name, error);
-+		} else {
-+			G_ELI_DEBUG(1, "Cannot access %s (error=%d).",
-+			    bpp->name, error);
-+		}
-+		goto failed;
-+	}
-+
-+	sc->sc_sectorsize = md->md_sectorsize;
-+	sc->sc_mediasize = bpp->mediasize;
-+	if (!(sc->sc_flags & G_ELI_FLAG_ONETIME))
-+		sc->sc_mediasize -= bpp->sectorsize;
-+	if (!(sc->sc_flags & G_ELI_FLAG_AUTH))
-+		sc->sc_mediasize -= (sc->sc_mediasize % sc->sc_sectorsize);
-+	else {
-+		sc->sc_mediasize /= sc->sc_bytes_per_sector;
-+		sc->sc_mediasize *= sc->sc_sectorsize;
-+	}
-+
-+	/*
-+	 * Remember the keys in our softc structure.
-+	 */
-+	g_eli_mkey_propagate(sc, mkey);
-+	sc->sc_ekeylen = md->md_keylen;
-+
-+	LIST_INIT(&sc->sc_workers);
-+
-+	threads = g_eli_threads;
-+	if (threads == 0)
-+		threads = mp_ncpus;
-+	else if (threads > mp_ncpus) {
-+		/* There is really no need for too many worker threads. */
-+		threads = mp_ncpus;
-+		G_ELI_DEBUG(0, "Reducing number of threads to %u.", threads);
-+	}
-+	for (i = 0; i < threads; i++) {
-+		if (g_eli_cpu_is_disabled(i)) {
-+			G_ELI_DEBUG(1, "%s: CPU %u disabled, skipping.",
-+			    bpp->name, i);
-+			continue;
-+		}
-+		wr = malloc(sizeof(*wr), M_ELI, M_WAITOK | M_ZERO);
-+		wr->w_softc = sc;
-+		wr->w_number = i;
-+		wr->w_active = TRUE;
-+
-+		error = g_eli_newsession(wr);
-+		if (error != 0) {
-+			free(wr, M_ELI);
-+			if (req != NULL) {
-+				gctl_error(req, "Cannot set up crypto session "
-+				    "for %s (error=%d).", bpp->name, error);
-+			} else {
-+				G_ELI_DEBUG(1, "Cannot set up crypto session "
-+				    "for %s (error=%d).", bpp->name, error);
-+			}
-+			goto failed;
-+		}
-+
-+		error = kproc_create(g_eli_worker, wr, &wr->w_proc, 0, 0,
-+		    "g_eli[%u] %s", i, bpp->name);
-+		if (error != 0) {
-+			g_eli_freesession(wr);
-+			free(wr, M_ELI);
-+			if (req != NULL) {
-+				gctl_error(req, "Cannot create kernel thread "
-+				    "for %s (error=%d).", bpp->name, error);
-+			} else {
-+				G_ELI_DEBUG(1, "Cannot create kernel thread "
-+				    "for %s (error=%d).", bpp->name, error);
-+			}
-+			goto failed;
-+		}
-+		LIST_INSERT_HEAD(&sc->sc_workers, wr, w_next);
-+		/* If we have hardware support, one thread is enough. */
-+		if (sc->sc_crypto == G_ELI_CRYPTO_HW)
-+			break;
-+	}
-+
-+	/*
-+	 * Create decrypted provider.
-+	 */
-+	pp = g_new_providerf(gp, "%s%s", bpp->name, G_ELI_SUFFIX);
-+	pp->mediasize = sc->sc_mediasize;
-+	pp->sectorsize = sc->sc_sectorsize;
-+
-+	g_error_provider(pp, 0);
-+
-+	G_ELI_DEBUG(0, "Device %s created.", pp->name);
-+	G_ELI_DEBUG(0, "Encryption: %s %u", g_eli_algo2str(sc->sc_ealgo),
-+	    sc->sc_ekeylen);
-+	if (sc->sc_flags & G_ELI_FLAG_AUTH)
-+		G_ELI_DEBUG(0, " Integrity: %s", g_eli_algo2str(sc->sc_aalgo));
-+	G_ELI_DEBUG(0, "    Crypto: %s",
-+	    sc->sc_crypto == G_ELI_CRYPTO_SW ? "software" : "hardware");
-+	return (gp);
-+failed:
-+	mtx_lock(&sc->sc_queue_mtx);
-+	sc->sc_flags |= G_ELI_FLAG_DESTROY;
-+	wakeup(sc);
-+	/*
-+	 * Wait for kernel threads self destruction.
-+	 */
-+	while (!LIST_EMPTY(&sc->sc_workers)) {
-+		msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
-+		    "geli:destroy", 0);
-+	}
-+	mtx_destroy(&sc->sc_queue_mtx);
-+	if (cp->provider != NULL) {
-+		if (cp->acr == 1)
-+			g_access(cp, -1, -1, -1);
-+		g_detach(cp);
-+	}
-+	g_destroy_consumer(cp);
-+	g_destroy_geom(gp);
-+	if (sc->sc_ekeys != NULL) {
-+		bzero(sc->sc_ekeys,
-+		    sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN));
-+		free(sc->sc_ekeys, M_ELI);
-+	}
-+	bzero(sc, sizeof(*sc));
-+	free(sc, M_ELI);
-+	return (NULL);
-+}
-+
-+int
-+g_eli_destroy(struct g_eli_softc *sc, boolean_t force)
-+{
-+	struct g_geom *gp;
-+	struct g_provider *pp;
-+
-+	g_topology_assert();
-+
-+	if (sc == NULL)
-+		return (ENXIO);
-+
-+	gp = sc->sc_geom;
-+	pp = LIST_FIRST(&gp->provider);
-+	if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
-+		if (force) {
-+			G_ELI_DEBUG(1, "Device %s is still open, so it "
-+			    "cannot be definitely removed.", pp->name);
-+		} else {
-+			G_ELI_DEBUG(1,
-+			    "Device %s is still open (r%dw%de%d).", pp->name,
-+			    pp->acr, pp->acw, pp->ace);
-+			return (EBUSY);
-+		}
-+	}
-+
-+	mtx_lock(&sc->sc_queue_mtx);
-+	sc->sc_flags |= G_ELI_FLAG_DESTROY;
-+	wakeup(sc);
-+	while (!LIST_EMPTY(&sc->sc_workers)) {
-+		msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
-+		    "geli:destroy", 0);
-+	}
-+	mtx_destroy(&sc->sc_queue_mtx);
-+	gp->softc = NULL;
-+	if (sc->sc_ekeys != NULL) {
-+		/* The sc_ekeys field can be NULL is device is suspended. */
-+		bzero(sc->sc_ekeys,
-+		    sc->sc_nekeys * (sizeof(uint8_t *) + G_ELI_DATAKEYLEN));
-+		free(sc->sc_ekeys, M_ELI);
-+	}
-+	bzero(sc, sizeof(*sc));
-+	free(sc, M_ELI);
-+
-+	if (pp == NULL || (pp->acr == 0 && pp->acw == 0 && pp->ace == 0))
-+		G_ELI_DEBUG(0, "Device %s destroyed.", gp->name);
-+	g_wither_geom_close(gp, ENXIO);
-+
-+	return (0);
-+}
-+
-+static int
-+g_eli_destroy_geom(struct gctl_req *req __unused,
-+    struct g_class *mp __unused, struct g_geom *gp)
-+{
-+	struct g_eli_softc *sc;
-+
-+	sc = gp->softc;
-+	return (g_eli_destroy(sc, FALSE));
-+}
-+
-+static int
-+g_eli_keyfiles_load(struct hmac_ctx *ctx, const char *provider)
-+{
-+	u_char *keyfile, *data, *size;
-+	char *file, name[64];
-+	int i;
-+
-+	for (i = 0; ; i++) {
-+		snprintf(name, sizeof(name), "%s:geli_keyfile%d", provider, i);
-+		keyfile = preload_search_by_type(name);
-+		if (keyfile == NULL)
-+			return (i);	/* Return number of loaded keyfiles. */
-+		data = preload_search_info(keyfile, MODINFO_ADDR);
-+		if (data == NULL) {
-+			G_ELI_DEBUG(0, "Cannot find key file data for %s.",
-+			    name);
-+			return (0);
-+		}
-+		data = *(void **)data;
-+		size = preload_search_info(keyfile, MODINFO_SIZE);
-+		if (size == NULL) {
-+			G_ELI_DEBUG(0, "Cannot find key file size for %s.",
-+			    name);
-+			return (0);
-+		}
-+		file = preload_search_info(keyfile, MODINFO_NAME);
-+		if (file == NULL) {
-+			G_ELI_DEBUG(0, "Cannot find key file name for %s.",
-+			    name);
-+			return (0);
-+		}
-+		G_ELI_DEBUG(1, "Loaded keyfile %s for %s (type: %s).", file,
-+		    provider, name);
-+		g_eli_crypto_hmac_update(ctx, data, *(size_t *)size);
-+	}
-+}
-+
-+static void
-+g_eli_keyfiles_clear(const char *provider)
-+{
-+	u_char *keyfile, *data, *size;
-+	char name[64];
-+	int i;
-+
-+	for (i = 0; ; i++) {
-+		snprintf(name, sizeof(name), "%s:geli_keyfile%d", provider, i);
-+		keyfile = preload_search_by_type(name);
-+		if (keyfile == NULL)
-+			return;
-+		data = preload_search_info(keyfile, MODINFO_ADDR);
-+		size = preload_search_info(keyfile, MODINFO_SIZE);
-+		if (data == NULL || size == NULL)
-+			continue;
-+		data = *(void **)data;
-+		bzero(data, *(size_t *)size);
-+	}
-+}
-+
-+/*
-+ * Tasting is only made on boot.
-+ * We detect providers which should be attached before root is mounted.
-+ */
-+static struct g_geom *
-+g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
-+{
-+	struct g_eli_metadata md;
-+	struct g_geom *gp;
-+	struct hmac_ctx ctx;
-+	char passphrase[256];
-+	u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN];
-+	u_int i, nkey, nkeyfiles, tries;
-+	int error;
-+
-+	g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name);
-+	g_topology_assert();
-+
-+	if (root_mounted() || g_eli_tries == 0)
-+		return (NULL);
-+
-+	G_ELI_DEBUG(3, "Tasting %s.", pp->name);
-+
-+	error = g_eli_read_metadata(mp, pp, &md);
-+	if (error != 0)
-+		return (NULL);
-+	gp = NULL;
-+
-+	if (strcmp(md.md_magic, G_ELI_MAGIC) != 0)
-+		return (NULL);
-+	if (md.md_version > G_ELI_VERSION) {
-+		printf("geom_eli.ko module is too old to handle %s.\n",
-+		    pp->name);
-+		return (NULL);
-+	}
-+	if (md.md_provsize != pp->mediasize)
-+		return (NULL);
-+	/* Should we attach it on boot? */
-+	if (!(md.md_flags & G_ELI_FLAG_BOOT))
-+		return (NULL);
-+	if (md.md_keys == 0x00) {
-+		G_ELI_DEBUG(0, "No valid keys on %s.", pp->name);
-+		return (NULL);
-+	}
-+	if (md.md_iterations == -1) {
-+		/* If there is no passphrase, we try only once. */
-+		tries = 1;
-+	} else {
-+		/* Ask for the passphrase no more than g_eli_tries times. */
-+		tries = g_eli_tries;
-+	}
-+
-+	for (i = 0; i < tries; i++) {
-+		g_eli_crypto_hmac_init(&ctx, NULL, 0);
-+
-+		/*
-+		 * Load all key files.
-+		 */
-+		nkeyfiles = g_eli_keyfiles_load(&ctx, pp->name);
-+
-+		if (nkeyfiles == 0 && md.md_iterations == -1) {
-+			/*
-+			 * No key files and no passphrase, something is
-+			 * definitely wrong here.
-+			 * geli(8) doesn't allow for such situation, so assume
-+			 * that there was really no passphrase and in that case
-+			 * key files are no properly defined in loader.conf.
-+			 */
-+			G_ELI_DEBUG(0,
-+			    "Found no key files in loader.conf for %s.",
-+			    pp->name);
-+			return (NULL);
-+		}
-+
-+		/* Ask for the passphrase if defined. */
-+		if (md.md_iterations >= 0) {
-+			printf("Enter passphrase for %s: ", pp->name);
-+			gets(passphrase, sizeof(passphrase),
-+			    g_eli_visible_passphrase);
-+		}
-+
-+		/*
-+		 * 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));
-+			bzero(passphrase, sizeof(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);
-+			bzero(passphrase, sizeof(passphrase));
-+			g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
-+			bzero(dkey, sizeof(dkey));
-+		}
-+
-+		g_eli_crypto_hmac_final(&ctx, key, 0);
-+
-+		/*
-+		 * Decrypt Master-Key.
-+		 */
-+		error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
-+		bzero(key, sizeof(key));
-+		if (error == -1) {
-+			if (i == tries - 1) {
-+				G_ELI_DEBUG(0,
-+				    "Wrong key for %s. No tries left.",
-+				    pp->name);
-+				g_eli_keyfiles_clear(pp->name);
-+				return (NULL);
-+			}
-+			G_ELI_DEBUG(0, "Wrong key for %s. Tries left: %u.",
-+			    pp->name, tries - i - 1);
-+			/* Try again. */
-+			continue;
-+		} else if (error > 0) {
-+			G_ELI_DEBUG(0, "Cannot decrypt Master Key for %s (error=%d).",
-+			    pp->name, error);
-+			g_eli_keyfiles_clear(pp->name);
-+			return (NULL);
-+		}
-+		G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
-+		break;
-+	}
-+
-+	/*
-+	 * We have correct key, let's attach provider.
-+	 */
-+	gp = g_eli_create(NULL, mp, pp, &md, mkey, nkey);
-+	bzero(mkey, sizeof(mkey));
-+	bzero(&md, sizeof(md));
-+	if (gp == NULL) {
-+		G_ELI_DEBUG(0, "Cannot create device %s%s.", pp->name,
-+		    G_ELI_SUFFIX);
-+		return (NULL);
-+	}
-+	return (gp);
-+}
-+
-+static void
-+g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
-+    struct g_consumer *cp, struct g_provider *pp)
-+{
-+	struct g_eli_softc *sc;
-+
-+	g_topology_assert();
-+	sc = gp->softc;
-+	if (sc == NULL)
-+		return;
-+	if (pp != NULL || cp != NULL)
-+		return;	/* Nothing here. */
-+	sbuf_printf(sb, "%s<Flags>", indent);
-+	if (sc->sc_flags == 0)
-+		sbuf_printf(sb, "NONE");
-+	else {
-+		int first = 1;
-+
-+#define ADD_FLAG(flag, name)	do {					\
-+	if (sc->sc_flags & (flag)) {					\
-+		if (!first)						\
-+			sbuf_printf(sb, ", ");				\
-+		else							\
-+			first = 0;					\
-+		sbuf_printf(sb, name);					\
-+	}								\
-+} while (0)
-+		ADD_FLAG(G_ELI_FLAG_SUSPEND, "SUSPEND");
-+		ADD_FLAG(G_ELI_FLAG_SINGLE_KEY, "SINGLE-KEY");
-+		ADD_FLAG(G_ELI_FLAG_NATIVE_BYTE_ORDER, "NATIVE-BYTE-ORDER");
-+		ADD_FLAG(G_ELI_FLAG_ONETIME, "ONETIME");
-+		ADD_FLAG(G_ELI_FLAG_BOOT, "BOOT");
-+		ADD_FLAG(G_ELI_FLAG_WO_DETACH, "W-DETACH");
-+		ADD_FLAG(G_ELI_FLAG_RW_DETACH, "RW-DETACH");
-+		ADD_FLAG(G_ELI_FLAG_AUTH, "AUTH");
-+		ADD_FLAG(G_ELI_FLAG_WOPEN, "W-OPEN");
-+		ADD_FLAG(G_ELI_FLAG_DESTROY, "DESTROY");
-+		ADD_FLAG(G_ELI_FLAG_RO, "READ-ONLY");
-+#undef  ADD_FLAG
-+	}
-+	sbuf_printf(sb, "</Flags>\n");
-+
-+	if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) {
-+		sbuf_printf(sb, "%s<UsedKey>%u</UsedKey>\n", indent,
-+		    sc->sc_nkey);
-+	}
-+	sbuf_printf(sb, "%s<Crypto>", indent);
-+	switch (sc->sc_crypto) {
-+	case G_ELI_CRYPTO_HW:
-+		sbuf_printf(sb, "hardware");
-+		break;
-+	case G_ELI_CRYPTO_SW:
-+		sbuf_printf(sb, "software");
-+		break;
-+	default:
-+		sbuf_printf(sb, "UNKNOWN");
-+		break;
-+	}
-+	sbuf_printf(sb, "</Crypto>\n");
-+	if (sc->sc_flags & G_ELI_FLAG_AUTH) {
-+		sbuf_printf(sb,
-+		    "%s<AuthenticationAlgorithm>%s</AuthenticationAlgorithm>\n",
-+		    indent, g_eli_algo2str(sc->sc_aalgo));
-+	}
-+	sbuf_printf(sb, "%s<KeyLength>%u</KeyLength>\n", indent,
-+	    sc->sc_ekeylen);
-+	sbuf_printf(sb, "%s<EncryptionAlgorithm>%s</EncryptionAlgorithm>\n", indent,
-+	    g_eli_algo2str(sc->sc_ealgo));
-+	sbuf_printf(sb, "%s<State>%s</State>\n", indent,
-+	    (sc->sc_flags & G_ELI_FLAG_SUSPEND) ? "SUSPENDED" : "ACTIVE");
-+}
-+
-+static void
-+g_eli_shutdown_pre_sync(void *arg, int howto)
-+{
-+	struct g_class *mp;
-+	struct g_geom *gp, *gp2;
-+	struct g_provider *pp;
-+	struct g_eli_softc *sc;
-+	int error;
-+
-+	mp = arg;
-+	DROP_GIANT();
-+	g_topology_lock();
-+	LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
-+		sc = gp->softc;
-+		if (sc == NULL)
-+			continue;
-+		pp = LIST_FIRST(&gp->provider);
-+		KASSERT(pp != NULL, ("No provider? gp=%p (%s)", gp, gp->name));
-+		if (pp->acr + pp->acw + pp->ace == 0)
-+			error = g_eli_destroy(sc, TRUE);
-+		else {
-+			sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
-+			gp->access = g_eli_access;
-+		}
-+	}
-+	g_topology_unlock();
-+	PICKUP_GIANT();
-+}
-+
-+static void
-+g_eli_init(struct g_class *mp)
-+{
-+
-+	g_eli_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
-+	    g_eli_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
-+	if (g_eli_pre_sync == NULL)
-+		G_ELI_DEBUG(0, "Warning! Cannot register shutdown event.");
-+}
-+
-+static void
-+g_eli_fini(struct g_class *mp)
-+{
-+
-+	if (g_eli_pre_sync != NULL)
-+		EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_eli_pre_sync);
-+}
-+
-+DECLARE_GEOM_CLASS(g_eli_class, g_eli);
-+MODULE_DEPEND(g_eli, crypto, 1, 1, 1);
---- /dev/null
-+++ b/sys/geom/eli/g_eli_privacy.c
-@@ -0,0 +1,330 @@
-+/*-
-+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd at FreeBSD.org>
-+ * 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 AUTHORS 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 AUTHORS 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.
-+ */
-+
-+#include <sys/cdefs.h>
-+__FBSDID("$FreeBSD$");
-+
-+#include <sys/param.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/linker.h>
-+#include <sys/module.h>
-+#include <sys/lock.h>
-+#include <sys/mutex.h>
-+#include <sys/bio.h>
-+#include <sys/sysctl.h>
-+#include <sys/malloc.h>
-+#include <sys/kthread.h>
-+#include <sys/proc.h>
-+#include <sys/sched.h>
-+#include <sys/smp.h>
-+#include <sys/uio.h>
-+#include <sys/vnode.h>
-+
-+#include <vm/uma.h>
-+
-+#include <geom/geom.h>
-+#include <geom/eli/g_eli.h>
-+#include <geom/eli/pkcs5v2.h>
-+
-+/*
-+ * Code paths:
-+ * BIO_READ:
-+ *	g_eli_start -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
-+ * BIO_WRITE:
-+ *	g_eli_start -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+
-+MALLOC_DECLARE(M_ELI);
-+
-+/*
-+ * The function is called after we read and decrypt data.
-+ *
-+ * g_eli_start -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> G_ELI_CRYPTO_READ_DONE -> g_io_deliver
-+ */
-+static int
-+g_eli_crypto_read_done(struct cryptop *crp)
-+{
-+	struct g_eli_softc *sc;
-+	struct bio *bp;
-+
-+	if (crp->crp_etype == EAGAIN) {
-+		if (g_eli_crypto_rerun(crp) == 0)
-+			return (0);
-+	}
-+	bp = (struct bio *)crp->crp_opaque;
-+	bp->bio_inbed++;
-+	if (crp->crp_etype == 0) {
-+		G_ELI_DEBUG(3, "Crypto READ request done (%d/%d).",
-+		    bp->bio_inbed, bp->bio_children);
-+		bp->bio_completed += crp->crp_olen;
-+	} else {
-+		G_ELI_DEBUG(1, "Crypto READ request failed (%d/%d) error=%d.",
-+		    bp->bio_inbed, bp->bio_children, crp->crp_etype);
-+		if (bp->bio_error == 0)
-+			bp->bio_error = crp->crp_etype;
-+	}
-+	/*
-+	 * Do we have all sectors already?
-+	 */
-+	if (bp->bio_inbed < bp->bio_children)
-+		return (0);
-+	free(bp->bio_driver2, M_ELI);
-+	bp->bio_driver2 = NULL;
-+	if (bp->bio_error != 0) {
-+		G_ELI_LOGREQ(0, bp, "Crypto READ request failed (error=%d).",
-+		    bp->bio_error);
-+		bp->bio_completed = 0;
-+	}
-+	/*
-+	 * Read is finished, send it up.
-+	 */
-+	sc = bp->bio_to->geom->softc;
-+	g_io_deliver(bp, bp->bio_error);
-+	atomic_subtract_int(&sc->sc_inflight, 1);
-+	return (0);
-+}
-+
-+/*
-+ * The function is called after data encryption.
-+ *
-+ * g_eli_start -> g_eli_crypto_run -> G_ELI_CRYPTO_WRITE_DONE -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+static int
-+g_eli_crypto_write_done(struct cryptop *crp)
-+{
-+	struct g_eli_softc *sc;
-+	struct g_geom *gp;
-+	struct g_consumer *cp;
-+	struct bio *bp, *cbp;
-+
-+	if (crp->crp_etype == EAGAIN) {
-+		if (g_eli_crypto_rerun(crp) == 0)
-+			return (0);
-+	}
-+	bp = (struct bio *)crp->crp_opaque;
-+	bp->bio_inbed++;
-+	if (crp->crp_etype == 0) {
-+		G_ELI_DEBUG(3, "Crypto WRITE request done (%d/%d).",
-+		    bp->bio_inbed, bp->bio_children);
-+	} else {
-+		G_ELI_DEBUG(1, "Crypto WRITE request failed (%d/%d) error=%d.",
-+		    bp->bio_inbed, bp->bio_children, crp->crp_etype);
-+		if (bp->bio_error == 0)
-+			bp->bio_error = crp->crp_etype;
-+	}
-+	/*
-+	 * All sectors are already encrypted?
-+	 */
-+	if (bp->bio_inbed < bp->bio_children)
-+		return (0);
-+	bp->bio_inbed = 0;
-+	bp->bio_children = 1;
-+	cbp = bp->bio_driver1;
-+	bp->bio_driver1 = NULL;
-+	gp = bp->bio_to->geom;
-+	if (bp->bio_error != 0) {
-+		G_ELI_LOGREQ(0, bp, "Crypto WRITE request failed (error=%d).",
-+		    bp->bio_error);
-+		free(bp->bio_driver2, M_ELI);
-+		bp->bio_driver2 = NULL;
-+		g_destroy_bio(cbp);
-+		sc = gp->softc;
-+		g_io_deliver(bp, bp->bio_error);
-+		atomic_subtract_int(&sc->sc_inflight, 1);
-+		return (0);
-+	}
-+	cbp->bio_data = bp->bio_driver2;
-+	cbp->bio_done = g_eli_write_done;
-+	cp = LIST_FIRST(&gp->consumer);
-+	cbp->bio_to = cp->provider;
-+	G_ELI_LOGREQ(2, cbp, "Sending request.");
-+	/*
-+	 * Send encrypted data to the provider.
-+	 */
-+	g_io_request(cbp, cp);
-+	return (0);
-+}
-+
-+/*
-+ * The function is called to read encrypted data.
-+ *
-+ * g_eli_start -> G_ELI_CRYPTO_READ -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
-+ */
-+void
-+g_eli_crypto_read(struct g_eli_softc *sc, struct bio *bp, boolean_t fromworker)
-+{
-+	struct g_consumer *cp;
-+	struct bio *cbp;
-+
-+	if (!fromworker) {
-+		/*
-+		 * We are not called from the worker thread, so check if
-+		 * device is suspended.
-+		 */
-+		mtx_lock(&sc->sc_queue_mtx);
-+		if (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
-+			/*
-+			 * If device is suspended, we place the request onto
-+			 * the queue, so it can be handled after resume.
-+			 */
-+			G_ELI_DEBUG(0, "device suspended, move onto queue");
-+			bioq_insert_tail(&sc->sc_queue, bp);
-+			mtx_unlock(&sc->sc_queue_mtx);
-+			wakeup(sc);
-+			return;
-+		}
-+		atomic_add_int(&sc->sc_inflight, 1);
-+		mtx_unlock(&sc->sc_queue_mtx);
-+	}
-+	bp->bio_pflags = 0;
-+	bp->bio_driver2 = NULL;
-+	cbp = bp->bio_driver1;
-+	cbp->bio_done = g_eli_read_done;
-+	cp = LIST_FIRST(&sc->sc_geom->consumer);
-+	cbp->bio_to = cp->provider;
-+	G_ELI_LOGREQ(2, cbp, "Sending request.");
-+	/*
-+	 * Read encrypted data from provider.
-+	 */
-+	g_io_request(cbp, cp);
-+}
-+
-+/*
-+ * This is the main function responsible for cryptography (ie. communication
-+ * with crypto(9) subsystem).
-+ *
-+ * BIO_READ:
-+ *	g_eli_start -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> G_ELI_CRYPTO_RUN -> g_eli_crypto_read_done -> g_io_deliver
-+ * BIO_WRITE:
-+ *	g_eli_start -> G_ELI_CRYPTO_RUN -> g_eli_crypto_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
-+ */
-+void
-+g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp)
-+{
-+	struct g_eli_softc *sc;
-+	struct cryptop *crp;
-+	struct cryptodesc *crd;
-+	struct uio *uio;
-+	struct iovec *iov;
-+	u_int i, nsec, secsize;
-+	int err, error;
-+	off_t dstoff;
-+	size_t size;
-+	u_char *p, *data;
-+
-+	G_ELI_LOGREQ(3, bp, "%s", __func__);
-+
-+	bp->bio_pflags = wr->w_number;
-+	sc = wr->w_softc;
-+	secsize = LIST_FIRST(&sc->sc_geom->provider)->sectorsize;
-+	nsec = bp->bio_length / secsize;
-+
-+	/*
-+	 * Calculate how much memory do we need.
-+	 * We need separate crypto operation for every single sector.
-+	 * It is much faster to calculate total amount of needed memory here and
-+	 * do the allocation once instead of allocating memory in pieces (many,
-+	 * many pieces).
-+	 */
-+	size = sizeof(*crp) * nsec;
-+	size += sizeof(*crd) * nsec;
-+	size += sizeof(*uio) * nsec;
-+	size += sizeof(*iov) * nsec;
-+	/*
-+	 * If we write the data we cannot destroy current bio_data content,
-+	 * so we need to allocate more memory for encrypted data.
-+	 */
-+	if (bp->bio_cmd == BIO_WRITE)
-+		size += bp->bio_length;
-+	p = malloc(size, M_ELI, M_WAITOK);
-+
-+	bp->bio_inbed = 0;
-+	bp->bio_children = nsec;
-+	bp->bio_driver2 = p;
-+
-+	if (bp->bio_cmd == BIO_READ)
-+		data = bp->bio_data;
-+	else {
-+		data = p;
-+		p += bp->bio_length;
-+		bcopy(bp->bio_data, data, bp->bio_length);
-+	}
-+
-+	error = 0;
-+	for (i = 0, dstoff = bp->bio_offset; i < nsec; i++, dstoff += secsize) {
-+		crp = (struct cryptop *)p;	p += sizeof(*crp);
-+		crd = (struct cryptodesc *)p;	p += sizeof(*crd);
-+		uio = (struct uio *)p;		p += sizeof(*uio);
-+		iov = (struct iovec *)p;	p += sizeof(*iov);
-+
-+		iov->iov_len = secsize;
-+		iov->iov_base = data;
-+		data += secsize;
-+
-+		uio->uio_iov = iov;
-+		uio->uio_iovcnt = 1;
-+		uio->uio_segflg = UIO_SYSSPACE;
-+		uio->uio_resid = secsize;
-+
-+		crp->crp_sid = wr->w_sid;
-+		crp->crp_ilen = secsize;
-+		crp->crp_olen = secsize;
-+		crp->crp_opaque = (void *)bp;
-+		crp->crp_buf = (void *)uio;
-+		if (bp->bio_cmd == BIO_WRITE)
-+			crp->crp_callback = g_eli_crypto_write_done;
-+		else /* if (bp->bio_cmd == BIO_READ) */
-+			crp->crp_callback = g_eli_crypto_read_done;
-+		crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
-+		if (g_eli_batch)
-+			crp->crp_flags |= CRYPTO_F_BATCH;
-+		crp->crp_desc = crd;
-+
-+		crd->crd_skip = 0;
-+		crd->crd_len = secsize;
-+		crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
-+		if (sc->sc_nekeys > 1)
-+			crd->crd_flags |= CRD_F_KEY_EXPLICIT;
-+		if (bp->bio_cmd == BIO_WRITE)
-+			crd->crd_flags |= CRD_F_ENCRYPT;
-+		crd->crd_alg = sc->sc_ealgo;
-+		crd->crd_key = g_eli_crypto_key(sc, dstoff, secsize);
-+		crd->crd_klen = sc->sc_ekeylen;
-+		if (sc->sc_ealgo == CRYPTO_AES_XTS)
-+			crd->crd_klen <<= 1;
-+		g_eli_crypto_ivgen(sc, dstoff, crd->crd_iv,
-+		    sizeof(crd->crd_iv));
-+		crd->crd_next = NULL;
-+
-+		crp->crp_etype = 0;
-+		err = crypto_dispatch(crp);
-+		if (error == 0)
-+			error = err;
-+	}
-+	if (bp->bio_error == 0)
-+		bp->bio_error = error;
-+}

Modified: trunk/freebsd-utils/debian/patches/series
===================================================================
--- trunk/freebsd-utils/debian/patches/series	2011-11-23 21:22:02 UTC (rev 3897)
+++ trunk/freebsd-utils/debian/patches/series	2011-11-25 18:33:26 UTC (rev 3898)
@@ -1,5 +1,4 @@
 000_devd_usb.diff
-000_sys_geom.diff
 001_unused.diff
 001_dmesg.diff
 002_ifconfig.diff

Modified: trunk/freebsd-utils/debian/rules
===================================================================
--- trunk/freebsd-utils/debian/rules	2011-11-23 21:22:02 UTC (rev 3897)
+++ trunk/freebsd-utils/debian/rules	2011-11-25 18:33:26 UTC (rev 3898)
@@ -78,6 +78,7 @@
 		 include/rpcsvc/nlm_prot.x include/rpcsvc/mount.x \
 		 sys/kgssapi/gssd.x \
 		 usr.bin/showmount \
+		 usr.sbin/powerd \
 	; do \
 	    svn export $(SVN)/$$i $(ORIGDIR)/$$i ; \
 	done




More information about the Glibc-bsd-commits mailing list