PR/58212: Malte Dehling: Add zfs verification method

This commit is contained in:
christos 2024-05-12 18:02:16 +00:00
parent 91e71a2ef4
commit c162bcc0ed
5 changed files with 157 additions and 20 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.22 2022/08/12 10:49:17 riastradh Exp $
# $NetBSD: Makefile,v 1.23 2024/05/12 18:02:16 christos Exp $
RUMPPRG=cgdconfig
MAN= cgdconfig.8
@ -29,4 +29,19 @@ ARGON2_NO_THREADS=1
.include "${NETBSDSRCDIR}/external/apache2/argon2/lib/libargon2/Makefile.inc"
.endif
.if ${MKZFS} != "no"
CPPFLAGS+= -DHAVE_ZFS
OSNET=${NETBSDSRCDIR}/external/cddl/osnet
CPPFLAGS.cgdconfig.c+= -I${OSNET}/include
CPPFLAGS.cgdconfig.c+= -I${OSNET}/sys
CPPFLAGS.cgdconfig.c+= -I${OSNET}/dist/head
CPPFLAGS.cgdconfig.c+= -I${OSNET}/dist/lib/libzpool/common
CPPFLAGS.cgdconfig.c+= -I${OSNET}/dist/uts/common
CPPFLAGS.cgdconfig.c+= -I${OSNET}/dist/uts/common/fs/zfs
COPTS.cgdconfig.c+= -Wno-unknown-pragmas
COPTS.cgdconfig.c+= -Wno-strict-prototypes
.endif
.include <bsd.prog.mk>

View File

@ -1,4 +1,4 @@
.\" $NetBSD: cgdconfig.8,v 1.57 2022/08/12 10:49:47 riastradh Exp $
.\" $NetBSD: cgdconfig.8,v 1.58 2024/05/12 18:02:16 christos Exp $
.\"
.\" Copyright (c) 2002, The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd November 4, 2021
.Dd May 12, 2024
.Dt CGDCONFIG 8
.Os
.Sh NAME
@ -270,6 +270,8 @@ scan for a valid Master Boot Record.
scan for a valid GUID partition table.
.It ffs
scan for a valid FFS file system.
.It zfs
scan for a valid ZFS vdev label (if compiled with MKZFS).
.It re-enter
prompt for passphrase twice, and ensure entered passphrases are
identical.

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgdconfig.c,v 1.62 2024/04/29 00:28:18 riastradh Exp $ */
/* $NetBSD: cgdconfig.c,v 1.63 2024/05/12 18:02:16 christos Exp $ */
/*-
* Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 2002, 2003\
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: cgdconfig.c,v 1.62 2024/04/29 00:28:18 riastradh Exp $");
__RCSID("$NetBSD: cgdconfig.c,v 1.63 2024/05/12 18:02:16 christos Exp $");
#endif
#ifdef HAVE_ARGON2
@ -73,6 +73,11 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.62 2024/04/29 00:28:18 riastradh Exp $");
#include <ufs/ffs/fs.h>
#ifdef HAVE_ZFS
#include <sys/vdev_impl.h>
#include <sha2.h>
#endif
#include "params.h"
#include "pkcs5_pbkdf2.h"
#include "utils.h"
@ -98,11 +103,11 @@ enum action {
/* if nflag is set, do not configure/unconfigure the cgd's */
int nflag = 0;
static int nflag = 0;
/* if Sflag is set, generate shared keys */
int Sflag = 0;
static int Sflag = 0;
/* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */
@ -110,7 +115,7 @@ int Sflag = 0;
#define PFLAG_GETPASS_ECHO 0x02
#define PFLAG_GETPASS_MASK 0x03
#define PFLAG_STDIN 0x04
int pflag = PFLAG_GETPASS;
static int pflag = PFLAG_GETPASS;
/*
* When configuring all cgds, save a cache of shared keys for key
@ -127,7 +132,7 @@ struct sharedkey {
SLIST_ENTRY(sharedkey) used;
int verified;
};
LIST_HEAD(, sharedkey) sharedkeys;
static LIST_HEAD(, sharedkey) sharedkeys;
SLIST_HEAD(sharedkeyhits, sharedkey);
static int configure(int, char **, struct params *, int);
@ -170,11 +175,14 @@ static int verify_ffs(int);
static int verify_reenter(struct params *);
static int verify_mbr(int);
static int verify_gpt(int);
#ifdef HAVE_ZFS
static int verify_zfs(int);
#endif
__dead static void usage(void);
/* Verbose Framework */
unsigned verbose = 0;
static unsigned verbose = 0;
#define VERBOSE(x,y) if (verbose >= x) y
#define VPRINTF(x,y) if (verbose >= x) (void)printf y
@ -636,12 +644,12 @@ getkey_argon2id(const char *target, struct keygen *kg, size_t keylen)
char *passp;
char buf[1024];
uint8_t raw[256];
int err;
int error;
snprintf(buf, sizeof(buf), "%s's passphrase%s:", target,
pflag & PFLAG_GETPASS_ECHO ? " (echo)" : "");
passp = maybe_getpass(buf);
if ((err = argon2_hash(kg->kg_iterations, kg->kg_memory,
if ((error = argon2_hash(kg->kg_iterations, kg->kg_memory,
kg->kg_parallelism,
passp, strlen(passp),
bits_getbuf(kg->kg_salt),
@ -649,7 +657,7 @@ getkey_argon2id(const char *target, struct keygen *kg, size_t keylen)
raw, sizeof(raw),
NULL, 0,
Argon2_id, kg->kg_version)) != ARGON2_OK) {
warnx("failed to generate Argon2id key, error code %d", err);
warnx("failed to generate Argon2id key, error code %d", error);
return NULL;
}
@ -1024,6 +1032,10 @@ verify(struct params *p, int fd)
return verify_mbr(fd);
case VERIFY_GPT:
return verify_gpt(fd);
#ifdef HAVE_ZFS
case VERIFY_ZFS:
return verify_zfs(fd);
#endif
default:
warnx("unimplemented verification method");
return -1;
@ -1161,7 +1173,6 @@ verify_gpt(int fd)
return -1;
}
ret = 1;
for (blksize = DEV_BSIZE;
(off = (blksize * GPT_HDR_BLKNO)) <= SCANSIZE - sizeof(hdr);
blksize <<= 1) {
@ -1173,15 +1184,114 @@ verify_gpt(int fd)
hdr.hdr_crc_self = 0;
if (crc32(&hdr, sizeof(hdr))) {
ret = 0;
break;
return 0;
}
}
}
return ret;
return 1;
}
#ifdef HAVE_ZFS
#define ZIO_CHECKSUM_BE(zcp) \
{ \
(zcp)->zc_word[0] = BE_64((zcp)->zc_word[0]); \
(zcp)->zc_word[1] = BE_64((zcp)->zc_word[1]); \
(zcp)->zc_word[2] = BE_64((zcp)->zc_word[2]); \
(zcp)->zc_word[3] = BE_64((zcp)->zc_word[3]); \
}
static int
verify_zfs(int fd)
{
off_t vdev_size;
int rv = 1;
if (prog_ioctl(fd, DIOCGMEDIASIZE, &vdev_size) == -1) {
warn("%s: ioctl", __func__);
return rv;
}
vdev_phys_t *vdev_phys = emalloc(sizeof(*vdev_phys));
for (size_t i = 0; i < VDEV_LABELS; i++) {
off_t vdev_phys_off = (i < VDEV_LABELS / 2 ?
i * sizeof(vdev_label_t) :
vdev_size - (VDEV_LABELS - i) * sizeof(vdev_label_t))
+ offsetof(vdev_label_t, vl_vdev_phys);
ssize_t ret = prog_pread(fd, vdev_phys, sizeof(*vdev_phys),
vdev_phys_off);
if (ret == -1) {
warn("%s: read failed", __func__);
goto out;
}
if ((size_t)ret < sizeof(*vdev_phys)) {
warnx("%s: incomplete block", __func__);
goto out;
}
bool byteswap;
switch (vdev_phys->vp_zbt.zec_magic) {
case BSWAP_64(ZEC_MAGIC):
byteswap = true;
break;
case ZEC_MAGIC:
byteswap = false;
break;
default:
goto out;
}
zio_cksum_t cksum_found = vdev_phys->vp_zbt.zec_cksum;
if (byteswap) {
ZIO_CHECKSUM_BSWAP(&cksum_found);
}
ZIO_SET_CHECKSUM(&vdev_phys->vp_zbt.zec_cksum,
vdev_phys_off, 0, 0, 0);
if (byteswap) {
ZIO_CHECKSUM_BSWAP(&vdev_phys->vp_zbt.zec_cksum);
}
SHA256_CTX ctx;
zio_cksum_t cksum_real;
SHA256Init(&ctx);
SHA256Update(&ctx, (uint8_t *)vdev_phys, sizeof *vdev_phys);
SHA256Final(&cksum_real, &ctx);
/*
* For historical reasons the on-disk sha256 checksums are
* always in big endian format.
* (see cddl/osnet/dist/uts/common/fs/zfs/sha256.c)
*/
ZIO_CHECKSUM_BE(&cksum_real);
if (!ZIO_CHECKSUM_EQUAL(cksum_found, cksum_real)) {
warnx("%s: checksum mismatch on vdev label %zu",
__func__, i);
warnx("%s: found %#jx, %#jx, %#jx, %#jx", __func__,
(uintmax_t)cksum_found.zc_word[0],
(uintmax_t)cksum_found.zc_word[1],
(uintmax_t)cksum_found.zc_word[2],
(uintmax_t)cksum_found.zc_word[3]);
warnx("%s: expected %#jx, %#jx, %#jx, %#jx", __func__,
(uintmax_t)cksum_real.zc_word[0],
(uintmax_t)cksum_real.zc_word[1],
(uintmax_t)cksum_real.zc_word[2],
(uintmax_t)cksum_real.zc_word[3]);
goto out;
}
}
rv = 0;
out:
free(vdev_phys);
return rv;
}
#endif
static off_t sblock_try[] = SBLOCKSEARCH;
static int

View File

@ -1,4 +1,4 @@
/* $NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $ */
/* $NetBSD: params.c,v 1.35 2024/05/12 18:02:16 christos Exp $ */
/*-
* Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $");
__RCSID("$NetBSD: params.c,v 1.35 2024/05/12 18:02:16 christos Exp $");
#endif
#include <sys/types.h>
@ -287,6 +287,10 @@ params_verify_method(string_t *in)
p->verify_method = VERIFY_MBR;
if (!strcmp("gpt", vm))
p->verify_method = VERIFY_GPT;
#ifdef HAVE_ZFS
if (!strcmp("zfs", vm))
p->verify_method = VERIFY_ZFS;
#endif
string_free(in);
@ -1065,6 +1069,11 @@ params_fput(struct params *p, FILE *f)
case VERIFY_GPT:
print_kvpair_cstr(f, ts, "verify_method", "gpt");
break;
#ifdef HAVE_ZFS
case VERIFY_ZFS:
print_kvpair_cstr(f, ts, "verify_method", "zfs");
break;
#endif
default:
warnx("unsupported verify_method (%d)", p->verify_method);
return -1;

View File

@ -1,4 +1,4 @@
/* $NetBSD: params.h,v 1.14 2022/08/12 10:49:35 riastradh Exp $ */
/* $NetBSD: params.h,v 1.15 2024/05/12 18:02:16 christos Exp $ */
/*-
* Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@ -81,6 +81,7 @@ struct params {
#define VERIFY_REENTER 0x4
#define VERIFY_MBR 0x5
#define VERIFY_GPT 0x6
#define VERIFY_ZFS 0x7
/* shared key derivation methods */