| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
| |
The systemd-cryptenroll man page states:
Takes a comma separated list of numeric slot indexes, or the special
strings ..., or any combination of these strings or numeric
indexes, in which case all slots matching either are wiped.
but we'd allow only one special string at any given time as the value
was not ORed when assigning. So, for example, --wipe=recovery,password
would actually become --wipe=password, etc.
|
|
|
|
|
|
|
|
|
| |
Passing 0 to log_xxx_errno() leads to an assertion, so let's not do that:
$ NEWPASSWORD="" build-san/systemd-cryptenroll --unlock-key-file=/tmp/password --password "$img"
/tmp/password has 0644 mode that is too permissive, please adjust the ownership and access mode.
Assertion '(_error) != 0' failed at src/cryptenroll/cryptenroll-password.c:164, function enroll_password(). Aborting.
Aborted (core dumped)
|
|
|
|
|
| |
parse_boolean_argument() returns the same information via both the output
argument and normal return.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes:
- Comment style
- Alignment style
- cleanup macro usage
- incorrect error message[1]
1. Thanks to tempusfugit991@gmail.com for pointing out the error
message mistake.
Signed-off-by: William Roberts <william.c.roberts@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Prevent attackers from spoofing the tpmKey portion of the AuthSession by
adding a trusted key to the LUKS header metadata. Also, use a persistent
object rather than a transient object.
This provides the following benifits:
1. No way to MITM the tpmKey portion of the session, see [1] for
details.
2. Strengthens the encrypted sessions, note that the bindKey could be
dropped now.
3. Speed, once it's created we just use it.
4. Owner Auth is needed to call create primary, so using the SRK
creates a scratch space for normal users.
This is a "first to set" model, in where the first person to set the key
in the LUKS header wins. Thus, setup should be done in a known good
state. If an SRK, which is a primary key at a special persistent
address, is found, it will use whatever is there. If not, it creates an
SRK. The SRK follows the convetions used through the tpm2-software
organization code on GitHub [2], however, a split has occured between
Windows and Linux with respect to SRK templates. The Linux SRK is
generated with the unique field size set to 0, in Windows, it properly
sets the size to key size in bytes and the unique data to all 0's of that
size. Note the proper templates for SRKs is covered in spec [3].
However, the most important thing, is that both SRKs are passwordless,
and thus they should be interchangable. If Windows is the first to make
the SRK, systemd will gladly accept it and vice-versa.
1. Without the bindKey being utilized, an attacker was able to intercept
this and fake a key, thus being able to decrypt and encrypt traffic as
needed. Introduction of the bindKey strengthened this, but allows for
the attacker to brute force AES128CFB using pin guesses. Introduction of
the salt increases the difficulty of this attack as well as DA attacks
on the TPM objects itself.
2. https://github.com/tpm2-software
3. https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf
Fixes: #20668
Fixes: #22637
Signed-off-by: William Roberts <william.c.roberts@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
$ dd if=/dev/zero of=luks.img bs=1M count=64
$ echo 1231dfsd234d | cryptsetup luksFormat luks.img
$ build-san/systemd-cryptenroll luks.img
SLOT TYPE
0 password
=================================================================
==640364==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 64 byte(s) in 1 object(s) allocated from:
#0 0x7f43ffeb95b5 in __interceptor_realloc.part.0 (/lib64/libasan.so.8+0xb95b5)
#1 0x7f43ff0a4f2f in greedy_realloc ../src/basic/alloc-util.c:70
#2 0x404d9f in list_enrolled ../src/cryptenroll/cryptenroll-list.c:30
#3 0x40f149 in run ../src/cryptenroll/cryptenroll.c:673
#4 0x40f149 in main ../src/cryptenroll/cryptenroll.c:692
#5 0x7f43fd64a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)
SUMMARY: AddressSanitizer: 64 byte(s) leaked in 1 allocation(s).
Aborted (core dumped)
Reported in https://github.com/systemd/systemd/pull/27007.
|
| |
|
|
|
|
|
|
|
|
|
| |
Follow-up for b0fc23fae51d244d2c33d70c10003aa5d5840223.
After the commit, 'signature_path' is now always non-NULL, hence the
condition can be dropped.
Fixes CID#1504492.
|
|
|
|
|
|
|
|
| |
If it was not requested to use a tpm2 signature file when enrolling, do
not fallback to the default /run/systemd/tpm2-pcr-signature.json as it
likely will be unrelated if it exists.
Fixes https://github.com/systemd/systemd/issues/25435
|
|
|
|
|
|
| |
Meson+ninja+compiler do this for us and are better at it.
https://mesonbuild.com/FAQ.html#do-i-need-to-add-my-headers-to-the-sources-list-like-in-autotools
|
|
|
|
|
|
|
|
|
|
| |
Add a salt to the pin and store it in the TPM2 LUKS header for future
this. This adds entropy to user supplied pins and helps brute forcing
the passphrase on the key residing in the TPM or brute forcing bind key
encrypted sessions with low entropy passphrases.
Signed-off-by: malikabhi05 <abhishek.malik@intel.com>
Signed-off-by: William Roberts <william.c.roberts@intel.com>
|
|
|
|
|
|
|
|
|
|
|
| |
This returns an ssize_t, not an int. On populare archs that's the
difference between 64bit and 32bit. hence, let's be more careful here,
and not silently drop half the bits on the ground by assigning the
return value to "int".
As noticed by @malikabhi05:
https://github.com/systemd/systemd/pull/24754#discussion_r1062903159
|
|
|
|
|
|
|
|
|
|
|
|
| |
This allows FIDO2 users to wipe out password slots and still be able to
enroll new key slots via systemd-cryptenroll. Note that when the user
wants to both unlock with a FIDO2 token and enroll a new FIDO2 token,
they cannot be set to automatic discovery. This is to safeguard against
confusion, because there will be multiple tokens connected to the system
when doing so -- and we require users to explicitly confirm which one to
use for unlocking and which one to use for enrollment.
Addresses #20230 for the FIDO2 case.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
signed values
Traditionally, TPM2 PCR policies are bound against literal PCR values,
which makes them hard to work with when updating software that is
measured into PCRs: each update will change the PCR values, and thus
break TPM2 policies of existing objects.
Let's improve the situation: let's allow signed PCR policies. Secrets
and other TPM2 objects can be associated with a public key that signs a
PCR policy. Thus, if the signed policy and the public key is presented,
access to the TPM2 object can be granted. This allows a less brittle
handling of updates: for example, whenever a kernel image is updated a
new signed PCR policy can be shipped along with it, signed by a private
key owned by the kernel vendor (ideally: same private key that is used
to sign the kernel image itself). TPM2 objects can then be bound to the
associated public key, thus allowing objects that can only be unlocked
by kernels of the same vendor. This makes it very easy to update kernels
without affecting locked secrets.
This does not hook up any of the consuming code (just passes NULL/0
everywhere). This is for later commits.
|
|
|
|
|
|
| |
Add a new tpm2_parse_pcr_argument() helper that unifies how we merge PCR
masks in a single function, we can use all over the place. Previously we
had basically the same code for this at 4 places.
|
| |
|
| |
|
|\
| |
| | |
adding the option to use a keyfile to unlock the device
|
| | |
|
|/ |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We currently have a convoluted and complex selection of which random
numbers to use. We can simplify this down to two functions that cover
all of our use cases:
1) Randomness for crypto: this one needs to wait until the RNG is
initialized. So it uses getrandom(0). If that's not available, it
polls on /dev/random, and then reads from /dev/urandom. This function
returns whether or not it was successful, as before.
2) Randomness for other things: this one uses getrandom(GRND_INSECURE).
If it's not available it uses getrandom(GRND_NONBLOCK). And if that
would block, then it falls back to /dev/urandom. And if /dev/urandom
isn't available, it uses the fallback code. It never fails and
doesn't return a value.
These two cases match all the uses of randomness inside of systemd.
I would prefer to make both of these return void, and get rid of the
fallback code, and simply assert in the incredibly unlikely case that
/dev/urandom doesn't exist. But Luca disagrees, so this commit attempts
to instead keep case (1) returning a return value, which all the callers
already check, and fix the fallback code in (2) to be less bad than
before.
For the less bad fallback code for (2), we now use auxval and some
timestamps, together with various counters representing the invocation,
hash it all together and provide the output. Provided that AT_RANDOM is
secure, this construction is probably okay too, though notably it
doesn't have any forward secrecy. Fortunately, it's only used by
random_bytes() and not by crypto_random_bytes().
|
|
|
|
|
| |
* Some authenticators(like Yubikey) support credential algorithm other than ES256
* Introduce a new option so users can make use of it
|
|
|
|
| |
This also avoids multiple evaluations in STRV_FOREACH_BACKWARDS()
|
|
|
|
|
|
|
|
| |
Add support for PIN enrollment with TPM2. A new "tpm2-pin" field is
introduced into metadata to signal that the policy needs to include a
PIN.
v2: fix tpm2_make_luks2_json in sd-repart
|
|
|
|
|
|
|
|
|
|
|
| |
Modify TPM2 authentication policy to optionally include an authValue, i.e.
a password/PIN. We use the "PIN" terminology since it's used by other
systems such as Windows, even though the PIN is not necessarily numeric.
The pin is hashed via SHA256 to allow for arbitrary length PINs.
v2: fix tpm2_seal in sd-repart
v3: applied review feedback
|
|
|
|
|
|
|
|
| |
The new helper combines a bunch of steps every invocation of
unsetenv_erase() did so far: getenv() + strdup() + unsetenv_erase().
Let's unify this into one helper that is harder to use incorrectly. It's
in inspired by TAKE_PTR() in a way: get the env var out and invalidate
where it was before.
|
|
|
|
| |
PKCS#11 -> FIDO2 in cryptenroll-fido2.c
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This macro is like JSON_BUILD_STRING() but uses our json library's
ability to use literal strings directly as JsonVariant objects.
The changes all our codebase to use this new macro whenever we build
JSON objects from literal strings.
(I tried to make this automatic, i.e. to detect in JSON_BUILD_STRING()
whether something is a literal string nicely and thus do this stuff
automatically, but I couldn't find a way.)
This should reduce memory usage of our JSON code a bit. Constant strings
we use very often will now be shared and mapped directly from the ELF
image.
|
|
|
|
|
|
| |
People should use homectl to enroll tokens into home directories, hence
point them there. Otherwise the auth data for the account and for the
LUKS volume will end up being different.
|
|
|
|
|
|
|
|
| |
glyph-util.[ch]
These functions are used pretty much independently of locale, i.e. the
only info relevant is whether th locale is UTF-8 or not. Hence let's
give this its own pair of .c/.h files.
|
|
|
|
|
|
|
|
|
|
| |
invalid
The field is not owned by us (even though is in our JSON objects) but by
the LUKS2 spec. Hence let's handle this a bit more gracefully: let's not
get confused by it, just warn and skip over it.
Fixes: #20847
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously, we hardcoded use of ECC as primary keys, since they are much
faster (i.e. saving multiple seconds) to do TPM2 operations with. Alas,
not all TPM2 chips appear to support ECC. Bummer.
Let's hence add a fallback logic: if we can't create an ECC primary key,
use an RSA key, and store that fact away.
AFIU the security guarantees should be roughly the same, it's just that
RSA primary keys is so much slower to work with than ECC.
The primary key algorithm is used is stored in the JSON header of LUKS
disks, in a new field. If the field is absent we assume to use ECC, to
provide full compatibility with old systemd versions.
The primary key algorithm is stored in a new field in the credentials
file format (in fact, a previously unused zero space is used), too.
Hopefully, this should ensure that TPM2 support will "just work" on more
systems.
Fixes: #20361
|
|
|
|
| |
Let's unify how we remove secrets from the env block.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously, we'd encode PCR policies strictly with the SHA256 PCR bank
set. However, as it appears not all hw implement those. Sad.
Let's add some minimal logic to auto-detect supported PCR banks: if
SHA256 is supported, use that. But if not, automatically fall back to
SHA1.
This then changes both the LUKS code, and the credentials code to
serialize the selected bank, along with the rest of the data in order to
make this robust.
This extends the LUK2 JSON metadata in a compatible way. The credentials
encryption format is modified in an incompatible way however, but given
that this is not part of any official release should be OK.
Fixes: #20134
|
|
|
|
| |
We use "+" as separator for PCR indexes now, but we forgot to replace
one "," by "+"
|
|
|
|
|
|
|
| |
Code using libcryptsetup already sets the global log function if it uses
dlopen_cryptsetup(). Make sure we do the same for the three programs
that explicitly link against libcryptsetup and hence to not use
dlopen_cryptsetup().
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Let's try to handle keys gracefully that do not implement all features
we ask for: simply turn the feature off, and continue.
This is in particular relevant since we enroll with PIN and UP by
default, and on devices that don't support that we should just work.
Replaces: #18509
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously, we supported only "," as separator. This adds support for
"+" and makes it the documented choice.
This is to make specifying PCRs in crypttab easier, since commas are
already used there for separating volume options, and needless escaping
sucks.
"," continues to be supported, but in order to keep things minimal not
documented.
Fixe: #19205
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We recently started making more use of malloc_usable_size() and rely on
it (see the string_erase() story). Given that we don't really support
sytems where malloc_usable_size() cannot be trusted beyond statistics
anyway, let's go fully in and rework GREEDY_REALLOC() on top of it:
instead of passing around and maintaining the currenly allocated size
everywhere, let's just derive it automatically from
malloc_usable_size().
I am mostly after this for the simplicity this brings. It also brings
minor efficiency improvements I guess, but things become so much nicer
to look at if we can avoid these allocation size variables everywhere.
Note that the malloc_usable_size() man page says relying on it wasn't
"good programming practice", but I think it does this for reasons that
don't apply here: the greedy realloc logic specifically doesn't rely on
the returned extra size, beyond the fact that it is equal or larger than
what was requested.
(This commit was supposed to be a quick patch btw, but apparently we use
the greedy realloc stuff quite a bit across the codebase, so this ends
up touching *a*lot* of code.)
|
|
|
|
|
|
| |
Some tokens support authorization via fingerprint or other biometric
ID. Add support for "user verification" to cryptenroll and cryptsetup.
Disable by default, as it is still quite uncommon.
|
|
|
|
|
|
|
|
|
|
| |
In some cases user presence might not be required to get _a_
secret out of a FIDO2 device, but it might be required to
the get actual secret that was used to lock the volume.
Record whether we used it in the LUKS header JSON metadata.
Let the cryptenroll user ask for the feature, but bail out if it is
required by the token and the user disabled it.
Enabled by default.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Closes: https://github.com/systemd/systemd/issues/19246
Some FIDO2 devices allow the user to choose whether to use a PIN or not
and will HMAC with a different secret depending on the choice.
Some other devices (or some device-specific configuration) can instead
make it mandatory.
Allow the cryptenroll user to choose whether to use a PIN or not, but
fail immediately if it is a hard requirement.
Record the choice in the JSON-encoded LUKS header metadata so that the
right set of options can be used on unlock.
|
|
|
|
|
|
|
|
|
|
|
|
| |
store first
This adds generic support for the SetCredential=/LoadCredential= logic
to our password querying infrastructure: if a password is requested by a
program that has a credential store configured via
$CREDENTIALS_DIRECTORY we'll look in it for a password.
The "systemd-ask-password" tool is updated with an option to specify the
credential to look for.
|
| |
|
|
|
|
|
| |
This fits better in shared/, and the new parse-argument.c file is a good home
for it.
|