g_eli.h revision 213070
11897Swollman/*-
21897Swollman * Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
31897Swollman * All rights reserved.
41897Swollman *
51897Swollman * Redistribution and use in source and binary forms, with or without
61897Swollman * modification, are permitted provided that the following conditions
71897Swollman * are met:
8100441Scharnier * 1. Redistributions of source code must retain the above copyright
91897Swollman *    notice, this list of conditions and the following disclaimer.
101897Swollman * 2. Redistributions in binary form must reproduce the above copyright
111897Swollman *    notice, this list of conditions and the following disclaimer in the
12100441Scharnier *    documentation and/or other materials provided with the distribution.
131897Swollman *
141897Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
151897Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16100441Scharnier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171897Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
181897Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191897Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20100441Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211897Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221897Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231897Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24100441Scharnier * SUCH DAMAGE.
251897Swollman *
261897Swollman * $FreeBSD: head/sys/geom/eli/g_eli.h 213070 2010-09-23 11:58:36Z pjd $
271897Swollman */
281897Swollman
2912798Swpaul#ifndef	_G_ELI_H_
30100441Scharnier#define	_G_ELI_H_
311897Swollman
32146833Sstefanf#include <sys/endian.h>
3312798Swpaul#include <sys/errno.h>
341897Swollman#include <sys/malloc.h>
3527935Scharnier#include <crypto/sha2/sha2.h>
361897Swollman#include <opencrypto/cryptodev.h>
37100441Scharnier#ifdef _KERNEL
38100441Scharnier#include <sys/bio.h>
39100441Scharnier#include <sys/libkern.h>
401897Swollman#include <geom/geom.h>
418874Srgrimes#else
4212798Swpaul#include <stdio.h>
431897Swollman#include <string.h>
4427935Scharnier#include <strings.h>
45200462Sdelphij#endif
461897Swollman#ifndef _OpenSSL_
4717142Sjkh#include <sys/md5.h>
4817142Sjkh#endif
49152398Sdwmalone
501897Swollman#define	G_ELI_CLASS_NAME	"ELI"
511897Swollman#define	G_ELI_MAGIC		"GEOM::ELI"
521897Swollman#define	G_ELI_SUFFIX		".eli"
5312798Swpaul
5412798Swpaul/*
551897Swollman * Version history:
5612798Swpaul * 0 - Initial version number.
5712798Swpaul * 1 - Added data authentication support (md_aalgo field and
581897Swollman *     G_ELI_FLAG_AUTH flag).
59152398Sdwmalone * 2 - Added G_ELI_FLAG_READONLY.
601897Swollman * 3 - Added 'configure' subcommand.
6112798Swpaul * 4 - IV is generated from offset converted to little-endian
62241737Sed *     (flag G_ELI_FLAG_NATIVE_BYTE_ORDER will be set for older versions).
63241737Sed * 5 - Added multiple encrypton keys and AES-XTS support.
641897Swollman */
6512798Swpaul#define	G_ELI_VERSION		5
6612798Swpaul
671897Swollman/* ON DISK FLAGS. */
6812798Swpaul/* Use random, onetime keys. */
691897Swollman#define	G_ELI_FLAG_ONETIME		0x00000001
7092921Simp/* Ask for the passphrase from the kernel, before mounting root. */
711897Swollman#define	G_ELI_FLAG_BOOT			0x00000002
721897Swollman/* Detach on last close, if we were open for writing. */
738874Srgrimes#define	G_ELI_FLAG_WO_DETACH		0x00000004
741897Swollman/* Detach on last close. */
7517142Sjkh#define	G_ELI_FLAG_RW_DETACH		0x00000008
76152398Sdwmalone/* Provide data authentication. */
771897Swollman#define	G_ELI_FLAG_AUTH			0x00000010
7812798Swpaul/* Provider is read-only, we should deny all write attempts. */
791897Swollman#define	G_ELI_FLAG_RO			0x00000020
801897Swollman/* RUNTIME FLAGS. */
811897Swollman/* Provider was open for writing. */
821897Swollman#define	G_ELI_FLAG_WOPEN		0x00010000
831897Swollman/* Destroy device. */
841897Swollman#define	G_ELI_FLAG_DESTROY		0x00020000
858874Srgrimes/* Provider uses native byte-order for IV generation. */
861897Swollman#define	G_ELI_FLAG_NATIVE_BYTE_ORDER	0x00040000
8717142Sjkh/* Provider uses single encryption key. */
88152398Sdwmalone#define	G_ELI_FLAG_SINGLE_KEY		0x00080000
891897Swollman
901897Swollman#define	SHA512_MDLEN		64
911897Swollman#define	G_ELI_AUTH_SECKEYLEN	SHA256_DIGEST_LENGTH
921897Swollman
931897Swollman#define	G_ELI_MAXMKEYS		2
948874Srgrimes#define	G_ELI_MAXKEYLEN		64
951897Swollman#define	G_ELI_USERKEYLEN	G_ELI_MAXKEYLEN
9612798Swpaul#define	G_ELI_DATAKEYLEN	G_ELI_MAXKEYLEN
97152398Sdwmalone#define	G_ELI_AUTHKEYLEN	G_ELI_MAXKEYLEN
981897Swollman#define	G_ELI_IVKEYLEN		G_ELI_MAXKEYLEN
991897Swollman#define	G_ELI_SALTLEN		64
1001897Swollman#define	G_ELI_DATAIVKEYLEN	(G_ELI_DATAKEYLEN + G_ELI_IVKEYLEN)
1011897Swollman/* Data-Key, IV-Key, HMAC_SHA512(Derived-Key, Data-Key+IV-Key) */
1021897Swollman#define	G_ELI_MKEYLEN		(G_ELI_DATAIVKEYLEN + SHA512_MDLEN)
1031897Swollman#define	G_ELI_OVERWRITES	5
1041897Swollman/* Switch data encryption key every 2^20 blocks. */
1051897Swollman#define	G_ELI_KEY_SHIFT		20
1061897Swollman
1071897Swollman#ifdef _KERNEL
1088874Srgrimesextern u_int g_eli_debug;
1091897Swollmanextern u_int g_eli_overwrites;
1101897Swollmanextern u_int g_eli_batch;
111152398Sdwmalone
1121897Swollman#define	G_ELI_CRYPTO_HW		1
1131897Swollman#define	G_ELI_CRYPTO_SW		2
1141897Swollman
1151897Swollman#define	G_ELI_DEBUG(lvl, ...)	do {					\
1161897Swollman	if (g_eli_debug >= (lvl)) {					\
117100441Scharnier		printf("GEOM_ELI");					\
1181897Swollman		if (g_eli_debug > 0)					\
1191897Swollman			printf("[%u]", lvl);				\
1201897Swollman		printf(": ");						\
1211897Swollman		printf(__VA_ARGS__);					\
1221897Swollman		printf("\n");						\
12317142Sjkh	}								\
124152398Sdwmalone} while (0)
1251897Swollman#define	G_ELI_LOGREQ(lvl, bp, ...)	do {				\
1261897Swollman	if (g_eli_debug >= (lvl)) {					\
1271897Swollman		printf("GEOM_ELI");					\
1281897Swollman		if (g_eli_debug > 0)					\
129152398Sdwmalone			printf("[%u]", lvl);				\
130152398Sdwmalone		printf(": ");						\
1311897Swollman		printf(__VA_ARGS__);					\
1321897Swollman		printf(" ");						\
1331897Swollman		g_print_bio(bp);					\
1341897Swollman		printf("\n");						\
1351897Swollman	}								\
1361897Swollman} while (0)
1371897Swollman
1381897Swollmanstruct g_eli_worker {
1391897Swollman	struct g_eli_softc	*w_softc;
14012798Swpaul	struct proc		*w_proc;
14112798Swpaul	u_int			 w_number;
14212798Swpaul	uint64_t		 w_sid;
14312798Swpaul	LIST_ENTRY(g_eli_worker) w_next;
14412798Swpaul};
1451897Swollman
1461897Swollmanstruct g_eli_softc {
1471897Swollman	struct g_geom	 *sc_geom;
1481897Swollman	u_int		  sc_crypto;
1491897Swollman	uint8_t		  sc_mkey[G_ELI_DATAIVKEYLEN];
1501897Swollman	uint8_t		**sc_ekeys;
1511897Swollman	u_int		  sc_nekeys;
152152398Sdwmalone	u_int		  sc_ealgo;
153152398Sdwmalone	u_int		  sc_ekeylen;
1541897Swollman	uint8_t		  sc_akey[G_ELI_AUTHKEYLEN];
1551897Swollman	u_int		  sc_aalgo;
1561897Swollman	u_int		  sc_akeylen;
1571897Swollman	u_int		  sc_alen;
158152398Sdwmalone	SHA256_CTX	  sc_akeyctx;
159152398Sdwmalone	uint8_t		  sc_ivkey[G_ELI_IVKEYLEN];
1601897Swollman	SHA256_CTX	  sc_ivctx;
1611897Swollman	int		  sc_nkey;
1621897Swollman	uint32_t	  sc_flags;
1631897Swollman	off_t		  sc_mediasize;
1641897Swollman	size_t		  sc_sectorsize;
1651897Swollman	u_int		  sc_bytes_per_sector;
1661897Swollman	u_int		  sc_data_per_sector;
1671897Swollman
1681897Swollman	/* Only for software cryptography. */
169152398Sdwmalone	struct bio_queue_head sc_queue;
1701897Swollman	struct mtx	  sc_queue_mtx;
1711897Swollman	LIST_HEAD(, g_eli_worker) sc_workers;
1721897Swollman};
1731897Swollman#define	sc_name		 sc_geom->name
1741897Swollman#endif	/* _KERNEL */
1751897Swollman
1761897Swollmanstruct g_eli_metadata {
1771897Swollman	char		md_magic[16];	/* Magic value. */
1781897Swollman	uint32_t	md_version;	/* Version number. */
1791897Swollman	uint32_t	md_flags;	/* Additional flags. */
1801897Swollman	uint16_t	md_ealgo;	/* Encryption algorithm. */
1811897Swollman	uint16_t	md_keylen;	/* Key length. */
1821897Swollman	uint16_t	md_aalgo;	/* Authentication algorithm. */
1831897Swollman	uint64_t	md_provsize;	/* Provider's size. */
1841897Swollman	uint32_t	md_sectorsize;	/* Sector size. */
1851897Swollman	uint8_t		md_keys;	/* Available keys. */
1861897Swollman	int32_t		md_iterations;	/* Number of iterations for PKCS#5v2. */
18717142Sjkh	uint8_t		md_salt[G_ELI_SALTLEN]; /* Salt. */
188152398Sdwmalone			/* Encrypted master key (IV-key, Data-key, HMAC). */
1891897Swollman	uint8_t		md_mkeys[G_ELI_MAXMKEYS * G_ELI_MKEYLEN];
1901897Swollman	u_char		md_hash[16];	/* MD5 hash. */
1911897Swollman} __packed;
1921897Swollman#ifndef _OpenSSL_
1931897Swollmanstatic __inline void
1941897Swollmaneli_metadata_encode(struct g_eli_metadata *md, u_char *data)
1951897Swollman{
1961897Swollman	MD5_CTX ctx;
19717142Sjkh	u_char *p;
198152398Sdwmalone
1991897Swollman	p = data;
2001897Swollman	bcopy(md->md_magic, p, sizeof(md->md_magic)); p += sizeof(md->md_magic);
2011897Swollman	le32enc(p, md->md_version);	p += sizeof(md->md_version);
2021897Swollman	le32enc(p, md->md_flags);	p += sizeof(md->md_flags);
2031897Swollman	le16enc(p, md->md_ealgo);	p += sizeof(md->md_ealgo);
2041897Swollman	le16enc(p, md->md_keylen);	p += sizeof(md->md_keylen);
2051897Swollman	le16enc(p, md->md_aalgo);	p += sizeof(md->md_aalgo);
2061897Swollman	le64enc(p, md->md_provsize);	p += sizeof(md->md_provsize);
2071897Swollman	le32enc(p, md->md_sectorsize);	p += sizeof(md->md_sectorsize);
2081897Swollman	*p = md->md_keys;		p += sizeof(md->md_keys);
2091897Swollman	le32enc(p, md->md_iterations);	p += sizeof(md->md_iterations);
2101897Swollman	bcopy(md->md_salt, p, sizeof(md->md_salt)); p += sizeof(md->md_salt);
2111897Swollman	bcopy(md->md_mkeys, p, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
2121897Swollman	MD5Init(&ctx);
2131897Swollman	MD5Update(&ctx, data, p - data);
2141897Swollman	MD5Final(md->md_hash, &ctx);
2151897Swollman	bcopy(md->md_hash, p, sizeof(md->md_hash));
2161897Swollman}
2171897Swollmanstatic __inline int
2181897Swollmaneli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
21917142Sjkh{
22017142Sjkh	MD5_CTX ctx;
2211897Swollman	const u_char *p;
2221897Swollman
22312798Swpaul	p = data + sizeof(md->md_magic) + sizeof(md->md_version);
224152398Sdwmalone	md->md_flags = le32dec(p);	p += sizeof(md->md_flags);
2251897Swollman	md->md_ealgo = le16dec(p);	p += sizeof(md->md_ealgo);
2261897Swollman	md->md_keylen = le16dec(p);	p += sizeof(md->md_keylen);
2271897Swollman	md->md_provsize = le64dec(p);	p += sizeof(md->md_provsize);
2281897Swollman	md->md_sectorsize = le32dec(p);	p += sizeof(md->md_sectorsize);
2291897Swollman	md->md_keys = *p;		p += sizeof(md->md_keys);
23017142Sjkh	md->md_iterations = le32dec(p);	p += sizeof(md->md_iterations);
2311897Swollman	bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
2321897Swollman	bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
2331897Swollman	MD5Init(&ctx);
2341897Swollman	MD5Update(&ctx, data, p - data);
2351897Swollman	MD5Final(md->md_hash, &ctx);
2361897Swollman	if (bcmp(md->md_hash, p, 16) != 0)
23712798Swpaul		return (EINVAL);
238152398Sdwmalone	return (0);
23912798Swpaul}
24012798Swpaul
24112798Swpaulstatic __inline int
2421897Swollmaneli_metadata_decode_v1v2v3v4v5(const u_char *data, struct g_eli_metadata *md)
2431897Swollman{
244152398Sdwmalone	MD5_CTX ctx;
2451897Swollman	const u_char *p;
2461897Swollman
2471897Swollman	p = data + sizeof(md->md_magic) + sizeof(md->md_version);
2481897Swollman	md->md_flags = le32dec(p);	p += sizeof(md->md_flags);
2491897Swollman	md->md_ealgo = le16dec(p);	p += sizeof(md->md_ealgo);
2508874Srgrimes	md->md_keylen = le16dec(p);	p += sizeof(md->md_keylen);
2511897Swollman	md->md_aalgo = le16dec(p);	p += sizeof(md->md_aalgo);
2521897Swollman	md->md_provsize = le64dec(p);	p += sizeof(md->md_provsize);
253152398Sdwmalone	md->md_sectorsize = le32dec(p);	p += sizeof(md->md_sectorsize);
2541897Swollman	md->md_keys = *p;		p += sizeof(md->md_keys);
2551897Swollman	md->md_iterations = le32dec(p);	p += sizeof(md->md_iterations);
25627935Scharnier	bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
2571897Swollman	bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
2581897Swollman	MD5Init(&ctx);
2591897Swollman	MD5Update(&ctx, data, p - data);
2601897Swollman	MD5Final(md->md_hash, &ctx);
2611897Swollman	if (bcmp(md->md_hash, p, 16) != 0)
2628874Srgrimes		return (EINVAL);
2631897Swollman	return (0);
26417142Sjkh}
265152398Sdwmalonestatic __inline int
2661897Swollmaneli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
2671897Swollman{
2681897Swollman	int error;
2691897Swollman
2701897Swollman	bcopy(data, md->md_magic, sizeof(md->md_magic));
2711897Swollman	md->md_version = le32dec(data + sizeof(md->md_magic));
2721897Swollman	switch (md->md_version) {
2731897Swollman	case 0:
2741897Swollman		error = eli_metadata_decode_v0(data, md);
2751897Swollman		break;
276152398Sdwmalone	case 1:
2771897Swollman	case 2:
2781897Swollman	case 3:
2791897Swollman	case 4:
2801897Swollman	case 5:
28127935Scharnier		error = eli_metadata_decode_v1v2v3v4v5(data, md);
2821897Swollman		break;
2831897Swollman	default:
2841897Swollman		error = EINVAL;
2851897Swollman		break;
2861897Swollman	}
287152398Sdwmalone	return (error);
2881897Swollman}
2891897Swollman#endif	/* !_OpenSSL */
2908874Srgrimes
2911897Swollmanstatic __inline u_int
2921897Swollmang_eli_str2ealgo(const char *name)
293152398Sdwmalone{
2941897Swollman
2951897Swollman	if (strcasecmp("null", name) == 0)
2961897Swollman		return (CRYPTO_NULL_CBC);
2971897Swollman	else if (strcasecmp("null-cbc", name) == 0)
2981897Swollman		return (CRYPTO_NULL_CBC);
2991897Swollman	else if (strcasecmp("aes", name) == 0)
3001897Swollman		return (CRYPTO_AES_XTS);
3018874Srgrimes	else if (strcasecmp("aes-cbc", name) == 0)
3021897Swollman		return (CRYPTO_AES_CBC);
3031897Swollman	else if (strcasecmp("aes-xts", name) == 0)
304152398Sdwmalone		return (CRYPTO_AES_XTS);
3051897Swollman	else if (strcasecmp("blowfish", name) == 0)
3061897Swollman		return (CRYPTO_BLF_CBC);
3071897Swollman	else if (strcasecmp("blowfish-cbc", name) == 0)
3081897Swollman		return (CRYPTO_BLF_CBC);
3091897Swollman	else if (strcasecmp("camellia", name) == 0)
3101897Swollman		return (CRYPTO_CAMELLIA_CBC);
3111897Swollman	else if (strcasecmp("camellia-cbc", name) == 0)
3121897Swollman		return (CRYPTO_CAMELLIA_CBC);
3138874Srgrimes	else if (strcasecmp("3des", name) == 0)
3141897Swollman		return (CRYPTO_3DES_CBC);
3151897Swollman	else if (strcasecmp("3des-cbc", name) == 0)
316152398Sdwmalone		return (CRYPTO_3DES_CBC);
3171897Swollman	return (CRYPTO_ALGORITHM_MIN - 1);
3181897Swollman}
3191897Swollman
3201897Swollmanstatic __inline u_int
3211897Swollmang_eli_str2aalgo(const char *name)
3221897Swollman{
3231897Swollman
3241897Swollman	if (strcasecmp("hmac/md5", name) == 0)
3251897Swollman		return (CRYPTO_MD5_HMAC);
326152398Sdwmalone	else if (strcasecmp("hmac/sha1", name) == 0)
3271897Swollman		return (CRYPTO_SHA1_HMAC);
3281897Swollman	else if (strcasecmp("hmac/ripemd160", name) == 0)
3291897Swollman		return (CRYPTO_RIPEMD160_HMAC);
3301897Swollman	else if (strcasecmp("hmac/sha256", name) == 0)
3311897Swollman		return (CRYPTO_SHA2_256_HMAC);
3321897Swollman	else if (strcasecmp("hmac/sha384", name) == 0)
3331897Swollman		return (CRYPTO_SHA2_384_HMAC);
3341897Swollman	else if (strcasecmp("hmac/sha512", name) == 0)
33512798Swpaul		return (CRYPTO_SHA2_512_HMAC);
33612798Swpaul	return (CRYPTO_ALGORITHM_MIN - 1);
33712798Swpaul}
33812798Swpaul
33912798Swpaulstatic __inline const char *
34012798Swpaulg_eli_algo2str(u_int algo)
34112798Swpaul{
34212798Swpaul
34312798Swpaul	switch (algo) {
34412798Swpaul	case CRYPTO_NULL_CBC:
34512798Swpaul		return ("NULL");
34612798Swpaul	case CRYPTO_AES_CBC:
34712798Swpaul		return ("AES-CBC");
34812798Swpaul	case CRYPTO_AES_XTS:
34912798Swpaul		return ("AES-XTS");
35012798Swpaul	case CRYPTO_BLF_CBC:
35112798Swpaul		return ("Blowfish-CBC");
35212798Swpaul	case CRYPTO_CAMELLIA_CBC:
35312798Swpaul		return ("CAMELLIA-CBC");
35412798Swpaul	case CRYPTO_3DES_CBC:
35512798Swpaul		return ("3DES-CBC");
35612798Swpaul	case CRYPTO_MD5_HMAC:
35712798Swpaul		return ("HMAC/MD5");
35812798Swpaul	case CRYPTO_SHA1_HMAC:
35912798Swpaul		return ("HMAC/SHA1");
36012798Swpaul	case CRYPTO_RIPEMD160_HMAC:
36112798Swpaul		return ("HMAC/RIPEMD160");
36212798Swpaul	case CRYPTO_SHA2_256_HMAC:
36312798Swpaul		return ("HMAC/SHA256");
36412798Swpaul	case CRYPTO_SHA2_384_HMAC:
36512798Swpaul		return ("HMAC/SHA384");
36612798Swpaul	case CRYPTO_SHA2_512_HMAC:
36712798Swpaul		return ("HMAC/SHA512");
36812798Swpaul	}
3691897Swollman	return ("unknown");
3701897Swollman}
371152398Sdwmalone
372152398Sdwmalonestatic __inline void
3731897Swollmaneli_metadata_dump(const struct g_eli_metadata *md)
3741897Swollman{
3751897Swollman	static const char hex[] = "0123456789abcdef";
3761897Swollman	char str[sizeof(md->md_mkeys) * 2 + 1];
3771897Swollman	u_int i;
3781897Swollman
3791897Swollman	printf("     magic: %s\n", md->md_magic);
38017142Sjkh	printf("   version: %u\n", (u_int)md->md_version);
381152398Sdwmalone	printf("     flags: 0x%x\n", (u_int)md->md_flags);
3821897Swollman	printf("     ealgo: %s\n", g_eli_algo2str(md->md_ealgo));
3831897Swollman	printf("    keylen: %u\n", (u_int)md->md_keylen);
3841897Swollman	if (md->md_flags & G_ELI_FLAG_AUTH)
3851897Swollman		printf("     aalgo: %s\n", g_eli_algo2str(md->md_aalgo));
3861897Swollman	printf("  provsize: %ju\n", (uintmax_t)md->md_provsize);
3871897Swollman	printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
3881897Swollman	printf("      keys: 0x%02x\n", (u_int)md->md_keys);
38917142Sjkh	printf("iterations: %u\n", (u_int)md->md_iterations);
3901897Swollman	bzero(str, sizeof(str));
3911897Swollman	for (i = 0; i < sizeof(md->md_salt); i++) {
3921897Swollman		str[i * 2] = hex[md->md_salt[i] >> 4];
3931897Swollman		str[i * 2 + 1] = hex[md->md_salt[i] & 0x0f];
3941897Swollman	}
3951897Swollman	printf("      Salt: %s\n", str);
3961897Swollman	bzero(str, sizeof(str));
3971897Swollman	for (i = 0; i < sizeof(md->md_mkeys); i++) {
3981897Swollman		str[i * 2] = hex[md->md_mkeys[i] >> 4];
3991897Swollman		str[i * 2 + 1] = hex[md->md_mkeys[i] & 0x0f];
4001897Swollman	}
4011897Swollman	printf("Master Key: %s\n", str);
40217142Sjkh	bzero(str, sizeof(str));
403152398Sdwmalone	for (i = 0; i < 16; i++) {
4041897Swollman		str[i * 2] = hex[md->md_hash[i] >> 4];
4051897Swollman		str[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
4061897Swollman	}
4071897Swollman	printf("  MD5 hash: %s\n", str);
4081897Swollman}
4091897Swollman
4101897Swollmanstatic __inline u_int
4111897Swollmang_eli_keylen(u_int algo, u_int keylen)
4121897Swollman{
4131897Swollman
4141897Swollman	switch (algo) {
4151897Swollman	case CRYPTO_NULL_CBC:
4161897Swollman		if (keylen == 0)
4171897Swollman			keylen = 64 * 8;
4181897Swollman		else {
4191897Swollman			if (keylen > 64 * 8)
4201897Swollman				keylen = 0;
4211897Swollman		}
4221897Swollman		return (keylen);
42312798Swpaul	case CRYPTO_AES_CBC:
42412798Swpaul	case CRYPTO_CAMELLIA_CBC:
425152398Sdwmalone		switch (keylen) {
42612798Swpaul		case 0:
42712798Swpaul			return (128);
42812798Swpaul		case 128:
429100441Scharnier		case 192:
43012798Swpaul		case 256:
43112798Swpaul			return (keylen);
43212798Swpaul		default:
43312798Swpaul			return (0);
43412798Swpaul		}
43512798Swpaul	case CRYPTO_AES_XTS:
43612798Swpaul		switch (keylen) {
43717142Sjkh		case 0:
438152398Sdwmalone			return (128);
43912798Swpaul		case 128:
44012798Swpaul		case 256:
44112798Swpaul			return (keylen);
442100441Scharnier		default:
44312798Swpaul			return (0);
44412798Swpaul		}
44512798Swpaul	case CRYPTO_BLF_CBC:
44612798Swpaul		if (keylen == 0)
44712798Swpaul			return (128);
44812798Swpaul		if (keylen < 128 || keylen > 448)
44912798Swpaul			return (0);
45012798Swpaul		if ((keylen % 32) != 0)
45112798Swpaul			return (0);
45212798Swpaul		return (keylen);
45312798Swpaul	case CRYPTO_3DES_CBC:
45412798Swpaul		if (keylen == 0 || keylen == 192)
45512798Swpaul			return (192);
45612798Swpaul		return (0);
45712798Swpaul	default:
45812798Swpaul		return (0);
45912798Swpaul	}
46012798Swpaul}
461152398Sdwmalone
462152398Sdwmalonestatic __inline u_int
46312798Swpaulg_eli_hashlen(u_int algo)
46412798Swpaul{
46512798Swpaul
46612798Swpaul	switch (algo) {
46712798Swpaul	case CRYPTO_MD5_HMAC:
46812798Swpaul		return (16);
46912798Swpaul	case CRYPTO_SHA1_HMAC:
47012798Swpaul		return (20);
47112798Swpaul	case CRYPTO_RIPEMD160_HMAC:
47212798Swpaul		return (20);
47312798Swpaul	case CRYPTO_SHA2_256_HMAC:
47412798Swpaul		return (32);
47512798Swpaul	case CRYPTO_SHA2_384_HMAC:
476100441Scharnier		return (48);
477100441Scharnier	case CRYPTO_SHA2_512_HMAC:
478100441Scharnier		return (64);
479100441Scharnier	}
480100441Scharnier	return (0);
481100441Scharnier}
482100441Scharnier
483100441Scharnier#ifdef _KERNEL
484100441Scharnierint g_eli_read_metadata(struct g_class *mp, struct g_provider *pp,
485100441Scharnier    struct g_eli_metadata *md);
486100441Scharnierstruct g_geom *g_eli_create(struct gctl_req *req, struct g_class *mp,
487100441Scharnier    struct g_provider *bpp, const struct g_eli_metadata *md,
488100441Scharnier    const u_char *mkey, int nkey);
489100441Scharnierint g_eli_destroy(struct g_eli_softc *sc, boolean_t force);
490100441Scharnier
491100441Scharnierint g_eli_access(struct g_provider *pp, int dr, int dw, int de);
492100441Scharniervoid g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb);
493100441Scharnier
494100441Scharniervoid g_eli_read_done(struct bio *bp);
495100441Scharniervoid g_eli_write_done(struct bio *bp);
496100441Scharnierint g_eli_crypto_rerun(struct cryptop *crp);
497100441Scharnieruint8_t *g_eli_crypto_key(struct g_eli_softc *sc, off_t offset,
498100441Scharnier    size_t blocksize);
499100441Scharniervoid g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
500100441Scharnier    size_t size);
501100441Scharnier
502100441Scharniervoid g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp);
503100441Scharnier
504100441Scharniervoid g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp);
505100441Scharniervoid g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp);
506100441Scharnier#endif
507100441Scharnier
508100441Scharniervoid g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key);
509100441Scharnierint g_eli_mkey_decrypt(const struct g_eli_metadata *md,
510100441Scharnier    const unsigned char *key, unsigned char *mkey, unsigned *nkeyp);
511100441Scharnierint g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
512    unsigned char *mkey);
513#ifdef _KERNEL
514void g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey);
515#endif
516
517int g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
518    const u_char *key, size_t keysize);
519int g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
520    const u_char *key, size_t keysize);
521
522struct hmac_ctx {
523	SHA512_CTX	shactx;
524	u_char		k_opad[128];
525};
526
527void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
528    size_t hkeylen);
529void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
530    size_t datasize);
531void g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize);
532void g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize,
533    const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize);
534#endif	/* !_G_ELI_H_ */
535