Module Name: src
Committed By: riastradh
Date: Tue Aug 30 08:48:42 UTC 2022
Modified Files:
src/sbin/cgdconfig: cgdconfig.c
Log Message:
cgdconfig(8): Gracefully handle failed verification with shared keys.
The first time each key is verified, if verification fails, we chuck
the failed key and try again with passphrase re-entry.
But if a key has already been verified, and verification fails,
assume something is wrong with the disk and fail.
To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/sbin/cgdconfig/cgdconfig.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sbin/cgdconfig/cgdconfig.c
diff -u src/sbin/cgdconfig/cgdconfig.c:1.58 src/sbin/cgdconfig/cgdconfig.c:1.59
--- src/sbin/cgdconfig/cgdconfig.c:1.58 Fri Aug 12 10:49:47 2022
+++ src/sbin/cgdconfig/cgdconfig.c Tue Aug 30 08:48:41 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: cgdconfig.c,v 1.58 2022/08/12 10:49:47 riastradh Exp $ */
+/* $NetBSD: cgdconfig.c,v 1.59 2022/08/30 08:48:41 riastradh 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.58 2022/08/12 10:49:47 riastradh Exp $");
+__RCSID("$NetBSD: cgdconfig.c,v 1.59 2022/08/30 08:48:41 riastradh Exp $");
#endif
#ifdef HAVE_ARGON2
@@ -114,7 +114,9 @@ int pflag = PFLAG_GETPASS;
/*
* When configuring all cgds, save a cache of shared keys for key
- * derivation.
+ * derivation. If the _first_ verification with a shared key fails, we
+ * chuck it and start over; if _subsequent_ verifications fail, we
+ * assume the disk is wrong and give up on it immediately.
*/
struct sharedkey {
@@ -122,8 +124,11 @@ struct sharedkey {
string_t *id;
bits_t *key;
LIST_ENTRY(sharedkey) list;
+ SLIST_ENTRY(sharedkey) used;
+ int verified;
};
LIST_HEAD(, sharedkey) sharedkeys;
+SLIST_HEAD(sharedkeyhits, sharedkey);
static int configure(int, char **, struct params *, int);
static int configure_stdin(struct params *, int argc, char **);
@@ -146,7 +151,8 @@ static int do_printkey(int, char **);
static int configure_params(int, const char *, const char *,
struct params *);
static void eliminate_cores(void);
-static bits_t *getkey(const char *, struct keygen *, size_t);
+static bits_t *getkey(const char *, struct keygen *, size_t,
+ struct sharedkeyhits *);
static bits_t *getkey_storedkey(const char *, struct keygen *, size_t);
static bits_t *getkey_randomkey(const char *, struct keygen *, size_t, int);
#ifdef HAVE_ARGON2
@@ -429,7 +435,8 @@ getsubkey(int alg, bits_t *key, bits_t *
}
static bits_t *
-getkey(const char *dev, struct keygen *kg, size_t len0)
+getkey(const char *dev, struct keygen *kg, size_t len0,
+ struct sharedkeyhits *skh)
{
bits_t *ret = NULL;
bits_t *tmp;
@@ -502,9 +509,11 @@ getkey(const char *dev, struct keygen *k
sk->id = string_dup(kg->kg_sharedid);
sk->key = tmp;
LIST_INSERT_HEAD(&sharedkeys, sk, list);
+ sk->verified = 0;
}
derive: if (kg->kg_sharedid) {
+ assert(sk != NULL);
/*
* tmp holds the master key, owned by the
* struct sharedkey record; replace it by the
@@ -517,6 +526,8 @@ derive: if (kg->kg_sharedid) {
bits_free(ret);
return NULL;
}
+ if (skh)
+ SLIST_INSERT_HEAD(skh, sk, used);
}
if (ret)
ret = bits_xor_d(tmp, ret);
@@ -811,6 +822,12 @@ configure(int argc, char **argv, struct
}
for (;;) {
+ struct sharedkeyhits skh;
+ struct sharedkey *sk, *sk1;
+ int all_verified;
+
+ SLIST_INIT(&skh);
+
fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname));
if (fd == -1)
return -1;
@@ -818,7 +835,7 @@ configure(int argc, char **argv, struct
if (p->key)
bits_free(p->key);
- p->key = getkey(argv[1], p->keygen, p->keylen);
+ p->key = getkey(argv[1], p->keygen, p->keylen, &skh);
if (!p->key)
goto bail_err;
@@ -831,12 +848,33 @@ configure(int argc, char **argv, struct
(void)unconfigure_fd(fd);
goto bail_err;
}
- if (ret == 0) /* success */
+ if (ret == 0) { /* success */
+ SLIST_FOREACH(sk, &skh, used)
+ sk->verified = 1;
break;
+ }
(void)unconfigure_fd(fd);
(void)prog_close(fd);
+ /*
+ * If the shared keys were all verified already, assume
+ * something is wrong with the disk and give up. If
+ * not, flush the cache of the ones that have not been
+ * verified in case we can try again with passphrase
+ * re-entry.
+ */
+ all_verified = 1;
+ SLIST_FOREACH_SAFE(sk, &skh, used, sk1) {
+ all_verified &= sk->verified;
+ if (!sk->verified) {
+ LIST_REMOVE(sk, list);
+ free(sk);
+ }
+ }
+ if (all_verified)
+ loop = 0;
+
if (!loop) {
warnx("verification failed permanently");
goto bail_err;
@@ -1331,7 +1369,7 @@ generate_convert(struct params *p, int a
return -1;
}
- oldp->key = getkey("old file", oldp->keygen, oldp->keylen);
+ oldp->key = getkey("old file", oldp->keygen, oldp->keylen, NULL);
/* we copy across the non-keygen info, here. */
@@ -1383,7 +1421,7 @@ generate_convert(struct params *p, int a
return ret;
}
- p->key = getkey("new file", p->keygen, p->keylen);
+ p->key = getkey("new file", p->keygen, p->keylen, NULL);
kg = keygen_generate(KEYGEN_STOREDKEY);
kg->kg_key = bits_xor(p->key, oldp->key);
@@ -1569,7 +1607,7 @@ printkey(const char *dev, const char *pa
warnx("invalid parameters file \"%s\"", paramsfile);
return -1;
}
- p->key = getkey(dev, p->keygen, p->keylen);
+ p->key = getkey(dev, p->keygen, p->keylen, NULL);
raw = bits_getbuf(p->key);
nbits = bits_len(p->key);
assert(nbits <= INT_MAX - 7);