summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/stand/boot/Makefile17
-rw-r--r--sys/arch/amd64/stand/boot/conf.c4
-rw-r--r--sys/arch/amd64/stand/libsa/biosdev.c327
-rw-r--r--sys/arch/amd64/stand/libsa/dev_i386.c11
-rw-r--r--sys/arch/amd64/stand/libsa/disk.h11
-rw-r--r--sys/arch/amd64/stand/libsa/diskprobe.c260
-rw-r--r--sys/arch/amd64/stand/libsa/exec_i386.c22
-rw-r--r--sys/arch/amd64/stand/libsa/gidt.S4
-rw-r--r--sys/arch/amd64/stand/libsa/softraid.c567
-rw-r--r--sys/arch/amd64/stand/libsa/softraid.h34
10 files changed, 661 insertions, 596 deletions
diff --git a/sys/arch/amd64/stand/boot/Makefile b/sys/arch/amd64/stand/boot/Makefile
index ff03f477b6a..2705ea74217 100644
--- a/sys/arch/amd64/stand/boot/Makefile
+++ b/sys/arch/amd64/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.16 2012/10/13 14:10:35 jsing Exp $
+# $OpenBSD: Makefile,v 1.17 2012/10/27 15:43:42 jsing Exp $
.include "${.CURDIR}/../Makefile.inc"
@@ -9,6 +9,10 @@ MLINKS?=boot.8 boot.conf.5
S =${.CURDIR}/../../../..
SADIR= ${.CURDIR}/..
+.if empty(CFLAGS:M-DFDBOOT)
+SOFTRAID=yes
+.endif
+
PROG?= boot
SRCS= srt0.S conf.c
LD?= ld
@@ -21,6 +25,9 @@ LDFLAGS+=-melf_i386 -L/usr/libdata
SRCS+= machdep.c dev_i386.c exec_i386.c cmd_i386.c
SRCS+= gidt.S alloca.S biosdev.c bioscons.c gateA20.c \
memprobe.c diskprobe.c time.c ## biosprobe.c
+.if defined(SOFTRAID)
+SRCS+= softraid.c
+.endif
.PATH: ${S}/stand/boot
SRCS+= boot.c cmd.c vars.c bootarg.c
@@ -33,8 +40,8 @@ SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c lseek.c \
open.c read.c stat.c write.c cread.c readdir.c cons.c loadfile.c \
elf32.c elf64.c
SRCS+= ufs.c
-.if defined(BOOT_CRYPTO)
-SRCS+= aes_xts.c explicit_bzero.c hmac_sha1.c pbkdf2.c rijndael.c sha1.c
+.if defined(SOFTRAID)
+SRCS+= aes_xts.c explicit_bzero.c hmac_sha1.c pbkdf2.c rijndael.c sha1.c
.endif
.PATH: ${S}/lib/libkern/arch/amd64 ${S}/lib/libkern
@@ -60,8 +67,8 @@ NOPROG=
.include <bsd.prog.mk>
-.if defined(BOOT_CRYPTO)
-CPPFLAGS+=-DBOOT_CRYPTO
+.if defined(SOFTRAID)
+CPPFLAGS+=-DSOFTRAID
.endif
CPPFLAGS+=-DBOOTMAGIC=$(BOOTMAGIC) ${DEBUGFLAGS} -DLINKADDR=${LINKADDR}
CPPFLAGS+=-DSLOW -DSMALL -DNOBYFOUR -DNO_GZIP -DDYNAMIC_CRC_TABLE
diff --git a/sys/arch/amd64/stand/boot/conf.c b/sys/arch/amd64/stand/boot/conf.c
index 91c6fb32225..4587d194a94 100644
--- a/sys/arch/amd64/stand/boot/conf.c
+++ b/sys/arch/amd64/stand/boot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.25 2012/10/12 15:00:33 jsing Exp $ */
+/* $OpenBSD: conf.c,v 1.26 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -42,7 +42,7 @@
#include <biosdev.h>
#include <dev/cons.h>
-const char version[] = "3.22";
+const char version[] = "3.23";
int debug = 1;
diff --git a/sys/arch/amd64/stand/libsa/biosdev.c b/sys/arch/amd64/stand/libsa/biosdev.c
index 4cdf9f970b2..d15cb0bafef 100644
--- a/sys/arch/amd64/stand/libsa/biosdev.c
+++ b/sys/arch/amd64/stand/libsa/biosdev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: biosdev.c,v 1.18 2012/10/09 13:55:36 jsing Exp $ */
+/* $OpenBSD: biosdev.c,v 1.19 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1996 Michael Shalayeff
@@ -31,8 +31,6 @@
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/disklabel.h>
-#include <dev/biovar.h>
-#include <dev/softraidvar.h>
#include <isofs/cd9660/iso.h>
#include <lib/libsa/saerrno.h>
#include <machine/tss.h>
@@ -42,11 +40,9 @@
#include "disk.h"
#include "libsa.h"
-#ifdef BOOT_CRYPTO
-#include <lib/libsa/aes_xts.h>
-#include <lib/libsa/hmac_sha1.h>
-#include <lib/libsa/pbkdf2.h>
-#include <lib/libsa/rijndael.h>
+#ifdef SOFTRAID
+#include <dev/softraidvar.h>
+#include "softraid.h"
#endif
static const char *biosdisk_err(u_int);
@@ -57,14 +53,6 @@ static int EDD_rw (int, int, u_int32_t, u_int32_t, void *);
static u_int findopenbsd(bios_diskinfo_t *, const char **);
-static const char *sr_getdisklabel(struct sr_boot_volume *, struct disklabel *);
-static int sr_strategy(struct sr_boot_volume *, int, daddr32_t, size_t,
- void *, size_t *);
-
-#ifdef BOOT_CRYPTO
-static int sr_crypto_decrypt_keys(struct sr_boot_volume *);
-#endif
-
extern int debug;
int bios_bootdev;
int bios_cddev = -1; /* Set by srt0 if coming from CD */
@@ -467,7 +455,9 @@ bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label)
int
biosopen(struct open_file *f, ...)
{
+#ifdef SOFTRAID
struct sr_boot_volume *bv;
+#endif
register char *cp, **file;
dev_t maj, unit, part;
struct diskinfo *dip;
@@ -520,6 +510,7 @@ biosopen(struct open_file *f, ...)
else
f->f_flags |= F_RAW;
+#ifdef SOFTRAID
/* Intercept softraid disks. */
if (strncmp("sr", dev, 2) == 0) {
@@ -532,10 +523,8 @@ biosopen(struct open_file *f, ...)
return EADAPT;
}
-#ifdef BOOT_CRYPTO
if (bv->sbv_level == 'C' && bv->sbv_keys == NULL)
sr_crypto_decrypt_keys(bv);
-#endif
if (bv->sbv_diskinfo == NULL) {
dip = alloc(sizeof(struct diskinfo));
@@ -562,6 +551,7 @@ biosopen(struct open_file *f, ...)
return 0;
}
+#endif
for (maj = 0; maj < nbdevs &&
strncmp(dev, bdevs[maj], devlen); maj++);
@@ -721,9 +711,11 @@ biosstrategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
u_int8_t error = 0;
size_t nsect;
+#ifdef SOFTRAID
/* Intercept strategy for softraid volumes. */
if (dip->sr_vol)
return sr_strategy(dip->sr_vol, rw, blk, size, buf, rsize);
+#endif
nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE;
blk += dip->disklabel.d_partitions[B_PARTITION(dip->bsddev)].p_offset;
@@ -761,302 +753,3 @@ biosioctl(struct open_file *f, u_long cmd, void *data)
{
return 0;
}
-
-static 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 sr_boot_chunk *bc;
-#ifdef BOOT_CRYPTO
- struct aes_xts_ctx ctx;
- size_t i, j, nsect;
- daddr64_t blkno;
- u_char iv[8];
- u_char *bp;
- int err;
-#endif
-
- /* We only support read-only softraid. */
- if (rw != F_READ)
- return EPERM;
-
- /* Partition offset within softraid volume. */
- sr_dip = (struct diskinfo *)bv->sbv_diskinfo;
- blk += sr_dip->disklabel.d_partitions[bv->sbv_part - 'a'].p_offset;
-
- 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;
- dip->bsddev = bc->sbc_mm;
- blk += bv->sbv_data_offset;
-
- /* XXX - If I/O failed we should try another chunk... */
- return biosstrategy(dip, rw, blk, size, buf, rsize);
-
-#ifdef BOOT_CRYPTO
- } 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;
- dip->bsddev = bc->sbc_mm;
-
- /* 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 = biosstrategy(dip, rw, bv->sbv_data_offset + blkno,
- DEV_BSIZE, bp, NULL);
- if (err != 0)
- 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);
- }
- if (rsize != NULL)
- *rsize = nsect * DEV_BSIZE;
-
- return err;
-#endif
- } else
- return ENOTSUP;
-}
-
-static const char *
-sr_getdisklabel(struct sr_boot_volume *bv, struct disklabel *label)
-{
- struct dos_partition *dp;
- struct dos_mbr mbr;
- u_int start = 0;
- char *buf;
- int i;
-
- /* Check for MBR to determine partition offset. */
- bzero(&mbr, sizeof(mbr));
- sr_strategy(bv, F_READ, DOSBBSECTOR, sizeof(struct dos_mbr),
- &mbr, NULL);
- if (mbr.dmbr_sign == DOSMBR_SIGNATURE) {
-
- /* Search for OpenBSD partition */
- for (i = 0; i < NDOSPART; i++) {
- dp = &mbr.dmbr_parts[i];
- if (!dp->dp_size)
- continue;
- if (dp->dp_typ == DOSPTYP_OPENBSD) {
- if (dp->dp_start > (dp->dp_start + DOSBBSECTOR))
- continue;
- start = dp->dp_start + DOSBBSECTOR;
- }
- }
- }
-
- start += LABELSECTOR;
-
- /* Read the disklabel. */
- buf = alloca(DEV_BSIZE);
- sr_strategy(bv, F_READ, start, sizeof(struct disklabel), buf, NULL);
-
-#if BIOS_DEBUG
- printf("sr_getdisklabel: magic %lx\n",
- ((struct disklabel *)buf)->d_magic);
- for (i = 0; i < MAXPARTITIONS; i++)
- printf("part %c: type = %d, size = %d, offset = %d\n", 'a' + i,
- (int)((struct disklabel *)buf)->d_partitions[i].p_fstype,
- (int)((struct disklabel *)buf)->d_partitions[i].p_size,
- (int)((struct disklabel *)buf)->d_partitions[i].p_offset);
-#endif
-
- /* Fill in disklabel */
- return (getdisklabel(buf, label));
-}
-
-#ifdef BOOT_CRYPTO
-
-#define RIJNDAEL128_BLOCK_LEN 16
-#define PASSPHRASE_LENGTH 1024
-
-#define SR_CRYPTO_KEYBLOCK_BYTES SR_CRYPTO_MAXKEYS * SR_CRYPTO_KEYBYTES
-
-#ifdef BIOS_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;
-
- 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, 0);
- bv->sbv_keys = NULL;
- }
- if (bv->sbv_maskkey != NULL) {
- explicit_bzero(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES);
- free(bv->sbv_maskkey, 0);
- bv->sbv_maskkey = NULL;
- }
- }
-}
-
-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_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;
- }
-
- printf("Passphrase: ");
- i = 0;
- for (i = 0; i < PASSPHRASE_LENGTH - 1; i++) {
- c = cngetc();
- if (c == '\r' || c == '\n')
- break;
- passphrase[i] = (c & 0xff);
- }
- passphrase[i] = 0;
- printf("\n");
-
-#ifdef BIOS_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\n");
- goto done;
- }
-
- /* Keys 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, 0);
- }
-
- return (rv);
-}
-#endif
diff --git a/sys/arch/amd64/stand/libsa/dev_i386.c b/sys/arch/amd64/stand/libsa/dev_i386.c
index de47768763f..342454a25d3 100644
--- a/sys/arch/amd64/stand/libsa/dev_i386.c
+++ b/sys/arch/amd64/stand/libsa/dev_i386.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev_i386.c,v 1.11 2012/10/08 14:15:23 jsing Exp $ */
+/* $OpenBSD: dev_i386.c,v 1.12 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1996-1999 Michael Shalayeff
@@ -32,10 +32,15 @@
#include <dev/cons.h>
#include <dev/biovar.h>
#include <dev/softraidvar.h>
+
#include "libsa.h"
#include "biosdev.h"
#include "disk.h"
+#ifdef SOFTRAID
+#include "softraid.h"
+#endif
+
extern int debug;
/* XXX use slot for 'rd' for 'hd' pseudo-device */
@@ -94,9 +99,11 @@ devopen(struct open_file *f, const char *fname, char **file)
void
devboot(dev_t bootdev, char *p)
{
+#ifdef SOFTRAID
struct sr_boot_volume *bv;
struct sr_boot_chunk *bc;
struct diskinfo *dip = NULL;
+#endif
int sr_boot_vol = -1;
int part_type = FS_UNUSED;
@@ -109,6 +116,7 @@ devboot(dev_t bootdev, char *p)
*p++ = 'r';
#endif
+#ifdef SOFTRAID
/*
* Determine the partition type for the 'a' partition of the
* boot device.
@@ -130,6 +138,7 @@ devboot(dev_t bootdev, char *p)
if (sr_boot_vol != -1)
break;
}
+#endif
if (sr_boot_vol != -1 && part_type != FS_BSDFFS) {
*p++ = 's';
diff --git a/sys/arch/amd64/stand/libsa/disk.h b/sys/arch/amd64/stand/libsa/disk.h
index adbe02d0285..8d4cd1eb40a 100644
--- a/sys/arch/amd64/stand/libsa/disk.h
+++ b/sys/arch/amd64/stand/libsa/disk.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: disk.h,v 1.3 2012/10/08 14:15:23 jsing Exp $ */
+/* $OpenBSD: disk.h,v 1.4 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
@@ -27,8 +27,8 @@
*
*/
-#ifndef _DISKPROBE_H
-#define _DISKPROBE_H
+#ifndef _DISK_H
+#define _DISK_H
#include <sys/queue.h>
@@ -50,9 +50,6 @@ extern struct diskinfo *bootdev_dip;
/* List of probed disks. */
extern struct disklist_lh disklist;
-/* List of softraid volumes. */
-extern struct sr_boot_volume_head sr_volumes;
-
void dump_diskinfo(void);
-#endif /* _DISKPROBE_H */
+#endif /* _DISK_H */
diff --git a/sys/arch/amd64/stand/libsa/diskprobe.c b/sys/arch/amd64/stand/libsa/diskprobe.c
index fabd395f7de..6b0af6f103b 100644
--- a/sys/arch/amd64/stand/libsa/diskprobe.c
+++ b/sys/arch/amd64/stand/libsa/diskprobe.c
@@ -1,8 +1,7 @@
-/* $OpenBSD: diskprobe.c,v 1.10 2012/10/09 13:55:36 jsing Exp $ */
+/* $OpenBSD: diskprobe.c,v 1.11 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
- * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,15 +34,19 @@
#include <sys/queue.h>
#include <sys/reboot.h>
#include <sys/disklabel.h>
-#include <dev/biovar.h>
-#include <dev/softraidvar.h>
-#include <stand/boot/bootarg.h>
-#include <machine/biosvar.h>
+
#include <lib/libz/zlib.h>
+#include <machine/biosvar.h>
+#include <stand/boot/bootarg.h>
+
#include "disk.h"
#include "biosdev.h"
#include "libsa.h"
+#ifdef SOFTRAID
+#include "softraid.h"
+#endif
+
#define MAX_CKSUMLEN MAXBSIZE / DEV_BSIZE /* Max # of blks to cksum */
/* Local Prototypes */
@@ -52,9 +55,6 @@ static int disksum(int);
/* List of disk devices we found/probed */
struct disklist_lh disklist;
-/* List of softraid volumes. */
-struct sr_boot_volume_head sr_volumes;
-
/* Pointer to boot device */
struct diskinfo *bootdev_dip;
@@ -165,246 +165,6 @@ hardprobe(void)
}
}
-#ifdef BOOT_CRYPTO
-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 BIOS_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 +
- omh->som_length);
- 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);
- }
-}
-#endif
-
-static 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;
- int i, error, volno;
- dev_t bsd_dev;
- daddr_t off;
-
- /* Probe for softraid volumes. */
- SLIST_INIT(&sr_volumes);
-
- md = alloc(SR_META_SIZE * 512);
-
- TAILQ_FOREACH(dip, &disklist, list) {
-
- /* Only check hard disks, skip those with I/O errors. */
- if ((dip->bios_info.bios_number & 0x80) == 0 ||
- (dip->bios_info.flags & BDI_INVALID))
- continue;
-
- /* Make sure disklabel has been read. */
- if ((dip->bios_info.flags & (BDI_BADLABEL|BDI_GOODLABEL)) == 0)
- continue;
-
- 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);
- off = DL_GETPOFFSET(pp) + SR_META_OFFSET;
- error = biosd_io(F_READ, &dip->bios_info, off,
- SR_META_SIZE, md);
- if (error)
- continue;
-
- /* Is this valid softraid metadata? */
- if (md->ssdi.ssd_magic != SR_MAGIC)
- continue;
-
- /* XXX - validate checksum. */
-
- /* 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 = dip->bios_info.bios_number;
- bc->sbc_part = 'a' + i;
-
- bsd_dev = dip->bios_info.bsd_dev;
- 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;
-
- /* Handle key disks separately... later. */
- if (md->ssdi.ssd_level == SR_KEYDISK_LEVEL)
- continue;
-
- 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));
- bv->sbv_diskinfo = NULL;
- bv->sbv_keys = NULL;
- 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);
-
-#ifdef BOOT_CRYPTO
- /* Load optional metadata for this volume. */
- srprobe_meta_opt_load(md, &bv->sbv_meta_opt);
-#endif
-
- /* 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++;
- }
- }
-
- /*
- * 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", bv->sbv_unit,
- bv->sbv_flags & BIOC_SCBOOTABLE ? "*" : "");
- }
-
- if (md)
- free(md, 0);
-}
-
/* Probe for all BIOS supported disks */
u_int32_t bios_cksumlen;
@@ -428,7 +188,9 @@ diskprobe(void)
#endif
hardprobe();
+#ifdef SOFTRAID
srprobe();
+#endif
/* Checksumming of hard disks */
for (i = 0; disksum(i++) && i < MAX_CKSUMLEN; )
diff --git a/sys/arch/amd64/stand/libsa/exec_i386.c b/sys/arch/amd64/stand/libsa/exec_i386.c
index 71f2c573399..cdce6ac2cd4 100644
--- a/sys/arch/amd64/stand/libsa/exec_i386.c
+++ b/sys/arch/amd64/stand/libsa/exec_i386.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_i386.c,v 1.10 2012/10/09 13:55:36 jsing Exp $ */
+/* $OpenBSD: exec_i386.c,v 1.11 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1997-1998 Michael Shalayeff
@@ -29,16 +29,18 @@
*/
#include <sys/param.h>
+#include <sys/disklabel.h>
#include <dev/cons.h>
-#include <stand/boot/bootarg.h>
+#include <lib/libsa/loadfile.h>
#include <machine/biosvar.h>
-#include <sys/disklabel.h>
+#include <stand/boot/bootarg.h>
+
#include "disk.h"
#include "libsa.h"
-#include <lib/libsa/loadfile.h>
-#ifdef BOOT_CRYPTO
+#ifdef SOFTRAID
#include <dev/softraidvar.h>
+#include "softraid.h"
#endif
typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
@@ -46,10 +48,6 @@ typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
char *bootmac = NULL;
-#ifdef BOOT_CRYPTO
-void sr_clear_keys();
-#endif
-
void
run_loadfile(u_long *marks, int howto)
{
@@ -66,7 +64,7 @@ run_loadfile(u_long *marks, int howto)
bios_ddb_t ddb;
extern int db_console;
bios_bootduid_t bootduid;
-#ifdef BOOT_CRYPTO
+#ifdef SOFTRAID
bios_bootsr_t bootsr;
struct sr_boot_volume *bv;
#endif
@@ -91,7 +89,7 @@ run_loadfile(u_long *marks, int howto)
bcopy(bootdev_dip->disklabel.d_uid, &bootduid.duid, sizeof(bootduid));
addbootarg(BOOTARG_BOOTDUID, sizeof(bootduid), &bootduid);
-#ifdef BOOT_CRYPTO
+#ifdef SOFTRAID
if (bootdev_dip->sr_vol != NULL) {
bv = bootdev_dip->sr_vol;
bzero(&bootsr, sizeof(bootsr));
@@ -102,9 +100,7 @@ run_loadfile(u_long *marks, int howto)
addbootarg(BOOTARG_BOOTSR, sizeof(bios_bootsr_t), &bootsr);
explicit_bzero(&bootsr, sizeof(bootsr));
}
-#endif
-#ifdef BOOT_CRYPTO
sr_clear_keys();
#endif
diff --git a/sys/arch/amd64/stand/libsa/gidt.S b/sys/arch/amd64/stand/libsa/gidt.S
index 2d56d1fb1e2..6a33ba94651 100644
--- a/sys/arch/amd64/stand/libsa/gidt.S
+++ b/sys/arch/amd64/stand/libsa/gidt.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: gidt.S,v 1.10 2012/10/09 13:57:41 jsing Exp $ */
+/* $OpenBSD: gidt.S,v 1.11 2012/10/27 15:43:42 jsing Exp $ */
/*
* Copyright (c) 1997 Michael Shalayeff
@@ -123,7 +123,7 @@
.globl _C_LABEL(_rtt)
ENTRY(_rtt)
-#ifdef BOOT_CRYPTO
+#ifdef SOFTRAID
call _C_LABEL(sr_clear_keys)
#endif
#ifdef GIDT_DEBUG
diff --git a/sys/arch/amd64/stand/libsa/softraid.c b/sys/arch/amd64/stand/libsa/softraid.c
new file mode 100644
index 00000000000..1fb19b8ebb9
--- /dev/null
+++ b/sys/arch/amd64/stand/libsa/softraid.c
@@ -0,0 +1,567 @@
+/* $OpenBSD: softraid.c,v 1.1 2012/10/27 15:43:42 jsing 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/aes_xts.h>
+#include <lib/libsa/hmac_sha1.h>
+#include <lib/libsa/pbkdf2.h>
+#include <lib/libsa/rijndael.h>
+
+#include "libsa.h"
+#include "biosdev.h"
+#include "disk.h"
+#include "softraid.h"
+
+/* List of softraid volumes. */
+struct sr_boot_volume_head sr_volumes;
+
+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 BIOS_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 +
+ omh->som_length);
+ 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(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;
+ int i, error, volno;
+ dev_t bsd_dev;
+ daddr_t off;
+
+ /* Probe for softraid volumes. */
+ SLIST_INIT(&sr_volumes);
+
+ md = alloc(SR_META_SIZE * 512);
+
+ TAILQ_FOREACH(dip, &disklist, list) {
+
+ /* Only check hard disks, skip those with I/O errors. */
+ if ((dip->bios_info.bios_number & 0x80) == 0 ||
+ (dip->bios_info.flags & BDI_INVALID))
+ continue;
+
+ /* Make sure disklabel has been read. */
+ if ((dip->bios_info.flags & (BDI_BADLABEL|BDI_GOODLABEL)) == 0)
+ continue;
+
+ 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);
+ off = DL_GETPOFFSET(pp) + SR_META_OFFSET;
+ error = biosd_io(F_READ, &dip->bios_info, off,
+ SR_META_SIZE, md);
+ if (error)
+ continue;
+
+ /* Is this valid softraid metadata? */
+ if (md->ssdi.ssd_magic != SR_MAGIC)
+ continue;
+
+ /* XXX - validate checksum. */
+
+ /* 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 = dip->bios_info.bios_number;
+ bc->sbc_part = 'a' + i;
+
+ bsd_dev = dip->bios_info.bsd_dev;
+ 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;
+
+ /* Handle key disks separately... later. */
+ if (md->ssdi.ssd_level == SR_KEYDISK_LEVEL)
+ continue;
+
+ 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));
+ bv->sbv_diskinfo = NULL;
+ bv->sbv_keys = NULL;
+ 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++;
+ }
+ }
+
+ /*
+ * 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", bv->sbv_unit,
+ bv->sbv_flags & BIOC_SCBOOTABLE ? "*" : "");
+ }
+
+ if (md)
+ free(md, 0);
+}
+
+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 sr_boot_chunk *bc;
+ struct aes_xts_ctx ctx;
+ size_t i, j, nsect;
+ daddr64_t blkno;
+ u_char iv[8];
+ u_char *bp;
+ int err;
+
+ /* We only support read-only softraid. */
+ if (rw != F_READ)
+ return EPERM;
+
+ /* Partition offset within softraid volume. */
+ sr_dip = (struct diskinfo *)bv->sbv_diskinfo;
+ blk += sr_dip->disklabel.d_partitions[bv->sbv_part - 'a'].p_offset;
+
+ 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;
+ dip->bsddev = bc->sbc_mm;
+ blk += bv->sbv_data_offset;
+
+ /* XXX - If I/O failed we should try another chunk... */
+ return biosstrategy(dip, rw, blk, size, buf, rsize);
+
+ } 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;
+ dip->bsddev = bc->sbc_mm;
+
+ /* 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 = biosstrategy(dip, rw, bv->sbv_data_offset + blkno,
+ DEV_BSIZE, bp, NULL);
+ if (err != 0)
+ 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);
+ }
+ if (rsize != NULL)
+ *rsize = nsect * DEV_BSIZE;
+
+ return err;
+
+ } else
+ return ENOTSUP;
+}
+
+const char *
+sr_getdisklabel(struct sr_boot_volume *bv, struct disklabel *label)
+{
+ struct dos_partition *dp;
+ struct dos_mbr mbr;
+ u_int start = 0;
+ char *buf;
+ int i;
+
+ /* Check for MBR to determine partition offset. */
+ bzero(&mbr, sizeof(mbr));
+ sr_strategy(bv, F_READ, DOSBBSECTOR, sizeof(mbr), &mbr, NULL);
+ if (mbr.dmbr_sign == DOSMBR_SIGNATURE) {
+
+ /* Search for OpenBSD partition */
+ for (i = 0; i < NDOSPART; i++) {
+ dp = &mbr.dmbr_parts[i];
+ if (!dp->dp_size)
+ continue;
+ if (dp->dp_typ == DOSPTYP_OPENBSD) {
+ if (dp->dp_start > (dp->dp_start + DOSBBSECTOR))
+ continue;
+ start = dp->dp_start + DOSBBSECTOR;
+ }
+ }
+ }
+
+ start += LABELSECTOR;
+
+ /* Read the disklabel. */
+ buf = alloca(DEV_BSIZE);
+ sr_strategy(bv, F_READ, start, sizeof(struct disklabel), buf, NULL);
+
+#if BIOS_DEBUG
+ printf("sr_getdisklabel: magic %lx\n",
+ ((struct disklabel *)buf)->d_magic);
+ for (i = 0; i < MAXPARTITIONS; i++)
+ printf("part %c: type = %d, size = %d, offset = %d\n", 'a' + i,
+ (int)((struct disklabel *)buf)->d_partitions[i].p_fstype,
+ (int)((struct disklabel *)buf)->d_partitions[i].p_size,
+ (int)((struct disklabel *)buf)->d_partitions[i].p_offset);
+#endif
+
+ /* Fill in disklabel */
+ return (getdisklabel(buf, label));
+}
+
+
+#define RIJNDAEL128_BLOCK_LEN 16
+#define PASSPHRASE_LENGTH 1024
+
+#define SR_CRYPTO_KEYBLOCK_BYTES SR_CRYPTO_MAXKEYS * SR_CRYPTO_KEYBYTES
+
+#ifdef BIOS_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;
+
+ 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, 0);
+ bv->sbv_keys = NULL;
+ }
+ if (bv->sbv_maskkey != NULL) {
+ explicit_bzero(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES);
+ free(bv->sbv_maskkey, 0);
+ bv->sbv_maskkey = NULL;
+ }
+ }
+}
+
+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_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;
+ }
+
+ printf("Passphrase: ");
+ i = 0;
+ for (i = 0; i < PASSPHRASE_LENGTH - 1; i++) {
+ c = cngetc();
+ if (c == '\r' || c == '\n')
+ break;
+ passphrase[i] = (c & 0xff);
+ }
+ passphrase[i] = 0;
+ printf("\n");
+
+#ifdef BIOS_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\n");
+ goto done;
+ }
+
+ /* Keys 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, 0);
+ }
+
+ return (rv);
+}
diff --git a/sys/arch/amd64/stand/libsa/softraid.h b/sys/arch/amd64/stand/libsa/softraid.h
new file mode 100644
index 00000000000..603e91493e2
--- /dev/null
+++ b/sys/arch/amd64/stand/libsa/softraid.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: softraid.h,v 1.1 2012/10/27 15:43:42 jsing 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 */