summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/softraid.c142
-rw-r--r--sys/dev/softraid_crypto.c63
-rw-r--r--sys/dev/softraidvar.h45
3 files changed, 174 insertions, 76 deletions
diff --git a/sys/dev/softraid.c b/sys/dev/softraid.c
index de95e4460db..33654c730bf 100644
--- a/sys/dev/softraid.c
+++ b/sys/dev/softraid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid.c,v 1.247 2011/09/18 13:11:08 jsing Exp $ */
+/* $OpenBSD: softraid.c,v 1.248 2011/09/18 19:40:49 jsing Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -150,7 +150,7 @@ void sr_meta_chunks_create(struct sr_softc *,
void sr_meta_init(struct sr_discipline *,
struct sr_chunk_head *);
void sr_meta_opt_handler(struct sr_discipline *,
- struct sr_meta_opt *);
+ struct sr_meta_opt_hdr *);
/* hotplug magic */
void sr_disk_attach(struct disk *, int);
@@ -605,9 +605,9 @@ sr_meta_init(struct sr_discipline *sd, struct sr_chunk_head *cl)
}
void
-sr_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt *om)
+sr_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt_hdr *om)
{
- if (om->somi.som_type != SR_OPT_BOOT)
+ if (om->som_type != SR_OPT_BOOT)
panic("unknown optional metadata type");
}
@@ -636,8 +636,8 @@ sr_meta_save(struct sr_discipline *sd, u_int32_t flags)
struct sr_chunk *src;
struct sr_meta_chunk *cm;
struct sr_workunit wu;
+ struct sr_meta_opt_hdr *omh;
struct sr_meta_opt_item *omi;
- struct sr_meta_opt *om;
int i;
DNPRINTF(SR_D_META, "%s: sr_meta_save %s\n",
@@ -672,12 +672,17 @@ restart:
}
/* Optional metadata. */
- om = (struct sr_meta_opt *)(cm);
+ omh = (struct sr_meta_opt_hdr *)(cm);
SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link) {
- bcopy(&omi->omi_om, om, sizeof(*om));
- sr_checksum(sc, om, &om->som_checksum,
- sizeof(struct sr_meta_opt_invariant));
- om++;
+ DNPRINTF(SR_D_META, "%s: saving optional metadata type %u with "
+ "length %u\n", DEVNAME(sc), omi->omi_som->som_type,
+ omi->omi_som->som_length);
+ bzero(&omi->omi_som->som_checksum, MD5_DIGEST_LENGTH);
+ sr_checksum(sc, omi->omi_som, &omi->omi_som->som_checksum,
+ omi->omi_som->som_length);
+ bcopy(omi->omi_som, omh, omi->omi_som->som_length);
+ omh = (struct sr_meta_opt_hdr *)((u_int8_t *)omh +
+ omi->omi_som->som_length);
}
for (i = 0; i < sm->ssdi.ssd_chunk_no; i++) {
@@ -793,8 +798,8 @@ sr_meta_read(struct sr_discipline *sd)
sr_meta_opt_load(sc, sm, &sd->sd_meta_opt);
SLIST_FOREACH(omi, &sd->sd_meta_opt, omi_link)
if (sd->sd_meta_opt_handler == NULL ||
- sd->sd_meta_opt_handler(sd, &omi->omi_om) != 0)
- sr_meta_opt_handler(sd, &omi->omi_om);
+ sd->sd_meta_opt_handler(sd, omi->omi_som) != 0)
+ sr_meta_opt_handler(sd, omi->omi_som);
cp++;
no_disk++;
@@ -814,21 +819,85 @@ void
sr_meta_opt_load(struct sr_softc *sc, struct sr_metadata *sm,
struct sr_meta_opt_head *som)
{
+ struct sr_meta_opt_hdr *omh;
struct sr_meta_opt_item *omi;
- struct sr_meta_opt *om;
+ u_int8_t checksum[MD5_DIGEST_LENGTH];
int i;
/* Process optional metadata. */
- om = (struct sr_meta_opt *)((u_int8_t *)(sm + 1) +
+ omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(sm + 1) +
sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
for (i = 0; i < sm->ssdi.ssd_opt_no; i++) {
omi = malloc(sizeof(struct sr_meta_opt_item),
M_DEVBUF, M_WAITOK | M_ZERO);
- bcopy(om, &omi->omi_om, sizeof(struct sr_meta_opt));
SLIST_INSERT_HEAD(som, omi, omi_link);
- om++;
+ if (omh->som_length == 0) {
+
+ /* Load old fixed length optional metadata. */
+ DNPRINTF(SR_D_META, "%s: old optional metadata of type "
+ "%u\n", DEVNAME(sc), omh->som_type);
+
+ /* Validate checksum. */
+ sr_checksum(sc, (void *)omh, &checksum,
+ SR_OLD_META_OPT_SIZE - MD5_DIGEST_LENGTH);
+ if (bcmp(&checksum, (void *)omh + SR_OLD_META_OPT_MD5,
+ sizeof(checksum)))
+ panic("%s: invalid optional metadata "
+ "checksum", DEVNAME(sc));
+
+ /* Determine correct length. */
+ switch (omh->som_type) {
+ case SR_OPT_CRYPTO:
+ omh->som_length = sizeof(struct sr_meta_crypto);
+ break;
+ case SR_OPT_BOOT:
+ omh->som_length = sizeof(struct sr_meta_boot);
+ break;
+ case SR_OPT_KEYDISK:
+ omh->som_length =
+ sizeof(struct sr_meta_keydisk);
+ break;
+ default:
+ panic("unknown old optional metadata "
+ "type %u\n", omh->som_type);
+ }
+
+ omi->omi_som = malloc(omh->som_length, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ bcopy((u_int8_t *)omh + SR_OLD_META_OPT_OFFSET,
+ (u_int8_t *)omi->omi_som + sizeof(*omi->omi_som),
+ omh->som_length - sizeof(*omi->omi_som));
+ omi->omi_som->som_type = omh->som_type;
+ omi->omi_som->som_length = omh->som_length;
+
+ omh = (struct sr_meta_opt_hdr *)((void *)omh +
+ SR_OLD_META_OPT_SIZE);
+ } else {
+
+ /* Load variable length optional metadata. */
+ DNPRINTF(SR_D_META, "%s: optional metadata of type %u, "
+ "length %u\n", DEVNAME(sc), omh->som_type,
+ omh->som_length);
+ omi->omi_som = malloc(omh->som_length, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ bcopy(omh, omi->omi_som, omh->som_length);
+
+ /* Validate checksum. */
+ bcopy(&omi->omi_som->som_checksum, &checksum,
+ MD5_DIGEST_LENGTH);
+ bzero(&omi->omi_som->som_checksum, MD5_DIGEST_LENGTH);
+ sr_checksum(sc, omi->omi_som,
+ &omi->omi_som->som_checksum, omh->som_length);
+ if (bcmp(&checksum, &omi->omi_som->som_checksum,
+ sizeof(checksum)))
+ panic("%s: invalid optional metadata checksum",
+ DEVNAME(sc));
+
+ omh = (struct sr_meta_opt_hdr *)((void *)omh +
+ omh->som_length);
+ }
}
}
@@ -841,9 +910,9 @@ sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm,
#ifdef SR_DEBUG
struct sr_meta_chunk *mc;
#endif
+ u_int8_t checksum[MD5_DIGEST_LENGTH];
char devname[32];
int rv = 1;
- u_int8_t checksum[MD5_DIGEST_LENGTH];
DNPRINTF(SR_D_META, "%s: sr_meta_validate(%p)\n", DEVNAME(sc), sm);
@@ -880,13 +949,10 @@ sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm,
* Version 3 - update metadata version and fix up data offset
* value since this did not exist in version 3.
*/
- sm->ssdi.ssd_version = SR_META_VERSION;
- snprintf(sm->ssdi.ssd_revision, sizeof(sm->ssdi.ssd_revision),
- "%03d", SR_META_VERSION);
if (sm->ssd_data_offset == 0)
sm->ssd_data_offset = SR_META_V3_DATA_OFFSET;
- } else if (sm->ssdi.ssd_version == SR_META_VERSION) {
+ } else if (sm->ssdi.ssd_version == 4) {
/*
* Version 4 - original metadata format did not store
@@ -895,6 +961,14 @@ sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm,
if (sm->ssd_data_offset == 0)
sm->ssd_data_offset = SR_DATA_OFFSET;
+ } else if (sm->ssdi.ssd_version == SR_META_VERSION) {
+
+ /*
+ * Version 5 - variable length optional metadata. Migration
+ * from earlier fixed length optional metadata is handled
+ * in sr_meta_read().
+ */
+
} else {
printf("%s: %s can not read metadata version %u, expected %u\n",
@@ -904,6 +978,11 @@ sr_meta_validate(struct sr_discipline *sd, dev_t dev, struct sr_metadata *sm,
}
+ /* Update version number and revision string. */
+ sm->ssdi.ssd_version = SR_META_VERSION;
+ snprintf(sm->ssdi.ssd_revision, sizeof(sm->ssdi.ssd_revision),
+ "%03d", SR_META_VERSION);
+
#ifdef SR_DEBUG
/* warn if disk changed order */
mc = (struct sr_meta_chunk *)(sm + 1);
@@ -3377,7 +3456,7 @@ void
sr_discipline_free(struct sr_discipline *sd)
{
struct sr_softc *sc;
- struct sr_meta_opt_head *omh;
+ struct sr_meta_opt_head *som;
struct sr_meta_opt_item *omi, *omi_next;
if (!sd)
@@ -3397,9 +3476,11 @@ sr_discipline_free(struct sr_discipline *sd)
if (sd->sd_meta_foreign)
free(sd->sd_meta_foreign, M_DEVBUF);
- omh = &sd->sd_meta_opt;
- for (omi = SLIST_FIRST(omh); omi != SLIST_END(omh); omi = omi_next) {
+ som = &sd->sd_meta_opt;
+ for (omi = SLIST_FIRST(som); omi != SLIST_END(som); omi = omi_next) {
omi_next = SLIST_NEXT(omi, omi_link);
+ if (omi->omi_som)
+ free(omi->omi_som, M_DEVBUF);
free(omi, M_DEVBUF);
}
@@ -4217,7 +4298,7 @@ sr_meta_print(struct sr_metadata *m)
{
int i;
struct sr_meta_chunk *mc;
- struct sr_meta_opt *mo;
+ struct sr_meta_opt_hdr *omh;
if (!(sr_debug & SR_D_META))
return;
@@ -4259,12 +4340,15 @@ sr_meta_print(struct sr_metadata *m)
printf("\t\tscm_status %d\n", mc->scm_status);
}
- mo = (struct sr_meta_opt *)(mc);
- for (i = 0; i < m->ssdi.ssd_opt_no; i++, mo++) {
- printf("\t\t\tsom_type %d\n", mo->somi.som_type);
+ omh = (struct sr_meta_opt_hdr *)((u_int8_t *)(m + 1) +
+ sizeof(struct sr_meta_chunk) * m->ssdi.ssd_chunk_no);
+ for (i = 0; i < m->ssdi.ssd_opt_no; i++) {
+ printf("\t\t\tsom_type %d\n", omh->som_type);
printf("\t\t\tsom_checksum ");
- sr_checksum_print(mo->som_checksum);
+ sr_checksum_print(omh->som_checksum);
printf("\n");
+ omh = (struct sr_meta_opt_hdr *)((void *)omh +
+ omh->som_length);
}
}
diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c
index 73ae5efc3da..80a1983ddeb 100644
--- a/sys/dev/softraid_crypto.c
+++ b/sys/dev/softraid_crypto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraid_crypto.c,v 1.72 2011/09/18 13:11:08 jsing Exp $ */
+/* $OpenBSD: softraid_crypto.c,v 1.73 2011/09/18 19:40:49 jsing Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Hans-Joerg Hoexer <hshoexer@openbsd.org>
@@ -92,7 +92,7 @@ int sr_crypto_free_resources(struct sr_discipline *);
int sr_crypto_ioctl(struct sr_discipline *,
struct bioc_discipline *);
int sr_crypto_meta_opt_handler(struct sr_discipline *,
- struct sr_meta_opt *);
+ struct sr_meta_opt_hdr *);
int sr_crypto_write(struct cryptop *);
int sr_crypto_rw(struct sr_workunit *);
int sr_crypto_rw2(struct sr_workunit *, struct sr_crypto_wu *);
@@ -154,9 +154,12 @@ sr_crypto_create(struct sr_discipline *sd, struct bioc_createraid *bc,
/* Create crypto optional metadata. */
omi = malloc(sizeof(struct sr_meta_opt_item), M_DEVBUF,
M_WAITOK | M_ZERO);
- omi->omi_om.somi.som_type = SR_OPT_CRYPTO;
+ omi->omi_som = malloc(sizeof(struct sr_meta_crypto), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ omi->omi_som->som_type = SR_OPT_CRYPTO;
+ omi->omi_som->som_length = sizeof(struct sr_meta_crypto);
SLIST_INSERT_HEAD(&sd->sd_meta_opt, omi, omi_link);
- sd->mds.mdd_crypto.scr_meta = &omi->omi_om.somi.som_meta.smm_crypto;
+ sd->mds.mdd_crypto.scr_meta = (struct sr_meta_crypto *)omi->omi_som;
sd->sd_meta->ssdi.ssd_opt_no++;
sd->mds.mdd_crypto.key_disk = NULL;
@@ -676,6 +679,7 @@ sr_crypto_create_key_disk(struct sr_discipline *sd, dev_t dev)
struct sr_metadata *sm = NULL;
struct sr_meta_chunk *km;
struct sr_meta_opt_item *omi = NULL;
+ struct sr_meta_keydisk *skm;
struct sr_chunk *key_disk = NULL;
struct disklabel label;
struct vnode *vn;
@@ -793,14 +797,17 @@ sr_crypto_create_key_disk(struct sr_discipline *sd, dev_t dev)
sizeof(sd->mds.mdd_crypto.scr_maskkey));
/* Copy mask key to optional metadata area. */
- sm->ssdi.ssd_opt_no = 1;
omi = malloc(sizeof(struct sr_meta_opt_item), M_DEVBUF,
M_WAITOK | M_ZERO);
- omi->omi_om.somi.som_type = SR_OPT_KEYDISK;
- bcopy(sd->mds.mdd_crypto.scr_maskkey,
- omi->omi_om.somi.som_meta.smm_keydisk.skm_maskkey,
- sizeof(omi->omi_om.somi.som_meta.smm_keydisk.skm_maskkey));
+ omi->omi_som = malloc(sizeof(struct sr_meta_keydisk), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ omi->omi_som->som_type = SR_OPT_KEYDISK;
+ omi->omi_som->som_length = sizeof(struct sr_meta_keydisk);
+ skm = (struct sr_meta_keydisk *)omi->omi_som;
+ bcopy(sd->mds.mdd_crypto.scr_maskkey, &skm->skm_maskkey,
+ sizeof(skm->skm_maskkey));
SLIST_INSERT_HEAD(&fakesd->sd_meta_opt, omi, omi_link);
+ fakesd->sd_meta->ssdi.ssd_opt_no++;
/* Save metadata. */
if (sr_meta_save(fakesd, SR_META_DIRTY)) {
@@ -838,7 +845,10 @@ 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_meta_opt_item *omi, *omi_next;
+ struct sr_meta_opt_hdr *omh;
+ struct sr_meta_keydisk *skm;
+ struct sr_meta_opt_head som;
struct sr_chunk *key_disk = NULL;
struct disklabel label;
struct vnode *vn = NULL;
@@ -920,26 +930,33 @@ sr_crypto_read_key_disk(struct sr_discipline *sd, dev_t dev)
sizeof(key_disk->src_meta));
/* Read mask key from optional metadata. */
- om = (struct sr_meta_opt *)((u_int8_t *)(sm + 1) +
- sizeof(struct sr_meta_chunk) * sm->ssdi.ssd_chunk_no);
- for (c = 0; c < sm->ssdi.ssd_opt_no; c++) {
- if (om->somi.som_type == SR_OPT_KEYDISK) {
- bcopy(&om->somi.som_meta.smm_keydisk.skm_maskkey,
+ SLIST_INIT(&som);
+ sr_meta_opt_load(sc, sm, &som);
+ SLIST_FOREACH(omi, &som, omi_link) {
+ omh = omi->omi_som;
+ if (omh->som_type == SR_OPT_KEYDISK) {
+ skm = (struct sr_meta_keydisk *)omh;
+ bcopy(&skm->skm_maskkey,
sd->mds.mdd_crypto.scr_maskkey,
sizeof(sd->mds.mdd_crypto.scr_maskkey));
- break;
- } else if (om->somi.som_type == SR_OPT_CRYPTO) {
- bcopy(&om->somi.som_meta.smm_crypto,
+ } else if (omh->som_type == SR_OPT_CRYPTO) {
+ /* Original keydisk format with key in crypto area. */
+ bcopy(omh + sizeof(struct sr_meta_opt_hdr),
sd->mds.mdd_crypto.scr_maskkey,
sizeof(sd->mds.mdd_crypto.scr_maskkey));
- break;
}
- om++;
}
open = 0;
done:
+ for (omi = SLIST_FIRST(&som); omi != SLIST_END(&som); omi = omi_next) {
+ omi_next = SLIST_NEXT(omi, omi_link);
+ if (omi->omi_som)
+ free(omi->omi_som, M_DEVBUF);
+ free(omi, M_DEVBUF);
+ }
+
if (sm)
free(sm, M_DEVBUF);
@@ -1150,12 +1167,12 @@ bad:
}
int
-sr_crypto_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt *om)
+sr_crypto_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt_hdr *om)
{
int rv = EINVAL;
- if (om->somi.som_type == SR_OPT_CRYPTO) {
- sd->mds.mdd_crypto.scr_meta = &om->somi.som_meta.smm_crypto;
+ if (om->som_type == SR_OPT_CRYPTO) {
+ sd->mds.mdd_crypto.scr_meta = (struct sr_meta_crypto *)om;
rv = 0;
}
diff --git a/sys/dev/softraidvar.h b/sys/dev/softraidvar.h
index 0b27906da56..a53f55adada 100644
--- a/sys/dev/softraidvar.h
+++ b/sys/dev/softraidvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: softraidvar.h,v 1.107 2011/09/18 13:11:08 jsing Exp $ */
+/* $OpenBSD: softraidvar.h,v 1.108 2011/09/18 19:40:49 jsing Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2008 Chris Kuethe <ckuethe@openbsd.org>
@@ -28,7 +28,7 @@
#include <crypto/md5.h>
-#define SR_META_VERSION 4 /* bump when sr_metadata changes */
+#define SR_META_VERSION 5 /* bump when sr_metadata changes */
#define SR_META_SIZE 64 /* save space at chunk beginning */
#define SR_META_OFFSET 16 /* skip 8192 bytes at chunk beginning */
@@ -134,7 +134,19 @@ struct sr_crypto_chk_hmac_sha1 {
u_int8_t sch_mac[20];
} __packed;
+#define SR_OPT_INVALID 0x00
+#define SR_OPT_CRYPTO 0x01
+#define SR_OPT_BOOT 0x02
+#define SR_OPT_KEYDISK 0x03
+
+struct sr_meta_opt_hdr {
+ u_int32_t som_type; /* optional metadata type. */
+ u_int32_t som_length; /* optional metadata length. */
+ u_int8_t som_checksum[MD5_DIGEST_LENGTH];
+} __packed;
+
struct sr_meta_crypto {
+ struct sr_meta_opt_hdr scm_hdr;
u_int32_t scm_alg; /* vol crypto algorithm */
#define SR_CRYPTOA_AES_XTS_128 1
#define SR_CRYPTOA_AES_XTS_256 2
@@ -163,38 +175,23 @@ struct sr_meta_crypto {
} __packed;
struct sr_meta_boot {
+ struct sr_meta_opt_hdr sbm_hdr;
u_int64_t sbm_root_uid;
u_int32_t sbm_bootblk_size;
u_int32_t sbm_bootldr_size;
} __packed;
struct sr_meta_keydisk {
+ struct sr_meta_opt_hdr skm_hdr;
u_int8_t skm_maskkey[SR_CRYPTO_MAXKEYBYTES];
} __packed;
-struct sr_meta_opt {
- struct sr_meta_opt_invariant {
- u_int32_t som_type; /* optional type */
-#define SR_OPT_INVALID 0x00
-#define SR_OPT_CRYPTO 0x01
-#define SR_OPT_BOOT 0x02
-#define SR_OPT_KEYDISK 0x03
- u_int32_t som_pad;
- union {
- struct sr_meta_crypto smm_crypto;
- struct sr_meta_boot smm_boot;
- struct sr_meta_keydisk smm_keydisk;
- } som_meta;
- } _som_invariant;
-#define somi _som_invariant
-#define somi_crypto _som_invariant.smm_crypto
-#define somi_boot _som_invariant.smm_boot
- /* MD5 of invariant optional metadata */
- u_int8_t som_checksum[MD5_DIGEST_LENGTH];
-} __packed;
+#define SR_OLD_META_OPT_SIZE 2480
+#define SR_OLD_META_OPT_OFFSET 8
+#define SR_OLD_META_OPT_MD5 (SR_OLD_META_OPT_SIZE - MD5_DIGEST_LENGTH)
struct sr_meta_opt_item {
- struct sr_meta_opt omi_om;
+ struct sr_meta_opt_hdr *omi_som;
SLIST_ENTRY(sr_meta_opt_item) omi_link;
};
@@ -560,7 +557,7 @@ struct sr_discipline {
void (*sd_set_vol_state)(struct sr_discipline *);
int (*sd_openings)(struct sr_discipline *);
int (*sd_meta_opt_handler)(struct sr_discipline *,
- struct sr_meta_opt *);
+ struct sr_meta_opt_hdr *);
/* SCSI emulation */
struct scsi_sense_data sd_scsi_sense;