summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2009-12-31 14:00:46 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2009-12-31 14:00:46 +0000
commit6c48a0797c3ce6da990d15cfd72f07f067df8e92 (patch)
tree9a9a5dbe741b0f8687bbcd65c0491e04aef8c4ee /sys/dev
parentde50ae56c1a30c7995a9b681464dbd29776af065 (diff)
Add support for key disks. This allows a crypto volume to be constructed
without using a passphrase - instead the encryption mask key is stored on the specified key disk partition (ideally being one on a removable device). This also enables automatic assembly of crypto volumes at boot time. ok marco@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/biovar.h3
-rw-r--r--sys/dev/softraid.c68
-rw-r--r--sys/dev/softraid_crypto.c353
-rw-r--r--sys/dev/softraidvar.h24
4 files changed, 413 insertions, 35 deletions
diff --git a/sys/dev/biovar.h b/sys/dev/biovar.h
index 8051c913316..2448903a74d 100644
--- a/sys/dev/biovar.h
+++ b/sys/dev/biovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: biovar.h,v 1.36 2009/11/23 16:33:59 jsing Exp $ */
+/* $OpenBSD: biovar.h,v 1.37 2009/12/31 14:00:45 jsing Exp $ */
/*
* Copyright (c) 2002 Niklas Hallqvist. All rights reserved.
@@ -177,6 +177,7 @@ struct bioc_createraid {
void *bc_cookie;
void *bc_dev_list;
u_int16_t bc_dev_list_len;
+ int32_t bc_key_disk;
#define BIOC_CRMAXLEN 1024
u_int16_t bc_level;
u_int32_t bc_flags;
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index 0bb97ccf9ec..4322c997285 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.187 2009/12/15 15:51:43 jsing Exp $ */
+/* $OpenBSD: softraid.c,v 1.188 2009/12/31 14:00:45 jsing Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -136,14 +136,9 @@ void sr_sensors_delete(struct sr_discipline *);
/* metadata */
int sr_meta_probe(struct sr_discipline *, dev_t *, int);
int sr_meta_attach(struct sr_discipline *, int);
-void sr_meta_getdevname(struct sr_softc *, dev_t, char *,
- int);
int sr_meta_rw(struct sr_discipline *, dev_t, void *,
size_t, daddr64_t, long);
int sr_meta_clear(struct sr_discipline *);
-int sr_meta_read(struct sr_discipline *);
-int sr_meta_validate(struct sr_discipline *, dev_t,
- struct sr_metadata *, void *);
void sr_meta_chunks_create(struct sr_softc *,
struct sr_chunk_head *);
void sr_meta_init(struct sr_discipline *,
@@ -181,8 +176,6 @@ int sr_meta_native_bootprobe(struct sr_softc *,
int sr_meta_native_probe(struct sr_softc *,
struct sr_chunk *);
int sr_meta_native_attach(struct sr_discipline *, int);
-int sr_meta_native_read(struct sr_discipline *, dev_t,
- struct sr_metadata *, void *);
int sr_meta_native_write(struct sr_discipline *, dev_t,
struct sr_metadata *,void *);
@@ -211,9 +204,7 @@ struct sr_meta_driver {
{ SR_META_OFFSET, SR_META_SIZE * 512,
sr_meta_native_probe, sr_meta_native_attach, NULL,
sr_meta_native_read, sr_meta_native_write, NULL },
-#define SR_META_F_NATIVE 0
{ 0, 0, NULL, NULL, NULL, NULL }
-#define SR_META_F_INVALID -1
};
int
@@ -990,7 +981,7 @@ sr_boot_assembly(struct sr_softc *sc)
{
struct device *dv;
struct bioc_createraid bc;
- struct sr_metadata_list_head mlh;
+ struct sr_metadata_list_head mlh, kdh;
struct sr_metadata_list *mle, *mlenext, *mle1, *mle2;
struct sr_metadata *metadata;
struct sr_boot_volume_head bvh;
@@ -1027,7 +1018,10 @@ sr_boot_assembly(struct sr_softc *sc)
/*
* Create a list of volumes and associate chunks with each volume.
*/
+
SLIST_INIT(&bvh);
+ SLIST_INIT(&kdh);
+
for (mle = SLIST_FIRST(&mlh); mle != SLIST_END(&mlh); mle = mlenext) {
mlenext = SLIST_NEXT(mle, sml_link);
@@ -1036,6 +1030,12 @@ sr_boot_assembly(struct sr_softc *sc)
metadata = (struct sr_metadata *)&mle->sml_metadata;
mle->sml_chunk_id = metadata->ssdi.ssd_chunk_id;
+ /* Handle key disks separately. */
+ if (metadata->ssdi.ssd_level == SR_KEYDISK_LEVEL) {
+ SLIST_INSERT_HEAD(&kdh, mle, sml_link);
+ continue;
+ }
+
SLIST_FOREACH(vol, &bvh, sbv_link) {
if (bcmp(&metadata->ssdi.ssd_uuid, &vol->sbv_uuid,
sizeof(metadata->ssdi.ssd_uuid)) == 0)
@@ -1184,6 +1184,8 @@ sr_boot_assembly(struct sr_softc *sc)
*/
SLIST_FOREACH(vol, &bvh, sbv_link) {
+ bzero(&bc, sizeof(bc));
+
/* Check if this is a hotspare "volume". */
if (vol->sbv_level == SR_HOTSPARE_LEVEL &&
vol->sbv_chunk_no == 1)
@@ -1197,6 +1199,23 @@ sr_boot_assembly(struct sr_softc *sc)
vol->sbv_volid, vol->sbv_chunk_no);
#endif
+ /*
+ * If this is a crypto volume, try to find a matching
+ * key disk...
+ */
+ bc.bc_key_disk = NODEV;
+ if (vol->sbv_level == 'C') {
+ SLIST_FOREACH(mle, &kdh, sml_link) {
+ metadata =
+ (struct sr_metadata *)&mle->sml_metadata;
+ if (bcmp(&metadata->ssdi.ssd_uuid,
+ &vol->sbv_uuid,
+ sizeof(metadata->ssdi.ssd_uuid)) == 0) {
+ bc.bc_key_disk = mle->sml_mm;
+ }
+ }
+ }
+
for (i = 0; i < BIOC_CRMAXLEN; i++) {
devs[i] = NODEV; /* mark device as illegal */
ondisk[i] = 0;
@@ -1231,7 +1250,6 @@ sr_boot_assembly(struct sr_softc *sc)
DEVNAME(sc), vol->sbv_volid);
}
- bzero(&bc, sizeof(bc));
bc.bc_level = vol->sbv_level;
bc.bc_dev_list_len = vol->sbv_chunk_no * sizeof(dev_t);
bc.bc_dev_list = devs;
@@ -2037,6 +2055,13 @@ sr_ioctl_vol(struct sr_softc *sc, struct bioc_vol *bv)
bv->bv_size = sd->sd_meta->ssdi.ssd_size << DEV_BSHIFT;
bv->bv_level = sd->sd_meta->ssdi.ssd_level;
bv->bv_nodisk = sd->sd_meta->ssdi.ssd_chunk_no;
+
+#ifdef CRYPTO
+ if (sd->sd_meta->ssdi.ssd_level == 'C' &&
+ sd->mds.mdd_crypto.key_disk != NULL)
+ bv->bv_nodisk++;
+#endif
+
if (bv->bv_status == BIOC_SVREBUILD) {
sz = sd->sd_meta->ssdi.ssd_size;
rb = sd->sd_meta->ssd_rebuild;
@@ -2090,10 +2115,18 @@ sr_ioctl_disk(struct sr_softc *sc, struct bioc_disk *bd)
continue;
id = bd->bd_diskid;
- if (id >= sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no)
+
+ if (id < sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no)
+ src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
+#ifdef CRYPTO
+ else if (id == sc->sc_dis[i]->sd_meta->ssdi.ssd_chunk_no &&
+ sc->sc_dis[i]->sd_meta->ssdi.ssd_level == 'C' &&
+ sc->sc_dis[i]->mds.mdd_crypto.key_disk != NULL)
+ src = sc->sc_dis[i]->mds.mdd_crypto.key_disk;
+#endif
+ else
break;
- src = sc->sc_dis[i]->sd_vol.sv_chunks[id];
bd->bd_status = src->src_meta.scm_status;
bd->bd_size = src->src_meta.scmi.scm_size << DEV_BSHIFT;
bd->bd_channel = vol;
@@ -2764,6 +2797,11 @@ sr_ioctl_createraid(struct sr_softc *sc, struct bioc_createraid *bc, int user)
sd->sd_meta->ssdi.ssd_level = bc->bc_level;
sd->sd_meta->ssdi.ssd_chunk_no = no_chunk;
+ /* Make the volume UUID available. */
+ bcopy(&ch_entry->src_meta.scmi.scm_uuid,
+ &sd->sd_meta->ssdi.ssd_uuid,
+ sizeof(sd->sd_meta->ssdi.ssd_uuid));
+
if (sd->sd_create) {
if ((i = sd->sd_create(sd, bc, no_chunk,
ch_entry->src_meta.scmi.scm_coerced_size))) {
@@ -3018,7 +3056,7 @@ sr_ioctl_discipline(struct sr_softc *sc, struct bioc_discipline *bd)
/* Dispatch a discipline specific ioctl. */
DNPRINTF(SR_D_IOCTL, "%s: sr_ioctl_discipline %s\n", DEVNAME(sc),
- dr->bd_dev);
+ bd->bd_dev);
for (i = 0; i < SR_MAXSCSIBUS; i++)
if (sc->sc_dis[i]) {
diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c
index 4b7fba4778a..3eb80233bb3 100644
--- a/sys/dev/softraid_crypto.c
+++ b/sys/dev/softraid_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid_crypto.c,v 1.44 2009/12/15 13:19:37 jsing Exp $ */
+/* $OpenBSD: softraid_crypto.c,v 1.45 2009/12/31 14:00:45 jsing Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Hans-Joerg Hoexer <hshoexer@openbsd.org>
@@ -128,19 +128,33 @@ sr_crypto_create(struct sr_discipline *sd, struct bioc_createraid *bc,
if (no_chunk != 1)
goto done;
- /* no hint available yet */
- if (bc->bc_opaque_flags & BIOC_SOOUT) {
+ sd->mds.mdd_crypto.key_disk = NULL;
+
+ if (bc->bc_key_disk != NODEV) {
+
+ /* Create a key disk. */
+ if (sr_crypto_get_kdf(bc, sd))
+ goto done;
+ sd->mds.mdd_crypto.key_disk =
+ sr_crypto_create_key_disk(sd, bc->bc_key_disk);
+ if (sd->mds.mdd_crypto.key_disk == NULL)
+ goto done;
+ sd->sd_capabilities |= SR_CAP_AUTO_ASSEMBLE;
+
+ } else if (bc->bc_opaque_flags & BIOC_SOOUT) {
+
+ /* No hint available yet. */
bc->bc_opaque_status = BIOC_SOINOUT_FAILED;
rv = EAGAIN;
goto done;
- }
- if (!(bc->bc_flags & BIOC_SCNOAUTOASSEMBLE))
+ } else if (sr_crypto_get_kdf(bc, sd))
goto done;
-
- if (sr_crypto_get_kdf(bc, sd))
+
+ /* Passphrase volumes cannot be automatically assembled. */
+ if (!(bc->bc_flags & BIOC_SCNOAUTOASSEMBLE) && bc->bc_key_disk == NODEV)
goto done;
-
+
strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name));
sd->sd_meta->ssdi.ssd_size = coerced_size;
@@ -159,8 +173,19 @@ sr_crypto_assemble(struct sr_discipline *sd, struct bioc_createraid *bc,
{
int rv = EINVAL;
- /* provide userland with kdf hint */
- if (bc->bc_opaque_flags & BIOC_SOOUT) {
+ sd->mds.mdd_crypto.key_disk = NULL;
+
+ if (bc->bc_key_disk != NODEV) {
+
+ /* Read the mask key from the key disk. */
+ sd->mds.mdd_crypto.key_disk =
+ sr_crypto_read_key_disk(sd, bc->bc_key_disk);
+ if (sd->mds.mdd_crypto.key_disk == NULL)
+ goto done;
+
+ } else if (bc->bc_opaque_flags & BIOC_SOOUT) {
+
+ /* provide userland with kdf hint */
if (bc->bc_opaque == NULL)
goto done;
@@ -176,13 +201,15 @@ sr_crypto_assemble(struct sr_discipline *sd, struct bioc_createraid *bc,
bc->bc_opaque_status = BIOC_SOINOUT_OK;
rv = EAGAIN;
goto done;
- }
- /* get kdf with maskkey from userland */
- if (bc->bc_opaque_flags & BIOC_SOIN)
+ } else if (bc->bc_opaque_flags & BIOC_SOIN) {
+
+ /* get kdf with maskkey from userland */
if (sr_crypto_get_kdf(bc, sd))
goto done;
+ }
+
sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi.ssd_chunk_no;
rv = 0;
@@ -374,7 +401,7 @@ sr_crypto_encrypt(u_char *p, u_char *c, u_char *key, size_t size, int alg)
break;
default:
DNPRINTF(SR_D_DIS, "%s: unsupported encryption algorithm %u\n",
- DEVNAME(sd->sd_sc), alg);
+ "softraid", alg);
rv = -1;
goto out;
}
@@ -400,7 +427,7 @@ sr_crypto_decrypt(u_char *c, u_char *p, u_char *key, size_t size, int alg)
break;
default:
DNPRINTF(SR_D_DIS, "%s: unsupported encryption algorithm %u\n",
- DEVNAME(sd->sd_sc), alg);
+ "softraid", alg);
rv = -1;
goto out;
}
@@ -595,6 +622,296 @@ out:
return (rv);
}
+struct sr_chunk *
+sr_crypto_create_key_disk(struct sr_discipline *sd, dev_t dev)
+{
+ struct sr_softc *sc = sd->sd_sc;
+ struct sr_discipline *fakesd = NULL;
+ struct sr_metadata *sm = NULL;
+ struct sr_meta_chunk *km;
+ struct sr_meta_opt *om;
+ struct sr_chunk *key_disk = NULL;
+ struct disklabel label;
+ struct vnode *vn;
+ char devname[32];
+ int c, part, open = 0;
+
+ /*
+ * Create a metadata structure on the key disk and store
+ * keying material in the optional metadata.
+ */
+
+ sr_meta_getdevname(sc, dev, devname, sizeof(devname));
+
+ /* Make sure chunk is not already in use. */
+ c = sr_chunk_in_use(sc, dev);
+ if (c != BIOC_SDINVALID && c != BIOC_SDOFFLINE) {
+ printf("%s: %s is already in use\n", DEVNAME(sc), devname);
+ goto done;
+ }
+
+ /* Open device. */
+ if (bdevvp(dev, &vn)) {
+ printf("%s:, sr_create_key_disk: can't allocate vnode\n",
+ DEVNAME(sc));
+ goto done;
+ }
+ if (VOP_OPEN(vn, FREAD | FWRITE, NOCRED, 0)) {
+ DNPRINTF(SR_D_META,"%s: sr_create_key_disk cannot open %s\n",
+ DEVNAME(sc), devname);
+ vput(vn);
+ goto fail;
+ }
+ open = 1; /* close dev on error */
+
+ /* Get partition details. */
+ part = DISKPART(dev);
+ if (VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, 0)) {
+ DNPRINTF(SR_D_META, "%s: sr_create_key_disk ioctl failed\n",
+ DEVNAME(sc));
+ VOP_CLOSE(vn, FREAD | FWRITE, NOCRED, 0);
+ vput(vn);
+ goto fail;
+ }
+ if (label.d_partitions[part].p_fstype != FS_RAID) {
+ printf("%s: %s partition not of type RAID (%d)\n",
+ DEVNAME(sc), devname,
+ label.d_partitions[part].p_fstype);
+ goto fail;
+ }
+
+ /*
+ * Create and populate chunk metadata.
+ */
+
+ key_disk = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_WAITOK | M_ZERO);
+ km = &key_disk->src_meta;
+
+ key_disk->src_dev_mm = dev;
+ key_disk->src_vn = vn;
+ strlcpy(key_disk->src_devname, devname, sizeof(km->scmi.scm_devname));
+ key_disk->src_size = 0;
+
+ km->scmi.scm_volid = sd->sd_meta->ssdi.ssd_level;
+ km->scmi.scm_chunk_id = 0;
+ km->scmi.scm_size = 0;
+ km->scmi.scm_coerced_size = 0;
+ strlcpy(km->scmi.scm_devname, devname, sizeof(km->scmi.scm_devname));
+ bcopy(&sd->sd_meta->ssdi.ssd_uuid, &km->scmi.scm_uuid,
+ sizeof(struct sr_uuid));
+
+ sr_checksum(sc, km, &km->scm_checksum,
+ sizeof(struct sr_meta_chunk_invariant));
+
+ km->scm_status = BIOC_SDONLINE;
+
+ /*
+ * Create and populate our own discipline and metadata.
+ */
+
+ sm = malloc(sizeof(struct sr_metadata), M_DEVBUF, M_WAITOK | M_ZERO);
+ sm->ssdi.ssd_magic = SR_MAGIC;
+ sm->ssdi.ssd_version = SR_META_VERSION;
+ sm->ssd_ondisk = 0;
+ sm->ssdi.ssd_flags = 0;
+ bcopy(&sd->sd_meta->ssdi.ssd_uuid, &sm->ssdi.ssd_uuid,
+ sizeof(struct sr_uuid));
+ sm->ssdi.ssd_chunk_no = 1;
+ sm->ssdi.ssd_volid = SR_KEYDISK_VOLID;
+ sm->ssdi.ssd_level = SR_KEYDISK_LEVEL;
+ sm->ssdi.ssd_size = 0;
+ strlcpy(sm->ssdi.ssd_vendor, "OPENBSD", sizeof(sm->ssdi.ssd_vendor));
+ snprintf(sm->ssdi.ssd_product, sizeof(sm->ssdi.ssd_product),
+ "SR %s", "KEYDISK");
+ snprintf(sm->ssdi.ssd_revision, sizeof(sm->ssdi.ssd_revision),
+ "%03d", SR_META_VERSION);
+
+ fakesd = malloc(sizeof(struct sr_discipline), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ fakesd->sd_sc = sd->sd_sc;
+ fakesd->sd_meta = sm;
+ fakesd->sd_meta_type = SR_META_F_NATIVE;
+ fakesd->sd_vol_status = BIOC_SVONLINE;
+ strlcpy(fakesd->sd_name, "KEYDISK", sizeof(fakesd->sd_name));
+
+ /* Add chunk to volume. */
+ fakesd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ fakesd->sd_vol.sv_chunks[0] = key_disk;
+ SLIST_INIT(&fakesd->sd_vol.sv_chunk_list);
+ SLIST_INSERT_HEAD(&fakesd->sd_vol.sv_chunk_list, key_disk, src_link);
+
+ /* Generate mask key. */
+ arc4random_buf(sd->mds.mdd_crypto.scr_maskkey,
+ sizeof(sd->mds.mdd_crypto.scr_maskkey));
+
+ /* Copy mask key to optional metadata area. */
+ sm->ssdi.ssd_opt_no = 1;
+ om = &key_disk->src_opt;
+ om->somi.som_type = SR_OPT_CRYPTO;
+ bcopy(sd->mds.mdd_crypto.scr_maskkey, &om->somi.som_meta.smm_crypto,
+ sizeof(om->somi.som_meta.smm_crypto));
+ sr_checksum(sc, om, om->som_checksum,
+ sizeof(struct sr_meta_opt_invariant));
+
+ /* Save metadata. */
+ if (sr_meta_save(fakesd, SR_META_DIRTY)) {
+ printf("%s: could not save metadata to %s\n",
+ DEVNAME(sc), devname);
+ goto fail;
+ }
+
+ goto done;
+
+fail:
+ if (key_disk)
+ free(key_disk, M_DEVBUF);
+ key_disk = NULL;
+
+done:
+ if (fakesd && fakesd->sd_vol.sv_chunks)
+ free(fakesd->sd_vol.sv_chunks, M_DEVBUF);
+ if (fakesd)
+ free(fakesd, M_DEVBUF);
+ if (sm)
+ free(sm, M_DEVBUF);
+ if (open) {
+ VOP_CLOSE(vn, FREAD | FWRITE, NOCRED, 0);
+ vput(vn);
+ }
+
+ return key_disk;
+}
+
+struct sr_chunk *
+sr_crypto_read_key_disk(struct sr_discipline *sd, dev_t dev)
+{
+ struct sr_softc *sc = sd->sd_sc;
+ struct sr_metadata *sm = NULL;
+ struct sr_meta_opt *om;
+ struct sr_chunk *key_disk = NULL;
+ struct disklabel label;
+ struct vnode *vn;
+ char devname[32];
+ int c, part, open = 0;
+
+ /*
+ * Load a key disk and load keying material into memory.
+ */
+
+ sr_meta_getdevname(sc, dev, devname, sizeof(devname));
+
+ /* Make sure chunk is not already in use. */
+ c = sr_chunk_in_use(sc, dev);
+ if (c != BIOC_SDINVALID && c != BIOC_SDOFFLINE) {
+ printf("%s: %s is already in use\n", DEVNAME(sc), devname);
+ goto done;
+ }
+
+ /* Open device. */
+ if (bdevvp(dev, &vn)) {
+ printf("%s:, sr_create_key_disk: can't allocate vnode\n",
+ DEVNAME(sc));
+ goto done;
+ }
+ if (VOP_OPEN(vn, FREAD | FWRITE, NOCRED, 0)) {
+ DNPRINTF(SR_D_META,"%s: sr_create_key_disk cannot open %s\n",
+ DEVNAME(sc), devname);
+ vput(vn);
+ goto done;
+ }
+ open = 1; /* close dev on error */
+
+ /* Get partition details. */
+ part = DISKPART(dev);
+ if (VOP_IOCTL(vn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, 0)) {
+ DNPRINTF(SR_D_META, "%s: sr_create_key_disk ioctl failed\n",
+ DEVNAME(sc));
+ VOP_CLOSE(vn, FREAD | FWRITE, NOCRED, 0);
+ vput(vn);
+ goto done;
+ }
+ if (label.d_partitions[part].p_fstype != FS_RAID) {
+ printf("%s: %s partition not of type RAID (%d)\n",
+ DEVNAME(sc), devname,
+ label.d_partitions[part].p_fstype);
+ goto done;
+ }
+
+ /*
+ * Read and validate key disk metadata.
+ */
+ sm = malloc(SR_META_SIZE * 512, M_DEVBUF, M_ZERO);
+ if (sm == NULL) {
+ printf("%s: not enough memory for metadata buffer\n",
+ DEVNAME(sc));
+ goto done;
+ }
+
+ if (sr_meta_native_read(sd, dev, sm, NULL)) {
+ printf("%s: native bootprobe could not read native "
+ "metadata\n", DEVNAME(sc));
+ goto done;
+ }
+
+ if (sr_meta_validate(sd, dev, sm, NULL)) {
+ DNPRINTF(SR_D_META, "%s: invalid metadata\n",
+ DEVNAME(sc));
+ goto done;
+ }
+
+ /* Make sure this is a key disk. */
+ if (sm->ssdi.ssd_level != SR_KEYDISK_LEVEL) {
+ printf("%s: %s is not a key disk\n", DEVNAME(sc), devname);
+ goto done;
+ }
+
+ /* Construct key disk chunk. */
+ key_disk = malloc(sizeof(struct sr_chunk), M_DEVBUF, M_ZERO);
+ if (key_disk == NULL) {
+ printf("%s: not enough memory for chunk\n",
+ DEVNAME(sc));
+ goto done;
+ }
+
+ key_disk->src_dev_mm = dev;
+ key_disk->src_vn = vn;
+ key_disk->src_size = 0;
+
+ bcopy((struct sr_meta_chunk *)(sm + 1), &key_disk->src_meta,
+ sizeof(key_disk->src_meta));
+
+ /* Read mask key from optional metadata. */
+
+ if (sm->ssdi.ssd_opt_no > 1)
+ panic("not yet read > 1 optional metadata members");
+
+ if (sm->ssdi.ssd_opt_no) {
+ om = (struct sr_meta_opt *)((u_int8_t *)(sm + 1) +
+ sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
+ bcopy(om, &key_disk->src_opt, sizeof(key_disk->src_opt));
+
+ if (om->somi.som_type == SR_OPT_CRYPTO) {
+ bcopy(&om->somi.som_meta.smm_crypto,
+ sd->mds.mdd_crypto.scr_maskkey,
+ sizeof(sd->mds.mdd_crypto.scr_maskkey));
+ }
+ }
+
+ open = 0;
+
+done:
+ if (sm)
+ free(sm, M_DEVBUF);
+
+ if (vn && open) {
+ VOP_CLOSE(vn, FREAD, NOCRED, 0);
+ vput(vn);
+ }
+
+ return key_disk;
+}
+
int
sr_crypto_alloc_resources(struct sr_discipline *sd)
{
@@ -671,6 +988,9 @@ sr_crypto_free_resources(struct sr_discipline *sd)
DNPRINTF(SR_D_DIS, "%s: sr_crypto_free_resources\n",
DEVNAME(sd->sd_sc));
+ if (sd->mds.mdd_crypto.key_disk != NULL)
+ free(sd->mds.mdd_crypto.key_disk, M_DEVBUF);
+
sr_hotplug_unregister(sd, sr_crypto_hotplug);
for (i = 0; sd->mds.mdd_crypto.scr_sid[i] != (u_int64_t)-1; i++) {
@@ -698,7 +1018,8 @@ sr_crypto_ioctl(struct sr_discipline *sd, struct bioc_discipline *bd)
struct sr_meta_opt *im_so;
int size, rv = 1;
- DNPRINTF(SR_D_IOCTL, "%s: sr_crypto_ioctl %u\n", DEVNAME(sc), cmd);
+ DNPRINTF(SR_D_IOCTL, "%s: sr_crypto_ioctl %u\n",
+ DEVNAME(sd->sd_sc), bd->bd_cmd);
switch (bd->bd_cmd) {
case SR_IOCTL_GET_KDFHINT:
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index ba89cf52b36..dcd126f735d 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.87 2009/12/15 13:19:37 jsing Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.88 2009/12/31 14:00:45 jsing Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -29,10 +29,16 @@ struct sr_uuid {
#define SR_HOTSPARE_LEVEL 0xffffffff
#define SR_HOTSPARE_VOLID 0xffffffff
+#define SR_KEYDISK_LEVEL 0xfffffffe
+#define SR_KEYDISK_VOLID 0xfffffffe
#define SR_META_SIZE 64 /* save space at chunk beginning */
#define SR_META_OFFSET 16 /* skip 8192 bytes at chunk beginning */
#define SR_META_VERSION 3 /* bump when sr_metadata changes */
+
+#define SR_META_F_NATIVE 0 /* Native metadata format. */
+#define SR_META_F_INVALID -1
+
struct sr_metadata {
struct sr_meta_invariant {
/* do not change order of ssd_magic, ssd_version */
@@ -150,8 +156,9 @@ struct sr_meta_opt {
struct sr_crypto_genkdf {
u_int32_t len;
u_int32_t type;
-#define SR_CRYPTOKDFT_INVALID (0)
-#define SR_CRYPTOKDFT_PBKDF2 (1<<0)
+#define SR_CRYPTOKDFT_INVALID 0
+#define SR_CRYPTOKDFT_PBKDF2 1
+#define SR_CRYPTOKDFT_KEYDISK 2
};
/* this is a hint for KDF using PKCS#5. Not interpreted by the kernel */
@@ -330,6 +337,7 @@ struct sr_raid6 {
#define SR_CRYPTO_NOWU 16
struct sr_crypto {
struct sr_meta_crypto scr_meta;
+ struct sr_chunk *key_disk;
struct pool sr_uiopl;
struct pool sr_iovpl;
@@ -549,8 +557,15 @@ void sr_wu_put(struct sr_workunit *);
/* misc functions */
int32_t sr_validate_stripsize(u_int32_t);
+int sr_meta_read(struct sr_discipline *);
+int sr_meta_native_read(struct sr_discipline *, dev_t,
+ struct sr_metadata *, void *);
+int sr_meta_validate(struct sr_discipline *, dev_t,
+ struct sr_metadata *, void *);
void sr_meta_save_callback(void *, void *);
int sr_meta_save(struct sr_discipline *, u_int32_t);
+void sr_meta_getdevname(struct sr_softc *, dev_t, char *,
+ int);
void sr_checksum(struct sr_softc *, void *, void *,
u_int32_t);
int sr_validate_io(struct sr_workunit *, daddr64_t *,
@@ -558,6 +573,7 @@ int sr_validate_io(struct sr_workunit *, daddr64_t *,
int sr_check_io_collision(struct sr_workunit *);
void sr_scsi_done(struct sr_discipline *,
struct scsi_xfer *);
+int sr_chunk_in_use(struct sr_softc *, dev_t);
/* discipline functions */
int sr_raid_inquiry(struct sr_workunit *);
@@ -588,6 +604,8 @@ void sr_raid1_set_vol_state(struct sr_discipline *);
int sr_crypto_get_kdf(struct bioc_createraid *,
struct sr_discipline *);
int sr_crypto_create_keys(struct sr_discipline *);
+struct sr_chunk * sr_crypto_create_key_disk(struct sr_discipline *, dev_t);
+struct sr_chunk * sr_crypto_read_key_disk(struct sr_discipline *, dev_t);
#ifdef SR_DEBUG
void sr_dump_mem(u_int8_t *, int);