Compare commits

...

902 Commits

Author SHA1 Message Date
Milan Broz
3323690cbc Version 2.7.0-rc1. 2023-12-20 15:21:01 +01:00
Milan Broz
1a50de508c Fix doxygen tags for API docs. 2023-12-20 15:12:30 +01:00
Milan Broz
b47f423907 Update release notes for 2.7.0-rc1 and LUKS2 doc. 2023-12-20 15:12:24 +01:00
Daniel Zatovic
d1b32a3b64 Add keyring linking API placeholders for multi-key scenarios. 2023-12-20 14:02:07 +01:00
Milan Broz
f87f6226aa opal: Fix benign gcc warning for possible uninitialized value. 2023-12-19 13:40:29 +01:00
Milan Broz
cd576666fc opal: Do not verify passphrase by default on luksErase.
Verify passphrase should be default only when creatng
a new passphrase, here it will fail if the passphrase
is wrong.
2023-12-19 12:35:50 +01:00
Ondrej Kozina
6b1f13fd0f opal: add comments to all lockless opal calls. 2023-12-18 17:26:47 +00:00
Milan Broz
7db221e47e Report Argon2 crypto backend version in debug output
For Argon2 native code (gcrypt, OpenSSL) a flag in debug output is printed.

If libargon is used, then [cryptsetup libargon2] is printed
(embedded code) or [external libargon2] for dynamic external library.

 # Crypto backend (OpenSSL 3.0.11 19 Sep 2023 [default][legacy] [external libargon2])
or
 # Crypto backend (OpenSSL 3.0.11 19 Sep 2023 [default][legacy] [cryptsetup libargon2])

Fixes: #851
2023-12-17 11:53:38 +00:00
Milan Broz
e5511b1920 Use uppercase OPAL in messages. 2023-12-17 12:52:39 +01:00
Ondrej Kozina
0ca1e680db opal: add exclusive lock to avoid race.
Activating LUKS2 device with OPAL support is multistep process.

1) read LR state
2) unlock LR
3) activate dm device
4) in case step 3) failed lock the device
   if in step 1) the device was locked.

Otherwise, in case parallel activation happened on one device
the process that failed to map dm device (device already active)
could relock the LR afterwards and effectively break already active
device.

To avoid that we do steps 1) through 4) protected by exclusive
opal lock unique per data block device configured for use with
LUKS2 OPAL support.
2023-12-13 20:59:14 +00:00
Ondrej Kozina
2e978c8776 opal: do not always re-lock range on failed activation.
If activation fails due to already active dm mapping
we must not automatically re-lock the OPAL range since
it would break the original active device.
2023-12-13 20:59:14 +00:00
Ondrej Kozina
31027b9240 test: check if device remains usable after failed attempt to double activation. 2023-12-13 20:59:14 +00:00
Ondrej Kozina
1d0680ce95 Drop unused crypt_read_lock helper. 2023-12-13 20:58:13 +00:00
Ondrej Kozina
997ef242a2 opal: no need to export internal opal_enabled function. 2023-12-13 15:16:02 +01:00
Ondrej Kozina
b869822c8b opal: erase key cached in kernel when LR gets locked.
It affects only HW OPAL locking range KEK.

After unlocking opal locking range we cache the key in kernel
so that we do not have to pass the key again for locking the
range later (the OPAL std requires key for lock command).

Unfortunately the key remains cached in kernel even after we
lock the range on purpose during crypt_deactivate* or crypt_suspend.

This had 2 side effects:

1) key remained in system memory even though the LUKS device was
   inactive (and all keys should be erased from memory).

2) when system gets suspended the locking range got automatically
   unlocked later after system resume because the key caching is used
   primarly to automatically unlock locking ranges that got locked
   after system suspend (due to power cut off on storage device).

Since kernel does not directly support dropping cached keys we achieve
that by overwritting the original key structure with empty one.
2023-12-04 19:02:11 +00:00
Boyuan Yang
2d080580bd po: update zh_CN.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Yuri Chornoivan
e3c65d9a34 po: update uk.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Remus-Gabriel Chelu
818e35e71c po: update ro.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Jakub Bogusz
ba751970af po: update pl.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Hiroshi Takekawa
13fcbe139d po: update ja.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Frédéric Marchal
5ea325afcc po: update fr.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Roland Illig
cf523b95be po: update de.po (from translationproject.org) 2023-12-04 20:01:31 +01:00
Ondrej Kozina
0f642a8397 Add missing vectors tests in valgrind setup. 2023-12-04 09:33:21 +00:00
Ondrej Kozina
b653567e3e Simplify meson tests.
Valgrind tests is now run with:

meson test -C <build_dir> --setup=valgrind
2023-12-04 09:33:21 +00:00
Milan Broz
85d23dde79 Revert "tests: Temporarily disable veritysetup tasklet option test."
This reverts commit 0e44494aba.

Kernel fix is in mainline and on the way to stable kernels.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/md?id=2a695062a5a42aead8c539a344168d4806b3fda2
2023-11-30 14:53:42 +00:00
Milan Broz
5e7bd7a36b fuzz: Try to limit image size in crypt2_load_proto_plain_json_fuzz
It seems that we see a lot of out of space in fuzzer run,
so try to avoid writing excessive big images here.
2023-11-30 15:01:04 +01:00
Milan Broz
f725123e4a Version 2.7.0-rc0. 2023-11-29 09:50:27 +01:00
Milan Broz
e1ef5214e7 Fix some typos found by lintian. 2023-11-29 09:49:55 +01:00
Milan Broz
b44c2ce071 Update pot file. 2023-11-29 09:22:52 +01:00
Milan Broz
5d50617594 Tweak some error messages. 2023-11-29 09:21:01 +01:00
Milan Broz
cea9c2972e Add release notes for 2.7.0-rc0. 2023-11-28 18:53:45 +00:00
Milan Broz
1e9d31e0e4 Add hw_opal.c for translation. 2023-11-28 18:53:45 +00:00
Milan Broz
d3a8393476 Set version 2.7.0-rc0. 2023-11-28 18:53:45 +00:00
Milan Broz
70a151242f meson: fix meson_dist_convert script 2023-11-28 18:53:45 +00:00
Milan Broz
ec4e2faf14 Add missing files to autoconf make dist. 2023-11-28 18:53:45 +00:00
Ondrej Kozina
e4a845c51e Use proper integer constant in meson_options.txt
Unfortunately it creates decimal base constant when converting
to C define.

But the former implicit and deprecated conversion did it as well.
2023-11-28 18:52:57 +00:00
Ondrej Kozina
d64203a018 Override meson default prefix. 2023-11-28 18:52:57 +00:00
Milan Broz
c0dfd1178d Fix some coverity scan issues.
The read in kernel crypto backend is part of user crypto API
encryption call, we have to trust it here.

JSON fix is just one place where return code was not checked
for this particular function.
2023-11-28 18:52:25 +00:00
Milan Broz
b3f1f611cd Always print error message for invalid keyring definition.
Many cases quietly returned error without any error message.
2023-11-27 15:13:04 +01:00
Мирослав Николић
86498858fc po: update sr.po (from translationproject.org) 2023-11-26 12:34:21 +01:00
Yuri Kozlov
403d12d52c po: update ru.po (from translationproject.org) 2023-11-26 12:34:21 +01:00
Jakub Bogusz
fcf6f8febf po: update pl.po (from translationproject.org) 2023-11-26 12:34:21 +01:00
Antonio Ceballos
06d02f4766 po: update es.po (from translationproject.org) 2023-11-26 12:34:21 +01:00
Milan Broz
6262da3a11 fuzz: add missing flex (util-linux req.) to fix fuzzing build 2023-11-26 10:39:22 +01:00
Milan Broz
dfbb7752b5 tests: fail early if PSID reset does not work for device.
This should stop user from using wrong device for tests.
2023-11-22 15:48:48 +01:00
Milan Broz
6b2cf68713 Suspend and resume also dm-integrity device with AEAD.
Currently we suspend top-level device only.

With OPAL, the underlying device will start to return errors
once OPAL LR is locked.

If the dm-integrity device is not suspended, regular journal
flush corrupts the device (journal write failure),
corrupting data above it.

Suspending the whole stack should fix the issue.
2023-11-22 12:15:18 +01:00
Milan Broz
0f51b5bacb Do not run sector read check on suspended device.
This can affect status command, but later also device
stack with authenticated encryption (*_dif device).

Ignoring direct-io should not be problem here.
The logic shoudl be simplified in future anyway...
2023-11-21 22:44:16 +01:00
Milan Broz
d3cc5e846a Do not require init_done for some deive helpers.
It processes only name, no need to depend on real device
checks (for direct-io) etc.
2023-11-21 22:44:16 +01:00
Ondrej Kozina
722c77c883 Fix wrong key id set when resuming LUKS2 device.
If volume key digest id was not 0 it failed on assert
in LUKS2 resume path later.
2023-11-21 21:43:34 +00:00
Daniel Zatovic
20c8096cc8 CI: change TSS package name for Debian 12
Change package name from tpm2-tss-engine-dev (on Debian 11) to libtss2-dev (on Debian 12).
2023-11-20 11:28:56 +01:00
Ondrej Kozina
8c0a943e5c Drop fake_token_path symbol from tests.
It's no longer used.
2023-11-17 10:42:23 +01:00
Ondrej Kozina
5ef1878b34 Do not use fake-token-path in ssh and systemd plugin tests. 2023-11-17 10:42:23 +01:00
Ondrej Kozina
836e5e4539 Add --external-tokens-path parameter in cryptsetup. 2023-11-16 17:49:09 +01:00
Ondrej Kozina
0328d61f29 Add crypt_token_set_external_path API.
It can be used to override system library where
libcryptsetup looks for external token handlers (plugins).

The parameter is required to be absolute path and it is set
per process context.

Fixes: #846.
2023-11-16 17:49:06 +01:00
Ondrej Kozina
31f82fd37c Drop deprecated use of implicit meson setup command. 2023-11-15 19:22:27 +00:00
Ondrej Kozina
9ca46971f2 Fix systemd-test-plugin initialization.
check for .git subdirectory to decide if systemd
repository needs to be cloned.
2023-11-15 19:22:27 +00:00
Ondrej Kozina
7aeb1c3aea Fix fake systemd tpm path symbol.
The prototype for the function in systemd has changed.
Otrherwise the tests abort with SEGFAULT.
2023-11-15 19:22:27 +00:00
Ondrej Kozina
cf7874de4b compat-test-opal does not depend on differ util. 2023-11-15 18:41:02 +01:00
Ondrej Kozina
d82a1843ba Speed up compat-test-opal valgrind test.
By not testing cleanup routines repeatingly
for leaks.
2023-11-15 18:41:02 +01:00
Ondrej Kozina
9a5a3855a0 Enable valgrind tests in meson. 2023-11-15 18:40:44 +01:00
Ondrej Kozina
83bb3648e3 Fix invalid comparison of bool and int types in root meson.build. 2023-11-15 13:33:05 +01:00
Ondrej Kozina
564379618a Increase minimal meson version to 0.64
It's inital cryptsetup upstream release with
meson support so let's not pollute scripts
with if-then-else branching from the very
beginning.
2023-11-15 13:33:05 +01:00
Daniel Zatovic
04a20e9b7d CI: disable -Wdeclaration-after-statement warning 2023-11-15 12:15:19 +01:00
Daniel Zatovic
11ab2f0d9e Dont mix declarations with code.
Move asserts after declarations.
2023-11-15 12:11:10 +01:00
Daniel Zatovic
7d4628e379 Remove obsolate AC_C_CONST macro.
The AC_C_CONST test program fails to compile under latest clang with
-Wall -Werror, which results in erroneously defining "const" keyword to
an empty string. The AC_C_CONST is considered obsolate.
2023-11-15 10:21:04 +01:00
Daniel Zatovic
a176f29dc4 CI: don't use non-existent meson flag
An unknown -Dinternal-argon2=false flag was used, new meson version
fails when it gets unknown flag. Use the correct
-Dargon-implementation=internal flag instead.
2023-11-13 12:08:43 +01:00
Daniel Zatovic
a8168eb854 CI: switch compilation test to Ubuntu Lunar (23.04) 2023-11-13 12:08:43 +01:00
Daniel Zatovic
98f2b9c136 CI: switch Debian runner from 11 to 12 2023-11-13 12:08:43 +01:00
Milan Broz
0e44494aba tests: Temporarily disable veritysetup tasklet option test.
Kernel bug reporte here:
  https://lore.kernel.org/dm-devel/fa17b8d8-2d84-45c8-ac6a-1876f1f55a52@gmail.com/
2023-11-13 12:00:13 +01:00
Milan Broz
371cfc4394 tests: Clean up also dm-integrity device in OPAL test 2023-11-07 19:39:37 +01:00
Ondrej Kozina
860550b3c6 Fix memory leaks detected in compat-test-opal. 2023-11-07 09:58:53 +01:00
Milan Broz
2a9752b6c8 tests: Do not run OPAL test with valgrind if variables are not set
Otherwise it will break run with exit code 77.
2023-11-06 17:12:57 +00:00
Ondrej Kozina
4543a445a0 Add hint about missing OPAL support in kernel.
Unfortunately there is currently no way how
to make difference between device lacking SED OPAL support
state and kernel missing SED OPAL support via disabled interface
via configure option.
2023-11-06 17:12:31 +00:00
Ondrej Kozina
ee31159c68 Enable tests fixed with recent commits. 2023-11-06 16:49:28 +01:00
Ondrej Kozina
029d4bdd57 Abort LUKS2 reencryption early if OPAL device used. 2023-11-06 16:49:28 +01:00
Ondrej Kozina
89e0ef96c2 Add LUKS2 OPAL requirement flag. 2023-11-06 16:49:26 +01:00
Ondrej Kozina
f623eb2e99 Add more onlyLUKS helpers for convenience. 2023-11-06 14:47:41 +01:00
Ondrej Kozina
d09b27a170 Fix memory leak in kernel keyring keyslot context.
The leak occured only when the context instance was
used more than once.
2023-11-03 21:27:59 +00:00
Ondrej Kozina
abf7e3e359 Fix memleak in test.
By defining custom buffer free function in test token handler
the default call to free() gets skipped.
2023-11-03 21:27:59 +00:00
Ondrej Kozina
79444bc615 Fix memory leak in device context. 2023-11-03 21:27:59 +00:00
Ondrej Kozina
0154893ad5 Remove inital opal-test.
Test fully included in compat-test-opal.
2023-11-02 17:15:14 +01:00
Ondrej Kozina
b23e9f32f2 Add basic compat-opal-test.
The aim of the test is verify compatibility with
SW only LUKS2 devices for basic operations like
activation, deactivation, suspend, resume and
token based activation.
2023-11-02 17:15:14 +01:00
Ondrej Kozina
1b7211f013 Do not allow decryption on devices with unsupported parameters.
Most notably LUKS2 w/ authenticated encryption profile. OPAL restriction
will be added in later commits.
2023-11-02 17:15:14 +01:00
Ondrej Kozina
b9ba5ec14d Do not allow --integrity option in reencryption action. 2023-11-02 17:15:14 +01:00
Ondrej Kozina
af8c53a823 Move LUKS2 legacy reencryption flag check.
There's already routine meant for verification if LUKS2
can be reencrypted. So move the appropriate code there instead.
2023-11-02 17:15:14 +01:00
Ondrej Kozina
45ddc623bc Restrict --hw-opal options only to luksFormat action. 2023-11-02 17:15:14 +01:00
Ondrej Kozina
52b2dc5148 Fail early if OPAL is selected with LUKS1. 2023-11-02 17:15:14 +01:00
Ondrej Kozina
e6590e808a Dump OPAL key size in bits. 2023-11-02 17:15:14 +01:00
Ondrej Kozina
7d17b09d41 Do not fail format actions by interrupting device wipe.
otherwise luksFormat and (integrity) format actions return
error when interrupted by user on purpose.
2023-11-02 17:12:34 +01:00
Ondrej Kozina
fea8b82e8d Add missing exclusive open check in crypt_format_luks2_opal. 2023-10-31 11:13:58 +01:00
Ondrej Kozina
32fbac17b1 Improve cmd line options man pages related to SED OPAL. 2023-10-31 11:13:58 +01:00
Ondrej Kozina
4081037bdb Add --key-file support in luksErase action with LUKS2 opal. 2023-10-31 11:13:58 +01:00
Ondrej Kozina
f15b2ffdec Correctly erase opal lr when luksFormat action fails. 2023-10-31 11:13:56 +01:00
Milan Broz
800ec5d1ed fuzzing: Fix crypt2_load_fuzz to not touch const data
The crypt2_load_fuzz fuzzer needs to calculate LUKS2 header checksum
to speed up fuzzing. Currently we incorrectly touch const data input.

This patch
 - calculates only primary LUKS2 header checksum (ignores secondary header)
 - uses temporary struct for modified data
 - keps fuzzer going even with original data if checksum calc fails.

Hopefully solves unknown write issue in fuzzer (not real utils) on oss-fuzz.
2023-10-30 13:11:31 +01:00
Milan Broz
7b6feb20b4 crypto_backend: remove superfluous memset fot hash and hmac contexts
The crypto backend crypt_hash ans crypt_hmac structs usually
contain only pointers to internal crypto lib structures, no need
to wipe them explicitly as there are no sensitive data.
It is a crypto lib responsibility to remove sensitive data
in destructor.

Only nettle backend directly contains hash context, keep it there.

This should also fix mysterious crashes in fuzzer with misaligned memset.
2023-10-27 09:49:46 +00:00
Milan Broz
0c9258484a tests: fix oss-fuzz build
- xz now requires some configure options to build with sanitizer
- lvm2 official repository moved
2023-10-27 09:03:50 +02:00
Ondrej Kozina
385c0afebe Fix tests in FIPS mode.
In FIPS mode, if test passphrase is shorter
than 8 bytes, keyslot passphrase check routine
returns different error code (-EINVAL) than
expected (-EPERM).
2023-10-18 15:02:09 +02:00
Ondrej Kozina
1f007061d6 Respect keyslot id while activating device by token.
Also by using --test-passphrase option this patch allows
cryptsetup to check if specific token (--token-id) is
able to unlock specific keyslot (--key-slot/-S).

It uses recently added crypt_activate_by_keyslot_context
API.

Fixes: #784.
2023-10-16 17:23:32 +00:00
Lennart Poettering
20bfec91d8 libdevmapper: propagate key mgmt related kernel ioctl error on _dm_create_device()
Let's not make up synthetic errors if the kernel returns a useful error
to us, that tells us about key validity.

Specifically, if we try to activate a dm-verity device with a signed
root hash, it's import to know when we couldn't activate it due to the
signing key missing in the kernel keyring. The kernel reports a nice
error code in that case (ENOKEY), let's make sure this is propagated
back to clients.

To be on the safe side, this allowlists only the three key management
related error codes ENOKEY, EKEYREVOKED, EKEYEXPIRED and returns ENOKEY
for all of them. The kernel's DM stack traditionally wasn't very good
with returning useful error codes, hence the conservative approach.

This patch is not sufficient to fix this properly. There's a patch
needed to fix errno propagation also in libdevmapper:

https://gitlab.com/lvmteam/lvm2/-/merge_requests/3

With both patches applied we get correct error code reporting.

Fixes: #841
2023-10-16 14:37:51 +02:00
Ondrej Kozina
15c3a2a2a9 Check passphrase for user selected keyslot only.
When adding new keyslot we check if provided existing
passphrase is correct first.

Since user may now select specific existing keyslot
(to extract volume key) it's no use to check any
matching keyslot. Test passphrase only for user
specified keyslot.
2023-10-09 09:49:54 +00:00
Milan Broz
717bd0665d plain: Add note to man page about cipher options. 2023-10-05 10:31:44 +02:00
Milan Broz
8f442bc97a tests: Avoid new plain type warnings if missing options. 2023-10-05 10:31:41 +02:00
Milan Broz
84682f6271 plain: Set default cipher to aes-xts-plain64 and hash to sha256.
These are configurable in build time, to force default backward compatibility use
--with-plain-hash=ripemd160 --with-plain-cipher=aes --with-plain-mode=cbc-essiv:sha256
configure options.

Fixes #758.
2023-10-05 10:31:20 +02:00
Milan Broz
a18fe71d8d plain: Print warning if using default cipher ahd hash options.
Unlike LUKS, plain mode uses no metadata where configured.
As we need to upgrade algorithms form time to time because of security
reasons, warn user to specify these options explicitly.

Related #758.
2023-10-05 08:12:51 +00:00
Ondrej Kozina
593f22a9a8 Fix empty device name in reencryption prompt message.
While resuming LUKS2 reencryption operation for
device identified by active mapping (--active-name) the
prompt about ongoing operation did not use correct
variable to get device name in the message.
2023-10-04 16:13:09 +02:00
Ondrej Kozina
edc2505923 Close stdin in tests where not expected to be used. 2023-10-04 11:40:56 +02:00
Ondrej Kozina
1f5b229a0e Add test coverage for device activation.
Add tests for device activation by volume
key uploaded in kernel keyring where user
only pass key description with no key type
description. In this case we add 'user' type
by default and it was not tested properly.
2023-10-04 11:40:45 +02:00
Ondrej Kozina
742bb0693d Fix return value in vk description parser.
Always return 0 on success or predefined negative
errno otherwise.
2023-10-04 11:39:56 +02:00
Ondrej Kozina
a5e2a97b53 Fix a bug in vk description parsing helper.
Fix a path with default kernel key type assumed.
It did not check correctly for return value from
asprintf and would leak the allocated memory
instead.
2023-10-04 11:39:56 +02:00
Ondrej Kozina
0236b82802 Fix user vk description leak in open action. 2023-10-04 11:39:56 +02:00
Ondrej Kozina
cfe257e10e Fix devel/debug leftover in LUKS2 api test. 2023-10-02 14:45:21 +02:00
Daniel Zatovic
05d3cb9196 CI: fix annocheck and csmock runners 2023-10-02 11:07:02 +02:00
Ondrej Kozina
df9976e2a7 We do not need to wipe specific keyslot area only. 2023-09-29 11:30:53 +02:00
Ondrej Kozina
f0b556b2d4 Do not wipe keyslot area before in-place overwrite.
If LUKS2 keyslot area has to be overwritten (due to lack of free space),
do not wipe the affected area first. It will get overwritten anyway.
Originaly, in between the keyslot wipe and new key material write, pbkdf
calculation took place. The pbkdf calculation takes ~2 seconds by default
and it put the user in unnecesary risk of loosing the keysot data in case
of a crash.
2023-09-29 11:30:53 +02:00
Ondrej Kozina
ca0c9c765e Avoid overwritting LUKS2 keyslot area if possible.
With LUKS2 crypt_keyslot_change_by_passphrase() call
does not have to overwrite binary keyslot
area in-place when user asked for specific keyslot id.

If there's enough free space in keyslot binary area
we can write new keyslot material in the the free area
(identified temporarily by new keyslot id) and switch
pointers (json metadata) to point to the new keyslot area after
the keyslot area write is complete. The old keyslot
area gets deleted after the new area write is finished.

Otherwise we needlesly risk to lose the existing keyslot
if the operation gets interupted.

With this patch LUKS2 crypt_keyslot_change_by_passphrase()
overwrites existing keyslot (including keyslot area)
only if there's no free space and therefore in-place update
is necessary.

Fixes: #839.
2023-09-29 11:30:53 +02:00
Ondrej Kozina
57bd4e0e66 Make all returned kernel key ids key_serial_t type. 2023-09-27 19:37:35 +00:00
Ondrej Kozina
fde3e881fc Do not return -errno codes from keyring utilities.
Fixes: #838.
2023-09-27 19:37:35 +00:00
Ondrej Kozina
d011ba710c Drop unused kernel keyring code. 2023-09-27 19:37:35 +00:00
Ondrej Kozina
6296e8d4f8 Improve debug output for kernel keyring.
Add more context to possibly failing kernel keyring routines
in log debug output.

Mostly split debug output for errors while trying to search the kernel
key by description and errors while trying to read/unlink the key
by its id.
2023-09-27 19:37:35 +00:00
Ondrej Kozina
cdce1d96f0 Do not print kernel key sizes in debug output.
Fixes: #837.
2023-09-27 12:04:42 +02:00
Ondrej Kozina
305688d678 Correctly cleanup volume key from kernel keyring on error.
If requested operation fails we should remove volume key
previously linked in user requested kernel keyring.
2023-09-26 12:03:11 +02:00
Ondrej Kozina
f6c464844d Fix posible NULL dereference bug. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
0404e65da8 Split volume key only if activating SED OPAL LUKS2. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
2d54e0bc58 Drop unused and unreleased API. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
05634f272c Drop setting kernel key permissions.
Libcryptsetup should not set such permissions. All
the issues it aims to solve can be workaround by
caller linking the key in appropriate keyring
first and moving it in final destination later.
2023-09-25 18:59:09 +00:00
Ondrej Kozina
51a1e218cf Split logic for uploading keys in kernel key service.
We can not link internal VK kernel key in custom user
keyring. There are two reasons for it:

The internal VK kernel key description can not be
acquired via API and it may change over time
(LUKS2 reencryption).

With recent SED OPAL support volume key becomes a 'blob'
containing up to two keys (dm-crypt key for SWE and key
for unlocking SED OPAL locking range). The internal
kernel key contains only dm-crypt (if required) but
custom user keyring needs to be provided with whole
volume key (blob).

Added user specified key description for the linked key
in custom user keyring. The linked key can be reached by
the specified description after successful activation (resume).
2023-09-25 18:59:09 +00:00
Ondrej Kozina
7ae109dccd Set correct volume key descripion when uploading key in keyring.
When key upload in kernel keyring is forced by CRYPT_ACTIVATE_KEYRING_KEY
flag it does not have to be the volume key assigned to default segment.
2023-09-25 18:59:09 +00:00
Ondrej Kozina
c16f644c9f Add helper utility to search only for keyrings. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
748cff228d Rename internal keyring utilities. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
f147c823ea Reduce code duplication in kernel keyring utilities. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
c497d8baa9 Drop redundant request_key call. 2023-09-25 18:59:09 +00:00
Ondrej Kozina
4872a14830 Fix wrong return value on error in keyring utils.
keyring_link_key_to_keyring_key_type could accidentaly
mask an unreachable key and make it look that key was
succesfully linked in custome keyring when it was not.
2023-09-25 18:59:09 +00:00
Milan Broz
b0610e1f73 Do not set flush and lockfs for DM device if resize grows the device.
Resize operation (crypt_resize) changes only size, so it is safe to
not flush IO (and  freeze fs with lockfs) during suspend/resume cycle.

For dm-integrity there can be two suspend/resume cycles as the subsequesnt
call sets recalculating flag.

Based on patch from Yury Vostrikov <mon@unformed.ru>

Resolves: #832
2023-09-20 15:30:10 +02:00
Milan Broz
1c7dd08c63 Try to sort options alphabetically. 2023-09-12 22:13:02 +02:00
Milan Broz
6df6ac49bf Remove dot from some option descriptions. 2023-09-12 22:13:00 +02:00
Milan Broz
1c31b93e5c Add --disable-blkid CLI option.
To be used with luksFormat if blkid fails for unknown reason.
2023-09-12 22:09:06 +02:00
Milan Broz
1969b6be2f Print blkid scan failure.
If old util-linux is used, blkid scan can fail because disk
is already locked for OPAL.
Do the same for other internal blkid issue.

Also add some debug messages to be clear what's going on.
2023-09-12 15:39:13 +02:00
Milan Broz
464fe987f9 Opal: print descriptive error if format locks the drive.
Some chipsets will set write-protection for the *full* drive
even if only small locking range is used.

As LUKS header expect to be writable ehen Opal LR is locked,
this is incompatible with LUKS.

Moreover, device need to be PSID reset and reconnected to clear
the flag. (And kernel lies about write protection so we cannot
get BLROGET ioctl to detect it.)

At least print some warning when LUKS2 header cannot be
written after Opal LR setup.

This applies for all USB adapters/firmware  with RTL9210 chipset.
(Need experimental patch to enable Opal through USB.)
2023-08-29 11:36:47 +02:00
Milan Broz
ab71eff3b9 opal: Remove key length debug msg. 2023-08-29 11:36:43 +02:00
Milan Broz
9b768cd401 Opal: add debug of Opal ioctl calls
This should print non-sensitive info only, no key info.
2023-08-29 11:36:39 +02:00
Milan Broz
c417c70a78 Opal: open device read-only as it is enough for ioctl.
This also solves the problem of using PSID reset
on write-protected device (some controllers lock the drive).
2023-08-29 11:36:35 +02:00
Milan Broz
8c87958b3b Fix unused symbol warnings in tests.
And actually fix two real bugs...
2023-08-28 12:43:42 +02:00
Milan Broz
81574d0f14 Enable -Wunused-parameter in CI tests. 2023-08-28 12:42:37 +02:00
Milan Broz
eb4a3f2904 Fix unused parameter warning in password utils. 2023-08-28 12:42:37 +02:00
Milan Broz
f18d370b4a Fix signed/unsigned warning in gcrypt backend. 2023-08-28 12:42:37 +02:00
Milan Broz
f70bf71dff Fix unused parameter in crypto backend handlers. 2023-08-28 12:42:37 +02:00
Milan Broz
5628de1f65 Fix unused parameter in LUKS2 reencryption handlers. 2023-08-28 12:42:37 +02:00
Milan Broz
ffd630973b Fix unused parameter in LUKS2 external tokens handlers. 2023-08-28 12:42:37 +02:00
Milan Broz
95425d45dd Fix unused parameter in blkid handlers. 2023-08-28 12:42:37 +02:00
Milan Broz
b31863c052 Fix unused parameter in keyring handlers. 2023-08-28 12:42:37 +02:00
Milan Broz
e14316f132 Mark unused parameters. 2023-08-28 12:42:37 +02:00
Milan Broz
54ada7b8e3 keyring: Fix possible sscanf string overflow.
Found by CodeQL.
2023-08-26 20:26:18 +02:00
Ondrej Kozina
e43de57fac Switch crypt_activate_by_signed_key to keyslot context based activation.
It introduces new keyslot context type CRYPT_KC_TYPE_SIGNED_KEY.
2023-08-16 14:17:34 +02:00
Ondrej Kozina
e5bd99665e Split volume key verification and device activation.
It makes key verification easier and also allows digest
verification for keys not assigned to device segment
(unbound keys) for more keyslot context types (tokens).
2023-08-16 14:17:34 +02:00
Daniel Zatovic
1aab3afcba Allow activation, resume and luksAddKey using VK stored in keyring.
Add --volume-key-keyring option, which takes a name of a key in keyring,
which will be used as a VK during device activation. The key can be
specified in keyctl-compatible syntax "%<key_type>:<key_name>".
2023-08-16 14:17:34 +02:00
Daniel Zatovic
d0ef2d84be Add tests for linking VK to a keyring and changing VK type.
Test various combinations of arguments for the options
--link-vk-to-keyring and --volume-key-type. Add API tests for the
crypt_set_keyring_to_link and crypt_set_vk_keyring_type functions.
2023-08-16 14:17:29 +02:00
Daniel Zatovic
6bcd9ed52c Add keyslot_context for volume key stored in a keyring. 2023-08-16 12:29:29 +02:00
Daniel Zatovic
1f2dac34d0 Support specifying keyring and key using keyctl syntax.
When using the --link-vk-to-keyring option, allow specifying the keyring
using the same syntax as keyctl (see "man keyctl"). E.g. "@u" for user
keyring and "%:testring" for a user-created keyring.
2023-08-16 12:29:29 +02:00
Daniel Zatovic
a674fb968c Support specifying volume key keyring type.
Currently only logon keyring type is supported. Add --volume-key-type to
allow specifying arbitrary type for the volume key.
2023-08-16 12:29:29 +02:00
Daniel Zatovic
138da3e73a Allow linking VK to a user-specified keyring.
Add a new API crypt_set_keyring_to_link nad CLI option
--link-vk-to-keyring. This allows the user to specify ID of the keyring
where the VK should be linked.
2023-08-16 12:29:29 +02:00
Daniel Zatovic
1b25cc5ed7 Don't revoke volume key in keyring.
Just unlink it from thread keyring where it is linked. The key should
get destroyed automatically once the reference count goes to zero, so
the revoke is redundant (unless there's a bug in the kernel keyring).

Note: the explicit revoke would destroy the key even when it is linked
to a user specified keyring.
2023-08-16 12:29:29 +02:00
Daniel Zatovic
cb184bcbb8 Allow resume by keyslot context. 2023-08-16 12:29:29 +02:00
Daniel Zatovic
aea21309ed Add keyring keyslot_context. 2023-08-16 12:29:26 +02:00
Daniel Zatovic
e2c413e5a9 Add tests for activation by keyslot context 2023-08-15 17:42:31 +02:00
Ondrej Kozina
cfbba1819b Add new token activation API tests. 2023-08-15 17:42:31 +02:00
Daniel Zatovic
58385d68d8 Allow activation via keyslot context. 2023-08-15 17:42:31 +02:00
Ondrej Kozina
28e1c95c22 Allow priority ignore keyslots with specific token or keyslot specified. 2023-08-15 17:42:31 +02:00
Ondrej Kozina
6751b43424 Allow keyslot in internal LUKS2 token activation code.
Extends code so that later API may support LUKS2 device
activation via token with specified keyslot.

Also allows testing if specific token is able to unlock specific
keyslot.
2023-08-15 17:42:31 +02:00
Ondrej Kozina
50207333f1 Fix a bug in LUKS2 header wipe function with keyslots area.
When formating LUKS2 device with no keyslots area (it's valid
LUKS2 header) there's a bug in wipe routine that is supposed
to wipe LUKS2 keyslots area. When the keyslots area size is of
zero length it causes wipe function to erase whole data device
starting at defined data offset.
2023-08-15 15:23:28 +02:00
Ondrej Kozina
b65fb6072e Do not mention --new-keyfile option in luksChangeKey action man page. 2023-08-15 15:23:17 +02:00
sad-goldfish
a7821c3d9e Add algorithm specification warning to integritysetup.8.adoc. 2023-08-03 06:57:50 +00:00
Brandon Enright
01f1512730 Minor reencrypt man page typo fixes 2023-08-02 20:01:25 +00:00
Ondrej Kozina
ef46ded7b4 Add OPAL2 detached header tests. 2023-08-02 13:46:46 +02:00
Ondrej Kozina
28da4ed72d Make luksErase work with detached header.
For it to work correctly with LUKS2 OPAL we have to
set data device properly so it can erase OPAL locking
range (or revert via PSID).
2023-08-02 13:46:46 +02:00
Ondrej Kozina
e1d494c4e1 Fix LUKS2 OPAL deactivation when header is missing.
When no header is available but LUSK2_OPAL dm uuid
prefix is detected try to lock opal locking range
upon LUKS2 device deactivation (best effort only as
in crypt_suspend).
2023-08-02 13:46:46 +02:00
Ondrej Kozina
5cf9e28530 Do not set default data offset with LUKS2 OPAL detached header. 2023-08-01 16:39:27 +02:00
Ondrej Kozina
570d3ad4e4 Add support for suspend/resume with LUKS2 OPAL2 devices. 2023-08-01 16:39:27 +02:00
Ondrej Kozina
b60ffe9e06 Introduce LUKS2-OPAL private dm uuid prefix.
LUKS2 devices with configured HW OPAL encryption (any configuration)
get activated with private dm uuid prefix LUKS2-OPAL so that we
can properly detect devices with HW OPAL encryption even with
missing LUKS2 header (detached header). Internally LUKS2-OPAL
prefix matches LUKS2 device type.
2023-08-01 16:36:26 +02:00
Ondrej Kozina
fc04761cdc Check dm uuid matches LUKS metadata during crypt_suspend. 2023-08-01 16:36:24 +02:00
Ondrej Kozina
0a805d325c Do not reinitialize dm backend when not needed.
device-mapper backend gets initialized with crypt_device
structure and it cannot be NULL in crypt_suspend.
2023-07-26 15:38:14 +02:00
Ondrej Kozina
ad3013dfe4 Simplify crypt_get_hw_encryption_type internals.
Do not take into account cipher specification and rely
solely on segment type in LUKS2 metadata.
2023-07-18 16:29:19 +02:00
Milan Broz
7754660409 Fix leak of volume key in activation code error path. 2023-07-18 12:01:56 +02:00
Milan Broz
928061f1f0 Print better metadata dump and status info for OPAL segment. 2023-07-17 22:39:26 +01:00
Ondrej Kozina
4d487d5dcf Properly handle authenticated encryption on OPAL device. 2023-07-17 22:39:26 +01:00
Milan Broz
33bf0c6ae9 opal: Limit sector size to maximum 4096 bytes.
Some devices support 16k optiomal size, but dm-crypt
has limit 4k.
2023-07-17 22:39:26 +01:00
Luca Boccassi
b7c361df94 man: document OPAL support
Signed-off-by: Luca Boccassi <bluca@debian.org>
2023-07-17 22:39:26 +01:00
Ondrej Kozina
ace8b8578c Add OPAL2 basic test. 2023-07-17 22:39:26 +01:00
Luca Boccassi
decbe09fb3 cryptsetup: support for hw-opal in luksErase
Wipe and disable the segment. Also support the factory reset ioctl for
a complete wipe of the entire drive with a specific argument.

Signed-off-by: Luca Boccassi <bluca@debian.org>
2023-07-17 22:39:26 +01:00
Milan Broz
5716f959a7 Add crypt_get_hw_encryption_type API call. 2023-07-17 22:39:26 +01:00
Luca Boccassi
446ad76011 cryptsetup: add --hw-opal and --hw-opal-only
Signed-off-by: Luca Boccassi <bluca@debian.org>
Co-authored-by: Ondrej Kozina <okozina@redhat.com>
2023-07-17 22:39:26 +01:00
Luca Boccassi
b9cc0129c9 libcryptsetup: add OPAL type and params
Signed-off-by: Luca Boccassi <bluca@debian.org>
Co-authored-by: Ondrej Kozina <okozina@redhat.com>
2023-07-17 13:14:52 +02:00
Ludwig Nussel
fc4151f77e Fix option name in error output 2023-06-28 14:10:03 +02:00
Milan Broz
b8711faf92 Fix activation of LUKS2 with capi format cipher and kernel crypt name.
While activation of internal cipher algorithms (like aes-generic)
is disallowed, some old LUKS2 images can still use it.

Check the cipher in activate call, but allow to load LUKS2 metadata.
This can allow to add repair code easily and also allow luksDump.

Also fix segfault in reencrypt code for such a header.

Fixes: #820
2023-06-26 13:26:13 +02:00
Milan Broz
1f01eea60e Fix reencryption to fail properly for unknown cipher.
crypt_get_cipher and crypt_get_cipher mode can return NULL,
check it in advance.
2023-06-26 13:25:59 +02:00
Ondrej Kozina
10847d7100 Create optional reduced dm-integrity device.
This enables creating dm-integrity devices that
does not use all available space but only initial
part of the device.

This will be used with future hw-opal-crypt segment
where partion may be not aligned to locking range
alignment and needs to be reduced.

We dont't want to span dm-integrity device into
area not included in opal locking range.
2023-06-22 14:43:19 +00:00
Milan Broz
e13840c5cb tcrypt: Fix test in FIPS mode. 2023-06-22 16:41:33 +02:00
Milan Broz
9c5f555930 tcrypt: Support new Blake2 hash.
VeraCrypt 1.26.2 introduces support for Blake2 PRF for PBKDF2.
This patch adds support for cryptsetup.
2023-06-22 08:46:38 +00:00
Milan Broz
33a3d1ba7b tcrypt: use hash values as substring if limiting KDF check.
This allows to specify --hash sha or --hash blake2 to limit
KDF without need to specify full algorithm name
(similar to cipher where we already use substring match).
2023-06-22 08:46:38 +00:00
Milan Broz
53aa5f6c4f Fix init_by_name to allow unknown cipher format in dm-crypt as null context.
Deactivation code should deactivate dm-crypt device even if it is unknown
for libcryptsetup. Previous fix for cipher specification was too strict.

Let's allow initialization as null context, that allow status and
deactivate to be usable again.
2023-06-22 08:46:06 +00:00
Ondrej Kozina
2712882aa3 Add helper function to change segment size. 2023-06-06 13:44:44 +00:00
Milan Broz
5042ec2cd0 Use unconditionally sleep 1 in scsi_debug test 2023-06-04 11:59:05 +02:00
Ondrej Kozina
d6107bf241 Refactor json_segment_create_crypt helper.
Refactor crypt segment json helper body into
separate routine so that it can be reused later
in future hw-opal-crypt segment helper.
2023-05-29 11:09:04 +02:00
Ondrej Kozina
47ac021c03 Refactor LUKS2 encryption parameters verification.
Code verifying encryption parameters needs to be reusable
for new code that will be added later.

Also due to previous changes to data offset and metadata size
calculations, encryption parameters can now be verified at
single place without need to split it over crypt_format_luks2
routine.
2023-05-29 11:09:04 +02:00
Ondrej Kozina
969e67e743 Use defined constant for cipher_spec buffer size. 2023-05-29 11:09:04 +02:00
Ondrej Kozina
6a8fa14007 Move cipher parsing outside LUKS2 header generator function.
Let's make LUKS2_generate_hdr as clean as possible. Cipher
specification string can be constructed in upper layers.

This will make future LUKS2_generate_hdr extension easier.
2023-05-29 11:09:04 +02:00
Ondrej Kozina
fd91de82ad Move integrity fields in json_segment_create_crypt segment helper.
The integrity is optional parameter of dm-crypt segment definition.
Move the low level json code in appropriate json helper.

It will make adding new segment easier. The future hw-opal-crypt
segment will inherit all crypt fields.
2023-05-29 11:09:04 +02:00
Ondrej Kozina
926679f7f1 Refactor LUKS2 metadata parameters calculations.
Move all metadata size and data offset calculations
logic away from LUKS2_generate_hdr. The function
was meant to generate solely LUKS2 header on disk json
format.

The aim is to have all logic related data offset and metadata
size in one place available to be calculated in advance so
that we can easily extend the code.
2023-05-29 11:08:29 +02:00
Ondrej Kozina
11d8c58c72 Fix wrong return value from LUKS2_generate_hdr on error.
On rare occasion (low memory) the function could return success
even though LUKS2 json metadata could be assembled properly.
2023-05-24 17:46:19 +02:00
Daniel Zatovic
716cf78da6 CI: Add apt-get update to Debian jobs. 2023-05-24 13:20:41 +02:00
Milan Broz
dff9ee8c8c Also disallow active devices with internal kernel names.
The same problem fixed in commit 438cf1d1b3
is present in libdevmapper wrapper when parsing active device table.

The whole point of conversion was that non-authenticated modes
can be always represented in the old cipher-mode-iv format.
As the internal names contains dash, these are unsupported.

That said, the libdevmapper backend now correctly returns
full cipher specification including capi prefix for this case.

Init_by_name call now fails with incomplatible cipher definition error.
2023-05-02 15:42:21 +02:00
Milan Broz
80a001232f tests: Fix memory leak introduced in previous patches. 2023-05-02 14:52:17 +02:00
Milan Broz
841c681825 Workaround for oss-fuzz build. 2023-04-29 16:28:29 +02:00
Milan Broz
438cf1d1b3 Disallow use of internal kenrel crypto driver names in "capi" specification.
The common way to specify cipher mode in cryptsetup
is to use cipher-mode-iv notation (like aes-xts-plain64).
With introduction of authenticated ciphers we also allow "capi:<spec>"
notation that is directly used by dm-crypt (e.g. capi:xts(aes)-plain64).

CAPI specification was never intended to be used with internal
kernel crypto api names (with dash in algorithm name), actually the
whole parsing routine wrongly parses mode here now.

The code not checks if parsing wrongly separated the full cipher
string and effectively allowing only proper cipher names
(example of no longer supported string is capi:xts(ecb(aes-generic))-plain64).

Thanks to Jan Wichelmann, Luca Wilke and Thomas Eisenbarth from
University of Lübeck for noticing the problems with this code.

Fixes: #809
2023-04-25 18:56:31 +02:00
Milan Broz
91d8ab7f20 Add Aria cipher support and block size info.
Aria cipher is similar to AES and is supported
in Linux kernel crypto API in recent releases.
This patch just add support for internal info table.
(This will cause that it is used also for keyslot
encryption if specified as a cipher argument.)
2023-04-24 19:29:08 +02:00
Milan Broz
d173514b81 Do not decrease PBKDF parameters if a user forces them.
If a user explicitly specifies PBKDF parameters (like iterations,
used memory of threads), do not limit them, even if it can cause
resource exhaustion.

The only limits are hard limits per the PBKDF algorithm.

The force options were mostly used for decreasing parameters,
but it should work even opposite - despite the fact it can mean
shooting yourself in the foot (OOM).

Fixes: #812
2023-04-24 13:09:34 +02:00
Milan Broz
9a92c6a677 Fix PBKDF vector test in FIPS mode.
Another example of FIPS theatre is that some vendors
implements hard limits for PBKDF attributes
(minimal password length, salt, etc).

This should be set by policy on another layer,
unfortunately someone apparently thinks it is a good idea
to harcode it to low-level crypto library directly.

This of course breaks some older test vectors
that use shorter attributes.

Just mark these and ignore possible API error in FIPS mode.
2023-04-20 23:20:47 +02:00
Milan Broz
6721d3a8b2 Use only half of detected free memory on systems without swap.
As tests shows, limiting used Argon2 memory to free memory on
systems without swap is still not enough.
Use just half of it, this should bring needed margin while
still use Argon2.

Note, for very-low memory constrained systems user should
avoid memory-hard PBKDF (IOW manually select PBKDF2), we
do not do this automatically.
2023-04-19 13:28:15 +00:00
Milan Broz
7893c33d71 Check for physical memory available also in PBKDF benchmark. 2023-04-19 13:28:15 +00:00
Milan Broz
23dd988545 Fix PBKDF2 vectors test for RHEL8 OpenSSL.
Seems someone clever had an idea to return hash output
through API size even the hash is actually not available
in FIPS mode.

Just check also hash init in this case (as we already
do elsewhere).
2023-04-19 10:55:35 +00:00
Ondrej Kozina
c81c3d1fc0 Remove unused code in reencryption. 2023-04-19 10:01:51 +02:00
Milan Broz
7859673bd2 Support OpenSSL 3.2 Argon2 implementation. 2023-04-19 07:16:08 +00:00
Milan Broz
34953cb10f Add support for Argon2 from libgcrypt.
Argon2 is available since version 1.10, but we need version
that allows empty passwords (1.11).
2023-04-19 07:15:35 +00:00
Vojtech Trefny
bc426bba67 bitlk: Fix segfaults when attempting to test volume key
Also clarify that checking the volume key is not possible for
BITLK in the docstring and man page.

Fixes: #810
2023-04-18 16:38:58 +02:00
Alex Xu (Hello71)
234ca010e2 Link only libcrypto from openssl
Reduces initramfs dependencies. libcrypto.pc is available in openssl
0.9.8+
2023-04-18 07:49:28 +00:00
Alex Xu (Hello71)
32febb4483 configure.ac: remove += bashism
Fixes: c1302555b7 ("Provide pkgconfig Require.private.")
2023-04-17 12:31:55 -04:00
Ondrej Kozina
b6eaa236bc Fix fips mode detection in gcrypt backend.
gcry_fips_mode_active must not be called before
gcry_check_version. Let's initialize backend in
before fips mode detection if it needs to.
2023-04-13 13:20:49 +00:00
Milan Broz
a617c23ccc Disable reencryption for DAX devices.
Device-mapper is not capable to stack DAX/non-DAX devices
in mapping table, so online reencryption cannot work.

Fixes: #760
2023-03-31 10:51:34 +00:00
Milan Broz
e4c2aa64b5 Detect DAX devices and and warn in LUKS format.
DAX / persistent memory devices do not provide atomic sector updates,
any single modification can corrupt the whole encryption block.
2023-03-31 10:51:34 +00:00
Milan Broz
2a2027ee3e Print message if device is not aligned to sector size.
If a partition is resized after format, activation could
fail when the device is not multiple of a sector size.

Print at least warning here as the message is only in syslog.

Related to Issue #807
2023-03-31 08:52:52 +00:00
Milan Broz
192ff16cd8 Fix fuzz tests build. 2023-03-18 11:16:22 +01:00
Milan Broz
17a0b1e2d3 Remove testing branch from CI script. 2023-03-10 18:09:24 +01:00
Milan Broz
c2045b9585 Update CodeQL config. 2023-03-10 11:41:51 +01:00
Milan Broz
9d5e45be54 Add header guard to ssh-utils.h. 2023-03-10 11:41:47 +01:00
Milan Broz
d4840d46e1 Do not overload global crc32 table name by a function parameter name. 2023-03-10 11:41:43 +01:00
Milan Broz
cca490a0b8 test: Do not overload global crypt_device variable name. 2023-03-10 11:41:33 +01:00
Milan Broz
a752e571ab reencrypt: fix checking of context name arguments. 2023-03-09 17:06:58 +01:00
Milan Broz
d209bb27b4 User more restrictive attributes for device file lock. 2023-03-09 16:55:46 +01:00
Milan Broz
ccf48bb28e tests: avoid possible overflow in multiplication
We need to operate in 64bits uint here.
2023-03-09 16:32:37 +01:00
Milan Broz
76c0a81318 tests: reserve one byte for trailing zero in global log buffer 2023-03-09 16:28:36 +01:00
Milan Broz
b297b59ba2 bitlk: avoid use ctime() with pointer to shared memory.
Use own buffer with ctime_r() is more secure.
2023-03-09 16:22:53 +01:00
Daniel Zatovic
f686fc7108 meson: Add dist hook only when asciidoctor is found.
Avoid attempting to use non-discovered program.
2023-03-09 14:40:26 +00:00
Ondrej Kozina
9a96e260aa Fix unlikely occurences of json_object leaks on error path.
In most cases it relates to error path triggering on general OOM.
2023-03-08 15:23:32 +01:00
Ondrej Kozina
cb177c5076 Improve code clarity a bit.
It also silences false positive warning with older compilers.
2023-03-08 15:23:32 +01:00
Ondrej Kozina
4ebc6a1616 Correct error paths in LUKS2 reencryption code path. 2023-03-08 15:23:25 +01:00
Ondrej Kozina
1c65c1c3d1 Add json_object_object_add_by_uint_by_ref helper.
Function is similar to json_object_object_add_by_uint but
it unsets *jobj_val_ref pointer if the function ends with
success.

It helps to create cleaner error patch and avoids eventual
double free corruption if **jobj_val_ref object changed
ownership.
2023-03-08 15:12:45 +01:00
Milan Broz
b12e9534c3 Replace LGTM with GitHub CodeQL.
Many warnings silenced for now.
2023-03-07 13:51:04 +01:00
Milan Broz
8b3162069e CI: move autogen.sh to specific build scripts.
It seems that autogen.sh is not called in some situations
(merge request updating configure scripts).

Let's move this directly before configure.
Also print disable-<feature> options to CI output.
2023-03-06 10:16:31 +00:00
Milan Broz
27f8e5c08f Print warning when keyslot requires more memory than available
This warning is displayed only if maximum memory was adjusted:
no swap, not enough memory, but is not printed if user set keyslot
memory cost above default limit intentionally.

In the latter case we have to check all available memory and guess
if swap is enough - this is not job af cryptsetup and also
it should not excessively parse any /sys files during keyslot open.
2023-03-04 20:06:11 +01:00
Milan Broz
899bad8c06 Try to avoid OOM killer on low-memory systems without swap.
Benchmark for memory-hard KDF is tricky, seems that relying
on maximum half of physical memory is not enough.

Let's allow only free physical available space if there is no swap.
This should not cause changes on normal systems, at least.
2023-03-04 20:06:11 +01:00
Milan Broz
62aa392205 Improve README.md.
Rebased changes from patch (MR !480) by Anthony D'Atri
(and some other minor changes).
2023-03-04 19:51:54 +01:00
Milan Broz
428c2f323b fuzz: Do not calculate checksum for too small headers.
LUKS2 header must be at least binary header size.
2023-03-03 20:24:37 +01:00
Milan Broz
045ed9d485 Update devel version. 2023-03-03 14:50:55 +01:00
Daniel Zatovic
114a13af84 Add support for meson build system.
For now, let's keep support for both - autotools and meson.
2023-03-03 13:49:47 +00:00
Milan Broz
9d5327c37b Fix sector_size display for non-LUKS2 crypt devices. 2023-02-21 08:32:39 +00:00
Milan Broz
1d109a114c Fix integrity info display for non-LUKS2 crypt devices. 2023-02-21 08:32:39 +00:00
Milan Broz
e455110c8e Fix crypt_init_by_name() for dm-crypt with integrity.
Initialization by name for dm-crypt with integrity is always
underlying device for dm-integrity target, not dm-integrity
device itself.

This fixes various problems like refresh command or
device printed in status command.

Fixes: #801
2023-02-21 08:32:39 +00:00
Daniel Zatovic
e244c8c543 CI: upgrade csmock image to RHEL 9. 2023-02-20 19:23:07 +01:00
Daniel Zatovic
384b7f2e94 fuzzing: Fix OSS-Fuzz static build script.
The scrip for building dependencies statically still builds popt as a
shared library. The libdevmapper library is installed manually, but
incorrectly (libdevmapper.pc is installed, but it should be
devmapper.pc).
2023-02-15 14:48:02 +01:00
wangzhiqiang
1f805cb35a Update file cryptsetup-ssh.c 2023-02-10 16:48:19 +00:00
wangzhiqiang
ec0efe7068 fix potential null pointer dereference.
Signed-off-by: wangzhiqiang <wangzhiqiang95@huawei.com>
2023-02-10 19:49:48 +08:00
Milan Broz
4fc619853d Version 2.6.1. 2023-02-09 17:12:17 +01:00
Milan Broz
72f799b393 Update Copyright year. 2023-02-09 17:11:18 +01:00
Milan Broz
5d622102c6 Some more cleanup of Release notes. 2023-02-09 13:43:29 +01:00
Ondrej Kozina
93c5013577 Clarify when cryptsetup asks for LUKS2 token PINs. 2023-02-09 12:40:50 +00:00
Milan Broz
83d3c04347 Reformat and cleanup README. 2023-02-09 12:28:53 +01:00
Milan Broz
53668a0203 Add 2.6.1 Release notes. 2023-02-08 17:05:34 +01:00
Yuri Chornoivan
fcf2ce9073 po: update uk.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Yuri Kozlov
9364fd5931 po: update ru.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Remus-Gabriel Chelu
f5253e6826 po: update ro.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Hiroshi Takekawa
f697444d14 po: update ja.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Frédéric Marchal
06b52c83b3 po: update fr.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Roland Illig
18a7427bad po: update de.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Petr Pisar
23dfb78823 po: update cs.po (from translationproject.org) 2023-02-06 10:37:13 +01:00
Milan Broz
5da3fd8622 Prepare 2.6.1-rc0 version. 2023-02-01 16:03:00 +01:00
Milan Broz
8b90d16762 Add fuzz patch file to tarball. 2023-02-01 16:02:26 +01:00
Milan Broz
31fe5ccd19 Update po/LINGUAS. 2023-02-01 15:57:27 +01:00
Remus-Gabriel Chelu
4339dd0bff po: add ro.po (from translationproject.org) 2023-02-01 15:54:12 +01:00
Temuri Doghonadze
7e6b8fc0d7 po: add ka.po (from translationproject.org) 2023-02-01 15:54:12 +01:00
Milan Broz
ace015a3e5 Fix OpenSSL < 2 crypto backend PBKDF2 possible iteration count overflow.
For OpenSSL2, we use PKCS5_PBKDF2_HMAC() function.
Unfortunately, the iteration count is defined as signed integer
(unlike unsigned in OpenSSL3 PARAMS KDF API).

This can lead to overflow and decreasing of actual iterations count.
In reality this can happen only if pbkdf-force-iterations is used.

This patch add check to INT_MAX if linked to older OpenSSL and
disallows such setting.

Note, this is misconception in OpenSSL2 API, cryptsetup internally
use uint32_t for iterations count.

Reported by wangzhiqiang <wangzhiqiang95@huawei.com> in cryptsetup list.
2023-02-01 13:12:02 +01:00
Daniel Zatovic
5ed0358f12 fuzzing: Fix protobuf fuzzer errors when using MSAN
Patch libprotobuf-mutator to unpoison buffers obtained from libfuzzer
via LLVMFuzzerMutate. This is required as libfuzzer is usually not
compiled with memory sanitizer support (not even in OSS-Fuzz project,
see https://github.com/google/oss-fuzz/issues/864). Therefore, we
manually mark the buffer as initialized using __msan_unpoison.

Fixes OSS-fuzz bug 52541, 52543 and 52533.
2023-01-31 23:45:34 +01:00
Milan Broz
5a33f1dc9a Add asciidoctor to compilation requirements in Readme. 2023-01-24 13:16:45 +01:00
Daniel Zatovic
ae80dc0e8e CI: add compilation tests with various disable options 2023-01-20 14:37:28 +00:00
Daniel Zatovic
3f6d5470e3 Fix compilation warning with disabled keyring. 2023-01-20 14:34:14 +01:00
Ondrej Kozina
4cd8d1efdb Fix api test on kernels with capi format support. 2023-01-19 11:50:48 +01:00
Milan Broz
48d6f85cc3 bitlk: fix printf debug message
Fixes Coverity warning.
2023-01-18 13:55:03 +01:00
Ondrej Kozina
5216002773 Use ISO C compliant inline assembly with supported compilers.
When compiled with enforced ISO C (e.g. -std=c11) 'asm' inline
does not compile (it's GNU extension). Use __asm__ inline assembly
with GCC and clang compliers instead.

Fixes: #786.
2023-01-18 08:59:58 +00:00
Milan Broz
482c819ea2 fvault2: fix compilatioon with very old uuid.h
UUID_STR_LEN is undefined for old headers, just
use internal definition (both are 37 bytes).
2023-01-17 13:32:29 +00:00
Milan Broz
0622b51634 verity: fix hash offset 64bit values
Hash offset is 64bit values, for some reason it is
used as size_t on one place. Fix it by properly use uint64_t.

Fixes: #792
2023-01-17 13:16:30 +01:00
Daniel Zatovic
7bbfccbbfa fuzzing: update script to build popt using CMake
Popt library removed support for autotools build system and can be built
only using CMake.
2023-01-11 14:02:47 +01:00
Milan Broz
7c25db5bf3 bitlk: fix possible leak of description
If metdata contains more than one description fields,
use just the first one.

Fixes OSS-fuzz bug 54682.
2022-12-30 13:47:20 +01:00
Milan Broz
034041a922 bitlk: clean formatting to use tabs 2022-12-29 01:02:24 +01:00
Milan Broz
776baf4ccc bitlk: fix use of startup BEK key on big-endian platform
The version and metadata size is stored as little-endian.
2022-12-29 01:02:20 +01:00
Milan Broz
d1a607e0b2 bitlk: harden parsing of metadata entries (for vmk and description entry)
For broken metadata BITLK format parsing can cause crash or out of memory
on several places.

Add better size checks to avoid parsing such a metadata.
Also be aware that entry_size can be smalle (so minus operation can underflow).

Also fix memory leak if FVEK entry is more than once in metadata
(just use the first entry and ignore others).
2022-12-29 01:02:05 +01:00
Milan Broz
1682e72bf5 bitlk: harden parsing of metadata entries
For broken metadata BITLK format parsing can cause crash or out of memory
on several places.

Add better size checks to avoid parsing such a metadata.

Fixes OSS-fuzz bug 54548,54553,54559.
2022-12-25 21:34:34 +01:00
Khem Raj
8e7f07841e Replace off64_t with off_t
AC_SYS_LARGEFILE autoconf macro is in use in configure script which will
add needed feature macros on commandline to enable 64bit off_t.

Also replace lseek64 with lseek, since it will be same when
_FILE_OFFSET_BITS=64 is defined on relevant platforms via AC_SYS_LARGEFILE

This fixes build with latest musl, where LFS64 interfaces are moved out
of _GNU_SOURCE feature test macros namespace [1]

[1] https://git.musl-libc.org/cgit/musl/commit/?id=25e6fee27f4a293728dd15b659170e7b9c7db9bc

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2022-12-23 15:49:00 +01:00
David Flor
50e8879528 fuzzing: add new fuzzer for fuzzing multiple types at once
* added fuzz target 'crypt2_load_ondisk_fuzz' that tries to load fuzz input as LUKS1, FileVault2, BitLocker in that order.
* added dictionary for this fuzz target
* added fuzz target to relevant files
2022-12-23 15:00:01 +01:00
Ondrej Kozina
c18dcfaa0b Abort encryption when header and data devices are same.
If data device reduction is not requsted this led
to data corruption since LUKS metadata was written
over the data device.
2022-12-14 09:52:19 +01:00
Ondrej Kozina
be088b8de8 Enable crypt_header_is_detached for empty contexts.
Also changes few tests now expecting crypt_header_is_detached
works with empty contexts.
2022-12-14 09:52:19 +01:00
Milan Broz
de221b4ea7 Fix typo in comment. 2022-12-08 14:17:50 +01:00
Milan Broz
170161b9b6 Free all possible allocated params if crypt_load() fails.
If format load fails in some intermediate step, the internal
params struct can contain already set values.
While context is set still to none type, it can cause segfault
in releasing active_name.

(Found by fuzzing target processing crypt_load.)
2022-12-08 14:17:44 +01:00
Milan Broz
a649d734b6 Let crypt_set_null_type wipe whole context always.
We have to be sure that after setting new type some
union is not misused.
2022-12-08 13:02:18 +01:00
Milan Broz
15c998d523 Move crypt_free_type and allow force type override.
Will be used later on error path.
2022-12-08 13:02:18 +01:00
Ondrej Kozina
14eff9480d Change tests to use passphrases with minimal 8 chars length.
Skip tests that can not satisfy minimal test passphrase length:

- empty passphrase
- LUKS1 cipher_null tests (empty passphrase is mandatory)
- LUKS1 encryption
2022-12-08 11:03:09 +00:00
Ondrej Kozina
4621580802 Run PBKDF benchmark with 8 bytes long well-known passphrase. 2022-12-08 11:03:09 +00:00
Milan Broz
4bede447c8 Set devel version. 2022-12-08 11:48:28 +01:00
Milan Broz
b08212ea45 Version 2.6.0. 2022-11-28 12:27:33 +01:00
Milan Broz
5a976ad1d9 Do not log score from pwquality.
This information is really not needed in debug log.
2022-11-28 10:37:58 +01:00
Yuri Kozlov
0e4182874b po: update ru.po (from translationproject.org) 2022-11-27 23:20:25 +01:00
Milan Broz
487e85fdec Wipe buffers to be sure padding is always empty.
Detected by valgrind as writing unitialized data.
2022-11-27 23:18:36 +01:00
Milan Broz
32344d5a84 tests: fix reencryption-mangle test valgrind log name.
Use the same logic as in compat-test (just the line
number is the last one for cryptsetup_raw).
2022-11-27 21:02:49 +01:00
Milan Broz
ebb16a511c tests: fix list of valgrind tests
FVAULT2 test was missing; systemd test does not support valgrid yet.
2022-11-27 19:48:57 +01:00
Milan Broz
51200eb6da tests: do not require build tools for localtest in systemd plugin test
Fo localtest we use installed binaries, only checkprograms need to be build.
2022-11-24 16:37:38 +01:00
Milan Broz
119c57e00e tests: remove stray backslash in grep expression 2022-11-24 15:01:47 +01:00
Milan Broz
700b0f6e36 tests: do not run systemd plugin test without fake tpm path
We want to avoid touching real TPM during test.
2022-11-24 15:00:19 +01:00
Milan Broz
8fff498062 tests: compile fake_tpm_path util also for localtest
Otherwise TPM_PATH will not be used.
2022-11-24 14:54:18 +01:00
Milan Broz
2ef2f6017d Update release notes. 2022-11-24 13:49:27 +01:00
Ondrej Kozina
cdfa213ad0 Allocate internal buffer in LUKS2 keyring token with crypt_safe_alloc.
With changes in db65a5ceac and subsequent
drop of library memlock_all we should lock keyring key material buffer
in memory system memory as well.
2022-11-24 09:03:29 +00:00
Milan Broz
dab00bfd4f CI: use libsepol-dev for Debian based distros.
Seems libselpol1-dev is disappearing.
2022-11-23 11:57:59 +00:00
Ondrej Kozina
c018558f2d Remove unused define CRYPT_KC_TYPE_UNDEFINED.
The defined was not yet released in stable version.
2022-11-23 11:08:55 +01:00
Milan Broz
3633b81909 CI: fix GutHub action install script 2022-11-22 16:38:10 +01:00
Yuri Chornoivan
b23a02b05c po: update uk.po (from translationproject.org) 2022-11-22 16:17:48 +01:00
Jakub Bogusz
347c39ca97 po: update pl.po (from translationproject.org) 2022-11-22 16:17:48 +01:00
Hiroshi Takekawa
2d1f1833e8 po: update ja.po (from translationproject.org) 2022-11-22 16:17:48 +01:00
Frédéric Marchal
7f09ab67e2 po: update fr.po (from translationproject.org) 2022-11-22 16:17:48 +01:00
Roland Illig
f5fb1f1b94 po: update de.po (from translationproject.org) 2022-11-22 16:17:48 +01:00
Petr Pisar
005141554f po: update cs.po (from translationproject.org) 2022-11-22 16:17:48 +01:00
Ondrej Kozina
cd8f80b7ee Clarify type requirements in crypt_volume_key_get_by_keyslot_context. 2022-11-21 15:56:14 +01:00
Milan Broz
c7bbae01a6 Fix some strings for translations.
No need to translate debug strings.
Fix spaces in key slot queries.
2022-11-20 12:36:26 +01:00
Milan Broz
257bc80ae9 Version 2.6.0-rc0. 2022-11-18 22:32:47 +01:00
Milan Broz
6c2e64bf75 fvault2: fix typo 2022-11-18 22:25:31 +01:00
Milan Broz
942cea1803 Update pot file. 2022-11-18 22:22:06 +01:00
Milan Broz
e7eab5fec2 Prepare version 2.6.0-rc0. 2022-11-18 22:02:44 +01:00
Ondrej Kozina
b0779c6529 Fix --disable-luks2-reencryption configuration option. 2022-11-18 16:40:48 +01:00
Milan Broz
37d045df00 fvault2: add basic info to cryptsetup man page 2022-11-18 15:27:00 +01:00
Milan Broz
4b95f36804 Fix possible undefined use od preprocessor.
Mixing preprocessor #if and code is undefined behavior in general,
rewrite tools_package_version to not use it.
2022-11-18 14:50:34 +01:00
Milan Broz
faf3b27f51 fvault2: reduce debug log, do not print ignored metadata blocks 2022-11-18 14:31:25 +01:00
Josef Andersson
c85d1351ea po: update sv.po (from translationproject.org) 2022-11-18 14:25:40 +01:00
Мирослав Николић
3b18fe2b23 po: update sr.po (from translationproject.org) 2022-11-18 14:25:40 +01:00
Milan Broz
e96588b8b5 Check and allocate header early so wipe fails only for IO errors.
The device_check is done in header write functions,
but these are not recached in normal format path as wipe call
is called earlier.

Call the device check also from wipe function to get better error
description.

This situation happens for example when a block device is too small
(regular file can be enlarged by falloc(); block device cannot).
2022-11-18 13:03:52 +00:00
Milan Broz
c31494abc6 Print warning early if LUKS container is too small for activation.
Activation with header only fails too late (in device-mapper
call) while it is clear from the beginning that it cannot succeed.

Just add an early and better worded error.

Ignore this situation for block device (we have to call ioctl to get size).
The most common case is a file container here anyway.

For block devices it fails during activation later.
2022-11-18 13:03:52 +00:00
Milan Broz
819902a33a Add a better warning if luksFormat ends with image without any space for data.
Header write can call falloc() to increase image size, so we should
check data offset after header is written.

Also change wording to be less cryptic and describe what is the real problem.

Note that the code can be used this way to crate detached header (without
space for data), so it is not an error.
2022-11-18 13:03:52 +00:00
Daniel Zatovic
395beb635c Speed up tests using faster hash and PBKDF options.
Use faster SHA1 instead of SHA256 in reencryption test and pass fast
PBKDF options in mode-test.
2022-11-18 11:08:31 +00:00
Ondrej Kozina
81c56a8395 Move assert include in internal header files. 2022-11-16 16:54:33 +01:00
Milan Broz
3333f3e9bb Fix some warning detected by Coverity.
The FVAULT2 block is always 8192 bytes (for CRC), but used
struct is smaller. Let's not confuse struct size with whole block.
2022-11-15 10:47:22 +01:00
Milan Broz
b086430877 fvault2: Move messages to debug level and add more debug log. 2022-11-14 21:50:18 +01:00
Milan Broz
01f3f3e66c fvault2: volume size can be unsigned 64bit 2022-11-14 21:50:18 +01:00
Milan Broz
e37d8bdf91 fvault2: harden device offset check
Check if value overflows and do not allow reading
metadata block exceeding fixed offset.
2022-11-14 21:50:18 +01:00
Milan Broz
8b4a5e5931 fvault2: some more code cleanup. 2022-11-14 21:50:18 +01:00
Milan Broz
33d8d19408 fvault2: passphr -> passphrase 2022-11-14 21:50:18 +01:00
Milan Broz
9bb98d49c0 fvault2: some minor code reformatting changes. 2022-11-14 21:50:18 +01:00
Pavel Tobias
1c5fd5ae10 Fvault2: add basic error logs 2022-11-14 21:50:18 +01:00
Milan Broz
3d1b965c46 fvault2: fix --test-passphrase option 2022-11-14 21:50:18 +01:00
Milan Broz
2770273582 fvault2: test volume key dump 2022-11-14 21:50:18 +01:00
Milan Broz
f6b6e41951 fvault2: Add a basic man page. 2022-11-14 21:50:18 +01:00
Milan Broz
03059fae75 tests: add valgrind support to fvault2 test. 2022-11-14 21:50:18 +01:00
Pavel Tobias
ba9757b14b Fvault2: add basic test 2022-11-14 21:50:18 +01:00
Pavel Tobias
cd5bd1c773 Fvault2: store UUIDs in text format 2022-11-14 21:50:18 +01:00
Vojtech Trefny
a5c7bba6ee Add missing support for fvault2 commands 2022-11-14 21:50:18 +01:00
Vojtech Trefny
4bce6d5962 Show error when trying to run fvault2Dump on a non-fvault device 2022-11-14 21:50:18 +01:00
Pavel Tobias
cb9deaf354 Fvault2: implement open 2022-11-14 21:50:18 +01:00
Pavel Tobias
0ce5de9c1c Fvault2: implement dump 2022-11-14 21:50:18 +01:00
Pavel Tobias
35071c6d50 Fvault2: derive volume key 2022-11-14 21:50:18 +01:00
Pavel Tobias
af6ea01997 Fvault2: read all relevant metadata from device 2022-11-14 21:50:18 +01:00
Pavel Tobias
1d5d6d73a5 Add support for CRC-32C (Castagnoli polynomial) to lib/crypto_backend 2022-11-14 21:50:18 +01:00
Pavel Tobias
1ffc9d967c Fvault2: prepare module in libcryptsetup 2022-11-14 21:50:18 +01:00
Milan Broz
1f4c7a83f9 Annotate some functions to prevent Coverity tainted input error.
These errors are really annoying, just silence them.
2022-11-14 13:05:04 +00:00
Milan Broz
f312ba6256 Fix json_object_copy return value check.
Reported by Coverity scan.
2022-11-14 13:05:04 +00:00
Milan Broz
5186f49613 tests: fix compilation warnings with C18
Fix the function prototype and define GNU source definition to get strdup().
2022-11-13 19:40:50 +01:00
Milan Broz
616d3cd493 tests: do not require whirlpool hash for LUKS1 test
Just remove unsupported images before test and continue.
2022-11-13 19:40:48 +01:00
Milan Broz
cd2e22cb87 tests: rename systemd plugin test
So the logic works the same as ssh-test-plugin.
2022-11-13 19:40:45 +01:00
Milan Broz
54073ef65f tests: do not run api tests twice in valgrind run.
These are run already just few lines above :)
2022-11-13 19:40:31 +01:00
Milan Broz
3e7c1e46fd tests: add source file dependence for fake tokens 2022-11-08 14:19:19 +01:00
Milan Broz
ea05e4307e tests: check that *.so token helpers are compiled. 2022-11-08 14:19:15 +01:00
Milan Broz
f35b9cc99b tests: do not use global CFLAGS for fake token helper.
Dynamic librarties cannot be linked with sanitizers this way,
just ignore CFLAGS here.
2022-11-08 14:19:11 +01:00
Milan Broz
d4888fba86 tests: compile fake_systemd_tpm_path.so through Makefile
Also fix Makefile to include source in make dist.

Note: we must not use CFLAGS there because possible sanitizers
use will make the loaded library unusable in LD_PRELOAD.
2022-11-08 14:19:04 +01:00
Milan Broz
f9e778a2cd luks2: fix warning undefined shift
Explicitly set uint32_t for shift, found by clang undefined
sanitizer.
Undefine shift cannot happen in reality, though.
2022-11-07 17:30:14 +00:00
Milan Broz
69025faa24 tests: Remove stray \" in grep expression. 2022-11-07 17:30:14 +00:00
Milan Broz
871000fa05 Fix a memory leak in crypt_keyslot_add_by_key.
Found by clang address sanitizer.

Also rename the variable - i's no longer a bare pointer,
the vk also owns the memory [okozina].
2022-11-07 17:30:14 +00:00
Milan Broz
cb53c643c2 CI: fix Debian build as pkfconf and pkg-config cannot co-exit.
Install pkgconf that is more recent and provides pkg-config too.
2022-11-04 20:28:08 +01:00
daniel.zatovic
f771f9a694 CI: install dependencies when running systemd test
Also update Debian to version 11.
2022-11-04 11:00:31 +01:00
daniel.zatovic
9009a2de26 CI: disable systemd tests on unsupported distributions 2022-11-04 11:00:31 +01:00
daniel.zatovic
6a279e21c9 Link compiled systemd to local libcryptsetup. 2022-11-04 11:00:31 +01:00
Christoph Anton Mitterer
124367f365 Add howto for converting printed to raw volume key
Signed-off-by: Christoph Anton Mitterer <mail@christoph.anton.mitterer.name>
2022-11-03 18:40:20 +00:00
Ondrej Kozina
55c39d7d16 Port crypt_volume_key_get internals to keyslot context variant. 2022-11-03 15:56:37 +01:00
Ondrej Kozina
f7e2ed956b Add crypt_volume_key_get_by_keyslot_context.
Extends avaiable methods for retrieving device volume key.
The volume key now may be extracted using passphrase, keyfile
(passphrase in a file) or token (LUKS2 only).

For LUKS devices, it returns generated volume key after
sucessfull crypt_format where new volume key got generated.

Fixes: #777.
2022-11-03 15:56:37 +01:00
Ondrej Kozina
0e6264c53c Do not cache volume key in keyslot context.
First, there was a bug where passphrase based
keyslot contextets did not cache volume keys
properly and caused leaks.

Second, it causes problems when keyslot context
is used twice with different keyslot id, e.g.:
CRYPT_ANY_SLOT vs specific id, unbound key vs
volume key, etc.
2022-11-02 12:22:25 +01:00
Ondrej Kozina
01c16111d7 Fix copy/paste mistakes in API docs. 2022-11-02 09:49:49 +01:00
daniel.zatovic
49ab658c9c CI: build and run fuzzers only conditionally 2022-10-31 20:47:23 +00:00
Milan Broz
888c6321df Do not compile systemd if running as systemd test as non-root. 2022-10-27 14:47:30 +02:00
Milan Broz
20f8c09195 Fix make dist to include systemd plugin test. 2022-10-27 14:38:23 +02:00
daniel.zatovic
57d4c677bd CI: add systemd-tpm2 token integration test. 2022-10-26 15:19:25 +02:00
Milan Broz
cde7b90735 fuzzing: Build OpenSSL with no-shared options
The -static option always disables threads, we want to use no-shared
build option instead.
2022-10-22 10:10:34 +00:00
Ondrej Kozina
3e4c69a017 Fix internal crypt segment compare routine.
The function is supposed to check if manipulated
active dm-crypt device matches the on-disk metadata.
Unfortunately it did not take into account differences
between normal cipher specification (aes-xts-plain64)
and capi format specification (capi:xts(aes)-plain64).
The internal query function always converted capi format
in normal format and therefor failed if capi format was
used in metadata.

Fixes: #759.
2022-10-20 14:24:11 +02:00
Ondrej Kozina
19c15a652f Copy also integrity string in legacy mode.
So that it handles integrity string same as it does
with cipher string.
2022-10-20 14:24:11 +02:00
Ondrej Kozina
2390395150 Code cleanup.
Type cast is not needed here.
2022-10-20 14:24:11 +02:00
Ondrej Kozina
9a9ddc7d22 Move cipher_dm2c to crypto utilities.
(Gets renamed to crypt_capi_to_cipher)
2022-10-20 14:24:02 +02:00
Ondrej Kozina
3616da631f Fix cipher convert routines naming confusion.
The function names were in fact swaped.
2022-10-20 14:23:48 +02:00
daniel.zatovic
b380fa7494 CI: Add fuzzer jobs. 2022-10-19 10:07:03 +02:00
Milan Broz
23f49eca43 Silent new keyslot option warning in tests.
After we introduced --new-key-slot option, just use it and
avoid CLI warning.
2022-10-18 15:51:11 +02:00
Milan Broz
00baa92756 fuzzing: Yet another dependency fix.
Previous fix breaks make dist. Let's set dependency
on object file explicitly.
2022-10-14 15:02:03 +02:00
daniel.zatovic
8bbb018a01 CI: Add Ubuntu 18.04 32bit job. 2022-10-14 09:27:27 +00:00
Milan Broz
c464d61995 fuzzing: Fix dependence issue
This patch avoids a race when running parallel jobs.
2022-10-14 06:48:32 +00:00
Milan Broz
d260ca6680 Fix api-test with older kernel. 2022-10-13 16:08:08 +02:00
Milan Broz
d05a2a6c99 fuzzing: Force dependence for generated header. 2022-10-10 12:32:10 +02:00
Milan Broz
758a2974f5 fuzzing: Clean up includes. 2022-10-09 12:59:57 +02:00
Milan Broz
4b5e814094 fuzzing: Remove unused code.
Also use C comments style in C-only file.
2022-10-09 12:36:52 +02:00
Milan Broz
98f5e0538a fuzzing: use ftruncate() instead of seeking to end of the file 2022-10-09 12:36:24 +02:00
Milan Broz
f03180d06a fuzzing: Simplify converters and used common defines for exit code. 2022-10-09 12:36:09 +02:00
Milan Broz
39b94ae530 fuzzing: Simplify plain JSON fuzzer. 2022-10-09 12:35:58 +02:00
Milan Broz
3690d5f532 fuzzing: Simplify proto fuzzer. 2022-10-09 12:35:20 +02:00
Milan Broz
e595940637 fuzzing: LLVMFuzzerTestOneInput must always return 0.
Also simplify the fuzzer function.
2022-10-09 12:34:26 +02:00
Milan Broz
dab939c3c9 fuzzing: Fix possible overflow in crypt2_load_fuzz.
Fixes OSS-Fuzz 52201.
2022-10-08 20:13:24 +02:00
daniel.zatovic
cc276527c7 fuzzing: Disable assembly in openssl build
Sanitizers can not instrument openssl's assembly and wrongly report
buffers from openssl as uninitialized.
2022-10-06 23:23:06 +02:00
Milan Broz
27429daf5d Fix typo. 2022-10-05 09:49:55 +02:00
Milan Broz
b20821a520 Fuzzing: disable po4a in static library dependence build as it seems to freeze. 2022-10-04 23:42:07 +02:00
Milan Broz
46b465ff2e Use upstream git for protobuf-mutator as required patches are merged now. 2022-10-04 13:10:36 +02:00
Milan Broz
d8fd9caa6a Add missing files to Makefile.am (and reformat lists). 2022-10-04 13:00:38 +02:00
daniel.zatovic
dad11f97ce Copy only selected fuzzers to out directory. 2022-10-04 13:00:33 +02:00
daniel.zatovic
c06e853938 Fix missing prototypes by adding a header file. 2022-10-04 13:00:29 +02:00
daniel.zatovic
c35e4479d5 Update fuzzing README 2022-10-04 13:00:25 +02:00
daniel.zatovic
8585fb29eb Add dictionary for the plain JSON fuzzer. 2022-10-04 13:00:21 +02:00
daniel.zatovic
97b3926655 Fix potential integer underflow. 2022-10-04 13:00:18 +02:00
Milan Broz
a3f248df9b Fix some clang++ warnings. 2022-10-04 13:00:15 +02:00
Milan Broz
e1a84607cc Rework build of fuzzers.
- Do not require any libraries installed, download everything
from upstream git, statically compile (use include, libs and pkg-config
from local directory under tests/fuzz).
Script should work both from OSS-Fuzz and locally.

- Do not require local protobuf (only staticallly compiled, see above).

- Add README.md (TBD, still not finished).

- Fix make dist and distcheck.

- Remove common.[ch] as we can use internal function.
  This makes fuzzers also C++ only (remove CFLAGS from Makefile).
2022-10-04 13:00:10 +02:00
daniel.zatovic
2f4267ba81 Add plain JSON metadata fuzzing 2022-10-04 12:59:07 +02:00
daniel.zatovic
99e8ee6b7e Add checks for compiler when building fuzz targets. 2022-10-04 12:59:04 +02:00
daniel.zatovic
f58aff21a9 Add fuzz targets, custom mutator and fuzzing dictionary 2022-10-04 12:58:59 +02:00
Milan Broz
de8a27ae02 Print a visible error in LUKS2 if AF hash is not available.
In LUKS1 there is only one hash algorithm specification,
it cannot happen, that AF hash algorithm is not
available, as it is used immediately before in PBKDF2.

In LUKS2 this can be completely different algorithm, so
it make sense to print a visible warning for user.

For example, Whirlpool and RIPEMD160 is now in OpenSSL legacy
provider which can be unavailable, see #773.)

This patch adds a message only, the code already fails with -EINVAL.
2022-10-03 10:33:32 +02:00
Milan Broz
b9b08eba7c Fix function prototype (and build for 32bit system). 2022-10-03 09:57:40 +02:00
Milan Broz
82b56300cd Wrap some very long lines. 2022-10-01 22:35:57 +02:00
Milan Broz
9f8fe3da16 Fix some typos. 2022-10-01 22:35:52 +02:00
Ondrej Kozina
50803ebacb Switch existing keslot adding API to new extension. 2022-09-29 17:31:29 +02:00
Ondrej Kozina
5fce0c2ad1 Extend luksAddKey action options via crypt_keyslot_add_by_keyslot_context API.
In practice luksAddKey action does two operations. It unlocks existing
device volume key and stores unlocked volume key in a new keyslot.
Previously the options were limited to key files and passphrases.
With this patch user may combine freely following options:

To unlock keyslot with volume key user may:
- provide existing passphrase via interactive prompt (default method)
- use --key-file option to provide file with a valid passphrase to existing keyslot
- provide volume key directly via --volume-key-file
- unlock keyslot via all available LUKS2 tokens by --token-only
- unlock keyslot via specific token with --token-id
- unlock keyslot via specific token type by --token-type

To provide the passphrase for a new keyslot user may:
- provide existing passphrase via interactive prompt (default method)
- use --new-keyfile parameter or positional parameter to read the
  passphrase from file.
- use --new-token-id to select specific LUKS2 token to get passphrase
  for new keyslot. New keyslot is assigned to selected token id if
  operation is succesfull.

Fixes: #725.
2022-09-29 17:31:29 +02:00
Ondrej Kozina
2e29eb7906 cryptsetup-luksAddKey man page cleanup. 2022-09-22 17:45:20 +02:00
Ondrej Kozina
b867f0b578 Add new API for adding new LUKS keyslots.
The crypt_keyslot_add_by_keyslot_context & associated
helper functions allow more options when adding new
keyslot. For example there was no simple way of
adding new LUKS2 keyslot when the only active keyslot
could be unlocked by passphrase (KEK) provided by LUKS2 token
(plugin). Now all available options for unlocking keyslots
may also be used when creating new keyslot and it combine
as called needs.

The available methods (keyslot contexts) are:
passphrase, keyfile, key (binary representation) and LUSK2 token.
2022-09-21 17:36:28 +02:00
Milan Broz
1745fd5aea Fix missing va_end macro in test error path. 2022-09-19 12:46:42 +00:00
Ondrej Kozina
90ad841a45 Add cryptsetup token unassign action.
Allows removing token binding on specific keyslot.
2022-09-16 14:34:28 +02:00
Ondrej Kozina
0397cac878 Abort assigning tokens with invalid parameters earlier. 2022-09-16 13:30:39 +02:00
Ondrej Kozina
033ff34109 Enable adding unassigned luks2-keyring token in cryptsetup.
There was no easy way to add unassigned luks2-keyring token.
Reuse --unbound parameter for it.
2022-09-16 12:34:32 +02:00
Ondrej Kozina
0d61e4c20f Clarify --unbound usage in man pages. 2022-09-16 12:32:24 +02:00
Milan Broz
b4863897fe Fix verity-compat-test if running with different locale. 2022-09-06 21:55:37 +02:00
Ondrej Kozina
eac02f5605 Fix NULL key_description bug in luks2-keyring token.
json-c parser transforms NULL pointer into special '(null)' string.
While being technically correct it hides the fact user passed NULL
pointer in crypt_token_params_luks2_keyring structure. This bug
could be trigerred by calling crypt_token_luks2_keyring_set().
2022-09-01 15:38:49 +02:00
daniel.zatovic
94e8a7ca96 Fix valgrind in SSH token test. 2022-08-25 08:02:37 +00:00
Milan Broz
b183bb25e2 Add support for dm-verity try_verify_in_tasklet option.
Available since kernel 6.0.
2022-08-25 08:01:07 +00:00
Ondrej Kozina
09ac5321f4 Fix memory leak in ssh token example. 2022-08-23 15:53:25 +02:00
Milan Broz
c1302555b7 Provide pkgconfig Require.private.
While we do not completely provides static build on udev
systems, having theses modules in pkgconfig can be useful otherwise.
2022-08-23 12:06:07 +00:00
Ondrej Kozina
01c032df04 Do not reload LUKS2 metadata when not necessary.
Following API calls trigerred LUKS2 metadata reload
from storage in case of failure:

crypt_convert
crypt_keyslot_add_by_key
crypt_keyslot_add_by_keyfile_device_offset
crypt_keyslot_add_by_passphrase
crypt_keyslot_change_by_passphrase
crypt_reencrypt_init_by_keyring
crypt_reencrypt_init_by_passphrase

This patch replaces LUKS2 metadata reload with
backup LUKS2 metadata copy kept in memory that is updated on
each sucessfull metadata write and rolled back to it whenever
needed in any of those calls listed above.
2022-08-19 14:46:42 +02:00
Milan Broz
88d9524e6c Mark crypt_memory_lock() API call deprecated.
And remove its implementation.
2022-08-16 19:56:32 +02:00
Milan Broz
4b47091b85 Remove call to explicit memlockall from cryptsetup.
Memory with keys is now locked per range.
2022-08-16 19:56:28 +02:00
Milan Broz
b9bf657449 Set process priority only for PBKDF benchmark.
Do not increase priority for the whole run, only
increase it when we calculate PBKDF paramaters.
2022-08-16 19:56:24 +02:00
Milan Broz
21d87a246e Do not use safe_malloc for LUKS header backup.
The content of LUKS header is not a key material, no need
to lock memory for possibly big header and big memory area locks.

Just ensure we wipe buffer before release of memory.
2022-08-16 19:56:20 +02:00
Milan Broz
db65a5ceac Lock memory in crypt_safe alloc functions.
This patch locks all memory ranges in safe allocations.

While crypto backend can have some secure memory calls,
it is usually limited by intitial config.

For our use is enough to keep keys in memory and prevent
swapping it out.

If the lock fails (because of limits) we quietly
stay with plain malloc.
2022-08-16 19:56:00 +02:00
daniel.zatovic
132027bafa Force probe in tests instead of lsblk which can use udev cache. 2022-08-11 21:26:03 +02:00
daniel.zatovic
f6fd73aea5 Add FIPS checks before running tests in FIPS mode. 2022-08-10 11:37:25 +00:00
Ondrej Kozina
5b001b7962 Delegate FIPS mode detection to configured crypto backend.
System FIPS mode check is no longer dependent on /etc/system-fips
file. The change should be compatible with older distributions since
we now depend on crypto backend internal routine.

This commit affects only FIPS enabled systems (with FIPS enabled
builds). In case this causes any regression in current distributions
feel free to drop the patch.

For reference see https://bugzilla.redhat.com/show_bug.cgi?id=2080516
2022-08-10 10:53:39 +02:00
daniel.zatovic
429afe8fc3 Add valgrind support to more tests. 2022-08-10 07:45:13 +00:00
Milan Broz
abfb5e374f Remove leftover debug option in test. 2022-08-09 22:54:43 +02:00
daniel.zatovic
f8c79f9a95 Fix valgrind summary leak detection.
Currently, only 1-9 leaks are detected. More than 10 leaks are evaluated
as no leak.
2022-08-05 16:38:38 +02:00
Milan Broz
190e4fc033 Always update automake library files if autogen.sh is run.
Fixes: #761
2022-08-01 08:47:34 +00:00
Ondrej Kozina
093adfc5f9 Fix user defined moved segment size in LUKS2 decryption.
--hotzone-size argument was ignored in cases where actual data size
was less than original LUKS2 data offset.
2022-08-01 07:05:06 +00:00
Milan Broz
a009614191 Set devel version. 2022-07-30 09:29:00 +02:00
Milan Broz
75111d382b Version 2.5.0. 2022-07-28 17:32:33 +02:00
Yuri Kozlov
1cc6c82f21 po: update ru.po (from translationproject.org) 2022-07-28 17:32:04 +02:00
Frédéric Marchal
2c555bd4a0 po: update fr.po (from translationproject.org) 2022-07-28 17:32:04 +02:00
Roland Illig
3f3f5a6aab po: update de.po (from translationproject.org) 2022-07-28 17:32:04 +02:00
Ondrej Kozina
c6ed1becd7 Fix bogus conditions in tests.
Do not test for dm-crypt versions not supported
by upstream kernels.
2022-07-28 17:18:57 +02:00
Milan Broz
766ac108ec Fix option descriptions and lists mentioned in man pages. 2022-07-28 10:51:22 +00:00
Milan Broz
94e5d227ce Fix warning messages if some kernel option is not supported.
Thus was broken by commit
  "Check if DM create device failed in an early phase."
  10b1d6493e

Also we should set EINVAL if we detect unsuported option.
2022-07-28 10:50:55 +00:00
Ondrej Kozina
f96e19147c Add prompt for LUKS2 decryption with header export. 2022-07-28 12:50:13 +02:00
Ondrej Kozina
05dbf04d82 Add early warning for reencryption of image files. 2022-07-28 12:47:10 +02:00
Ondrej Kozina
b9b7c3a9bd Add detached header warning in reencrypt man page. 2022-07-28 10:41:20 +00:00
Ondrej Kozina
17e6d2053a Add mangle tests for LUKS2 decryption with datashift. 2022-07-28 07:57:36 +00:00
Ondrej Kozina
912109ae66 Improve reencryption parameters verification in cli.
Try to catch as many invalid parameters as possible
before entering library call.
2022-07-28 07:57:36 +00:00
Ondrej Kozina
25b877a403 Fix bug in reencryption parameters verification. 2022-07-28 07:57:36 +00:00
Milan Broz
8270b72bfc Use bool instead od int in LUKS1 reencryption context. 2022-07-27 12:01:11 +02:00
Milan Broz
9c0cdcc2f9 Do not use huge LUKS1 reencryption context on heap.
This will reduce cryptsetup tool size (~20kB at least).
2022-07-27 11:57:05 +02:00
Milan Broz
1e2cb2d419 Avoid using huge dummy context in LUKS1 reencryption check.
This struct is not needed at all, just use NULL.
2022-07-27 11:47:06 +02:00
Guilhem Moulin
3e178caeaf Document more supported options in cryptsetup-luksResume(8).
`cryptsetup luksResume --disable-external-tokens --keyfile-offset 123`
does work but these options weren't documented.
2022-07-21 02:29:05 +02:00
Guilhem Moulin
803957cd3e Add support for --key-slot in luksResume action. 2022-07-20 20:00:09 +02:00
Milan Broz
bf4bfeac8a Rename some tests to simplify localtest parsing. 2022-07-18 15:09:28 +02:00
Milan Broz
090dca635a Add ssh-test-plugin to localtest if RUN_SSH_PLUGIN_TEST is set. 2022-07-18 11:16:23 +02:00
Milan Broz
0369ffdcc1 Rename ssh plugin test to ssh-test-plugin.
So we can filter it out in local tests
(*-test means generic tests, *-test-plugin specific plugin tests).
2022-07-18 09:11:23 +02:00
Milan Broz
648a85ed3a Unify use of tabulators in tests. 2022-07-16 19:14:31 +00:00
Milan Broz
8f3884e0d7 Change default target for Makefile.localtest. 2022-07-16 19:14:31 +00:00
Guilhem Moulin
289d5e5891 Add unit-utils-crypt-test to Makefile.localtest's list of tests.
This requires (re-)building the executable with -DNO_CRYPTSETUP_PATH.
Only in that case do we allow the test to run under non-empty
$CRYPTSETUP_PATH.
2022-07-16 19:14:31 +00:00
Guilhem Moulin
b37d04975d Add compat-test-args to Makefile.localtest's list of tests. 2022-07-16 19:14:31 +00:00
Guilhem Moulin
6578dac2f9 Add blockwise-compat to Makefile.localtest's list of tests.
This requires (re-)building `unit-utils-io` with -DNO_CRYPTSETUP_PATH.
Only in that case do we allow the test to run under non-empty
$CRYPTSETUP_PATH.
2022-07-16 19:14:31 +00:00
Guilhem Moulin
dc5f284e42 blockwise-compat: Wait a bit so scsi_debug has a chance to fully initialize.
Similar to a76c96d361.  See also !386.
2022-07-16 19:14:31 +00:00
Guilhem Moulin
32149e4ee7 blockwise-compat: Make skip() exit with status 77.
This is mostly useful under TESTSUITE_NOSKIP=y.
2022-07-16 19:14:31 +00:00
Guilhem Moulin
0e4857ee81 unit-wipe-test: Make skip() exit with status 77.
This is mostly useful under TESTSUITE_NOSKIP=y.
2022-07-16 19:14:31 +00:00
Milan Broz
06dd06ea27 tests: allow unit-wipe-test to run with local tests. 2022-07-16 19:14:31 +00:00
Milan Broz
03eb8f860a tests: check for differ existence in compat-test. 2022-07-16 19:14:31 +00:00
Guilhem Moulin
fbcef71c41 Pass $(LDFLAGS) when building fake_token_path.so.
The Debian tooling sets ‘LDFLAGS = -Wl,-z,relro -Wl,-z,now’ and
complains when anything is built without hardened compiler/linker flags.

Granted this is a non-issue here since fake_token_path.so isn't included
in any binary package, but muting the false positive is arguably no
better fix than honoring $(LDFLAGS) during the build.
2022-07-16 13:51:11 +02:00
Milan Broz
8315ada3b0 Fix wipe unit test if direct-io not available.
If test is run in tmpfs, direct-io is not supported.

Thanks Guilhem Moulin for reporting the issue.
2022-07-15 21:50:21 +02:00
Yuri Chornoivan
782dae9292 po: update uk.po (from translationproject.org) 2022-07-15 20:15:48 +02:00
Jakub Bogusz
96c0544527 po: update pl.po (from translationproject.org) 2022-07-15 20:15:48 +02:00
Hiroshi Takekawa
cb7e2c6433 po: update ja.po (from translationproject.org) 2022-07-15 20:15:48 +02:00
Petr Pisar
f0da65cc63 po: update cs.po (from translationproject.org) 2022-07-15 20:15:48 +02:00
Guilhem Moulin
a76c96d361 unit-wipe-test: Wait a bit so scsi_debug has a chance to fully initialize.
On my test system `tests/unit-wipe-test` fails (as root) due to a race
condition in add_device():

	root@host:~# ./unit-wipe-test
	[1] Wipe full file [0/DIO][0][1048576/DIO][1048576][4194304/DIO][4194304][OK]
	[2] Wipe blocks in file [0/DIO][0][1048576/DIO][1048576][4194304/DIO][4194304][OK]
	[  105.828258] scsi_debug:sdebug_driver_probe: scsi_debug: trim poll_queues to 0. poll_q/nr_hw = (0/1)
	[  105.830450] scsi host2: scsi_debug: version 0191 [20210520]
	[  105.830450]   dev_size_mb=8, opts=0x0, submit_queues=1, statistics=0
	[  105.832924] scsi 2:0:0:0: Direct-Access     Linux    scsi_debug       0191 PQ: 0 ANSI: 7
	[  105.835417] scsi 2:0:0:0: Attached scsi generic sg1 type 0
	FAIL Cannot find /dev/.
	FAILED backtrace:
	48 ./unit-wipe-test
	144 main ./unit-wipe-test
	[  105.875131] sd 2:0:0:0: Power-on or device reset occurred
	[  105.876069] sd 2:0:0:0: [sda] 16384 512-byte logical blocks: (8.39 MB/8.00 MiB)
	[  105.877190] sd 2:0:0:0: [sda] Write Protect is off
	[  105.878002] sd 2:0:0:0: [sda] Write cache: enabled, read cache: enabled, supports DPO and FUA
	[  105.879619] sd 2:0:0:0: [sda] Optimal transfer size 524288 bytes
	[  105.914222] sd 2:0:0:0: [sda] Attached SCSI disk
	[  106.866296] sd 2:0:0:0: [sda] Synchronizing SCSI cache

Observe how the “Power-on or device reset occurred” event occurs only
after add_device() has returned.  Interestingly, for subsequent runs the
delay appears to be much shorter and doesn't trigger the race condition:

	root@host:~# ./unit-wipe-test
	[1] Wipe full file [0/DIO][0][1048576/DIO][1048576][4194304/DIO][4194304][OK]
	[2] Wipe blocks in file [0/DIO][0][1048576/DIO][1048576][4194304/DIO][4194304][OK]
	[  130.639855] scsi_debug:sdebug_driver_probe: scsi_debug: trim poll_queues to 0. poll_q/nr_hw = (0/1)
	[  130.641463] scsi host2: scsi_debug: version 0191 [20210520]
	[  130.641463]   dev_size_mb=8, opts=0x0, submit_queues=1, statistics=0
	[  130.643809] scsi 2:0:0:0: Direct-Access     Linux    scsi_debug       0191 PQ: 0 ANSI: 7
	[  130.645342] sd 2:0:0:0: Power-on or device reset occurred
	[  130.646364] sd 2:0:0:0: [sda] 16384 512-byte logical blocks: (8.39 MB/8.00 MiB)
	[  130.647585] sd 2:0:0:0: [sda] Write Protect is off
	[  130.648428] sd 2:0:0:0: Attached scsi generic sg1 type 0
	[  130.649339] sd 2:0:0:0: [sda] Write cache: enabled, read cache: enabled, supports DPO and FUA
	[  130.650763] sd 2:0:0:0: [sda] Optimal transfer size 524288 bytes
	[  130.682223] sd 2:0:0:0: [sda] Attached SCSI disk
	[3] Wipe full block device [0/DIO][0][1048576/DIO][1048576][4194304/DIO][4194304][OK]
	[4] Wipe blocks in block device [0/DIO][0][1048576/DIO][1048576][4194304/DIO][4194304][OK]
	[  137.858283] sd 2:0:0:0: [sda] Synchronizing SCSI cache

This commit adds an optional 2s delay if scsi_debug hasn't shown up in
sysfs after the modprobe call.
2022-07-15 18:13:37 +00:00
Guilhem Moulin
3106b4e2c1 More typo and spelling fixes.
Reported by `git ls-tree -rz --name-only | grep -Evz -e '\.(pdf|xz)$' -e
^po/ | xargs -r0 spellintian --`.  All changes are
documentation-related (comments, manuals, etc.) except for s/fial/fail/
in tests/unit-wipe-test.

The remaining entry are AFAICT all false positives, mostly annotations
such as `@param name name of xyz` or `struct foo foo`:

	$ git ls-tree -rz HEAD --name-only | grep -Evz -e '\.(pdf|xz)$' -e ^po/ | xargs -r0 spellintian --
	COPYING.LGPL: "GNU Library Public License" -> "GNU Library General Public License"
	autogen.sh: echo echo (duplicate word) -> echo
	configure.ac: fi fi (duplicate word) -> fi
	docs/v1.7.2-ReleaseNotes: option option (duplicate word) -> option
	lib/crypto_backend/cipher_check.c: block block (duplicate word) -> block
	lib/libcryptsetup.h: name name (duplicate word) -> name
	lib/libcryptsetup.h: type type (duplicate word) -> type
	lib/libcryptsetup.h: passphrase passphrase (duplicate word) -> passphrase
	lib/libcryptsetup.h: flags flags (duplicate word) -> flags
	lib/libcryptsetup.h: password password (duplicate word) -> password
	lib/libcryptsetup.h: salt salt (duplicate word) -> salt
	lib/libcryptsetup.h: keyslot keyslot (duplicate word) -> keyslot
	lib/libcryptsetup.h: priority priority (duplicate word) -> priority
	lib/libcryptsetup.h: offset offset (duplicate word) -> offset
	lib/libcryptsetup.h: length length (duplicate word) -> length
	lib/libcryptsetup.h: keyfile keyfile (duplicate word) -> keyfile
	lib/libcryptsetup.h: token token (duplicate word) -> token
	lib/libcryptsetup.h: cipher cipher (duplicate word) -> cipher
	lib/libcryptsetup.h: size size (duplicate word) -> size
	lib/luks2/luks2_json_metadata.c: long long (duplicate word) -> long
	lib/luks2/luks2_keyslot_luks2.c: AFEKSize AFEKSize (duplicate word) -> AFEKSize
	lib/luks2/luks2_reencrypt.c: alignment alignment (duplicate word) -> alignment
	lib/luks2/luks2_reencrypt_digest.c: ptr ptr (duplicate word) -> ptr
	lib/luks2/luks2_reencrypt_digest.c: buffer buffer (duplicate word) -> buffer
	lib/luks2/luks2_segment.c: min min (duplicate word) -> min
	lib/verity/verity_fec.c: blocks blocks (duplicate word) -> blocks
	man/cryptsetup.8.adoc: LUKS LUKS (duplicate word) -> LUKS
	scripts/cryptsetup.conf.in: root root (duplicate word) -> root
	src/Makemodule.am: endif endif (duplicate word) -> endif
	src/cryptsetup.c: long long (duplicate word) -> long
	src/utils_args.c: long long (duplicate word) -> long
	tests/compat-test2: fi fi (duplicate word) -> fi
	tests/device-test: echo echo (duplicate word) -> echo
	tests/differ.c: long long (duplicate word) -> long
	tests/loopaes-test: done done (duplicate word) -> done
	tests/luks2-integrity-test: aead aead (duplicate word) -> aead
	tests/luks2-reencryption-test: fi fi (duplicate word) -> fi
	tests/mode-test: done done (duplicate word) -> done
	tests/password-hash-test: cat cat (duplicate word) -> cat
	tests/password-hash-test: fi fi (duplicate word) -> fi
	tests/unit-wipe.c: long long (duplicate word) -> long
	tests/verity-compat-test: done done (duplicate word) -> done
	tests/verity-compat-test: fi fi (duplicate word) -> fi
	tokens/ssh/cryptsetup-ssh.c: argp argp (duplicate word) -> argp
	tokens/ssh/cryptsetup-ssh.c: arguments arguments (duplicate word) -> arguments

(Treated COPYING.LGPL as a false positive too since it's the exact text
from https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html .)
2022-07-15 16:35:02 +02:00
Guilhem Moulin
5d711c000f Fix minor spelling errors.
(Found by Lintian.)
2022-07-15 12:16:39 +02:00
Milan Broz
bf2e48e404 Version 2.5.0-rc1. 2022-07-14 16:00:01 +02:00
Ondrej Kozina
d943b2efb9 Clarify cryptsetup-open options in man page. 2022-07-14 13:51:37 +00:00
Milan Broz
02d5c5ce38 Add 2.5.0-rc1 Release Notes. 2022-07-14 14:10:33 +02:00
Milan Broz
bdc97ef389 Update cryptsetup.pot. 2022-07-14 14:09:45 +02:00
Milan Broz
6540ffd1a6 Fix spacing with man footer by adding space.
So it is always separate section.
2022-07-14 09:42:04 +02:00
Milan Broz
c7a8c9a620 Always regenerate man pages if source file changes. 2022-07-14 09:42:01 +02:00
Milan Broz
d96dcff883 Set 2.5.0-rc1 version. 2022-07-13 21:13:07 +02:00
Milan Broz
4034c548c2 Update LUKS2 on-disk description. 2022-07-13 21:13:07 +02:00
daniel.zatovic
8eff391a66 Regenerate manual pages using AsciiDoctor in spec file. 2022-07-13 21:08:17 +02:00
daniel.zatovic
dae6aa0384 Obsolete cryptsetup-reencrypt and add manual pages to spec file.
The cryptsetup-reencrypt utility is now replaced by reencrypt action.
New per-action manual pages have been added.
2022-07-13 21:08:15 +02:00
daniel.zatovic
a2afe0396f Split manual pages into per-action page and use AsciiDoc format
Use pre-generated man pages in make dist.

[Added fixes and updates from Ondrej Kozina and Milan Broz]
2022-07-13 21:08:02 +02:00
daniel.zatovic
fec2517386 CI: enable Asciidoctor 2022-07-13 16:03:35 +02:00
Ondrej Kozina
c413434715 Add error message for failed in-use auto-detect.
When reencrypting image files cryptsetup is unable to
detect reliably if image file is in use or not.

User must decide it explictly. Add error message that
references --force-offline-reencrypt to solve the issue
in non interactive mode.

(It will be replaced with early detection in before 2.5.0 final
release).
2022-07-13 10:56:17 +00:00
Milan Broz
aa126ac10a Remove dracut plugin that is obsolete and will not work with current reencrypt code. 2022-07-12 17:58:48 +00:00
Ondrej Kozina
56d4e9924e Add LUKS2 reencryption mangle tests. 2022-07-12 14:05:03 +02:00
Ondrej Kozina
a60fd0a81b Do not fail LUKS2 validation by newer online-reencrypt requirement.
Do not invalidate LUKS2 format when future online-reencrypt
requirement flag is encountered (by older releases).
But it must stop device from being activated, reencrypted
or modified.
2022-07-12 14:05:03 +02:00
Ondrej Kozina
af68e8a1da Check for multiple online reencrypt requirement flags.
Having multiple online-reencrypt requirements flags
candidate in config section should invalidate LUKS2
metadata.
2022-07-12 14:05:03 +02:00
Ondrej Kozina
13f6dfa61f Add proper version data to reencryption verification digest.
LUKS2 decryption requires new online-reencrypt version
flag (v3).

The verification digest performs coding
for version suffix in "online-reencrypt-v" flag string
as follows:

'v1' :  unused (no digest)
'v2' :  0x30 + 2   = 0x32 = '2'
'v3' :  0x30 + 3   = 0x33 = '3'
(...)
'v10':  0x30 + 10  = 0x3A = ':'
'v11':  0x30 + 11  = 0x3B = ';'
(...)
'v207': 0x30 + 207 = 0xFF
2022-07-12 14:03:25 +02:00
Ondrej Kozina
8493f6afd5 Change size of requirement version to 1 byte.
Mostly due to reencryption verification routine
currently expects only single byte of version
data to create digest from.
2022-07-12 13:54:24 +02:00
Milan Broz
1a55b69a0f Fix leak of dm target structure.
The dmd_source need to be cleared with dm_targets_free().
2022-07-07 09:17:13 +00:00
Milan Broz
914f621251 Do not use uninitialized memory for cipher check.
We do not care about the bufer content, but valgrind do, just wipe
the buffer before test.
2022-07-07 09:17:13 +00:00
Milan Broz
5904516122 Skip reencryption test if required ciphers are not available in userspace.
This happens for some very old systems like CentOS6 or own compiled
crypto libraries.
2022-07-05 15:08:43 +02:00
Milan Broz
4507ced868 Report failure if userspace cannot use specified cipher.
Reencryption require support both for kernel and userspace library.

If only kernel supports the copher, the error was quiet.
2022-07-05 15:07:33 +02:00
Milan Broz
b4603f1e28 Fix valgrind test in compat-test. 2022-07-04 14:34:04 +02:00
Petr Pisar
1c21c24f7b po: update cs.po (from translationproject.org) 2022-07-04 09:36:22 +02:00
Ondrej Kozina
0009d9532e Extend LUKS2 decryption with datashift API tests. 2022-06-30 11:21:38 +02:00
Ondrej Kozina
47cb9b0ee2 Fix copy&paste mistake in exclusive open comment. 2022-06-27 16:01:50 +02:00
Ondrej Kozina
0ffd105cb8 Harden LUKS2 decryption with datashift parameters.
Abort early if detached header is passed in API
by any chance.
2022-06-27 16:01:50 +02:00
Ondrej Kozina
24d498e393 Add debug message in LUKS2 reencryption initialization. 2022-06-27 16:01:50 +02:00
Ondrej Kozina
3c8b3201d7 Improve crypt_reencrypt_status return values.
Empty context or any non-LUKS types now returns
CRYPT_REENCRYPT_INVALID value.

For LUKS1 devices return CRYPT_REENCRYPT_NONE
(since any LUKS1 device in legacy reencryption
does not have valid LUKS1 header/metadata).
2022-06-27 16:01:50 +02:00
Ondrej Kozina
f531b567e0 Test reencryption initalization error path.
Test cli behaves properly when there's not enough
space in keyslots area for new unbound keyslot or
reencryption keyslot.

Fixes: #688.
2022-06-27 16:01:43 +02:00
Jakub Bogusz
7c76881921 po: update pl.po (from translationproject.org) 2022-06-24 15:19:10 +02:00
Milan Broz
f642417ed7 Add check to LUKS1 convert for segments count. 2022-06-23 07:24:27 +02:00
Milan Broz
1c1df24258 Clean up convert code style.
Remove FIXMEs and comment style.
2022-06-23 07:10:22 +02:00
Milan Broz
b3e8e1a9d4 Log visible error if convert fails due to validation check 2022-06-23 07:08:42 +02:00
Milan Broz
d22b003640 Fix possible keyslot area size overflow during convert to LUKS2
If keyslots are not sorted according to binary area offset,
the calculation of area size is wrong and can overflow
(LUKS1 does not store area size, only offset).

Let's just use function that calculates size from volume key size.
Images where keyslot areas are not aligned to 4k offset
are not supported anyway.

Fixes: #753
2022-06-23 07:06:38 +02:00
Ondrej Kozina
a485f44b57 Fix decryption with datashift initialization.
It did not work with --active-name option for
active LUKS2 devices.
2022-06-21 15:27:43 +02:00
Ondrej Kozina
f182d73001 Speed up reencryption tests.
By not testing repeatedly that 'wipe' test utility actually
wipes the device. This test is supposed to test reencryption
code.

I have left untouched already existing first time checks
for each data digest.
2022-06-21 10:47:42 +02:00
Yuri Chornoivan
05fc7b172d po: update uk.po (from translationproject.org) 2022-06-20 17:30:20 +02:00
Hiroshi Takekawa
66c5b52b42 po: update ja.po (from translationproject.org) 2022-06-20 17:30:20 +02:00
Frédéric Marchal
af3559a0f6 po: update fr.po (from translationproject.org) 2022-06-20 17:30:20 +02:00
Roland Illig
bcde337a42 po: update de.po (from translationproject.org) 2022-06-20 17:30:20 +02:00
Yuri Chornoivan
83103627b2 Fix minor typo.
Fixes: #752
2022-06-20 11:37:44 +00:00
Milan Broz
8f8703f1c3 Update cryptsetup.pot. 2022-06-17 19:58:31 +02:00
Milan Broz
857d17d210 Fix makefile to include wipe-test in dist tarball. 2022-06-17 19:57:31 +02:00
Milan Broz
62a3954c9d Add a debug message after crypt_load in error path. 2022-06-17 19:30:35 +02:00
Milan Broz
c72aecf86d Add comment to validation code. 2022-06-17 16:08:52 +02:00
Milan Broz
d9b66afe5e Replace json_bool with stdbool.
This is some relict from old code, just use bool, we already
require it elsewhere.
2022-06-17 16:04:31 +02:00
Milan Broz
18ada2b7de Check for interval overflow in LUKS2 validation code.
Invalid values that overflows in interval check were silently ignored.

Fix this by explictily adding check for interval overflow in keyslots
and segment validation.

Fixes: #748
2022-06-17 16:03:32 +02:00
Milan Broz
279490b622 Add test for keyslot area overflow during validation. 2022-06-17 16:03:32 +02:00
Milan Broz
dfd96d8a39 Report uint64 overflows and conversion errors in log debug during LUKS2 validate. 2022-06-17 16:03:30 +02:00
Milan Broz
ba9e36ceae Add empty string check to LUKS2 JSON validation.
Most of the LUKS2 fields cannot be empty,
add check for JSON validation for it to fail early.

Fixes: #746
2022-06-17 14:46:50 +02:00
Ondrej Kozina
f97af5dcfe Add LUKS2 decryption with datashift tests. 2022-06-17 13:48:15 +02:00
Ondrej Kozina
b4e9bca354 Enable LUKS2 decryption datashift support in cli.
Fixes: #669.
2022-06-17 13:48:12 +02:00
Ondrej Kozina
c36f9899cf Add support for LUKS2 decryption with datashift.
Adds support for LUKS2 decryption of devices with a
header put in the head of data device. During the initialization
header is exported to a file and first data segment
is moved to head of data device in place of original header.

The feature introduces several new resilience modes (combination
of existing modes datashift and "checksum" or "journal").
Where datashift resilience mode is applied for data moved towards
the first segment and first segment is decrypted in-place.

The mode is not backward compatible with prior LUKS2 reencryption
and therefor interrupted operation in progress can not be resumed
using older cryptsetup releases.

Fixes: #669.
2022-06-17 13:48:12 +02:00
Ondrej Kozina
f3a46b8e93 Check user provided correct passphrase before initializing decryption.
It would fail later anyway (due to wrong passphrase provided) but
it's better to stop sooner.
2022-06-17 13:48:12 +02:00
Ondrej Kozina
b84132c140 Wrap some long lines. 2022-06-17 13:48:12 +02:00
Ondrej Kozina
90ff707bff Move load_luks2_by_name helper. 2022-06-17 13:48:12 +02:00
Ondrej Kozina
f00d897240 Wipe unused area after reencryption with datashift in forward direction. 2022-06-17 13:48:12 +02:00
Ondrej Kozina
daa2b60d62 Sync signature wipes in tools_wipe_all_signutares. 2022-06-17 13:48:12 +02:00
Ondrej Kozina
4892b24d6a Add options parameters to tools_wipe_all_signatures routine. 2022-06-17 13:47:48 +02:00
Ondrej Kozina
369a18cd3b Rename sector size related variables. 2022-06-14 17:11:25 +02:00
Ondrej Kozina
2240e75bb9 Add proper error message for invalid device_size reencryption argument. 2022-06-14 15:31:52 +02:00
Ondrej Kozina
3a4e38736c Rename variable used to store total reencryption data size. 2022-06-14 15:31:52 +02:00
Ondrej Kozina
dff34a1251 Check datashift value against larger sector size.
For example it could cause an issue if misaligned to 4K sector
size during decryption.
2022-06-14 15:31:52 +02:00
Ondrej Kozina
c08aa21a93 Move datashift alignment verification to reencrypt_verify_resilience_params. 2022-06-14 15:31:52 +02:00
Ondrej Kozina
cbf82733ae Clarify error message about invalid datashift value. 2022-06-14 15:31:52 +02:00
Ondrej Kozina
75e429b8d1 Simplify LUKS2 sector_size helpers. 2022-06-14 15:31:52 +02:00
Ondrej Kozina
e23992d531 Fix bug in json_segment_get_sector_size.
Upper layers always expected 0 on error.
Due to this bug this function could cause
sector_size overflow when segment definition
did not contain 'sector_size' field ('linear').
2022-06-14 15:31:52 +02:00
Milan Broz
f881092bbc tcrypt: fix EPERM return code
If some kdf are not available, we incuidentally returned EINVAL
error code instead od EPERM.

This caused that error message is not correctly printed and also
retry count is not applied.

Fixes: #745.
2022-06-13 12:45:22 +02:00
Ondrej Kozina
ba37298e4f Add debug message in validation code for missing key digest. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
98ca9c61d6 Add new internal state marking resilience type as not set. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
ee5a7d19c9 Simplify reencrypt_update_flag usage due to version support. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
7b4d5fe067 Provide routine for setting LUKS2 requirement with version. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
07f8dfc46d Write updated LUKS2 reencrypt keyslot immediately. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
99a3d328f0 Harden checksum resilience parameters verification. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
e8ec3e1005 Allocate buffer for checksum resilience on-demand. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
007e56727c Refactor reencrypt_recover_segment. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
4de09ace8f Minor code refactoring in reencryption loop. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
97b88d878e Refactor internal reencrypt_hotzone_protect_final.
Avoid passing whole reencryption context when not
needed.
2022-06-09 12:03:14 +02:00
Ondrej Kozina
b43ca18c64 Postpone reencryption dm segments refresh.
Refresh (and therefore suspend hotzone) reencryption dm
segments in-before actual hotzone reencryption takes place.

This commit shortens time window during which hotzone is
suspended. Also it avoids eventual deadlock if reencryption process
triggers page miss during storage wrapper reinitialization and required
data is stored in (previously) suspended hotzone (corner case).
2022-06-09 12:03:14 +02:00
Ondrej Kozina
0768d3be84 Cleanup existing assert usage in LUKS2 json code. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
828cfdb6a2 Reduce code duplication in LUKS2 requirements handling. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
582f2c3449 Replace memset with crypt_safe_memzero where reasonable.
Better safe than sorry.
2022-06-09 12:03:14 +02:00
Ondrej Kozina
bf0d0203e8 Add routine for erasing resilience structure. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
b75a6d2b64 Properly update hash parameter for checksum resilience.
Checksum hash parameter obtained via API call can not be used directly.
It gets lost during subsequent call to crypt_reencrypt_init_by_* API
when library reloads crypt context.
2022-06-09 12:03:14 +02:00
Ondrej Kozina
450265c153 Separate reencryption params verification for update. 2022-06-09 12:03:14 +02:00
Ondrej Kozina
cfb54be9a3 Refactor reencrypt_length() function. 2022-06-09 12:03:14 +02:00
daniel.zatovic
828ddad7c2 CI: add Alpine Linux runner 2022-06-09 09:46:51 +00:00
Milan Broz
dd3fe9f5fd Check cipher before LUKS conversion to LUKS2.
There are some historic incompatibilities that are ignored
for LUKS1 but do not work for LUKS2.

Check the cipher before conversion through crypto backend.

Also it switches LUKS2_check_cipher to use userspace backend only
(this should be ok for the reencryption code that uses it too).

Fixes: #641
2022-06-09 08:50:15 +00:00
Ondrej Kozina
692bb8a455 Properly define uint32_t constants in API.
We do not change any value but it was not declared properly
and limit values had to be type cast to avoid compiler warnings
with strict options.
2022-06-07 11:30:34 +02:00
Milan Broz
6ac27f50ad Print output of symver attribute check in autoconf. 2022-06-06 07:29:38 +00:00
Milan Broz
93f90bf0f7 Do not report FIXME and empty blocks in LGTM. 2022-06-05 20:42:08 +02:00
Milan Broz
e921991ba5 Annotate LGTM TOCTOU condition.
The race here is not avoidable.
2022-06-05 20:38:22 +02:00
Milan Broz
4913de11fc Remove condition that is always true. 2022-06-05 20:29:52 +02:00
Milan Broz
82a6ae3c25 Remove condition that is always true. 2022-06-05 20:27:52 +02:00
Milan Broz
ddc8c9c441 Use %s for JSON progress print. 2022-06-05 20:26:20 +02:00
Milan Broz
fc49a258bd Add configuration file for lgtm analyser. 2022-06-04 22:30:22 +02:00
Ondrej Kozina
a1734e2d52 Revalidate LUKS2 reencrypt keyslot after update. 2022-05-26 12:13:06 +00:00
Ondrej Kozina
8f97d9b6e6 Do not refresh reencryption digest when not needed.
Due to commit 0113ac2d88
we recalculate reencryption digest whenever LUKS2 reencryption
keyslot gets updated. Until now we perform reencryption digest
refresh every time we call LUKS2_keyslot_reencrypt_update even
when no metadata was updated.

This improves on it and should speed up reencryption resume
process.
2022-05-26 12:13:06 +00:00
Ondrej Kozina
fa12a0a490 Add missing translation tag. 2022-05-26 12:13:06 +00:00
Ondrej Kozina
d9dad29149 Move LUKS2 reencrypt keyslot update procedure.
The LUKS2 reencrypt keyslot update process should
not be performed in crypt_reencrypt_run() loop where
data reencryption takes place.

The proper location is reencryption process initialization
when we validate reencryption metadata and decide if
new user provided resilience metadata are valid.
2022-05-26 12:13:06 +00:00
Ondrej Kozina
fc4b2cab25 Store proper resilience data in LUKS2 reencrypt initialization.
Prior to commit 0113ac2d88 it did
not matter what resilince metadata we stored during initialization.
So we stored 'none' type unless 'datashift' operation was initialized.

After the commit, it triggered reencryption metadata digest refresh
almost each time (except 'datashift') which was suboptimal.

By storing proper resilience type during reencryption initialization
we will avoid the needless reencryption digest refresh later (after
update optimization).
2022-05-26 12:13:06 +00:00
Ondrej Kozina
d9eff7ffd7 Test passed resilience parameter is not NULL. 2022-05-26 12:13:06 +00:00
Ondrej Kozina
2820626f5e Move LUKS2_keyslot_reencrypt_allocate function.
It does not fit internal LUKS2 keyslot API so
there's no need to hook it in it.
2022-05-26 12:13:06 +00:00
Ondrej Kozina
1cdb7da2ad Fix mem leaks on error path in reenc_keyslot_alloc. 2022-05-26 12:13:06 +00:00
Ondrej Kozina
e00eecf9ca Remove unused union member. 2022-05-26 12:13:06 +00:00
Ondrej Kozina
346f104f26 Move internal structure definition to internal header file. 2022-05-26 12:13:06 +00:00
Ondrej Kozina
082d23af92 Store data_shift value in rp structure.
data_shift value is part of recovery data
and should be stored in rp structure instead.
2022-05-26 12:13:06 +00:00
Ondrej Kozina
392b0136dc Store checksum protection data block size in rp structure.
The structure is supposed to store all data necessary to perform
reencryption crash recovery. The data block size stored
in LUKS2 metadata was missing and stored in reencryption top level handle
instead.
2022-05-26 12:13:06 +00:00
Ondrej Kozina
3a4ced84a6 Release lock on reencryption initialization error path. 2022-05-26 12:13:06 +00:00
Milan Broz
16c35d155a Fix error message for LUKS2 only cryptsetup commands.
Some cryptsetup commands requires LUKS2 device, but message
"not a LUKS device" is printed. Just change it to LUKS2.

Fixes: #741
2022-05-26 10:17:34 +02:00
Milan Broz
97a22c27dd Make crypt_load quiet if metadata is not detected.
Ths will allow automatic scan of known formats.

Errors are printed only if something is wrong with already detected metadata.

This change means that it is responsibility of the caller to print an error
message if needed.

Also fix some places without a message.

Fixes: #642
2022-05-26 10:17:32 +02:00
Milan Broz
bce9bd3a3b Use better error message for incompatible dm-integrity metadata.
If cryptsetup/integritysetup tool is too old, it can happen that
kernel dm-integrity uses more recent version of dm-integrity metadata.

Print (and also traslate) better error in this case.

Fixes: #667
2022-05-26 06:44:53 +00:00
Milan Broz
59692e3ca2 Add a test for LUKS2 integrity with detached header. 2022-05-26 06:44:53 +00:00
Milan Broz
39fda3bed1 Properly deactivate integrity device even if LUKS2 header is not available.
If LUKS2 is used with integrity protection, there is always a dm-integrity
device underneath.

We should deactivate the device if DM status return tag size (it means,
that dm-crypt uses dm-integrity DIF).

This allows "cryptsetup close <name>" peroperly remove both stacked devices
even if LUKS2 header is no longer available (like in detached header activation).
2022-05-26 06:44:53 +00:00
Milan Broz
2d2f230c9d Allow use of --header option for cryptsetup close.
This can have perhpas only one use - checking that
activated device has the same UUID.
2022-05-26 06:44:53 +00:00
Milan Broz
4dd514a12f Fix activation of LUKS2 device with integrity and detached header.
While the metadata device is detached header here, integrity
superblock is located on the data device.
For standalone integrity device it is diffferent
- data device contains only data and possible metadata device
contains integrity superblock and tag areas.

Fix it by checking metadata format.

Fixes: #609,#730
2022-05-26 06:44:53 +00:00
Milan Broz
7e6c48f67c integritysetup: mention and test xxhash64 non-crypto hash
Fast xxhash64 algoritm can be used for integrity protection.
Add implicit tag size (so user do not need to use --tag-size),
mention it in man page and add a test.

Fixes: #632
2022-05-24 14:36:25 +00:00
Milan Broz
360bd7f68d integritysetup: clarify format question message and man page if data device is used
If existing data device is used, user must specify --no-wipe option
otherwise data device is wiped.
(Tags then can be recalculated on activation with --integrity-recalculate option).

Fixes: #679
2022-05-24 14:36:25 +00:00
Vojtech Trefny
f1fd38c726 bitlk: Add warning when activating device with wrong size 2022-05-24 06:48:26 +00:00
Vojtech Trefny
795b37d128 bitlk: Add BitLocker volume size to dump 2022-05-24 06:48:26 +00:00
Milan Broz
5aa01da2b5 Fix two more lowercase ARG macro undefs. 2022-05-24 08:46:54 +02:00
Daniel Parks
3341bfd6c5 The ARG macro should be uppercased when undefining it
This isn't a bug right now, but it could be in the future if ARG is
used in a different context.
2022-05-23 17:26:48 +00:00
Vojtech Trefny
6c73057156 integrity: Fix integrity_key_size for algorithms without keys
INTEGRITY_key_size returns -EINVAL for algorithms without a key
and because crypt_params_integrity.integrity_key_size is an
unsigned integer we get key size 4294967274 instead of more
appropriate 0 for these algorithms.
2022-05-22 19:58:00 +02:00
Milan Broz
5d9e362553 Make CRYPT_WIPE_ENCRYPTED_ZERO obsolete.
It was never implemented (the idea was to speed up wipe), but
with the recent RNG performance changes it makes no longer sense.
2022-05-18 16:39:53 +02:00
Milan Broz
4d6e9e7c32 Add crypt_wipe unit test.
It uses simple C wrapper aroung crypt_wipe() libcryptsetup
and then bash test scripts wipung simple file and block device.
2022-05-18 16:39:48 +02:00
Milan Broz
227fdb7393 Fix init for util_wipe call.
It should init crypt, as it uses RNG.

Also it should fail early if no device is initialized.
2022-05-18 16:39:43 +02:00
Milan Broz
251eb37c4a Do not try to print NULL string in destructor. 2022-05-18 16:39:38 +02:00
Milan Broz
0009089855 Add ZEROOUT ioctl support for crypt_wipe.
For block devices we can use in-kernel BLKZEROOUT ioctl,
that should be faster in most cases.

This cannot be used for images in files.
2022-05-18 16:39:30 +02:00
Milan Broz
41d61df667 Set loopback sector size according to verity block sizes.
Verity block size has the same limits, so we can optimize
loop device this way.
2022-05-18 09:57:48 +00:00
Milan Broz
8945f3e9e2 Add per-keyslot options to man page.
Some options were missing for LUKS2 luksAddKey and luksChangeKey.

Fixes: #720
2022-05-17 14:37:24 +02:00
Milan Broz
8606865e15 Avoid using top_srcdir in SOURCES. 2022-05-11 09:36:26 +00:00
Milan Broz
9e7894081f Verity: dump device sizes.
Calculating device sizes for verity devices is a little bit tricky,
Data, hash and FEC can share devices or it can be a separate devices.

This patch prints used device sizes in veritysetup dump command,
but it requires that user specifies all values that are not stored
in superblock (like a FEC device and FEC roots).
2022-05-09 22:48:59 +02:00
Milan Broz
0c80ee6c28 Move verity dump to per-format directory. 2022-05-09 13:47:16 +02:00
Milan Broz
853abf53f5 Fix debug message for crypt_activate_by_signed_key.
If name is not uses, there are two spaces.
Also it is more readable now.
2022-05-09 13:46:58 +02:00
Milan Broz
3173595fc9 Avoid using bash arrays in verity test.
This will break on every small change (as in following patch).
Just grep the key word as used elsewhere.
2022-05-09 13:46:24 +02:00
Milan Broz
ede2a8a45f Add some basic UTF conversion function test.
Used only in bitlk format.
2022-05-03 15:48:09 +00:00
Milan Broz
6631033d8a Fix cryptsetup manpage to use PBKDF consitently.
Fixes: #738
2022-05-02 08:01:06 +02:00
Fabrice Fontaine
fe3878199c configure.ac: replace argp_usage check
Replace check for argp_usage by argp_parse as argp_usage is not used by
cryptsetup. Moreover, this will fix the following build failure raised
with argp-standalone in version 1.4.0 and
e7ff8d9787:

/home/autobuild/autobuild/instance-10/output-1/host/lib/gcc/i686-buildroot-linux-musl/10.3.0/../../../../i686-buildroot-linux-musl/bin/ld: tokens/ssh/cryptsetup_ssh-cryptsetup-ssh.o: in function `parse_opt':
cryptsetup-ssh.c:(.text+0x14c): undefined reference to `argp_state_help'
/home/autobuild/autobuild/instance-10/output-1/host/lib/gcc/i686-buildroot-linux-musl/10.3.0/../../../../i686-buildroot-linux-musl/bin/ld: tokens/ssh/cryptsetup_ssh-cryptsetup-ssh.o: in function `main':
cryptsetup-ssh.c:(.text+0x7db): undefined reference to `argp_parse'

Fixes:
 - http://autobuild.buildroot.org/results/cb3fdae4e0da603f304501f65127800346cb3915

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2022-04-28 17:24:35 +00:00
Milan Broz
2bf0f537f6 Add constant time memcmp and use it for comparing keys.
There is perhaps no problem now, but it is a good practise to use
constant time for key comaprison to avoid possible side channel
issues.
2022-04-28 15:19:23 +00:00
Milan Broz
4f44bb40b7 Do not print full help in CI clang scan_build. 2022-04-28 12:56:59 +00:00
Milan Broz
3ee0b37303 Use absolute path for compilers scripts.
Then make check-programs in tests directory works.
2022-04-28 12:56:59 +00:00
Milan Broz
a25d10407d Fix some scan build warnings for api-test-2. 2022-04-28 12:56:59 +00:00
Milan Broz
ae3ce2a207 Compile test also programs tests dir. 2022-04-28 12:56:59 +00:00
Milan Broz
2d8cdb2e35 Add unit test fo some functions in utils_crypt.c. 2022-04-28 08:11:58 +00:00
Milan Broz
ceed3c0c3b Introduce crypt_log_hex helper and use it for log_std output. 2022-04-28 08:11:58 +00:00
Milan Broz
e161cd1859 Add constant time crypt_bytes_to_hex helper and use it in libdevmapper.
Fixes: #736
2022-04-28 08:11:58 +00:00
Milan Broz
ff14c17de7 Use constant time conversion for crypt_hex_to_bytes.
We use hexa conversions for keys, avoid possible
leaks with cover channels by making these functions
constant time.
2022-04-28 08:11:58 +00:00
Ondrej Kozina
1ac6a58475 Simplify LUKS2_segment_first_unused_id(). 2022-04-27 11:50:48 +02:00
Ondrej Kozina
2dbd96ebbf Fix LUKS2_get_data_size function.
The function wrongly expected segment objects being
ordered (ascending order) in segments container.

The LUKS2 format never guaranteed that and it could
lead to wrong LUKS2 device size calculation in case
last segment (by key) was stored before any other segment
with fixed size.
2022-04-27 11:44:51 +02:00
Ondrej Kozina
a29f74b5ad Silent reencryption by volume key passed in file.
It emitted confusing error message. It's expected
new volume key would not match the existing one.
2022-04-26 05:46:01 +00:00
Ondrej Kozina
cc107ee20e Silent crypt_volume_key_verify call.
And moves the error message in tools instead.
2022-04-25 19:47:09 +00:00
Ondrej Kozina
c67db10c22 Do not allow sector size increase reencryption in offline mode.
The eventual logical block size increase on dm-crypt device above
filesystem block size may lead making fs unusable. Do not allow
offline reencryption when sector size increase is requested.

If users really want to perform it make them use existing
--force-offline-reencrypt option.
2022-04-25 12:18:33 +02:00
Ondrej Kozina
65a5943ee5 Check sb block size only if actual sector size gets increased. 2022-04-25 09:55:55 +02:00
Ondrej Kozina
5a8b95aa45 Clarify clean up path of empty dm_target structure. 2022-04-22 15:02:41 +00:00
Milan Broz
f391f4baf1 Fix memory leaks in integrity resize with keyed parameters.
The whole game with reallocating keys is not needed.

(Perhaps not even for crypt type, but that is not part of this patch).
2022-04-22 11:34:13 +02:00
Milan Broz
4cdcd908f4 Fix memory leak in integrity resize api-test. 2022-04-21 08:21:01 +00:00
Milan Broz
1d6a445e43 Fix integrity api-test.
The journal crypt is in wrong format (this never worked! :),
here it takes kernel syntax.
Also use CBC a CTR mode could be missing here.

Fox typo in key length caclulation.

Clear temporary dm devices after test, loop devices are reused.

If the first device format is ok, all subsequent cals should
be treated as an error.
2022-04-21 08:21:01 +00:00
Milan Broz
ed13852899 Fix reload integrity device.
The offset cannot be referenced from the crypt union for integrity type.

Keyring setting key works only for crypt devices.

Also reformat long lines.
2022-04-21 08:21:01 +00:00
Milan Broz
efc1590405 Fix formatting warning for a 32bit arch. 2022-04-21 08:21:01 +00:00
Milan Broz
4b1ba47ca1 Avoid compilation warning if configured with --disable-blkid. 2022-04-20 16:08:58 +00:00
Milan Broz
e4a0d25315 Fix missing batch option in test. 2022-04-20 16:08:58 +00:00
Milan Broz
81a63aca22 Fix tests if compiled with --disable-blkid.
Note that htere are some systems with blkid but without
blkid support for secondary LUKS2 header (CentOS6 for example).
2022-04-20 16:08:58 +00:00
Milan Broz
ebabf3ffee Add compile-in flag to program version output.
Then we can check if tools are compiled with a support for specific
extension/library.
2022-04-20 16:08:58 +00:00
Milan Broz
3363bad8c2 Speed-up tcrypt test.
We can limit hash and cipher to not scan all variants here.
2022-04-20 14:37:13 +00:00
Milan Broz
773fc0195f Fix typos found by codespell.
Thanks Dimitri Papadopoulos Orfanos for the patch.

Fixes: #734.
2022-04-20 14:37:13 +00:00
Milan Broz
d3ad18ad81 Add compile info to README.
This information was lost when we removed default automake INSTALL file.
2022-04-20 14:37:13 +00:00
Milan Broz
5c7858883c Remove cryptsetup-reencrypt version dump from tests. 2022-04-20 14:37:13 +00:00
Ondrej Kozina
c9da460b6c Do not allow dangerous sector size change during reencryption.
By changing encryption sector size during reencryption we may
increase effective logical block size for dm-crypt active device.

For example if hosted filesystem on encrypted data device
has block size set to 512 bytes and we increase dm-crypt logical
size durign reencryption to 4096 bytes it breaks the filesystem.

Do not allow encryption sector size to be increased over value
provided by fs superblock in BLOCK_SIZE property.

The check is applied while initialising LUKS2 device encryption
(reencrypt --encrypt/--new) or when initialising LUKS2 reencryption
on active dm-crypt device.

Note that this check cannot be applied on offline device (data device
is encrypted).
2022-04-19 13:27:37 +00:00
Ondrej Kozina
38d1f01b12 Add tools helper reporting blkid support. 2022-04-19 13:27:37 +00:00
Ondrej Kozina
624026a98f Refactor reencrypt_get_active_name helper. 2022-04-19 13:27:37 +00:00
Ondrej Kozina
f6452e1656 Add superblock BLOCK_SIZE detection in tools. 2022-04-19 13:27:37 +00:00
Ondrej Kozina
2388777763 Add option to probe only superblocks in blkid. 2022-04-19 13:27:37 +00:00
Ondrej Kozina
be5c5788d4 Add support for superblock BLOCK_SIZE property. 2022-04-19 13:27:37 +00:00
Milan Broz
f1eea3a4b3 Clean reencrypt status struct for API call.
This function should not return unitialized struct as there
is no indication that it failed and caller can access it.

Also fixes a Coverity warning.
2022-04-19 08:53:44 +00:00
Milan Broz
2857e10083 Fix UTF16 buffer overflow in bitlk volume key dump.
It is UTF16, so even the terminating character is char16_t.

(Found by gcc sanitizer.)
2022-04-17 13:59:03 +02:00
Milan Broz
99c4c3adbf Skip question if batch mode is set for volume key bitlk dump.
Other formats use the same logic.
2022-04-17 13:58:08 +02:00
Milan Broz
f34b3b27ec Do not use definitions in for cycle. 2022-04-15 21:44:52 +02:00
Milan Broz
ab6762b849 Fix possible missing uchar.h. 2022-04-15 21:43:45 +02:00
Milan Broz
3fbc480e32 Clean headers for utf8 wrapper. 2022-04-15 21:22:07 +02:00
Milan Broz
ce1c39dc54 Properly report if sectior size cannot be used for bitlk activation. 2022-04-15 21:02:52 +02:00
Milan Broz
9b60e2d959 Add some tests for invalid keyslot JSON objects. 2022-04-14 10:28:20 +00:00
Milan Broz
e89071e73f Fix keyslot JSON validation.
If keyslot JSON is corrupted (kdf,af,area objects),
validate function can crash.

Fix it by always using JSON type check.

Fixes: #731
2022-04-14 10:28:20 +00:00
Ondrej Kozina
dbd4dc1dc0 Speedup reencryption tests. 2022-04-13 16:23:01 +02:00
Ondrej Kozina
acd2601bd7 Drop unused code in lib/utils_blkid.c 2022-04-13 16:16:57 +02:00
Ondrej Kozina
d56ccc97b8 Detect broken LUKS metadata in-before encryption.
We should abort LUKS device in-place encryption
when target data device or metadata device
contain broken LUKS metadata (any version).
Filed crypt_load() call was not good enough check
because the call fails also when a device contains
LUKS metadata overlapping with other superblock
(e.g. LVM2 PV signature).

Let blkid decide if device contains broken LUKS
metadata or not.

Fixes: #723.
2022-04-11 11:38:56 +00:00
Ondrej Kozina
412de7dc25 Add suport for filtering only LUKS signatures. 2022-04-11 11:38:56 +00:00
Ondrej Kozina
8c350b65a3 Prepare tools_detect_signatures for new filter type. 2022-04-11 11:38:56 +00:00
Milan Broz
83ef36bd59 Add tests for LUKS2 JSON mangled top-level objects. 2022-04-09 21:27:09 +02:00
Milan Broz
c07cfa20de test generators: unify checksum check functions 2022-04-09 21:25:55 +02:00
Milan Broz
6d8587c137 test generators: unify kill header check functions 2022-04-09 21:25:55 +02:00
Milan Broz
d43b495f21 test generators: unify mangle & kill header functions 2022-04-09 21:25:55 +02:00
Milan Broz
e97238fb6d test generators: use one common cleanup function 2022-04-09 21:25:55 +02:00
Milan Broz
c9ead0482d test generators: use one common prepare function 2022-04-09 21:25:55 +02:00
daniel.zatovic
9c26a73d96 Validate JSON area root objects' types. 2022-04-07 15:29:05 +00:00
Ondrej Kozina
ea35573c82 Ask user for confirmation before resuming reencryption.
The prompt is not showed in batch mode or when user
explicitly asks for reencryption resume via --resume-only.
2022-04-07 13:50:09 +02:00
Ondrej Kozina
d3079c2fb3 Do not resume reencryption with conflicting parameters.
Do not resume reencryption operation with conflicting parameters.
For example if operation was initialized as --encrypt do not
allow resume with oposing parameter --decrypt and vice versa.

Also checks for conflicting --resilience parameters (datashift cannot
be changed after initialization).

Previously, conflicting reencryption parameters were silently ignored.
So, for example operation initialized with mode --encrypt and resumed
with mode --decrypt simply finished --encrypt operation and did not
report any error. This could lead to impresion different type of
operation was perfomed instead.

Fixes: #570.
2022-04-07 13:49:40 +02:00
Ondrej Kozina
b661452e3a Asks offline reencryption confirmation only with image files.
If auto-detection fails for other reason just return the
error. Users may now bypass active device auto-detection
with --force-offline-reencrypt option.
2022-04-07 11:51:41 +02:00
Ondrej Kozina
31c4afbc17 Add --force-offline-reencrypt option.
It can be used to enforce offline reencryption
in batch mode when data_device is regular file
and therefore cryptsetup cannot detect properly
active device dm name.

Also it may be useful when active device
auto-detection fails for some reason and user
has no other choice but inspect device holders
manually.
2022-04-06 22:59:37 +02:00
Ondrej Kozina
496a0e37c4 Active device auto-detection code cleanup. 2022-04-06 22:59:35 +02:00
Ondrej Kozina
8c04264fb3 Reduce code duplication in active device auto-detection. 2022-04-06 22:57:13 +02:00
Milan Broz
db1ff4cf88 Silence false positive Coverity warning.
The init_keyslot_passwords() allocates properly sized arrray here.
2022-03-30 17:53:14 +02:00
Milan Broz
3e4368feeb Use link to main branch. 2022-03-30 13:08:57 +02:00
Milan Broz
faee0e694f Use main branch in GitHub CI. 2022-03-30 13:07:55 +02:00
Milan Broz
7a38f16cef Use volume key in FAQ. 2022-03-29 19:06:38 +00:00
Milan Broz
08aa2ca242 Replace master on a few more places. 2022-03-29 19:06:38 +00:00
Milan Broz
3a56cf05bf Replace mk_ with vk_ name prefix. 2022-03-29 19:06:38 +00:00
Milan Broz
b6c36f50ba Replace name master with volume key.
And keep two tests for compatibility.
2022-03-29 19:06:38 +00:00
Milan Broz
b050448db9 Add aliases for --volume-key-file and --dump-volume-key-file. 2022-03-29 19:06:38 +00:00
Milan Broz
68796e12dd Replace OPT_MASTER_KEY_FILE_ID with OPT_VOLUME_KEY_FILE_ID. 2022-03-29 19:06:38 +00:00
Milan Broz
650c7e8b67 Enable csmock for merge requests. 2022-03-29 15:40:48 +00:00
Milan Broz
0dc18fba22 Fix a leak in error path.
Also fix a warning, all detected by Coverity scan.
2022-03-29 15:40:48 +00:00
Milan Broz
1116289de4 Try to load dm-integrity in api-test. 2022-03-29 14:17:53 +00:00
Milan Broz
1595fcf479 Do not run keyed integrity resize tests for older kernel. 2022-03-29 14:17:53 +00:00
Milan Broz
c4c1ca2224 Use batch mode for integrity resize test. 2022-03-29 14:17:53 +00:00
Ondrej Kozina
2b42968e92 Port cryptsetup --new option to CRYPT_ARG_ALIAS type. 2022-03-29 12:54:58 +02:00
Ondrej Kozina
e2a5af9e64 Add new argument type CRYPT_ARG_ALIAS.
It can be used to easily define option
aliases for command line utilities.
2022-03-29 12:54:15 +02:00
Milan Broz
e4ed545cbf Remove debug line from api-test. 2022-03-28 22:27:54 +02:00
Ondrej Kozina
65be641f20 Refactor LUKS reencryption. 2022-03-24 15:14:32 +00:00
Ondrej Kozina
ce55fa4d1c Refactor LUKS decryption. 2022-03-24 15:14:32 +00:00
Ondrej Kozina
92baacadad Refactor LUKS encryption.
It also adds hardened checks for accidental
nested device encryption.
2022-03-24 15:14:32 +00:00
Ondrej Kozina
2e59229e5a Add checks for some conflicting requests.
It also moves device load for reencryption purposes
further up in code path to better optimize the code
later.
2022-03-24 15:14:32 +00:00
Ondrej Kozina
3f42b69fc8 Add reencrypt_luks2_resume helper.
To be used later.
2022-03-24 15:14:32 +00:00
Ondrej Kozina
b10c0b6a02 Simplify load_luks2_by_name.
Also adds specific error messsage when device
is not actualy LUKS2.
2022-03-24 15:14:32 +00:00
Ondrej Kozina
f388662418 Remove 'type' argument from load_luks helper.
The code removal will help simplify further code
changes.
2022-03-24 15:14:32 +00:00
Ondrej Kozina
8bc10ee853 Rename luks2 reencryption initialization routines. 2022-03-24 15:14:32 +00:00
Ondrej Kozina
b663b9305c Add helper for checking data device type during encryption.
In case operation is invoked with --header parameter
check if data device does not already contain LUKS device
2022-03-24 15:14:32 +00:00
Ondrej Kozina
828555db97 Remove unused code in helper routine. 2022-03-24 15:14:32 +00:00
Ondrej Kozina
ba08f02a40 Move helper for LUKS2 auth. encryption detection. 2022-03-24 15:14:32 +00:00
Ondrej Kozina
a55b0530a4 Restrict --active-name to LUKS2 type only. 2022-03-24 15:14:32 +00:00
daniel.zatovic
a2f30ebd4c Display progress when wiping the end of resized device. 2022-03-24 11:38:16 +01:00
daniel.zatovic
d20d41c7a5 Add log messages, when kernel doesn't support resize. 2022-03-24 11:38:16 +01:00
daniel.zatovic
4eba55c73e Add tests for integritysetup resize action. 2022-03-24 11:38:16 +01:00
daniel.zatovic
29ddd68a0f Add API tests for resize of integrity volume. 2022-03-24 11:38:16 +01:00
daniel.zatovic
9707b71f98 Describe resize action in manual page. 2022-03-24 11:38:16 +01:00
daniel.zatovic
36cdda870b Add resize action to integritysetup.
Fixes: #594.
2022-03-24 11:38:16 +01:00
daniel.zatovic
9b8a872006 Add support for resizing raw integrity devices. 2022-03-24 11:38:16 +01:00
daniel.zatovic
45b808c186 Move checking for detached integrity metadata device.
To allow resizing integrity devices with detached metadata device, the
check has to be moved from _compare_integrity_devices to
_reload_device_with_integrity.
2022-03-24 11:38:16 +01:00
daniel.zatovic
87afb9d783 Remove size parameter comparison for integrity devices.
To support device resize, we can not compare the device size (it is
already not compared for crypt devices).
2022-03-24 11:38:16 +01:00
daniel.zatovic
86402a1102 Add API tests for refreshing integrity devices. 2022-03-24 11:38:16 +01:00
daniel.zatovic
64e7c3d3b1 Add support for refreshing integrity devices.
If the provided key is NULL, we load it from the active device. This is
always available, since keyring keys are not supported in kernel for
integrity devices.
2022-03-24 11:38:16 +01:00
daniel.zatovic
f6c1445c6b Add support for querying journal active devices for integrity and encryption keys. 2022-03-18 09:56:59 +00:00
Ondrej Kozina
f5724a30f9 Test nested encryption is not possible. 2022-03-17 19:07:10 +00:00
Ondrej Kozina
47f31205cf Do not allow nested encryption in LUKS reencrypt.
Try to avoid accidental nested encryption via
cryptsetup reencrypt --new/--encrypt command.

If detached header or data device is already reported
as LUKS1 or LUKS2 device operation gets aborted.

Fixes: #713.
2022-03-17 19:07:10 +00:00
Ondrej Kozina
5bd5462a9e Improve helpers for reencryption utilities.
Also clarifies some code path.
2022-03-17 19:07:10 +00:00
Ondrej Kozina
d1f0376c77 Decouple auth. encryption check from in-reencrypt detection. 2022-03-17 19:07:10 +00:00
Ondrej Kozina
dae91fd9ec Code reshuffle in-before some changes. 2022-03-17 19:07:10 +00:00
daniel.zatovic
df4ed89141 CI: disable updates. 2022-03-17 19:04:41 +00:00
Milan Broz
559012b6a7 Check dm-zero availability for bitlk type.
Bitlocker compatible mode uses dm-zero to mask metadata area,
device cannot be activated if dm-zero is not available.

Just add zero target check to device-mapper backend and
if activation fails, print a better error message here.

Fixes: #722
2022-03-16 12:21:30 +01:00
Milan Broz
6534e86c22 Update gitignore. 2022-03-15 13:12:27 +01:00
Milan Broz
70c1eb7352 Support make check-programs target from top level makefile.
Also fix genereated header dependence.
2022-03-15 13:07:10 +01:00
Ondrej Kozina
dee2fa7159 Prefer token PIN query before passphrase in some case.
When user provides --token-type or specific --token-id
prefer token PIN query over passphrase query (if token
handler responds with 'PIN needed').

Fixes: #670.
2022-03-14 17:34:41 +01:00
Ondrej Kozina
3af754b5eb Use proper function parameter in token pin helper. 2022-03-14 17:33:41 +01:00
Ondrej Kozina
3b85ab2dc1 Do not continue operation when interrupted in PIN prompt. 2022-03-14 14:04:36 +00:00
Ondrej Kozina
2a5483d8c3 Add progress function init before reencryption loop.
Otherwise elapsed time tracking is off and also breaks
speed estimation.
2022-03-07 12:35:38 +01:00
Ondrej Kozina
8340d0cb1a Remove useless condition in reencryption loop.
(always true)
2022-03-07 12:35:38 +01:00
Ondrej Kozina
3cd5d83ee9 Add --progress-json parameter to utilities.
Progress data can now be printed out in json format
suitable for machine processing.
2022-03-07 12:35:38 +01:00
Ondrej Kozina
6852c49d0c Merge progress functions into single routine. 2022-03-07 12:35:38 +01:00
Ondrej Kozina
63c79256e4 Refactor time diff calculation helper. 2022-03-07 12:35:38 +01:00
Ondrej Kozina
75622b332b Improve progress routine for cryptsetup utilities.
The progress routine is now fully translated and
prints out progress in following manner (examples):

Progress: 25,5%, ETA 00m31s, 7 GiB written, speed 838,6 MiB/s
Progress: 25,5%, ETA 20h11m31s, 7 GiB written, speed 24 KiB/s
Progress: 25,5%, ETA 06 days, 12 MiB written, speed 4 KiB/s

Also got rid of -lm dependency due to floor().

Fixes: #671.
2022-03-07 12:35:38 +01:00
Ondrej Kozina
c1e94abbab Move progress utilities in separate file. 2022-03-07 12:35:38 +01:00
Ondrej Kozina
1af7eefbc0 Minor time progress print out improvements.
Mostly moves float arithmetics in slow path and
also cleans up code a bit.
2022-03-07 12:35:37 +01:00
Milan Broz
bf4a039d50 Add a debug info if maximum interactive passphrase was read (possible trimmed).
If passphrase is read from a real terminal, there is maximum
interactive input length applied. This means that passphrase
can be trimmed in this case.

This patch adds debug log warning, if read does not detect
end of input (EOL or EOF) and the maximal input read is achieved.

We cannot say for sure if the next character is EOL without
actually reading it, debug warning should be enough in this case.

Fixes: #699
2022-02-25 14:14:03 +01:00
Milan Broz
0085985419 Fix gcc warnings in tests. 2022-02-24 20:28:29 +01:00
Milan Broz
12c35da768 Check all snprintf calls for returning values for tests. 2022-02-24 20:28:25 +01:00
Milan Broz
677e06c48a Check all snprintf calls for returning values. 2022-02-24 20:28:18 +01:00
Milan Broz
c27d6a89bb Add hint for false positive coverity warning. 2022-02-24 14:04:24 +01:00
Milan Broz
e5ce189db8 Add info about broken Intel QAT crypt drivers to FAQ. 2022-02-24 11:05:25 +01:00
Milan Broz
3407cbbad1 Add info about bug report to FAQ and add SECURITY.md file. 2022-02-23 22:20:09 +01:00
Milan Broz
2c91590d52 Add info about CVE-2021-4122 to FAQ. 2022-02-23 21:35:20 +01:00
Milan Broz
c5e500ea0f Add note about fake RAID and data corruption.
Fixes: #714
2022-02-23 21:27:05 +01:00
Milan Broz
5efe03ddd7 Update mailing list info in FAQ. 2022-02-23 21:08:34 +01:00
Ondrej Kozina
8ab41e0776 Improve debug messages while verifying reencryption metadata. 2022-02-23 15:00:11 +01:00
Ondrej Kozina
f671febe64 Add more tests for --test-passphrase parameter. 2022-02-23 15:00:11 +01:00
Ondrej Kozina
0a9f14c658 Fix --test-passphrase when device in reencryption.
Commit 0113ac2d broke test passphrase mode when
device was in LUKS2 reencryption.

Previously --test-passphrase parameter automatically raised
CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY flag. It did not make sense
when users mostly want to test whether device can be activated by
provided passphrase or not. Raise the aforementioned flag only
if user requested it either by --unbound parameter or when
specific keyslot was selected.

Reported in: https://bugzilla.redhat.com/show_bug.cgi?id=2056439

Fixes: #716.
2022-02-23 15:00:08 +01:00
Ondrej Kozina
6b774e617b Remove unused funtion prototype and few useless comments. 2022-02-23 12:28:20 +01:00
Milan Broz
0d6b63a6a2 FAQ: Use relative links in chapter references. 2022-02-22 12:17:25 +01:00
Milan Broz
6018d2bcd8 Use markdown version of FAQ. 2022-02-22 12:03:37 +01:00
Ondrej Kozina
d5dbde5dd1 Clarify graceful reencryption interruption.
Currently it can be interrupted by both SIGINT and SIGTERM
signals.

Fixes: #715.
2022-02-21 11:38:57 +01:00
Milan Broz
ef7559bad9 Print output of verity test if concurrent check fails.
This tests randomly fails in CI, at least print output if this happens.
2022-02-21 10:13:38 +00:00
Milan Broz
e9e994fb0d Run some io to actually test dm-crypt flags. 2022-02-21 10:13:38 +00:00
Arno Wagner
c5d9f3f380 Typos, additional info on dd use. 2022-02-20 20:19:16 +00:00
Milan Broz
d23943f989 Fix old list archive link. 2022-02-17 19:58:55 +01:00
Milan Broz
b47b89adac Add new list info. 2022-02-17 19:56:00 +01:00
daniel.zatovic
452467661e Support --device-size option for plain devices. 2022-02-13 08:52:39 +00:00
Ondrej Kozina
bef46c950d Properly detect optimal encryption sector size.
Move code setting data device during format so that
we can properly detect optimal encryption sector size
for data device instead of metadata device (header).

Fixes: #708.
2022-02-09 15:43:25 +01:00
Milan Broz
5c323e9146 Remove ssh backgroud option causing spurious test failures.
The keyfile creation must be synchronous, otherwise following command
can fail ("SFTP server: No such file").
2022-02-08 22:12:35 +01:00
Milan Broz
33d8605924 Fix duplicate ssh plugin error message. 2022-02-08 22:12:31 +01:00
Vojtech Trefny
76086dbe95 ssh-plugin-test: Make the test fail if SSH setup fails
We should avoid silently skipping the test if there is something
wrong with the test itself. If we have all dependencies, the test
should be able to run.
2022-02-08 16:10:31 +01:00
Vojtech Trefny
7eb44f32a3 ssh-plugin-test: Copy SSH key manually instead of with ssh-copy-id
ssh-copy-id requires password authentication that might be disabled
on some cloud images. We can simply copy the key manually, because
everything runs on localhost anyway.

Fixes: #701
2022-02-08 16:10:08 +01:00
Milan Broz
cef0dc059a Add missing variable to run ssh plugin test. 2022-02-08 10:45:12 +01:00
Milan Broz
e4091fe8a5 Fix some benign warnings with gcc-12.
The string buffer is large enough, but gcc do not understant it.
Easy to avoid these warnings with a larger buffer here.
2022-02-06 18:03:49 +01:00
Milan Broz
685148af00 Enable new warnings (introduced in gcc-12). 2022-02-06 18:02:41 +01:00
Ondrej Kozina
8798aa0a75 Do not upload keys in keyring during offline reencryption.
Fixes: #696.
2022-02-05 10:29:55 +00:00
Ondrej Kozina
7ca1a233f1 Split reencrypt_verify_and_upload_keys function. 2022-02-05 10:29:55 +00:00
Ondrej Kozina
ab295b1159 Do not resume device when not suspended.
Abort action luksResume early if device is not suspended.
We would needlesly ask for passphrase or load cryptsetup
plugins only to fail later in crypt_resume_by_* API.
2022-02-04 13:41:24 +01:00
Ondrej Kozina
fea648cb1d Add support for crypt_resume_by_token_pin in cryptsetup. 2022-02-04 13:40:22 +01:00
Ondrej Kozina
ce6f6a48e8 Add crypt_resume_by_token_pin API. 2022-02-04 13:40:20 +01:00
Ondrej Kozina
416f1343fe Split LUKS2_activate_by_token. 2022-02-04 13:32:45 +01:00
Ondrej Kozina
388ba9f00d Add explicit tests for command failure in LUKS1 reencryption test. 2022-02-04 11:28:05 +01:00
Ondrej Kozina
e38a184907 Avoid partial read in luks1 reencryption loop.
Starting with kernel 5.17-rc there are some changes
in block layer aiming to block partial I/O in
O_DIRECT mode.
2022-02-04 11:28:05 +01:00
Milan Broz
f2dbab7043 Add more label/susbystem API tests. 2022-02-03 11:43:04 +01:00
Luca Boccassi
2938c1f077 Add crypt_get_label/subsystem
There's an API to set the label and subsystem, and they are
dumped with luksDump, but there's no programmatic interface
to query them.
2022-02-03 10:23:57 +00:00
Milan Broz
95d35ecf4b Allow CI rawhide runner to fail.
As there is often something broken (currently kernel), let's just
set it to allow_failure in CI.
2022-02-03 11:21:48 +01:00
Milan Broz
a1baa01ddd Set higher timeout for interactive tests.
Under heavy load 10 seconds is not enough, just use the same
values as when running under valgrind.
2022-02-03 08:05:11 +01:00
Ondrej Kozina
7ab7365020 Add check program for symver attribute.
Fixes: #709.
2022-02-02 21:30:48 +00:00
daniel.zatovic
43a636d809 CI: Detect core dumps generated during testing 2022-02-02 20:32:53 +00:00
Milan Broz
8531a8a753 Skip more tests if --disable-cryptsetup is used.
If there is no cryptsetup, some tests returns ok while noting was
tested in reality. Just mark them skipped.
2022-02-02 21:29:54 +01:00
Alyssa Ross
c0cef43a4e Skip cryptsetup tests when cryptsetup is disabled
If configured with --disable-cryptsetup (e.g. if only veritysetup is
required), these tests won't be able to run cryptsetup, so they need
to be skipped.
2022-02-02 16:51:49 +00:00
Ondrej Kozina
06b6542b28 Remove -Wno-attributes from -Wall tests.
It breaks compile time check for __attribute__((__symver__))
and it does not make sense either. Quoting gcc man page:

-Wno-attributes

Do not warn if an unexpected "__attribute__" is used, such as
unrecognized attributes, function attributes applied to variables,
etc. This does not stop errors for incorrect use of supported attributes.

Well, we do want to check for unsupported __attributes__ un our code,
right?
2022-02-02 15:05:09 +01:00
Milan Broz
03adc091ce Use tabs in SSH plugin test. 2022-01-29 12:07:38 +01:00
Milan Broz
f85921497c Remove loop device use from SSH plugin test. 2022-01-29 12:07:35 +01:00
Milan Broz
ab975bc1c4 Update copyright year.
And unify format in several places.
2022-01-29 10:43:02 +01:00
Milan Broz
0cb4f59006 Rename encrypt helper function to avoid clash with unistd prototype. 2022-01-29 10:21:06 +01:00
Ondrej Kozina
230b80404d Remove parameters annotated by __attribute__((unused)).
Attribute unused is useless and makes code imcomprehensible
when decorates internal functions not exposed via API.

Let's cleanup internal funtion prototypes whenever possible.
2022-01-28 17:27:00 +00:00
Alex Xu (Hello71)
46efbc0a36 argon2: Don't call _endthreadex/pthread_exit
Returning from the thread creation function is documented to be a valid
way of exiting a thread on both Windows and pthread systems. Removing
the explicit call avoids the need to install libgcc_s.so in initramfs
for glibc systems, and slightly reduces code size.

Upstream: https://github.com/P-H-C/phc-winner-argon2/pull/331
2022-01-28 15:06:08 +00:00
Milan Broz
903dae1b6c Enable clang and gcc cast-align[=strict] warning in CI. 2022-01-26 10:28:57 +00:00
Milan Broz
0b2c4187b0 Workaround clang alignment warnings (Wcast-align) when working with byt arrays.
This should silence similar warnings like
  warning: cast from 'char *' to 'struct xyz *' increases required alignment from 1 to X
when we try to calclulate byte pointer offsets in a buffer.
2022-01-26 10:28:57 +00:00
Milan Broz
c11a83bf0f Enable clang -Wextra and -Wsign-compare build in CI. 2022-01-26 10:28:57 +00:00
Milan Broz
a68eb60be9 Fix clang warnings for integer comparison. 2022-01-26 10:28:57 +00:00
daniel.zatovic
48872e9f2e CI: Save journalctl in artifacts. 2022-01-25 22:24:39 +01:00
daniel.zatovic
bb35a284e8 CI: Save dmesg in artifacts. 2022-01-25 22:24:33 +01:00
Vojtech Trefny
793b7cddaf bitlk: Fix coverity warnings introduced in 6e47fb6d 2022-01-24 17:54:54 +01:00
Ondrej Kozina
161eeb7473 Fix resource leaks in utils_reencrypt.c
Fixes: #703.
2022-01-24 16:29:35 +00:00
daniel.zatovic
71f33418d2 Add FIPS update again. 2022-01-24 12:04:23 +01:00
daniel.zatovic
f4e2daec94 Fix annocheck job. 2022-01-22 22:24:10 +01:00
Milan Broz
34f033b254 Do not use too small key in tests.
Apparently FIPS mode enforces somewhere minimal key size.
As 64bit key is no longer useful anyway, just remove it.

Apparently cipher_null is now more safer with the longer key,
isn't? :-)
2022-01-21 12:30:10 +01:00
Milan Broz
91db91352f Get rid of SHA1 in tests.
OpenSSL with FIPS provider now doesn't not support SHA1.
Kernel still does, but some operations fail anyway (we get
hash size from crypto backend).

Let's remove most of the SHA1 use in tests, SHA1 removal
will happen anyway.

The LUKS1 compatimage is regenerated with the same parameters,
just hash is switched to sha256 so we do not need to fix tests.
2022-01-21 12:29:36 +01:00
Milan Broz
05a237be2a Fix PBKDF benchmark in OpenSSL3 FIPS mode.
OpenSSL now enforces minimal parameters for PBKDF2 according to SP 800-132
key length (112 bits), minimal salt length (128 bits) and minimal number
of iterations (1000).

Our benchmark violates this, causeing cryptsetup misbehave for luksFormat.

Just inrease tet salt to 16 bytes here, it will little bit influence benchmark,
but there is no way back.
2022-01-21 09:47:13 +01:00
daniel.zatovic
cb9a204a98 Remove merge jobs and RHEL 9 FIPS package updates. 2022-01-20 15:10:17 +00:00
daniel.zatovic
bec18489c7 Add new RHEL and CentOS runners. 2022-01-20 15:10:17 +00:00
Milan Broz
f596e48cc4 Increase timeout for interactive input test. 2022-01-20 14:37:31 +01:00
Vojtech Trefny
ae213537ba utf8: Fix clang null pointer dereference warning 2022-01-20 13:01:05 +01:00
Milan Broz
c4e60a7037 Use only default flags for test CI compilation. 2022-01-20 11:27:04 +01:00
Milan Broz
12a07dcdbd Fix scan-build to fail for reported warnings. 2022-01-20 11:16:55 +01:00
Vojtech Trefny
6e47fb6d85 Use custom utf8/16 conversion instead of iconv
We can avoid the additional dependency by using few functions from
systemd.
2022-01-19 17:09:32 +00:00
Ondrej Kozina
e12ce642a1 Fix typo in repair prompt. 2022-01-19 14:31:11 +01:00
Milan Broz
9a1b3a8aff Remove old base64 implementation and switch to crypto_backend.
This completely removes old base64 implementation.
Code was originally taken from coreutils but recent changes
added many new funtions we do not need.
2022-01-18 12:15:20 +01:00
Milan Broz
f1c7a9896d Add base64 wrappers to crypto_backend.
We need LGPL 2.1+ implementation in crypto backend and also this code
is much easier to read and maintain.
2022-01-18 12:15:20 +01:00
Vojtech Trefny
c210c3a665 man: Fix default locking directory in cryptsetup man page
The default location has been changed from /run/lock/cryptsetup to
/run/cryptsetup in 6f4c15b2b2.
2022-01-17 07:31:54 +01:00
Milan Broz
8e27541a3b Relax a little bit warnings in CI and run it in merge requests.
It is almost impossible for contributors to replicate our warnings
if filtered. Let's make it simpler.

Also run clang with extended warnings (some fixes needed).
2022-01-15 16:11:49 +01:00
Guilhem Moulin
1592511fdb Local tests: Add option to avoid treating skipped tests as success.
`make -f Makefile.localtest tests CRYPTSETUP_PATH=/sbin TESTSUITE_NOSKIP=y`
exits with status 77 upon the first skipped test.  This can be useful
when a full test coverage is desired.

As before the test suite exits (with status 1) as soon as a failed (or
skipped when the TESTSUITE_NOSKIP environment variable is defined to
non-empty string) test is encountered.
2022-01-15 11:55:18 +00:00
Guilhem Moulin
cbc143bf95 tests: Replace which calls with command -v.
AFAIK older versions of the POSIX Standard didn't specify a way to
locate commands.  Many operating systems and distributions added a
which(1) utility for that purpose, unfortunately without consistent
behavior across the board.

OTOH POSIX.1-2008 (or was it older?  POSIX.1-2001 mentions it too, but
with a restriction: “On systems supporting the User Portability Utilities
option”) specifies that `command -v` can be used for that purpose:

    https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/utilities/command.html

Moreover the standard adds that if the argument is neither a valid
utility, builtin, shell function nor alias then “no output shall be
written and the exit status shall reflect that the name was not found”.
It's therefore no longer needed to void the error output (spewing error
messages was one of the inconsistent behavior of the different which(1)
utilities).

The upcoming Debian 12 (codename Bookworm) appears to have deprecated
its which(1) utility (as a first step for its removal from the base
system):

    $ which foo
    /usr/bin/which: this version of `which' is deprecated; use `command -v' in scripts instead.

In most places the deprecation notice isn't visible when running the
test suite because most `which` calls run with the error output
redirected to /dev/null, however this is not the case everywhere:

    https://gitlab.com/cryptsetup/cryptsetup/-/blob/v2.4.3/tests/integrity-compat-test#L333
    https://gitlab.com/cryptsetup/cryptsetup/-/blob/v2.4.3/tests/reencryption-compat-test2#L232

This commit replaces all `which` calls from tests/* with `command -v`,
and removes the error output redirection.
2022-01-15 08:50:15 +00:00
Guilhem Moulin
3e160447eb Fix minor spelling error.
(Found by Lintian.)
2022-01-14 15:48:25 +01:00
Milan Broz
5ab106465c Update README. 2022-01-13 10:23:27 +01:00
Milan Broz
79720dabb9 Fix reencrypt mangle test for older jq. 2022-01-13 10:07:38 +01:00
Milan Broz
0bff50a31a Remove reference to missing test. 2022-01-12 18:38:37 +01:00
Milan Broz
c2291a1b9b Add Release Notes. 2022-01-12 18:38:30 +01:00
Milan Broz
f1d7d30dbb Update LUKS2 on-disk description. 2022-01-12 18:38:26 +01:00
Ondrej Kozina
00feca3ce0 Allow reencryption metadata repair from cryptsetup. 2022-01-12 18:38:22 +01:00
Ondrej Kozina
ea47937187 Add CRYPT_REENCRYPT_REPAIR_NEEDED flag.
crypt_reencrypt_status() returns this flag if old
online-reencrypt requirement is detected and reencryption
keyslot digest is missing.

crypt_reencrypt_init_by_passphrase() with same flag applied
repairs (upgrade) reencryption metadata so that
automatic reencryption recovery during activation
is again possible and reencryption operation can be resumed
post CVE-2021-4122 fix.
2022-01-12 18:38:17 +01:00
Milan Broz
f77b26b42b Add reencryption mangle test 2022-01-12 18:38:14 +01:00
Ondrej Kozina
6c8314b297 Make reencryption flag and keyslot inseparable.
LUKS2 validation code now requires reencrypt keyslot together with
online-reencryption flag or none of those.
2022-01-12 18:38:10 +01:00
Ondrej Kozina
59e39e484a Rename LUKS2_keyslot_reencrypt_create function.
The function never writes on-disk. Also removed validation
function call-in since it will be called later before
writing on-disk and metadata does not have to be complete
at the moment of LUKS2_keyslot_reencrypt_allocate call.
2022-01-12 18:38:06 +01:00
Ondrej Kozina
b61ec23e48 Add segments validation for reencryption.
Effective segments during LUKS2 reencryption must
match key characteristics of backup segment
(cipher, sector_size, segment type).
2022-01-12 18:37:52 +01:00
Ondrej Kozina
7420f879e0 Split requirements validation from config section validation. 2022-01-12 14:01:44 +01:00
Ondrej Kozina
7de8ff5ccf Expose json_segment_contains_flag to internal library. 2022-01-12 14:01:04 +01:00
Ondrej Kozina
b4ba1d8758 Move requirement helpers for later changes. 2022-01-12 14:00:57 +01:00
Milan Broz
139d663541 Add disable-luks2 reencryption configure option.
The option --disable-luks2-reencryption completely disable
LUKS2 reencryption code.

When used, the libcryptsetup library can read metadata with
reencryption code, but all reencryption API calls and cryptsetup
reencrypt commands are disabled.

Devices with online reencryption in progress cannot be activated.

This option can cause some incompatibilities. Please use with care.
2022-01-12 13:58:35 +01:00
Milan Broz
665816ae4d Print better error if resilience hash is not available. 2022-01-12 13:56:46 +01:00
Milan Broz
c522996edc Do not run reencryption recovery when not needed. 2022-01-12 13:56:22 +01:00
Milan Broz
750afe309f Reenc keyslot must have key_size == 1. 2022-01-12 13:55:49 +01:00
Milan Broz
eb220d834d Fix debug message. 2022-01-12 13:55:39 +01:00
Ondrej Kozina
0113ac2d88 Fix CVE-2021-4122 - LUKS2 reencryption crash recovery attack
Fix possible attacks against data confidentiality through LUKS2 online
reencryption extension crash recovery.

An attacker can modify on-disk metadata to simulate decryption in
progress with crashed (unfinished) reencryption step and persistently
decrypt part of the LUKS device.

This attack requires repeated physical access to the LUKS device but
no knowledge of user passphrases.

The decryption step is performed after a valid user activates
the device with a correct passphrase and modified metadata.
There are no visible warnings for the user that such recovery happened
(except using the luksDump command). The attack can also be reversed
afterward (simulating crashed encryption from a plaintext) with
possible modification of revealed plaintext.

The problem was caused by reusing a mechanism designed for actual
reencryption operation without reassessing the security impact for new
encryption and decryption operations. While the reencryption requires
calculating and verifying both key digests, no digest was needed to
initiate decryption recovery if the destination is plaintext (no
encryption key). Also, some metadata (like encryption cipher) is not
protected, and an attacker could change it. Note that LUKS2 protects
visible metadata only when a random change occurs. It does not protect
against intentional modification but such modification must not cause
a violation of data confidentiality.

The fix introduces additional digest protection of reencryption
metadata. The digest is calculated from known keys and critical
reencryption metadata. Now an attacker cannot create correct metadata
digest without knowledge of a passphrase for used keyslots.
For more details, see LUKS2 On-Disk Format Specification version 1.1.0.
2022-01-12 13:50:37 +01:00
Josef Andersson
5a17d677c4 po: update sv.po (from translationproject.org) 2021-12-25 16:19:16 +01:00
Мирослав Николић
629fb68aa8 po: update sr.po (from translationproject.org) 2021-12-25 16:19:16 +01:00
Antonio Ceballos
31b36a410b po: update es.po (from translationproject.org) 2021-12-25 16:19:16 +01:00
Tianjia Zhang
80b2cb213c Fix manual typo. 2021-12-24 16:43:57 +08:00
Sean
f996b9b9e8 Update README.md 2021-12-08 16:44:01 +00:00
Milan Broz
c4b66283fe Run CI on stable branches.
The stable branch is named "v2.<minor>.x".
2021-12-01 22:43:33 +01:00
Milan Broz
feb4d24327 Do not mix tabs and spaces in GitHub CI script. 2021-11-28 21:04:12 +01:00
Milan Broz
8a3716d18c Do not mix tabs and spaces in Gitlab CI script. 2021-11-28 21:02:09 +01:00
Milan Broz
e5534c47e9 Fix tabs in GitLab CI scripts and remove gcc comment.
The -Wall changes according to gcc versions.
2021-11-28 21:00:25 +01:00
Milan Broz
03e4cc6f6d Fix missing backslash in CI. 2021-11-28 20:52:31 +01:00
Milan Broz
7940563131 Add limitation to cryptsetup group again in CI. 2021-11-28 20:50:20 +01:00
Vojtech Trefny
6eae9f6e91 bitlk: Fix support for startup key with new metadata entry
Windows 11 now includes the BitLocker volume GUID in the BEK file
metadata entries. This was previously not included so cryptsetup
refused to open the file because there was an unknown metadata
entry in the startup key.

Fixes: #690
2021-11-28 17:10:25 +01:00
Ondrej Kozina
1c36ddfe73 Unify few reencryption error messages. 2021-11-24 19:58:57 +01:00
Ondrej Kozina
db9991d471 Clarify some variable names in reencryption utils. 2021-11-24 19:58:57 +01:00
Ondrej Kozina
6bc1378ddb Remove LUKS2 encryption data size restriction.
LUKS2 encryption with data shift required remaining
data size (size remaining after substracting --reduce-data-size value)
to be at least --reduce-data-size. This was wrong. Remaining
data size restriction should be correctly at least single sector
(whatever sector size is selected or auto-detected).
2021-11-24 19:58:57 +01:00
Ondrej Kozina
d4e49f9988 Enable legacy reencryption compat test. 2021-11-24 19:58:57 +01:00
Ondrej Kozina
2e23913e3b Fix compat-test-args to reflect on luks1 reencryption params.
--decrypt parameter works with LUKS1 format even without --header
parameter.
2021-11-24 19:58:57 +01:00
Ondrej Kozina
8d7bce164c Fix compat-test-args test.
Option --device-size was never used in open action.
2021-11-24 19:58:57 +01:00
Ondrej Kozina
2cf11a2fa4 All options allowed with luksFormat also pass with reencrypt action.
During encryption (both formats) we need full luksFormat action
parameters set
2021-11-24 19:58:57 +01:00
Ondrej Kozina
bd4405ada6 Add --keyslot-cipher and --keyslot-key-size action restrictions. 2021-11-24 19:58:57 +01:00
Ondrej Kozina
c46fd35e56 Add per action parameters verification routines.
It cleans up bloated main function and improves code clarity on
when some parameters need to be verified and when not.
2021-11-24 19:58:57 +01:00
Ondrej Kozina
957c58db41 Remove cryptsetup-reencrypt from the project. 2021-11-24 19:58:57 +01:00
Ondrej Kozina
06fd461bd8 Add --new alias for --encrypt parameter.
To be compatible with cryptsetup-reencrypt utility.
2021-11-24 19:58:57 +01:00
Ondrej Kozina
686acf82a2 Add option to turn off O_EXCL flag in device_check() 2021-11-24 19:58:57 +01:00
Ondrej Kozina
cade8201d2 Enable legacy LUKS1 reencryption in cryptsetup utility. 2021-11-24 19:58:57 +01:00
Ondrej Kozina
390f3f5b73 Remove (legacy) LUKS2 code from former cryptsetup-reencrypt utility.
The old LUKS2 reencryption from cryptsetup-reencrypt will not be
supported anymore.
2021-11-24 19:58:57 +01:00
Ondrej Kozina
d5fdf47b19 Copy effective cryptsetup-reencrypt code in new file.
With only minor editing and drop of code path entry and
command line parameters parsing.
2021-11-24 19:58:57 +01:00
Ondrej Kozina
7d77e0dcbd Refactor new LUKS2 reencryption code.
It will ease the merge with legacy LUKS1 reencryption
code later.
2021-11-24 19:58:54 +01:00
Ondrej Kozina
eb0f9b4f29 Move LUKS2 reencrytption code in separate file. 2021-11-24 19:57:37 +01:00
Ondrej Kozina
7b10f71373 Preparation to merge cryptsetup-reencrypt in cryptsetup. 2021-11-24 19:57:37 +01:00
Ondrej Kozina
c82c3509cf Do not build cryptsetup-reencrypt.
Source code will be removed later completely.
2021-11-24 19:57:37 +01:00
Ondrej Kozina
74ad0d71b9 Add --keep-key parameter for LUKS2 reencryption.
One of missing features when comparing to legacy
reencryption code.
2021-11-24 19:57:30 +01:00
Chris Coulson
98cd52c8d7 allow tokens to be replaced
Currently, token import and token add actions will fail if you use the
--token-id option to specify a token ID that is already in use, but there
are scenarios where you might genuinely want to replace an existing token
in a single atomic operation.

A use case for this might be for a keyslot that is protected by a
TPM, where you store the TPM sealed key and associated metadata as a
token and you want to update the PCR policy associated with the sealed
object or make other changes to it. Currently this requires importing a
new token and then removing the old token.

Instead, add a --token-replace option to allow token import and token
add to replace an existing token if you try to add or import one with an
ID that is already in use.
2021-11-23 15:45:33 +00:00
daniel.zatovic
a9bf78adc3 Remove LLVM repo script 2021-11-23 14:57:51 +01:00
Daniel Zaťovič
83efc03426 Add compilation tests and static analysis on the Gitlab shared runner. 2021-11-23 14:53:10 +01:00
Milan Broz
bfc39f68d8 Set devel version. 2021-11-19 14:36:47 +01:00
429 changed files with 69350 additions and 29824 deletions

31
.codeql-config.yml Normal file
View File

@@ -0,0 +1,31 @@
name: "Cryptsetup CodeQL config"
query-filters:
- exclude:
id: cpp/fixme-comment
- exclude:
id: cpp/empty-block
- exclude:
id: cpp/poorly-documented-function
- exclude:
id: cpp/loop-variable-changed
- exclude:
id: cpp/empty-if
- exclude:
id: cpp/long-switch
- exclude:
id: cpp/complex-condition
- exclude:
id: cpp/commented-out-code
# These produce many false positives
- exclude:
id: cpp/uninitialized-local
- exclude:
id: cpp/path-injection
- exclude:
id: cpp/missing-check-scanf
# CodeQL should understand coverity [toctou] comments
- exclude:
id: cpp/toctou-race-condition

View File

@@ -4,9 +4,10 @@ set -ex
PACKAGES=(
git make autoconf automake autopoint pkg-config libtool libtool-bin
gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev
gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol-dev
libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev libpwquality-dev
sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass
asciidoctor meson ninja-build
)
COMPILER="${COMPILER:?}"

View File

@@ -12,27 +12,27 @@ CXX="g++${COMPILER_VERSION:+-$COMPILER_VERSION}"
set -ex
for phase in "${PHASES[@]}"; do
case $phase in
CONFIGURE)
opts=(
--enable-libargon2
)
case $phase in
CONFIGURE)
opts=(
--enable-libargon2
)
sudo -E git clean -xdf
sudo -E git clean -xdf
./autogen.sh
CC="$CC" CXX="$CXX" CFLAGS="${CFLAGS[@]}" CXXFLAGS="${CXXFLAGS[@]}" ./configure "${opts[@]}"
;;
MAKE)
make -j
make -j -C tests check-programs
;;
CHECK)
make check
;;
./autogen.sh
CC="$CC" CXX="$CXX" CFLAGS="${CFLAGS[@]}" CXXFLAGS="${CXXFLAGS[@]}" ./configure "${opts[@]}"
;;
MAKE)
make -j
make -j -C tests check-programs
;;
CHECK)
make check
;;
*)
echo >&2 "Unknown phase '$phase'"
exit 1
esac
*)
echo >&2 "Unknown phase '$phase'"
exit 1
esac
done

View File

@@ -2,9 +2,10 @@ name: Build test
on:
push:
branches:
- 'master'
- 'main'
- 'wip-luks2'
- 'v2.3.x'
- 'v2.4.x'
paths-ignore:
- 'docs/**'

50
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: "CodeQL"
on:
push:
branches:
- 'main'
- 'wip-luks2'
- 'v2.3.x'
- 'v2.4.x'
permissions:
contents: read
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
if: github.repository == 'mbroz/cryptsetup'
concurrency:
group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: +security-extended,security-and-quality
config-file: .codeql-config.yml
- name: Install dependencies
run: sudo -E .github/workflows/cibuild-setup-ubuntu.sh
env: { COMPILER: "gcc", COMPILER_VERSION: "11", RUN_SSH_PLUGIN_TEST: "1" }
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

5
.gitignore vendored
View File

@@ -6,6 +6,8 @@ Makefile.in.in
*.lo
*.la
*.o
*.so
*.8
**/*.dirstamp
.deps/
.libs/
@@ -54,3 +56,6 @@ tests/luks1-images
tests/tcrypt-images
tests/unit-utils-io
tests/vectors-test
tests/test-symbols-list.h
tests/all-symbols-test
tests/fuzz/LUKS2.pb*

View File

@@ -1,108 +1,23 @@
stages:
- test
.debian-prep:
before_script:
- sudo apt-get -y update --fix-missing
- >
sudo apt-get -y install -y -qq git gcc make
autoconf automake autopoint pkg-config libtool libtool-bin gettext
libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev
libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev
libpwquality-dev sharutils dmsetup jq xxd expect keyutils
netcat passwd openssh-client sshpass
- sudo apt-get -y build-dep cryptsetup
- sudo -E git clean -xdf
- ./autogen.sh
- ./configure --enable-libargon2
.dump_kernel_log:
after_script:
- sudo dmesg > /mnt/artifacts/dmesg.log
- sudo journalctl > /mnt/artifacts/journalctl.log
- '[ "$(ls -A /var/coredumps)" ] && exit 1 || true'
.dnf-openssl-backend:
before_script:
- >
sudo dnf -y -q install
autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
libargon2-devel libblkid-devel libpwquality-devel libselinux-devel
libssh-devel libtool libuuid-devel make popt-devel
libsepol-devel.x86_64 netcat openssh-clients passwd pkgconfig sharutils
sshpass tar uuid-devel vim-common device-mapper expect gettext git jq
keyutils openssl-devel openssl
- sudo -E git clean -xdf
- ./autogen.sh
- ./configure --enable-fips --enable-pwquality --enable-libargon2 --with-crypto_backend=openssl
# Merge request: Build and run only non-root tests
test-mergerq-job-debian-noroot:
extends:
- .debian-prep
tags:
- libvirt
- debian10
stage: test
interruptible: true
rules:
# - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
# when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- make check
# For main branch commit, run all tests as root
test-main-commit-job-debian:
extends:
- .debian-prep
tags:
- libvirt
- debian10
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
- sudo -E make clean
test-main-commit-job-dnf:
extends:
- .dnf-openssl-backend
tags:
- libvirt
- fedora-rawhide
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-mergerq-job-dnf:
extends:
- .dnf-openssl-backend
tags:
- libvirt
- fedora-rawhide
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
# - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
# when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
include:
- local: .gitlab/ci/debian.yml
- local: .gitlab/ci/fedora.yml
- local: .gitlab/ci/rhel.yml
- local: .gitlab/ci/centos.yml
- local: .gitlab/ci/annocheck.yml
- local: .gitlab/ci/csmock.yml
- local: .gitlab/ci/gitlab-shared-docker.yml
- local: .gitlab/ci/compilation-various-disables.yml
- local: .gitlab/ci/compilation-gcc.gitlab-ci.yml
- local: .gitlab/ci/compilation-clang.gitlab-ci.yml
- local: .gitlab/ci/alpinelinux.yml
- local: .gitlab/ci/ubuntu-32bit.yml
- local: .gitlab/ci/cifuzz.yml

View File

@@ -0,0 +1,55 @@
.alpinelinux-dependencies:
after_script:
- sudo dmesg > /mnt/artifacts/dmesg.log
- sudo cp /var/log/messages /mnt/artifacts/
- '[ "$(ls -A /var/coredumps)" ] && exit 1 || true'
before_script:
- >
sudo apk add
lvm2-dev openssl1.1-compat-dev popt-dev util-linux-dev json-c-dev
argon2-dev device-mapper which sharutils gettext gettext-dev automake
autoconf libtool build-base keyutils tar jq expect git asciidoctor
- ./autogen.sh
- ./configure --prefix=/usr --libdir=/lib --sbindir=/sbin --disable-static --enable-libargon2 --with-crypto_backend=openssl --disable-external-tokens --disable-ssh-token --enable-asciidoc
test-main-commit-job-alpinelinux:
extends:
- .alpinelinux-dependencies
tags:
- libvirt
- alpinelinux
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "0"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-mergerq-job-alpinelinux:
extends:
- .alpinelinux-dependencies
tags:
- libvirt
- alpinelinux
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "0"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check

17
.gitlab/ci/annocheck.yml Normal file
View File

@@ -0,0 +1,17 @@
test-main-commit-job-annocheck:
extends:
- .dump_kernel_log
tags:
- libvirt
- rhel9-annocheck
stage: test
interruptible: true
allow_failure: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- sudo /opt/run-annocheck.sh

59
.gitlab/ci/centos.yml Normal file
View File

@@ -0,0 +1,59 @@
.centos-openssl-backend:
extends:
- .dump_kernel_log
before_script:
- >
sudo dnf -y -q install
autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
libblkid-devel libpwquality-devel libselinux-devel libssh-devel libtool
libuuid-devel make popt-devel libsepol-devel nc openssh-clients passwd
pkgconfig sharutils sshpass tar uuid-devel vim-common device-mapper
expect gettext git jq keyutils openssl-devel openssl gem
- sudo gem install asciidoctor
- sudo -E git clean -xdf
- ./autogen.sh
- ./configure --enable-fips --enable-pwquality --with-crypto_backend=openssl --enable-asciidoc
# non-FIPS jobs
test-main-commit-centos-stream9:
extends:
- .centos-openssl-backend
tags:
- libvirt
- centos-stream9
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-mergerq-centos-stream9:
extends:
- .centos-openssl-backend
tags:
- libvirt
- centos-stream9
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check

View File

@@ -0,0 +1,50 @@
#!/bin/bash
set -ex
PACKAGES=(
git make autoconf automake autopoint pkg-config libtool libtool-bin
gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol-dev
libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev libpwquality-dev
sharutils dmsetup jq xxd expect keyutils netcat-openbsd passwd openssh-client
sshpass asciidoctor
)
COMPILER="${COMPILER:?}"
COMPILER_VERSION="${COMPILER_VERSION:?}"
grep -E '^deb' /etc/apt/sources.list > /etc/apt/sources.list~
sed -Ei 's/^deb /deb-src /' /etc/apt/sources.list~
cat /etc/apt/sources.list~ >> /etc/apt/sources.list
apt-get -y update --fix-missing
DEBIAN_FRONTEND=noninteractive apt-get -yq install software-properties-common wget lsb-release
RELEASE="$(lsb_release -cs)"
if [[ $COMPILER == "gcc" ]]; then
# Latest gcc stack deb packages provided by
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
add-apt-repository -y ppa:ubuntu-toolchain-r/test
PACKAGES+=(gcc-$COMPILER_VERSION)
elif [[ $COMPILER == "clang" ]]; then
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
add-apt-repository "deb http://apt.llvm.org/${RELEASE}/ llvm-toolchain-${RELEASE}-${COMPILER_VERSION} main"
# scan-build
PACKAGES+=(clang-tools-$COMPILER_VERSION clang-$COMPILER_VERSION lldb-$COMPILER_VERSION lld-$COMPILER_VERSION clangd-$COMPILER_VERSION)
PACKAGES+=(perl)
else
exit 1
fi
apt-get -y update --fix-missing
DEBIAN_FRONTEND=noninteractive apt-get -yq install "${PACKAGES[@]}"
apt-get -y build-dep cryptsetup
echo "====================== VERSIONS ==================="
if [[ $COMPILER == "clang" ]]; then
echo "Using scan-build${COMPILER_VERSION:+-$COMPILER_VERSION}"
fi
${COMPILER}-$COMPILER_VERSION -v
echo "====================== END VERSIONS ==================="

46
.gitlab/ci/cifuzz.yml Normal file
View File

@@ -0,0 +1,46 @@
cifuzz:
variables:
OSS_FUZZ_PROJECT_NAME: cryptsetup
CFL_PLATFORM: gitlab
CIFUZZ_DEBUG: "True"
FUZZ_SECONDS: 300 # 5 minutes per fuzzer
ARCHITECTURE: "x86_64"
DRY_RUN: "False"
LOW_DISK_SPACE: "True"
BAD_BUILD_CHECK: "True"
LANGUAGE: "c"
DOCKER_HOST: "tcp://docker:2375"
DOCKER_IN_DOCKER: "true"
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
image:
name: gcr.io/oss-fuzz-base/cifuzz-base
entrypoint: [""]
services:
- docker:dind
stage: test
parallel:
matrix:
- SANITIZER: [address, undefined, memory]
rules:
# Default code change.
# - if: $CI_PIPELINE_SOURCE == "merge_request_event"
# variables:
# MODE: "code-change"
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $BUILD_AND_RUN_FUZZERS != null
before_script:
# Get gitlab's container id.
- export CFL_CONTAINER_ID=`cut -c9- < /proc/1/cpuset`
script:
# Will build and run the fuzzers.
# We use a hack to override CI_JOB_ID, because otherwise a bad path is used
# in GitLab CI environment
- CI_JOB_ID="$CI_PROJECT_NAMESPACE/$CI_PROJECT_TITLE" python3 "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py"
artifacts:
# Upload artifacts when a crash makes the job fail.
when: always
paths:
- artifacts/

48
.gitlab/ci/clang-Wall Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
# clang -Wall plus other important warnings not included in -Wall
for arg in "$@"
do
case $arg in
-O*) Wuninitialized=-Wuninitialized;; # only makes sense with `-O'
esac
done
CLANG="clang${COMPILER_VERSION:+-$COMPILER_VERSION}"
#PEDANTIC="-std=gnu99"
#PEDANTIC="-pedantic -std=gnu99"
#PEDANTIC="-pedantic -std=gnu99 -Wno-variadic-macros"
#CONVERSION="-Wconversion"
EXTRA="\
-Wextra \
-Wsign-compare \
-Wcast-align
-Werror-implicit-function-declaration \
-Wpointer-arith \
-Wwrite-strings \
-Wswitch \
-Wmissing-format-attribute \
-Winit-self \
-Wold-style-definition \
-Wno-missing-field-initializers \
-Wunused-parameter \
-Wno-long-long"
exec $CLANG $PEDANTIC $CONVERSION \
-Wall $Wuninitialized \
-Wno-switch \
-Wdisabled-optimization \
-Wwrite-strings \
-Wpointer-arith \
-Wbad-function-cast \
-Wmissing-prototypes \
-Wmissing-declarations \
-Wstrict-prototypes \
-Wnested-externs \
-Wcomment \
-Winline \
-Wcast-qual \
-Wredundant-decls $EXTRA \
"$@"

View File

@@ -0,0 +1,30 @@
test-clang-compilation:
extends:
- .gitlab-shared-clang
script:
- export CFLAGS="-Wall -Werror"
- ./autogen.sh
- ./configure
- make -j
- make -j check-programs
test-clang-Wall-script:
extends:
- .gitlab-shared-clang
script:
- export CFLAGS="-g -O0"
- export CC="$CI_PROJECT_DIR/.gitlab/ci/clang-Wall"
- ./autogen.sh
- ./configure
- make -j CFLAGS="-g -O0 -Werror"
- make -j CFLAGS="-g -O0 -Werror" check-programs
test-scan-build:
extends:
- .gitlab-shared-clang
script:
- ./autogen.sh
- scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} -V ./configure CFLAGS="-g -O0"
- make clean
- scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} --status-bugs -maxloop 10 make -j
- scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} --status-bugs -maxloop 10 make -j check-programs

View File

@@ -0,0 +1,30 @@
test-gcc-compilation:
extends:
- .gitlab-shared-gcc
script:
- export CFLAGS="-Wall -Werror"
- ./autogen.sh
- ./configure
- make -j
- make -j check-programs
test-gcc-Wall-script:
extends:
- .gitlab-shared-gcc
script:
- export CFLAGS="-g -O0"
- export CC="$CI_PROJECT_DIR/.gitlab/ci/gcc-Wall"
- ./autogen.sh
- ./configure
- make -j CFLAGS="-g -O0 -Werror"
- make -j CFLAGS="-g -O0 -Werror" check-programs
test-gcc-fanalyzer:
extends:
- .gitlab-shared-gcc
script:
- export CFLAGS="-Wall -Werror -g -O0 -fanalyzer -fdiagnostics-path-format=separate-events"
- ./autogen.sh
- ./configure
- make -j
- make -j check-programs

View File

@@ -0,0 +1,32 @@
test-gcc-disable-compiles:
extends:
- .gitlab-shared-gcc
parallel:
matrix:
- DISABLE_FLAGS: [
"keyring",
"external-tokens ssh-token",
"luks2-reencryption",
"cryptsetup veritysetup integritysetup",
"kernel_crypto",
"udev",
"internal-argon2",
"blkid"
]
artifacts:
name: "meson-build-logs-$CI_COMMIT_REF_NAME"
paths:
- meson_builddir/meson-logs
script:
- DEBIAN_FRONTEND=noninteractive apt-get -yq install meson ninja-build
- export CFLAGS="-Wall -Werror"
- ./autogen.sh
- echo "Configuring with --disable-$DISABLE_FLAGS"
- ./configure $(for i in $DISABLE_FLAGS; do echo "--disable-$i"; done)
- make -j
- make -j check-programs
- git checkout -f && git clean -xdf
- meson -v
- echo "Configuring with -D$DISABLE_FLAGS=false"
- meson setup meson_builddir $(for i in $DISABLE_FLAGS; do [ "$i" == "internal-argon2" ] && echo "-Dargon-implementation=internal" || echo "-D$i=false"; done)
- ninja -C meson_builddir

23
.gitlab/ci/csmock.yml Normal file
View File

@@ -0,0 +1,23 @@
test-commit-job-csmock:
extends:
- .dump_kernel_log
tags:
- libvirt
- rhel9-csmock
stage: test
interruptible: true
allow_failure: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/ || $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- sudo /opt/run-csmock.sh
artifacts:
# Upload artifacts when a crash makes the job fail.
when: always
paths:
- cryptsetup-csmock-results.tar.xz
- cryptsetup-csmock-results

98
.gitlab/ci/debian.yml Normal file
View File

@@ -0,0 +1,98 @@
.debian-prep:
extends:
- .dump_kernel_log
before_script:
- sudo apt-get -y update
- >
[ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] ||
sudo apt-get -y install -y -qq swtpm meson ninja-build python3-jinja2
gperf libcap-dev libtss2-dev libmount-dev swtpm-tools
- >
sudo apt-get -y install -y -qq git gcc make autoconf automake autopoint
pkgconf libtool libtool-bin gettext libssl-dev libdevmapper-dev
libpopt-dev uuid-dev libsepol-dev libjson-c-dev libssh-dev libblkid-dev
tar libargon2-0-dev libpwquality-dev sharutils dmsetup jq xxd expect
keyutils netcat-openbsd passwd openssh-client sshpass asciidoctor
- sudo apt-get -y build-dep cryptsetup
- sudo -E git clean -xdf
- ./autogen.sh
- ./configure --enable-libargon2 --enable-asciidoc
test-mergerq-job-debian:
extends:
- .debian-prep
tags:
- libvirt
- debian12
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-main-commit-job-debian:
extends:
- .debian-prep
tags:
- libvirt
- debian12
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
# meson tests
test-mergerq-job-debian-meson:
extends:
- .debian-prep
tags:
- libvirt
- debian12
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- sudo apt-get -y install -y -qq meson ninja-build
- meson setup build
- ninja -C build
- cd build && sudo -E meson test --verbose --print-errorlogs
test-main-commit-job-debian-meson:
extends:
- .debian-prep
tags:
- libvirt
- debian12
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- sudo apt-get -y install -y -qq meson ninja-build
- meson setup build
- ninja -C build
- cd build && sudo -E meson test --verbose --print-errorlogs

60
.gitlab/ci/fedora.yml Normal file
View File

@@ -0,0 +1,60 @@
.dnf-openssl-backend:
extends:
- .dump_kernel_log
before_script:
- >
[ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] ||
sudo dnf -y -q install
swtpm meson ninja-build python3-jinja2 gperf libcap-devel tpm2-tss-devel
libmount-devel swtpm-tools
- >
sudo dnf -y -q install
autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
libargon2-devel libblkid-devel libpwquality-devel libselinux-devel
libssh-devel libtool libuuid-devel make popt-devel
libsepol-devel.x86_64 netcat openssh-clients passwd pkgconfig sharutils
sshpass tar uuid-devel vim-common device-mapper expect gettext git jq
keyutils openssl-devel openssl asciidoctor
- sudo -E git clean -xdf
- ./autogen.sh
- ./configure --enable-fips --enable-pwquality --enable-libargon2 --with-crypto_backend=openssl --enable-asciidoc
test-main-commit-job-rawhide:
extends:
- .dnf-openssl-backend
tags:
- libvirt
- fedora-rawhide
stage: test
interruptible: true
allow_failure: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-mergerq-job-rawhide:
extends:
- .dnf-openssl-backend
tags:
- libvirt
- fedora-rawhide
stage: test
interruptible: true
allow_failure: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check

57
.gitlab/ci/gcc-Wall Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
# gcc -Wall plus other important warnings not included in -Wall
for arg in "$@"
do
case $arg in
-O*) Wuninitialized=-Wuninitialized;; # only makes sense with `-O'
esac
done
GCC="gcc${COMPILER_VERSION:+-$COMPILER_VERSION}"
#PEDANTIC="-std=gnu99"
#PEDANTIC="-pedantic -std=gnu99"
#PEDANTIC="-pedantic -std=gnu99 -Wno-variadic-macros"
#CONVERSION="-Wconversion"
# -Wpacked \
# This does more than expected for gcc (mixed code with declarations)
# -Wdeclaration-after-statement \
EXTRA="-Wextra \
-Wsign-compare \
-Werror-implicit-function-declaration \
-Wpointer-arith \
-Wwrite-strings \
-Wswitch \
-Wmissing-format-attribute \
-Wstrict-aliasing=3 \
-Winit-self \
-Wunsafe-loop-optimizations \
-Wold-style-definition \
-Wno-missing-field-initializers \
-Wunused-parameter \
-Wno-long-long \
-Wmaybe-uninitialized \
-Wvla \
-Wformat-overflow \
-Wformat-truncation"
exec $GCC $PEDANTIC $CONVERSION \
-Wall $Wuninitialized \
-Wno-switch \
-Wdisabled-optimization \
-Wwrite-strings \
-Wpointer-arith \
-Wbad-function-cast \
-Wmissing-prototypes \
-Wmissing-declarations \
-Wstrict-prototypes \
-Wnested-externs \
-Wcomment \
-Winline \
-Wcast-align=strict \
-Wcast-qual \
-Wredundant-decls $EXTRA \
"$@"

View File

@@ -0,0 +1,30 @@
.gitlab-shared-docker:
image: ubuntu:lunar
tags:
- gitlab-org-docker
stage: test
interruptible: true
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
before_script:
- .gitlab/ci/cibuild-setup-ubuntu.sh
- export CC="${COMPILER}${COMPILER_VERSION:+-$COMPILER_VERSION}"
- export CXX="${COMPILER}++${COMPILER_VERSION:+-$COMPILER_VERSION}"
.gitlab-shared-gcc:
extends:
- .gitlab-shared-docker
variables:
COMPILER: "gcc"
COMPILER_VERSION: "11"
RUN_SSH_PLUGIN_TEST: "1"
.gitlab-shared-clang:
extends:
- .gitlab-shared-docker
variables:
COMPILER: "clang"
COMPILER_VERSION: "17"
RUN_SSH_PLUGIN_TEST: "1"

106
.gitlab/ci/rhel.yml Normal file
View File

@@ -0,0 +1,106 @@
.rhel-openssl-backend:
extends:
- .dump_kernel_log
before_script:
- >
sudo yum -y -q install
autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
libblkid-devel libpwquality-devel libselinux-devel libssh-devel libtool
libuuid-devel make popt-devel libsepol-devel nc openssh-clients passwd
pkgconfig sharutils sshpass tar uuid-devel vim-common device-mapper
expect gettext git jq keyutils openssl-devel openssl gem > /dev/null 2>&1
- sudo gem install asciidoctor
- sudo -E git clean -xdf
- ./autogen.sh
- ./configure --enable-fips --enable-pwquality --with-crypto_backend=openssl --enable-asciidoc
# non-FIPS jobs
test-main-commit-rhel8:
extends:
- .rhel-openssl-backend
tags:
- libvirt
- rhel8
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-main-commit-rhel9:
extends:
- .rhel-openssl-backend
tags:
- libvirt
- rhel9
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
# FIPS jobs
test-main-commit-rhel8-fips:
extends:
- .rhel-openssl-backend
tags:
- libvirt
- rhel8-fips
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- fips-mode-setup --check || exit 1
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-main-commit-rhel9-fips:
extends:
- .rhel-openssl-backend
tags:
- libvirt
- rhel9-fips
stage: test
interruptible: true
allow_failure: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- fips-mode-setup --check || exit 1
- make -j
- make -j -C tests check-programs
- sudo -E make check

View File

@@ -0,0 +1,41 @@
test-mergerq-job-ubuntu-32bit:
extends:
- .debian-prep
tags:
- libvirt
- ubuntu-bionic-32bit
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check
test-main-commit-job-ubuntu-32bit:
extends:
- .debian-prep
tags:
- libvirt
- ubuntu-bionic-32bit
stage: test
interruptible: true
variables:
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
when: never
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
script:
- make -j
- make -j -C tests check-programs
- sudo -E make check

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,18 @@
EXTRA_DIST = README.md COPYING.LGPL FAQ docs misc autogen.sh
SUBDIRS = po tests
EXTRA_DIST = README.md SECURITY.md COPYING.LGPL FAQ.md docs misc autogen.sh
EXTRA_DIST += meson_options.txt \
meson.build \
lib/crypto_backend/argon2/meson.build \
lib/crypto_backend/meson.build \
lib/meson.build \
man/meson.build \
po/meson.build \
scripts/meson.build \
src/meson.build \
tests/meson.build \
tokens/meson.build \
tokens/ssh/meson.build
SUBDIRS = po tests tests/fuzz
CLEANFILES =
DISTCLEAN_TARGETS =
@@ -14,9 +27,15 @@ AM_CPPFLAGS = \
-DVERSION=\""$(VERSION)"\" \
-DEXTERNAL_LUKS2_TOKENS_PATH=\"${EXTERNAL_LUKS2_TOKENS_PATH}\"
AM_CFLAGS = -Wall
AM_CXXFLAGS = -Wall
AM_LDFLAGS =
LDADD = $(LTLIBINTL) -lm
if ENABLE_FUZZ_TARGETS
AM_CFLAGS += -fsanitize=fuzzer-no-link
AM_CXXFLAGS += -fsanitize=fuzzer-no-link
endif
LDADD = $(LTLIBINTL)
tmpfilesddir = @DEFAULT_TMPFILESDIR@
@@ -27,6 +46,7 @@ sbin_PROGRAMS =
man8_MANS =
tmpfilesd_DATA =
pkgconfig_DATA =
dist_noinst_DATA =
include man/Makemodule.am
@@ -46,7 +66,7 @@ ACLOCAL_AMFLAGS = -I m4
DISTCHECK_CONFIGURE_FLAGS = \
--with-tmpfilesdir=$$dc_install_base/usr/lib/tmpfiles.d \
--enable-internal-argon2 --enable-internal-sse-argon2 \
--enable-external-tokens --enable-ssh-token
--enable-external-tokens --enable-ssh-token --enable-asciidoc
distclean-local:
-find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f
@@ -60,3 +80,11 @@ install-data-local:
uninstall-local:
rmdir $(DESTDIR)/${EXTERNAL_LUKS2_TOKENS_PATH} 2>/dev/null || :
check-programs: libcryptsetup.la
$(MAKE) -C tests $@
if ENABLE_FUZZ_TARGETS
fuzz-targets: libcryptsetup.la libcrypto_backend.la
$(MAKE) -C tests/fuzz $@
endif

176
README.md
View File

@@ -2,106 +2,150 @@
What the ...?
=============
**Cryptsetup** is a utility used to conveniently set up disk encryption based
on the [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
**Cryptsetup** is an open-source utility used to conveniently set up disk encryption based
on the [dm-crypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**,
**TrueCrypt** (including **VeraCrypt** extension) and **BitLocker** formats.
These formats are supported:
* **plain** volumes,
* **LUKS** volumes,
* **loop-AES**,
* **TrueCrypt** (including **VeraCrypt** extension),
* **BitLocker**, and
* **FileVault2**.
The project also includes a **veritysetup** utility used to conveniently setup
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module
and **integritysetup** to setup
[DMIntegrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity) block integrity kernel module.
[dm-verity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity)
block integrity checking kernel module and **integritysetup** to setup
[dm-integrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity)
block integrity kernel module.
LUKS Design
-----------
**LUKS** is the standard for Linux hard disk encryption. By providing a standard on-disk-format, it does not
only facilitate compatibility among distributions, but also provides secure management of multiple user passwords.
LUKS stores all necessary setup information in the partition header, enabling to transport or migrate data seamlessly.
**LUKS** is the standard for Linux disk encryption. By providing a standardized on-disk format,
it not only facilitate compatibility among distributions, but also enables secure management
of multiple user passwords. LUKS stores all necessary setup information in the partition header,
which enables users to transport or migrate data seamlessly.
### Specifications
Last version of the LUKS2 format specification is
[available here](https://gitlab.com/cryptsetup/LUKS2-docs).
Last version of the LUKS1 format specification is
[available here](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
Why LUKS?
---------
* compatibility via standardization,
* secure against low entropy attacks,
* support for multiple keys,
* effective passphrase revocation,
* free.
[Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
-----------------
[Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
--------------------------------
### Specification and documentation
* The latest version of the
[LUKS2 format specification](https://gitlab.com/cryptsetup/LUKS2-docs).
* The latest version of the
[LUKS1 format specification](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
* [Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
* [Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
Download
--------
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
Release notes and tarballs are available at
[kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
**The latest stable cryptsetup version is 2.4.2**
* [cryptsetup-2.4.2.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.2.tar.xz)
* Signature [cryptsetup-2.4.2.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.2.tar.sign)
**The latest stable cryptsetup release candidate version is 2.7.0-rc1**
* [cryptsetup-2.7.0-rc1.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.7/cryptsetup-2.7.0-rc1.tar.xz)
* Signature [cryptsetup-2.7.0-rc1.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.7/cryptsetup-2.7.0-rc1.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.4.2 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/v2.4.2-ReleaseNotes).
* [Cryptsetup 2.7.0-rc1 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.7/v2.7.0-rc1-ReleaseNotes).
**The latest stable cryptsetup release version is 2.6.1**
* [cryptsetup-2.6.1.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.1.tar.xz)
* Signature [cryptsetup-2.6.1.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.1.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.6.1 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/v2.6.1-ReleaseNotes).
Previous versions
* [Version 2.3.6](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.6.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.6.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.6-ReleaseNotes).
* [Version 2.5.0](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/cryptsetup-2.5.0.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/cryptsetup-2.5.0.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/v2.5.0-ReleaseNotes).
* [Version 1.7.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.sign) -
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.5-ReleaseNotes).
Source and API docs
-------------------
For development version code, please refer to [source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page,
mirror on [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) or [GitHub](https://github.com/mbroz/cryptsetup).
Source and API documentation
----------------------------
For development version code, please refer to the
[source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page, with mirrors
at [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) and
[GitHub](https://github.com/mbroz/cryptsetup).
For libcryptsetup documentation see [libcryptsetup API](https://mbroz.fedorapeople.org/libcryptsetup_API/) page.
For libcryptsetup documentation see
[libcryptsetup API](https://mbroz.fedorapeople.org/libcryptsetup_API/) page.
The libcryptsetup API/ABI changes are tracked in [compatibility report](https://abi-laboratory.pro/tracker/timeline/cryptsetup/).
NLS PO files are maintained by [TranslationProject](https://translationproject.org/domain/cryptsetup.html).
NLS PO files are maintained by
[TranslationProject](https://translationproject.org/domain/cryptsetup.html).
Required packages
-----------------
All distributions provide cryptsetup as distro package. If you need to compile cryptsetup youfself, some packages are required for compilation. Please always prefer distro specific build tools to manually configuring cryptsetup.
For available compile options, check ``configure --help`` for more info. If you are using a git snapshot, you need to generate a configure script with ``autogen.sh`` script.
All major Linux distributions provide cryptsetup as a bundled package. If you need
to compile cryptsetup yourself, various additional packages are required.
Any distribution-specific build tools are preferred when manually configuring cryptsetup.
Here is the list of packages needed for the compilation of project for particular distributions:
* For Fedora: `git gcc make autoconf automake gettext-devel pkgconfig openssl-devel popt-devel device-mapper-devel libuuid-devel json-c-devel libblkid-devel findutils libtool libssh-devel tar`. Optionally `libargon2-devel libpwquality-devel`. To run the internal testsuite you also need to install `sharutils device-mapper jq vim-common expect keyutils netcat shadow-utils openssh-clients openssh sshpass`.
Below are the packages needed to build for certain Linux distributions:
* For Debian and Ubuntu: `git gcc make autoconf automake autopoint pkg-config libtool gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev libjson-c-dev libssh-dev libblkid-dev tar`. Optionally `libargon2-0-dev libpwquality-dev`. To run the internal testsuite you also need to install `sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass`
**For Fedora**:
```
git gcc make autoconf automake gettext-devel pkgconfig openssl-devel popt-devel device-mapper-devel
libuuid-devel json-c-devel libblkid-devel findutils libtool libssh-devel tar
Note that the list could change as the distributions evolve.
Optionally: libargon2-devel libpwquality-devel
```
To run the internal testsuite (make check) you also need to install
```
sharutils device-mapper jq vim-common expect keyutils netcat shadow-utils openssh-clients openssh sshpass
```
**For Debian and Ubuntu**:
```
git gcc make autoconf automake autopoint pkg-config libtool gettext libssl-dev libdevmapper-dev
libpopt-dev uuid-dev libsepol1-dev libjson-c-dev libssh-dev libblkid-dev tar
Optionally: libargon2-0-dev libpwquality-dev
```
To run the internal testsuite (make check) you also need to install
```
sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass
```
Note that the list may change as Linux distributions evolve.
Compilation
-----------
The cryptsetup project uses **automake** and **autoconf** system to generate all files needed to build.
When building from a git snapshot,, use **./autogen.sh && ./configure && make**
to compile the project. When building from a release **tar.xz** tarball, the configure script
is pre-generated (no need to run **autoconf.sh**).
See **./configure --help** and use the **--disable-[feature]** and **--enable-[feature]** options.
To run the test suite that come with the project, type **make check**.
Note that most tests will need root user privileges and will run dangerous storage failure simulations.
Do **not** run tests with root privilege on production systems! Some tests will need the **scsi_debug**
kernel module to be installed.
For more details, please refer to the
[automake](https://www.gnu.org/software/automake/manual/automake.html) and
[autoconf](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf.html) documentation.
Help!
-----
### Documentation
Please read the following before posting questions to the mailing list so that
you can ask better questions and better understand answers.
Please read the following documentation before posting questions in the mailing list. You will be able to ask better questions and better understand the answers.
* [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
* LUKS Specifications
* [Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions),
* [LUKS Specifications](#specification-and-documentation), and
* manuals (aka man page, man pages, man-page)
The FAQ is online and in the source code for the project. The Specifications are referenced above in this document. The man pages are in source and should be available after installation using standard man commands. e.g. man cryptsetup
The FAQ is available online and in the source code for the project. The specifications are
referenced above in this document. The man pages live within the source tree and should be
available after installation using standard man commands, e.g. **man cryptsetup**.
### Mailing List
For cryptsetup and LUKS related questions, please use the cryptsetup mailing list
[cryptsetup@lists.linux.dev](mailto:cryptsetup@lists.linux.dev),
hosted at [kernel.org subspace](https://subspace.kernel.org/lists.linux.dev.html).
To subscribe send an empty email message to
[cryptsetup+subscribe@lists.linux.dev](mailto:cryptsetup+subscribe@lists.linux.dev).
For cryptsetup and LUKS related questions, please use the dm-crypt mailing list, [dm-crypt@saout.de](mailto:dm-crypt@saout.de). To subscribe send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
You can also browse and/or search the mailing [list archive](https://lore.kernel.org/cryptsetup/).
USEnet News (NNTP), Atom feed and git access to the public inbox is available through
[lore.kernel.org](https://lore.kernel.org) service.
You can also browse and/or search the mailing list archives using the following resources:
* [list archive](https://www.saout.de/pipermail/dm-crypt/)
* [web interface on lore.kernel.org](https://lore.kernel.org/dm-crypt/)
* [marc.info](https://marc.info/?l=dm-crypt).
The former **dm-crypt** [list archive](https://lore.kernel.org/dm-crypt/) is also available.

10
SECURITY.md Normal file
View File

@@ -0,0 +1,10 @@
# Reporting a Security Bug in cryptsetup project
If you think you have discovered a security issue, please report it through
the project issue tracker [New issue](https://gitlab.com/cryptsetup/cryptsetup/issues)
as a confidential issue (select confidential checkbox).
An alternative is to send PGP encrypted mail to the cryptsetup maintainer.
Current maintainer is [Milan Broz](mailto:gmazyland@gmail.com), use PGP key
with fingerprint 2A29 1824 3FDE 4664 8D06 86F9 D9B0 577B D93E 98FC.

View File

@@ -74,7 +74,7 @@ autopoint --force $AP_OPTS
libtoolize --force --copy
aclocal -I m4 $AL_OPTS
autoheader $AH_OPTS
automake --add-missing --copy --gnu $AM_OPTS
automake --force-missing --add-missing --copy --gnu $AM_OPTS
autoconf $AC_OPTS
echo

View File

@@ -1,9 +1,9 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[2.4.2])
AC_INIT([cryptsetup],[2.7.0-rc1])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
LIBCRYPTSETUP_VERSION_INFO=19:0:7
LIBCRYPTSETUP_VERSION_INFO=22:0:10
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(src/cryptsetup.c)
@@ -28,13 +28,13 @@ AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_MAKE_SET
AC_PROG_MKDIR_P
AC_ENABLE_STATIC(no)
LT_INIT
PKG_PROG_PKG_CONFIG
AM_ICONV
dnl ==========================================================================
dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
@@ -53,12 +53,33 @@ AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])
])
])
dnl ==========================================================================
dnl AsciiDoc manual pages
AC_ARG_ENABLE([asciidoc],
AS_HELP_STRING([--disable-asciidoc], [do not generate man pages from asciidoc]),
[], [enable_asciidoc=yes]
)
AC_PATH_PROG([ASCIIDOCTOR], [asciidoctor])
if test "x$enable_asciidoc" = xyes -a "x$ASCIIDOCTOR" = x; then
AC_MSG_ERROR([Building man pages requires asciidoctor installed.])
fi
AM_CONDITIONAL([ENABLE_ASCIIDOC], [test "x$enable_asciidoc" = xyes])
have_manpages=no
AS_IF([test -f "$srcdir/man/cryptsetup-open.8"], [
AC_MSG_NOTICE([re-use already generated man-pages.])
have_manpages=yes]
)
AM_CONDITIONAL([HAVE_MANPAGES], [test "x$have_manpages" = xyes])
dnl ==========================================================================
AC_C_RESTRICT
AC_HEADER_DIRENT
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h uchar.h sys/ioctl.h sys/mman.h \
sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h)
AC_CHECK_DECLS([O_CLOEXEC],,[AC_DEFINE([O_CLOEXEC],[0], [Defined to 0 if not provided])],
[[
@@ -107,7 +128,6 @@ if test "x$enable_largefile" = "xno"; then
AC_MSG_ERROR([Building with --disable-largefile is not supported, it can cause data corruption.])
fi
AC_C_CONST
AC_C_BIGENDIAN
AC_TYPE_OFF_T
AC_SYS_LARGEFILE
@@ -130,6 +150,7 @@ if test "x$enable_external_tokens" = "xyes"; then
AC_SUBST(DL_LIBS, $LIBS)
LIBS=$saved_LIBS
fi
AM_CONDITIONAL(EXTERNAL_TOKENS, test "x$enable_external_tokens" = "xyes")
AC_ARG_ENABLE([ssh-token],
AS_HELP_STRING([--disable-ssh-token], [disable LUKS2 ssh-token]),
@@ -140,6 +161,14 @@ if test "x$enable_ssh_token" = "xyes" -a "x$enable_external_tokens" = "xno"; the
AC_MSG_ERROR([Requested LUKS2 ssh-token build, but external tokens are disabled.])
fi
dnl LUKS2 online reencryption
AC_ARG_ENABLE([luks2-reencryption],
AS_HELP_STRING([--disable-luks2-reencryption], [disable LUKS2 online reencryption extension]),
[], [enable_luks2_reencryption=yes])
if test "x$enable_luks2_reencryption" = "xyes"; then
AC_DEFINE(USE_LUKS2_REENCRYPTION, 1, [Use LUKS2 online reencryption extension])
fi
dnl ==========================================================================
AM_GNU_GETTEXT([external],[need-ngettext])
@@ -185,6 +214,17 @@ if test "x$enable_pwquality" = "xyes"; then
PWQUALITY_STATIC_LIBS="$PWQUALITY_LIBS -lcrack -lz"
fi
dnl ==========================================================================
dnl fuzzers, it requires own static library compilation later
AC_ARG_ENABLE([fuzz-targets],
AS_HELP_STRING([--enable-fuzz-targets], [enable building fuzz targets]))
AM_CONDITIONAL(ENABLE_FUZZ_TARGETS, test "x$enable_fuzz_targets" = "xyes")
if test "x$enable_fuzz_targets" = "xyes"; then
AX_CHECK_COMPILE_FLAG([-fsanitize=fuzzer-no-link],,
AC_MSG_ERROR([Required compiler options not supported; use clang.]), [-Werror])
fi
dnl ==========================================================================
dnl passwdqc library (cryptsetup CLI only)
AC_ARG_ENABLE([passwdqc],
@@ -226,6 +266,9 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
GCRYPT_REQ_VERSION=1.1.42
fi
use_internal_pbkdf2=0
use_internal_argon2=1
dnl libgcrypt rejects to use pkgconfig, use AM_PATH_LIBGCRYPT from gcrypt-devel here.
dnl Do not require gcrypt-devel if other crypto backend is used.
m4_ifdef([AM_PATH_LIBGCRYPT],[
@@ -249,7 +292,24 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
NO_FIPS([])
fi
m4_ifdef([AM_PATH_LIBGCRYPT],[
AC_ARG_ENABLE([gcrypt-argon2],
dnl Check if we can use gcrypt Argon2 (1.11.0 supports empty password)
AS_HELP_STRING([--disable-gcrypt-argon2], [force disable internal gcrypt Argon2]),
[],
[AM_PATH_LIBGCRYPT([1.11.0], [use_internal_argon2=0], [use_internal_argon2=1])])
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])],
AC_MSG_ERROR([Missing support for gcrypt: install gcrypt and regenerate configure.]))
AC_MSG_CHECKING([if internal cryptsetup Argon2 is compiled-in])
if test $use_internal_argon2 = 0; then
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
fi
AC_CHECK_DECLS([GCRY_CIPHER_MODE_XTS], [], [], [#include <gcrypt.h>])
AC_CHECK_DECLS([GCRY_KDF_ARGON2], [], [], [#include <gcrypt.h>])
if test "x$enable_static_cryptsetup" = "xyes"; then
saved_LIBS=$LIBS
@@ -269,19 +329,25 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
])
AC_DEFUN([CONFIGURE_OPENSSL], [
PKG_CHECK_MODULES([OPENSSL], [openssl >= 0.9.8],,
PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto >= 0.9.8],,
AC_MSG_ERROR([You need openssl library.]))
CRYPTO_CFLAGS=$OPENSSL_CFLAGS
CRYPTO_LIBS=$OPENSSL_LIBS
CRYPTO_CFLAGS=$LIBCRYPTO_CFLAGS
CRYPTO_LIBS=$LIBCRYPTO_LIBS
use_internal_pbkdf2=0
use_internal_argon2=1
if test "x$enable_static_cryptsetup" = "xyes"; then
saved_PKG_CONFIG=$PKG_CONFIG
PKG_CONFIG="$PKG_CONFIG --static"
PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl])
CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS
PKG_CHECK_MODULES([LIBCRYPTO_STATIC], [libcrypto])
CRYPTO_STATIC_LIBS=$LIBCRYPTO_STATIC_LIBS
PKG_CONFIG=$saved_PKG_CONFIG
fi
saved_LIBS=$LIBS
AC_CHECK_DECLS([OSSL_get_max_threads], [], [], [#include <openssl/thread.h>])
AC_CHECK_DECLS([OSSL_KDF_PARAM_ARGON2_VERSION], [], [], [#include <openssl/core_names.h>])
LIBS=$saved_LIBS
])
AC_DEFUN([CONFIGURE_NSS], [
@@ -302,6 +368,7 @@ AC_DEFUN([CONFIGURE_NSS], [
CRYPTO_CFLAGS=$NSS_CFLAGS
CRYPTO_LIBS=$NSS_LIBS
use_internal_pbkdf2=1
use_internal_argon2=1
NO_FIPS([])
])
@@ -312,6 +379,7 @@ AC_DEFUN([CONFIGURE_KERNEL], [
# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])],
# [#include <sys/socket.h>])
use_internal_pbkdf2=1
use_internal_argon2=1
NO_FIPS([])
])
@@ -328,6 +396,7 @@ AC_DEFUN([CONFIGURE_NETTLE], [
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
use_internal_pbkdf2=0
use_internal_argon2=1
NO_FIPS([])
])
@@ -354,11 +423,6 @@ AC_ARG_ENABLE([veritysetup],
[], [enable_veritysetup=yes])
AM_CONDITIONAL(VERITYSETUP, test "x$enable_veritysetup" = "xyes")
AC_ARG_ENABLE([cryptsetup-reencrypt],
AS_HELP_STRING([--disable-cryptsetup-reencrypt], [disable cryptsetup-reencrypt tool]),
[], [enable_cryptsetup_reencrypt=yes])
AM_CONDITIONAL(REENCRYPT, test "x$enable_cryptsetup_reencrypt" = "xyes")
AC_ARG_ENABLE([integritysetup],
AS_HELP_STRING([--disable-integritysetup], [disable integritysetup support]),
[], [enable_integritysetup=yes])
@@ -411,7 +475,7 @@ if test "x$enable_ssh_token" = "xyes"; then
AC_CHECK_DECLS([ssh_session_is_known_server], [], [], [#include <libssh/libssh.h>])
AC_CHECK_HEADER([argp.h], [], AC_MSG_ERROR([You need argp library.]))
saved_LIBS=$LIBS
AC_SEARCH_LIBS([argp_usage],[argp])
AC_SEARCH_LIBS([argp_parse],[argp])
AC_SUBST(ARGP_LIBS, $LIBS)
LIBS=$saved_LIBS
fi
@@ -457,7 +521,15 @@ AC_ARG_ENABLE([internal-argon2],
AC_ARG_ENABLE([libargon2],
AS_HELP_STRING([--enable-libargon2], [enable external libargon2 (PHC) library (disables internal bundled version)]))
if test "x$enable_libargon2" = "xyes" ; then
if test $use_internal_argon2 = 0 -o "x$enable_internal_argon2" = "xno" ; then
if test "x$enable_internal_argon2" = "xyes" -o "x$enable_libargon" = "xyes"; then
AC_MSG_WARN([Argon2 in $with_crypto_backend lib is used; internal Argon2 options are ignored.])
fi
enable_internal_argon2=no
enable_internal_sse_argon2=no
enable_libargon2=no
use_internal_argon2=0
elif test "x$enable_libargon2" = "xyes" ; then
AC_CHECK_HEADERS(argon2.h,,
[AC_MSG_ERROR([You need libargon2 development library installed.])])
AC_CHECK_DECL(Argon2_id,,[AC_MSG_ERROR([You need more recent Argon2 library with support for Argon2id.])], [#include <argon2.h>])
@@ -481,11 +553,10 @@ else
fi
fi
if test "x$enable_internal_argon2" = "xyes"; then
AC_DEFINE(USE_INTERNAL_ARGON2, 1, [Use internal Argon2])
fi
AM_CONDITIONAL(CRYPTO_INTERNAL_ARGON2, test "x$enable_internal_argon2" = "xyes")
AM_CONDITIONAL(CRYPTO_INTERNAL_SSE_ARGON2, test "x$enable_internal_sse_argon2" = "xyes")
dnl If libargon is in use, we have defined HAVE_ARGON2_H
AC_DEFINE_UNQUOTED(USE_INTERNAL_ARGON2, [$use_internal_argon2], [Use internal Argon2])
dnl Link with blkid to check for other device types
AC_ARG_ENABLE([blkid],
@@ -520,6 +591,27 @@ AM_CONDITIONAL(HAVE_BLKID, test "x$enable_blkid" = "xyes")
AM_CONDITIONAL(HAVE_BLKID_WIPE, test "x$enable_blkid_wipe" = "xyes")
AM_CONDITIONAL(HAVE_BLKID_STEP_BACK, test "x$enable_blkid_step_back" = "xyes")
AC_ARG_ENABLE([hw-opal],
AS_HELP_STRING([--disable-hw-opal], [disable use of hardware-backed OPAL for device encryption]),
[],
[enable_hw_opal=yes])
if test "x$enable_hw_opal" = "xyes"; then
have_opal=yes
AC_CHECK_DECLS([ OPAL_FL_SUM_SUPPORTED,
IOC_OPAL_GET_LR_STATUS,
IOC_OPAL_GET_GEOMETRY
],
[],
[have_opal=no],
[#include <linux/sed-opal.h>])
if test "x$have_opal" = "xyes"; then
AC_DEFINE([HAVE_HW_OPAL], 1, [Define to 1 to enable OPAL support.])
else
AC_MSG_WARN([Can not compile with OPAL support, kernel headers are too old, requires v6.4.])
fi
fi
dnl Magic for cryptsetup.static build.
if test "x$enable_static_cryptsetup" = "xyes"; then
saved_PKG_CONFIG=$PKG_CONFIG
@@ -552,6 +644,23 @@ if test "x$enable_static_cryptsetup" = "xyes"; then
PKG_CONFIG=$saved_PKG_CONFIG
fi
dnl Check compiler support for symver function attribute
AC_MSG_CHECKING([for symver attribute support])
saved_CFLAGS=$CFLAGS
CFLAGS="-O0 -Werror"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
void _test_sym(void);
__attribute__((__symver__("sym@VERSION_4.2"))) void _test_sym(void) {}
]],
[[ _test_sym() ]]
)],[
AC_DEFINE([HAVE_ATTRIBUTE_SYMVER], 1, [Define to 1 to use __attribute__((symver))])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
])
CFLAGS=$saved_CFLAGS
AC_MSG_CHECKING([for systemd tmpfiles config directory])
PKG_CHECK_VAR([systemd_tmpfilesdir], [systemd], [tmpfilesdir], [], [systemd_tmpfilesdir=no])
AC_MSG_RESULT([$systemd_tmpfilesdir])
@@ -577,6 +686,22 @@ AC_SUBST([LIBSSH_LIBS])
AC_SUBST([LIBCRYPTSETUP_VERSION])
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
dnl Set Requires.private for libcryptsetup.pc
dnl pwquality is used only by tools
PKGMODULES="uuid devmapper json-c"
case $with_crypto_backend in
gcrypt) PKGMODULES="$PKGMODULES libgcrypt" ;;
openssl) PKGMODULES="$PKGMODULES openssl" ;;
nss) PKGMODULES="$PKGMODULES nss" ;;
nettle) PKGMODULES="$PKGMODULES nettle" ;;
esac
if test "x$enable_libargon2" = "xyes"; then
PKGMODULES="$PKGMODULES libargon2"
fi
if test "x$enable_blkid" = "xyes"; then
PKGMODULES="$PKGMODULES blkid"
fi
AC_SUBST([PKGMODULES])
dnl ==========================================================================
AC_ARG_ENABLE([dev-random],
AS_HELP_STRING([--enable-dev-random], [use /dev/random by default for key generation (otherwise use /dev/urandom)]))
@@ -612,9 +737,9 @@ AC_DEFUN([CS_ABSPATH], [
])
dnl ==========================================================================
CS_STR_WITH([plain-hash], [password hashing function for plain mode], [ripemd160])
CS_STR_WITH([plain-hash], [password hashing function for plain mode], [sha256])
CS_STR_WITH([plain-cipher], [cipher for plain mode], [aes])
CS_STR_WITH([plain-mode], [cipher mode for plain mode], [cbc-essiv:sha256])
CS_STR_WITH([plain-mode], [cipher mode for plain mode], [xts-plain64])
CS_NUM_WITH([plain-keybits],[key length in bits for plain mode], [256])
CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha256])
@@ -699,5 +824,6 @@ lib/libcryptsetup.pc
po/Makefile.in
scripts/cryptsetup.conf
tests/Makefile
tests/fuzz/Makefile
])
AC_OUTPUT

View File

@@ -74,7 +74,7 @@
2012-03-16 Milan Broz <gmazyland@gmail.com>
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
* Add repair command and crypt_repair() for known LUKS metadata problems repair.
* Allow to specify --align-payload only for luksFormat.
* Allow one to specify --align-payload only for luksFormat.
2012-03-16 Milan Broz <mbroz@redhat.com>
* Unify password verification option.
@@ -228,7 +228,7 @@
* Fix password callback call.
* Fix default plain password entry from terminal in activate_by_passphrase.
* Add --dump-master-key option for luksDump to allow volume key dump.
* Allow to activate by internally cached volume key
* Allow one to activate by internally cached volume key
(format/activate without keyslots active - used for temporary devices).
* Initialize volume key from active device in crypt_init_by_name()
* Fix cryptsetup binary exitcodes.

View File

@@ -1,7 +1,7 @@
/*
* libcryptsetup API log example
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -1,7 +1,7 @@
/*
* libcryptsetup API - using LUKS device example
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

Binary file not shown.

View File

@@ -85,7 +85,7 @@ Libcryptsetup API additions:
* Fix optional password callback handling.
* Allow to activate by internally cached volume key immediately after
* Allow one to activate by internally cached volume key immediately after
crypt_format() without active slot (for temporary devices with
on-disk metadata)

View File

@@ -24,7 +24,7 @@ Changes since version 1.4.1
* Fix header check to support old (cryptsetup 1.0.0) header alignment.
(Regression in 1.4.0)
* Allow to specify --align-payload only for luksFormat.
* Allow one to specify --align-payload only for luksFormat.
* Add --master-key-file option to luksOpen (open using volume key).

View File

@@ -32,7 +32,7 @@ Changes since version 1.4.2
Device-mapper now retry removal if device is busy.
* Allow "private" activation (skip some udev global rules) flag.
Cryptsetup library API now allows to specify CRYPT_ACTIVATE_PRIVATE,
Cryptsetup library API now allows one to specify CRYPT_ACTIVATE_PRIVATE,
which means that some udev rules are not processed.
(Used for temporary devices, like internal keyslot mappings where
it is not desirable to run any device scans.)

View File

@@ -4,7 +4,7 @@ Cryptsetup 1.6.0 Release Notes
Changes since version 1.6.0-rc1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Change LUKS default cipher to to use XTS encryption mode,
* Change LUKS default cipher to use XTS encryption mode,
aes-xts-plain64 (i.e. using AES128-XTS).
XTS mode becomes standard in hard disk encryption.
@@ -209,7 +209,7 @@ Important changes
WARNING: these tests do not use dmcrypt, only crypto API.
You have to benchmark the whole device stack and you can get completely
different results. But is is usable for basic comparison.
different results. But it is usable for basic comparison.
(Note for example AES-NI decryption optimization effect in example above.)
Features

View File

@@ -8,7 +8,7 @@ Changes since version 1.6.1
* Fix cipher specification string parsing (found by gcc -fsanitize=address option).
* Try to map TCRYPT system encryption through partition
(allows to activate mapping when other partition on the same device is mounted).
(allows one to activate mapping when other partition on the same device is mounted).
* Print a warning if system encryption is used and device is a partition.
(TCRYPT system encryption uses whole device argument.)

View File

@@ -25,7 +25,7 @@ Changes since version 1.6.3
Please refer to cryptsetup FAQ for detail how to fix this situation.
* Allow to use --disable-gcrypt-pbkdf2 during configuration
* Allow one to use --disable-gcrypt-pbkdf2 during configuration
to force use internal PBKDF2 code.
* Require gcrypt 1.6.1 for imported implementation of PBKDF2

View File

@@ -38,7 +38,7 @@ Changes since version 1.6.4
The command "cryptsetup status" will print basic info, even if you
do not provide detached header argument.
* Allow to specify ECB mode in cryptsetup benchmark.
* Allow one to specify ECB mode in cryptsetup benchmark.
* Add some LUKS images for regression testing.
Note that if image with Whirlpool fails, the most probable cause is that

View File

@@ -35,14 +35,14 @@ Changes since version 1.6.6
* Support permanent device decryption for cryptsetup-reencrypt.
To remove LUKS encryption from a device, you can now use --decrypt option.
* Allow to use --header option in all LUKS commands.
* Allow one to use --header option in all LUKS commands.
The --header always takes precedence over positional device argument.
* Allow luksSuspend without need to specify a detached header.
* Detect if O_DIRECT is usable on a device allocation.
There are some strange storage stack configurations which wrongly allows
to open devices with direct-io but fails on all IO operations later.
one to open devices with direct-io but fails on all IO operations later.
Cryptsetup now tries to read the device first sector to ensure it can use
direct-io.

View File

@@ -30,7 +30,7 @@ Changes since version 1.6.7
cryptsetup resize will try to resize underlying loop device as well.
(It can be used to grow up file-backed device in one step.)
* Cryptsetup now allows to use empty password through stdin pipe.
* Cryptsetup now allows one to use empty password through stdin pipe.
(Intended only for testing in scripts.)
Cryptsetup API NOTE:

View File

@@ -3,7 +3,7 @@ Cryptsetup 1.7.4 Release Notes
Changes since version 1.7.3
* Allow to specify LUKS1 hash algorithm in Python luksFormat wrapper.
* Allow one to specify LUKS1 hash algorithm in Python luksFormat wrapper.
* Use LUKS1 compiled-in defaults also in Python wrapper.

View File

@@ -89,7 +89,7 @@ Important features
Integritysetup is intended to be used for settings that require
non-cryptographic data integrity protection with no data encryption.
Fo setting integrity protected encrypted devices, see disk authenticated
For setting integrity protected encrypted devices, see disk authenticated
encryption below.
Note that after formatting the checksums need to be initialized;
@@ -583,7 +583,7 @@ Unfinished things & TODO for next releases
in kernel (more on this later).
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
in kernel have too small 96-bit nonces that are problematic with
randomly generated IVs (the collison probability is not negligible).
randomly generated IVs (the collision probability is not negligible).
For the GCM, nonce collision is a fatal problem.
* Authenticated encryption do not set encryption for dm-integrity journal.

View File

@@ -30,7 +30,7 @@ Changes since version 2.0.1
* Add LUKS2 specific options for cryptsetup-reencrypt.
Tokens and persistent flags are now transferred during reencryption;
change of PBKDF keyslot parameters is now supported and allows
change of PBKDF keyslot parameters is now supported and allows one
to set precalculated values (no benchmarks).
* Do not allow LUKS2 --persistent and --test-passphrase cryptsetup flags

View File

@@ -28,7 +28,7 @@ Changes since version 2.0.2
* New API extensions for unbound keyslots (LUKS2 only)
crypt_keyslot_get_key_size() and crypt_volume_key_get()
These functions allow to get key and key size for unbound keyslots.
These functions allow one to get key and key size for unbound keyslots.
* New enum value CRYPT_SLOT_UNBOUND for keyslot status (LUKS2 only).

View File

@@ -170,21 +170,21 @@ These new calls are now exported, for details see libcryptsetup.h:
* crypt_get_metadata_size
* crypt_set_metadata_size
allows to set/get area sizes in LUKS header
allows one to set/get area sizes in LUKS header
(according to specification).
* crypt_get_default_type
get default compiled-in LUKS type (version).
* crypt_get_pbkdf_type_params
allows to get compiled-in PBKDF parameters.
allows one to get compiled-in PBKDF parameters.
* crypt_keyslot_set_encryption
* crypt_keyslot_get_encryption
allows to set/get per-keyslot encryption algorithm for LUKS2.
allows one to set/get per-keyslot encryption algorithm for LUKS2.
* crypt_keyslot_get_pbkdf
allows to get PBKDF parameters per-keyslot.
allows one to get PBKDF parameters per-keyslot.
and these new defines:
* CRYPT_LOG_DEBUG_JSON (message type for JSON debug)

View File

@@ -9,7 +9,7 @@ native read-write access to BitLocker Full Disk Encryption devices.
The BITLK implementation is based on publicly available information
and it is an independent and opensource implementation that allows
to access this proprietary disk encryption.
one to access this proprietary disk encryption.
Changes since version 2.2.2
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -18,7 +18,7 @@ Changes since version 2.3.1
The slot number --key-slot (-S) option is mandatory here.
An unbound keyslot store a key is that is not assigned to data
area on disk (LUKS2 allows to store arbitrary keys).
area on disk (LUKS2 allows one to store arbitrary keys).
* Rephrase some error messages and remove redundant end-of-lines.

View File

@@ -75,7 +75,7 @@ Changes since version 2.3.3
If users want to use blake2b/blake2s, the kernel algorithm name includes
a dash (like "blake2s-256").
Theses algorithms can now be used for integritysetup devices.
These algorithms can now be used for integritysetup devices.
* Fix crypto backend to properly handle ECB mode.

101
docs/v2.4.3-ReleaseNotes Normal file
View File

@@ -0,0 +1,101 @@
Cryptsetup 2.4.3 Release Notes
==============================
Stable security bug-fix release that fixes CVE-2021-4122.
All users of cryptsetup 2.4.x must upgrade to this version.
Changes since version 2.4.2
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix possible attacks against data confidentiality through LUKS2 online
reencryption extension crash recovery (CVE-2021-4122).
An attacker can modify on-disk metadata to simulate decryption in
progress with crashed (unfinished) reencryption step and persistently
decrypt part of the LUKS device.
This attack requires repeated physical access to the LUKS device but
no knowledge of user passphrases.
The decryption step is performed after a valid user activates
the device with a correct passphrase and modified metadata.
There are no visible warnings for the user that such recovery happened
(except using the luksDump command). The attack can also be reversed
afterward (simulating crashed encryption from a plaintext) with
possible modification of revealed plaintext.
The size of possible decrypted data depends on configured LUKS2 header
size (metadata size is configurable for LUKS2).
With the default parameters (16 MiB LUKS2 header) and only one
allocated keyslot (512 bit key for AES-XTS), simulated decryption with
checksum resilience SHA1 (20 bytes checksum for 4096-byte blocks),
the maximal decrypted size can be over 3GiB.
The attack is not applicable to LUKS1 format, but the attacker can
update metadata in place to LUKS2 format as an additional step.
For such a converted LUKS2 header, the keyslot area is limited to
decrypted size (with SHA1 checksums) over 300 MiB.
The issue is present in all cryptsetup releases since 2.2.0.
Versions 1.x, 2.0.x, and 2.1.x are not affected, as these do not
contain LUKS2 reencryption extension.
The problem was caused by reusing a mechanism designed for actual
reencryption operation without reassessing the security impact for new
encryption and decryption operations. While the reencryption requires
calculating and verifying both key digests, no digest was needed to
initiate decryption recovery if the destination is plaintext (no
encryption key). Also, some metadata (like encryption cipher) is not
protected, and an attacker could change it. Note that LUKS2 protects
visible metadata only when a random change occurs. It does not protect
against intentional modification but such modification must not cause
a violation of data confidentiality.
The fix introduces additional digest protection of reencryption
metadata. The digest is calculated from known keys and critical
reencryption metadata. Now an attacker cannot create correct metadata
digest without knowledge of a passphrase for used keyslots.
For more details, see LUKS2 On-Disk Format Specification version 1.1.0.
The former reencryption operation (without the additional digest) is no
longer supported (reencryption with the digest is not backward
compatible). You need to finish in-progress reencryption before
updating to new packages. The alternative approach is to perform
a repair command from the updated package to recalculate reencryption
digest and fix metadata.
The reencryption repair operation always require a user passphrase.
WARNING: Devices with older reencryption in progress can be no longer
activated without performing the action mentioned above.
Encryption in progress can be detected by running the luksDump command
(output includes reencrypt keyslot with reencryption parameters). Also,
during the active reencryption, no keyslot operations are available
(change of passphrases, etc.).
The issue was found by Milan Broz as cryptsetup maintainer.
Other changes
~~~~~~~~~~~~~
* Add configure option --disable-luks2-reencryption to completely disable
LUKS2 reencryption code.
When used, the libcryptsetup library can read metadata with
reencryption code, but all reencryption API calls and cryptsetup
reencrypt commands are disabled.
Devices with online reencryption in progress cannot be activated.
This option can cause some incompatibilities. Please use with care.
* Improve internal metadata validation code for reencryption metadata.
* Add updated documentation for LUKS2 On-Disk Format Specification
version 1.1.0 (with reencryption extension description and updated
metadata description). See docs/on-disk-format-luks2.pdf or online
version in https://gitlab.com/cryptsetup/LUKS2-docs repository.
* Fix support for bitlk (BitLocker compatible) startup key with new
metadata entry introduced in Windows 11.
* Fix space restriction for LUKS2 reencryption with data shift.
The code required more space than was needed.

291
docs/v2.5.0-ReleaseNotes Normal file
View File

@@ -0,0 +1,291 @@
Cryptsetup 2.5.0 Release Notes
==============================
Stable release with new features and bug fixes.
Changes since version 2.4.3
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Split manual pages into per-action pages and use AsciiDoc format.
Manual pages are now generated from AsciiDoc format, allowing easy
conditional modifications for per-action options.
Generation of man pages requires the asciidoctor tool installed.
Pre-generated man pages are also included in the distribution tarball.
You can use --disable-asciidoc configure option to skip man page
generation completely. In this case, pre-generated man pages will be
used for installation.
For cryptsetup, there is main man page (cryptsetup.8) that references
separate man pages for each command (for example, cryptsetup-open.8).
You can open such a man page by simply running "man cryptsetup open".
Also, man pages for action aliases are available (cryptsetup-luksOpen.8
is an alias for cryptsetup-open.8, etc.)
LUKS volume reencryption changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Remove cryptsetup-reencrypt tool from the project and move reencryption
to already existing "cryptsetup reencrypt" command.
Cryptsetup reencrypt now handles both LUKS1 and LUKS2 reencryption,
encryption, and decryption.
If you need to emulate the old cryptsetup-reencrypt binary, use simple
wrappers script running "exec cryptsetup reencrypt $@".
All command line options should be compatible. An exception is the
reencryption of LUKS2 volumes with old LUKS1 reencryption code that was
replaced by native and more resilient LUKS2 reencryption.
* LUKS2: implement --decryption option that allows LUKS removal. The
operation can run online or offline and supports the data shift option.
During the initialization, the LUKS2 header is exported to a file.
The first data segment is moved to the head of the data device in place
of the original header.
The feature internally introduces several new resilience modes
(combination of existing modes datashift and "checksum" or "journal").
Datashift resilience mode is applied for data moved towards the first
segment, and the first segment is then decrypted in place.
This decryption mode is not backward compatible with prior LUKS2
reencryption. Interrupted operations in progress cannot be resumed
using older cryptsetup releases.
* Reencryption metadata options that are not compatible with recent code
(features implemented in more recent releases) are now only read, but
code will not activate or modify such metadata.
Reencryption metadata contains a version that is validated when
reencryption is resumed.
For more info, see the updated LUKS2 on-disk format specification.
Safe operation of reencryption is to always finish the operation with
only one version of the tools.
* Fix decryption operation with --active-name option and restrict
it to be used only with LUKS2.
* Do not refresh reencryption digest when not needed.
This should speed up the reencryption resume process.
* Store proper resilience data in LUKS2 reencrypt initialization.
Resuming reencryption now does not require specification of resilience
type parameters if these are the same as during initialization.
* Properly wipe the unused area after reencryption with datashift in
the forward direction.
* Check datashift value against larger sector size.
For example, it could cause an issue if misaligned 4K sector appears
during decryption.
* Do not allow sector size increase reencryption in offline mode.
The eventual logical block size increase on the dm-crypt device above
may lead to an unusable filesystem. Do not allow offline reencryption
when sector size increase is requested.
You can use --force-offline-reencrypt option to override this check
(and potentially destroy the data).
* Do not allow dangerous sector size change during reencryption.
By changing the encryption sector size during reencryption, a user
may increase the effective logical block size for the dm-crypt active
device.
Do not allow encryption sector size to be increased over the value
provided by fs superblock in BLOCK_SIZE property.
* Ask the user for confirmation before resuming reencryption.
The prompt is not shown in batch mode or when the user explicitly asks
for a reencryption resume via --resume-only.
* Do not resume reencryption with conflicting parameters.
For example, if the operation was initialized as --encrypt, do not
allow resume with opposing parameter --decrypt and vice versa.
Also, the code now checks for conflicting resilience parameters
(datashift cannot be changed after initialization).
* Add --force-offline-reencrypt option.
It can be used to enforce offline reencryption in batch mode when
the device is a regular file; therefore, cryptsetup cannot detect
properly active devices using it.
Also, it may be useful to override the active device auto-detection
for specific storage configurations (dangerous!).
* Do not allow nested encryption in LUKS reencrypt.
Avoid accidental nested encryption via cryptsetup reencrypt --encrypt.
* Fix --test-passphrase when the device is in reencryption.
* Do not upload keys in keyring during offline reencryption.
Reencryption runs in userspace, so the kernel does not need the key.
* Support all options allowed with luksFormat with encrypt action.
* Add prompt if LUKS2 decryption is run with a detached header.
* Add warning for reencryption of file image and mention
the possible use of --force-offline-reencrypt option.
Other changes
~~~~~~~~~~~~~
* Add resize action to integritysetup.
This allows resizing of standalone integrity devices.
* Support --device-size option (that allows unit specification) for plain
devices (existing --size option requires 512-byte sectors units).
* Fix detection of encryption sector size if a detached header is used.
* Remove obsolete dracut plugin reencryption example.
* Fix possible keyslot area size overflow during conversion to LUKS2.
If keyslots are not sorted according to binary area offset, the area
size calculation was wrong and could overflow.
* Hardening and fixes to LUKS2 validation functions:
* Log a visible error if convert fails due to validation check.
* Check for interval (keyslot and segment area) overflow.
* Check cipher availability before LUKS conversion to LUKS2.
Some historic incompatibilities are ignored for LUKS1 but do not
work for LUKS2.
* Add empty string check to LUKS2 metadata JSON validation.
Most of the LUKS2 fields cannot be empty.
* Fix JSON objects validation to check JSON object type properly.
* TCRYPT: Properly apply retry count and continue if some PBKDF variant
is unavailable.
* BITLK: Add a warning when activating a device with the wrong size
stored in metadata.
* BITLK: Add BitLocker volume size to dump command.
* BITLK: Fix possible UTF16 buffer overflow in volume key dump.
* BITLK: Skip question if the batch mode is set for volume key dump.
* BITLK: Check dm-zero availability in the kernel.
Bitlocker compatible mode uses dm-zero to mask metadata area.
The device cannot be activated if dm-zero is not available.
* Fix error message for LUKS2-only cryptsetup commands to explicitly
state LUKS2 version is required.
* Fix error message for incompatible dm-integrity metadata.
If the integritysetup tool is too old, kernel dm-integrity may use
a more recent version of dm-integrity metadata.
* Properly deactivate the integrity device even if the LUKS2 header
is no longer available.
If LUKS2 is used with integrity protection, there is always
a dm-integrity device underneath that must be deactivated.
* Allow use of --header option for cryptsetup close.
This can be used to check that the activated device has the same UUID.
* Fix activation of LUKS2 device with integrity and detached header.
The kernel-parsed dm-integrity superblock is always located on the
data device, the incorrectly used detached header device here.
* Add ZEROOUT IOCTL support for crypt_wipe API call.
For block devices, we can use optimized in-kernel BLKZEROOUT ioctl.
* VERITY: set loopback sector size according to dm-verity block sizes.
Verity block size has the same limits, so we can optimize the loop
device to increase performance.
* Other Documentation and man page improvements:
* Update LUKS2 on-disk format description.
* Add per-keyslot LUKS2 options to the man page.
Some options were missing for LUKS2 luksAddKey and luksChangeKey.
* Fix cryptsetup manpage to use PBKDF consistently.
* Add compile info to README. This information was lost when we removed
the default automake INSTALL file.
* Use volume key consistently in FAQ and man pages.
* Use markdown version of FAQ directly for installation.
* Clarify graceful reencryption interruption.
Currently, it can be interrupted by both SIGINT and SIGTERM signals.
* Add new mailing list info.
* Mention non-cryptographic xxhash64 hash for integrity protection.
* veritysetup: dump device sizes.
Calculating device sizes for verity devices is a little bit tricky.
Data, hash, and FEC can share devices or be separate devices.
Now dump command prints used device sizes, but it requires that
the user specifies all values that are not stored in superblock
(like FEC device and FEC roots).
* Fix check for argp_usage in configure if argp-standalone lib is used.
* Add constant time memcmp and hexa print implementation and use it for
cryptographic keys handling.
* Display progress when wiping the end of the resized device.
* LUKS2 token: prefer token PIN query before passphrase in some cases.
When a user provides --token-type or specific --token-id, a token PIN
query is preferred to a passphrase query.
* LUKS2 token: allow tokens to be replaced with --token-replace option
for cryptsetup token command.
* LUKS2 token: do not continue operation when interrupted in PIN prompt.
* Add --progress-json parameter to utilities.
Progress data can now be printed out in JSON format suitable for
machine processing.
* Embedded Argon2 PBKDF: optimize and simplify thread exit.
* Avoid using SHA1 in tests and fix new enforcements introduced in FIPS
provider for OpenSSL3 (like minimal parameters for PBKDF2).
* Use custom UTF conversion and avoid linking to iconv as a dependency.
* Reimplement BASE64 with simplified code instead of coreutils version.
* Fix regression when warning messages were not displayed
if some kernel feature is not supported (2.4.2).
* Add support for --key-slot option in luksResume action.
Libcryptsetup API extensions and changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Properly define uint32_t constants in API.
This is not a real change, but it avoids strict compiler warnings.
* crypt_resume_by_token_pin() - Resume crypt device using LUKS2 token.
* crypt_get_label() - Get the label of the LUKS2 device.
* crypt_get_subsystem() - Get the subsystem label of the LUKS2 device.
* Make CRYPT_WIPE_ENCRYPTED_ZERO crypt_wipe() option obsolete.
It was never implemented (the idea was to speed up wipe), but with
the recent RNG performance changes, it makes no longer sense.
* Add struct crypt_params_reencrypt changes related to decryption.
* Improve crypt_reencrypt_status() return values.
Empty or any non-LUKS types now returns CRYPT_REENCRYPT_INVALID status.
For LUKS1 devices, it returns CRYPT_REENCRYPT_NONE.

236
docs/v2.6.0-ReleaseNotes Normal file
View File

@@ -0,0 +1,236 @@
Cryptsetup 2.6.0 Release Notes
==============================
Stable release with new features and bug fixes.
Changes since version 2.5.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Introduce support for handling macOS FileVault2 devices (FVAULT2).
Cryptsetup now supports the mapping of FileVault2 full-disk encryption
by Apple for the macOS operating system using a native Linux kernel.
You can open an existing USB FileVault portable device and (with
the hfsplus filesystem driver) access the native data read/write.
Cryptsetup supports only (legacy) FileVault2 based on Core Storage
and HFS+ filesystem (introduced in MacOS X 10.7 Lion).
It does NOT support the new version of FileVault based on the APFS
filesystem used in recent macOS versions.
Header formatting and changes are not supported; cryptsetup never
changes the metadata on the device.
FVAULT2 extension requires kernel userspace crypto API and kernel
driver for HFS+ (hfsplus) filesystem (available on most systems today).
Example of using FileVault2 formatted USB device:
A typical encrypted device contains three partitions; the FileVault
encrypted partition is here sda2:
$ lsblk -o NAME,FSTYPE,LABEL /dev/sda
NAME FSTYPE LABEL
sda
|-sda1 vfat EFI
|-sda2
`-sda3 hfsplus Boot OS X
Note: blkid does not recognize FileVault2 format yet.
To dump metadata information about the device, you can use
the fvault2Dump command:
$ cryptsetup fvault2Dump /dev/sda2
Header information for FVAULT2 device /dev/sda2.
Physical volume UUID: 6f353c05-daae-4e76-a0ee-6a9569a22d81
Family UUID: f82cceb0-a788-4815-945a-53d57fcd55a8
Logical volume offset: 67108864 [bytes]
Logical volume size: 3288334336 [bytes]
Cipher: aes
Cipher mode: xts-plain64
PBKDF2 iterations: 97962
PBKDF2 salt: 173a4ec7447662ec79ca7a47df6c2a01
To activate the device, use open --type fvault2 option:
$ cryptsetup open --type fvault2 /dev/sda2 test
Enter passphrase for /dev/sda2: ...
And check the status of the active device:
$ cryptsetup status test
/dev/mapper/test is active.
type: FVAULT2
cipher: aes-xts-plain64
keysize: 256 bits
key location: dm-crypt
device: /dev/sda2
sector size: 512
offset: 131072 sectors
size: 6422528 sectors
mode: read/write
Now, if the kernel contains hfsplus filesystem driver, you can mount
decrypted content:
$ mount /dev/mapper/test /mnt/test
For more info about implementation, please refer to the master thesis
by Pavel Tobias, which was the source for this extension.
https://is.muni.cz/th/p0aok/?lang=en
* libcryptsetup: no longer use global memory locking through mlockall()
For many years, libcryptsetup locked all memory (including dependent
library address space) to prevent swapping sensitive content outside
of RAM.
This strategy no longer works as the locking of basic libraries exceeds
the memory locking limit if running as a non-root user.
Libcryptsetup now locks only memory ranges containing sensitive
material (keys) through crypt_safe_alloc() calls.
This change solves many reported mysterious problems of unexpected
failures. If the initial lock was still under the limit and succeeded,
some following memory allocation could fail later as it exceeded
the locking limit. If the initial locking fails, memory locking
was quietly ignored completely.
The whole crypt_memory_lock() API call is deprecated; it no longer
calls memlockall().
* libcryptsetup: process priority is increased only for key derivation
(PBKDF) calls.
Increasing priority was tight to memory locking and works only if
running under superuser.
Only PBKDF calls and benchmarking now increase the process priority.
* Add new LUKS keyslot context handling functions and API.
In practice, the luksAddKey action does two operations.
It unlocks the existing device volume key and stores the unlocked
volume key in a new keyslot.
Previously the options were limited to key files and passphrases.
Newly available methods (keyslot contexts) are passphrase, keyfile,
key (binary representation), and LUKS2 token.
To unlock a keyslot user may:
- provide existing passphrase via interactive prompt (default method)
- use --key-file option to provide a file with a valid passphrase
- provide volume key directly via --volume-key-file
- unlock keyslot via all available LUKS2 tokens by --token-only
- unlock keyslot via specific token with --token-id
- unlock keyslot via specific token type by --token-type
To provide the passphrase for a new keyslot, a user may:
- provide existing passphrase via interactive prompt (default method)
- use --new-keyfile to read the passphrase from the file
- use --new-token-id to select LUKS2 token to get passphrase
for new keyslot. The new keyslot is assigned to the selected token
id if the operation is successful.
* The volume key may now be extracted using a passphrase, keyfile, or
token. For LUKS devices, it also returns the volume key after
a successful crypt_format call.
* Fix --disable-luks2-reencryption configuration option.
* cryptsetup: Print a better error message and warning if the format
produces an image without space available for data.
Activation now fails early with a more descriptive message.
* Print error if anti-forensic LUKS2 hash setting is not available.
If the specified hash was not available, activation quietly failed.
* Fix internal crypt segment compare routine if the user
specified cipher in kernel format (capi: prefix).
* cryptsetup: Add token unassign action.
This action allows removing token binding on specific keyslot.
* veritysetup: add support for --use-tasklets option.
This option sets try_verify_in_tasklet kernel dm-verity option
(available since Linux kernel 6.0) to allow some performance
improvement on specific systems.
* Provide pkgconfig Require.private settings.
While we do not completely provide static build on udev systems,
it helps produce statically linked binaries in certain situations.
* Always update automake library files if autogen.sh is run.
For several releases, we distributed older automake scripts by mistake.
* reencryption: Fix user defined moved segment size in LUKS2 decryption.
The --hotzone-size argument was ignored in cases where the actual data
size was less than the original LUKS2 data offset.
* Delegate FIPS mode detection to configured crypto backend.
System FIPS mode check no longer depends on /etc/system-fips file.
* tests: externally provided systemd plugin is now optionally compiled
from systemd git and tested with cryptsetup
* tests: initial integration to OSS-fuzz project with basic crypt_load()
test for LUKS2 and JSON mutated fuzzing.
For more info, see README in tests/fuzz directory.
* Update documentation, including FAQ and man pages.
Libcryptsetup API extensions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The libcryptsetup API is backward compatible with existing symbols.
New symbols:
crypt_keyslot_context_init_by_passphrase
crypt_keyslot_context_init_by_keyfile
crypt_keyslot_context_init_by_token
crypt_keyslot_context_init_by_volume_key
crypt_keyslot_context_get_error
crypt_keyslot_context_set_pin
crypt_keyslot_context_get_type
crypt_keyslot_context_free
crypt_keyslot_add_by_keyslot_context
crypt_volume_key_get_by_keyslot_context
New defines:
CRYPT_FVAULT2 "FVAULT2" (FileVault2 compatible mode)
Keyslot context types:
CRYPT_KC_TYPE_PASSPHRASE
CRYPT_KC_TYPE_KEYFILE
CRYPT_KC_TYPE_TOKEN
CRYPT_KC_TYPE_KEY
CRYPT_ACTIVATE_TASKLETS (dm-verity: use tasklets activation flag)
WARNING!
~~~~~~~~
The next version of cryptsetup will change the encryption mode and key
derivation option for the PLAIN format.
This change will cause backward incompatibility.
For this reason, the user will have to specify the exact parameters
for cipher, key size, and key derivation parameters for plain format.
The default encryption mode will be AES-XTS with 512bit key (AES-256).
The CBC mode is no longer considered the best default, as it allows easy
bit-flipped ciphertext modification attacks and performance problems.
For the passphrase hashing in plain mode, the encryption key is directly
derived through iterative hashing from a user-provided passphrase
(except a keyfile that is not hashed).
The default hash is RIPEMD160, which is no longer the best default
option. The exact change will be yet discussed but should include
the possibility of using a password-based key derivation function
instead of iterative hashing.

50
docs/v2.6.1-ReleaseNotes Normal file
View File

@@ -0,0 +1,50 @@
Cryptsetup 2.6.1 Release Notes
==============================
Stable bug-fix release with minor extensions.
All users of cryptsetup 2.6.0 should upgrade to this version.
Changes since version 2.6.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* bitlk: Fixes for BitLocker-compatible on-disk metadata parser
(found by new cryptsetup OSS-Fuzz fuzzers).
- Fix a possible memory leak if the metadata contains more than
one description field.
- Harden parsing of metadata entries for key and description entries.
- Fix broken metadata parsing that can cause a crash or out of memory.
* Fix possible iteration overflow in OpenSSL2 PBKDF2 crypto backend.
OpenSSL2 uses a signed integer for PBKDF2 iteration count.
As cryptsetup uses an unsigned value, this can lead to overflow and
a decrease in the actual iteration count.
This situation can happen only if the user specifies
--pbkdf-force-iterations option.
OpenSSL3 (and other supported crypto backends) are not affected.
* Fix compilation for new ISO C standards (gcc with -std=c11 and higher).
* fvault2: Fix compilation with very old uuid.h.
* verity: Fix possible hash offset setting overflow.
* bitlk: Fix use of startup BEK key on big-endian platforms.
* Fix compilation with latest musl library.
Recent musl no longer implements lseek64() in some configurations.
Use lseek() as 64-bit offset is mandatory for cryptsetup.
* Do not initiate encryption (reencryption command) when the header and
data devices are the same.
If data device reduction is not requsted, this leads to data corruption
since LUKS metadata was written over the data device.
* Fix possible memory leak if crypt_load() fails.
* Always use passphrases with a minimal 8 chars length for benchmarking.
Some enterprise distributions decided to set an unconditional check
for PBKDF2 password length when running in FIPS mode.
This questionable change led to unexpected failures during LUKS format
and keyslot operations, where short passwords were used for
benchmarking PBKDF2 speed.
PBKDF2 benchmark calculations should not be affected by this change.

View File

@@ -0,0 +1,444 @@
Cryptsetup 2.7.0-rc1 Release Notes
==================================
Stable release candidate with new features and bug fixes.
Changes since version 2.7.0-rc0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Used Argon2 PBKDF implementation is now reported in debug mode
in the cryptographic backend version. For native support in
OpenSSL 3.2 or libgcrypt 1.11, "argon2" is displayed.
If libargon2 is used, "cryptsetup libargon2" (for embedded
library) or "external libargon2" is displayed.
* Fix wiping of OPAL key in the kernel on luksSuspend.
* Use metadata lock for OPAL disk manipulation to avoid unexpected
states if two processes manipulate the device.
Changes since version 2.6.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Introduce support for hardware OPAL disk encryption.
Some SATA and NVMe devices support hardware encryption through OPAL2
TCG interface (SEDs - self-encrypting drives). Using hardware disk
encryption is controversial as you must trust proprietary hardware.
On the other side, using both software and hardware encryption
layers increases the security margin by adding an additional layer
of protection. There is usually no performance drop if OPAL encryption
is used (the drive always operates with full throughput), and it does
not add any utilization to the main CPU.
LUKS2 now supports hardware encryption through the Linux kernel
SED OPAL interface (CONFIG_BLK_SED_OPAL Linux kernel option must be
enabled). Cryptsetup OPAL is never enabled by default; you have to use
luksFormat parameters to use it. OPAL support can be disabled during
the build phase with --disable-hw-opal configure option.
LUKS2 OPAL encryption is configured the same way as software encryption
- it stores metadata in the LUKS2 header and activates encryption for
the data area on the disk (configured OPAL locking range).
LUKS2 header metadata must always be visible (thus not encrypted).
The key stored in LUKS2 keyslots contains two parts - volume key
for software (dm-crypt) encryption and unlocking key for OPAL.
OPAL unlocking key is independent of the dm-crypt volume key and is
always 256 bits long. Cryptsetup does not support full drive OPAL
encryption; only a specific locking range is always used.
If the OPAL device is in its initial factory state (after factory
reset), cryptsetup needs to configure the OPAL admin user and password.
If the OPAL admin user is already set, the OPAL password must be
provided during luksFormat.
The provided password is needed only to configure or reset the OPAL
locking range; LUKS device activation requires LUKS passphrase only.
LUKS passphrase should be different from OPAL password (OPAL admin user
is configured inside OPAL hardware while LUKS unlocking passphrase
unlocks LUKS keyslot).
OPAL encryption can be used in combination with software (dm-crypt)
encryption (--hw-opal option) or without the software layer
(--hw-opal-only option).
You can see the configured segment parameters in the luksDump command.
LUKS2 devices with OPAL segments set a new requirement flag in
the LUKS2 header to prevent older cryptsetup metadata manipulation.
Do not use hardware-only encryption if you do not fully trust your
hardware vendor.
Compatibility notes:
- Linux kernel SED interface does NOT work through USB external
adapters due to the mising compatibility layer in Linux USB storage
drivers (even if USB hardware itself can support OPAL commands).
- other TCG security subsystems like Ruby or Pyrite are not
supported. Note that many drives support only Pyrite subsystem that
does NOT encrypt data (it provides only authentication).
- compatibility among OPAL-enabled drives is often very problematic,
specifically for older drives. Many drives have bugs in the firmware
that make the Linux kernel interface unusable.
- if you forget the OPAL admin password, the only way to recover is
the full drive factory reset through the PSID key (usually printed
on the drive itself) that wipes all data on the drive (not only the
LUKS area).
- cryptsetup reencryption is not supported for LUKS2 OPAL-enabled
devices
- most OPAL drives use AES-XTS cipher mode (older drives can use
AES-CBC). This information is not available through kernel SED API.
- locked OPAL locking ranges return IO errors while reading; this
can produce a lot of scary messages in the log if some tools (like
blkid) try to read the locked area.
Examples:
* Formatting the drive
Use --hw-opal with luksFormat (or --hw-opal-only for hardware only
encryption):
# cryptsetup luksFormat --hw-opal <device>
Enter passphrase for <device>: ***
Enter OPAL Admin password: ***
* Check configuration with luksDump.
Note "hw-opal-crypt" segment that uses both dm-crypt and OPAL
encryption - keyslot stores 768 bits key (512 sw + 256 bits OPAL key).
# cryptsetup luksDump <device>
LUKS header information
Version: 2
...
Data segments:
0: hw-opal-crypt
offset: 16777216 [bytes]
length: ... [bytes]
cipher: aes-xts-plain64
sector: 512 [bytes]
HW OPAL encryption:
OPAL segment number: 1
OPAL key: 256 bits
OPAL segment length: ... [bytes]
Keyslots:
0: luks2
Key: 768 bits
...
For devices with OPAL encryption ONLY (only 256 bits OPAL unlocking
key is stored):
LUKS header information
Version: 2
...
Data segments:
0: hw-opal
offset: 16777216 [bytes]
length: ... [bytes]
cipher: (no SW encryption)
HW OPAL encryption:
OPAL segment number: 1
OPAL key: 256 bits
OPAL segment length: ... [bytes]
Keyslots:
0: luks2
Key: 256 bits
...
* Activation and deactivation (open, close, luksSuspend, luksResume)
with OPAL works the same as for the LUKS2 device.
* Erase LUKS metadata (keyslots) and remove OPAL locking range:
# cryptsetup luksErase <device>
Enter OPAL Admin password: ***
The LUKS header is destroyed (unlike in normal LUKS luksErase) as
data are no longer accessible even with previous volume key knowledge.
* Factory reset OPAL drive (if you do not know the Admin password).
You need the PSID (physical presence security ID), which is usually
printed on the device label. Note this will reset the device to
factory state, erasing all data on it (not only LUKS).
# cryptsetup luksErase --hw-opal-factory-reset <device>
Enter OPAL PSID: ***
* plain mode: Set default cipher to aes-xts-plain64 and password hashing
to sha256.
NOTE: this is a backward incompatible change for plain mode (if you
rely on defaults). It is not relevant for LUKS devices.
The default plain encryption mode was CBC for a long time, with many
performance problems. Using XTS mode aligns it with LUKS defaults.
The hash algorithm for plain mode was ripemd160, which is considered
deprecated, so the new default is sha256.
The default key size remains 256 bits (it means using AES-128 as XTS
requires two keys).
Always specify cipher, hash, and key size for plain mode (or even
better, use LUKS as it stores all options in its metadata on disk).
As we need to upgrade algorithms from time to time because of security
reasons, cryptsetup now warns users to specify these options explicitly
in the open cryptsetup command if plain mode is used.
Cryptsetup does not block using any legacy encryption type; just it
must be specified explicitly on the cryptsetup command line.
You can configure these defaults during build time if you need to
enforce backward compatibility.
To get the backward-compatible setting, use:
--with-plain-hash=ripemd160 --with-plain-cipher=aes
--with-plain-mode=cbc-essiv:sha256
Compiled-in defaults are visible in cryptsetup --help output.
* Allow activation (open), luksResume, and luksAddKey to use the volume
key stored in a keyring.
* Allow to store volume key to a user-specified keyring in open and
luksResume commands.
These options are intended to be used for integration with other
systems for automation.
Users can now use the volume key (not passphrase) stored in arbitrary
kernel keyring and directly use it in particular cryptsetup commands
with --volume-key-keyring option. The keyring can use various policies
(set outside of the cryptsetup scope, for example, by keyctl).
The --volume-key-keyring option takes a key description in
keyctl-compatible syntax and can either be a numeric key ID or
a string name in the format [%<key type>:]<key name>.
The default key type is "user".
To store the volume key in a keyring, you can use cryptsetup with
--link-vk-to-keyring option that is available for open and luksResume
cryptsetup command. The option argument has a more complex format:
<keyring_description>::<key_description>.
The <keyring_description> contains the existing kernel keyring
description (numeric id or keyctl format). The <keyring_description>
may be optionaly prefixed with "%:" or "%keyring:". The string "::" is
a delimiter that separates keyring and key descriptions.
The <key_description> has the same syntax as used in the
--volume-key-keyring option.
Example:
Open the device and store the volume key to the keyring:
# cryptsetup open <device> --link-vk-to-keyring "@s::%user:testkey" tst
Add keyslot using the stored key in a keyring:
# cryptsetup luksAddKey <device> --volume-key-keyring "%user:testkey"
* Do not flush IO operations if resize grows the device.
This can help performance in specific cases where the encrypted device
is extended automatically while running many IO operations.
* Use only half of detected free memory for Argon2 PBKDF on systems
without swap (for LUKS2 new keyslot or format operations).
This should avoid out-of-memory crashes on low-memory systems without
swap. The benchmark for memory-hard KDF during format is tricky, and
it seems that relying on the maximum half of physical memory is not
enough; relying on free memory should bring the needed security margin
while still using Argon2.
There is no change for systems with active swap.
Note, for very-low memory-constrained systems, a user should avoid
memory-hard PBKDF completely (manually select legacy PBKDF2 instead
of Argon2); cryptsetup does not change PBKDF automatically.
* Add the possibility to specify a directory for external LUKS2 token
handlers (plugins).
Use --external-tokens-path parameter in cryptsetup or
crypt_token_set_external_path API call. The parameter is required to be
an absolute path, and it is set per process context. This parameter is
intended mainly for testing and developing new tokens.
* Do not allow reencryption/decryption on LUKS2 devices with
authenticated encryption or hardware (OPAL) encryption.
The operation fails later anyway; cryptsetup now detects incompatible
parameters early.
* Do not fail LUKS format if the operation was interrupted on subsequent
device wipe.
Device wipe (used with authenticated encryption) is an optional
operation and can be interrupted; not yet wiped part of the device will
only report integrity errors (until overwritten with new data).
* Fix the LUKS2 keyslot option to be used while activating the device
by a token.
It can also be used to check if a specific token (--token-id) can
unlock a specific keyslot (--key-slot option) when --test-passphrase
option is specified.
* Properly report if the dm-verity device cannot be activated due to
the inability to verify the signed root hash.
If the kernel returns ENOKEY, it is properly propagated.
* Fix to check passphrase for selected keyslot only when adding
new keyslot.
If the user specifies the exact keyslot to unlock, cryptsetup no longer
checks other keyslots.
* Fix to not wipe the keyslot area before in-place overwrite.
If the LUKS2 keyslot area has to be overwritten (due to lack of free
space for keyslot swap), cryptsetup does not wipe the affected area as
the first step (it will be overwritten later anyway).
Previously, there was an unnecessary risk of losing the keyslot data
if the code crashed before adding the new keyslot.
If there is enough space in the keyslot area, cryptsetup never
overwrites the older keyslot before the new one is written correctly
(even if the keyslot number remains the same).
* bitlk: Fix segfaults when attempting to verify the volume key.
Also, clarify that verifying the volume key is impossible without
providing a passphrase or recovery key.
* Add --disable-blkid command line option to avoid blkid device check.
* Add support for the meson build system.
All basic operations are supported (compile, test, and dist) with some
minor exceptions; please see the meson manual for more info.
The Meson build system will completely replace autotools in some future
major release. Both autotools and meson build systems are supported,
and the release archive is built with autotools.
* Fix wipe operation that overwrites the whole device if used for LUKS2
header with no keyslot area.
Formatting a LUKS2 device with no defined keyslots area is a very
specific operation, and the code now properly recognizes such
configuration.
* Fix luksErase to work with detached LUKS header.
* Disallow the use of internal kernel crypto driver names in "capi"
specification.
The common way to specify cipher mode in cryptsetup is to use
cipher-mode-iv notation (like aes-xts-plain64).
With the introduction of authenticated ciphers, we also allow
"capi:<spec>" notation that is directly used by dm-crypt
(e.g., capi:xts(aes)-plain64).
CAPI specification was never intended to be used directly in the LUKS
header; unfortunately, the code allowed it until now.
Devices with CAPI specification in metadata can no longer be activated;
header repair is required.
CAPI specification could allow attackers to change the cipher
specification to enforce loading some specific kernel crypto driver
(for example, load driver with known side-channel issues).
This can be problematic, specifically in a cloud environment
(modifying LUKS2 metadata in container image).
Thanks to Jan Wichelmann, Luca Wilke, and Thomas Eisenbarth from
University of Luebeck for noticing the problems with this code.
* Fix reencryption to fail early for unknown cipher.
* tcrypt: Support new Blake2 hash for VeraCrypt.
VeraCrypt introduces support for Blake2 PRF for PBKDF2; also support it
in cryptsetup compatible tcrypt format.
* tcrypt: use hash values as substring for limiting KDF check.
This allows the user to specify --hash sha or --hash blake2 to limit
the KDF scan without the need to specify the full algorithm name
(similar to cipher where we already use substring match).
* Add Aria cipher support and block size info.
Aria cipher is similar to AES and is supported in Linux kernel crypto
API in recent releases.
It can be now used also for LUKS keyslot encryption.
* Do not decrease PBKDF parameters if the user forces them.
If a user explicitly specifies PBKDF parameters (like iterations,
used memory, or threads), do not limit them, even if it can cause
resource exhaustion.
The force options were mostly used for decreasing parameters, but it
should work even opposite - despite the fact it can mean an
out-of-memory crash.
The only limits are hard limits per the PBKDF algorithm.
* Support OpenSSL 3.2 Argon2 implementation.
Argon2 is now available directly in OpenSSL, so the code no longer
needs to use libargon implementation.
Configure script should detect this automatically.
* Add support for Argon2 from libgcrypt
(requires yet unreleased gcrypt 1.11).
Argon2 has been available since version 1.10, but we need version 1.11,
which will allow empty passwords.
* Link only libcrypto from OpenSSL.
This reduces dependencies as other OpenSSL libraries are not needed.
* Disable reencryption for Direct-Access (DAX) devices.
Linux kernel device-mapper cannot stack DAX/non-DAX devices in
the mapping table, so online reencryption cannot work. Detect DAX
devices and warn users during LUKS format. Also, DAX or persistent
memory devices do not provide atomic sector updates; any single
modification can corrupt the whole encryption block.
* Print a warning message if the device is not aligned to sector size.
If a partition is resized after format, activation could fail when
the device is not multiple of a sector size. Print at least a warning
here, as the activation error message is visible only in kernel syslog.
* Fix sector size and integrity fields display for non-LUKS2 crypt
devices for the status command.
* Fix suspend for LUKS2 with authenticated encryption (also suspend
dm-integrity device underneath).
This should stop the dm-integrity device from issuing journal updates
and possibly corrupt data if the user also tries to modify the
underlying device.
Libcryptsetup API extensions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The libcryptsetup API is backward compatible for all existing symbols.
New symbols:
crypt_activate_by_keyslot_context
crypt_format_luks2_opal
crypt_get_hw_encryption_type
crypt_get_hw_encryption_key_size
crypt_keyslot_context_init_by_keyring
crypt_keyslot_context_init_by_vk_in_keyring
crypt_keyslot_context_init_by_signed_key
crypt_resume_by_keyslot_context
crypt_token_set_external_path
crypt_set_keyring_to_link
crypt_wipe_hw_opal
New defines (hw encryption status):
CRYPT_SW_ONLY
CRYPT_OPAL_HW_ONLY
CRYPT_SW_AND_OPAL_HW
New keyslot context types:
CRYPT_KC_TYPE_KEYRING
CRYPT_KC_TYPE_VK_KEYRING
CRYPT_KC_TYPE_SIGNED_KEY
New requirement flag:
CRYPT_REQUIREMENT_OPAL

View File

@@ -33,7 +33,6 @@ libcryptsetup_la_LIBADD = \
@JSON_C_LIBS@ \
@BLKID_LIBS@ \
@DL_LIBS@ \
$(LTLIBICONV) \
$(LTLIBINTL) \
libcrypto_backend.la \
libutils_io.la
@@ -54,8 +53,6 @@ libcryptsetup_la_SOURCES = \
lib/utils_loop.h \
lib/utils_devpath.c \
lib/utils_wipe.c \
lib/utils_fips.c \
lib/utils_fips.h \
lib/utils_device.c \
lib/utils_keyring.c \
lib/utils_keyring.h \
@@ -70,14 +67,14 @@ libcryptsetup_la_SOURCES = \
lib/volumekey.c \
lib/random.c \
lib/crypt_plain.c \
lib/base64.h \
lib/base64.c \
lib/integrity/integrity.h \
lib/integrity/integrity.c \
lib/loopaes/loopaes.h \
lib/loopaes/loopaes.c \
lib/tcrypt/tcrypt.h \
lib/tcrypt/tcrypt.c \
lib/keyslot_context.h \
lib/keyslot_context.c \
lib/luks1/af.h \
lib/luks1/af.c \
lib/luks1/keyencryption.c \
@@ -100,12 +97,17 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
lib/luks2/luks2_reencrypt_digest.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \
lib/luks2/luks2_internal.h \
lib/luks2/luks2.h \
lib/luks2/hw_opal/hw_opal.c \
lib/luks2/hw_opal/hw_opal.h \
lib/utils_blkid.c \
lib/utils_blkid.h \
lib/bitlk/bitlk.h \
lib/bitlk/bitlk.c
lib/bitlk/bitlk.c \
lib/fvault2/fvault2.h \
lib/fvault2/fvault2.c

View File

@@ -1,605 +0,0 @@
/* base64.c -- Encode binary data using printable characters.
Copyright (C) 1999-2001, 2004-2006, 2009-2019 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <https://www.gnu.org/licenses/>. */
/* Written by Simon Josefsson. Partially adapted from GNU MailUtils
* (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
* from Paul Eggert, Bruno Haible, and Stepan Kasal.
*
* See also RFC 4648 <https://www.ietf.org/rfc/rfc4648.txt>.
*
* Be careful with error checking. Here is how you would typically
* use these functions:
*
* bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
* if (!ok)
* FAIL: input was not valid base64
* if (out == NULL)
* FAIL: memory allocation error
* OK: data in OUT/OUTLEN
*
* size_t outlen = base64_encode_alloc (in, inlen, &out);
* if (out == NULL && outlen == 0 && inlen != 0)
* FAIL: input too long
* if (out == NULL)
* FAIL: memory allocation error
* OK: data in OUT/OUTLEN.
*
*/
#include <config.h>
/* Get prototype. */
#include "base64.h"
/* Get malloc. */
#include <stdlib.h>
/* Get UCHAR_MAX. */
#include <limits.h>
#include <string.h>
/* C89 compliant way to cast 'char' to 'unsigned char'. */
static unsigned char
to_uchar (char ch)
{
return ch;
}
static const char b64c[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* Base64 encode IN array of size INLEN into OUT array. OUT needs
to be of length >= BASE64_LENGTH(INLEN), and INLEN needs to be
a multiple of 3. */
static void
base64_encode_fast (const char *restrict in, size_t inlen, char *restrict out)
{
while (inlen)
{
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
*out++ = b64c[((to_uchar (in[0]) << 4) + (to_uchar (in[1]) >> 4)) & 0x3f];
*out++ = b64c[((to_uchar (in[1]) << 2) + (to_uchar (in[2]) >> 6)) & 0x3f];
*out++ = b64c[to_uchar (in[2]) & 0x3f];
inlen -= 3;
in += 3;
}
}
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
terminate the output buffer. */
void
base64_encode (const char *restrict in, size_t inlen,
char *restrict out, size_t outlen)
{
/* Note this outlen constraint can be enforced at compile time.
I.E. that the output buffer is exactly large enough to hold
the encoded inlen bytes. The inlen constraints (of corresponding
to outlen, and being a multiple of 3) can change at runtime
at the end of input. However the common case when reading
large inputs is to have both constraints satisfied, so we depend
on both in base_encode_fast(). */
if (outlen % 4 == 0 && inlen == outlen / 4 * 3)
{
base64_encode_fast (in, inlen, out);
return;
}
while (inlen && outlen)
{
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
if (!--outlen)
break;
*out++ = b64c[((to_uchar (in[0]) << 4)
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
& 0x3f];
if (!--outlen)
break;
*out++ =
(inlen
? b64c[((to_uchar (in[1]) << 2)
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
& 0x3f]
: '=');
if (!--outlen)
break;
*out++ = inlen ? b64c[to_uchar (in[2]) & 0x3f] : '=';
if (!--outlen)
break;
if (inlen)
inlen--;
if (inlen)
in += 3;
}
if (outlen)
*out = '\0';
}
/* Allocate a buffer and store zero terminated base64 encoded data
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
the length of the encoded data, excluding the terminating zero. On
return, the OUT variable will hold a pointer to newly allocated
memory that must be deallocated by the caller. If output string
length would overflow, 0 is returned and OUT is set to NULL. If
memory allocation failed, OUT is set to NULL, and the return value
indicates length of the requested memory block, i.e.,
BASE64_LENGTH(inlen) + 1. */
size_t
base64_encode_alloc (const char *in, size_t inlen, char **out)
{
size_t outlen = 1 + BASE64_LENGTH (inlen);
/* Check for overflow in outlen computation.
*
* If there is no overflow, outlen >= inlen.
*
* If the operation (inlen + 2) overflows then it yields at most +1, so
* outlen is 0.
*
* If the multiplication overflows, we lose at least half of the
* correct value, so the result is < ((inlen + 2) / 3) * 2, which is
* less than (inlen + 2) * 0.66667, which is less than inlen as soon as
* (inlen > 4).
*/
if (inlen > outlen)
{
*out = NULL;
return 0;
}
*out = malloc (outlen);
if (!*out)
return outlen;
base64_encode (in, inlen, *out, outlen);
return outlen - 1;
}
/* With this approach this file works independent of the charset used
(think EBCDIC). However, it does assume that the characters in the
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
1003.1-2001 require that char and unsigned char are 8-bit
quantities, though, taking care of that problem. But this may be a
potential problem on non-POSIX C99 platforms.
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
as the formal parameter rather than "x". */
#define B64(_) \
((_) == 'A' ? 0 \
: (_) == 'B' ? 1 \
: (_) == 'C' ? 2 \
: (_) == 'D' ? 3 \
: (_) == 'E' ? 4 \
: (_) == 'F' ? 5 \
: (_) == 'G' ? 6 \
: (_) == 'H' ? 7 \
: (_) == 'I' ? 8 \
: (_) == 'J' ? 9 \
: (_) == 'K' ? 10 \
: (_) == 'L' ? 11 \
: (_) == 'M' ? 12 \
: (_) == 'N' ? 13 \
: (_) == 'O' ? 14 \
: (_) == 'P' ? 15 \
: (_) == 'Q' ? 16 \
: (_) == 'R' ? 17 \
: (_) == 'S' ? 18 \
: (_) == 'T' ? 19 \
: (_) == 'U' ? 20 \
: (_) == 'V' ? 21 \
: (_) == 'W' ? 22 \
: (_) == 'X' ? 23 \
: (_) == 'Y' ? 24 \
: (_) == 'Z' ? 25 \
: (_) == 'a' ? 26 \
: (_) == 'b' ? 27 \
: (_) == 'c' ? 28 \
: (_) == 'd' ? 29 \
: (_) == 'e' ? 30 \
: (_) == 'f' ? 31 \
: (_) == 'g' ? 32 \
: (_) == 'h' ? 33 \
: (_) == 'i' ? 34 \
: (_) == 'j' ? 35 \
: (_) == 'k' ? 36 \
: (_) == 'l' ? 37 \
: (_) == 'm' ? 38 \
: (_) == 'n' ? 39 \
: (_) == 'o' ? 40 \
: (_) == 'p' ? 41 \
: (_) == 'q' ? 42 \
: (_) == 'r' ? 43 \
: (_) == 's' ? 44 \
: (_) == 't' ? 45 \
: (_) == 'u' ? 46 \
: (_) == 'v' ? 47 \
: (_) == 'w' ? 48 \
: (_) == 'x' ? 49 \
: (_) == 'y' ? 50 \
: (_) == 'z' ? 51 \
: (_) == '0' ? 52 \
: (_) == '1' ? 53 \
: (_) == '2' ? 54 \
: (_) == '3' ? 55 \
: (_) == '4' ? 56 \
: (_) == '5' ? 57 \
: (_) == '6' ? 58 \
: (_) == '7' ? 59 \
: (_) == '8' ? 60 \
: (_) == '9' ? 61 \
: (_) == '+' ? 62 \
: (_) == '/' ? 63 \
: -1)
static const signed char b64[0x100] = {
B64 (0), B64 (1), B64 (2), B64 (3),
B64 (4), B64 (5), B64 (6), B64 (7),
B64 (8), B64 (9), B64 (10), B64 (11),
B64 (12), B64 (13), B64 (14), B64 (15),
B64 (16), B64 (17), B64 (18), B64 (19),
B64 (20), B64 (21), B64 (22), B64 (23),
B64 (24), B64 (25), B64 (26), B64 (27),
B64 (28), B64 (29), B64 (30), B64 (31),
B64 (32), B64 (33), B64 (34), B64 (35),
B64 (36), B64 (37), B64 (38), B64 (39),
B64 (40), B64 (41), B64 (42), B64 (43),
B64 (44), B64 (45), B64 (46), B64 (47),
B64 (48), B64 (49), B64 (50), B64 (51),
B64 (52), B64 (53), B64 (54), B64 (55),
B64 (56), B64 (57), B64 (58), B64 (59),
B64 (60), B64 (61), B64 (62), B64 (63),
B64 (64), B64 (65), B64 (66), B64 (67),
B64 (68), B64 (69), B64 (70), B64 (71),
B64 (72), B64 (73), B64 (74), B64 (75),
B64 (76), B64 (77), B64 (78), B64 (79),
B64 (80), B64 (81), B64 (82), B64 (83),
B64 (84), B64 (85), B64 (86), B64 (87),
B64 (88), B64 (89), B64 (90), B64 (91),
B64 (92), B64 (93), B64 (94), B64 (95),
B64 (96), B64 (97), B64 (98), B64 (99),
B64 (100), B64 (101), B64 (102), B64 (103),
B64 (104), B64 (105), B64 (106), B64 (107),
B64 (108), B64 (109), B64 (110), B64 (111),
B64 (112), B64 (113), B64 (114), B64 (115),
B64 (116), B64 (117), B64 (118), B64 (119),
B64 (120), B64 (121), B64 (122), B64 (123),
B64 (124), B64 (125), B64 (126), B64 (127),
B64 (128), B64 (129), B64 (130), B64 (131),
B64 (132), B64 (133), B64 (134), B64 (135),
B64 (136), B64 (137), B64 (138), B64 (139),
B64 (140), B64 (141), B64 (142), B64 (143),
B64 (144), B64 (145), B64 (146), B64 (147),
B64 (148), B64 (149), B64 (150), B64 (151),
B64 (152), B64 (153), B64 (154), B64 (155),
B64 (156), B64 (157), B64 (158), B64 (159),
B64 (160), B64 (161), B64 (162), B64 (163),
B64 (164), B64 (165), B64 (166), B64 (167),
B64 (168), B64 (169), B64 (170), B64 (171),
B64 (172), B64 (173), B64 (174), B64 (175),
B64 (176), B64 (177), B64 (178), B64 (179),
B64 (180), B64 (181), B64 (182), B64 (183),
B64 (184), B64 (185), B64 (186), B64 (187),
B64 (188), B64 (189), B64 (190), B64 (191),
B64 (192), B64 (193), B64 (194), B64 (195),
B64 (196), B64 (197), B64 (198), B64 (199),
B64 (200), B64 (201), B64 (202), B64 (203),
B64 (204), B64 (205), B64 (206), B64 (207),
B64 (208), B64 (209), B64 (210), B64 (211),
B64 (212), B64 (213), B64 (214), B64 (215),
B64 (216), B64 (217), B64 (218), B64 (219),
B64 (220), B64 (221), B64 (222), B64 (223),
B64 (224), B64 (225), B64 (226), B64 (227),
B64 (228), B64 (229), B64 (230), B64 (231),
B64 (232), B64 (233), B64 (234), B64 (235),
B64 (236), B64 (237), B64 (238), B64 (239),
B64 (240), B64 (241), B64 (242), B64 (243),
B64 (244), B64 (245), B64 (246), B64 (247),
B64 (248), B64 (249), B64 (250), B64 (251),
B64 (252), B64 (253), B64 (254), B64 (255)
};
#if UCHAR_MAX == 255
# define uchar_in_range(c) true
#else
# define uchar_in_range(c) ((c) <= 255)
#endif
/* Return true if CH is a character from the Base64 alphabet, and
false otherwise. Note that '=' is padding and not considered to be
part of the alphabet. */
bool
isbase64 (char ch)
{
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
}
/* Initialize decode-context buffer, CTX. */
void
base64_decode_ctx_init (struct base64_decode_context *ctx)
{
ctx->i = 0;
}
/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
none of those four is a newline, then return *IN. Otherwise, copy up to
4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
index CTX->i and setting CTX->i to reflect the number of bytes copied,
and return CTX->buf. In either case, advance *IN to point to the byte
after the last one processed, and set *N_NON_NEWLINE to the number of
verified non-newline bytes accessible through the returned pointer. */
static const char *
get_4 (struct base64_decode_context *ctx,
char const *restrict *in, char const *restrict in_end,
size_t *n_non_newline)
{
if (ctx->i == 4)
ctx->i = 0;
if (ctx->i == 0)
{
char const *t = *in;
if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
{
/* This is the common case: no newline. */
*in += 4;
*n_non_newline = 4;
return (const char *) t;
}
}
{
/* Copy non-newline bytes into BUF. */
char const *p = *in;
while (p < in_end)
{
char c = *p++;
if (c != '\n')
{
ctx->buf[ctx->i++] = c;
if (ctx->i == 4)
break;
}
}
*in = p;
*n_non_newline = ctx->i;
return ctx->buf;
}
}
#define return_false \
do \
{ \
*outp = out; \
return false; \
} \
while (false)
/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
decoding is successful, false otherwise. If *OUTLEN is too small,
as many bytes as possible are written to *OUT. On return, advance
*OUT to point to the byte after the last one written, and decrement
*OUTLEN to reflect the number of bytes remaining in *OUT. */
static bool
decode_4 (char const *restrict in, size_t inlen,
char *restrict *outp, size_t *outleft)
{
char *out = *outp;
if (inlen < 2)
return false;
if (!isbase64 (in[0]) || !isbase64 (in[1]))
return false;
if (*outleft)
{
*out++ = ((b64[to_uchar (in[0])] << 2)
| (b64[to_uchar (in[1])] >> 4));
--*outleft;
}
if (inlen == 2)
return_false;
if (in[2] == '=')
{
if (inlen != 4)
return_false;
if (in[3] != '=')
return_false;
}
else
{
if (!isbase64 (in[2]))
return_false;
if (*outleft)
{
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
| (b64[to_uchar (in[2])] >> 2));
--*outleft;
}
if (inlen == 3)
return_false;
if (in[3] == '=')
{
if (inlen != 4)
return_false;
}
else
{
if (!isbase64 (in[3]))
return_false;
if (*outleft)
{
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
| b64[to_uchar (in[3])]);
--*outleft;
}
}
}
*outp = out;
return true;
}
/* Decode base64-encoded input array IN of length INLEN to output array
OUT that can hold *OUTLEN bytes. The input data may be interspersed
with newlines. Return true if decoding was successful, i.e. if the
input was valid base64 data, false otherwise. If *OUTLEN is too
small, as many bytes as possible will be written to OUT. On return,
*OUTLEN holds the length of decoded bytes in OUT. Note that as soon
as any non-alphabet, non-newline character is encountered, decoding
is stopped and false is returned. If INLEN is zero, then process
only whatever data is stored in CTX.
Initially, CTX must have been initialized via base64_decode_ctx_init.
Subsequent calls to this function must reuse whatever state is recorded
in that buffer. It is necessary for when a quadruple of base64 input
bytes spans two input buffers.
If CTX is NULL then newlines are treated as garbage and the input
buffer is processed as a unit. */
bool
base64_decode_ctx (struct base64_decode_context *ctx,
const char *restrict in, size_t inlen,
char *restrict out, size_t *outlen)
{
size_t outleft = *outlen;
bool ignore_newlines = ctx != NULL;
bool flush_ctx = false;
unsigned int ctx_i = 0;
if (ignore_newlines)
{
ctx_i = ctx->i;
flush_ctx = inlen == 0;
}
while (true)
{
size_t outleft_save = outleft;
if (ctx_i == 0 && !flush_ctx)
{
while (true)
{
/* Save a copy of outleft, in case we need to re-parse this
block of four bytes. */
outleft_save = outleft;
if (!decode_4 (in, inlen, &out, &outleft))
break;
in += 4;
inlen -= 4;
}
}
if (inlen == 0 && !flush_ctx)
break;
/* Handle the common case of 72-byte wrapped lines.
This also handles any other multiple-of-4-byte wrapping. */
if (inlen && *in == '\n' && ignore_newlines)
{
++in;
--inlen;
continue;
}
/* Restore OUT and OUTLEFT. */
out -= outleft_save - outleft;
outleft = outleft_save;
{
char const *in_end = in + inlen;
char const *non_nl;
if (ignore_newlines)
non_nl = get_4 (ctx, &in, in_end, &inlen);
else
non_nl = in; /* Might have nl in this case. */
/* If the input is empty or consists solely of newlines (0 non-newlines),
then we're done. Likewise if there are fewer than 4 bytes when not
flushing context and not treating newlines as garbage. */
if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
{
inlen = 0;
break;
}
if (!decode_4 (non_nl, inlen, &out, &outleft))
break;
inlen = in_end - in;
}
}
*outlen -= outleft;
return inlen == 0;
}
/* Allocate an output buffer in *OUT, and decode the base64 encoded
data stored in IN of size INLEN to the *OUT buffer. On return, the
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
if the caller is not interested in the decoded length. *OUT may be
NULL to indicate an out of memory error, in which case *OUTLEN
contains the size of the memory block needed. The function returns
true on successful decoding and memory allocation errors. (Use the
*OUT and *OUTLEN parameters to differentiate between successful
decoding and memory error.) The function returns false if the
input was invalid, in which case *OUT is NULL and *OUTLEN is
undefined. */
bool
base64_decode_alloc_ctx (struct base64_decode_context *ctx,
const char *in, size_t inlen, char **out,
size_t *outlen)
{
/* This may allocate a few bytes too many, depending on input,
but it's not worth the extra CPU time to compute the exact size.
The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
input ends with "=" and minus another 1 if the input ends with "==".
Dividing before multiplying avoids the possibility of overflow. */
size_t needlen = 3 * (inlen / 4) + 3;
*out = malloc (needlen);
if (!*out)
return true;
if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
{
free (*out);
*out = NULL;
return false;
}
if (outlen)
*outlen = needlen;
return true;
}

View File

@@ -1,68 +0,0 @@
/* base64.h -- Encode binary data using printable characters.
Copyright (C) 2004-2006, 2009-2019 Free Software Foundation, Inc.
Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <https://www.gnu.org/licenses/>. */
#ifndef BASE64_H
# define BASE64_H
/* Get size_t. */
# include <stddef.h>
/* Get bool. */
# include <stdbool.h>
# ifdef __cplusplus
extern "C" {
# endif
/* This uses that the expression (n+(k-1))/k means the smallest
integer >= n/k, i.e., the ceiling of n/k. */
# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
struct base64_decode_context
{
unsigned int i;
char buf[4];
};
extern bool isbase64 (char ch) __attribute__ ((__const__));
extern void base64_encode (const char *restrict in, size_t inlen,
char *restrict out, size_t outlen);
extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
extern bool base64_decode_ctx (struct base64_decode_context *ctx,
const char *restrict in, size_t inlen,
char *restrict out, size_t *outlen);
extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
const char *in, size_t inlen,
char **out, size_t *outlen);
#define base64_decode(in, inlen, out, outlen) \
base64_decode_ctx (NULL, in, inlen, out, outlen)
#define base64_decode_alloc(in, inlen, out, outlen) \
base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
# ifdef __cplusplus
}
# endif
#endif /* BASE64_H */

View File

@@ -1,9 +1,9 @@
/*
* BITLK (BitLocker-compatible) volume handling
*
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2021 Milan Broz
* Copyright (C) 2019-2021 Vojtech Trefny
* Copyright (C) 2019-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2023 Milan Broz
* Copyright (C) 2019-2023 Vojtech Trefny
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,7 +24,6 @@
#include <string.h>
#include <uuid/uuid.h>
#include <time.h>
#include <iconv.h>
#include <limits.h>
#include "bitlk.h"
@@ -234,86 +233,11 @@ static const char* get_bitlk_type_string(BITLKEncryptionType type)
}
}
/* TODO -- move to some utils file */
static void hexprint(struct crypt_device *cd, const char *d, int n, const char *sep)
{
int i;
for(i = 0; i < n; i++)
log_std(cd, "%02hhx%s", (const char)d[i], sep);
}
static uint64_t filetime_to_unixtime(uint64_t time)
{
return (time - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS;
}
static int convert_to_utf8(struct crypt_device *cd, uint8_t *input, size_t inlen, char **out)
{
char *outbuf = NULL;
iconv_t ic;
size_t ic_inlen = inlen;
size_t ic_outlen = inlen;
char *ic_outbuf = NULL;
size_t r = 0;
outbuf = malloc(inlen);
if (outbuf == NULL)
return -ENOMEM;
memset(outbuf, 0, inlen);
ic_outbuf = outbuf;
ic = iconv_open("UTF-8", "UTF-16LE");
r = iconv(ic, (char **) &input, &ic_inlen, &ic_outbuf, &ic_outlen);
iconv_close(ic);
if (r == 0)
*out = strdup(outbuf);
else {
*out = NULL;
log_dbg(cd, "Failed to convert volume description: %s", strerror(errno));
r = 0;
}
free(outbuf);
return r;
}
static int passphrase_to_utf16(struct crypt_device *cd, char *input, size_t inlen, char **out)
{
char *outbuf = NULL;
iconv_t ic;
size_t ic_inlen = inlen;
size_t ic_outlen = inlen * 2;
char *ic_outbuf = NULL;
size_t r = 0;
if (inlen == 0)
return r;
outbuf = crypt_safe_alloc(inlen * 2);
if (outbuf == NULL)
return -ENOMEM;
memset(outbuf, 0, inlen * 2);
ic_outbuf = outbuf;
ic = iconv_open("UTF-16LE", "UTF-8");
r = iconv(ic, &input, &ic_inlen, &ic_outbuf, &ic_outlen);
iconv_close(ic);
if (r == 0) {
*out = outbuf;
} else {
*out = NULL;
crypt_safe_free(outbuf);
log_dbg(cd, "Failed to convert passphrase: %s", strerror(errno));
r = -errno;
}
return r;
}
static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, int end, struct bitlk_vmk **vmk)
{
uint16_t key_entry_size = 0;
@@ -324,19 +248,23 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
const char *key = NULL;
struct volume_key *vk = NULL;
bool supported = false;
int r = 0;
/* only passphrase or recovery passphrase vmks are supported (can be used to activate) */
supported = (*vmk)->protection == BITLK_PROTECTION_PASSPHRASE ||
(*vmk)->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE ||
(*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY;
while (end - start > 2) {
while ((end - start) >= (ssize_t)(sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value))) {
/* size of this entry */
memcpy(&key_entry_size, data + start, sizeof(key_entry_size));
key_entry_size = le16_to_cpu(key_entry_size);
if (key_entry_size == 0)
break;
if (key_entry_size > (end - start))
return -EINVAL;
/* type and value of this entry */
memcpy(&key_entry_type, data + start + sizeof(key_entry_size), sizeof(key_entry_type));
memcpy(&key_entry_value,
@@ -355,20 +283,24 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
}
/* stretch key with salt, skip 4 B (encryption method of the stretch key) */
if (key_entry_value == BITLK_ENTRY_VALUE_STRETCH_KEY)
if (key_entry_value == BITLK_ENTRY_VALUE_STRETCH_KEY) {
if ((end - start) < (BITLK_ENTRY_HEADER_LEN + BITLK_SALT_SIZE + 4))
return -EINVAL;
memcpy((*vmk)->salt,
data + start + BITLK_ENTRY_HEADER_LEN + 4,
sizeof((*vmk)->salt));
BITLK_SALT_SIZE);
/* AES-CCM encrypted key */
else if (key_entry_value == BITLK_ENTRY_VALUE_ENCRYPTED_KEY) {
} else if (key_entry_value == BITLK_ENTRY_VALUE_ENCRYPTED_KEY) {
if (key_entry_size < (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE))
return -EINVAL;
/* nonce */
memcpy((*vmk)->nonce,
data + start + BITLK_ENTRY_HEADER_LEN,
sizeof((*vmk)->nonce));
BITLK_NONCE_SIZE);
/* MAC tag */
memcpy((*vmk)->mac_tag,
data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE,
sizeof((*vmk)->mac_tag));
BITLK_VMK_MAC_TAG_SIZE);
/* AES-CCM encrypted key */
key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE);
key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE;
@@ -393,9 +325,16 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
} else if (key_entry_value == BITLK_ENTRY_VALUE_RECOVERY_TIME) {
;
} else if (key_entry_value == BITLK_ENTRY_VALUE_STRING) {
if (convert_to_utf8(cd, data + start + BITLK_ENTRY_HEADER_LEN, key_entry_size - BITLK_ENTRY_HEADER_LEN, &string) < 0) {
log_err(cd, _("Invalid string found when parsing Volume Master Key."));
if (key_entry_size < BITLK_ENTRY_HEADER_LEN)
return -EINVAL;
string = malloc((key_entry_size - BITLK_ENTRY_HEADER_LEN) * 2 + 1);
if (!string)
return -ENOMEM;
r = crypt_utf16_to_utf8(&string, CONST_CAST(char16_t *)(data + start + BITLK_ENTRY_HEADER_LEN),
key_entry_size - BITLK_ENTRY_HEADER_LEN);
if (r < 0 || !string) {
free(string);
log_err(cd, _("Invalid string found when parsing Volume Master Key."));
return -EINVAL;
} else if ((*vmk)->name != NULL) {
if (supported) {
@@ -475,6 +414,7 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
struct bitlk_fve_metadata fve = {};
struct bitlk_entry_vmk entry_vmk = {};
uint8_t *fve_entries = NULL;
size_t fve_entries_size = 0;
uint32_t fve_metadata_size = 0;
int fve_offset = 0;
char guid_buf[UUID_STR_LEN] = {0};
@@ -483,9 +423,9 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
int i = 0;
int r = 0;
int start = 0;
int end = 0;
size_t key_size = 0;
const char *key = NULL;
char *description = NULL;
struct bitlk_vmk *vmk = NULL;
struct bitlk_vmk *vmk_p = params->vmks;
@@ -499,8 +439,8 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
/* read and check the signature */
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), &sig, sizeof(sig), 0) != sizeof(sig)) {
log_err(cd, _("Failed to read BITLK signature from %s."), device_path(device));
r = -EINVAL;
log_dbg(cd, "Failed to read BITLK signature from %s.", device_path(device));
r = -EIO;
goto out;
}
@@ -511,7 +451,7 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
params->togo = true;
fve_offset = BITLK_HEADER_METADATA_OFFSET_TOGO;
} else {
log_err(cd, _("Invalid or unknown signature for BITLK device."));
log_dbg(cd, "Invalid or unknown signature for BITLK device.");
r = -EINVAL;
goto out;
}
@@ -581,8 +521,8 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
le16_to_cpu(fve.curr_state), le16_to_cpu(fve.next_state));
}
params->volume_size = le64_to_cpu(fve.volume_size);
params->metadata_version = le16_to_cpu(fve.fve_version);
fve_metadata_size = le32_to_cpu(fve.metadata_size);
switch (le16_to_cpu(fve.encryption)) {
/* AES-CBC with Elephant difuser */
@@ -637,40 +577,56 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
params->creation_time = filetime_to_unixtime(le64_to_cpu(fve.creation_time));
fve_metadata_size = le32_to_cpu(fve.metadata_size);
if (fve_metadata_size < (BITLK_FVE_METADATA_HEADER_LEN + sizeof(entry_size) + sizeof(entry_type)) ||
fve_metadata_size > BITLK_FVE_METADATA_SIZE) {
r = -EINVAL;
goto out;
}
fve_entries_size = fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN;
/* read and parse all FVE metadata entries */
fve_entries = malloc(fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN);
fve_entries = malloc(fve_entries_size);
if (!fve_entries) {
r = -ENOMEM;
goto out;
}
memset(fve_entries, 0, (fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN));
memset(fve_entries, 0, fve_entries_size);
log_dbg(cd, "Reading BITLK FVE metadata entries of size %" PRIu32 " on device %s, offset %" PRIu64 ".",
fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN, device_path(device),
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN);
log_dbg(cd, "Reading BITLK FVE metadata entries of size %zu on device %s, offset %" PRIu64 ".",
fve_entries_size, device_path(device), params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN);
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), fve_entries, fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN,
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN) != (ssize_t)(fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN)) {
device_alignment(device), fve_entries, fve_entries_size,
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN) != (ssize_t)fve_entries_size) {
log_err(cd, _("Failed to read BITLK metadata entries from %s."), device_path(device));
r = -EINVAL;
goto out;
}
end = fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN;
while (end - start > 2) {
while ((fve_entries_size - start) >= (sizeof(entry_size) + sizeof(entry_type))) {
/* size of this entry */
memcpy(&entry_size, fve_entries + start, sizeof(entry_size));
entry_size = le16_to_cpu(entry_size);
if (entry_size == 0)
break;
if (entry_size > (fve_entries_size - start)) {
r = -EINVAL;
goto out;
}
/* type of this entry */
memcpy(&entry_type, fve_entries + start + sizeof(entry_size), sizeof(entry_type));
entry_type = le16_to_cpu(entry_type);
/* VMK */
if (entry_type == BITLK_ENTRY_TYPE_VMK) {
if (entry_size < (BITLK_ENTRY_HEADER_LEN + sizeof(entry_vmk))) {
r = -EINVAL;
goto out;
}
/* skip first four variables in the entry (entry size, type, value and version) */
memcpy(&entry_vmk,
fve_entries + start + BITLK_ENTRY_HEADER_LEN,
@@ -707,7 +663,11 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
vmk_p = vmk;
vmk = vmk->next;
/* FVEK */
} else if (entry_type == BITLK_ENTRY_TYPE_FVEK) {
} else if (entry_type == BITLK_ENTRY_TYPE_FVEK && !params->fvek) {
if (entry_size < (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE)) {
r = -EINVAL;
goto out;
}
params->fvek = malloc(sizeof(struct bitlk_fvek));
if (!params->fvek) {
r = -ENOMEM;
@@ -715,11 +675,11 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
}
memcpy(params->fvek->nonce,
fve_entries + start + BITLK_ENTRY_HEADER_LEN,
sizeof(params->fvek->nonce));
BITLK_NONCE_SIZE);
/* MAC tag */
memcpy(params->fvek->mac_tag,
fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE,
sizeof(params->fvek->mac_tag));
BITLK_VMK_MAC_TAG_SIZE);
/* AES-CCM encrypted key */
key_size = entry_size - (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE);
key = (const char *) fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE;
@@ -731,20 +691,35 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
/* volume header info (location and size) */
} else if (entry_type == BITLK_ENTRY_TYPE_VOLUME_HEADER) {
struct bitlk_entry_header_block entry_header;
if ((fve_entries_size - start) < (BITLK_ENTRY_HEADER_LEN + sizeof(entry_header))) {
r = -EINVAL;
goto out;
}
memcpy(&entry_header,
fve_entries + start + BITLK_ENTRY_HEADER_LEN,
sizeof(entry_header));
params->volume_header_offset = le64_to_cpu(entry_header.offset);
params->volume_header_size = le64_to_cpu(entry_header.size);
/* volume description (utf-16 string) */
} else if (entry_type == BITLK_ENTRY_TYPE_DESCRIPTION) {
r = convert_to_utf8(cd, fve_entries + start + BITLK_ENTRY_HEADER_LEN,
entry_size - BITLK_ENTRY_HEADER_LEN,
&(params->description));
if (r < 0) {
BITLK_bitlk_vmk_free(vmk);
} else if (entry_type == BITLK_ENTRY_TYPE_DESCRIPTION && !params->description) {
if (entry_size < BITLK_ENTRY_HEADER_LEN) {
r = -EINVAL;
goto out;
}
description = malloc((entry_size - BITLK_ENTRY_HEADER_LEN) * 2 + 1);
if (!description) {
r = -ENOMEM;
goto out;
}
r = crypt_utf16_to_utf8(&description, CONST_CAST(char16_t *)(fve_entries + start + BITLK_ENTRY_HEADER_LEN),
entry_size - BITLK_ENTRY_HEADER_LEN);
if (r < 0) {
free(description);
BITLK_bitlk_vmk_free(vmk);
log_err(cd, _("Failed to convert BITLK volume description"));
goto out;
}
params->description = description;
}
start += entry_size;
@@ -760,6 +735,7 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
{
struct volume_key *vk_p;
struct bitlk_vmk *vmk_p;
char time[32];
int next_id = 0;
int i = 0;
@@ -767,7 +743,9 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
log_std(cd, "Version: \t%u\n", params->metadata_version);
log_std(cd, "GUID: \t%s\n", params->guid);
log_std(cd, "Sector size: \t%u [bytes]\n", params->sector_size);
log_std(cd, "Created: \t%s", ctime((time_t *)&(params->creation_time)));
log_std(cd, "Volume size: \t%" PRIu64 " [bytes]\n", params->volume_size);
if (ctime_r((time_t *)&params->creation_time, time))
log_std(cd, "Created: \t%s", time);
log_std(cd, "Description: \t%s\n", params->description);
log_std(cd, "Cipher name: \t%s\n", params->cipher);
log_std(cd, "Cipher mode: \t%s\n", params->cipher_mode);
@@ -785,7 +763,7 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
log_std(cd, "\tGUID: \t%s\n", vmk_p->guid);
log_std(cd, "\tProtection: \t%s\n", get_vmk_protection_string (vmk_p->protection));
log_std(cd, "\tSalt: \t");
hexprint(cd, (const char *) vmk_p->salt, 16, "");
crypt_log_hex(cd, (const char *) vmk_p->salt, 16, "", 0, NULL);
log_std(cd, "\n");
vk_p = vmk_p->vk;
@@ -835,13 +813,13 @@ static int get_recovery_key(struct crypt_device *cd,
- each part is a number dividable by 11
*/
if (passwordLen != BITLK_RECOVERY_KEY_LEN) {
if (passwordLen == BITLK_RECOVERY_KEY_LEN + 1 && password[passwordLen - 1] == '\n') {
/* looks like a recovery key with an extra newline, possibly from a key file */
passwordLen--;
log_dbg(cd, "Possible extra EOL stripped from the recovery key.");
} else
return 0;
}
if (passwordLen == BITLK_RECOVERY_KEY_LEN + 1 && password[passwordLen - 1] == '\n') {
/* looks like a recovery key with an extra newline, possibly from a key file */
passwordLen--;
log_dbg(cd, "Possible extra EOL stripped from the recovery key.");
} else
return 0;
}
for (i = BITLK_RECOVERY_PART_LEN; i < passwordLen; i += BITLK_RECOVERY_PART_LEN + 1) {
if (password[i] != '-')
@@ -869,21 +847,31 @@ static int get_recovery_key(struct crypt_device *cd,
return 0;
}
static int parse_external_key_entry(struct crypt_device *cd, const char *data, int start, int end, struct volume_key **vk)
static int parse_external_key_entry(struct crypt_device *cd,
const char *data,
int start,
int end,
struct volume_key **vk,
const struct bitlk_metadata *params)
{
uint16_t key_entry_size = 0;
uint16_t key_entry_type = 0;
uint16_t key_entry_value = 0;
size_t key_size = 0;
const char *key = NULL;
struct bitlk_guid guid;
char guid_buf[UUID_STR_LEN] = {0};
while (end - start > 2) {
while ((end - start) >= (ssize_t)(sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value))) {
/* size of this entry */
memcpy(&key_entry_size, data + start, sizeof(key_entry_size));
key_entry_size = le16_to_cpu(key_entry_size);
if (key_entry_size == 0)
break;
if (key_entry_size > (end - start))
return -EINVAL;
/* type and value of this entry */
memcpy(&key_entry_type, data + start + sizeof(key_entry_size), sizeof(key_entry_type));
memcpy(&key_entry_value,
@@ -892,13 +880,14 @@ static int parse_external_key_entry(struct crypt_device *cd, const char *data, i
key_entry_type = le16_to_cpu(key_entry_type);
key_entry_value = le16_to_cpu(key_entry_value);
/* only properties should be in this entry */
if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) {
if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY && key_entry_type != BITLK_ENTRY_TYPE_VOLUME_GUID) {
log_err(cd, _("Unexpected metadata entry type '%u' found when parsing external key."), key_entry_type);
return -EINVAL;
}
if (key_entry_value == BITLK_ENTRY_VALUE_KEY) {
if (key_entry_size < (BITLK_ENTRY_HEADER_LEN + 4))
return -EINVAL;
key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + 4);
key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + 4;
*vk = crypt_alloc_volume_key(key_size, key);
@@ -908,7 +897,17 @@ static int parse_external_key_entry(struct crypt_device *cd, const char *data, i
/* optional "ExternalKey" string, we can safely ignore it */
} else if (key_entry_value == BITLK_ENTRY_VALUE_STRING)
;
else {
/* GUID of the BitLocker device we are trying to open with this key */
else if (key_entry_value == BITLK_ENTRY_VALUE_GUID) {
if ((end - start) < (ssize_t)(BITLK_ENTRY_HEADER_LEN + sizeof(struct bitlk_guid)))
return -EINVAL;
memcpy(&guid, data + start + BITLK_ENTRY_HEADER_LEN, sizeof(struct bitlk_guid));
guid_to_string(&guid, guid_buf);
if (strcmp(guid_buf, params->guid) != 0) {
log_err(cd, _("BEK file GUID '%s' does not match GUID of the volume."), guid_buf);
return -EINVAL;
}
} else {
log_err(cd, _("Unexpected metadata entry value '%u' found when parsing external key."), key_entry_value);
return -EINVAL;
}
@@ -925,7 +924,8 @@ static int get_startup_key(struct crypt_device *cd,
const char *password,
size_t passwordLen,
const struct bitlk_vmk *vmk,
struct volume_key **su_key)
struct volume_key **su_key,
const struct bitlk_metadata *params)
{
struct bitlk_bek_header bek_header = {0};
char guid_buf[UUID_STR_LEN] = {0};
@@ -934,7 +934,7 @@ static int get_startup_key(struct crypt_device *cd,
uint16_t key_entry_type = 0;
uint16_t key_entry_value = 0;
if (passwordLen < BITLK_BEK_FILE_HEADER_LEN)
if (passwordLen < (BITLK_BEK_FILE_HEADER_LEN + sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value)))
return -EPERM;
memcpy(&bek_header, password, BITLK_BEK_FILE_HEADER_LEN);
@@ -946,13 +946,14 @@ static int get_startup_key(struct crypt_device *cd,
else
return -EPERM;
if (bek_header.metadata_version != 1) {
log_err(cd, _("Unsupported BEK metadata version %" PRIu32), bek_header.metadata_version);
if (le32_to_cpu(bek_header.metadata_version) != 1) {
log_err(cd, _("Unsupported BEK metadata version %" PRIu32), le32_to_cpu(bek_header.metadata_version));
return -ENOTSUP;
}
if (bek_header.metadata_size != passwordLen) {
log_err(cd, _("Unexpected BEK metadata size %" PRIu32 " does not match BEK file length"), bek_header.metadata_size);
if (le32_to_cpu(bek_header.metadata_size) != passwordLen) {
log_err(cd, _("Unexpected BEK metadata size %" PRIu32 " does not match BEK file length"),
le32_to_cpu(bek_header.metadata_size));
return -EINVAL;
}
@@ -975,7 +976,7 @@ static int get_startup_key(struct crypt_device *cd,
if (key_entry_type == BITLK_ENTRY_TYPE_STARTUP_KEY && key_entry_value == BITLK_ENTRY_VALUE_EXTERNAL_KEY) {
return parse_external_key_entry(cd, password,
BITLK_BEK_FILE_HEADER_LEN + BITLK_ENTRY_HEADER_LEN + BITLK_STARTUP_KEY_HEADER_LEN,
passwordLen, su_key);
passwordLen, su_key, params);
} else {
log_err(cd, _("Unexpected metadata entry found when parsing startup key."));
log_dbg(cd, "Entry type: %u, entry value: %u", key_entry_type, key_entry_value);
@@ -983,8 +984,7 @@ static int get_startup_key(struct crypt_device *cd,
}
}
static int bitlk_kdf(struct crypt_device *cd,
const char *password,
static int bitlk_kdf(const char *password,
size_t passwordLen,
bool recovery,
const uint8_t *salt,
@@ -993,7 +993,7 @@ static int bitlk_kdf(struct crypt_device *cd,
struct bitlk_kdf_data kdf = {};
struct crypt_hash *hd = NULL;
int len = 0;
char *utf16Password = NULL;
char16_t *utf16Password = NULL;
int i = 0;
int r = 0;
@@ -1010,11 +1010,16 @@ static int bitlk_kdf(struct crypt_device *cd,
if (!recovery) {
/* passphrase: convert to UTF-16 first, then sha256(sha256(pw)) */
r = passphrase_to_utf16(cd, CONST_CAST(char*)password, passwordLen, &utf16Password);
utf16Password = crypt_safe_alloc(sizeof(char16_t) * (passwordLen + 1));
if (!utf16Password) {
r = -ENOMEM;
goto out;
}
r = crypt_utf8_to_utf16(&utf16Password, CONST_CAST(char*)password, passwordLen);
if (r < 0)
goto out;
crypt_hash_write(hd, utf16Password, passwordLen * 2);
crypt_hash_write(hd, (char*)utf16Password, passwordLen * 2);
r = crypt_hash_final(hd, kdf.initial_sha256, len);
if (r < 0)
goto out;
@@ -1116,7 +1121,7 @@ int BITLK_get_volume_key(struct crypt_device *cd,
next_vmk = params->vmks;
while (next_vmk) {
if (next_vmk->protection == BITLK_PROTECTION_PASSPHRASE) {
r = bitlk_kdf(cd, password, passwordLen, false, next_vmk->salt, &vmk_dec_key);
r = bitlk_kdf(password, passwordLen, false, next_vmk->salt, &vmk_dec_key);
if (r) {
/* something wrong happened, but we still want to check other key slots */
next_vmk = next_vmk->next;
@@ -1136,13 +1141,13 @@ int BITLK_get_volume_key(struct crypt_device *cd,
continue;
}
log_dbg(cd, "Trying to use given password as a recovery key.");
r = bitlk_kdf(cd, recovery_key->key, recovery_key->keylength,
r = bitlk_kdf(recovery_key->key, recovery_key->keylength,
true, next_vmk->salt, &vmk_dec_key);
crypt_free_volume_key(recovery_key);
if (r)
return r;
} else if (next_vmk->protection == BITLK_PROTECTION_STARTUP_KEY) {
r = get_startup_key(cd, password, passwordLen, next_vmk, &vmk_dec_key);
r = get_startup_key(cd, password, passwordLen, next_vmk, &vmk_dec_key, params);
if (r) {
next_vmk = next_vmk->next;
continue;
@@ -1243,7 +1248,7 @@ static int _activate(struct crypt_device *cd,
uint64_t next_start = 0;
uint64_t next_end = 0;
uint64_t last_segment = 0;
uint32_t dmt_flags;
uint32_t dmt_flags = 0;
r = _activate_check(cd, params);
if (r)
@@ -1254,6 +1259,11 @@ static int _activate(struct crypt_device *cd,
if (r)
return r;
if (dmd.size * SECTOR_SIZE != params->volume_size)
log_std(cd, _("WARNING: BitLocker volume size %" PRIu64 " does not match the underlying device size %" PRIu64 ""),
params->volume_size,
dmd.size * SECTOR_SIZE);
/* there will be always 4 dm-zero segments: 3x metadata, 1x FS header */
for (i = 0; i < 3; i++) {
segments[num_segments].offset = params->metadata_offset[i] / SECTOR_SIZE;
@@ -1384,6 +1394,14 @@ static int _activate(struct crypt_device *cd,
log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."));
r = -ENOTSUP;
}
if ((dmd.flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED)) {
log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for large sector size."));
r = -ENOTSUP;
}
if (dm_flags(cd, DM_ZERO, &dmt_flags) < 0) {
log_err(cd, _("Cannot activate device, kernel dm-zero module is missing."));
r = -ENOTSUP;
}
}
out:
dm_targets_free(cd, &dmd);

View File

@@ -1,9 +1,9 @@
/*
* BITLK (BitLocker-compatible) header definition
*
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2021 Milan Broz
* Copyright (C) 2019-2021 Vojtech Trefny
* Copyright (C) 2019-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2023 Milan Broz
* Copyright (C) 2019-2023 Vojtech Trefny
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -61,6 +61,7 @@ typedef enum {
BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006,
BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007,
BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f,
BITLK_ENTRY_TYPE_VOLUME_GUID = 0x0019,
} BITLKFVEEntryType;
typedef enum {
@@ -76,6 +77,7 @@ typedef enum {
BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009,
BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f,
BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015,
BITLK_ENTRY_VALUE_GUID = 0x0017,
} BITLKFVEEntryValue;
struct bitlk_vmk {
@@ -97,6 +99,7 @@ struct bitlk_fvek {
struct bitlk_metadata {
uint16_t sector_size;
uint64_t volume_size;
bool togo;
bool state;
BITLKEncryptionType type;

View File

@@ -2,8 +2,8 @@
* cryptsetup plain device helper functions
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

@@ -9,6 +9,8 @@ libcrypto_backend_la_SOURCES = \
lib/crypto_backend/crypto_storage.c \
lib/crypto_backend/pbkdf_check.c \
lib/crypto_backend/crc32.c \
lib/crypto_backend/base64.c \
lib/crypto_backend/utf8.c \
lib/crypto_backend/argon2_generic.c \
lib/crypto_backend/cipher_generic.c \
lib/crypto_backend/cipher_check.c

View File

@@ -279,7 +279,6 @@ static void *fill_segment_thr(void *thread_data)
{
argon2_thread_data *my_data = thread_data;
fill_segment(my_data->instance_ptr, my_data->pos);
argon2_thread_exit();
return 0;
}

View File

@@ -0,0 +1,28 @@
libargon2_sources = files(
'blake2/blake2b.c',
'argon2.c',
'core.c',
'encoding.c',
'thread.c',
)
if use_internal_sse_argon2
libargon2_sources += files(
'opt.c',
)
else
libargon2_sources += files(
'ref.c',
)
endif
libargon2 = static_library('argon2',
libargon2_sources,
override_options : ['c_std=c89', 'optimization=3'],
build_by_default : false,
include_directories: include_directories(
'blake2',
),
dependencies : [
threads,
])

View File

@@ -46,12 +46,4 @@ int argon2_thread_join(argon2_thread_handle_t handle) {
#endif
}
void argon2_thread_exit(void) {
#if defined(_WIN32)
_endthreadex(0);
#else
pthread_exit(NULL);
#endif
}
#endif /* ARGON2_NO_THREADS */

View File

@@ -58,10 +58,5 @@ int argon2_thread_create(argon2_thread_handle_t *handle,
*/
int argon2_thread_join(argon2_thread_handle_t handle);
/* Terminate the current thread. Must be run inside a thread created by
* argon2_thread_create.
*/
void argon2_thread_exit(void);
#endif /* ARGON2_NO_THREADS */
#endif

View File

@@ -1,8 +1,8 @@
/*
* Argon2 PBKDF2 library wrapper
*
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -29,14 +29,12 @@
#define CONST_CAST(x) (x)(uintptr_t)
#if USE_INTERNAL_ARGON2 || HAVE_ARGON2_H
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
#if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H
return -EINVAL;
#else
argon2_type atype;
argon2_context context = {
.flags = ARGON2_DEFAULT_FLAGS,
@@ -54,6 +52,9 @@ int argon2(const char *type, const char *password, size_t password_length,
};
int r;
/* This code must not be run if crypt backend library natively supports Argon2 */
assert(!(crypt_backend_flags() & CRYPT_BACKEND_ARGON2));
if (!strcmp(type, "argon2i"))
atype = Argon2_i;
else if(!strcmp(type, "argon2id"))
@@ -75,5 +76,33 @@ int argon2(const char *type, const char *password, size_t password_length,
}
return r;
#endif
}
#else /* USE_INTERNAL_ARGON2 || HAVE_ARGON2_H */
#pragma GCC diagnostic ignored "-Wunused-parameter"
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
return -EINVAL;
}
#endif
/* Additional string for crypt backend version */
const char *crypt_argon2_version(void)
{
const char *version = "";
if (crypt_backend_flags() & CRYPT_BACKEND_ARGON2)
return version;
#if HAVE_ARGON2_H /* this has priority over internal argon2 */
version = " [external libargon2]";
#elif USE_INTERNAL_ARGON2
version = " [cryptsetup libargon2]";
#endif
return version;
}

276
lib/crypto_backend/base64.c Normal file
View File

@@ -0,0 +1,276 @@
/*
* Base64 "Not encryption" helpers, copied and adapted from systemd project.
*
* Copyright (C) 2010 Lennart Poettering
*
* cryptsetup related changes
* Copyright (C) 2021-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include "crypto_backend.h"
#define WHITESPACE " \t\n\r"
/* https://tools.ietf.org/html/rfc4648#section-4 */
static char base64char(int x)
{
static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
return table[x & 63];
}
static int unbase64char(char c)
{
unsigned offset;
if (c >= 'A' && c <= 'Z')
return c - 'A';
offset = 'Z' - 'A' + 1;
if (c >= 'a' && c <= 'z')
return c - 'a' + offset;
offset += 'z' - 'a' + 1;
if (c >= '0' && c <= '9')
return c - '0' + offset;
offset += '9' - '0' + 1;
if (c == '+')
return offset;
offset++;
if (c == '/')
return offset;
return -EINVAL;
}
int crypt_base64_encode(char **out, size_t *out_length, const char *in, size_t in_length)
{
char *r, *z;
const uint8_t *x;
assert(in || in_length == 0);
assert(out);
/* three input bytes makes four output bytes, padding is added so we must round up */
z = r = malloc(4 * (in_length + 2) / 3 + 1);
if (!r)
return -ENOMEM;
for (x = (const uint8_t *)in; x < (const uint8_t*)in + (in_length / 3) * 3; x += 3) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
*(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
*(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
*(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
*(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
}
switch (in_length % 3) {
case 2:
*(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
*(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
*(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
*(z++) = '=';
break;
case 1:
*(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
*(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
*(z++) = '=';
*(z++) = '=';
break;
}
*z = 0;
*out = r;
if (out_length)
*out_length = z - r;
return 0;
}
static int unbase64_next(const char **p, size_t *l)
{
int ret;
assert(p);
assert(l);
/* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
* greedily skip all preceding and all following whitespace. */
for (;;) {
if (*l == 0)
return -EPIPE;
if (!strchr(WHITESPACE, **p))
break;
/* Skip leading whitespace */
(*p)++, (*l)--;
}
if (**p == '=')
ret = INT_MAX; /* return padding as INT_MAX */
else {
ret = unbase64char(**p);
if (ret < 0)
return ret;
}
for (;;) {
(*p)++, (*l)--;
if (*l == 0)
break;
if (!strchr(WHITESPACE, **p))
break;
/* Skip following whitespace */
}
return ret;
}
int crypt_base64_decode(char **out, size_t *out_length, const char *in, size_t in_length)
{
uint8_t *buf = NULL;
const char *x;
uint8_t *z;
size_t len;
int r;
assert(in || in_length == 0);
assert(out);
assert(out_length);
if (in_length == (size_t) -1)
in_length = strlen(in);
/* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
* bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
len = (in_length / 4) * 3 + (in_length % 4 != 0 ? (in_length % 4) - 1 : 0);
buf = malloc(len + 1);
if (!buf)
return -ENOMEM;
for (x = in, z = buf;;) {
int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
a = unbase64_next(&x, &in_length);
if (a == -EPIPE) /* End of string */
break;
if (a < 0) {
r = a;
goto err;
}
if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */
r = -EINVAL;
goto err;
}
b = unbase64_next(&x, &in_length);
if (b < 0) {
r = b;
goto err;
}
if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */
r = -EINVAL;
goto err;
}
c = unbase64_next(&x, &in_length);
if (c < 0) {
r = c;
goto err;
}
d = unbase64_next(&x, &in_length);
if (d < 0) {
r = d;
goto err;
}
if (c == INT_MAX) { /* Padding at the third character */
if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */
r = -EINVAL;
goto err;
}
/* b == 00YY0000 */
if (b & 15) {
r = -EINVAL;
goto err;
}
if (in_length > 0) { /* Trailing rubbish? */
r = -ENAMETOOLONG;
goto err;
}
*(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
break;
}
if (d == INT_MAX) {
/* c == 00ZZZZ00 */
if (c & 3) {
r = -EINVAL;
goto err;
}
if (in_length > 0) { /* Trailing rubbish? */
r = -ENAMETOOLONG;
goto err;
}
*(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
*(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
break;
}
*(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
*(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
*(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
}
*z = 0;
*out_length = (size_t) (z - buf);
*out = (char *)buf;
return 0;
err:
free(buf);
/* Ignore other errors in crypt_backend */
if (r != -ENOMEM)
r = -EINVAL;
return r;
}

View File

@@ -1,8 +1,8 @@
/*
* Cipher performance check
*
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 Milan Broz
* Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel cipher generic utilities
*
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2021 Milan Broz
* Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -51,6 +51,7 @@ static const struct cipher_alg cipher_algs[] = {
{ "xchacha12,aes", "adiantum", 32, false },
{ "xchacha20,aes", "adiantum", 32, false },
{ "sm4", NULL, 16, false },
{ "aria", NULL, 16, false },
{ NULL, NULL, 0, false }
};

View File

@@ -97,18 +97,87 @@ static const uint32_t crc32_tab[] = {
0x2d02ef8dL
};
static const uint32_t crc32c_tab[] = {
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL,
0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL,
0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L,
0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L,
0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL,
0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L,
0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL,
0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L,
0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L,
0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL,
0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L,
0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L,
0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL,
0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL,
0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L,
0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL,
0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L,
0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL,
0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL,
0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL,
0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L,
0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L,
0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL,
0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL,
0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L,
0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL,
0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L,
0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L,
0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL,
0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L,
0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L,
0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L,
0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L,
0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL,
0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L,
0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L,
0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL,
0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L,
0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L,
0xAD7D5351L
};
/*
* This a generic crc32() function, it takes seed as an argument,
* and does __not__ xor at the end. Then individual users can do
* whatever they need.
*/
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
static uint32_t compute_crc32(
const uint32_t *crc32_table,
uint32_t seed,
const unsigned char *buf,
size_t len)
{
uint32_t crc = seed;
const unsigned char *p = buf;
while(len-- > 0)
crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
crc = crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return crc;
}
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
{
return compute_crc32(crc32_tab, seed, buf, len);
}
uint32_t crypt_crc32c(uint32_t seed, const unsigned char *buf, size_t len)
{
return compute_crc32(crc32c_tab, seed, buf, len);
}

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,10 +21,17 @@
#ifndef _CRYPTO_BACKEND_H
#define _CRYPTO_BACKEND_H
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#ifdef HAVE_UCHAR_H
#include <uchar.h>
#else
#define char32_t uint32_t
#define char16_t uint16_t
#endif
struct crypt_hash;
struct crypt_hmac;
@@ -34,10 +41,13 @@ struct crypt_storage;
int crypt_backend_init(bool fips);
void crypt_backend_destroy(void);
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
#define CRYPT_BACKEND_PBKDF2_INT (1 << 1) /* Iteration in PBKDF2 is signed int and can overflow */
#define CRYPT_BACKEND_ARGON2 (1 << 2) /* Backend provides native Argon2 implementation */
uint32_t crypt_backend_flags(void);
const char *crypt_backend_version(void);
const char *crypt_argon2_version(void);
/* HASH */
int crypt_hash_size(const char *name);
@@ -82,6 +92,15 @@ int crypt_pbkdf_perf(const char *kdf, const char *hash,
/* CRC32 */
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len);
uint32_t crypt_crc32c(uint32_t seed, const unsigned char *buf, size_t len);
/* Base64 */
int crypt_base64_encode(char **out, size_t *out_length, const char *in, size_t in_length);
int crypt_base64_decode(char **out, size_t *out_length, const char *in, size_t in_length);
/* UTF8/16 */
int crypt_utf16_to_utf8(char **out, const char16_t *s, size_t length /* bytes! */);
int crypt_utf8_to_utf16(char16_t **out, const char *s, size_t length);
/* Block ciphers */
int crypt_cipher_ivsize(const char *name, const char *mode);
@@ -135,4 +154,10 @@ static inline void crypt_backend_memzero(void *s, size_t n)
#endif
}
/* Memcmp helper (memcmp in constant time) */
int crypt_backend_memeq(const void *m1, const void *m2, size_t n);
/* crypto backend running in FIPS mode */
bool crypt_fips_mode(void);
#endif /* _CRYPTO_BACKEND_H */

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -58,4 +58,18 @@ int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
const char *iv, size_t iv_length,
const char *tag, size_t tag_length);
/* Internal implementation for constant time memory comparison */
static inline int crypt_internal_memeq(const void *m1, const void *m2, size_t n)
{
const unsigned char *_m1 = (const unsigned char *) m1;
const unsigned char *_m2 = (const unsigned char *) m2;
unsigned char result = 0;
size_t i;
for (i = 0; i < n; i++)
result |= _m1[i] ^ _m2[i];
return result;
}
#endif /* _CRYPTO_BACKEND_INTERNAL_H */

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation (skcipher)
*
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -109,6 +109,7 @@ int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
}
/* The in/out should be aligned to page boundary */
/* coverity[ -taint_source : arg-3 ] */
static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
const char *in, size_t in_length,
char *out, size_t out_length,
@@ -312,6 +313,8 @@ int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
}
#else /* ENABLE_AF_ALG */
#pragma GCC diagnostic ignored "-Wunused-parameter"
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
const char *mode, const void *key, size_t key_length)
{

View File

@@ -1,8 +1,8 @@
/*
* GCRYPT crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,8 +22,8 @@
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <gcrypt.h>
#include <pthread.h>
#include "crypto_backend_internal.h"
static int crypto_backend_initialised = 0;
@@ -127,10 +127,11 @@ int crypt_backend_init(bool fips __attribute__((unused)))
crypto_backend_initialised = 1;
crypt_hash_test_whirlpool_bug();
r = snprintf(version, sizeof(version), "gcrypt %s%s%s",
r = snprintf(version, sizeof(version), "gcrypt %s%s%s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled",
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "");
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "",
crypt_backend_flags() & CRYPT_BACKEND_ARGON2 ? ", argon2" : "");
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
@@ -152,7 +153,11 @@ const char *crypt_backend_version(void)
uint32_t crypt_backend_flags(void)
{
return 0;
uint32_t flags = 0;
#if HAVE_DECL_GCRY_KDF_ARGON2 && !USE_INTERNAL_ARGON2
flags |= CRYPT_BACKEND_ARGON2;
#endif
return flags;
}
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
@@ -267,7 +272,6 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
void crypt_hash_destroy(struct crypt_hash *ctx)
{
gcry_md_close(ctx->hd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -342,7 +346,6 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
void crypt_hmac_destroy(struct crypt_hmac *ctx)
{
gcry_md_close(ctx->hd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -387,6 +390,130 @@ static int pbkdf2(const char *hash,
#endif /* USE_INTERNAL_PBKDF2 */
}
#if HAVE_DECL_GCRY_KDF_ARGON2 && !USE_INTERNAL_ARGON2
struct gcrypt_thread_job
{
pthread_t thread;
struct job_thread_param {
gcry_kdf_job_fn_t job;
void *p;
} work;
};
struct gcrypt_threads
{
pthread_attr_t attr;
unsigned int num_threads;
unsigned int max_threads;
struct gcrypt_thread_job *jobs_ctx;
};
static void *gcrypt_job_thread(void *p)
{
struct job_thread_param *param = p;
param->job(param->p);
pthread_exit(NULL);
}
static int gcrypt_wait_all_jobs(void *ctx)
{
unsigned int i;
struct gcrypt_threads *threads = ctx;
for (i = 0; i < threads->num_threads; i++) {
pthread_join(threads->jobs_ctx[i].thread, NULL);
threads->jobs_ctx[i].thread = 0;
}
threads->num_threads = 0;
return 0;
}
static int gcrypt_dispatch_job(void *ctx, gcry_kdf_job_fn_t job, void *p)
{
struct gcrypt_threads *threads = ctx;
if (threads->num_threads >= threads->max_threads)
return -1;
threads->jobs_ctx[threads->num_threads].work.job = job;
threads->jobs_ctx[threads->num_threads].work.p = p;
if (pthread_create(&threads->jobs_ctx[threads->num_threads].thread, &threads->attr,
gcrypt_job_thread, &threads->jobs_ctx[threads->num_threads].work))
return -1;
threads->num_threads++;
return 0;
}
static int gcrypt_argon2(const char *type,
const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
gcry_kdf_hd_t hd;
int atype, r = -EINVAL;
unsigned long param[4];
struct gcrypt_threads threads = {
.max_threads = parallel,
.num_threads = 0
};
const gcry_kdf_thread_ops_t ops = {
.jobs_context = &threads,
.dispatch_job = gcrypt_dispatch_job,
.wait_all_jobs = gcrypt_wait_all_jobs
};
if (!strcmp(type, "argon2i"))
atype = GCRY_KDF_ARGON2I;
else if (!strcmp(type, "argon2id"))
atype = GCRY_KDF_ARGON2ID;
else
return -EINVAL;
param[0] = key_length;
param[1] = iterations;
param[2] = memory;
param[3] = parallel;
if (gcry_kdf_open(&hd, GCRY_KDF_ARGON2, atype, param, 4,
password, password_length, salt, salt_length,
NULL, 0, NULL, 0)) {
free(threads.jobs_ctx);
return -EINVAL;
}
if (parallel == 1) {
/* Do not use threads here */
if (gcry_kdf_compute(hd, NULL))
goto out;
} else {
threads.jobs_ctx = calloc(threads.max_threads,
sizeof(struct gcrypt_thread_job));
if (!threads.jobs_ctx)
goto out;
if (pthread_attr_init(&threads.attr))
goto out;
if (gcry_kdf_compute(hd, &ops))
goto out;
}
if (gcry_kdf_final(hd, key_length, key))
goto out;
r = 0;
out:
gcry_kdf_close(hd);
pthread_attr_destroy(&threads.attr);
free(threads.jobs_ctx);
return r;
}
#endif
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
@@ -401,8 +528,13 @@ int crypt_pbkdf(const char *kdf, const char *hash,
return pbkdf2(hash, password, password_length, salt, salt_length,
key, key_length, iterations);
else if (!strncmp(kdf, "argon2", 6))
#if HAVE_DECL_GCRY_KDF_ARGON2 && !USE_INTERNAL_ARGON2
return gcrypt_argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#else
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
return -EINVAL;
}
@@ -550,3 +682,28 @@ out:
return -ENOTSUP;
#endif
}
int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
{
return crypt_internal_memeq(m1, m2, n);
}
#if !ENABLE_FIPS
bool crypt_fips_mode(void) { return false; }
#else
bool crypt_fips_mode(void)
{
static bool fips_mode = false, fips_checked = false;
if (fips_checked)
return fips_mode;
if (crypt_backend_init(false /* ignored */))
return false;
fips_mode = gcry_fips_mode_active();
fips_checked = true;
return fips_mode;
}
#endif /* ENABLE FIPS */

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -245,7 +245,6 @@ void crypt_hash_destroy(struct crypt_hash *ctx)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -324,7 +323,6 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -416,3 +414,13 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
iv, iv_length, tag, tag_length);
}
int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
{
return crypt_internal_memeq(m1, m2, n);
}
bool crypt_fips_mode(void)
{
return false;
}

View File

@@ -1,8 +1,8 @@
/*
* Nettle crypto backend implementation
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 Milan Broz
* Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,6 +26,7 @@
#include <nettle/sha3.h>
#include <nettle/hmac.h>
#include <nettle/pbkdf2.h>
#include <nettle/memops.h>
#include "crypto_backend_internal.h"
#if HAVE_NETTLE_VERSION_H
@@ -446,3 +447,14 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
iv, iv_length, tag, tag_length);
}
int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
{
/* The logic is inverse to memcmp... */
return !memeql_sec(m1, m2, n);
}
bool crypt_fips_mode(void)
{
return false;
}

View File

@@ -1,8 +1,8 @@
/*
* NSS crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -395,3 +395,13 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
iv, iv_length, tag, tag_length);
}
int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
{
return NSS_SecureMemcmp(m1, m2, n);
}
bool crypt_fips_mode(void)
{
return false;
}

View File

@@ -1,8 +1,8 @@
/*
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2021 Milan Broz
* Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -30,6 +30,8 @@
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
@@ -42,9 +44,20 @@ static OSSL_PROVIDER *ossl_legacy = NULL;
static OSSL_PROVIDER *ossl_default = NULL;
static OSSL_LIB_CTX *ossl_ctx = NULL;
static char backend_version[256] = "OpenSSL";
#define MAX_THREADS 8
#if !HAVE_DECL_OSSL_GET_MAX_THREADS
static int OSSL_set_max_threads(OSSL_LIB_CTX *ctx __attribute__((unused)),
uint64_t max_threads __attribute__((unused))) { return 0; }
static uint64_t OSSL_get_max_threads(OSSL_LIB_CTX *ctx __attribute__((unused))) { return 0; }
#else
#include <openssl/thread.h>
#endif
#endif
#define CONST_CAST(x) (x)(uintptr_t)
#define UNUSED(x) (void)(x)
static int crypto_backend_initialised = 0;
@@ -160,6 +173,7 @@ static int openssl_backend_init(bool fips)
*/
#if OPENSSL_VERSION_MAJOR >= 3
int r;
bool ossl_threads = false;
/*
* In FIPS mode we keep default OpenSSL context & global config
@@ -179,16 +193,24 @@ static int openssl_backend_init(bool fips)
ossl_legacy = OSSL_PROVIDER_try_load(ossl_ctx, "legacy", 0);
}
r = snprintf(backend_version, sizeof(backend_version), "%s %s%s%s",
if (OSSL_set_max_threads(ossl_ctx, MAX_THREADS) == 1 &&
OSSL_get_max_threads(ossl_ctx) == MAX_THREADS)
ossl_threads = true;
r = snprintf(backend_version, sizeof(backend_version), "%s %s%s%s%s%s",
OpenSSL_version(OPENSSL_VERSION),
ossl_default ? "[default]" : "",
ossl_legacy ? "[legacy]" : "",
fips ? "[fips]" : "");
fips ? "[fips]" : "",
ossl_threads ? "[threads]" : "",
crypt_backend_flags() & CRYPT_BACKEND_ARGON2 ? "[argon2]" : "");
if (r < 0 || (size_t)r >= sizeof(backend_version)) {
openssl_backend_exit();
return -EINVAL;
}
#else
UNUSED(fips);
#endif
return 0;
}
@@ -230,7 +252,14 @@ void crypt_backend_destroy(void)
uint32_t crypt_backend_flags(void)
{
return 0;
uint32_t flags = 0;
#if OPENSSL_VERSION_MAJOR < 3
flags |= CRYPT_BACKEND_PBKDF2_INT;
#endif
#if HAVE_DECL_OSSL_KDF_PARAM_ARGON2_VERSION
flags |= CRYPT_BACKEND_ARGON2;
#endif
return flags;
}
const char *crypt_backend_version(void)
@@ -275,6 +304,8 @@ static void hash_id_free(const EVP_MD *hash_id)
{
#if OPENSSL_VERSION_MAJOR >= 3
EVP_MD_free(CONST_CAST(EVP_MD*)hash_id);
#else
UNUSED(hash_id);
#endif
}
@@ -291,6 +322,8 @@ static void cipher_type_free(const EVP_CIPHER *cipher_type)
{
#if OPENSSL_VERSION_MAJOR >= 3
EVP_CIPHER_free(CONST_CAST(EVP_CIPHER*)cipher_type);
#else
UNUSED(cipher_type);
#endif
}
@@ -385,7 +418,6 @@ void crypt_hash_destroy(struct crypt_hash *ctx)
{
hash_id_free(ctx->hash_id);
EVP_MD_CTX_free(ctx->md);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -521,7 +553,6 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
hash_id_free(ctx->hash_id);
HMAC_CTX_free(ctx->md);
#endif
memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -573,6 +604,10 @@ static int openssl_pbkdf2(const char *password, size_t password_length,
if (!hash_id)
return -EINVAL;
/* OpenSSL2 has iteration as signed int, avoid overflow */
if (iterations > INT_MAX)
return -EINVAL;
r = PKCS5_PBKDF2_HMAC(password, (int)password_length, (const unsigned char *)salt,
(int)salt_length, iterations, hash_id, (int)key_length, (unsigned char*) key);
#endif
@@ -583,8 +618,53 @@ static int openssl_argon2(const char *type, const char *password, size_t passwor
const char *salt, size_t salt_length, char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
#if HAVE_DECL_OSSL_KDF_PARAM_ARGON2_VERSION
EVP_KDF_CTX *ctx;
EVP_KDF *argon2;
unsigned int threads = parallel;
int r;
OSSL_PARAM params[] = {
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD,
CONST_CAST(void*)password, password_length),
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT,
CONST_CAST(void*)salt, salt_length),
OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, &iterations),
OSSL_PARAM_uint(OSSL_KDF_PARAM_THREADS, &threads),
OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &parallel),
OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memory),
OSSL_PARAM_END
};
if (OSSL_get_max_threads(ossl_ctx) == 0)
threads = 1;
argon2 = EVP_KDF_fetch(ossl_ctx, type, NULL);
if (!argon2)
return -EINVAL;
ctx = EVP_KDF_CTX_new(argon2);
if (!ctx) {
EVP_KDF_free(argon2);
return -EINVAL;;
}
if (EVP_KDF_CTX_set_params(ctx, params) != 1) {
EVP_KDF_CTX_free(ctx);
EVP_KDF_free(argon2);
return -EINVAL;
}
r = EVP_KDF_derive(ctx, (unsigned char*)key, key_length, NULL /*params*/);
EVP_KDF_CTX_free(ctx);
EVP_KDF_free(argon2);
/* _derive() returns 0 or negative value on error, 1 on success */
return r == 1 ? 0 : -EINVAL;
#else
return argon2(type, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
#endif
}
/* PBKDF */
@@ -789,9 +869,6 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_length __attribute__((un
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL) != 1)
goto out;
//EVP_CIPHER_CTX_key_length(ctx)
//EVP_CIPHER_CTX_iv_length(ctx)
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_length, NULL) != 1)
goto out;
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_length, CONST_CAST(void*)tag) != 1)
@@ -809,3 +886,34 @@ out:
return -ENOTSUP;
#endif
}
int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
{
return CRYPTO_memcmp(m1, m2, n);
}
#if !ENABLE_FIPS
bool crypt_fips_mode(void) { return false; }
#else
static bool openssl_fips_mode(void)
{
#if OPENSSL_VERSION_MAJOR >= 3
return EVP_default_properties_is_fips_enabled(NULL);
#else
return FIPS_mode();
#endif
}
bool crypt_fips_mode(void)
{
static bool fips_mode = false, fips_checked = false;
if (fips_checked)
return fips_mode;
fips_mode = openssl_fips_mode();
fips_checked = true;
return fips_mode;
}
#endif /* ENABLE FIPS */

View File

@@ -2,7 +2,7 @@
* Generic wrapper for storage encryption modes and Initial Vectors
* (reimplementation of some functions from Linux dm-crypt kernel)
*
* Copyright (C) 2014-2021 Milan Broz
* Copyright (C) 2014-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -151,7 +151,8 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
{
uint64_t val;
uint64_t val, *u64_iv;
uint32_t *u32_iv;
switch (ctx->type) {
case IV_NONE:
@@ -161,19 +162,24 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
break;
case IV_PLAIN:
memset(ctx->iv, 0, ctx->iv_size);
*(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
u32_iv = (void *)ctx->iv;
*u32_iv = cpu_to_le32(sector & 0xffffffff);
break;
case IV_PLAIN64:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
u64_iv = (void *)ctx->iv;
*u64_iv = cpu_to_le64(sector);
break;
case IV_PLAIN64BE:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(sector);
/* iv_size is at least of size u64; usually it is 16 bytes */
u64_iv = (void *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)];
*u64_iv = cpu_to_be64(sector);
break;
case IV_ESSIV:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
u64_iv = (void *)ctx->iv;
*u64_iv = cpu_to_le64(sector);
return crypt_cipher_encrypt(ctx->cipher,
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
break;
@@ -184,7 +190,8 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
break;
case IV_EBOIV:
memset(ctx->iv, 0, ctx->iv_size);
*(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
u64_iv = (void *)ctx->iv;
*u64_iv = cpu_to_le64(sector << ctx->shift);
return crypt_cipher_encrypt(ctx->cipher,
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
break;

View File

@@ -0,0 +1,40 @@
if use_internal_argon2
subdir('argon2')
endif
libcrypto_backend_dependencies = [
crypto_backend_library,
clock_gettime,
]
libcrypto_backend_link_with = []
libcrypto_backend_sources = files(
'argon2_generic.c',
'base64.c',
'cipher_check.c',
'cipher_generic.c',
'crc32.c',
'crypto_cipher_kernel.c',
'crypto_storage.c',
'pbkdf_check.c',
'utf8.c',
)
crypto_backend = get_option('crypto-backend')
libcrypto_backend_sources += files('crypto_@0@.c'.format(crypto_backend))
if use_internal_pbkdf2
libcrypto_backend_sources += files('pbkdf2_generic.c')
endif
if use_internal_argon2 and get_option('argon-implementation') == 'internal'
libcrypto_backend_link_with += libargon2
elif get_option('argon-implementation') == 'libargon2'
libcrypto_backend_dependencies += libargon2_external
endif
libcrypto_backend = static_library('crypto_backend',
libcrypto_backend_sources,
include_directories: includes_lib,
dependencies: libcrypto_backend_dependencies,
link_with: libcrypto_backend_link_with)

View File

@@ -4,8 +4,8 @@
* Copyright (C) 2004 Free Software Foundation
*
* cryptsetup related changes
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -1,7 +1,7 @@
/*
* PBKDF performance check
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2021 Milan Broz
* Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2023 Milan Broz
* Copyright (C) 2016-2020 Ondrej Mosnacek
*
* This file is free software; you can redistribute it and/or

288
lib/crypto_backend/utf8.c Normal file
View File

@@ -0,0 +1,288 @@
/*
* UTF8/16 helpers, copied and adapted from systemd project.
*
* Copyright (C) 2010 Lennart Poettering
*
* cryptsetup related changes
* Copyright (C) 2021-2023 Vojtech Trefny
* Parts of the original systemd implementation are based on the GLIB utf8
* validation functions.
* gutf8.c - Operations on UTF-8 strings.
*
* Copyright (C) 1999 Tom Tromey
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include <endian.h>
#include "crypto_backend.h"
static inline bool utf16_is_surrogate(char16_t c)
{
return c >= 0xd800U && c <= 0xdfffU;
}
static inline bool utf16_is_trailing_surrogate(char16_t c)
{
return c >= 0xdc00U && c <= 0xdfffU;
}
static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail)
{
return ((((char32_t) lead - 0xd800U) << 10) + ((char32_t) trail - 0xdc00U) + 0x10000U);
}
/**
* utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
* @out_utf8: output buffer of at least 4 bytes or NULL
* @g: UCS-4 character to encode
*
* This encodes a single UCS-4 character as UTF-8 and writes it into @out_utf8.
* The length of the character is returned. It is not zero-terminated! If the
* output buffer is NULL, only the length is returned.
*
* Returns: The length in bytes that the UTF-8 representation does or would
* occupy.
*/
static size_t utf8_encode_unichar(char *out_utf8, char32_t g)
{
if (g < (1 << 7)) {
if (out_utf8)
out_utf8[0] = g & 0x7f;
return 1;
} else if (g < (1 << 11)) {
if (out_utf8) {
out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f);
out_utf8[1] = 0x80 | (g & 0x3f);
}
return 2;
} else if (g < (1 << 16)) {
if (out_utf8) {
out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f);
out_utf8[1] = 0x80 | ((g >> 6) & 0x3f);
out_utf8[2] = 0x80 | (g & 0x3f);
}
return 3;
} else if (g < (1 << 21)) {
if (out_utf8) {
out_utf8[0] = 0xf0 | ((g >> 18) & 0x07);
out_utf8[1] = 0x80 | ((g >> 12) & 0x3f);
out_utf8[2] = 0x80 | ((g >> 6) & 0x3f);
out_utf8[3] = 0x80 | (g & 0x3f);
}
return 4;
}
return 0;
}
/**
* crypt_utf16_to_utf8()
* @out: output buffer, should be 2 * @length + 1 long
* @s: string to convert
* @length: length of @s in bytes
*
* Converts a UTF16LE encoded string to a UTF8 encoded string.
*
* Returns: 0 on success, negative errno otherwise
*/
int crypt_utf16_to_utf8(char **out, const char16_t *s, size_t length /* bytes! */)
{
const uint8_t *f;
char *t;
assert(s);
assert(out);
assert(*out);
/* Input length is in bytes, i.e. the shortest possible character takes 2 bytes. Each unicode character may
* take up to 4 bytes in UTF-8. Let's also account for a trailing NUL byte. */
if (length * 2 < length)
return -EOVERFLOW; /* overflow */
f = (const uint8_t*) s;
t = *out;
while (f + 1 < (const uint8_t*) s + length) {
char16_t w1, w2;
/* see RFC 2781 section 2.2 */
w1 = f[1] << 8 | f[0];
f += 2;
if (!utf16_is_surrogate(w1)) {
t += utf8_encode_unichar(t, w1);
continue;
}
if (utf16_is_trailing_surrogate(w1))
continue; /* spurious trailing surrogate, ignore */
if (f + 1 >= (const uint8_t*) s + length)
break;
w2 = f[1] << 8 | f[0];
f += 2;
if (!utf16_is_trailing_surrogate(w2)) {
f -= 2;
continue; /* surrogate missing its trailing surrogate, ignore */
}
t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2));
}
*t = 0;
return 0;
}
/* count of characters used to encode one unicode char */
static size_t utf8_encoded_expected_len(uint8_t c)
{
if (c < 0x80)
return 1;
if ((c & 0xe0) == 0xc0)
return 2;
if ((c & 0xf0) == 0xe0)
return 3;
if ((c & 0xf8) == 0xf0)
return 4;
if ((c & 0xfc) == 0xf8)
return 5;
if ((c & 0xfe) == 0xfc)
return 6;
return 0;
}
/* decode one unicode char */
static int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar)
{
char32_t unichar;
size_t len, i;
assert(str);
len = utf8_encoded_expected_len(str[0]);
switch (len) {
case 1:
*ret_unichar = (char32_t)str[0];
return 0;
case 2:
unichar = str[0] & 0x1f;
break;
case 3:
unichar = (char32_t)str[0] & 0x0f;
break;
case 4:
unichar = (char32_t)str[0] & 0x07;
break;
case 5:
unichar = (char32_t)str[0] & 0x03;
break;
case 6:
unichar = (char32_t)str[0] & 0x01;
break;
default:
return -EINVAL;
}
for (i = 1; i < len; i++) {
if (((char32_t)str[i] & 0xc0) != 0x80)
return -EINVAL;
unichar <<= 6;
unichar |= (char32_t)str[i] & 0x3f;
}
*ret_unichar = unichar;
return 0;
}
static size_t utf16_encode_unichar(char16_t *out, char32_t c)
{
/* Note that this encodes as little-endian. */
switch (c) {
case 0 ... 0xd7ffU:
case 0xe000U ... 0xffffU:
out[0] = htole16(c);
return 1;
case 0x10000U ... 0x10ffffU:
c -= 0x10000U;
out[0] = htole16((c >> 10) + 0xd800U);
out[1] = htole16((c & 0x3ffU) + 0xdc00U);
return 2;
default: /* A surrogate (invalid) */
return 0;
}
}
/**
* crypt_utf8_to_utf16()
* @out: output buffer, should be @length + 1 long
* @s: string to convert
* @length: length of @s in bytes
*
* Converts a UTF8 encoded string to a UTF16LE encoded string.
*
* Returns: 0 on success, negative errno otherwise
*/
int crypt_utf8_to_utf16(char16_t **out, const char *s, size_t length)
{
char16_t *p;
size_t i;
int r;
assert(s);
p = *out;
for (i = 0; i < length;) {
char32_t unichar;
size_t e;
e = utf8_encoded_expected_len(s[i]);
if (e <= 1) /* Invalid and single byte characters are copied as they are */
goto copy;
if (i + e > length) /* sequence longer than input buffer, then copy as-is */
goto copy;
r = utf8_encoded_to_unichar(s + i, &unichar);
if (r < 0) /* sequence invalid, then copy as-is */
goto copy;
p += utf16_encode_unichar(p, unichar);
i += e;
continue;
copy:
*(p++) = htole16(s[i++]);
}
*p = 0;
return 0;
}

1057
lib/fvault2/fvault2.c Normal file

File diff suppressed because it is too large Load Diff

80
lib/fvault2/fvault2.h Normal file
View File

@@ -0,0 +1,80 @@
/*
* FVAULT2 (FileVault2-compatible) volume handling
*
* Copyright (C) 2021-2022 Pavel Tobias
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _CRYPTSETUP_FVAULT2_H
#define _CRYPTSETUP_FVAULT2_H
#include <stddef.h>
#include <stdint.h>
#define FVAULT2_WRAPPED_KEY_SIZE 24
#define FVAULT2_PBKDF2_SALT_SIZE 16
#define FVAULT2_UUID_LEN 37
struct crypt_device;
struct volume_key;
struct fvault2_params {
const char *cipher;
const char *cipher_mode;
uint16_t key_size;
uint32_t pbkdf2_iters;
char pbkdf2_salt[FVAULT2_PBKDF2_SALT_SIZE];
char wrapped_kek[FVAULT2_WRAPPED_KEY_SIZE];
char wrapped_vk[FVAULT2_WRAPPED_KEY_SIZE];
char family_uuid[FVAULT2_UUID_LEN];
char ph_vol_uuid[FVAULT2_UUID_LEN];
uint64_t log_vol_off;
uint64_t log_vol_size;
};
int FVAULT2_read_metadata(
struct crypt_device *cd,
struct fvault2_params *params);
int FVAULT2_get_volume_key(
struct crypt_device *cd,
const char *passphrase,
size_t passphrase_len,
const struct fvault2_params *params,
struct volume_key **vol_key);
int FVAULT2_dump(
struct crypt_device *cd,
struct device *device,
const struct fvault2_params *params);
int FVAULT2_activate_by_passphrase(
struct crypt_device *cd,
const char *name,
const char *passphrase,
size_t passphrase_len,
const struct fvault2_params *params,
uint32_t flags);
int FVAULT2_activate_by_volume_key(
struct crypt_device *cd,
const char *name,
const char *key,
size_t key_size,
const struct fvault2_params *params,
uint32_t flags);
#endif

View File

@@ -1,7 +1,7 @@
/*
* Integrity volume handling
*
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,17 @@
#include "integrity.h"
#include "internal.h"
/* For LUKS2, integrity metadata are on DATA device even for detached header! */
static struct device *INTEGRITY_metadata_device(struct crypt_device *cd)
{
const char *type = crypt_get_type(cd);
if (type && !strcmp(type, CRYPT_LUKS2))
return crypt_data_device(cd);
return crypt_metadata_device(cd);
}
static int INTEGRITY_read_superblock(struct crypt_device *cd,
struct device *device,
uint64_t offset, struct superblock *sb)
@@ -38,11 +49,13 @@ static int INTEGRITY_read_superblock(struct crypt_device *cd,
return -EINVAL;
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) ||
sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
log_std(cd, "No integrity superblock detected on %s.\n",
device_path(device));
device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic))) {
log_dbg(cd, "No kernel dm-integrity metadata detected on %s.", device_path(device));
r = -EINVAL;
} else if (sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
log_err(cd, _("Incompatible kernel dm-integrity metadata (version %u) detected on %s."),
sb->version, device_path(device));
r = -EINVAL;
} else {
sb->integrity_tag_size = le16toh(sb->integrity_tag_size);
@@ -63,7 +76,7 @@ int INTEGRITY_read_sb(struct crypt_device *cd,
struct superblock sb;
int r;
r = INTEGRITY_read_superblock(cd, crypt_metadata_device(cd), 0, &sb);
r = INTEGRITY_read_superblock(cd, INTEGRITY_metadata_device(cd), 0, &sb);
if (r)
return r;
@@ -120,7 +133,7 @@ int INTEGRITY_data_sectors(struct crypt_device *cd,
return 0;
}
int INTEGRITY_key_size(struct crypt_device *cd __attribute__((unused)), const char *integrity)
int INTEGRITY_key_size(const char *integrity)
{
if (!integrity)
return 0;
@@ -154,6 +167,9 @@ int INTEGRITY_hash_tag_size(const char *integrity)
if (!strcmp(integrity, "crc32") || !strcmp(integrity, "crc32c"))
return 4;
if (!strcmp(integrity, "xxhash64"))
return 8;
r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
if (r == 1)
r = crypt_hash_size(hash);
@@ -163,8 +179,7 @@ int INTEGRITY_hash_tag_size(const char *integrity)
return r < 0 ? 0 : r;
}
int INTEGRITY_tag_size(struct crypt_device *cd __attribute__((unused)),
const char *integrity,
int INTEGRITY_tag_size(const char *integrity,
const char *cipher,
const char *cipher_mode)
{
@@ -228,13 +243,13 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
if (sb_flags & SB_FLAG_RECALCULATING)
dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
r = INTEGRITY_data_sectors(cd, INTEGRITY_metadata_device(cd),
crypt_get_data_offset(cd) * SECTOR_SIZE, &dmd->size);
if (r < 0)
return r;
return dm_integrity_target_set(cd, &dmd->segment, 0, dmd->size,
crypt_metadata_device(cd), crypt_data_device(cd),
INTEGRITY_metadata_device(cd), crypt_data_device(cd),
crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
crypt_get_sector_size(cd), vk, journal_crypt_key,
journal_mac_key, params);
@@ -256,18 +271,8 @@ int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
log_dbg(cd, "Trying to activate INTEGRITY device on top of %s, using name %s, tag size %d, provided sectors %" PRIu64".",
device_path(tgt->data_device), name, tgt->u.integrity.tag_size, dmd->size);
r = device_block_adjust(cd, tgt->data_device, DEV_EXCL,
tgt->u.integrity.offset, NULL, &dmd->flags);
if (r)
return r;
r = create_or_reload_device(cd, name, type, dmd);
if (tgt->u.integrity.meta_device) {
r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL);
if (r)
return r;
}
r = dm_create_device(cd, name, type, dmd);
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel does not support dm-integrity mapping."));
return -ENOTSUP;
@@ -299,25 +304,93 @@ int INTEGRITY_activate(struct crypt_device *cd,
struct volume_key *journal_mac_key,
uint32_t flags, uint32_t sb_flags)
{
struct crypt_dm_active_device dmd = {};
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
journal_mac_key, &dmd, flags, sb_flags);
struct crypt_dm_active_device dmdq = {}, dmd = {};
int r;
if (flags & CRYPT_ACTIVATE_REFRESH) {
r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE |
DM_ACTIVE_CRYPT_KEY |
DM_ACTIVE_INTEGRITY_PARAMS |
DM_ACTIVE_JOURNAL_CRYPT_KEY |
DM_ACTIVE_JOURNAL_MAC_KEY, &dmdq);
if (r < 0)
return r;
r = INTEGRITY_create_dmd_device(cd, params, vk ?: dmdq.segment.u.integrity.vk,
journal_crypt_key ?: dmdq.segment.u.integrity.journal_crypt_key,
journal_mac_key ?: dmdq.segment.u.integrity.journal_integrity_key,
&dmd, flags, sb_flags);
if (!r)
dmd.size = dmdq.size;
} else
r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
journal_mac_key, &dmd, flags, sb_flags);
if (!r)
r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags);
dm_targets_free(cd, &dmdq);
dm_targets_free(cd, &dmd);
return r;
}
static int _create_reduced_device(struct crypt_device *cd,
const char *name,
uint64_t device_size_sectors,
struct device **ret_device)
{
int r;
char path[PATH_MAX];
struct device *dev;
struct crypt_dm_active_device dmd = {
.size = device_size_sectors,
.flags = CRYPT_ACTIVATE_PRIVATE,
};
assert(cd);
assert(name);
assert(device_size_sectors);
assert(ret_device);
r = snprintf(path, sizeof(path), "%s/%s", dm_get_dir(), name);
if (r < 0 || (size_t)r >= sizeof(path))
return -EINVAL;
r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
crypt_get_data_offset(cd), &device_size_sectors, &dmd.flags);
if (r)
return r;
log_dbg(cd, "Activating reduced helper device %s.", name);
r = dm_linear_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), crypt_get_data_offset(cd));
if (!r)
r = dm_create_device(cd, name, CRYPT_SUBDEV, &dmd);
dm_targets_free(cd, &dmd);
if (r < 0)
return r;
r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags);
dm_targets_free(cd, &dmd);
r = device_alloc(cd, &dev, path);
if (!r) {
*ret_device = dev;
return 0;
}
dm_remove_device(cd, name, CRYPT_DEACTIVATE_FORCE);
return r;
}
int INTEGRITY_format(struct crypt_device *cd,
const struct crypt_params_integrity *params,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key)
struct volume_key *journal_mac_key,
uint64_t backing_device_sectors)
{
uint32_t dmi_flags;
char tmp_name[64], tmp_uuid[40];
char reduced_device_name[70], tmp_name[64], tmp_uuid[40];
struct crypt_dm_active_device dmdi = {
.size = 8,
.flags = CRYPT_ACTIVATE_PRIVATE, /* We always create journal but it can be unused later */
@@ -325,6 +398,8 @@ int INTEGRITY_format(struct crypt_device *cd,
struct dm_target *tgt = &dmdi.segment;
int r;
uuid_t tmp_uuid_bin;
uint64_t data_offset_sectors;
struct device *p_metadata_device, *p_data_device, *reduced_device = NULL;
struct volume_key *vk = NULL;
uuid_generate(tmp_uuid_bin);
@@ -334,18 +409,42 @@ int INTEGRITY_format(struct crypt_device *cd,
if (r < 0 || (size_t)r >= sizeof(tmp_name))
return -EINVAL;
p_metadata_device = INTEGRITY_metadata_device(cd);
if (backing_device_sectors) {
r = snprintf(reduced_device_name, sizeof(reduced_device_name),
"temporary-cryptsetup-reduced-%s", tmp_uuid);
if (r < 0 || (size_t)r >= sizeof(reduced_device_name))
return -EINVAL;
/*
* Creates reduced dm-linear mapping over data device starting at
* crypt_data_offset(cd) and backing_device_sectors in size.
*/
r = _create_reduced_device(cd, reduced_device_name,
backing_device_sectors, &reduced_device);
if (r < 0)
return r;
data_offset_sectors = 0;
p_data_device = reduced_device;
if (p_metadata_device == crypt_data_device(cd))
p_metadata_device = reduced_device;
} else {
data_offset_sectors = crypt_get_data_offset(cd);
p_data_device = crypt_data_device(cd);
}
/* There is no data area, we can actually use fake zeroed key */
if (params && params->integrity_key_size)
vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, crypt_metadata_device(cd),
crypt_data_device(cd), crypt_get_integrity_tag_size(cd),
crypt_get_data_offset(cd), crypt_get_sector_size(cd), vk,
r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, p_metadata_device,
p_data_device, crypt_get_integrity_tag_size(cd),
data_offset_sectors, crypt_get_sector_size(cd), vk,
journal_crypt_key, journal_mac_key, params);
if (r < 0) {
crypt_free_volume_key(vk);
return r;
}
if (r < 0)
goto err;
log_dbg(cd, "Trying to format INTEGRITY device on top of %s, tmp name %s, tag size %d.",
device_path(tgt->data_device), tmp_name, tgt->u.integrity.tag_size);
@@ -355,24 +454,26 @@ int INTEGRITY_format(struct crypt_device *cd,
log_err(cd, _("Kernel does not support dm-integrity mapping."));
r = -ENOTSUP;
}
if (r) {
dm_targets_free(cd, &dmdi);
return r;
}
if (r)
goto err;
if (tgt->u.integrity.meta_device) {
r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL);
if (r) {
dm_targets_free(cd, &dmdi);
return r;
}
if (r)
goto err;
}
r = dm_create_device(cd, tmp_name, CRYPT_INTEGRITY, &dmdi);
crypt_free_volume_key(vk);
dm_targets_free(cd, &dmdi);
if (r)
return r;
goto err;
return dm_remove_device(cd, tmp_name, CRYPT_DEACTIVATE_FORCE);
r = dm_remove_device(cd, tmp_name, CRYPT_DEACTIVATE_FORCE);
err:
dm_targets_free(cd, &dmdi);
crypt_free_volume_key(vk);
if (reduced_device) {
dm_remove_device(cd, reduced_device_name, CRYPT_DEACTIVATE_FORCE);
device_free(cd, reduced_device);
}
return r;
}

View File

@@ -1,7 +1,7 @@
/*
* Integrity header definition
*
* Copyright (C) 2016-2021 Milan Broz
* Copyright (C) 2016-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -66,9 +66,8 @@ int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offs
int INTEGRITY_data_sectors(struct crypt_device *cd,
struct device *device, uint64_t offset,
uint64_t *data_sectors);
int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity);
int INTEGRITY_tag_size(struct crypt_device *cd,
const char *integrity,
int INTEGRITY_key_size(const char *integrity);
int INTEGRITY_tag_size(const char *integrity,
const char *cipher,
const char *cipher_mode);
int INTEGRITY_hash_tag_size(const char *integrity);
@@ -76,7 +75,8 @@ int INTEGRITY_hash_tag_size(const char *integrity);
int INTEGRITY_format(struct crypt_device *cd,
const struct crypt_params_integrity *params,
struct volume_key *journal_crypt_key,
struct volume_key *journal_mac_key);
struct volume_key *journal_mac_key,
uint64_t backing_device_sectors);
int INTEGRITY_activate(struct crypt_device *cd,
const char *name,

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <inttypes.h>
#include <fcntl.h>
#include <assert.h>
#include "nls.h"
#include "bitops.h"
@@ -38,7 +39,6 @@
#include "utils_crypt.h"
#include "utils_loop.h"
#include "utils_dm.h"
#include "utils_fips.h"
#include "utils_keyring.h"
#include "utils_io.h"
#include "crypto_backend/crypto_backend.h"
@@ -53,6 +53,7 @@
#define MAX_DM_DEPS 32
#define CRYPT_SUBDEV "SUBDEV" /* prefix for sublayered devices underneath public crypt types */
#define CRYPT_LUKS2_HW_OPAL "LUKS2-OPAL" /* dm uuid prefix used for any HW OPAL enabled LUKS2 device */
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
@@ -89,6 +90,7 @@ int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
struct crypt_pbkdf_type *pbkdf,
size_t volume_key_size);
const char *crypt_get_cipher_spec(struct crypt_device *cd);
uint32_t pbkdf_adjusted_phys_memory_kb(void);
/* Device backend */
struct device;
@@ -113,6 +115,7 @@ void device_release_excl(struct crypt_device *cd, struct device *device);
void device_disable_direct_io(struct device *device);
int device_is_identical(struct device *device1, struct device *device2);
int device_is_rotational(struct device *device);
int device_is_dax(struct device *device);
size_t device_alignment(struct device *device);
int device_direct_io(const struct device *device);
int device_fallocate(struct device *device, uint64_t size);
@@ -153,21 +156,31 @@ int create_or_reload_device_with_integrity(struct crypt_device *cd, const char *
struct device *crypt_metadata_device(struct crypt_device *cd);
struct device *crypt_data_device(struct crypt_device *cd);
uint64_t crypt_get_metadata_size_bytes(struct crypt_device *cd);
uint64_t crypt_get_keyslots_size_bytes(struct crypt_device *cd);
uint64_t crypt_get_data_offset_sectors(struct crypt_device *cd);
int crypt_opal_supported(struct crypt_device *cd, struct device *opal_device);
int crypt_confirm(struct crypt_device *cd, const char *msg);
char *crypt_lookup_dev(const char *dev_id);
int crypt_dev_is_rotational(int major, int minor);
int crypt_dev_is_dax(int major, int minor);
int crypt_dev_is_partition(const char *dev_path);
char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size);
int crypt_dev_get_partition_number(const char *dev_path);
char *crypt_get_base_device(const char *dev_path);
uint64_t crypt_dev_partition_offset(const char *dev_path);
int lookup_by_disk_id(const char *dm_uuid);
int lookup_by_sysfs_uuid_field(const char *dm_uuid);
int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid);
int crypt_uuid_type_cmp(const char *dm_uuid, const char *type);
size_t crypt_getpagesize(void);
unsigned crypt_cpusonline(void);
uint64_t crypt_getphysmemory_kb(void);
uint64_t crypt_getphysmemoryfree_kb(void);
bool crypt_swapavailable(void);
int init_crypto(struct crypt_device *ctx);
@@ -178,8 +191,7 @@ int init_crypto(struct crypt_device *ctx);
int crypt_get_debug_level(void);
int crypt_memlock_inc(struct crypt_device *ctx);
int crypt_memlock_dec(struct crypt_device *ctx);
void crypt_process_priority(struct crypt_device *cd, int *priority, bool raise);
int crypt_metadata_locking_enabled(void);
@@ -203,7 +215,7 @@ void crypt_set_luks2_reencrypt(struct crypt_device *cd, struct luks2_reencrypt *
struct luks2_reencrypt *crypt_get_luks2_reencrypt(struct crypt_device *cd);
int onlyLUKS2(struct crypt_device *cd);
int onlyLUKS2mask(struct crypt_device *cd, uint32_t mask);
int onlyLUKS2reencrypt(struct crypt_device *cd);
int crypt_wipe_device(struct crypt_device *cd,
struct device *device,
@@ -222,6 +234,14 @@ int crypt_get_integrity_tag_size(struct crypt_device *cd);
int crypt_key_in_keyring(struct crypt_device *cd);
void crypt_set_key_in_keyring(struct crypt_device *cd, unsigned key_in_keyring);
int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk);
int crypt_keyring_get_user_key(struct crypt_device *cd,
const char *key_description,
char **key,
size_t *key_size);
int crypt_keyring_get_key_by_name(struct crypt_device *cd,
const char *key_description,
char **key,
size_t *key_size);
int crypt_use_keyring_for_vk(struct crypt_device *cd);
void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *key_description, key_type_t ktype);
void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks);
@@ -251,4 +271,8 @@ static inline bool uint64_mult_overflow(uint64_t *u, uint64_t b, size_t size)
return false;
}
#define KEY_NOT_VERIFIED -2
#define KEY_EXTERNAL_VERIFICATION -1
#define KEY_VERIFIED 0
#endif /* INTERNAL_H */

828
lib/keyslot_context.c Normal file
View File

@@ -0,0 +1,828 @@
/*
* LUKS - Linux Unified Key Setup, keyslot unlock helpers
*
* Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022-2023 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <errno.h>
#include "luks1/luks.h"
#include "luks2/luks2.h"
#include "keyslot_context.h"
static int get_luks2_key_by_passphrase(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
int segment,
struct volume_key **r_vk)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
assert(r_vk);
r = LUKS2_keyslot_open(cd, keyslot, segment, kc->u.p.passphrase, kc->u.p.passphrase_size, r_vk);
if (r < 0)
kc->error = r;
return r;
}
static int get_luks1_volume_key_by_passphrase(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
assert(r_vk);
r = LUKS_open_key_with_hdr(keyslot, kc->u.p.passphrase, kc->u.p.passphrase_size,
crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
if (r < 0)
kc->error = r;
return r;
}
static int get_luks2_volume_key_by_passphrase(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
return get_luks2_key_by_passphrase(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
}
static int get_passphrase_by_passphrase(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
const char **r_passphrase,
size_t *r_passphrase_size)
{
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
assert(r_passphrase);
assert(r_passphrase_size);
*r_passphrase = kc->u.p.passphrase;
*r_passphrase_size = kc->u.p.passphrase_size;
return 0;
}
static int get_passphrase_by_keyfile(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
const char **r_passphrase,
size_t *r_passphrase_size)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
assert(r_passphrase);
assert(r_passphrase_size);
if (!kc->i_passphrase) {
r = crypt_keyfile_device_read(cd, kc->u.kf.keyfile,
&kc->i_passphrase, &kc->i_passphrase_size,
kc->u.kf.keyfile_offset, kc->u.kf.keyfile_size, 0);
if (r < 0) {
kc->error = r;
return r;
}
}
*r_passphrase = kc->i_passphrase;
*r_passphrase_size = kc->i_passphrase_size;
return 0;
}
static int get_luks2_key_by_keyfile(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
int segment,
struct volume_key **r_vk)
{
int r;
const char *passphrase;
size_t passphrase_size;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
assert(r_vk);
r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
if (r)
return r;
r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, r_vk);
if (r < 0)
kc->error = r;
return r;
}
static int get_luks2_volume_key_by_keyfile(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
return get_luks2_key_by_keyfile(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
}
static int get_luks1_volume_key_by_keyfile(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
int r;
const char *passphrase;
size_t passphrase_size;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
assert(r_vk);
r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
if (r)
return r;
r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size,
crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
if (r < 0)
kc->error = r;
return r;
}
static int get_key_by_key(struct crypt_device *cd __attribute__((unused)),
struct crypt_keyslot_context *kc,
int keyslot __attribute__((unused)),
int segment __attribute__((unused)),
struct volume_key **r_vk)
{
assert(kc && kc->type == CRYPT_KC_TYPE_KEY);
assert(r_vk);
if (!kc->u.k.volume_key) {
kc->error = -ENOENT;
return kc->error;
}
*r_vk = crypt_alloc_volume_key(kc->u.k.volume_key_size, kc->u.k.volume_key);
if (!*r_vk) {
kc->error = -ENOMEM;
return kc->error;
}
return 0;
}
static int get_volume_key_by_key(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot __attribute__((unused)),
struct volume_key **r_vk)
{
return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
}
static int get_generic_volume_key_by_key(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
struct volume_key **r_vk)
{
return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
}
static int get_generic_signed_key_by_key(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
struct volume_key **r_vk,
struct volume_key **r_signature)
{
struct volume_key *vk, *vk_sig;
assert(kc && ((kc->type == CRYPT_KC_TYPE_KEY) ||
(kc->type == CRYPT_KC_TYPE_SIGNED_KEY)));
assert(r_vk);
assert(r_signature);
/* return key with no signature */
if (kc->type == CRYPT_KC_TYPE_KEY) {
*r_signature = NULL;
return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
}
if (!kc->u.ks.volume_key || !kc->u.ks.signature) {
kc->error = -EINVAL;
return kc->error;
}
vk = crypt_alloc_volume_key(kc->u.ks.volume_key_size, kc->u.ks.volume_key);
if (!vk) {
kc->error = -ENOMEM;
return kc->error;
}
vk_sig = crypt_alloc_volume_key(kc->u.ks.signature_size, kc->u.ks.signature);
if (!vk_sig) {
crypt_free_volume_key(vk);
kc->error = -ENOMEM;
return kc->error;
}
*r_vk = vk;
*r_signature = vk_sig;
return 0;
}
static int get_luks2_key_by_token(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
int segment,
struct volume_key **r_vk)
{
int r;
struct luks2_hdr *hdr;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_TOKEN);
assert(r_vk);
hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
if (!hdr)
return -EINVAL;
r = LUKS2_token_unlock_key(cd, hdr, keyslot, kc->u.t.id, kc->u.t.type,
kc->u.t.pin, kc->u.t.pin_size, segment, kc->u.t.usrptr, r_vk);
if (r < 0)
kc->error = r;
return r;
}
static int get_luks2_volume_key_by_token(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
return get_luks2_key_by_token(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
}
static int get_passphrase_by_token(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
const char **r_passphrase,
size_t *r_passphrase_size)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_TOKEN);
assert(r_passphrase);
assert(r_passphrase_size);
if (!kc->i_passphrase) {
r = LUKS2_token_unlock_passphrase(cd, crypt_get_hdr(cd, CRYPT_LUKS2), kc->u.t.id,
kc->u.t.type, kc->u.t.pin, kc->u.t.pin_size,
kc->u.t.usrptr, &kc->i_passphrase, &kc->i_passphrase_size);
if (r < 0) {
kc->error = r;
return r;
}
kc->u.t.id = r;
}
*r_passphrase = kc->i_passphrase;
*r_passphrase_size = kc->i_passphrase_size;
return kc->u.t.id;
}
static int get_passphrase_by_keyring(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
const char **r_passphrase,
size_t *r_passphrase_size)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_KEYRING);
assert(r_passphrase);
assert(r_passphrase_size);
if (!kc->i_passphrase) {
r = crypt_keyring_get_user_key(cd, kc->u.kr.key_description,
&kc->i_passphrase, &kc->i_passphrase_size);
if (r < 0) {
log_err(cd, _("Failed to read passphrase from keyring."));
kc->error = -EINVAL;
return -EINVAL;
}
}
*r_passphrase = kc->i_passphrase;
*r_passphrase_size = kc->i_passphrase_size;
return 0;
}
static int get_luks2_key_by_keyring(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
int segment,
struct volume_key **r_vk)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_KEYRING);
assert(r_vk);
r = get_passphrase_by_keyring(cd, kc, CONST_CAST(const char **) &kc->i_passphrase,
&kc->i_passphrase_size);
if (r < 0) {
log_err(cd, _("Failed to read passphrase from keyring."));
kc->error = -EINVAL;
return -EINVAL;
}
r = LUKS2_keyslot_open(cd, keyslot, segment, kc->i_passphrase, kc->i_passphrase_size, r_vk);
if (r < 0)
kc->error = r;
return 0;
}
static int get_luks2_volume_key_by_keyring(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
return get_luks2_key_by_keyring(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
}
static int get_luks1_volume_key_by_keyring(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk)
{
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
assert(r_vk);
r = get_passphrase_by_keyring(cd, kc, CONST_CAST(const char **) &kc->i_passphrase,
&kc->i_passphrase_size);
if (r < 0) {
log_err(cd, _("Failed to read passphrase from keyring."));
kc->error = -EINVAL;
return -EINVAL;
}
r = LUKS_open_key_with_hdr(keyslot, kc->i_passphrase, kc->i_passphrase_size,
crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
if (r < 0)
kc->error = r;
return r;
}
static int get_key_by_vk_in_keyring(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot __attribute__((unused)),
int segment __attribute__((unused)),
struct volume_key **r_vk)
{
char *key;
size_t key_size;
int r;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_VK_KEYRING);
assert(r_vk);
r = crypt_keyring_get_key_by_name(cd, kc->u.vk_kr.key_description,
&key, &key_size);
if (r < 0) {
log_err(cd, _("Failed to read volume key candidate from keyring."));
kc->error = -EINVAL;
return -EINVAL;
}
*r_vk = crypt_alloc_volume_key(key_size, key);
crypt_safe_free(key);
if (!*r_vk) {
kc->error = -ENOMEM;
return kc->error;
}
return 0;
}
static int get_volume_key_by_vk_in_keyring(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot __attribute__((unused)),
struct volume_key **r_vk)
{
return get_key_by_vk_in_keyring(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
}
static void unlock_method_init_internal(struct crypt_keyslot_context *kc)
{
assert(kc);
kc->error = 0;
kc->i_passphrase = NULL;
kc->i_passphrase_size = 0;
}
void crypt_keyslot_unlock_by_keyring_internal(struct crypt_keyslot_context *kc,
const char *key_description)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_KEYRING;
kc->u.kr.key_description = key_description;
kc->get_luks2_key = get_luks2_key_by_keyring;
kc->get_luks2_volume_key = get_luks2_volume_key_by_keyring;
kc->get_luks1_volume_key = get_luks1_volume_key_by_keyring;
kc->get_passphrase = get_passphrase_by_keyring;
kc->get_plain_volume_key = NULL;
kc->get_bitlk_volume_key = NULL;
kc->get_fvault2_volume_key = NULL;
kc->get_verity_volume_key = NULL;
kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
const char *volume_key,
size_t volume_key_size)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_KEY;
kc->u.k.volume_key = volume_key;
kc->u.k.volume_key_size = volume_key_size;
kc->get_luks2_key = get_key_by_key;
kc->get_luks2_volume_key = get_volume_key_by_key;
kc->get_luks1_volume_key = get_volume_key_by_key;
kc->get_passphrase = NULL; /* keyslot key context does not provide passphrase */
kc->get_plain_volume_key = get_generic_volume_key_by_key;
kc->get_bitlk_volume_key = get_generic_volume_key_by_key;
kc->get_fvault2_volume_key = get_generic_volume_key_by_key;
kc->get_verity_volume_key = get_generic_signed_key_by_key;
kc->get_integrity_volume_key = get_generic_volume_key_by_key;
unlock_method_init_internal(kc);
}
void crypt_keyslot_unlock_by_signed_key_init_internal(struct crypt_keyslot_context *kc,
const char *volume_key,
size_t volume_key_size,
const char *signature,
size_t signature_size)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_SIGNED_KEY;
kc->u.ks.volume_key = volume_key;
kc->u.ks.volume_key_size = volume_key_size;
kc->u.ks.signature = signature;
kc->u.ks.signature_size = signature_size;
kc->get_luks2_key = NULL;
kc->get_luks2_volume_key = NULL;
kc->get_luks1_volume_key = NULL;
kc->get_passphrase = NULL;
kc->get_plain_volume_key = NULL;
kc->get_bitlk_volume_key = NULL;
kc->get_fvault2_volume_key = NULL;
kc->get_verity_volume_key = get_generic_signed_key_by_key;
kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
void crypt_keyslot_unlock_by_passphrase_init_internal(struct crypt_keyslot_context *kc,
const char *passphrase,
size_t passphrase_size)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_PASSPHRASE;
kc->u.p.passphrase = passphrase;
kc->u.p.passphrase_size = passphrase_size;
kc->get_luks2_key = get_luks2_key_by_passphrase;
kc->get_luks2_volume_key = get_luks2_volume_key_by_passphrase;
kc->get_luks1_volume_key = get_luks1_volume_key_by_passphrase;
kc->get_passphrase = get_passphrase_by_passphrase;
kc->get_plain_volume_key = NULL;
kc->get_bitlk_volume_key = NULL;
kc->get_fvault2_volume_key = NULL;
kc->get_verity_volume_key = NULL;
kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
void crypt_keyslot_unlock_by_keyfile_init_internal(struct crypt_keyslot_context *kc,
const char *keyfile,
size_t keyfile_size,
uint64_t keyfile_offset)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_KEYFILE;
kc->u.kf.keyfile = keyfile;
kc->u.kf.keyfile_size = keyfile_size;
kc->u.kf.keyfile_offset = keyfile_offset;
kc->get_luks2_key = get_luks2_key_by_keyfile;
kc->get_luks2_volume_key = get_luks2_volume_key_by_keyfile;
kc->get_luks1_volume_key = get_luks1_volume_key_by_keyfile;
kc->get_passphrase = get_passphrase_by_keyfile;
kc->get_plain_volume_key = NULL;
kc->get_bitlk_volume_key = NULL;
kc->get_fvault2_volume_key = NULL;
kc->get_verity_volume_key = NULL;
kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *kc,
int token,
const char *type,
const char *pin,
size_t pin_size,
void *usrptr)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_TOKEN;
kc->u.t.id = token;
kc->u.t.type = type;
kc->u.t.pin = pin;
kc->u.t.pin_size = pin_size;
kc->u.t.usrptr = usrptr;
kc->get_luks2_key = get_luks2_key_by_token;
kc->get_luks2_volume_key = get_luks2_volume_key_by_token;
kc->get_luks1_volume_key = NULL; /* LUKS1 is not supported */
kc->get_passphrase = get_passphrase_by_token;
kc->get_plain_volume_key = NULL;
kc->get_bitlk_volume_key = NULL;
kc->get_fvault2_volume_key = NULL;
kc->get_verity_volume_key = NULL;
kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
void crypt_keyslot_unlock_by_vk_in_keyring_internal(struct crypt_keyslot_context *kc,
const char *key_description)
{
assert(kc);
kc->type = CRYPT_KC_TYPE_VK_KEYRING;
kc->u.vk_kr.key_description = key_description;
kc->get_luks2_key = get_key_by_vk_in_keyring;
kc->get_luks2_volume_key = get_volume_key_by_vk_in_keyring;
kc->get_luks1_volume_key = NULL;
kc->get_passphrase = NULL; /* keyslot key context does not provide passphrase */
kc->get_plain_volume_key = NULL;
kc->get_bitlk_volume_key = NULL;
kc->get_fvault2_volume_key = NULL;
kc->get_verity_volume_key = NULL;
kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *kc)
{
if (!kc)
return;
crypt_safe_free(kc->i_passphrase);
kc->i_passphrase = NULL;
kc->i_passphrase_size = 0;
}
void crypt_keyslot_context_free(struct crypt_keyslot_context *kc)
{
crypt_keyslot_context_destroy_internal(kc);
free(kc);
}
int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd __attribute__((unused)),
const char *passphrase,
size_t passphrase_size,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc || !passphrase)
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_passphrase_init_internal(tmp, passphrase, passphrase_size);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd __attribute__((unused)),
const char *keyfile,
size_t keyfile_size,
uint64_t keyfile_offset,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc || !keyfile)
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_keyfile_init_internal(tmp, keyfile, keyfile_size, keyfile_offset);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_init_by_token(struct crypt_device *cd __attribute__((unused)),
int token,
const char *type,
const char *pin, size_t pin_size,
void *usrptr,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc || (token < 0 && token != CRYPT_ANY_TOKEN))
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_token_init_internal(tmp, token, type, pin, pin_size, usrptr);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd __attribute__((unused)),
const char *volume_key,
size_t volume_key_size,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc)
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_key_init_internal(tmp, volume_key, volume_key_size);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_init_by_signed_key(struct crypt_device *cd __attribute__((unused)),
const char *volume_key,
size_t volume_key_size,
const char *signature,
size_t signature_size,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc)
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_signed_key_init_internal(tmp, volume_key, volume_key_size,
signature, signature_size);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_init_by_keyring(struct crypt_device *cd __attribute__((unused)),
const char *key_description,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc)
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_keyring_internal(tmp, key_description);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_init_by_vk_in_keyring(struct crypt_device *cd __attribute__((unused)),
const char *key_description,
struct crypt_keyslot_context **kc)
{
struct crypt_keyslot_context *tmp;
if (!kc)
return -EINVAL;
tmp = malloc(sizeof(*tmp));
if (!tmp)
return -ENOMEM;
crypt_keyslot_unlock_by_vk_in_keyring_internal(tmp, key_description);
*kc = tmp;
return 0;
}
int crypt_keyslot_context_get_error(struct crypt_keyslot_context *kc)
{
return kc ? kc->error : -EINVAL;
}
int crypt_keyslot_context_set_pin(struct crypt_device *cd __attribute__((unused)),
const char *pin, size_t pin_size,
struct crypt_keyslot_context *kc)
{
if (!kc || kc->type != CRYPT_KC_TYPE_TOKEN)
return -EINVAL;
kc->u.t.pin = pin;
kc->u.t.pin_size = pin_size;
kc->error = 0;
return 0;
}
int crypt_keyslot_context_get_type(const struct crypt_keyslot_context *kc)
{
return kc ? kc->type : -EINVAL;
}
const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc)
{
assert(kc);
switch (kc->type) {
case CRYPT_KC_TYPE_PASSPHRASE:
return "passphrase";
case CRYPT_KC_TYPE_KEYFILE:
return "keyfile";
case CRYPT_KC_TYPE_TOKEN:
return "token";
case CRYPT_KC_TYPE_KEY:
return "key";
case CRYPT_KC_TYPE_KEYRING:
return "keyring";
case CRYPT_KC_TYPE_VK_KEYRING:
return "volume key in keyring";
case CRYPT_KC_TYPE_SIGNED_KEY:
return "signed key";
default:
return "<unknown>";
}
}

151
lib/keyslot_context.h Normal file
View File

@@ -0,0 +1,151 @@
/*
* LUKS - Linux Unified Key Setup, keyslot unlock helpers
*
* Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022-2023 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef KEYSLOT_CONTEXT_H
#define KEYSLOT_CONTEXT_H
#include <stdbool.h>
#include <stdint.h>
#include "internal.h"
typedef int (*keyslot_context_get_key) (
struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
int segment,
struct volume_key **r_vk);
typedef int (*keyslot_context_get_volume_key) (
struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot,
struct volume_key **r_vk);
typedef int (*keyslot_context_get_generic_volume_key) (
struct crypt_device *cd,
struct crypt_keyslot_context *kc,
struct volume_key **r_vk);
typedef int (*keyslot_context_get_generic_signed_key) (
struct crypt_device *cd,
struct crypt_keyslot_context *kc,
struct volume_key **r_vk,
struct volume_key **r_signature);
typedef int (*keyslot_context_get_passphrase) (
struct crypt_device *cd,
struct crypt_keyslot_context *kc,
const char **r_passphrase,
size_t *r_passphrase_size);
/* crypt_keyslot_context */
struct crypt_keyslot_context {
int type;
union {
struct {
const char *passphrase;
size_t passphrase_size;
} p;
struct {
const char *keyfile;
uint64_t keyfile_offset;
size_t keyfile_size;
} kf;
struct {
int id;
const char *type;
const char *pin;
size_t pin_size;
void *usrptr;
} t;
struct {
const char *volume_key;
size_t volume_key_size;
} k;
struct {
const char *volume_key;
size_t volume_key_size;
const char *signature;
size_t signature_size;
} ks;
struct {
const char *key_description;
} kr;
struct {
const char *key_description;
} vk_kr;
} u;
int error;
char *i_passphrase;
size_t i_passphrase_size;
keyslot_context_get_key get_luks2_key;
keyslot_context_get_volume_key get_luks1_volume_key;
keyslot_context_get_volume_key get_luks2_volume_key;
keyslot_context_get_generic_volume_key get_plain_volume_key;
keyslot_context_get_generic_volume_key get_bitlk_volume_key;
keyslot_context_get_generic_volume_key get_fvault2_volume_key;
keyslot_context_get_generic_signed_key get_verity_volume_key;
keyslot_context_get_generic_volume_key get_integrity_volume_key;
keyslot_context_get_passphrase get_passphrase;
};
void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *method);
void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
const char *volume_key,
size_t volume_key_size);
void crypt_keyslot_unlock_by_signed_key_init_internal(struct crypt_keyslot_context *kc,
const char *volume_key,
size_t volume_key_size,
const char *signature,
size_t signature_size);
void crypt_keyslot_unlock_by_passphrase_init_internal(struct crypt_keyslot_context *kc,
const char *passphrase,
size_t passphrase_size);
void crypt_keyslot_unlock_by_keyfile_init_internal(struct crypt_keyslot_context *kc,
const char *keyfile,
size_t keyfile_size,
uint64_t keyfile_offset);
void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *kc,
int token,
const char *type,
const char *pin,
size_t pin_size,
void *usrptr);
void crypt_keyslot_unlock_by_keyring_internal(struct crypt_keyslot_context *kc,
const char *key_description);
void crypt_keyslot_unlock_by_vk_in_keyring_internal(struct crypt_keyslot_context *kc,
const char *key_description);
const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc);
#endif /* KEYSLOT_CONTEXT_H */

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -46,6 +46,7 @@ extern "C" {
*/
struct crypt_device; /* crypt device handle */
struct crypt_keyslot_context;
/**
* Initialize crypt device handle and check if the provided device exists.
@@ -271,9 +272,9 @@ struct crypt_pbkdf_type {
};
/** Iteration time set by crypt_set_iteration_time(), for compatibility only. */
#define CRYPT_PBKDF_ITER_TIME_SET (1 << 0)
/** Never run benchmarks, use pre-set value or defaults. */
#define CRYPT_PBKDF_NO_BENCHMARK (1 << 1)
#define CRYPT_PBKDF_ITER_TIME_SET (UINT32_C(1) << 0)
/** Never run benchmarks or limit by system resources, use pre-set values or defaults. */
#define CRYPT_PBKDF_NO_BENCHMARK (UINT32_C(1) << 1)
/** PBKDF2 according to RFC2898, LUKS1 legacy */
#define CRYPT_KDF_PBKDF2 "pbkdf2"
@@ -344,6 +345,7 @@ void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_m
/**
* Helper to lock/unlock memory to avoid swap sensitive data to disk.
* \b Deprecated, only for backward compatibility. Memory with keys are locked automatically.
*
* @param cd crypt device handle, can be @e NULL
* @param lock 0 to unlock otherwise lock memory
@@ -353,7 +355,7 @@ void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_m
* @note Only root can do this.
* @note It locks/unlocks all process memory, not only crypt context.
*/
int crypt_memory_lock(struct crypt_device *cd, int lock);
int crypt_memory_lock(struct crypt_device *cd, int lock) __attribute__((deprecated));
/**
* Set global lock protection for on-disk metadata (file-based locking).
@@ -427,6 +429,8 @@ int crypt_get_metadata_size(struct crypt_device *cd,
#define CRYPT_INTEGRITY "INTEGRITY"
/** BITLK (BitLocker-compatible mode) */
#define CRYPT_BITLK "BITLK"
/** FVAULT2 (FileVault2-compatible mode) */
#define CRYPT_FVAULT2 "FVAULT2"
/** LUKS any version */
#define CRYPT_LUKS NULL
@@ -446,6 +450,34 @@ const char *crypt_get_type(struct crypt_device *cd);
*/
const char *crypt_get_default_type(void);
/**
* @defgroup crypt-hw-encryption-types HW encryption type
* @addtogroup crypt-hw-encryption-types
* @{
*/
/** SW encryption, no OPAL encryption in place (default) */
#define CRYPT_SW_ONLY INT16_C(0)
/** OPAL HW encryption only (no SW encryption!) */
#define CRYPT_OPAL_HW_ONLY INT16_C(1)
/** SW encryption stacked over OPAL HW encryption */
#define CRYPT_SW_AND_OPAL_HW INT16_C(2)
/** @} */
/**
* Get HW encryption type
*
* @return HW encryption type (see @link crypt-hw-encryption-types @endlink)
* or negative errno otherwise.
*/
int crypt_get_hw_encryption_type(struct crypt_device *cd);
/**
* Get HW encryption (like OPAL) key size (in bytes)
*
* @return key size or 0 if no HW encryption is used.
*/
int crypt_get_hw_encryption_key_size(struct crypt_device *cd);
/**
*
* Structure used as parameter for PLAIN device type.
@@ -513,13 +545,13 @@ struct crypt_params_verity {
};
/** No on-disk header (only hashes) */
#define CRYPT_VERITY_NO_HEADER (1 << 0)
#define CRYPT_VERITY_NO_HEADER (UINT32_C(1) << 0)
/** Verity hash in userspace before activation */
#define CRYPT_VERITY_CHECK_HASH (1 << 1)
#define CRYPT_VERITY_CHECK_HASH (UINT32_C(1) << 1)
/** Create hash - format hash device */
#define CRYPT_VERITY_CREATE_HASH (1 << 2)
#define CRYPT_VERITY_CREATE_HASH (UINT32_C(1) << 2)
/** Root hash signature required for activation */
#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (1 << 3)
#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (UINT32_C(1) << 3)
/**
*
@@ -542,18 +574,18 @@ struct crypt_params_tcrypt {
};
/** Include legacy modes when scanning for header */
#define CRYPT_TCRYPT_LEGACY_MODES (1 << 0)
#define CRYPT_TCRYPT_LEGACY_MODES (UINT32_C(1) << 0)
/** Try to load hidden header (describing hidden device) */
#define CRYPT_TCRYPT_HIDDEN_HEADER (1 << 1)
#define CRYPT_TCRYPT_HIDDEN_HEADER (UINT32_C(1) << 1)
/** Try to load backup header */
#define CRYPT_TCRYPT_BACKUP_HEADER (1 << 2)
#define CRYPT_TCRYPT_BACKUP_HEADER (UINT32_C(1) << 2)
/** Device contains encrypted system (with boot loader) */
#define CRYPT_TCRYPT_SYSTEM_HEADER (1 << 3)
#define CRYPT_TCRYPT_SYSTEM_HEADER (UINT32_C(1) << 3)
/** Include VeraCrypt modes when scanning for header,
* all other TCRYPT flags applies as well.
* VeraCrypt device is reported as TCRYPT type.
*/
#define CRYPT_TCRYPT_VERA_MODES (1 << 4)
#define CRYPT_TCRYPT_VERA_MODES (UINT32_C(1) << 4)
/**
*
@@ -605,6 +637,18 @@ struct crypt_params_luks2 {
const char *label; /**< header label or @e NULL*/
const char *subsystem; /**< header subsystem label or @e NULL*/
};
/**
* Structure used as parameter for OPAL (HW encrypted) device type.
*
* @see crypt_format_luks2_opal
*
*/
struct crypt_params_hw_opal {
const char *admin_key; /**< admin key */
size_t admin_key_size; /**< admin key size in bytes */
size_t user_key_size; /**< user authority key size part in bytes */
};
/** @} */
/**
@@ -644,6 +688,34 @@ int crypt_format(struct crypt_device *cd,
size_t volume_key_size,
void *params);
/**
* Create (format) new LUKS2 crypt device over HW OPAL device but do not activate it.
*
* @pre @e cd contains initialized and not formatted device context (device type must @b not be set)
*
* @param cd crypt device handle
* @param cipher for SW encryption (e.g. "aes") or NULL for HW encryption only
* @param cipher_mode including IV specification (e.g. "xts-plain") or NULL for HW encryption only
* @param uuid requested UUID or @e NULL if it should be generated
* @param volume_keys pre-generated volume keys or @e NULL if it should be generated (only for LUKS2 SW encryption)
* @param volume_keys_size size of volume keys in bytes (only for SW encryption).
* @param params LUKS2 crypt type specific parameters (see @link crypt-type @endlink)
* @param opal_params OPAL specific parameters
*
* @returns @e 0 on success or negative errno value otherwise.
*
* @note Note that crypt_format_luks2_opal does not create LUKS keyslot.
* To create keyslot call any crypt_keyslot_add_* function.
*/
int crypt_format_luks2_opal(struct crypt_device *cd,
const char *cipher,
const char *cipher_mode,
const char *uuid,
const char *volume_keys,
size_t volume_keys_size,
struct crypt_params_luks2 *params,
struct crypt_params_hw_opal *opal_params);
/**
* Set format compatibility flags.
*
@@ -662,11 +734,11 @@ void crypt_set_compatibility(struct crypt_device *cd, uint32_t flags);
uint32_t crypt_get_compatibility(struct crypt_device *cd);
/** dm-integrity device uses less effective (legacy) padding (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING (1 << 0)
#define CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING (UINT32_C(1) << 0)
/** dm-integrity device does not protect superblock with HMAC (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC (1 << 1)
#define CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC (UINT32_C(1) << 1)
/** dm-integrity allow recalculating of volumes with HMAC keys (old kernels) */
#define CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC (1 << 2)
#define CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC (UINT32_C(1) << 2)
/**
* Convert to new type for already existing device.
@@ -718,6 +790,24 @@ int crypt_set_label(struct crypt_device *cd,
const char *label,
const char *subsystem);
/**
* Get the label of an existing device.
*
* @param cd crypt device handle
*
* @return label, or @e NULL otherwise
*/
const char *crypt_get_label(struct crypt_device *cd);
/**
* Get the subsystem of an existing device.
*
* @param cd crypt device handle
*
* @return subsystem, or @e NULL otherwise
*/
const char *crypt_get_subsystem(struct crypt_device *cd);
/**
* Enable or disable loading of volume keys via kernel keyring. When set to
* 'enabled' library loads key in kernel keyring first and pass the key
@@ -749,7 +839,8 @@ int crypt_volume_key_keyring(struct crypt_device *cd, int enable);
* @post In case LUKS header is read successfully but payload device is too small
* error is returned and device type in context is set to @e NULL
*
* @note Note that in current version load works only for LUKS and VERITY device type.
* @note Note that load works only for device types with on-disk metadata.
* @note Function does not print visible error message if metadata is not present.
*
*/
int crypt_load(struct crypt_device *cd,
@@ -881,6 +972,60 @@ int crypt_resume_by_volume_key(struct crypt_device *cd,
const char *name,
const char *volume_key,
size_t volume_key_size);
/**
* Resume crypt device using LUKS2 token.
*
* @param cd LUKS2 crypt device handle
* @param name name of device to resume
* @param type restrict type of token, if @e NULL all types are allowed
* @param pin passphrase (or PIN) to unlock token (may be binary data)
* @param pin_size size of @e pin
* @param usrptr provided identification in callback
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note EPERM errno means token provided passphrase successfully, but
* passphrase did not unlock any keyslot associated with the token.
*
* @note ENOENT errno means no token (or subsequently assigned keyslot) was
* eligible to resume LUKS2 device.
*
* @note ENOANO errno means that token is PIN protected and was either missing
* (NULL) or wrong.
*
* @note Negative EAGAIN errno means token handler requires additional hardware
* not present in the system to unlock keyslot.
*
* @note with @param token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
* to resume device using any available token. It may happen that various token handlers
* return different error codes. At the end loop returns error codes in the following
* order (from the most significant to the least) any negative errno except those
* listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
*/
int crypt_resume_by_token_pin(struct crypt_device *cd,
const char *name,
const char *type,
int token,
const char *pin,
size_t pin_size,
void *usrptr);
/**
* Resume crypt device using keyslot context.
*
* @param cd crypt device handle
* @param name name of device to resume
* @param keyslot requested keyslot to check or @e CRYPT_ANY_SLOT, keyslot is
* ignored for unlock methods not based on passphrase
* @param kc keyslot context providing volume key or passphrase.
*
* @return unlocked key slot number for passphrase-based unlock, zero for other
* unlock methods (e.g. volume key context) or negative errno on error.
*/
int crypt_resume_by_keyslot_context(struct crypt_device *cd,
const char *name,
int keyslot,
struct crypt_keyslot_context *kc);
/** @} */
/**
@@ -1005,13 +1150,13 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
size_t passphrase_size);
/** create keyslot with volume key not associated with current dm-crypt segment */
#define CRYPT_VOLUME_KEY_NO_SEGMENT (1 << 0)
#define CRYPT_VOLUME_KEY_NO_SEGMENT (UINT32_C(1) << 0)
/** create keyslot with new volume key and assign it to current dm-crypt segment */
#define CRYPT_VOLUME_KEY_SET (1 << 1)
#define CRYPT_VOLUME_KEY_SET (UINT32_C(1) << 1)
/** Assign key to first matching digest before creating new digest */
#define CRYPT_VOLUME_KEY_DIGEST_REUSE (1 << 2)
#define CRYPT_VOLUME_KEY_DIGEST_REUSE (UINT32_C(1) << 2)
/**
* Add key slot using provided key.
@@ -1039,7 +1184,7 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
* @warning CRYPT_VOLUME_KEY_SET flag force updates volume key. It is @b not @b reencryption!
* By doing so you will most probably destroy your ciphertext data device. It's supposed
* to be used only in wrapped keys scheme for key refresh process where real (inner) volume
* key stays untouched. It may be involed on active @e keyslot which makes the (previously
* key stays untouched. It may be involved on active @e keyslot which makes the (previously
* unbound) keyslot new regular keyslot.
*/
int crypt_keyslot_add_by_key(struct crypt_device *cd,
@@ -1050,6 +1195,250 @@ int crypt_keyslot_add_by_key(struct crypt_device *cd,
size_t passphrase_size,
uint32_t flags);
/**
* @defgroup crypt-keyslot-context Crypt keyslot context
* @addtogroup crypt-keyslot-context
* @{
*/
/**
* Release crypt keyslot context and used memory.
*
* @param kc crypt keyslot context
*/
void crypt_keyslot_context_free(struct crypt_keyslot_context *kc);
/**
* Initialize keyslot context via passphrase.
*
* @param cd crypt device handle initialized to LUKS device context
* @param passphrase passphrase for a keyslot
* @param passphrase_size size of passphrase
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_PASSPHRASE
*
* @return zero on success or negative errno otherwise.
*/
int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
const char *passphrase,
size_t passphrase_size,
struct crypt_keyslot_context **kc);
/**
* Initialize keyslot context via key file path.
*
* @param cd crypt device handle initialized to LUKS device context
*
* @param keyfile key file with passphrase for a keyslot
* @param keyfile_size number of bytes to read from keyfile, @e 0 is unlimited
* @param keyfile_offset number of bytes to skip at start of keyfile
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEYFILE
*
* @return zero on success or negative errno otherwise.
*/
int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
const char *keyfile,
size_t keyfile_size,
uint64_t keyfile_offset,
struct crypt_keyslot_context **kc);
/**
* Initialize keyslot context via LUKS2 token.
*
* @param cd crypt device handle initialized to LUKS2 device context
*
* @param token token providing passphrase for a keyslot or CRYPT_ANY_TOKEN
* @param type restrict type of token, if @e NULL all types are allowed
* @param pin passphrase (or PIN) to unlock token (may be binary data)
* @param pin_size size of @e pin
* @param usrptr provided identification in callback
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_TOKEN
*
* @return zero on success or negative errno otherwise.
*/
int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
int token,
const char *type,
const char *pin, size_t pin_size,
void *usrptr,
struct crypt_keyslot_context **kc);
/**
* Initialize keyslot context via key.
*
* @param cd crypt device handle initialized to LUKS device context
*
* @param volume_key provided volume key or @e NULL if used after crypt_format
* or with CRYPT_VOLUME_KEY_NO_SEGMENT flag
* @param volume_key_size size of volume_key
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEY
*
* @return zero on success or negative errno otherwise.
*/
int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
const char *volume_key,
size_t volume_key_size,
struct crypt_keyslot_context **kc);
/**
* Initialize keyslot context via signed key.
*
* @param cd crypt device handle initialized to device context
*
* @param volume_key provided volume key
* @param volume_key_size size of volume_key
* @param signature buffer with signature for the key
* @param signature_size bsize of signature buffer
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_SIGNED_KEY
*
* @return zero on success or negative errno otherwise.
*
* @note currently supported only with VERITY devices.
*/
int crypt_keyslot_context_init_by_signed_key(struct crypt_device *cd,
const char *volume_key,
size_t volume_key_size,
const char *signature,
size_t signature_size,
struct crypt_keyslot_context **kc);
/**
* Initialize keyslot context via passphrase stored in a keyring.
*
* @param cd crypt device handle initialized to LUKS device context
*
* @param key_description kernel keyring key description library should look
* for passphrase in
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEYRING
*
* @return zero on success or negative errno otherwise.
*/
int crypt_keyslot_context_init_by_keyring(struct crypt_device *cd,
const char *key_description,
struct crypt_keyslot_context **kc);
/**
* Initialize keyslot context via volume key stored in a keyring.
*
* @param cd crypt device handle initialized to LUKS device context
*
* @param key_description kernel keyring key description library should look
* for passphrase in. The key can be passed either as number in ASCII,
* or a text representation in the form "%<key_type>:<key_name>"
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEYRING
*
* @return zero on success or negative errno otherwise.
*/
int crypt_keyslot_context_init_by_vk_in_keyring(struct crypt_device *cd,
const char *key_description,
struct crypt_keyslot_context **kc);
/**
* Get error code per keyslot context from last failed call.
*
* @note If @link crypt_keyslot_add_by_keyslot_context @endlink passed with
* no negative return code. The return value of this function is undefined.
*
* @param kc keyslot context involved in failed @link crypt_keyslot_add_by_keyslot_context @endlink
*
* @return Negative errno if keyslot context caused a failure, zero otherwise.
*/
int crypt_keyslot_context_get_error(struct crypt_keyslot_context *kc);
/**
* Set new pin to token based keyslot context.
*
* @note Use when @link crypt_keyslot_add_by_keyslot_context @endlink failed
* and token keyslot context returned -ENOANO error code via
* @link crypt_keyslot_context_get_error @endlink.
*
* @param cd crypt device handle initialized to LUKS2 device context
* @param pin passphrase (or PIN) to unlock token (may be binary data)
* @param pin_size size of @e pin
* @param kc LUKS2 keyslot context (only @link CRYPT_KC_TYPE_TOKEN @endlink is allowed)
*
* @return zero on success or negative errno otherwise
*/
int crypt_keyslot_context_set_pin(struct crypt_device *cd,
const char *pin, size_t pin_size,
struct crypt_keyslot_context *kc);
/**
* @defgroup crypt-keyslot-context-types Crypt keyslot context types
* @addtogroup crypt-keyslot-context-types
* @{
*/
/** keyslot context initialized by passphrase (@link crypt_keyslot_context_init_by_passphrase @endlink) */
#define CRYPT_KC_TYPE_PASSPHRASE INT16_C(1)
/** keyslot context initialized by keyfile (@link crypt_keyslot_context_init_by_keyfile @endlink) */
#define CRYPT_KC_TYPE_KEYFILE INT16_C(2)
/** keyslot context initialized by token (@link crypt_keyslot_context_init_by_token @endlink) */
#define CRYPT_KC_TYPE_TOKEN INT16_C(3)
/** keyslot context initialized by volume key or unbound key (@link crypt_keyslot_context_init_by_volume_key @endlink) */
#define CRYPT_KC_TYPE_KEY INT16_C(4)
/** keyslot context initialized by description of a keyring key
* (@link crypt_keyslot_context_init_by_keyring @endlink)
*/
#define CRYPT_KC_TYPE_KEYRING INT16_C(5)
/** keyslot context initialized by description of a keyring key containing the volume key
* (@link crypt_keyslot_context_init_by_vk_in_keyring @endlink)
*/
#define CRYPT_KC_TYPE_VK_KEYRING INT16_C(6)
/** keyslot context initialized by signed key (@link crypt_keyslot_context_init_by_signed_key @endlink) */
#define CRYPT_KC_TYPE_SIGNED_KEY INT16_C(7)
/** @} */
/**
* Get type identifier for crypt keyslot context.
*
* @param kc keyslot context
*
* @return crypt keyslot context type id (see @link crypt-keyslot-context-types @endlink) or negative errno otherwise.
*/
int crypt_keyslot_context_get_type(const struct crypt_keyslot_context *kc);
/** @} */
/**
* Add key slot by volume key provided by keyslot context (kc). New
* keyslot will be protected by passphrase provided by new keyslot context (new_kc).
* See @link crypt-keyslot-context @endlink for context initialization routines.
*
* @pre @e cd contains initialized and formatted LUKS device context.
*
* @param cd crypt device handle
* @param keyslot_existing existing keyslot or CRYPT_ANY_SLOT to get volume key from.
* @param kc keyslot context providing volume key.
* @param keyslot_new new keyslot or CRYPT_ANY_SLOT (first free number is used).
* @param new_kc keyslot context providing passphrase for new keyslot.
* @param flags key flags to set
*
* @return allocated key slot number or negative errno otherwise.
*
* @note new_kc can not be @e CRYPT_KC_TYPE_KEY type keyslot context.
*
* @note For kc parameter with type @e CRYPT_KC_TYPE_KEY the keyslot_existing
* parameter is ignored.
*
* @note in case there is no active LUKS keyslot to get existing volume key from, one of following must apply:
* @li @e cd must be device handle used in crypt_format() by current process (it holds reference to generated volume key)
* @li kc must be of @e CRYPT_KC_TYPE_KEY type with valid volume key.
*
* @note With CRYPT_VOLUME_KEY_NO_SEGMENT flag raised and kc of type @e CRYPT_KC_TYPE_KEY with @e volume_key set to @e NULL
* the new volume_key will be generated and stored in new keyslot. The keyslot will become unbound (unusable to
* dm-crypt device activation).
*
* @warning CRYPT_VOLUME_KEY_SET flag force updates volume key. It is @b not @b reencryption!
* By doing so you will most probably destroy your ciphertext data device. It's supposed
* to be used only in wrapped keys scheme for key refresh process where real (inner) volume
* key stays untouched. It may be involved on active @e keyslot which makes the (previously
* unbound) keyslot new regular keyslot.
*/
int crypt_keyslot_add_by_keyslot_context(struct crypt_device *cd,
int keyslot_existing,
struct crypt_keyslot_context *kc,
int keyslot_new,
struct crypt_keyslot_context *new_kc,
uint32_t flags);
/**
* Destroy (and disable) key slot.
*
@@ -1073,59 +1462,61 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
*/
/** device is read only */
#define CRYPT_ACTIVATE_READONLY (1 << 0)
#define CRYPT_ACTIVATE_READONLY (UINT32_C(1) << 0)
/** only reported for device without uuid */
#define CRYPT_ACTIVATE_NO_UUID (1 << 1)
#define CRYPT_ACTIVATE_NO_UUID (UINT32_C(1) << 1)
/** activate even if cannot grant exclusive access (DANGEROUS) */
#define CRYPT_ACTIVATE_SHARED (1 << 2)
#define CRYPT_ACTIVATE_SHARED (UINT32_C(1) << 2)
/** enable discards aka TRIM */
#define CRYPT_ACTIVATE_ALLOW_DISCARDS (1 << 3)
#define CRYPT_ACTIVATE_ALLOW_DISCARDS (UINT32_C(1) << 3)
/** skip global udev rules in activation ("private device"), input only */
#define CRYPT_ACTIVATE_PRIVATE (1 << 4)
#define CRYPT_ACTIVATE_PRIVATE (UINT32_C(1) << 4)
/** corruption detected (verity), output only */
#define CRYPT_ACTIVATE_CORRUPTED (1 << 5)
#define CRYPT_ACTIVATE_CORRUPTED (UINT32_C(1) << 5)
/** use same_cpu_crypt option for dm-crypt */
#define CRYPT_ACTIVATE_SAME_CPU_CRYPT (1 << 6)
#define CRYPT_ACTIVATE_SAME_CPU_CRYPT (UINT32_C(1) << 6)
/** use submit_from_crypt_cpus for dm-crypt */
#define CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS (1 << 7)
#define CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS (UINT32_C(1) << 7)
/** dm-verity: ignore_corruption flag - ignore corruption, log it only */
#define CRYPT_ACTIVATE_IGNORE_CORRUPTION (1 << 8)
#define CRYPT_ACTIVATE_IGNORE_CORRUPTION (UINT32_C(1) << 8)
/** dm-verity: restart_on_corruption flag - restart kernel on corruption */
#define CRYPT_ACTIVATE_RESTART_ON_CORRUPTION (1 << 9)
#define CRYPT_ACTIVATE_RESTART_ON_CORRUPTION (UINT32_C(1) << 9)
/** dm-verity: ignore_zero_blocks - do not verify zero blocks */
#define CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS (1 << 10)
#define CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS (UINT32_C(1) << 10)
/** key loaded in kernel keyring instead directly in dm-crypt */
#define CRYPT_ACTIVATE_KEYRING_KEY (1 << 11)
#define CRYPT_ACTIVATE_KEYRING_KEY (UINT32_C(1) << 11)
/** dm-integrity: direct writes, do not use journal */
#define CRYPT_ACTIVATE_NO_JOURNAL (1 << 12)
#define CRYPT_ACTIVATE_NO_JOURNAL (UINT32_C(1) << 12)
/** dm-integrity: recovery mode - no journal, no integrity checks */
#define CRYPT_ACTIVATE_RECOVERY (1 << 13)
#define CRYPT_ACTIVATE_RECOVERY (UINT32_C(1) << 13)
/** ignore persistently stored flags */
#define CRYPT_ACTIVATE_IGNORE_PERSISTENT (1 << 14)
#define CRYPT_ACTIVATE_IGNORE_PERSISTENT (UINT32_C(1) << 14)
/** dm-verity: check_at_most_once - check data blocks only the first time */
#define CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE (1 << 15)
#define CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE (UINT32_C(1) << 15)
/** allow activation check including unbound keyslots (keyslots without segments) */
#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (1 << 16)
#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (UINT32_C(1) << 16)
/** dm-integrity: activate automatic recalculation */
#define CRYPT_ACTIVATE_RECALCULATE (1 << 17)
#define CRYPT_ACTIVATE_RECALCULATE (UINT32_C(1) << 17)
/** reactivate existing and update flags, input only */
#define CRYPT_ACTIVATE_REFRESH (1 << 18)
#define CRYPT_ACTIVATE_REFRESH (UINT32_C(1) << 18)
/** Use global lock to serialize memory hard KDF on activation (OOM workaround) */
#define CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF (1 << 19)
#define CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF (UINT32_C(1) << 19)
/** dm-integrity: direct writes, use bitmap to track dirty sectors */
#define CRYPT_ACTIVATE_NO_JOURNAL_BITMAP (1 << 20)
#define CRYPT_ACTIVATE_NO_JOURNAL_BITMAP (UINT32_C(1) << 20)
/** device is suspended (key should be wiped from memory), output only */
#define CRYPT_ACTIVATE_SUSPENDED (1 << 21)
#define CRYPT_ACTIVATE_SUSPENDED (UINT32_C(1) << 21)
/** use IV sector counted in sector_size instead of default 512 bytes sectors */
#define CRYPT_ACTIVATE_IV_LARGE_SECTORS (1 << 22)
#define CRYPT_ACTIVATE_IV_LARGE_SECTORS (UINT32_C(1) << 22)
/** dm-verity: panic_on_corruption flag - panic kernel on corruption */
#define CRYPT_ACTIVATE_PANIC_ON_CORRUPTION (1 << 23)
#define CRYPT_ACTIVATE_PANIC_ON_CORRUPTION (UINT32_C(1) << 23)
/** dm-crypt: bypass internal workqueue and process read requests synchronously. */
#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (1 << 24)
#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (UINT32_C(1) << 24)
/** dm-crypt: bypass internal workqueue and process write requests synchronously. */
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (1 << 25)
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (UINT32_C(1) << 25)
/** dm-integrity: reset automatic recalculation */
#define CRYPT_ACTIVATE_RECALCULATE_RESET (1 << 26)
#define CRYPT_ACTIVATE_RECALCULATE_RESET (UINT32_C(1) << 26)
/** dm-verity: try to use tasklets */
#define CRYPT_ACTIVATE_TASKLETS (UINT32_C(1) << 27)
/**
* Active device runtime attributes
@@ -1174,11 +1565,13 @@ uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd,
* LUKS2 header requirements
*/
/** Unfinished offline reencryption */
#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (1 << 0)
#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (UINT32_C(1) << 0)
/** Online reencryption in-progress */
#define CRYPT_REQUIREMENT_ONLINE_REENCRYPT (1 << 1)
#define CRYPT_REQUIREMENT_ONLINE_REENCRYPT (UINT32_C(1) << 1)
/** Device configured with OPAL support */
#define CRYPT_REQUIREMENT_OPAL (UINT32_C(1) << 2)
/** unknown requirement in header (output only) */
#define CRYPT_REQUIREMENT_UNKNOWN (1 << 31)
#define CRYPT_REQUIREMENT_UNKNOWN (UINT32_C(1) << 31)
/**
* Persistent flags type
@@ -1230,6 +1623,38 @@ int crypt_persistent_flags_get(struct crypt_device *cd,
* @{
*/
/**
* Activate device or check using keyslot context. In some cases (device under
* reencryption), more than one keyslot context is required (e.g. one for the old
* volume key and one for the new volume key). The order of the keyslot
* contexts does not matter. When less keyslot contexts are supplied than
* required to unlock the device an -EPERM/-ENOKEY/TODO error code is returned
* and you should call the function again with more keyslot contexts.
*
* NOTE: the API at the moment works for one keyslot context only, the second
* keyslot context is just an API placeholder
*
* @param cd crypt device handle
* @param name name of device to create, if @e NULL only check passphrase
* @param keyslot requested keyslot to check or @e CRYPT_ANY_SLOT, keyslot is
* ignored for unlock methods not based on passphrase
* @param kc keyslot context providing volume key or passphrase.
* @param additional_keyslot requested additional keyslot to check or @e CRYPT_ANY_SLOT
* @param additional_kc keyslot context providing additional volume key or
* passphrase (e.g. old volume key for device under reencryption).
* @param flags activation flags
*
* @return unlocked key slot number for passphrase-based unlock, zero for other
* unlock methods (e.g. volume key context) or negative errno on error.
*/
int crypt_activate_by_keyslot_context(struct crypt_device *cd,
const char *name,
int keyslot,
struct crypt_keyslot_context *kc,
int additional_keyslot,
struct crypt_keyslot_context *additional_kc,
uint32_t flags);
/**
* Activate device or check passphrase.
*
@@ -1308,8 +1733,11 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
* @note For VERITY the volume key means root hash required for activation.
* Because kernel dm-verity is always read only, you have to provide
* CRYPT_ACTIVATE_READONLY flag always.
* @note For TCRYPT the volume key should be always NULL and because master
* key from decrypted header is used instead.
* @note For TCRYPT the volume key should be always NULL
* the key from decrypted header is used instead.
* @note For BITLK the name cannot be @e NULL checking volume key is not
* supported for BITLK, the device will be activated even if the
* provided key is not correct.
*/
int crypt_activate_by_volume_key(struct crypt_device *cd,
const char *name,
@@ -1365,11 +1793,11 @@ int crypt_activate_by_keyring(struct crypt_device *cd,
uint32_t flags);
/** lazy deactivation - remove once last user releases it */
#define CRYPT_DEACTIVATE_DEFERRED (1 << 0)
#define CRYPT_DEACTIVATE_DEFERRED (UINT32_C(1) << 0)
/** force deactivation - if the device is busy, it is replaced by error device */
#define CRYPT_DEACTIVATE_FORCE (1 << 1)
#define CRYPT_DEACTIVATE_FORCE (UINT32_C(1) << 1)
/** if set, remove lazy deactivation */
#define CRYPT_DEACTIVATE_DEFERRED_CANCEL (1 << 2)
#define CRYPT_DEACTIVATE_DEFERRED_CANCEL (UINT32_C(1) << 2)
/**
* Deactivate crypt device. This function tries to remove active device-mapper
@@ -1415,6 +1843,9 @@ int crypt_deactivate(struct crypt_device *cd, const char *name);
* @note For TCRYPT cipher chain is the volume key concatenated
* for all ciphers in chain.
* @note For VERITY the volume key means root hash used for activation.
* @note For LUKS devices, if passphrase is @e NULL and volume key is cached in
* device context it returns the volume key generated in preceding
* @link crypt_format @endlink call.
*/
int crypt_volume_key_get(struct crypt_device *cd,
int keyslot,
@@ -1423,6 +1854,41 @@ int crypt_volume_key_get(struct crypt_device *cd,
const char *passphrase,
size_t passphrase_size);
/**
* Get volume key from crypt device by keyslot context.
*
* @param cd crypt device handle
* @param keyslot use this keyslot or @e CRYPT_ANY_SLOT
* @param volume_key buffer for volume key
* @param volume_key_size on input, size of buffer @e volume_key,
* on output size of @e volume_key
* @param kc keyslot context used to unlock volume key
*
* @return unlocked key slot number or negative errno otherwise.
*
* @note See @link crypt-keyslot-context-types @endlink for info on keyslot
* context initialization.
* @note For TCRYPT cipher chain is the volume key concatenated
* for all ciphers in chain (kc may be NULL).
* @note For VERITY the volume key means root hash used for activation
* (kc may be NULL).
* @note For LUKS devices, if kc is @e NULL and volume key is cached in
* device context it returns the volume key generated in preceding
* @link crypt_format @endlink call.
* @note @link CRYPT_KC_TYPE_TOKEN @endlink keyslot context is usable only with LUKS2 devices.
* @note @link CRYPT_KC_TYPE_KEY @endlink keyslot context can not be used.
* @note To get LUKS2 unbound key, keyslot parameter must not be @e CRYPT_ANY_SLOT.
* @note EPERM errno means provided keyslot context could not unlock any (or selected)
* keyslot.
* @note ENOENT errno means no LUKS keyslot is available to retrieve volume key from
* and there's no cached volume key in device handle.
*/
int crypt_volume_key_get_by_keyslot_context(struct crypt_device *cd,
int keyslot,
char *volume_key,
size_t *volume_key_size,
struct crypt_keyslot_context *kc);
/**
* Verify that provided volume key is valid for crypt device.
*
@@ -1431,6 +1897,10 @@ int crypt_volume_key_get(struct crypt_device *cd,
* @param volume_key_size size of @e volume_key
*
* @return @e 0 on success or negative errno value otherwise.
*
* @note Negative EPERM return value means that passed volume_key
* did not pass digest verification routine (not a valid volume
* key).
*/
int crypt_volume_key_verify(struct crypt_device *cd,
const char *volume_key,
@@ -1923,7 +2393,7 @@ int crypt_keyfile_read(struct crypt_device *cd,
uint32_t flags);
/** Read key only to the first end of line (\\n). */
#define CRYPT_KEYFILE_STOP_EOL (1 << 0)
#define CRYPT_KEYFILE_STOP_EOL (UINT32_C(1) << 0)
/** @} */
/**
@@ -1937,7 +2407,7 @@ int crypt_keyfile_read(struct crypt_device *cd,
typedef enum {
CRYPT_WIPE_ZERO, /**< Fill with zeroes */
CRYPT_WIPE_RANDOM, /**< Use RNG to fill data */
CRYPT_WIPE_ENCRYPTED_ZERO, /**< Add encryption and fill with zeroes as plaintext */
CRYPT_WIPE_ENCRYPTED_ZERO, /**< Obsolete, same as CRYPT_WIPE_RANDOM */
CRYPT_WIPE_SPECIAL, /**< Compatibility only, do not use (Gutmann method) */
} crypt_wipe_pattern;
@@ -1973,7 +2443,37 @@ int crypt_wipe(struct crypt_device *cd,
);
/** Use direct-io */
#define CRYPT_WIPE_NO_DIRECT_IO (1 << 0)
#define CRYPT_WIPE_NO_DIRECT_IO (UINT32_C(1) << 0)
enum {
CRYPT_LUKS2_SEGMENT = -2,
CRYPT_NO_SEGMENT = -1,
};
/**
* Safe erase of a partition or an entire OPAL device. WARNING: ALL DATA ON
* PARTITION/DISK WILL BE LOST. If the CRYPT_NO_SEGMENT is passed as the segment
* parameter, the entire device will be wiped, not just what is included in the
* LUKS2 device/partition.
*
* @param cd crypt device handle
* @param segment the segment number to wipe (0..8), or CRYPT_LUKS2_SEGMENT
* to wipe the segment configured in the LUKS2 header, or CRYPT_NO_SEGMENT
* to wipe the entire device via a factory reset.
* @param password admin password/PSID (for factory reset) to wipe the
* partition/device
* @param password_size length of password/PSID
* @param flags (currently unused)
*
* @return @e 0 on success or negative errno value otherwise.
*/
int crypt_wipe_hw_opal(struct crypt_device *cd,
int segment, /* 0..8, CRYPT_LUKS2_SEGMENT -2, CRYPT_NO_SEGMENT -1 */
const char *password, /* Admin1 PIN or PSID */
size_t password_size,
uint32_t flags /* currently unused */
);
/** @} */
/**
@@ -2281,6 +2781,17 @@ int crypt_token_register(const crypt_token_handler *handler);
*/
const char *crypt_token_external_path(void);
/**
* Override configured external token handlers path for the library.
*
* @param path Absolute path (starts with '/') to new external token handlers directory or @e NULL.
*
* @note if @e path is @e NULL the external token path is reset to default path.
*
* @return @e 0 on success or negative errno value otherwise.
*/
int crypt_token_set_external_path(const char *path);
/**
* Disable external token handlers (plugins) support
* If disabled, it cannot be enabled again.
@@ -2390,13 +2901,16 @@ int crypt_activate_by_token_pin(struct crypt_device *cd,
*/
/** Initialize reencryption metadata but do not run reencryption yet. (in) */
#define CRYPT_REENCRYPT_INITIALIZE_ONLY (1 << 0)
/** Move the first segment, used only with data shift. (in/out) */
#define CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT (1 << 1)
#define CRYPT_REENCRYPT_INITIALIZE_ONLY (UINT32_C(1) << 0)
/** Move the first segment, used only with datashift resilience mode
* and subvariants. (in/out) */
#define CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT (UINT32_C(1) << 1)
/** Resume already initialized reencryption only. (in) */
#define CRYPT_REENCRYPT_RESUME_ONLY (1 << 2)
#define CRYPT_REENCRYPT_RESUME_ONLY (UINT32_C(1) << 2)
/** Run reencryption recovery only. (in) */
#define CRYPT_REENCRYPT_RECOVERY (1 << 3)
#define CRYPT_REENCRYPT_RECOVERY (UINT32_C(1) << 3)
/** Reencryption requires metadata protection. (in/out) */
#define CRYPT_REENCRYPT_REPAIR_NEEDED (UINT32_C(1) << 4)
/**
* Reencryption direction
@@ -2421,10 +2935,15 @@ typedef enum {
struct crypt_params_reencrypt {
crypt_reencrypt_mode_info mode; /**< Reencryption mode, immutable after first init. */
crypt_reencrypt_direction_info direction; /**< Reencryption direction, immutable after first init. */
const char *resilience; /**< Resilience mode: "none", "checksum", "journal" or "shift" (only "shift" is immutable after init) */
const char *resilience; /**< Resilience mode: "none", "checksum", "journal", "datashift",
"datashift-checksum" or "datashift-journal".
"datashift" mode is immutable, "datashift-" subvariant can be only
changed to other "datashift-" subvariant */
const char *hash; /**< Used hash for "checksum" resilience type, ignored otherwise. */
uint64_t data_shift; /**< Used in "shift" mode, must be non-zero, immutable after first init. */
uint64_t max_hotzone_size; /**< Exact hotzone size for "none" mode. Maximum hotzone size for "checksum" and "journal" modes. */
uint64_t data_shift; /**< Used in "datashift" mode (and subvariants), must be non-zero,
immutable after first init. */
uint64_t max_hotzone_size; /**< Maximum hotzone size (may be lowered by library). For "datashift-" subvariants
it is used to set size of moved segment (decryption only). */
uint64_t device_size; /**< Reencrypt only initial part of the data device. */
const struct crypt_params_luks2 *luks2; /**< LUKS2 parameters for the final reencryption volume.*/
uint32_t flags; /**< Reencryption flags. */
@@ -2582,6 +3101,58 @@ void crypt_safe_memzero(void *data, size_t size);
/** @} */
/**
* @defgroup crypt-keyring Kernel keyring manipulation
* @addtogroup crypt-keyring
* @{
*/
/**
* Link the volume key to the specified kernel keyring.
*
* The volume can have one or two keys. Normally, the device has one key.
* However if reencryption was started and not finished yet, the volume will
* have two volume keys (the new VK for the already reencrypted segment and old
* VK for the not yet reencrypted segment).
*
* The @e old_key_description argument is required only for
* devices that are in re-encryption and have two volume keys at the same time
* (old and new). You can set the @e old_key_description to NULL,
* but if you supply number of keys less than required, the function will
* return -EAGAIN. In that case you need to call the function again and set
* the missing key description. When supplying just one key description, make
* sure to supply it in the @e key_description.
*
* NOTE: the API at the moment works for one key description only, the second
* name is just an API placeholder
*
* @param cd crypt device handle
* @param key_description the key description of the volume key linked in desired keyring.
* @param old_key_description the key description of the old volume key linked in desired keyring
* (for devices in re-encryption).
* @param key_type_desc the key type used for the volume key. Currently only "user" and "logon" types are
* supported. if @e NULL is specified the default "user" type is applied.
* @param keyring_to_link_vk the keyring description of the keyring in which volume key should
* be linked, if @e NULL is specified, linking will be disabled.
*
* @note keyring_to_link_vk may be passed in various string formats:
* It can be kernel key numeric id of existing keyring written as a string,
* keyring name prefixed optionally be either "%:" or "%keyring:" substrings or keyctl
* special values for keyrings "@t", "@p", "@s" and so on. See keyctl(1) man page,
* section KEY IDENTIFIERS for more information. All other prefixes starting "%<type>:"
* are ignored.
*
* @note key_description "%<type>:" prefixes are ignored. Type is applied based on key_type parameter
* value.
*/
int crypt_set_keyring_to_link(struct crypt_device* cd,
const char* key_description,
const char* old_key_description,
const char* key_type_desc,
const char* keyring_to_link_vk);
/** @} */
#ifdef __cplusplus
}
#endif

View File

@@ -8,3 +8,4 @@ Description: cryptsetup library
Version: @LIBCRYPTSETUP_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lcryptsetup
Requires.private: @PKGMODULES@

View File

@@ -144,3 +144,39 @@ CRYPTSETUP_2.4 {
crypt_token_external_disable;
crypt_token_external_path;
} CRYPTSETUP_2.0;
CRYPTSETUP_2.5 {
global:
crypt_get_label;
crypt_get_subsystem;
crypt_resume_by_token_pin;
} CRYPTSETUP_2.4;
CRYPTSETUP_2.6 {
global:
crypt_keyslot_context_free;
crypt_keyslot_context_init_by_passphrase;
crypt_keyslot_context_init_by_keyfile;
crypt_keyslot_context_init_by_token;
crypt_keyslot_context_init_by_volume_key;
crypt_keyslot_context_get_error;
crypt_keyslot_context_set_pin;
crypt_keyslot_context_get_type;
crypt_keyslot_add_by_keyslot_context;
crypt_volume_key_get_by_keyslot_context;
} CRYPTSETUP_2.5;
CRYPTSETUP_2.7 {
global:
crypt_activate_by_keyslot_context;
crypt_format_luks2_opal;
crypt_get_hw_encryption_type;
crypt_get_hw_encryption_key_size;
crypt_keyslot_context_init_by_keyring;
crypt_keyslot_context_init_by_vk_in_keyring;
crypt_keyslot_context_init_by_signed_key;
crypt_resume_by_keyslot_context;
crypt_token_set_external_path;
crypt_set_keyring_to_link;
crypt_wipe_hw_opal;
} CRYPTSETUP_2.6;

View File

@@ -1,8 +1,8 @@
/*
* Definitions of common constant and generic macros fo libcryptsetup
* Definitions of common constant and generic macros of libcryptsetup
*
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,6 +25,9 @@
/* to silent gcc -Wcast-qual for const cast */
#define CONST_CAST(x) (x)(uintptr_t)
/* to silent clang -Wcast-align when working with byte arrays */
#define VOIDP_CAST(x) (x)(void*)
#define UNUSED(x) (void)(x)
#ifndef ARRAY_SIZE

View File

@@ -1,7 +1,7 @@
/*
* Helpers for defining versioned symbols
*
* Copyright (C) 2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2021-2023 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,7 +31,7 @@
* It's supposed to be used only with symbols that are exported in at least
* two versions simultaneously as follows:
*
* - the latest version is marked with _NEW variant and oll other compatible
* - the latest version is marked with _NEW variant and all other compatible
* symbols should be marked with _OLD variant
*
* Examples:
@@ -67,16 +67,14 @@
* under CRYPT_SYMBOL_EXPORT_OLD(int, crypt_func_X, ...) macro
*/
#ifdef __has_attribute
# if __has_attribute(symver)
# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
__attribute__((__symver__(#_public_sym _ver_str #_maj "." #_min)))
# endif
#if HAVE_ATTRIBUTE_SYMVER
# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
__attribute__((__symver__(#_public_sym _ver_str #_maj "." #_min)))
#endif
#if !defined(_CRYPT_SYMVER) && defined(__GNUC__)
#if !defined(_CRYPT_SYMVER) && (defined(__GNUC__) || defined(__clang__))
# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
asm(".symver " #_local_sym "," #_public_sym _ver_str #_maj "." #_min);
__asm__(".symver " #_local_sym "," #_public_sym _ver_str #_maj "." #_min);
#endif
#define _CRYPT_FUNC(_public_sym, _prefix_str, _maj, _min, _ret, ...) \

View File

@@ -3,8 +3,8 @@
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2021 Milan Broz
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,7 +31,6 @@
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h> /* for major, minor */
#endif
#include <assert.h>
#include "internal.h"
#define DM_CRYPT_TARGET "crypt"
@@ -47,6 +46,7 @@ static bool _dm_ioctl_checked = false;
static bool _dm_crypt_checked = false;
static bool _dm_verity_checked = false;
static bool _dm_integrity_checked = false;
static bool _dm_zero_checked = false;
static int _quiet_log = 0;
static uint32_t _dm_flags = 0;
@@ -204,6 +204,9 @@ static void _dm_set_verity_compat(struct crypt_device *cd,
if (_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch))
_dm_flags |= DM_VERITY_PANIC_CORRUPTION_SUPPORTED;
if (_dm_satisfies_version(1, 9, 0, verity_maj, verity_min, verity_patch))
_dm_flags |= DM_VERITY_TASKLETS_SUPPORTED;
_dm_verity_checked = true;
}
@@ -241,6 +244,20 @@ static void _dm_set_integrity_compat(struct crypt_device *cd,
_dm_integrity_checked = true;
}
static void _dm_set_zero_compat(struct crypt_device *cd,
unsigned zero_maj,
unsigned zero_min,
unsigned zero_patch)
{
if (_dm_zero_checked || zero_maj == 0)
return;
log_dbg(cd, "Detected dm-zero version %i.%i.%i.",
zero_maj, zero_min, zero_patch);
_dm_zero_checked = true;
}
/* We use this for loading target module */
static void _dm_check_target(dm_target_type target_type)
{
@@ -278,11 +295,12 @@ static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_typ
unsigned dm_maj, dm_min, dm_patch;
int r = 0;
if ((target_type == DM_CRYPT && _dm_crypt_checked) ||
if ((target_type == DM_CRYPT && _dm_crypt_checked) ||
(target_type == DM_VERITY && _dm_verity_checked) ||
(target_type == DM_INTEGRITY && _dm_integrity_checked) ||
(target_type == DM_LINEAR) || (target_type == DM_ZERO) ||
(_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked))
(target_type == DM_ZERO && _dm_zero_checked) ||
(target_type == DM_LINEAR) ||
(_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked))
return 1;
/* Shut up DM while checking */
@@ -331,8 +349,12 @@ static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_typ
_dm_set_integrity_compat(cd, (unsigned)target->version[0],
(unsigned)target->version[1],
(unsigned)target->version[2]);
} else if (!strcmp(DM_ZERO_TARGET, target->name)) {
_dm_set_zero_compat(cd, (unsigned)target->version[0],
(unsigned)target->version[1],
(unsigned)target->version[2]);
}
target = (struct dm_versions *)((char *) target + target->next);
target = VOIDP_CAST(struct dm_versions *)((char *) target + target->next);
} while (last_target != target);
r = 1;
@@ -355,13 +377,14 @@ int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags)
*flags = _dm_flags;
if (target == DM_UNKNOWN &&
_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked)
_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked)
return 0;
if ((target == DM_CRYPT && _dm_crypt_checked) ||
if ((target == DM_CRYPT && _dm_crypt_checked) ||
(target == DM_VERITY && _dm_verity_checked) ||
(target == DM_INTEGRITY && _dm_integrity_checked) ||
(target == DM_LINEAR) || (target == DM_ZERO)) /* nothing to check */
(target == DM_ZERO && _dm_zero_checked) ||
(target == DM_LINEAR)) /* nothing to check */
return 0;
return -ENODEV;
@@ -444,14 +467,6 @@ char *dm_device_name(const char *path)
return dm_device_path(NULL, major(st.st_rdev), minor(st.st_rdev));
}
static void hex_key(char *hexkey, size_t key_size, const char *key)
{
unsigned i;
for(i = 0; i < key_size; i++)
sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
}
static size_t int_log10(uint64_t x)
{
uint64_t r = 0;
@@ -460,27 +475,22 @@ static size_t int_log10(uint64_t x)
return r;
}
#define CLEN 64 /* 2*MAX_CIPHER_LEN */
#define CLENS "63" /* for sscanf length + '\0' */
#define CAPIL 144 /* should be enough to fit whole capi string */
#define CAPIS "143" /* for sscanf of crypto API string + 16 + \0 */
static int cipher_c2dm(const char *org_c, const char *org_i, unsigned tag_size,
static int cipher_dm2c(const char *org_c, const char *org_i, unsigned tag_size,
char *c_dm, int c_dm_size,
char *i_dm, int i_dm_size)
{
int c_size = 0, i_size = 0, i;
char cipher[CLEN], mode[CLEN], iv[CLEN+1], tmp[CLEN];
char capi[CAPIL];
char cipher[MAX_CAPI_ONE_LEN], mode[MAX_CAPI_ONE_LEN], iv[MAX_CAPI_ONE_LEN+1],
tmp[MAX_CAPI_ONE_LEN], capi[MAX_CAPI_LEN];
if (!c_dm || !c_dm_size || !i_dm || !i_dm_size)
return -EINVAL;
i = sscanf(org_c, "%" CLENS "[^-]-%" CLENS "s", cipher, tmp);
i = sscanf(org_c, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", cipher, tmp);
if (i != 2)
return -EINVAL;
i = sscanf(tmp, "%" CLENS "[^-]-%" CLENS "s", mode, iv);
i = sscanf(tmp, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", mode, iv);
if (i == 1) {
memset(iv, 0, sizeof(iv));
strncpy(iv, mode, sizeof(iv)-1);
@@ -527,75 +537,6 @@ static int cipher_c2dm(const char *org_c, const char *org_i, unsigned tag_size,
return 0;
}
static int cipher_dm2c(char **org_c, char **org_i, const char *c_dm, const char *i_dm)
{
char cipher[CLEN], mode[CLEN], iv[CLEN], auth[CLEN];
char tmp[CAPIL], dmcrypt_tmp[CAPIL*2], capi[CAPIL+1];
size_t len;
int i;
if (!c_dm)
return -EINVAL;
/* legacy mode */
if (strncmp(c_dm, "capi:", 4)) {
if (!(*org_c = strdup(c_dm)))
return -ENOMEM;
*org_i = NULL;
return 0;
}
/* modes with capi: prefix */
i = sscanf(c_dm, "capi:%" CAPIS "[^-]-%" CLENS "s", tmp, iv);
if (i != 2)
return -EINVAL;
len = strlen(tmp);
if (len < 2)
return -EINVAL;
if (tmp[len-1] == ')')
tmp[len-1] = '\0';
if (sscanf(tmp, "rfc4309(%" CAPIS "s", capi) == 1) {
if (!(*org_i = strdup("aead")))
return -ENOMEM;
} else if (sscanf(tmp, "rfc7539(%" CAPIS "[^,],%" CLENS "s", capi, auth) == 2) {
if (!(*org_i = strdup(auth)))
return -ENOMEM;
} else if (sscanf(tmp, "authenc(%" CLENS "[^,],%" CAPIS "s", auth, capi) == 2) {
if (!(*org_i = strdup(auth)))
return -ENOMEM;
} else {
if (i_dm) {
if (!(*org_i = strdup(i_dm)))
return -ENOMEM;
} else
*org_i = NULL;
memset(capi, 0, sizeof(capi));
strncpy(capi, tmp, sizeof(capi)-1);
}
i = sscanf(capi, "%" CLENS "[^(](%" CLENS "[^)])", mode, cipher);
if (i == 2)
i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv);
else
i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv);
if (i < 0 || (size_t)i >= sizeof(dmcrypt_tmp)) {
free(*org_i);
*org_i = NULL;
return -EINVAL;
}
if (!(*org_c = strdup(dmcrypt_tmp))) {
free(*org_i);
*org_i = NULL;
return -ENOMEM;
}
return 0;
}
static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u)
{
size_t r = snprintf(buf, buf_size, " %s:%u", s, u);
@@ -613,7 +554,7 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
if (!tgt)
return NULL;
r = cipher_c2dm(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size,
r = cipher_dm2c(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size,
cipher_dm, sizeof(cipher_dm), integrity_dm, sizeof(integrity_dm));
if (r < 0)
return NULL;
@@ -655,24 +596,21 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
null_cipher = 1;
if (null_cipher)
hexkey = crypt_safe_alloc(2);
hexkey = crypt_bytes_to_hex(0, NULL);
else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
keystr_len = strlen(tgt->u.crypt.vk->key_description) + int_log10(tgt->u.crypt.vk->keylength) + 10;
hexkey = crypt_safe_alloc(keystr_len);
} else
hexkey = crypt_safe_alloc(tgt->u.crypt.vk->keylength * 2 + 1);
if (!hexkey)
goto out;
if (null_cipher)
strncpy(hexkey, "-", 2);
else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description);
if (!hexkey)
goto out;
r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength,
tgt->u.crypt.vk->key_description);
if (r < 0 || r >= keystr_len)
goto out;
} else
hex_key(hexkey, tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key);
hexkey = crypt_bytes_to_hex(tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key);
if (!hexkey)
goto out;
max_size = strlen(hexkey) + strlen(cipher_dm) +
strlen(device_block_path(tgt->data_device)) +
@@ -725,6 +663,8 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
num_options++;
if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE)
num_options++;
if (flags & CRYPT_ACTIVATE_TASKLETS)
num_options++;
max_fec_size = (tgt->u.verity.fec_device ? strlen(device_block_path(tgt->u.verity.fec_device)) : 0) + 256;
fec_features = crypt_safe_alloc(max_fec_size);
@@ -755,30 +695,26 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
} else
*verity_verify_args = '\0';
if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 */
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s", num_options,
if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 + 22 */
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s", num_options,
(flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "",
(flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "",
(flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? " panic_on_corruption" : "",
(flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "",
(flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "");
(flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "",
(flags & CRYPT_ACTIVATE_TASKLETS) ? " try_verify_in_tasklet" : "");
if (r < 0 || (size_t)r >= sizeof(features))
goto out;
} else
*features = '\0';
hexroot = crypt_safe_alloc(tgt->u.verity.root_hash_size * 2 + 1);
hexroot = crypt_bytes_to_hex(tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
if (!hexroot)
goto out;
hex_key(hexroot, tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
hexsalt = crypt_safe_alloc(vp->salt_size ? vp->salt_size * 2 + 1 : 2);
hexsalt = crypt_bytes_to_hex(vp->salt_size, vp->salt);
if (!hexsalt)
goto out;
if (vp->salt_size)
hex_key(hexsalt, vp->salt_size, vp->salt);
else
strncpy(hexsalt, "-", 2);
max_size = strlen(hexroot) + strlen(hexsalt) +
strlen(device_block_path(tgt->data_device)) +
@@ -843,10 +779,9 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
num_options++;
if (tgt->u.integrity.vk) {
hexkey = crypt_safe_alloc(tgt->u.integrity.vk->keylength * 2 + 1);
hexkey = crypt_bytes_to_hex(tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
if (!hexkey)
goto out;
hex_key(hexkey, tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
} else
hexkey = NULL;
@@ -861,11 +796,10 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
num_options++;
if (tgt->u.integrity.journal_integrity_key) {
hexkey = crypt_safe_alloc(tgt->u.integrity.journal_integrity_key->keylength * 2 + 1);
hexkey = crypt_bytes_to_hex( tgt->u.integrity.journal_integrity_key->keylength,
tgt->u.integrity.journal_integrity_key->key);
if (!hexkey)
goto out;
hex_key(hexkey, tgt->u.integrity.journal_integrity_key->keylength,
tgt->u.integrity.journal_integrity_key->key);
} else
hexkey = NULL;
@@ -880,11 +814,10 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
num_options++;
if (tgt->u.integrity.journal_crypt_key) {
hexkey = crypt_safe_alloc(tgt->u.integrity.journal_crypt_key->keylength * 2 + 1);
hexkey = crypt_bytes_to_hex(tgt->u.integrity.journal_crypt_key->keylength,
tgt->u.integrity.journal_crypt_key->key);
if (!hexkey)
goto out;
hex_key(hexkey, tgt->u.integrity.journal_crypt_key->keylength,
tgt->u.integrity.journal_crypt_key->key);
} else
hexkey = NULL;
@@ -980,7 +913,7 @@ out:
return params_out;
}
static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags __attribute__((unused)))
static char *get_dm_linear_params(const struct dm_target *tgt)
{
char *params;
int r;
@@ -1001,7 +934,7 @@ static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags __
return params;
}
static char *get_dm_zero_params(const struct dm_target *tgt __attribute__((unused)), uint32_t flags __attribute__((unused)))
static char *get_dm_zero_params(void)
{
char *params = crypt_safe_alloc(1);
if (!params)
@@ -1263,8 +1196,7 @@ int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char
return r;
r_udev = r;
if (r_udev <= 0)
r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
return r == -ENOENT ? r_udev : r;
}
@@ -1328,9 +1260,9 @@ static int _create_dm_targets_params(struct crypt_dm_active_device *dmd)
else if (tgt->type == DM_INTEGRITY)
tgt->params = get_dm_integrity_params(tgt, dmd->flags);
else if (tgt->type == DM_LINEAR)
tgt->params = get_dm_linear_params(tgt, dmd->flags);
tgt->params = get_dm_linear_params(tgt);
else if (tgt->type == DM_ZERO)
tgt->params = get_dm_zero_params(tgt, dmd->flags);
tgt->params = get_dm_zero_params();
else {
r = -ENOTSUP;
goto err;
@@ -1399,7 +1331,15 @@ static int _dm_create_device(struct crypt_device *cd, const char *name, const ch
goto out;
if (!dm_task_run(dmt)) {
r = dm_status_device(cd, name);;
r = -dm_task_get_errno(dmt);
if (r == -ENOKEY || r == -EKEYREVOKED || r == -EKEYEXPIRED) {
/* propagate DM errors around key management as such */
r = -ENOKEY;
goto out;
}
r = dm_status_device(cd, name);
if (r >= 0)
r = -EEXIST;
if (r != -EEXIST && r != -ENODEV)
@@ -1576,6 +1516,9 @@ static void _dm_target_free_query_path(struct crypt_device *cd, struct dm_target
static void _dm_target_erase(struct crypt_device *cd, struct dm_target *tgt)
{
if (tgt->direction == TARGET_EMPTY)
return;
if (tgt->direction == TARGET_QUERY)
_dm_target_free_query_path(cd, tgt);
@@ -1667,16 +1610,99 @@ int dm_create_device(struct crypt_device *cd, const char *name,
return -ENOTSUP;
r = _dm_create_device(cd, name, type, dmd);
if (r < 0 && dm_flags(cd, dmd->segment.type, &dmt_flags))
if (!r || r == -EEXIST)
goto out;
if (r && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
if (dm_flags(cd, dmd->segment.type, &dmt_flags))
goto out;
if ((dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
check_retry(cd, &dmd->flags, dmt_flags)) {
log_dbg(cd, "Retrying open without incompatible options.");
r = _dm_create_device(cd, name, type, dmd);
if (!r || r == -EEXIST)
goto out;
}
if (dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
!(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) {
log_err(cd, _("Requested dm-crypt performance options are not supported."));
r = -EINVAL;
}
if (dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) &&
!(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
log_err(cd, _("Requested dm-crypt performance options are not supported."));
r = -EINVAL;
}
if (dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) &&
!(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED)) {
log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
r = -EINVAL;
}
if (dmd->flags & CRYPT_ACTIVATE_TASKLETS &&
!(dmt_flags & DM_VERITY_TASKLETS_SUPPORTED)) {
log_err(cd, _("Requested dm-verity tasklets option is not supported."));
r = -EINVAL;
}
if (dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION &&
!(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED)) {
log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
r = -EINVAL;
}
if (dmd->segment.type == DM_VERITY &&
dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED)) {
log_err(cd, _("Requested dm-verity FEC options are not supported."));
r = -EINVAL;
}
if (dmd->segment.type == DM_CRYPT) {
if (dmd->segment.u.crypt.integrity && !(dmt_flags & DM_INTEGRITY_SUPPORTED)) {
log_err(cd, _("Requested data integrity options are not supported."));
r = -EINVAL;
}
if (dmd->segment.u.crypt.sector_size != SECTOR_SIZE && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED)) {
log_err(cd, _("Requested sector_size option is not supported."));
r = -EINVAL;
}
if (dmd->segment.u.crypt.sector_size > SECTOR_SIZE &&
dmd->size % dmd->segment.u.crypt.sector_size) {
log_err(cd, _("The device size is not multiple of the requested sector size."));
r = -EINVAL;
}
}
if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
!(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED)) {
log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
r = -EINVAL;
}
if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE_RESET) &&
!(dmt_flags & DM_INTEGRITY_RESET_RECALC_SUPPORTED)) {
log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
r = -EINVAL;
}
if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED)) {
log_err(cd, _("Discard/TRIM is not supported."));
r = -EINVAL;
}
if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) &&
!(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED)) {
log_err(cd, _("Requested dm-integrity bitmap mode is not supported."));
r = -EINVAL;
}
out:
/*
* Print warning if activating dm-crypt cipher_null device unless it's reencryption helper or
* keyslot encryption helper device (LUKS1 cipher_null devices).
@@ -1685,54 +1711,6 @@ int dm_create_device(struct crypt_device *cd, const char *name,
crypt_is_cipher_null(dmd->segment.u.crypt.cipher))
log_dbg(cd, "Activated dm-crypt device with cipher_null. Device is not encrypted.");
if (r == -EINVAL &&
dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
!(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if (r == -EINVAL &&
dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) &&
!(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if (r == -EINVAL && dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) &&
!(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED))
log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
if (r == -EINVAL && dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION &&
!(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED))
log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
if (r == -EINVAL && dmd->segment.type == DM_VERITY &&
dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED))
log_err(cd, _("Requested dm-verity FEC options are not supported."));
if (r == -EINVAL && dmd->segment.type == DM_CRYPT) {
if (dmd->segment.u.crypt.integrity && !(dmt_flags & DM_INTEGRITY_SUPPORTED))
log_err(cd, _("Requested data integrity options are not supported."));
if (dmd->segment.u.crypt.sector_size != SECTOR_SIZE && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED))
log_err(cd, _("Requested sector_size option is not supported."));
}
if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
!(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED))
log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE_RESET) &&
!(dmt_flags & DM_INTEGRITY_RESET_RECALC_SUPPORTED))
log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
log_err(cd, _("Discard/TRIM is not supported."));
if (r == -EINVAL && dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) &&
!(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED))
log_err(cd, _("Requested dm-integrity bitmap mode is not supported."));
out:
dm_exit_context();
return r;
}
@@ -2027,9 +2005,7 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags,
/* cipher */
if (get_flags & DM_ACTIVE_CRYPT_CIPHER) {
r = cipher_dm2c(CONST_CAST(char**)&cipher,
CONST_CAST(char**)&integrity,
rcipher, rintegrity);
r = crypt_capi_to_cipher(&cipher, &integrity, rcipher, rintegrity);
if (r < 0)
goto err;
}
@@ -2262,6 +2238,8 @@ static int _dm_target_query_verity(struct crypt_device *cd,
*act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
else if (!strcasecmp(arg, "check_at_most_once"))
*act_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
else if (!strcasecmp(arg, "try_verify_in_tasklet"))
*act_flags |= CRYPT_ACTIVATE_TASKLETS;
else if (!strcasecmp(arg, "use_fec_from_device")) {
str = strsep(&params, " ");
str2 = crypt_lookup_dev(str);
@@ -2370,6 +2348,8 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
struct device *data_device = NULL, *meta_device = NULL;
char *integrity = NULL, *journal_crypt = NULL, *journal_integrity = NULL;
struct volume_key *vk = NULL;
struct volume_key *journal_integrity_key = NULL;
struct volume_key *journal_crypt_key = NULL;
tgt->type = DM_INTEGRITY;
tgt->direction = TARGET_QUERY;
@@ -2499,6 +2479,28 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
goto err;
}
}
if (str) {
len = crypt_hex_to_bytes(str, &str2, 1);
if (len < 0) {
r = len;
goto err;
}
r = 0;
if (get_flags & DM_ACTIVE_JOURNAL_CRYPT_KEY) {
journal_crypt_key = crypt_alloc_volume_key(len, str2);
if (!journal_crypt_key)
r = -ENOMEM;
} else if (get_flags & DM_ACTIVE_JOURNAL_CRYPT_KEYSIZE) {
journal_crypt_key = crypt_alloc_volume_key(len, NULL);
if (!journal_crypt_key)
r = -ENOMEM;
}
crypt_safe_free(str2);
if (r < 0)
goto err;
}
} else if (!strncmp(arg, "journal_mac:", 12) && !journal_integrity) {
str = &arg[12];
arg = strsep(&str, ":");
@@ -2509,6 +2511,28 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
goto err;
}
}
if (str) {
len = crypt_hex_to_bytes(str, &str2, 1);
if (len < 0) {
r = len;
goto err;
}
r = 0;
if (get_flags & DM_ACTIVE_JOURNAL_MAC_KEY) {
journal_integrity_key = crypt_alloc_volume_key(len, str2);
if (!journal_integrity_key)
r = -ENOMEM;
} else if (get_flags & DM_ACTIVE_JOURNAL_MAC_KEYSIZE) {
journal_integrity_key = crypt_alloc_volume_key(len, NULL);
if (!journal_integrity_key)
r = -ENOMEM;
}
crypt_safe_free(str2);
if (r < 0)
goto err;
}
} else if (!strcmp(arg, "recalculate")) {
*act_flags |= CRYPT_ACTIVATE_RECALCULATE;
} else if (!strcmp(arg, "reset_recalculate")) {
@@ -2544,6 +2568,10 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
tgt->u.integrity.journal_integrity = journal_integrity;
if (vk)
tgt->u.integrity.vk = vk;
if (journal_integrity_key)
tgt->u.integrity.journal_integrity_key = journal_integrity_key;
if (journal_crypt_key)
tgt->u.integrity.journal_crypt_key = journal_crypt_key;
return 0;
err:
device_free(cd, data_device);
@@ -2552,6 +2580,8 @@ err:
free(journal_crypt);
free(journal_integrity);
crypt_free_volume_key(vk);
crypt_free_volume_key(journal_integrity_key);
crypt_free_volume_key(journal_crypt_key);
return r;
}
@@ -2595,7 +2625,7 @@ err:
return r;
}
static int _dm_target_query_error(struct crypt_device *cd __attribute__((unused)), struct dm_target *tgt)
static int _dm_target_query_error(struct dm_target *tgt)
{
tgt->type = DM_ERROR;
tgt->direction = TARGET_QUERY;
@@ -2603,7 +2633,7 @@ static int _dm_target_query_error(struct crypt_device *cd __attribute__((unused)
return 0;
}
static int _dm_target_query_zero(struct crypt_device *cd __attribute__((unused)), struct dm_target *tgt)
static int _dm_target_query_zero(struct dm_target *tgt)
{
tgt->type = DM_ZERO;
tgt->direction = TARGET_QUERY;
@@ -2631,9 +2661,9 @@ static int dm_target_query(struct crypt_device *cd, struct dm_target *tgt, const
else if (!strcmp(target_type, DM_LINEAR_TARGET))
r = _dm_target_query_linear(cd, tgt, get_flags, params);
else if (!strcmp(target_type, DM_ERROR_TARGET))
r = _dm_target_query_error(cd, tgt);
r = _dm_target_query_error(tgt);
else if (!strcmp(target_type, DM_ZERO_TARGET))
r = _dm_target_query_zero(cd, tgt);
r = _dm_target_query_zero(tgt);
if (!r) {
tgt->offset = *start;
@@ -2681,7 +2711,7 @@ static int _dm_query_device(struct crypt_device *cd, const char *name,
goto out;
}
/* Never allow to return empty key */
/* Never allow one to return empty key */
if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi.suspended) {
log_dbg(cd, "Cannot read volume key while suspended.");
r = -EINVAL;
@@ -2763,7 +2793,8 @@ int dm_query_device(struct crypt_device *cd, const char *name,
return r;
}
static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps, char **names, size_t names_offset, size_t names_length)
static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps,
char **names, size_t names_offset, size_t names_length)
{
#if HAVE_DECL_DM_DEVICE_GET_NAME
struct crypt_dm_active_device dmd;
@@ -2809,7 +2840,8 @@ static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_
#endif
}
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix, char **names, size_t names_length)
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,
char **names, size_t names_length)
{
struct dm_task *dmt;
struct dm_info dmi;
@@ -2948,7 +2980,7 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
{
uint32_t dmt_flags;
int msg_size;
char *msg = NULL;
char *msg = NULL, *key = NULL;
int r = -ENOTSUP;
if (dm_init_context(cd, DM_CRYPT) || dm_flags(cd, DM_CRYPT, &dmt_flags))
@@ -2970,14 +3002,22 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
goto out;
}
strcpy(msg, "key set ");
if (!vk->keylength)
snprintf(msg + 8, msg_size - 8, "-");
else if (vk->key_description)
snprintf(msg + 8, msg_size - 8, ":%zu:logon:%s", vk->keylength, vk->key_description);
else
hex_key(&msg[8], vk->keylength, vk->key);
if (vk->key_description) {
r = snprintf(msg, msg_size, "key set :%zu:logon:%s", vk->keylength,
vk->key_description);
} else {
key = crypt_bytes_to_hex(vk->keylength, vk->key);
if (!key) {
r = -ENOMEM;
goto out;
}
r = snprintf(msg, msg_size, "key set %s", key);
}
if (r < 0 || r >= msg_size) {
r = -EINVAL;
goto out;
}
if (!_dm_message(name, msg) ||
_dm_resume_device(name, 0)) {
r = -EINVAL;
@@ -2986,6 +3026,7 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
r = 0;
out:
crypt_safe_free(msg);
crypt_safe_free(key);
dm_exit_context();
return r;
}
@@ -3000,6 +3041,18 @@ const char *dm_get_dir(void)
return dm_dir();
}
int dm_get_iname(const char *name, char **iname, bool with_path)
{
int r;
if (with_path)
r = asprintf(iname, "%s/%s_dif", dm_get_dir(), name);
else
r = asprintf(iname, "%s_dif", name);
return r < 0 ? -ENOMEM : 0;
}
int dm_is_dm_device(int major)
{
return dm_is_dm_major((uint32_t)major);

View File

@@ -1,8 +1,8 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 Milan Broz
* Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -1,8 +1,8 @@
/*
* loop-AES compatible volume handling
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2021 Milan Broz
* Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2023 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -2,7 +2,7 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefore supporting secure data destruction.
@@ -131,7 +131,7 @@ out:
return r;
}
int AF_merge(struct crypt_device *ctx __attribute__((unused)), const char *src, char *dst,
int AF_merge(const char *src, char *dst,
size_t blocksize, unsigned int blocknumbers, const char *hash)
{
unsigned int i;
@@ -142,7 +142,7 @@ int AF_merge(struct crypt_device *ctx __attribute__((unused)), const char *src,
if (!bufblock)
return -ENOMEM;
for(i = 0; i < blocknumbers - 1; i++) {
for (i = 0; i < blocknumbers - 1; i++) {
XORblock(src + blocksize * i, bufblock, bufblock, blocksize);
r = diffuse(bufblock, bufblock, blocksize, hash);
if (r < 0)

Some files were not shown because too many files have changed in this diff Show More