diff options
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/stand/boot/Makefile | 17 | ||||
-rw-r--r-- | sys/arch/amd64/stand/boot/conf.c | 4 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/biosdev.c | 327 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/dev_i386.c | 11 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/disk.h | 11 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/diskprobe.c | 260 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/exec_i386.c | 22 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/gidt.S | 4 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/softraid.c | 567 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/softraid.h | 34 |
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 */ |