summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2011-05-08 14:56:02 +0000
committerattilio <attilio@FreeBSD.org>2011-05-08 14:56:02 +0000
commit7ff10cb598d55bfe8ced2b56f014c4dca7b432e9 (patch)
tree762b070eea5b970647293823ae548d0a9715786e /sys/geom
parent060cccb5372db4bb6441c43f1c99bfab65c6b010 (diff)
parentb838671bb4661d8bd3ad95d511c0b7bcd93a5c4b (diff)
downloadFreeBSD-src-7ff10cb598d55bfe8ced2b56f014c4dca7b432e9.zip
FreeBSD-src-7ff10cb598d55bfe8ced2b56f014c4dca7b432e9.tar.gz
MFC
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/eli/g_eli.c15
-rw-r--r--sys/geom/eli/g_eli.h34
-rw-r--r--sys/geom/eli/g_eli_ctl.c7
-rw-r--r--sys/geom/eli/g_eli_integrity.c4
-rw-r--r--sys/geom/eli/g_eli_key_cache.c14
-rw-r--r--sys/geom/part/g_part_apm.c7
-rw-r--r--sys/geom/part/g_part_bsd.c4
-rw-r--r--sys/geom/part/g_part_ebr.c4
-rw-r--r--sys/geom/part/g_part_mbr.c4
-rw-r--r--sys/geom/part/g_part_pc98.c4
-rw-r--r--sys/geom/part/g_part_vtoc8.c7
11 files changed, 73 insertions, 31 deletions
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c
index 6466aef..30497a4 100644
--- a/sys/geom/eli/g_eli.c
+++ b/sys/geom/eli/g_eli.c
@@ -57,6 +57,9 @@ MALLOC_DEFINE(M_ELI, "eli data", "GEOM_ELI Data");
SYSCTL_DECL(_kern_geom);
SYSCTL_NODE(_kern_geom, OID_AUTO, eli, CTLFLAG_RW, 0, "GEOM_ELI stuff");
+static int g_eli_version = G_ELI_VERSION;
+SYSCTL_INT(_kern_geom_eli, OID_AUTO, version, CTLFLAG_RD, &g_eli_version, 0,
+ "GELI version");
int g_eli_debug = 0;
TUNABLE_INT("kern.geom.eli.debug", &g_eli_debug);
SYSCTL_INT(_kern_geom_eli, OID_AUTO, debug, CTLFLAG_RW, &g_eli_debug, 0,
@@ -329,7 +332,12 @@ g_eli_newsession(struct g_eli_worker *wr)
crie.cri_klen = sc->sc_ekeylen;
if (sc->sc_ealgo == CRYPTO_AES_XTS)
crie.cri_klen <<= 1;
- crie.cri_key = sc->sc_ekey;
+ if ((sc->sc_flags & G_ELI_FLAG_FIRST_KEY) != 0) {
+ crie.cri_key = g_eli_key_hold(sc, 0,
+ LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize);
+ } else {
+ crie.cri_key = sc->sc_ekey;
+ }
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
bzero(&cria, sizeof(cria));
cria.cri_alg = sc->sc_aalgo;
@@ -368,6 +376,9 @@ g_eli_newsession(struct g_eli_worker *wr)
panic("%s: invalid condition", __func__);
}
+ if ((sc->sc_flags & G_ELI_FLAG_FIRST_KEY) != 0)
+ g_eli_key_drop(sc, crie.cri_key);
+
return (error);
}
@@ -708,6 +719,8 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
sc->sc_flags |= G_ELI_FLAG_NATIVE_BYTE_ORDER;
if (md->md_version < 5)
sc->sc_flags |= G_ELI_FLAG_SINGLE_KEY;
+ if (md->md_version < 6 && (sc->sc_flags & G_ELI_FLAG_AUTH) != 0)
+ sc->sc_flags |= G_ELI_FLAG_FIRST_KEY;
sc->sc_ealgo = md->md_ealgo;
sc->sc_nkey = nkey;
diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h
index e0fa616..68f92e5 100644
--- a/sys/geom/eli/g_eli.h
+++ b/sys/geom/eli/g_eli.h
@@ -63,10 +63,19 @@
* 2 - Added G_ELI_FLAG_READONLY.
* 3 - Added 'configure' subcommand.
* 4 - IV is generated from offset converted to little-endian
- * (flag G_ELI_FLAG_NATIVE_BYTE_ORDER will be set for older versions).
+ * (the G_ELI_FLAG_NATIVE_BYTE_ORDER flag will be set for older versions).
* 5 - Added multiple encrypton keys and AES-XTS support.
+ * 6 - Fixed usage of multiple keys for authenticated providers (the
+ * G_ELI_FLAG_FIRST_KEY flag will be set for older versions).
*/
-#define G_ELI_VERSION 5
+#define G_ELI_VERSION_00 0
+#define G_ELI_VERSION_01 1
+#define G_ELI_VERSION_02 2
+#define G_ELI_VERSION_03 3
+#define G_ELI_VERSION_04 4
+#define G_ELI_VERSION_05 5
+#define G_ELI_VERSION_06 6
+#define G_ELI_VERSION G_ELI_VERSION_06
/* ON DISK FLAGS. */
/* Use random, onetime keys. */
@@ -92,6 +101,8 @@
#define G_ELI_FLAG_SINGLE_KEY 0x00080000
/* Device suspended. */
#define G_ELI_FLAG_SUSPEND 0x00100000
+/* Provider uses first encryption key. */
+#define G_ELI_FLAG_FIRST_KEY 0x00200000
#define G_ELI_NEW_BIO 255
@@ -254,7 +265,7 @@ eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
}
static __inline int
-eli_metadata_decode_v1v2v3v4v5(const u_char *data, struct g_eli_metadata *md)
+eli_metadata_decode_v1v2v3v4v5v6(const u_char *data, struct g_eli_metadata *md)
{
MD5_CTX ctx;
const u_char *p;
@@ -285,15 +296,16 @@ eli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
bcopy(data, md->md_magic, sizeof(md->md_magic));
md->md_version = le32dec(data + sizeof(md->md_magic));
switch (md->md_version) {
- case 0:
+ case G_ELI_VERSION_00:
error = eli_metadata_decode_v0(data, md);
break;
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- error = eli_metadata_decode_v1v2v3v4v5(data, md);
+ case G_ELI_VERSION_01:
+ case G_ELI_VERSION_02:
+ case G_ELI_VERSION_03:
+ case G_ELI_VERSION_04:
+ case G_ELI_VERSION_05:
+ case G_ELI_VERSION_06:
+ error = eli_metadata_decode_v1v2v3v4v5v6(data, md);
break;
default:
error = EINVAL;
@@ -509,8 +521,6 @@ void g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb);
void g_eli_read_done(struct bio *bp);
void g_eli_write_done(struct bio *bp);
int g_eli_crypto_rerun(struct cryptop *crp);
-uint8_t *g_eli_crypto_key(struct g_eli_softc *sc, off_t offset,
- size_t blocksize);
void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
size_t size);
diff --git a/sys/geom/eli/g_eli_ctl.c b/sys/geom/eli/g_eli_ctl.c
index a5de30b..65672d5 100644
--- a/sys/geom/eli/g_eli_ctl.c
+++ b/sys/geom/eli/g_eli_ctl.c
@@ -1014,7 +1014,12 @@ g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb)
gctl_error(req, "No '%s' argument.", "version");
return;
}
- if (*version != G_ELI_VERSION) {
+ while (*version != G_ELI_VERSION) {
+ if (G_ELI_VERSION == G_ELI_VERSION_06 &&
+ *version == G_ELI_VERSION_05) {
+ /* Compatible. */
+ break;
+ }
gctl_error(req, "Userland and kernel parts are out of sync.");
return;
}
diff --git a/sys/geom/eli/g_eli_integrity.c b/sys/geom/eli/g_eli_integrity.c
index d37bacb..50f2a31 100644
--- a/sys/geom/eli/g_eli_integrity.c
+++ b/sys/geom/eli/g_eli_integrity.c
@@ -149,7 +149,7 @@ g_eli_auth_read_done(struct cryptop *crp)
bp->bio_error = crp->crp_etype;
}
sc = bp->bio_to->geom->softc;
- g_eli_key_drop(sc, crp->crp_desc->crd_key);
+ g_eli_key_drop(sc, crp->crp_desc->crd_next->crd_key);
/*
* Do we have all sectors already?
*/
@@ -513,6 +513,8 @@ g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp)
crde->crd_skip = sc->sc_alen;
crde->crd_len = data_secsize;
crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
+ if ((sc->sc_flags & G_ELI_FLAG_FIRST_KEY) == 0)
+ crde->crd_flags |= CRD_F_KEY_EXPLICIT;
if (bp->bio_cmd == BIO_WRITE)
crde->crd_flags |= CRD_F_ENCRYPT;
crde->crd_alg = sc->sc_ealgo;
diff --git a/sys/geom/eli/g_eli_key_cache.c b/sys/geom/eli/g_eli_key_cache.c
index 9dc65a2..0a5a9ca 100644
--- a/sys/geom/eli/g_eli_key_cache.c
+++ b/sys/geom/eli/g_eli_key_cache.c
@@ -57,9 +57,13 @@ static uint64_t g_eli_key_cache_misses;
SYSCTL_UQUAD(_kern_geom_eli, OID_AUTO, key_cache_misses, CTLFLAG_RW,
&g_eli_key_cache_misses, 0, "Key cache misses");
+#define G_ELI_KEY_MAGIC 0xe11341c
+
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. */
@@ -98,6 +102,7 @@ g_eli_key_fill(struct g_eli_softc *sc, struct g_eli_key *key, uint64_t keyno)
sizeof(hmacdata), key->gek_key, 0);
key->gek_keyno = keyno;
key->gek_count = 0;
+ key->gek_magic = G_ELI_KEY_MAGIC;
}
static struct g_eli_key *
@@ -150,6 +155,7 @@ g_eli_key_replace(struct g_eli_softc *sc, struct g_eli_key *key, uint64_t keyno)
{
mtx_assert(&sc->sc_ekeys_lock, MA_OWNED);
+ KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid magic."));
RB_REMOVE(g_eli_key_tree, &sc->sc_ekeys_tree, key);
TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
@@ -167,7 +173,7 @@ g_eli_key_remove(struct g_eli_softc *sc, struct g_eli_key *key)
{
mtx_assert(&sc->sc_ekeys_lock, MA_OWNED);
-
+ KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid magic."));
KASSERT(key->gek_count == 0, ("gek_count=%d", key->gek_count));
RB_REMOVE(g_eli_key_tree, &sc->sc_ekeys_tree, key);
@@ -276,6 +282,8 @@ g_eli_key_hold(struct g_eli_softc *sc, off_t offset, size_t blocksize)
/* We have all the keys, so avoid some overhead. */
key = RB_FIND(g_eli_key_tree, &sc->sc_ekeys_tree, &keysearch);
KASSERT(key != NULL, ("No key %ju found.", (uintmax_t)keyno));
+ KASSERT(key->gek_magic == G_ELI_KEY_MAGIC,
+ ("Invalid key magic."));
return (key->gek_key);
}
@@ -306,6 +314,8 @@ g_eli_key_hold(struct g_eli_softc *sc, off_t offset, size_t blocksize)
key->gek_count++;
mtx_unlock(&sc->sc_ekeys_lock);
+ KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid key magic."));
+
return (key->gek_key);
}
@@ -317,6 +327,8 @@ g_eli_key_drop(struct g_eli_softc *sc, uint8_t *rawkey)
if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0)
return;
+ KASSERT(key->gek_magic == G_ELI_KEY_MAGIC, ("Invalid key magic."));
+
if (sc->sc_ekeys_total == sc->sc_ekeys_allocated)
return;
diff --git a/sys/geom/part/g_part_apm.c b/sys/geom/part/g_part_apm.c
index 9806bb8..cd318c7 100644
--- a/sys/geom/part/g_part_apm.c
+++ b/sys/geom/part/g_part_apm.c
@@ -255,7 +255,7 @@ g_part_apm_create(struct g_part_table *basetable, struct g_part_parms *gpp)
return (ENOSPC);
/* APM uses 32-bit LBAs. */
- last = MIN(pp->mediasize / pp->sectorsize, 0xffffffff) - 1;
+ last = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX) - 1;
basetable->gpt_first = 2 + basetable->gpt_entries;
basetable->gpt_last = last;
@@ -398,6 +398,8 @@ g_part_apm_probe(struct g_part_table *basetable, struct g_consumer *cp)
g_free(buf);
if (table->ddr.ddr_blksize != pp->sectorsize)
return (ENXIO);
+ if (table->ddr.ddr_blkcount > pp->mediasize / pp->sectorsize)
+ return (ENXIO);
} else {
/*
* Check for Tivo drives, which have no DDR and a different
@@ -412,7 +414,8 @@ g_part_apm_probe(struct g_part_table *basetable, struct g_consumer *cp)
}
table->ddr.ddr_sig = APM_DDR_SIG; /* XXX */
table->ddr.ddr_blksize = pp->sectorsize; /* XXX */
- table->ddr.ddr_blkcount = pp->mediasize / pp->sectorsize;/* XXX */
+ table->ddr.ddr_blkcount =
+ MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
table->tivo_series1 = 1;
g_free(buf);
}
diff --git a/sys/geom/part/g_part_bsd.c b/sys/geom/part/g_part_bsd.c
index 61fe89a..269b943 100644
--- a/sys/geom/part/g_part_bsd.c
+++ b/sys/geom/part/g_part_bsd.c
@@ -206,7 +206,7 @@ g_part_bsd_create(struct g_part_table *basetable, struct g_part_parms *gpp)
if (BBSIZE % pp->sectorsize)
return (ENOTBLK);
- msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
secpercyl = basetable->gpt_sectors * basetable->gpt_heads;
ncyls = msize / secpercyl;
@@ -365,7 +365,7 @@ g_part_bsd_read(struct g_part_table *basetable, struct g_consumer *cp)
pp = cp->provider;
table = (struct g_part_bsd_table *)basetable;
- msize = pp->mediasize / pp->sectorsize;
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
table->bbarea = g_read_data(cp, 0, BBSIZE, &error);
if (table->bbarea == NULL)
diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c
index 5f665ca..f6278cc 100644
--- a/sys/geom/part/g_part_ebr.c
+++ b/sys/geom/part/g_part_ebr.c
@@ -288,7 +288,7 @@ g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
if (strcmp(psn, "MBR"))
return (ENXIO);
- msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
msize -= msize % basetable->gpt_sectors;
basetable->gpt_first = 0;
basetable->gpt_last = msize - 1;
@@ -464,7 +464,7 @@ g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp)
pp = cp->provider;
table = (struct g_part_ebr_table *)basetable;
- msize = pp->mediasize / pp->sectorsize;
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
lba = 0;
while (1) {
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c
index 63b7e64..4fa829a 100644
--- a/sys/geom/part/g_part_mbr.c
+++ b/sys/geom/part/g_part_mbr.c
@@ -262,7 +262,7 @@ g_part_mbr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
if (pp->sectorsize < MBRSIZE)
return (ENOSPC);
- msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
basetable->gpt_first = basetable->gpt_sectors;
basetable->gpt_last = msize - (msize % basetable->gpt_sectors) - 1;
@@ -433,7 +433,7 @@ g_part_mbr_read(struct g_part_table *basetable, struct g_consumer *cp)
pp = cp->provider;
table = (struct g_part_mbr_table *)basetable;
- msize = pp->mediasize / pp->sectorsize;
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
buf = g_read_data(cp, 0L, pp->sectorsize, &error);
if (buf == NULL)
diff --git a/sys/geom/part/g_part_pc98.c b/sys/geom/part/g_part_pc98.c
index d8aa87d..693fad8 100644
--- a/sys/geom/part/g_part_pc98.c
+++ b/sys/geom/part/g_part_pc98.c
@@ -261,7 +261,7 @@ g_part_pc98_create(struct g_part_table *basetable, struct g_part_parms *gpp)
cyl = basetable->gpt_heads * basetable->gpt_sectors;
- msize = MIN(pp->mediasize / SECSIZE, 0xffffffff);
+ msize = MIN(pp->mediasize / SECSIZE, UINT32_MAX);
basetable->gpt_first = cyl;
basetable->gpt_last = msize - (msize % cyl) - 1;
@@ -451,7 +451,7 @@ g_part_pc98_read(struct g_part_table *basetable, struct g_consumer *cp)
pp = cp->provider;
table = (struct g_part_pc98_table *)basetable;
- msize = pp->mediasize / SECSIZE;
+ msize = MIN(pp->mediasize / SECSIZE, UINT32_MAX);
buf = g_read_data(cp, 0L, BOOTSIZE, &error);
if (buf == NULL)
diff --git a/sys/geom/part/g_part_vtoc8.c b/sys/geom/part/g_part_vtoc8.c
index e59c8e4..245d1f9 100644
--- a/sys/geom/part/g_part_vtoc8.c
+++ b/sys/geom/part/g_part_vtoc8.c
@@ -198,9 +198,7 @@ g_part_vtoc8_create(struct g_part_table *basetable, struct g_part_parms *gpp)
table = (struct g_part_vtoc8_table *)basetable;
- msize = pp->mediasize / pp->sectorsize;
- if (msize > 0xffffffffu)
- msize = 0xffffffffu;
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
table->secpercyl = basetable->gpt_sectors * basetable->gpt_heads;
pcyls = msize / table->secpercyl;
acyls = 2;
@@ -392,8 +390,7 @@ g_part_vtoc8_read(struct g_part_table *basetable, struct g_consumer *cp)
bcopy(buf, &table->vtoc, sizeof(table->vtoc));
g_free(buf);
- msize = pp->mediasize / pp->sectorsize;
-
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
sectors = be16dec(&table->vtoc.nsecs);
if (sectors < 1)
goto invalid_label;
OpenPOWER on IntegriCloud