1220922Spjd/*-
2220922Spjd * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
3220922Spjd * All rights reserved.
4220922Spjd *
5220922Spjd * Redistribution and use in source and binary forms, with or without
6220922Spjd * modification, are permitted provided that the following conditions
7220922Spjd * are met:
8220922Spjd * 1. Redistributions of source code must retain the above copyright
9220922Spjd *    notice, this list of conditions and the following disclaimer.
10220922Spjd * 2. Redistributions in binary form must reproduce the above copyright
11220922Spjd *    notice, this list of conditions and the following disclaimer in the
12220922Spjd *    documentation and/or other materials provided with the distribution.
13220922Spjd *
14220922Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15220922Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16220922Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17220922Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18220922Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19220922Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20220922Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21220922Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22220922Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23220922Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24220922Spjd * SUCH DAMAGE.
25220922Spjd */
26220922Spjd
27220922Spjd#include <sys/cdefs.h>
28220922Spjd__FBSDID("$FreeBSD$");
29220922Spjd
30220922Spjd#include <sys/param.h>
31220922Spjd#include <sys/kernel.h>
32220922Spjd#include <sys/malloc.h>
33220922Spjd#include <sys/queue.h>
34220922Spjd#include <sys/sysctl.h>
35220922Spjd#include <sys/systm.h>
36220922Spjd#include <sys/tree.h>
37220922Spjd
38220922Spjd#include <geom/geom.h>
39220922Spjd
40220922Spjd#include <geom/eli/g_eli.h>
41220922Spjd
42220922SpjdMALLOC_DECLARE(M_ELI);
43220922Spjd
44220922SpjdSYSCTL_DECL(_kern_geom_eli);
45220922Spjd/*
46220922Spjd * The default limit (8192 keys) will allow to cache all keys for 4TB
47220922Spjd * provider with 512 bytes sectors and will take around 1MB of memory.
48220922Spjd */
49220922Spjdstatic u_int g_eli_key_cache_limit = 8192;
50220922SpjdTUNABLE_INT("kern.geom.eli.key_cache_limit", &g_eli_key_cache_limit);
51220922SpjdSYSCTL_UINT(_kern_geom_eli, OID_AUTO, key_cache_limit, CTLFLAG_RDTUN,
52220922Spjd    &g_eli_key_cache_limit, 0, "Maximum number of encryption keys to cache");
53220922Spjdstatic uint64_t g_eli_key_cache_hits;
54220922SpjdSYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_hits, CTLFLAG_RW,
55220922Spjd    &g_eli_key_cache_hits, 0, "Key cache hits");
56220922Spjdstatic uint64_t g_eli_key_cache_misses;
57220922SpjdSYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_misses, CTLFLAG_RW,
58220922Spjd    &g_eli_key_cache_misses, 0, "Key cache misses");
59220922Spjd
60221624Spjd#define	G_ELI_KEY_MAGIC	0xe11341c
61221624Spjd
62220922Spjdstruct g_eli_key {
63220922Spjd	/* Key value, must be first in the structure. */
64220922Spjd	uint8_t		gek_key[G_ELI_DATAKEYLEN];
65221624Spjd	/* Magic. */
66221624Spjd	int		gek_magic;
67220922Spjd	/* Key number. */
68220922Spjd	uint64_t	gek_keyno;
69220922Spjd	/* Reference counter. */
70220922Spjd	int		gek_count;
71220922Spjd	/* Keeps keys sorted by most recent use. */
72220922Spjd	TAILQ_ENTRY(g_eli_key) gek_next;
73220922Spjd	/* Keeps keys sorted by number. */
74220922Spjd	RB_ENTRY(g_eli_key) gek_link;
75220922Spjd};
76220922Spjd
77220922Spjdstatic int
78220922Spjdg_eli_key_cmp(const struct g_eli_key *a, const struct g_eli_key *b)
79220922Spjd{
80220922Spjd
81220922Spjd	if (a->gek_keyno > b->gek_keyno)
82220922Spjd		return (1);
83220922Spjd	else if (a->gek_keyno < b->gek_keyno)
84220922Spjd		return (-1);
85220922Spjd	return (0);
86220922Spjd}
87220922Spjd
88220922SpjdRB_PROTOTYPE(g_eli_key_tree, g_eli_key, gek_link, g_eli_key_cmp);
89220922SpjdRB_GENERATE(g_eli_key_tree, g_eli_key, gek_link, g_eli_key_cmp);
90220922Spjd
91220922Spjdstatic void
92220922Spjdg_eli_key_fill(struct g_eli_softc *sc, struct g_eli_key *key, uint64_t keyno)
93220922Spjd{
94220922Spjd	struct {
95220922Spjd		char magic[4];
96220922Spjd		uint8_t keyno[8];
97220922Spjd	} __packed hmacdata;
98220922Spjd
99220922Spjd	bcopy("ekey", hmacdata.magic, 4);
100220922Spjd	le64enc(hmacdata.keyno, keyno);
101220922Spjd	g_eli_crypto_hmac(sc->sc_mkey, G_ELI_MAXKEYLEN, (uint8_t *)&hmacdata,
102220922Spjd	    sizeof(hmacdata), key->gek_key, 0);
103220922Spjd	key->gek_keyno = keyno;
104220922Spjd	key->gek_count = 0;
105221624Spjd	key->gek_magic = G_ELI_KEY_MAGIC;
106220922Spjd}
107220922Spjd
108220922Spjdstatic struct g_eli_key *
109220922Spjdg_eli_key_allocate(struct g_eli_softc *sc, uint64_t keyno)
110220922Spjd{
111220922Spjd	struct g_eli_key *key, *ekey, keysearch;
112220922Spjd
113220922Spjd	mtx_assert(&sc->sc_ekeys_lock, MA_OWNED);
114220922Spjd	mtx_unlock(&sc->sc_ekeys_lock);
115220922Spjd
116220922Spjd	key = malloc(sizeof(*key), M_ELI, M_WAITOK);
117220922Spjd	g_eli_key_fill(sc, key, keyno);
118220922Spjd
119220922Spjd	mtx_lock(&sc->sc_ekeys_lock);
120220922Spjd	/*
121220922Spjd	 * Recheck if the key wasn't added while we weren't holding the lock.
122220922Spjd	 */
123220922Spjd	keysearch.gek_keyno = keyno;
124220922Spjd	ekey = RB_FIND(g_eli_key_tree, &sc->sc_ekeys_tree, &keysearch);
125220922Spjd	if (ekey != NULL) {
126220922Spjd		bzero(key, sizeof(*key));
127221953Strociny		free(key, M_ELI);
128220922Spjd		key = ekey;
129220922Spjd		TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
130220922Spjd	} else {
131220922Spjd		RB_INSERT(g_eli_key_tree, &sc->sc_ekeys_tree, key);
132220922Spjd		sc->sc_ekeys_allocated++;
133220922Spjd	}
134220922Spjd	TAILQ_INSERT_TAIL(&sc->sc_ekeys_queue, key, gek_next);
135220922Spjd
136220922Spjd	return (key);
137220922Spjd}
138220922Spjd
139220922Spjdstatic struct g_eli_key *
140220922Spjdg_eli_key_find_last(struct g_eli_softc *sc)
141220922Spjd{
142220922Spjd	struct g_eli_key *key;
143220922Spjd
144220922Spjd	mtx_assert(&sc->sc_ekeys_lock, MA_OWNED);
145220922Spjd
146220922Spjd	TAILQ_FOREACH(key, &sc->sc_ekeys_queue, gek_next) {
147220922Spjd		if (key->gek_count == 0)
148220922Spjd			break;
149220922Spjd	}
150220922Spjd
151220922Spjd	return (key);
152220922Spjd}
153220922Spjd
154220922Spjdstatic void
155220922Spjdg_eli_key_replace(struct g_eli_softc *sc, struct g_eli_key *key, uint64_t keyno)
156220922Spjd{
157220922Spjd
158220922Spjd	mtx_assert(&sc->sc_ekeys_lock, MA_OWNED);
159221624Spjd	KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid magic."));
160220922Spjd
161220922Spjd	RB_REMOVE(g_eli_key_tree, &sc->sc_ekeys_tree, key);
162220922Spjd	TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
163220922Spjd
164220922Spjd	KASSERT(key->gek_count == 0, ("gek_count=%d", key->gek_count));
165220922Spjd
166220922Spjd	g_eli_key_fill(sc, key, keyno);
167220922Spjd
168220922Spjd	RB_INSERT(g_eli_key_tree, &sc->sc_ekeys_tree, key);
169220922Spjd	TAILQ_INSERT_TAIL(&sc->sc_ekeys_queue, key, gek_next);
170220922Spjd}
171220922Spjd
172220922Spjdstatic void
173220922Spjdg_eli_key_remove(struct g_eli_softc *sc, struct g_eli_key *key)
174220922Spjd{
175220922Spjd
176220922Spjd	mtx_assert(&sc->sc_ekeys_lock, MA_OWNED);
177221624Spjd	KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid magic."));
178220922Spjd	KASSERT(key->gek_count == 0, ("gek_count=%d", key->gek_count));
179220922Spjd
180220922Spjd	RB_REMOVE(g_eli_key_tree, &sc->sc_ekeys_tree, key);
181220922Spjd	TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
182220922Spjd	sc->sc_ekeys_allocated--;
183220922Spjd	bzero(key, sizeof(*key));
184220922Spjd	free(key, M_ELI);
185220922Spjd}
186220922Spjd
187220922Spjdvoid
188220922Spjdg_eli_key_init(struct g_eli_softc *sc)
189220922Spjd{
190220922Spjd
191220922Spjd	mtx_lock(&sc->sc_ekeys_lock);
192220922Spjd	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) {
193220922Spjd		uint8_t *mkey;
194220922Spjd
195220922Spjd		mkey = sc->sc_mkey + sizeof(sc->sc_ivkey);
196220922Spjd
197220922Spjd		sc->sc_ekeys_total = 1;
198220922Spjd		sc->sc_ekeys_allocated = 0;
199220922Spjd		if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0)
200220922Spjd			bcopy(mkey, sc->sc_ekey, G_ELI_DATAKEYLEN);
201220922Spjd		else {
202220922Spjd			/*
203220922Spjd			 * The encryption key is: ekey = HMAC_SHA512(Master-Key, 0x10)
204220922Spjd			 */
205220922Spjd			g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x10", 1,
206220922Spjd			    sc->sc_ekey, 0);
207220922Spjd		}
208220922Spjd	} else {
209220922Spjd		off_t mediasize;
210220922Spjd		size_t blocksize;
211220922Spjd
212220922Spjd		if ((sc->sc_flags & G_ELI_FLAG_AUTH) != 0) {
213220922Spjd			struct g_provider *pp;
214220922Spjd
215220922Spjd			pp = LIST_FIRST(&sc->sc_geom->consumer)->provider;
216220922Spjd			mediasize = pp->mediasize;
217220922Spjd			blocksize = pp->sectorsize;
218220922Spjd		} else {
219220922Spjd			mediasize = sc->sc_mediasize;
220220922Spjd			blocksize = sc->sc_sectorsize;
221220922Spjd		}
222220922Spjd		sc->sc_ekeys_total =
223220922Spjd		    ((mediasize - 1) >> G_ELI_KEY_SHIFT) / blocksize + 1;
224220922Spjd		sc->sc_ekeys_allocated = 0;
225220922Spjd		TAILQ_INIT(&sc->sc_ekeys_queue);
226220922Spjd		RB_INIT(&sc->sc_ekeys_tree);
227220923Spjd		if (sc->sc_ekeys_total <= g_eli_key_cache_limit) {
228220923Spjd			uint64_t keyno;
229220923Spjd
230220923Spjd			for (keyno = 0; keyno < sc->sc_ekeys_total; keyno++)
231220923Spjd				(void)g_eli_key_allocate(sc, keyno);
232220923Spjd			KASSERT(sc->sc_ekeys_total == sc->sc_ekeys_allocated,
233220923Spjd			    ("sc_ekeys_total=%ju != sc_ekeys_allocated=%ju",
234220923Spjd			    (uintmax_t)sc->sc_ekeys_total,
235220923Spjd			    (uintmax_t)sc->sc_ekeys_allocated));
236220923Spjd		}
237220922Spjd	}
238220922Spjd	mtx_unlock(&sc->sc_ekeys_lock);
239220922Spjd}
240220922Spjd
241220922Spjdvoid
242220922Spjdg_eli_key_destroy(struct g_eli_softc *sc)
243220922Spjd{
244220922Spjd
245220922Spjd	mtx_lock(&sc->sc_ekeys_lock);
246220922Spjd	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) {
247220922Spjd		bzero(sc->sc_ekey, sizeof(sc->sc_ekey));
248220922Spjd	} else {
249220922Spjd		struct g_eli_key *key;
250220922Spjd
251220922Spjd		while ((key = TAILQ_FIRST(&sc->sc_ekeys_queue)) != NULL)
252220922Spjd			g_eli_key_remove(sc, key);
253220922Spjd		TAILQ_INIT(&sc->sc_ekeys_queue);
254220922Spjd		RB_INIT(&sc->sc_ekeys_tree);
255220922Spjd	}
256220922Spjd	mtx_unlock(&sc->sc_ekeys_lock);
257220922Spjd}
258220922Spjd
259220922Spjd/*
260220922Spjd * Select encryption key. If G_ELI_FLAG_SINGLE_KEY is present we only have one
261220922Spjd * key available for all the data. If the flag is not present select the key
262220922Spjd * based on data offset.
263220922Spjd */
264220922Spjduint8_t *
265220922Spjdg_eli_key_hold(struct g_eli_softc *sc, off_t offset, size_t blocksize)
266220922Spjd{
267220922Spjd	struct g_eli_key *key, keysearch;
268220922Spjd	uint64_t keyno;
269220922Spjd
270220922Spjd	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0)
271220922Spjd		return (sc->sc_ekey);
272220922Spjd
273220922Spjd	/* We switch key every 2^G_ELI_KEY_SHIFT blocks. */
274220922Spjd	keyno = (offset >> G_ELI_KEY_SHIFT) / blocksize;
275220922Spjd
276220922Spjd	KASSERT(keyno < sc->sc_ekeys_total,
277220922Spjd	    ("%s: keyno=%ju >= sc_ekeys_total=%ju",
278220922Spjd	    __func__, (uintmax_t)keyno, (uintmax_t)sc->sc_ekeys_total));
279220922Spjd
280220922Spjd	keysearch.gek_keyno = keyno;
281220922Spjd
282220923Spjd	if (sc->sc_ekeys_total == sc->sc_ekeys_allocated) {
283220923Spjd		/* We have all the keys, so avoid some overhead. */
284220923Spjd		key = RB_FIND(g_eli_key_tree, &sc->sc_ekeys_tree, &keysearch);
285220923Spjd		KASSERT(key != NULL, ("No key %ju found.", (uintmax_t)keyno));
286221624Spjd		KASSERT(key->gek_magic == G_ELI_KEY_MAGIC,
287221624Spjd		    ("Invalid key magic."));
288220923Spjd		return (key->gek_key);
289220923Spjd	}
290220923Spjd
291220922Spjd	mtx_lock(&sc->sc_ekeys_lock);
292220922Spjd	key = RB_FIND(g_eli_key_tree, &sc->sc_ekeys_tree, &keysearch);
293220922Spjd	if (key != NULL) {
294220922Spjd		g_eli_key_cache_hits++;
295220922Spjd		TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
296220922Spjd		TAILQ_INSERT_TAIL(&sc->sc_ekeys_queue, key, gek_next);
297220922Spjd	} else {
298220922Spjd		/*
299220922Spjd		 * No key in cache, find the least recently unreferenced key
300220922Spjd		 * or allocate one if we haven't reached our limit yet.
301220922Spjd		 */
302220922Spjd		if (sc->sc_ekeys_allocated < g_eli_key_cache_limit) {
303220922Spjd			key = g_eli_key_allocate(sc, keyno);
304220922Spjd		} else {
305220922Spjd			g_eli_key_cache_misses++;
306220922Spjd			key = g_eli_key_find_last(sc);
307220922Spjd			if (key != NULL) {
308220922Spjd				g_eli_key_replace(sc, key, keyno);
309220922Spjd			} else {
310220922Spjd				/* All keys are referenced? Allocate one. */
311220922Spjd				key = g_eli_key_allocate(sc, keyno);
312220922Spjd			}
313220922Spjd		}
314220922Spjd	}
315220922Spjd	key->gek_count++;
316220922Spjd	mtx_unlock(&sc->sc_ekeys_lock);
317220922Spjd
318221624Spjd	KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid key magic."));
319221624Spjd
320220922Spjd	return (key->gek_key);
321220922Spjd}
322220922Spjd
323220922Spjdvoid
324220922Spjdg_eli_key_drop(struct g_eli_softc *sc, uint8_t *rawkey)
325220922Spjd{
326220922Spjd	struct g_eli_key *key = (struct g_eli_key *)rawkey;
327220922Spjd
328220922Spjd	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0)
329220922Spjd		return;
330220922Spjd
331221624Spjd	KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid key magic."));
332221624Spjd
333220923Spjd	if (sc->sc_ekeys_total == sc->sc_ekeys_allocated)
334220923Spjd		return;
335220923Spjd
336220922Spjd	mtx_lock(&sc->sc_ekeys_lock);
337220922Spjd	KASSERT(key->gek_count > 0, ("key->gek_count=%d", key->gek_count));
338220922Spjd	key->gek_count--;
339220922Spjd	while (sc->sc_ekeys_allocated > g_eli_key_cache_limit) {
340220922Spjd		key = g_eli_key_find_last(sc);
341220922Spjd		if (key == NULL)
342220922Spjd			break;
343220922Spjd		g_eli_key_remove(sc, key);
344220922Spjd	}
345220922Spjd	mtx_unlock(&sc->sc_ekeys_lock);
346220922Spjd}
347