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.
This way you can convert an existing parameters file to one that is
derived from a shared key, and derive other subkeys for other disks
from the same shared key.
cgdconfig -G -S -o /etc/cgd/wd0.shared /etc/cgd/wd0
cgdconfig -G -S -o /etc/cgd/wd1.shared \
-P /etc/cgd/wd0.shared /etc/cgd/wd1
This way, if you enter the same new password both times, wd0.shared
and wd1.shared generate the same keys as wd0 and wd1, but only need
one password entry with `cgdconfig -C'.
Usage model:
- Generate a parameters file that supports sharing its main key:
cgdconfig -g -S -o /etc/cgd/wd0e -V gpt adiantum
- Make another parameters file that uses the same shared main key but
derives an independent subkey from it:
cgdconfig -g -S -P /etc/cgd/wd0e -o /etc/cgd/ld1e \
-V disklabel aes-cbc 256
New clause `shared <id> algorithm <alg> subkey <info>' in a keygen
block enables `cgdconfig -C' to reuse a key between different params
files, so you can, e.g., use a single password for multiple disks.
This is better than simply caching the password itself because:
- Hashing the password is expensive, so it should only be done once.
Suppose your budget is time t before you get bored, and you
calibrate password hash parameters to unlock n disks before you get
bored waiting for `cgdconfig -C'.
. With n password hashings the adversary's cost goes up only by a
factor of t/n.
. With one password hashing and n subkeys the adversary's cost goes
up by a factor of n.
And if you ever add a disk, rehashing it will make `cgdconfig -C'
go over budget, whereas another subkey adds negligible cost to you.
- Subkeys work for other types of keygen blocks, like shell_cmd,
which could be used to get a key from a hardware token that needs a
button press.
The <info> parameter must be different for each params file;
everything else in the keygen block must be the same. With this
clause, the keygen block determines a shared key used only to derive
keys; the actual key used by cgdconfig is derived from the shared key
by the specified algorithm.
The only supported algorithm is hkdf-hmac-sha256, which uses
HKDF-Expand of RFC 5869 instantiated with SHA-256.
Example:
algorithm aes-cbc;
iv-method encblkno1;
keylength 128;
verify_method none;
keygen pkcs5_pbkdf2/sha1 {
iterations 39361;
salt AAAAgMoHiYonye6KogdYJAobCHE=;
shared "pw" algorithm hkdf-hmac-sha256
subkey AAAAgFlw0BMQ5gY+haYkZ6JC+yY=;
};
The key used for this disk will be derived by
HKDF-HMAC-SHA256_k(WXDQExDmBj6FpiRnokL7Jg==),
where k is the outcome of PBKDF2-SHA1 with the given parameters.
Note that <info> encodes a four-byte prefix giving the big-endian
length in bits of the info argument to HKDF, just like all other bit
strings in cgdconfig parameters files.
If you have multiple disks configured using the same keygen block
except for the info parameter, `cgdconfig -C' will only prompt once
for your passphrase, generate a shared key k with PBKDF2 as usual,
and then reuse it for each of the disks.
Apparently fsck doesn't have a way to replay it to its internal memory
only. (Someone(TM) should implement this...)
This means that if you use -n, it can't replay the journal. But the
sequence of prints is such that it looks like it did. This is quite
misleading. Add an additional specific warning.
If getfsspecname() fails that will usually mean that a NAME=wedge or
ROOT.x partition is unabailable. raidframe specified unavailable
partitions as "absent" so in this case, pass "absent" rather than the
unaltered NAME= or ROOT.x string, which the kernel has no clue what
do do with, and doesn't configure the raid at all.
I found this juxtaposition in the shutdown man page kind of
interesting:
time Time is the time at which shutdown will bring the system down
and may be the word now or a future time in one of two formats:
... [2nd format:] [[[[[cc]yy]mm]dd]hh]mm, ...
If the century [cc] is not specified, it defaults to 1900 for
years [yy] between 69 and 99, ...
In that, all the "[text]" except the one "[[[[["(etc) sequence are my
interjections, The ellipses ("...") represent where I omitted irrelevant
(for here) text.
Interesting yes, bizarre also. Requiring a future time, and then
defaulting to the (long gone) 20th century (for any random year)
makes no sense at all. So I fixed it.
In another hundred years or so, anytime from 2100 onwards, but best
left at least a decade into the new century, it will need altering again.
[One could write the code to automate this adjustment, but the man
page would still need updating.] More significant changes will be
needed as the 101st century approaches (years 10000 and beyond), as
then a 2 digit century will no longer be adequate. Call me then, and
if I'm able, I'll fix it.
If someone really has a need to schedule a shutdown for sometime
between 1969 and 1999 that can still be done by explicitly giving
the "19" cc value. It is just no longer ever the default.
Otherwise, now, years 20..90 mean the 21st century (2020..2099)
(the first 2 of those are already unusable, but, IMO, that's OK)
and years 00..19 mean the 22nd century (2100..2119) (except that
00, 2100, is still technically the final year of the 21st century).
This is advance planning for near the end of the 21st century when
someone wants to schedule a shutdown for early in the following
century, and can't be bothered typing the 2 century digits.
This does the same config file parse that -c/-C do, but only
that (hence no raidframe device is needed, or accepted).
Any syntax errors in the config file will be reported, nothing
else happens.
First, and what got me started on this set of cleanups, the queue
length in the "queue" section (START queue) is limited to what will
fit in a char without losing accuracy (I tried setting it to 200,
rather than the more common (universal?) 100 and found that the
value configured into the array was -56 instead.
Why the value needs to be passed through a char variable I have no
idea (it is an int in the filesystem raidframe headers) - but that's
the way it is done, and changing it would be an ABI change I believe
(and so need versioning to alter) and that isn't worth it for this
(or not now, IMO).
Instead check that the value in the char is the same value as was
read from the config file, and complain if not. Those of you with
unsigned chars will be able to have queue lengths up to 255, the
rest of us are limited to 127.
While looking at that, I noticed some code that obviously fails to
understand that scanf("%s") will never return a string containing
spaces, and proceeded to attempt to remove trailing spaces from the
result ... amusingly, after having used the result for its intended
purpose (non existent trailing spaces unremoved), after which that
buffer was never used again. That code is now gone (but for now,
just #if 0'd rather than actually deleted - it should be cleaned up
sometime).
Then I saw some other issues with how the config was parsed - a
simple (unbounded) scanf("%s") into a buffer, which hypothetically
might not be large enough (not a security issue really, raidctl has
no special privs, and it isn't likely that root could easily be
tricked into running it on a bogus config file - or not without
looking first anyway, and a huge long string would rather stand
out). Bound the string length to something reasonable, and
assert() that the buffer is big enough to contain it.
Lastly, in the event of one particular detected error in the
config file, the code would write a warning, but then just go
ahead and use the bad data (or nothing perhaps) anyway - a
failure of logic flow (unlikely to have ever happened, everyone
seems to simply copy the sample config from the man page, and
make minor adjustments as needed).
If any of these changes make any difference to anyone (except
me with my attempt to make longer queues - for no particularly
well thought out reason), I'd be very surprised.
the following comment appeared:
/*
* After NetBSD 9, convert this to not output the numRow's value,
* which is no longer required or ever used.
*/
We are after NetBSD 9 (well after). The change requested in that
comment is made here, and the comment is thus removed.
A couple of places in rf_configure.c where a value for the "rows"
parameter was output in an error message (always simply as the
constant 0) have also been updated (those messages will no longer
include "row 0", which they always said previously). One of them
was also slightly reworded to be clearer what problem it was
experiencing (when it said 'unable to get device file' it meant
it was unable to locate the name for the device in the config file,
not that it was found, and there was some other problem with it).
allow conditionally disabling the building of certain user space
programs in the 'base' set.
There is not enough consensus that this is the right way and a few
people had strong objections, see source-changes-d@.