summaryrefslogtreecommitdiffstats
path: root/sys/geom/eli/g_eli.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2010-09-23 11:49:47 +0000
committerpjd <pjd@FreeBSD.org>2010-09-23 11:49:47 +0000
commited0ad07f3dd1bc5f1fad46c75e5d57ecbbca3cf8 (patch)
treeb964c8ab4d3ce3c31a74eb0012bc3b98d1bd45c7 /sys/geom/eli/g_eli.c
parent7c5b734f64e42e6d5b7864578947df2fe8b2149b (diff)
downloadFreeBSD-src-ed0ad07f3dd1bc5f1fad46c75e5d57ecbbca3cf8.zip
FreeBSD-src-ed0ad07f3dd1bc5f1fad46c75e5d57ecbbca3cf8.tar.gz
Implement switching of data encryption key every 2^20 blocks.
This ensures the same encryption key won't be used for more than 2^20 blocks (sectors). This will be the default now. MFC after: 1 week
Diffstat (limited to 'sys/geom/eli/g_eli.c')
-rw-r--r--sys/geom/eli/g_eli.c91
1 files changed, 67 insertions, 24 deletions
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c
index 4bcce3d..c44cddc 100644
--- a/sys/geom/eli/g_eli.c
+++ b/sys/geom/eli/g_eli.c
@@ -375,6 +375,34 @@ g_eli_worker(void *arg)
}
/*
+ * 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
@@ -548,13 +576,10 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
/* 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;
- /*
- * Remember the keys in our softc structure.
- */
- g_eli_mkey_propagate(sc, mkey);
- sc->sc_ekeylen = md->md_keylen;
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
sc->sc_akeylen = sizeof(sc->sc_akey) * 8;
@@ -584,14 +609,6 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
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.
- */
- SHA256_Init(&sc->sc_ivctx);
- SHA256_Update(&sc->sc_ivctx, sc->sc_ivkey, sizeof(sc->sc_ivkey));
-
gp->softc = sc;
sc->sc_geom = gp;
@@ -633,12 +650,37 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
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;
+
+ /*
+ * 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.
+ */
+ SHA256_Init(&sc->sc_ivctx);
+ SHA256_Update(&sc->sc_ivctx, sc->sc_ivkey, sizeof(sc->sc_ivkey));
+
LIST_INIT(&sc->sc_workers);
bzero(&crie, sizeof(crie));
crie.cri_alg = sc->sc_ealgo;
crie.cri_klen = sc->sc_ekeylen;
- crie.cri_key = sc->sc_ekey;
+ 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;
@@ -715,16 +757,8 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
* Create decrypted provider.
*/
pp = g_new_providerf(gp, "%s%s", bpp->name, G_ELI_SUFFIX);
- pp->sectorsize = md->md_sectorsize;
- pp->mediasize = bpp->mediasize;
- if (!(sc->sc_flags & G_ELI_FLAG_ONETIME))
- pp->mediasize -= bpp->sectorsize;
- if (!(sc->sc_flags & G_ELI_FLAG_AUTH))
- pp->mediasize -= (pp->mediasize % pp->sectorsize);
- else {
- pp->mediasize /= sc->sc_bytes_per_sector;
- pp->mediasize *= pp->sectorsize;
- }
+ pp->mediasize = sc->sc_mediasize;
+ pp->sectorsize = sc->sc_sectorsize;
g_error_provider(pp, 0);
@@ -755,6 +789,11 @@ failed:
}
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);
@@ -794,6 +833,9 @@ g_eli_destroy(struct g_eli_softc *sc, boolean_t force)
}
mtx_destroy(&sc->sc_queue_mtx);
gp->softc = 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);
@@ -1042,6 +1084,7 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
sbuf_printf(sb, name); \
} \
} while (0)
+ 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");
OpenPOWER on IntegriCloud