diff options
author | 2014-11-26 19:50:03 +0000 | |
---|---|---|
committer | 2014-11-26 19:50:03 +0000 | |
commit | 21e2043f619d8d059f7ba46612b6d0a5bbbaf9af (patch) | |
tree | 0cad49f9753589d1cd327f064379db253e08d032 | |
parent | Copy some Open Firmware interface functions from the kernel to ofwboot. (diff) | |
download | wireguard-openbsd-21e2043f619d8d059f7ba46612b6d0a5bbbaf9af.tar.xz wireguard-openbsd-21e2043f619d8d059f7ba46612b6d0a5bbbaf9af.zip |
Add softraid boot support code files ported by me to sparc64 from amd64.
Not hooked to the build yet.
ok kettenis@
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/softraid.c | 633 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/softraid.h | 34 |
2 files changed, 667 insertions, 0 deletions
diff --git a/sys/arch/sparc64/stand/ofwboot/softraid.c b/sys/arch/sparc64/stand/ofwboot/softraid.c new file mode 100644 index 00000000000..9308a8475ef --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/softraid.c @@ -0,0 +1,633 @@ +/* $OpenBSD: softraid.c,v 1.1 2014/11/26 19:50:03 stsp Exp $ */ + +/* + * Copyright (c) 2012 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/disklabel.h> +#include <sys/reboot.h> + +#include <dev/biovar.h> +#include <dev/softraidvar.h> + +#include <lib/libsa/stand.h> +#include <lib/libsa/aes_xts.h> +#include <lib/libsa/hmac_sha1.h> +#include <lib/libsa/pbkdf2.h> +#include <lib/libsa/rijndael.h> + +#include "disk.h" +#include "ofdev.h" +#include "softraid.h" + +/* List of softraid volumes. */ +struct sr_boot_volume_head sr_volumes; + +/* Metadata from keydisks. */ +struct sr_boot_keydisk { + struct sr_uuid kd_uuid; + u_int8_t kd_key[SR_CRYPTO_MAXKEYBYTES]; + SLIST_ENTRY(sr_boot_keydisk) kd_link; +}; +SLIST_HEAD(sr_boot_keydisk_head, sr_boot_keydisk); +struct sr_boot_keydisk_head sr_keydisks; + +void +srprobe_meta_opt_load(struct sr_metadata *sm, struct sr_meta_opt_head *som) +{ + struct sr_meta_opt_hdr *omh; + struct sr_meta_opt_item *omi; +#if 0 + u_int8_t checksum[MD5_DIGEST_LENGTH]; +#endif + int i; + + /* Process optional metadata. */ + 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++) { + +#ifdef DEBUG + printf("Found optional metadata of type %u, length %u\n", + omh->som_type, omh->som_length); +#endif + + /* Unsupported old fixed length optional metadata. */ + if (omh->som_length == 0) { + omh = (struct sr_meta_opt_hdr *)((void *)omh + + SR_OLD_META_OPT_SIZE); + continue; + } + + /* Load variable length optional metadata. */ + omi = alloc(sizeof(struct sr_meta_opt_item)); + bzero(omi, sizeof(struct sr_meta_opt_item)); + SLIST_INSERT_HEAD(som, omi, omi_link); + omi->omi_som = alloc(omh->som_length); + bzero(omi->omi_som, omh->som_length); + bcopy(omh, omi->omi_som, omh->som_length); + +#if 0 + /* XXX - 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)); +#endif + + omh = (struct sr_meta_opt_hdr *)((void *)omh + + omh->som_length); + } +} + +void +srprobe_keydisk_load(struct sr_metadata *sm) +{ + struct sr_meta_opt_hdr *omh; + struct sr_meta_keydisk *skm; + struct sr_boot_keydisk *kd; + int i; + + /* Process optional metadata. */ + 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++) { + + /* Unsupported old fixed length optional metadata. */ + if (omh->som_length == 0) { + omh = (struct sr_meta_opt_hdr *)((void *)omh + + SR_OLD_META_OPT_SIZE); + continue; + } + + if (omh->som_type != SR_OPT_KEYDISK) { + omh = (struct sr_meta_opt_hdr *)((void *)omh + + omh->som_length); + continue; + } + + kd = alloc(sizeof(struct sr_boot_keydisk)); + bcopy(&sm->ssdi.ssd_uuid, &kd->kd_uuid, sizeof(kd->kd_uuid)); + skm = (struct sr_meta_keydisk*)omh; + bcopy(&skm->skm_maskkey, &kd->kd_key, sizeof(kd->kd_key)); + SLIST_INSERT_HEAD(&sr_keydisks, kd, kd_link); + } +} + +void +srprobe(void) +{ + struct sr_boot_volume *bv, *bv1, *bv2; + struct sr_boot_chunk *bc, *bc1, *bc2; + struct sr_meta_chunk *mc; + struct sr_metadata *md; + struct diskinfo *dip; + struct partition *pp; + struct of_dev ofdev; + size_t read; + int i, error, diskno, volno, ihandle; + dev_t bsd_dev; + + /* Probe for softraid volumes. */ + SLIST_INIT(&sr_volumes); + SLIST_INIT(&sr_keydisks); + + md = alloc(SR_META_SIZE * 512); + diskno = 0; + ihandle = -1; + TAILQ_FOREACH(dip, &disklist, list) { + ihandle = OF_open(dip->path); + if (ihandle == -1) + continue; + bzero(&ofdev, sizeof(ofdev)); + ofdev.handle = ihandle; + ofdev.type = OFDEV_DISK; + ofdev.bsize = DEV_BSIZE; + for (i = 0; i < MAXPARTITIONS; i++) { + pp = &dip->disklabel.d_partitions[i]; + if (pp->p_fstype != FS_RAID || pp->p_size == 0) + continue; + + /* Read softraid metadata. */ + bzero(md, SR_META_SIZE * 512); + ofdev.partoff = DL_GETPOFFSET(pp); + error = strategy(&ofdev, F_READ, SR_META_OFFSET, + SR_META_SIZE * 512, md, &read); + if (error || read != SR_META_SIZE * 512) + continue; + + /* Is this valid softraid metadata? */ + if (md->ssdi.ssd_magic != SR_MAGIC) + continue; + + /* XXX - validate checksum. */ + + /* Handle key disks separately... */ + if (md->ssdi.ssd_level == SR_KEYDISK_LEVEL) { + srprobe_keydisk_load(md); + continue; + } + + /* Locate chunk-specific metadata for this chunk. */ + mc = (struct sr_meta_chunk *)(md + 1); + mc += md->ssdi.ssd_chunk_id; + + bc = alloc(sizeof(struct sr_boot_chunk)); + bc->sbc_diskinfo = dip; + bc->sbc_disk = diskno++; + bc->sbc_part = 'a' + i; + + bsd_dev = MAKEBOOTDEV( + dip->disklabel.d_type == DTYPE_SCSI ? 4 : 0, + 0, 0, diskno, RAW_PART); + bc->sbc_mm = MAKEBOOTDEV(B_TYPE(bsd_dev), + B_ADAPTOR(bsd_dev), B_CONTROLLER(bsd_dev), + B_UNIT(bsd_dev), bc->sbc_part - 'a'); + + bc->sbc_chunk_id = md->ssdi.ssd_chunk_id; + bc->sbc_ondisk = md->ssd_ondisk; + bc->sbc_state = mc->scm_status; + + SLIST_FOREACH(bv, &sr_volumes, sbv_link) { + if (bcmp(&md->ssdi.ssd_uuid, &bv->sbv_uuid, + sizeof(md->ssdi.ssd_uuid)) == 0) + break; + } + + if (bv == NULL) { + bv = alloc(sizeof(struct sr_boot_volume)); + bzero(bv, sizeof(struct sr_boot_volume)); + bv->sbv_level = md->ssdi.ssd_level; + bv->sbv_volid = md->ssdi.ssd_volid; + bv->sbv_chunk_no = md->ssdi.ssd_chunk_no; + bv->sbv_flags = md->ssdi.ssd_vol_flags; + bv->sbv_size = md->ssdi.ssd_size; + bv->sbv_data_offset = md->ssd_data_offset; + bcopy(&md->ssdi.ssd_uuid, &bv->sbv_uuid, + sizeof(md->ssdi.ssd_uuid)); + SLIST_INIT(&bv->sbv_chunks); + SLIST_INIT(&bv->sbv_meta_opt); + + /* Load optional metadata for this volume. */ + srprobe_meta_opt_load(md, &bv->sbv_meta_opt); + + /* Maintain volume order. */ + bv2 = NULL; + SLIST_FOREACH(bv1, &sr_volumes, sbv_link) { + if (bv1->sbv_volid > bv->sbv_volid) + break; + bv2 = bv1; + } + if (bv2 == NULL) + SLIST_INSERT_HEAD(&sr_volumes, bv, + sbv_link); + else + SLIST_INSERT_AFTER(bv2, bv, sbv_link); + } + + /* Maintain chunk order. */ + bc2 = NULL; + SLIST_FOREACH(bc1, &bv->sbv_chunks, sbc_link) { + if (bc1->sbc_chunk_id > bc->sbc_chunk_id) + break; + bc2 = bc1; + } + if (bc2 == NULL) + SLIST_INSERT_HEAD(&bv->sbv_chunks, + bc, sbc_link); + else + SLIST_INSERT_AFTER(bc2, bc, sbc_link); + + bv->sbv_chunks_found++; + } + OF_close(ihandle); + } + + /* + * Assemble RAID volumes. + */ + volno = 0; + SLIST_FOREACH(bv, &sr_volumes, sbv_link) { + + /* Skip if this is a hotspare "volume". */ + if (bv->sbv_level == SR_HOTSPARE_LEVEL && + bv->sbv_chunk_no == 1) + continue; + + /* Determine current ondisk version. */ + bv->sbv_ondisk = 0; + SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) { + if (bc->sbc_ondisk > bv->sbv_ondisk) + bv->sbv_ondisk = bc->sbc_ondisk; + } + SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) { + if (bc->sbc_ondisk != bv->sbv_ondisk) + bc->sbc_state = BIOC_SDOFFLINE; + } + + /* XXX - Check for duplicate chunks. */ + + /* + * Validate that volume has sufficient chunks for + * read-only access. + * + * XXX - check chunk states. + */ + bv->sbv_state = BIOC_SVOFFLINE; + switch (bv->sbv_level) { + case 0: + case 'C': + case 'c': + if (bv->sbv_chunk_no == bv->sbv_chunks_found) + bv->sbv_state = BIOC_SVONLINE; + break; + + case 1: + if (bv->sbv_chunk_no == bv->sbv_chunks_found) + bv->sbv_state = BIOC_SVONLINE; + else if (bv->sbv_chunks_found > 0) + bv->sbv_state = BIOC_SVDEGRADED; + break; + } + + bv->sbv_unit = volno++; + if (bv->sbv_state != BIOC_SVOFFLINE) + printf("sr%d%s\n", bv->sbv_unit, + bv->sbv_flags & BIOC_SCBOOTABLE ? "*" : ""); + } + + explicit_bzero(md, SR_META_SIZE * 512); + free(md, SR_META_SIZE * 512); +} + +int +sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size, + void *buf, size_t *rsize) +{ + struct diskinfo *sr_dip, *dip; + struct partition *pp; + struct sr_boot_chunk *bc; + struct aes_xts_ctx ctx; + struct of_dev ofdev; + size_t i, j, nsect; + daddr_t blkno; + u_char iv[8]; + u_char *bp; + int err; + int ihandle; + + /* We only support read-only softraid. */ + if (rw != F_READ) + return ENOTSUP; + + /* Partition offset within softraid volume. */ + sr_dip = (struct diskinfo *)bv->sbv_diskinfo; + blk += + DL_GETPOFFSET(&sr_dip->disklabel.d_partitions[bv->sbv_part - 'a']); + + if (bv->sbv_level == 0) { + return ENOTSUP; + } else if (bv->sbv_level == 1) { + + /* Select first online chunk. */ + SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) + if (bc->sbc_state == BIOC_SDONLINE) + break; + if (bc == NULL) + return EIO; + + dip = (struct diskinfo *)bc->sbc_diskinfo; + pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a']; + blk += bv->sbv_data_offset; + + /* XXX - If I/O failed we should try another chunk... */ + ihandle = OF_open(dip->path); + if (ihandle == -1) + return EIO; + bzero(&ofdev, sizeof(ofdev)); + ofdev.handle = ihandle; + ofdev.type = OFDEV_DISK; + ofdev.bsize = DEV_BSIZE; + ofdev.partoff = DL_GETPOFFSET(pp); + err = strategy(&ofdev, rw, blk, size, buf, rsize); + OF_close(ihandle); + return err; + + } else if (bv->sbv_level == 'C') { + + /* Select first online chunk. */ + SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) + if (bc->sbc_state == BIOC_SDONLINE) + break; + if (bc == NULL) + return EIO; + + dip = (struct diskinfo *)bc->sbc_diskinfo; + pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a']; + + ihandle = OF_open(dip->path); + if (ihandle == -1) + return EIO; + bzero(&ofdev, sizeof(ofdev)); + ofdev.handle = ihandle; + ofdev.type = OFDEV_DISK; + ofdev.bsize = DEV_BSIZE; + ofdev.partoff = DL_GETPOFFSET(pp); + + /* XXX - select correct key. */ + aes_xts_setkey(&ctx, (u_char *)bv->sbv_keys, 64); + + nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE; + for (i = 0; i < nsect; i++) { + blkno = blk + i; + bp = ((u_char *)buf) + i * DEV_BSIZE; + + err = strategy(&ofdev, rw, + bv->sbv_data_offset + blkno, + DEV_BSIZE, bp, rsize); + if (err != 0 || *rsize != DEV_BSIZE) { + printf("Read from crypto volume failed " + "(read %d bytes): %s\n", *rsize, + strerror(err)); + OF_close(ihandle); + return err; + } + bcopy(&blkno, iv, sizeof(blkno)); + aes_xts_reinit(&ctx, iv); + for (j = 0; j < DEV_BSIZE; j += AES_XTS_BLOCKSIZE) + aes_xts_decrypt(&ctx, bp + j); + } + *rsize = nsect * DEV_BSIZE; + OF_close(ihandle); + return err; + + } else + return ENOTSUP; +} + +const char * +sr_getdisklabel(struct sr_boot_volume *bv, struct disklabel *label) +{ + struct of_dev ofdev; + int err; +#ifdef DEBUG + int i; +#endif + + bzero(&ofdev, sizeof ofdev); + ofdev.type = OFDEV_SOFTRAID; + + if (load_disklabel(&ofdev, label)) + return ("Could not read disklabel from softraid"); +#ifdef DEBUG + printf("sr_getdisklabel: magic %lx\n", label->d_magic); + for (i = 0; i < MAXPARTITIONS; i++) + printf("part %c: type = %d, size = %d, offset = %d\n", 'a' + i, + (int)label->d_partitions[i].p_fstype, + (int)label->d_partitions[i].p_size, + (int)label->d_partitions[i].p_offset); +#endif + + return (NULL); +} + + +#define RIJNDAEL128_BLOCK_LEN 16 +#define PASSPHRASE_LENGTH 1024 + +#define SR_CRYPTO_KEYBLOCK_BYTES SR_CRYPTO_MAXKEYS * SR_CRYPTO_KEYBYTES + +#ifdef DEBUG +void +printhex(const char *s, const u_int8_t *buf, size_t len) +{ + u_int8_t n1, n2; + size_t i; + + printf("%s: ", s); + for (i = 0; i < len; i++) { + n1 = buf[i] & 0x0f; + n2 = buf[i] >> 4; + printf("%c", n2 > 9 ? n2 + 'a' - 10 : n2 + '0'); + printf("%c", n1 > 9 ? n1 + 'a' - 10 : n1 + '0'); + } + printf("\n"); +} +#endif + +void +sr_clear_keys(void) +{ + struct sr_boot_volume *bv; + struct sr_boot_keydisk *kd; + + SLIST_FOREACH(bv, &sr_volumes, sbv_link) { + if (bv->sbv_level != 'C') + continue; + if (bv->sbv_keys != NULL) { + explicit_bzero(bv->sbv_keys, SR_CRYPTO_KEYBLOCK_BYTES); + free(bv->sbv_keys, SR_CRYPTO_KEYBLOCK_BYTES); + bv->sbv_keys = NULL; + } + if (bv->sbv_maskkey != NULL) { + explicit_bzero(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES); + free(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES); + bv->sbv_maskkey = NULL; + } + } + SLIST_FOREACH(kd, &sr_keydisks, kd_link) { + explicit_bzero(kd, sizeof(*kd)); + free(kd, sizeof(*kd)); + } +} + +void +sr_crypto_calculate_check_hmac_sha1(u_int8_t *maskkey, int maskkey_size, + u_int8_t *key, int key_size, u_char *check_digest) +{ + u_int8_t check_key[SHA1_DIGEST_LENGTH]; + SHA1_CTX shactx; + + explicit_bzero(check_key, sizeof(check_key)); + explicit_bzero(&shactx, sizeof(shactx)); + + /* k = SHA1(mask_key) */ + SHA1Init(&shactx); + SHA1Update(&shactx, maskkey, maskkey_size); + SHA1Final(check_key, &shactx); + + /* mac = HMAC_SHA1_k(unencrypted key) */ + hmac_sha1(key, key_size, check_key, sizeof(check_key), check_digest); + + explicit_bzero(check_key, sizeof(check_key)); + explicit_bzero(&shactx, sizeof(shactx)); +} + +int +sr_crypto_decrypt_keys(struct sr_boot_volume *bv) +{ + struct sr_meta_crypto *cm; + struct sr_boot_keydisk *kd; + struct sr_meta_opt_item *omi; + struct sr_crypto_kdf_pbkdf2 *kdfhint; + struct sr_crypto_kdfinfo kdfinfo; + char passphrase[PASSPHRASE_LENGTH]; + u_int8_t digest[SHA1_DIGEST_LENGTH]; + u_int8_t *keys = NULL; + u_int8_t *kp, *cp; + rijndael_ctx ctx; + int rv = -1; + int c, i; + + SLIST_FOREACH(omi, &bv->sbv_meta_opt, omi_link) + if (omi->omi_som->som_type == SR_OPT_CRYPTO) + break; + + if (omi == NULL) { + printf("Crypto metadata not found!\n"); + goto done; + } + + cm = (struct sr_meta_crypto *)omi->omi_som; + kdfhint = (struct sr_crypto_kdf_pbkdf2 *)&cm->scm_kdfhint; + + switch (cm->scm_mask_alg) { + case SR_CRYPTOM_AES_ECB_256: + break; + default: + printf("unsupported encryption algorithm %u\n", + cm->scm_mask_alg); + goto done; + } + + SLIST_FOREACH(kd, &sr_keydisks, kd_link) { + if (bcmp(&kd->kd_uuid, &bv->sbv_uuid, sizeof(kd->kd_uuid)) == 0) + break; + } + if (kd) { + bcopy(&kd->kd_key, &kdfinfo.maskkey, sizeof(kdfinfo.maskkey)); + } else { + printf("Passphrase: "); + for (i = 0; i < PASSPHRASE_LENGTH - 1; i++) { + c = getchar(); + if (c == '\r' || c == '\n') + break; + passphrase[i] = (c & 0xff); + } + passphrase[i] = 0; + printf("\n"); + +#ifdef DEBUG + printf("Got passphrase: %s with len %d\n", + passphrase, strlen(passphrase)); +#endif + + if (pkcs5_pbkdf2(passphrase, strlen(passphrase), kdfhint->salt, + sizeof(kdfhint->salt), kdfinfo.maskkey, + sizeof(kdfinfo.maskkey), kdfhint->rounds) != 0) { + printf("pbkdf2 failed\n"); + goto done; + } + } + + /* kdfinfo->maskkey now has key. */ + + /* Decrypt disk keys. */ + keys = alloc(SR_CRYPTO_KEYBLOCK_BYTES); + bzero(keys, SR_CRYPTO_KEYBLOCK_BYTES); + + if (rijndael_set_key(&ctx, kdfinfo.maskkey, 256) != 0) + goto done; + + cp = (u_int8_t *)cm->scm_key; + kp = keys; + for (i = 0; i < SR_CRYPTO_KEYBLOCK_BYTES; i += RIJNDAEL128_BLOCK_LEN) + rijndael_decrypt(&ctx, (u_char *)(cp + i), (u_char *)(kp + i)); + + /* Check that the key decrypted properly. */ + sr_crypto_calculate_check_hmac_sha1(kdfinfo.maskkey, + sizeof(kdfinfo.maskkey), keys, SR_CRYPTO_KEYBLOCK_BYTES, digest); + + if (bcmp(digest, cm->chk_hmac_sha1.sch_mac, sizeof(digest))) { + printf("incorrect passphrase or keydisk\n"); + goto done; + } + + /* Keys and keydisks will be cleared before boot and from _rtt. */ + bv->sbv_keys = keys; + bv->sbv_maskkey = alloc(sizeof(kdfinfo.maskkey)); + bcopy(&kdfinfo.maskkey, bv->sbv_maskkey, sizeof(kdfinfo.maskkey)); + + rv = 0; + +done: + explicit_bzero(passphrase, PASSPHRASE_LENGTH); + explicit_bzero(&kdfinfo, sizeof(kdfinfo)); + explicit_bzero(digest, sizeof(digest)); + + if (keys != NULL && rv != 0) { + explicit_bzero(keys, SR_CRYPTO_KEYBLOCK_BYTES); + free(keys, SR_CRYPTO_KEYBLOCK_BYTES); + } + + return (rv); +} diff --git a/sys/arch/sparc64/stand/ofwboot/softraid.h b/sys/arch/sparc64/stand/ofwboot/softraid.h new file mode 100644 index 00000000000..77d43b69e9c --- /dev/null +++ b/sys/arch/sparc64/stand/ofwboot/softraid.h @@ -0,0 +1,34 @@ +/* $OpenBSD: softraid.h,v 1.1 2014/11/26 19:50:03 stsp Exp $ */ + +/* + * Copyright (c) 2012 Joel Sing <jsing@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SOFTRAID_H_ +#define _SOFTRAID_H_ + +void srprobe(void); + +const char *sr_getdisklabel(struct sr_boot_volume *, struct disklabel *); +int sr_strategy(struct sr_boot_volume *, int, daddr32_t, size_t, + void *, size_t *); + +int sr_crypto_decrypt_keys(struct sr_boot_volume *); +void sr_clear_keys(void); + +/* List of softraid volumes. */ +extern struct sr_boot_volume_head sr_volumes; + +#endif /* _SOFTRAID_H */ |