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