Changeset View
Changeset View
Standalone View
Standalone View
sys/geom/eli/g_eli_key_cache.c
Show All 22 Lines | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#ifdef _KERNEL | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/tree.h> | #include <sys/tree.h> | ||||
#endif /* _KERNEL */ | |||||
#include <geom/geom.h> | #include <geom/geom.h> | ||||
#include <geom/eli/g_eli.h> | #include <geom/eli/g_eli.h> | ||||
#ifdef _KERNEL | |||||
MALLOC_DECLARE(M_ELI); | MALLOC_DECLARE(M_ELI); | ||||
SYSCTL_DECL(_kern_geom_eli); | SYSCTL_DECL(_kern_geom_eli); | ||||
/* | /* | ||||
* The default limit (8192 keys) will allow to cache all keys for 4TB | * The default limit (8192 keys) will allow to cache all keys for 4TB | ||||
* provider with 512 bytes sectors and will take around 1MB of memory. | * provider with 512 bytes sectors and will take around 1MB of memory. | ||||
*/ | */ | ||||
static u_int g_eli_key_cache_limit = 8192; | static u_int g_eli_key_cache_limit = 8192; | ||||
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, key_cache_limit, CTLFLAG_RDTUN, | SYSCTL_UINT(_kern_geom_eli, OID_AUTO, key_cache_limit, CTLFLAG_RDTUN, | ||||
&g_eli_key_cache_limit, 0, "Maximum number of encryption keys to cache"); | &g_eli_key_cache_limit, 0, "Maximum number of encryption keys to cache"); | ||||
static uint64_t g_eli_key_cache_hits; | static uint64_t g_eli_key_cache_hits; | ||||
SYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_hits, CTLFLAG_RW, | SYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_hits, CTLFLAG_RW, | ||||
&g_eli_key_cache_hits, 0, "Key cache hits"); | &g_eli_key_cache_hits, 0, "Key cache hits"); | ||||
static uint64_t g_eli_key_cache_misses; | static uint64_t g_eli_key_cache_misses; | ||||
SYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_misses, CTLFLAG_RW, | SYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_misses, CTLFLAG_RW, | ||||
&g_eli_key_cache_misses, 0, "Key cache misses"); | &g_eli_key_cache_misses, 0, "Key cache misses"); | ||||
#define G_ELI_KEY_MAGIC 0xe11341c | #endif /* _KERNEL */ | ||||
struct g_eli_key { | |||||
/* Key value, must be first in the structure. */ | |||||
uint8_t gek_key[G_ELI_DATAKEYLEN]; | |||||
/* Magic. */ | |||||
int gek_magic; | |||||
/* Key number. */ | |||||
uint64_t gek_keyno; | |||||
/* Reference counter. */ | |||||
int gek_count; | |||||
/* Keeps keys sorted by most recent use. */ | |||||
TAILQ_ENTRY(g_eli_key) gek_next; | |||||
/* Keeps keys sorted by number. */ | |||||
RB_ENTRY(g_eli_key) gek_link; | |||||
}; | |||||
static int | static int | ||||
g_eli_key_cmp(const struct g_eli_key *a, const struct g_eli_key *b) | g_eli_key_cmp(const struct g_eli_key *a, const struct g_eli_key *b) | ||||
{ | { | ||||
if (a->gek_keyno > b->gek_keyno) | if (a->gek_keyno > b->gek_keyno) | ||||
return (1); | return (1); | ||||
else if (a->gek_keyno < b->gek_keyno) | else if (a->gek_keyno < b->gek_keyno) | ||||
return (-1); | return (-1); | ||||
return (0); | return (0); | ||||
} | } | ||||
RB_PROTOTYPE(g_eli_key_tree, g_eli_key, gek_link, g_eli_key_cmp); | void | ||||
RB_GENERATE(g_eli_key_tree, g_eli_key, gek_link, g_eli_key_cmp); | |||||
static void | |||||
g_eli_key_fill(struct g_eli_softc *sc, struct g_eli_key *key, uint64_t keyno) | g_eli_key_fill(struct g_eli_softc *sc, struct g_eli_key *key, uint64_t keyno) | ||||
{ | { | ||||
const uint8_t *ekey; | const uint8_t *ekey; | ||||
struct { | struct { | ||||
char magic[4]; | char magic[4]; | ||||
uint8_t keyno[8]; | uint8_t keyno[8]; | ||||
} __packed hmacdata; | } __packed hmacdata; | ||||
if ((sc->sc_flags & G_ELI_FLAG_ENC_IVKEY) != 0) | if ((sc->sc_flags & G_ELI_FLAG_ENC_IVKEY) != 0) | ||||
ekey = sc->sc_mkey; | ekey = sc->sc_mkey; | ||||
else | else | ||||
ekey = sc->sc_ekey; | ekey = sc->sc_ekey; | ||||
bcopy("ekey", hmacdata.magic, 4); | bcopy("ekey", hmacdata.magic, 4); | ||||
le64enc(hmacdata.keyno, keyno); | le64enc(hmacdata.keyno, keyno); | ||||
g_eli_crypto_hmac(ekey, G_ELI_MAXKEYLEN, (uint8_t *)&hmacdata, | g_eli_crypto_hmac(ekey, G_ELI_MAXKEYLEN, (uint8_t *)&hmacdata, | ||||
sizeof(hmacdata), key->gek_key, 0); | sizeof(hmacdata), key->gek_key, 0); | ||||
key->gek_keyno = keyno; | key->gek_keyno = keyno; | ||||
key->gek_count = 0; | key->gek_count = 0; | ||||
key->gek_magic = G_ELI_KEY_MAGIC; | key->gek_magic = G_ELI_KEY_MAGIC; | ||||
} | } | ||||
#ifdef _KERNEL | |||||
RB_PROTOTYPE(g_eli_key_tree, g_eli_key, gek_link, g_eli_key_cmp); | |||||
RB_GENERATE(g_eli_key_tree, g_eli_key, gek_link, g_eli_key_cmp); | |||||
static struct g_eli_key * | static struct g_eli_key * | ||||
g_eli_key_allocate(struct g_eli_softc *sc, uint64_t keyno) | g_eli_key_allocate(struct g_eli_softc *sc, uint64_t keyno) | ||||
{ | { | ||||
struct g_eli_key *key, *ekey, keysearch; | struct g_eli_key *key, *ekey, keysearch; | ||||
mtx_assert(&sc->sc_ekeys_lock, MA_OWNED); | mtx_assert(&sc->sc_ekeys_lock, MA_OWNED); | ||||
mtx_unlock(&sc->sc_ekeys_lock); | mtx_unlock(&sc->sc_ekeys_lock); | ||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | g_eli_key_drop(struct g_eli_softc *sc, uint8_t *rawkey) | ||||
while (sc->sc_ekeys_allocated > g_eli_key_cache_limit) { | while (sc->sc_ekeys_allocated > g_eli_key_cache_limit) { | ||||
key = g_eli_key_find_last(sc); | key = g_eli_key_find_last(sc); | ||||
if (key == NULL) | if (key == NULL) | ||||
break; | break; | ||||
g_eli_key_remove(sc, key); | g_eli_key_remove(sc, key); | ||||
} | } | ||||
mtx_unlock(&sc->sc_ekeys_lock); | mtx_unlock(&sc->sc_ekeys_lock); | ||||
} | } | ||||
#endif /* _KERNEL */ |