diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2009-12-31 14:00:46 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2009-12-31 14:00:46 +0000 |
commit | 6c48a0797c3ce6da990d15cfd72f07f067df8e92 (patch) | |
tree | 9a9a5dbe741b0f8687bbcd65c0491e04aef8c4ee /sys/dev | |
parent | de50ae56c1a30c7995a9b681464dbd29776af065 (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.h | 3 | ||||
-rw-r--r-- | sys/dev/softraid.c | 68 | ||||
-rw-r--r-- | sys/dev/softraid_crypto.c | 353 | ||||
-rw-r--r-- | sys/dev/softraidvar.h | 24 |
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); |