diff options
author | pjd <pjd@FreeBSD.org> | 2010-09-23 11:49:47 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2010-09-23 11:49:47 +0000 |
commit | ed0ad07f3dd1bc5f1fad46c75e5d57ecbbca3cf8 (patch) | |
tree | b964c8ab4d3ce3c31a74eb0012bc3b98d1bd45c7 /sys/geom/eli/g_eli.c | |
parent | 7c5b734f64e42e6d5b7864578947df2fe8b2149b (diff) | |
download | FreeBSD-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.c | 91 |
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"); |