Compare commits

...

401 Commits

Author SHA1 Message Date
Milan Broz
30af820205 Version 2.7.2 final. 2024-04-09 12:03:57 +02:00
Milan Broz
84d3820a2f Add warning about OPAL admin PIN to man page and release notes. 2024-04-09 11:51:19 +02:00
Milan Broz
53044370e3 Version 2.7.2. 2024-04-08 22:46:47 +02:00
Milan Broz
29d13c4a45 Add 2.7.2 release notes. 2024-04-08 22:37:11 +02:00
Milan Broz
c0735f94c4 tests: print OPAL device parameters in test envirenment if specified 2024-04-08 22:37:02 +02:00
Daniel Zatovic
e15975d4ef CI: add WD PC SN740 OPAL drive job 2024-04-08 22:36:46 +02:00
Antonio Ceballos
7a9afb51ae po: update es.po (from translationproject.org) 2024-04-04 14:56:28 +02:00
Ondrej Kozina
95c7316860 Compile --disable-hw-opal variant. 2024-04-04 14:56:09 +02:00
Ondrej Kozina
29366ae05a Do not check passphrase quality in-before erase.
The passphrase (Admin PIN) already exists and there's no
reason to check quiality of it.
2024-04-04 14:55:56 +02:00
Milan Broz
e52e41d2f7 Relicense older script to LGPL fro GPL2.0 only.
(As I am sole author here.)
2024-04-04 14:55:42 +02:00
Milan Broz
5b10bcfbc4 FAQ: update license version to CC BY-SA 4.0.
With email approval from Arno Wagner dated March 29, 2024:

 From: Arno Wagner
 To: Milan Broz
 Subject: Re: cryuptsetup FAQ license

  Hi Milan,

  fine for me. You can change it directly.

  Arno

  On Wed, Mar 27, 2024 at 13:38:36 CET, Milan Broz wrote:
  > Hi Arno,
  >
  > the FAQ in cryptsetup is licensed under CC-BY-SA-3.0 that is no longer a recent version - https://creativecommons.org/licenses/by-sa/3.0/
  >
  > I use CC-BY-SA-4.0 (https://creativecommons.org/licenses/by-sa/4.0/deed.en) for LUKS2 docs and think it is the best option for docs.
  >
  > Do you agree with updating the license to CC-BY-SA-4.0 for the FAQ.md file? (I, as coauthor, obviously agree :-)
  >
  > Thanks,
  > Milan
2024-04-04 14:55:29 +02:00
Ondrej Kozina
daf6d7402a Fix invalid assert for hw-opal data segment keys.
hw-opal segment does not receive volume key for data
encryption, unlike crypt segment or hw-opal-crypt segment.
It gets key encryption key that is passed to device fw which
later unlocks the locking range key sealed in the device.

The assert may be skipped while volume key is not set.

Fixes: #875.
2024-04-04 14:55:12 +02:00
Ondrej Kozina
37ffd30d07 Fix data segment length compensation on misaligned partitions.
While properly calculated data segment needed compensation due to
misaligned partition (locking range had to be truncated),
we passed wrong value (original partition size) to LUKS2 metadata.

It has to use calculated locking range length in bytes.

Fixes: #873.
2024-04-04 14:54:51 +02:00
Daniel Zatovic
737d8495ad CI: make OPAL jobs uninterruptible 2024-04-04 14:54:36 +02:00
Ondrej Kozina
cde779ccd3 Add --hw-opal-factory-reset switch in erase options explicitly. 2024-04-04 14:54:18 +02:00
Ondrej Kozina
dddb2f7d3c Check HW OPAL range parameters in proper units.
The opal_range_check_attributes_fd function expected both
offset and length parameters of a LR to be passed in sectors (512B).
During format we passed it wrongly in OPAL blocks which caused
bogus check provided OPAL block size was not 512B.

Fixes: #871.
2024-04-04 14:54:02 +02:00
Daniel Zatovic
87fe3fb602 tests: run systemd tests using meson only when requested 2024-04-04 14:53:31 +02:00
Milan Broz
ca50f2cd33 Version 2.7.1. 2024-03-07 15:47:06 +01:00
Milan Broz
d5559df2cc tests: Fix Makefile * Meson to include all fs images. 2024-03-07 15:39:12 +01:00
Milan Broz
a2d820649b Update LUKS2 spec. 2024-03-07 15:27:52 +01:00
Milan Broz
94286c387f Add 2.7.1 release notes. 2024-03-07 15:27:44 +01:00
Milan Broz
2c53e71415 test: Fix tests on RHEL7 clones (no keyring in dm-crypt). 2024-03-07 14:26:46 +01:00
Milan Broz
2f0e804fd1 Add xfs V5 image to tests.
XFS V4 can be disabled in kernel, add image V5.

Minimal 300M xfs size avoided by using QA variables magic in format:
export TEST_DIR=1 TEST_DEV=1 QA_CHECK_FS=1 ; mkfs -t xfs ...
2024-03-07 14:26:34 +01:00
Ondrej Kozina
d478e09f2e tests: fix compat-test-opal bug for empty LUKS2 passphrase.
The bug was hidden due to previously contradicting condition.
2024-03-07 14:26:22 +01:00
Ondrej Kozina
0645219c9d tests: move luks1 decryption resume test.
It cannot be run in fips mode due to empty passphrase
is no longer allowed.
2024-03-07 14:26:09 +01:00
Ondrej Kozina
ba7973236b tests: fix fips mode detection contradiction in various tests. 2024-03-07 14:25:53 +01:00
Yuri Chornoivan
5d6bcc2c3b po: update uk.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Remus-Gabriel Chelu
05b16f73f9 po: update ro.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Jakub Bogusz
60274f1fcf po: update pl.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Hiroshi Takekawa
f8b4931bb1 po: update ja.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Frédéric Marchal
cb59aeb85a po: update fr.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Roland Illig
2f72f227b5 po: update de.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Petr Pisar
004419e1d6 po: update cs.po (from translationproject.org) 2024-03-06 09:53:01 +01:00
Ondrej Kozina
5c3dba8688 Add regression test for resuming LUKS1 decryption. 2024-03-06 09:52:55 +01:00
Ondrej Kozina
25e3adab7e Fix regression in LUKS1 decryption.
With removal of cryptsetup-reencrypt there was
a bug introduced that broke resuming interrupted
LUKS1 decryption operation. LUKS2 code was not
affected.
2024-03-06 09:52:44 +01:00
Milan Broz
bbdf692104 Set version 2.7.1-rc0. 2024-02-29 20:45:28 +01:00
Milan Broz
9d38ea70e2 Require --debug log in bug report issue template. 2024-02-29 17:07:41 +00:00
Milan Broz
2cd0be9501 Allow all stable branches in GitHub actions. 2024-02-29 17:07:41 +00:00
Ondrej Kozina
5a0208cd06 Allow --link-vk-to-keyring with --test-passphrase option.
To make it possible to upload volume key in user specified kernel
keyring without need to (re)activate the device.
2024-02-29 16:25:17 +01:00
Ondrej Kozina
db635c428b Fix abort triggered by initializing decryption via --active-name.
The invalid test unfortunately hid an error in processing
of --active-name command line option.
2024-02-28 17:11:46 +01:00
Milan Broz
678b28989b Fix indentation in integritysetup man page and crypt description. 2024-02-22 20:58:35 +00:00
Milan Broz
82f37d7a10 Sort options in man pages alphabetically. 2024-02-22 20:58:35 +00:00
Milan Broz
cbf818a660 Fix JSON exampe in progress-frequency option. 2024-02-22 20:58:35 +00:00
Milan Broz
3ff8d55a8b Fix veritysetup man page typo. 2024-02-22 20:58:35 +00:00
Sergei Ilinykh
349572e69e Fix compilation with libargon2 argon when internal disabled
This fixes a regression introduced somewhere on the way to 2.7.0.
A specific set of options led to complete lack of Argon2
regardless of --enable-libargon2 option.
2024-02-22 20:43:35 +03:00
Daniel Zatovic
0725efefa7 CI: fix improper distro specification for 32-bit Debian.
The `variables` section is repeated for 32-bit Debian job. Therefore the
`DISTRO` environment variable is ignored and 64-bit distro name is
inherited from the `.debian-prep` job.
2024-02-22 16:50:46 +01:00
Daniel Zatovic
af35c93332 CI: don't store kernel log, only check for coredumps.
The kernel log is uploaded automatically by the custom executor, no need
to upload it from inside the VM (and /mnt/artifacts is not mounted in
the new CI scripts).
2024-02-22 11:41:37 +00:00
Daniel Zatovic
193f8ff595 CI: increase disk size for csmock job. 2024-02-22 11:41:37 +00:00
Daniel Zatovic
f91524dc63 CI: add OPAL jobs. 2024-02-22 11:41:37 +00:00
Daniel Zatovic
f8e79cdbe6 CI: update jobs for new CI infrastrucure 2024-02-22 11:41:37 +00:00
Ondrej Kozina
35cd898c63 Fix crypto vectors test in meson.
Otherwise it gets skipped in meson everytime.
2024-02-21 15:56:14 +01:00
Tobias Rosenkranz
91c1d2202a Skip test if keyctl is missing 2024-02-18 14:46:37 +01:00
Milan Broz
a6d9dc0a16 Do not require argon2.h if implemented natively in crypto library. 2024-02-13 12:38:00 +01:00
Ondrej Kozina
f681194b57 Fix mistake in crypt_set_keyring_to_link documentation.
The keyring_to_link_vk parameter must be prefixed by
either "%:" or "%keyring:" substrings provided caller
opted for text description of the target keyring.
2024-02-13 11:40:13 +01:00
Ondrej Kozina
fdac0d7ee2 cryptsetup.spec: drop libargon2 in favour of openssl implementation. 2024-02-12 10:43:47 +00:00
Milan Broz
b417154e71 Fix configure Argon2 OpenSSL detection to not compile internal Argon2.
Code is not called anyway, but should be completely disabled.
Note: there is intentionally no way to disable OpenSSL Argon2 if present.
2024-02-09 12:51:34 +01:00
Milan Broz
4dde8f078f Version 2.7.0. 2024-01-24 10:47:32 +01:00
Milan Broz
f11af15cd0 Fix local variable name that hides global one.
Found by CodeQL.
2024-01-23 20:22:11 +01:00
Milan Broz
bd0ef58b3a Update copyright notice to include 2024 year. 2024-01-23 16:10:44 +01:00
Ondrej Kozina
cbc7253400 Unify error code for missing key description.
Use -ESRCH for similar error code as with
crypt_activate_by_keyslot_context. Here it's not
confliciting with previous use for the very code but
let's make it easier and use same code for similar case.
2024-01-23 12:08:43 +01:00
Ondrej Kozina
35ec935cc2 Update API documentation for crypt_set_keyring_to_link.
The section about placeholder API no longer applies.
2024-01-23 12:03:39 +01:00
Ondrej Kozina
7eca077490 Replace code for missing key error in API.
While trying to activate device in LUKS2 reencryption
we originally used -ENOKEY error code for case
where one or more volume keys could not be unlocked or
were not provided direclty by (CRYPT_KC_TYPE_KEY or
CRYPT_KC_TYPE_VK_KEYRING) keyslot contexts.

We missed the fact the error code was already previously
used for signaling case when dm subsystem could not load
device table due to key in kernel keyring could not be
read from kernel. It's propagated by libdevmapper.

For it we replace -ENOKEY with -ESRCH for signaling the missing
keyslot context or volume key for devices in LUKS2 reencryption.
2024-01-23 11:55:12 +01:00
Ondrej Kozina
8dd3266599 tests: use per-test keyring for caching VKs. 2024-01-22 17:28:19 +01:00
Ondrej Kozina
135ed491d1 Do not drop keys from keyring on successfull reencryption recovery.
The key might be needed in activation of ordinary LUKS2 device
provided the recovery took place in before device activation
and actually finished LUKS2 device reencryption.

Fixes: #863.
2024-01-22 12:13:40 +01:00
Milan Broz
de1cd97fde Fix typo in verity test. 2024-01-20 19:01:25 +01:00
Milan Broz
f040f74f46 Fix autoconf valgrind test.
All environment variables are predefined in make run,
use it in $(VAR) from, as shell variables processing does not work here.
2024-01-20 10:56:22 +01:00
Daniel Zatovic
136ba21c65 Add tests for device activation using multiple VKs. 2024-01-19 16:26:30 +00:00
Daniel Zatovic
7fb98caa79 Allow activating multi key devices using VKs in keyring.
We already support activation of a device using a volume key in keyring.
However, in case of multi-key devices (i.e. device with reencryption
running) we need to supply two volume keys.
2024-01-19 16:26:30 +00:00
Daniel Zatovic
4321992561 Add tests for storing VK in keyring during resume. 2024-01-19 16:26:30 +00:00
Daniel Zatovic
f354a0b038 Add tests for storing multiple VKs in a custom keyring. 2024-01-19 16:26:30 +00:00
Daniel Zatovic
5814b39cdd Allow linking multiple VKs (also in reencryption).
If the device is in reencryption, it has two active volume keys. Linking
the VK to keyring is not supported for such devices, because the API
only counts with one key. This commit modifies the API
crypt_set_keyring_to_link to allow passing multiple keyring key names.
2024-01-19 16:26:30 +00:00
Milan Broz
e0eb4dad95 Fix tests to support --disable-keyring option.
Also remove unused function in test.
2024-01-19 13:40:25 +00:00
Antonio Ceballos
0ba3e3077c po: update es.po (from translationproject.org) 2024-01-19 12:59:50 +01:00
Petr Pisar
dfe241dc24 po: update cs.po (from translationproject.org) 2024-01-19 12:59:50 +01:00
Milan Broz
001f228059 LUKS2: add more sanity assignments to header code.
Ensure we do not return partial binary header and also
explicitly set header size to zero to silnce stupid
cppcheck warnings.
2024-01-17 21:25:30 +01:00
Milan Broz
89ee1ed656 LUKS2: add sanity check for hdr_size.
Simplify code a little bit for static analysis and also
ensure that even second LUKS2 header with wrong hdr_size is
always detected.
2024-01-17 21:25:27 +01:00
Milan Broz
cac3184da3 Add a few tainted data info for coverity to avoid warnings.
If sysconf is lying, then anything can happen.
But check for overflow anyway.

Device/partition offset overflow for IV can only cause
bad decryption (expected).
2024-01-17 21:25:00 +01:00
Milan Broz
b048a417b7 Silence false positive cppcheck warning. 2024-01-17 12:20:00 +01:00
Milan Broz
cfdb1b93af Fix signed (error) return from read in loop utils. 2024-01-17 12:19:55 +01:00
Milan Broz
d15447814a Use gcc 13 for GitHub actions. 2024-01-17 12:19:48 +01:00
Ondrej Kozina
912d410458 Fix some grammar issues suggested by auto-correction tools. 2024-01-16 09:55:06 +00:00
Ondrej Kozina
d730f45201 Update kernel keyring usage documentation. 2024-01-16 09:55:06 +00:00
Ondrej Kozina
605acab31a Fix some grammar issues suggested by auto-correction tools. 2024-01-15 12:30:32 +01:00
Ondrej Kozina
ebca40640d docs: Describe additional LUKS2 locks. 2024-01-15 12:22:43 +01:00
Ondrej Kozina
a50a39a192 tests: add in-place LUKS2 encryption api test.
Simple test for plaintext data placed at specified offset
(non zero offset relative to head of data device).
2024-01-05 14:22:07 +01:00
Ondrej Kozina
adc83f6dca tests: add helper for creating arbitrary linear mapping. 2024-01-05 14:22:07 +01:00
Ondrej Kozina
bd0768a42a Respect CRYPT_ACTIVATE_SHARED in reencryption. 2024-01-05 14:22:07 +01:00
Yuri Chornoivan
543d220bd4 po: update uk.po (from translationproject.org) 2024-01-05 09:48:54 +01:00
Remus-Gabriel Chelu
44490e3ee1 po: update ro.po (from translationproject.org) 2024-01-05 09:48:54 +01:00
Jakub Bogusz
4b2015eafd po: update pl.po (from translationproject.org) 2024-01-05 09:48:54 +01:00
Hiroshi Takekawa
65005b4cd3 po: update ja.po (from translationproject.org) 2024-01-05 09:48:54 +01:00
Frédéric Marchal
fae0d2c1f2 po: update fr.po (from translationproject.org) 2024-01-05 09:48:54 +01:00
Roland Illig
2c16a80113 po: update de.po (from translationproject.org) 2024-01-05 09:48:54 +01:00
Milan Broz
44c6a76b09 Add note for luksSuspend to man page.
It should not be expected that suspend operation wipes
possible plaintext data from memory.

Related: #855
2023-12-22 12:17:55 +01:00
Milan Broz
37a2750e4f Update cryptsetup.spec. 2023-12-20 18:25:51 +01:00
Krassy Boykinov
b5006a5404 man: Update authenticated encryption trim description and add references
790666ff (Add support for allow_discrads for dm-integrity., 2020-04-09)
added TRIM support for standalone dm-integrity volumes.
This change is now reflected in the cryptsetup(8) man page.
2023-12-20 14:56:08 +00:00
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
268 changed files with 37498 additions and 12728 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

@@ -7,7 +7,7 @@ PACKAGES=(
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
asciidoctor meson ninja-build
)
COMPILER="${COMPILER:?}"

View File

@@ -4,8 +4,7 @@ on:
branches:
- 'main'
- 'wip-luks2'
- 'v2.3.x'
- 'v2.4.x'
- 'v2.*.x'
paths-ignore:
- 'docs/**'
@@ -17,7 +16,7 @@ jobs:
fail-fast: false
matrix:
env:
- { COMPILER: "gcc", COMPILER_VERSION: "11", RUN_SSH_PLUGIN_TEST: "1" }
- { COMPILER: "gcc", COMPILER_VERSION: "13", RUN_SSH_PLUGIN_TEST: "1" }
env: ${{ matrix.env }}
steps:
- name: Repository checkout

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

@@ -0,0 +1,49 @@
name: "CodeQL"
on:
push:
branches:
- 'main'
- 'wip-luks2'
- 'v2.*.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: "13", RUN_SSH_PLUGIN_TEST: "1" }
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -17,7 +17,7 @@ jobs:
run: sudo -E .github/workflows/cibuild-setup-ubuntu.sh
env:
COMPILER: "gcc"
COMPILER_VERSION: "11"
COMPILER_VERSION: "13"
- name: Install Coverity
run: |
wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=mbroz/cryptsetup" -O cov-analysis-linux64.tar.gz

View File

@@ -1,22 +1,22 @@
stages:
- test
.dump_kernel_log:
.fail_if_coredump_generated:
after_script:
- sudo dmesg > /mnt/artifacts/dmesg.log
- sudo journalctl > /mnt/artifacts/journalctl.log
- '[ "$(ls -A /var/coredumps)" ] && exit 1 || true'
include:
- local: .gitlab/ci/debian.yml
- local: .gitlab/ci/fedora.yml
- local: .gitlab/ci/fedora-opal.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/debian-i686.yml
- local: .gitlab/ci/cifuzz.yml

View File

@@ -1,12 +1,12 @@
.alpinelinux-dependencies:
after_script:
- sudo dmesg > /mnt/artifacts/dmesg.log
- sudo cp /var/log/messages /mnt/artifacts/
- '[ "$(ls -A /var/coredumps)" ] && exit 1 || true'
variables:
DISTRO: cryptsetup-alpine-edge
extends:
- .fail_if_coredump_generated
before_script:
- >
sudo apk add
lvm2-dev openssl1.1-compat-dev popt-dev util-linux-dev json-c-dev
lvm2-dev openssl-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
@@ -17,7 +17,7 @@ test-main-commit-job-alpinelinux:
- .alpinelinux-dependencies
tags:
- libvirt
- alpinelinux
- cryptsetup-alpine-edge
stage: test
interruptible: true
variables:
@@ -38,7 +38,7 @@ test-mergerq-job-alpinelinux:
- .alpinelinux-dependencies
tags:
- libvirt
- alpinelinux
- cryptsetup-alpine-edge
stage: test
interruptible: true
variables:

View File

@@ -1,19 +1,18 @@
test-main-commit-job-annocheck:
extends:
- .dump_kernel_log
- .fail_if_coredump_generated
tags:
- libvirt
- rhel9-annocheck
- cryptsetup-rhel-9
stage: test
interruptible: true
allow_failure: true
variables:
DISTRO: cryptsetup-rhel-9
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:
- /opt/build-rpm-script.sh > /dev/null 2>&1
- annocheck /var/lib/mock/rhel-9.0.0-candidate-x86_64/result/*.rpm --profile=el9
- annocheck /var/lib/mock/rhel-9.0.0-candidate-x86_64/result/*.rpm --profile=el8
- sudo /opt/run-annocheck.sh

View File

@@ -1,6 +1,8 @@
.centos-openssl-backend:
variables:
DISTRO: cryptsetup-centos-stream-9
extends:
- .dump_kernel_log
- .fail_if_coredump_generated
before_script:
- >
sudo dnf -y -q install
@@ -21,7 +23,7 @@ test-main-commit-centos-stream9:
- .centos-openssl-backend
tags:
- libvirt
- centos-stream9
- cryptsetup-centos-stream-9
stage: test
interruptible: true
variables:
@@ -42,7 +44,7 @@ test-mergerq-centos-stream9:
- .centos-openssl-backend
tags:
- libvirt
- centos-stream9
- cryptsetup-centos-stream-9
stage: test
interruptible: true
variables:

View File

@@ -6,8 +6,8 @@ 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 passwd openssh-client sshpass
asciidoctor
sharutils dmsetup jq xxd expect keyutils netcat-openbsd passwd openssh-client
sshpass asciidoctor
)
COMPILER="${COMPILER:?}"

View File

@@ -25,10 +25,9 @@ EXTRA="\
-Wswitch \
-Wmissing-format-attribute \
-Winit-self \
-Wdeclaration-after-statement \
-Wold-style-definition \
-Wno-missing-field-initializers \
-Wno-unused-parameter \
-Wunused-parameter \
-Wno-long-long"
exec $CLANG $PEDANTIC $CONVERSION \

View File

@@ -3,6 +3,7 @@ test-clang-compilation:
- .gitlab-shared-clang
script:
- export CFLAGS="-Wall -Werror"
- ./autogen.sh
- ./configure
- make -j
- make -j check-programs
@@ -13,6 +14,7 @@ test-clang-Wall-script:
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
@@ -21,6 +23,7 @@ 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

View File

@@ -3,6 +3,7 @@ test-gcc-compilation:
- .gitlab-shared-gcc
script:
- export CFLAGS="-Wall -Werror"
- ./autogen.sh
- ./configure
- make -j
- make -j check-programs
@@ -13,6 +14,7 @@ test-gcc-Wall-script:
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
@@ -22,6 +24,7 @@ test-gcc-fanalyzer:
- .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,33 @@
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",
"hw-opal"
]
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

View File

@@ -1,17 +1,25 @@
test-commit-job-csmock:
extends:
- .dump_kernel_log
- .fail_if_coredump_generated
tags:
- libvirt
- rhel7-csmock
- cryptsetup-rhel-9
stage: test
interruptible: true
allow_failure: true
variables:
DISTRO: cryptsetup-rhel-9
RUN_SSH_PLUGIN_TEST: "1"
DISK_SIZE: 20
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:
- /opt/csmock-run-script.sh
- 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

View File

@@ -1,12 +1,13 @@
test-mergerq-job-ubuntu-32bit:
test-mergerq-job-debian-i686:
extends:
- .debian-prep
tags:
- libvirt
- ubuntu-bionic-32bit
- cryptsetup-debian-12i686
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-12i686
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
@@ -19,15 +20,16 @@ test-mergerq-job-ubuntu-32bit:
- make -j -C tests check-programs
- sudo -E make check
test-main-commit-job-ubuntu-32bit:
test-main-commit-job-debian-i686:
extends:
- .debian-prep
tags:
- libvirt
- ubuntu-bionic-32bit
- cryptsetup-debian-12i686
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-12i686
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null

View File

@@ -1,17 +1,18 @@
.debian-prep:
extends:
- .dump_kernel_log
- .fail_if_coredump_generated
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 tpm2-tss-engine-dev libmount-dev swtpm-tools
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 passwd openssh-client sshpass asciidoctor
tar libargon2-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
@@ -22,10 +23,11 @@ test-mergerq-job-debian:
- .debian-prep
tags:
- libvirt
- debian11
- cryptsetup-debian-12
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-12
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
@@ -41,10 +43,11 @@ test-main-commit-job-debian:
- .debian-prep
tags:
- libvirt
- debian11
- cryptsetup-debian-12
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-12
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
@@ -54,3 +57,46 @@ test-main-commit-job-debian:
- make -j
- make -j -C tests check-programs
- sudo -E make check
# meson tests
test-mergerq-job-debian-meson:
extends:
- .debian-prep
tags:
- libvirt
- cryptsetup-debian-12
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-12
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
- cryptsetup-debian-12
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-12
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

134
.gitlab/ci/fedora-opal.yml Normal file
View File

@@ -0,0 +1,134 @@
.dnf-openssl-backend:
variables:
DISTRO: cryptsetup-fedora-rawhide
extends:
- .fail_if_coredump_generated
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
.opal-template-fedora:
extends:
- .dnf-openssl-backend
tags:
- libvirt
- cryptsetup-fedora-rawhide
stage: test
interruptible: false
variables:
OPAL2_DEV: "/dev/nvme0n1"
OPAL2_PSID_FILE: "/home/gitlab-runner/psid.txt"
VOLATILE: 1
script:
- sudo dnf install -y -q nvme-cli
- sudo nvme list
- make -j
- make -j -C tests check-programs
- sudo -E make check TESTS="00modules-test compat-test-opal"
# Samsung SSD 980 500GB (on tiber machine)
test-commit-rawhide-samsung980:
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
extends:
- .opal-template-fedora
tags:
- tiber
stage: test
interruptible: false
variables:
PCI_PASSTHROUGH_VENDOR_ID: "144d"
PCI_PASSTHROUGH_DEVICE_ID: "a809"
test-mergerq-rawhide-samsung980:
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
extends:
- .opal-template-fedora
tags:
- tiber
stage: test
interruptible: false
variables:
PCI_PASSTHROUGH_VENDOR_ID: "144d"
PCI_PASSTHROUGH_DEVICE_ID: "a809"
# WD PC SN740 SDDQNQD-512G-1014 (on tiber machine)
test-commit-rawhide-sn740:
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
extends:
- .opal-template-fedora
tags:
- tiber
stage: test
interruptible: false
variables:
PCI_PASSTHROUGH_VENDOR_ID: "15b7"
PCI_PASSTHROUGH_DEVICE_ID: "5017"
test-mergerq-rawhide-sn740:
rules:
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
extends:
- .opal-template-fedora
tags:
- tiber
stage: test
interruptible: false
variables:
PCI_PASSTHROUGH_VENDOR_ID: "15b7"
PCI_PASSTHROUGH_DEVICE_ID: "5017"
# # UMIS RPETJ256MGE2MDQ (on tiber machine)
# test-commit-rawhide-umis:
# rules:
# - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
# when: never
# - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
# extends:
# - .opal-template-fedora
# tags:
# - tiber
# stage: test
# interruptible: false
# variables:
# PCI_PASSTHROUGH_VENDOR_ID: "1cc4"
# PCI_PASSTHROUGH_DEVICE_ID: "6302"
#
# test-mergerq-rawhide-umis:
# rules:
# - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
# when: never
# - if: $CI_PIPELINE_SOURCE == "merge_request_event"
# extends:
# - .opal-template-fedora
# tags:
# - tiber
# stage: test
# interruptible: false
# variables:
# PCI_PASSTHROUGH_VENDOR_ID: "1cc4"
# PCI_PASSTHROUGH_DEVICE_ID: "6302"

View File

@@ -1,6 +1,8 @@
.dnf-openssl-backend:
variables:
DISTRO: cryptsetup-fedora-rawhide
extends:
- .dump_kernel_log
- .fail_if_coredump_generated
before_script:
- >
[ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] ||
@@ -24,7 +26,7 @@ test-main-commit-job-rawhide:
- .dnf-openssl-backend
tags:
- libvirt
- fedora-rawhide
- cryptsetup-fedora-rawhide
stage: test
interruptible: true
allow_failure: true
@@ -44,7 +46,7 @@ test-mergerq-job-rawhide:
- .dnf-openssl-backend
tags:
- libvirt
- fedora-rawhide
- cryptsetup-fedora-rawhide
stage: test
interruptible: true
allow_failure: true

View File

@@ -31,7 +31,7 @@ EXTRA="-Wextra \
-Wunsafe-loop-optimizations \
-Wold-style-definition \
-Wno-missing-field-initializers \
-Wno-unused-parameter \
-Wunused-parameter \
-Wno-long-long \
-Wmaybe-uninitialized \
-Wvla \

View File

@@ -1,5 +1,5 @@
.gitlab-shared-docker:
image: ubuntu:focal
image: ubuntu:lunar
tags:
- gitlab-org-docker
stage: test
@@ -12,7 +12,6 @@
- .gitlab/ci/cibuild-setup-ubuntu.sh
- export CC="${COMPILER}${COMPILER_VERSION:+-$COMPILER_VERSION}"
- export CXX="${COMPILER}++${COMPILER_VERSION:+-$COMPILER_VERSION}"
- ./autogen.sh
.gitlab-shared-gcc:
extends:
@@ -27,5 +26,5 @@
- .gitlab-shared-docker
variables:
COMPILER: "clang"
COMPILER_VERSION: "13"
COMPILER_VERSION: "17"
RUN_SSH_PLUGIN_TEST: "1"

View File

@@ -1,6 +1,6 @@
.rhel-openssl-backend:
extends:
- .dump_kernel_log
- .fail_if_coredump_generated
before_script:
- >
sudo yum -y -q install
@@ -21,10 +21,11 @@ test-main-commit-rhel8:
- .rhel-openssl-backend
tags:
- libvirt
- rhel8
- cryptsetup-rhel-8
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-rhel-8
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
@@ -42,10 +43,11 @@ test-main-commit-rhel9:
- .rhel-openssl-backend
tags:
- libvirt
- rhel9
- cryptsetup-rhel-9
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-rhel-9
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
@@ -65,10 +67,11 @@ test-main-commit-rhel8-fips:
- .rhel-openssl-backend
tags:
- libvirt
- rhel8-fips
- cryptsetup-rhel-8-fips
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-rhel-8-fips
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null
@@ -87,11 +90,12 @@ test-main-commit-rhel9-fips:
- .rhel-openssl-backend
tags:
- libvirt
- rhel9-fips
- cryptsetup-rhel-9-fips
stage: test
interruptible: true
allow_failure: true
variables:
DISTRO: cryptsetup-rhel-9-fips
RUN_SSH_PLUGIN_TEST: "1"
rules:
- if: $RUN_SYSTEMD_PLUGIN_TEST != null

View File

@@ -9,7 +9,10 @@
### Debug log
<!-- Paste a debug log of the failing command (add --debug option) between the markers below (to keep raw debug format).-->
<!-- We need a lot of information from the debug log; without it, we cannot process your report. -->
<!-- Debug log does not contain any private information. Do not paste private data; we'll ask you for more information if needed. -->
```
Output with --debug option:
```
<!-- NOTE: WITHOUT DEBUG LOG, THE BUG REPORT WILL BE CLOSED. ALSO, PLEASE DO NOT TRY TO REMOVE PARTS OF THE DEBUG LOG! -->

View File

@@ -1,11 +0,0 @@
queries:
- exclude: cpp/fixme-comment
- exclude: cpp/empty-block
# symver attribute detection cannot be used, disable it for lgtm
extraction:
cpp:
configure:
command:
- "./autogen.sh"
- "./configure --enable-external-tokens --enable-ssh-token"
- "echo \"#undef HAVE_ATTRIBUTE_SYMVER\" >> config.h"

15
FAQ.md
View File

@@ -169,17 +169,12 @@
me write the section. Please note that by contributing to this FAQ,
you accept the license described below.
This work is under the "Attribution-Share Alike 3.0 Unported" license,
which means distribution is unlimited, you may create derived works, but
This work is licensed under a Creative Commons CC-BY-SA-4.0
"Attribution-ShareAlike 4.0 International" license which means
distribution is unlimited, you may create derived works, but
attributions to original authors and this license statement must be
retained and the derived work must be under the same license. See
https://creativecommons.org/licenses/by-sa/3.0/ for more details of the
license.
Side note: I did text license research some time ago and I think this
license is best suited for the purpose at hand and creates the least
problems.
retained and the derived work must be under the same license.
See https://creativecommons.org/licenses/by-sa/4.0/ for more details.
* **1.6 Where is the project website?**

View File

@@ -1,4 +1,17 @@
EXTRA_DIST = README.md COPYING.LGPL FAQ.md docs misc autogen.sh
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 =

165
README.md
View File

@@ -2,115 +2,144 @@
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), **BitLocker** and **FileVault2** 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 release version is 2.6.0**
* [cryptsetup-2.6.0.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.0.tar.xz)
* Signature [cryptsetup-2.6.0.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.0.tar.sign)
**The latest stable cryptsetup release version is 2.7.2**
* [cryptsetup-2.7.2.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.7/cryptsetup-2.7.2.tar.xz)
* Signature [cryptsetup-2.7.2.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.7/cryptsetup-2.7.2.tar.sign)
_(You need to decompress file first to check signature.)_
* [Cryptsetup 2.6.0 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/v2.6.0-ReleaseNotes).
* [Cryptsetup 2.7.2 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.7/v2.7.2-ReleaseNotes).
Previous versions
* [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) -
* [Version 2.6.1](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.1.tar.xz) -
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.1.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 yourself, some packages are required for compilation. Please always prefer distro specific build tools to manually configuring cryptsetup.
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 needed files for compilation. If you check it from the git snapshot, use ``./autogen.sh && ./configure && make`` to compile the project. If you use downloaded released ``*.tar.xz`` archive, the configure script is already pre-generated (no need to run ``autoconf.sh``).
See ``./configure --help`` and use ``--disable-*`` and ``--enable-*`` options.
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.
For running the test suite that come with the project, type ``make check``.
Note that most tests will need root user privileges and run many dangerous storage fail simulations.
Do **not** run tests with root privilege on production systems! Some tests will need scsi_debug kernel module to be available.
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 [automake](https://www.gnu.org/software/automake/manual/automake.html) and [autoconf](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf.html) manuals.
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 mail to [cryptsetup+subscribe@lists.linux.dev](mailto:cryptsetup+subscribe@lists.linux.dev).
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).
You can also browse and/or search the mailing [list archive](https://lore.kernel.org/cryptsetup/).
News (NNTP), Atom feed and git access to public inbox is available through [lore.kernel.org](https://lore.kernel.org) service.
USEnet News (NNTP), Atom feed and git access to the public inbox is available through
[lore.kernel.org](https://lore.kernel.org) service.
The former dm-crypt [list archive](https://lore.kernel.org/dm-crypt/) is also available.
The former **dm-crypt** [list archive](https://lore.kernel.org/dm-crypt/) is also available.

View File

@@ -1,9 +1,9 @@
AC_PREREQ([2.67])
AC_INIT([cryptsetup],[2.6.0])
AC_INIT([cryptsetup],[2.7.2])
dnl library version from <major>.<minor>.<release>[-<suffix>]
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
LIBCRYPTSETUP_VERSION_INFO=21:0:9
LIBCRYPTSETUP_VERSION_INFO=22:0:10
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(src/cryptsetup.c)
@@ -128,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
@@ -267,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],[
@@ -290,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
@@ -310,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], [use_internal_argon2=0], [], [#include <openssl/core_names.h>])
LIBS=$saved_LIBS
])
AC_DEFUN([CONFIGURE_NSS], [
@@ -343,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([])
])
@@ -353,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([])
])
@@ -369,6 +396,7 @@ AC_DEFUN([CONFIGURE_NETTLE], [
CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
use_internal_pbkdf2=0
use_internal_argon2=1
NO_FIPS([])
])
@@ -493,12 +521,21 @@ 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 || ( test "x$enable_internal_argon2" = "xno" && test "x$enable_libargon2" != "xyes" ); then
if test "x$enable_internal_argon2" = "xyes" || test "x$enable_libargon2" = "xyes"; then
AC_MSG_NOTICE([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>])
PKG_CHECK_MODULES([LIBARGON2], [libargon2],,[LIBARGON2_LIBS="-largon2"])
enable_internal_argon2=no
use_internal_argon2=0
else
AC_MSG_WARN([Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2.])
@@ -517,11 +554,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],
@@ -556,6 +592,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
@@ -634,16 +691,16 @@ 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+=" libgcrypt" ;;
openssl) PKGMODULES+=" openssl" ;;
nss) PKGMODULES+=" nss" ;;
nettle) PKGMODULES+=" nettle" ;;
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+=" libargon2"
PKGMODULES="$PKGMODULES libargon2"
fi
if test "x$enable_blkid" = "xyes"; then
PKGMODULES+=" blkid"
PKGMODULES="$PKGMODULES blkid"
fi
AC_SUBST([PKGMODULES])
dnl ==========================================================================
@@ -681,9 +738,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])

View File

@@ -12,30 +12,53 @@ no longer stored directly in dm-crypt target. Starting with cryptsetup 2.0 we
load VK in kernel keyring by default for LUKSv2 devices (when dm-crypt with the
feature is available).
Currently cryptsetup loads VK in 'logon' type kernel key so that VK is passed in
the kernel and can't be read from userspace afterward. Also cryptsetup loads VK in
thread keyring (before passing the reference to dm-crypt target) so that the key
Currently, cryptsetup loads VK in 'logon' type kernel key so that VK is passed in
the kernel and can't be read from userspace afterwards. Also, cryptsetup loads VK in
the thread keyring (before passing the reference to dm-crypt target) so that the key
lifetime is directly bound to the process that performs the dm-crypt setup. When
cryptsetup process exits (for whatever reason) the key gets unlinked in kernel
cryptsetup process exits (for whatever reason) the key gets unlinked in the kernel
automatically. In summary, the key description visible in dm-crypt table line is
a reference to VK that usually no longer exists in kernel keyring service if you
used cryptsetup to for device activation.
used cryptsetup for device activation.
Using this feature dm-crypt no longer maintains a direct key copy (but there's
always at least one copy in kernel crypto layer).
always at least one copy in the kernel crypto layer).
Additionally, libcryptsetup supports the linking of volume keys to
user-specified kernel keyring with crypt_set_keyring_to_link(). The user may
specify keyring name, key type ('user' or 'logon') and key description where
libcryptsetup should link the verified volume key upon subsequent device
activation (or key verification alone).
The volume key(s) (provided the key type is 'user') linked in the user keyring
can be later used to activate the device via crypt_activate_by_keyslot_context()
with CRYPT_KC_TYPE_VK_KEYRING type keyslot context
(acquired by crypt_keyslot_context_init_by_vk_in_keyring()).
Example of how to use volume key linked in custom user keyring from cryptsetup
utility:
1) Open the device and store the volume key to the session keyring:
# cryptsetup open <device> --link-vk-to-keyring "@s::%user:testkey" tst
2) Add a keyslot using the stored volume key in a keyring:
# cryptsetup luksAddKey <device> --volume-key-keyring "%user:testkey"
3) Activate the device using the volume key cached in a keyring ('user' type key)
# cryptsetup open <device> <active_name> --volume-key-keyring "testkey"
II) Keyslot passphrase
The second use case for kernel keyring is to allow cryptsetup reading the keyslot
passphrase stored in kernel keyring instead. The user may load passphrase in kernel
passphrase stored in kernel keyring instead. The user may load the passphrase in the kernel
keyring and notify cryptsetup to read it from there later. Currently, cryptsetup
cli supports kernel keyring for passphrase only via LUKS2 internal token
(luks2-keyring). Library also provides a general method for device activation by
reading passphrase from keyring: crypt_activate_by_keyring(). The key type
(luks2-keyring). The library also provides a general method for device activation by
reading the passphrase from the keyring: crypt_activate_by_keyring(). The key type
for use case II) must always be 'user' since we need to read the actual key
data from userspace unlike with VK in I). Ability to read keyslot passphrase
from kernel keyring also allows easily auto-activate LUKS2 devices.
data from userspace unlike with VK in I). The ability to read keyslot passphrases
from kernel keyring also allows easy auto-activate LUKS2 devices.
Simple example how to use kernel keyring for keyslot passphrase:
Simple example of how to use kernel keyring for keyslot passphrase:
1) create LUKS2 keyring token for keyslot 0 (in LUKS2 device/image)
cryptsetup token add --key-description my:key -S 0 /dev/device
@@ -43,7 +66,7 @@ cryptsetup token add --key-description my:key -S 0 /dev/device
2) Load keyslot passphrase in user keyring
read -s -p "Keyslot passphrase: "; echo -n $REPLY | keyctl padd user my:key @u
3) Activate device using passphrase stored in kernel keyring
3) Activate the device using the passphrase stored in the kernel keyring
cryptsetup open /dev/device my_unlocked_device
4a) unlink the key when no longer needed by
@@ -52,5 +75,5 @@ keyctl unlink %user:my:key @u
4b) or revoke it immediately by
keyctl revoke %user:my:key
If cryptsetup asks for passphrase in step 3) something went wrong with keyring
If cryptsetup asks for a passphrase in step 3) something went wrong with keyring
activation. See --debug output then.

View File

@@ -5,7 +5,7 @@ Why
~~~
LUKS2 format keeps two identical copies of metadata stored consecutively
at the head of metadata device (file or bdev). The metadata
at the head of the metadata device (file or bdev). The metadata
area (both copies) must be updated in a single atomic operation to avoid
header corruption during concurrent write.
@@ -15,17 +15,17 @@ locking with legacy format was not so obvious as it is with the LUKSv2 format.
With LUKS2 the boundary between read-only and read-write is blurry and what
used to be the exclusively read-only operation (i.e., cryptsetup open command) may
easily become read-update operation silently without user's knowledge.
Major feature of LUKS2 format is resilience against accidental
easily become read-update operation silently without the user's knowledge.
A major feature of the LUKS2 format is resilience against accidental
corruption of metadata (i.e., partial header overwrite by parted or cfdisk
while creating partition on mistaken block device).
Such header corruption is detected early on header read and auto-recovery
while creating a partition on a mistaken block device).
Such header corruption is detected early on the header read and the auto-recovery
procedure takes place (the corrupted header with checksum mismatch is being
replaced by the secondary one if that one is intact).
On current Linux systems header load operation may be triggered without user
direct intervention for example by udev rule or from systemd service.
Such clash of header read and auto-recovery procedure could have severe
consequences with the worst case of having LUKS2 device unaccessible or being
On current Linux systems header load operation may be triggered without the user
direct intervention for example by an udev rule or from a systemd service.
Such a clash of header read and auto-recovery procedure could have severe
consequences with the worst case of having a LUKS2 device inaccessible or being
broken beyond repair.
The whole locking of LUKSv2 device headers split into two categories depending
@@ -36,17 +36,17 @@ I) block device
We perform flock() on file descriptors of files stored in a private
directory (by default /run/lock/cryptsetup). The file name is derived
from major:minor couple of affected block device. Note we recommend
that access to private locking directory is supposed to be limited
to superuser only. For this method to work the distribution needs
from major:minor couple of the affected block device. Note we recommend
that access to the private locking directory is supposed to be limited
to the superuser only. For this method to work the distribution needs
to install the locking directory with appropriate access rights.
II) regular files
~~~~~~~~~~~~~~~~~
First notable difference between headers stored in a file
A first notable difference between headers stored in a file
vs. headers stored in a block device is that headers in a file may be
manipulated by the regular user unlike headers on block devices. Therefore
manipulated by the regular user, unlike headers on block devices. Therefore
we perform flock() protection on file with the luks2 header directly.
Limitations
@@ -58,4 +58,40 @@ while locking is enabled.
We do not suppress any other negative effect that two or more concurrent
writers of the same header may cause.
b) The locking is not cluster aware in any way.
b) The locking is not cluster-aware in any way.
Additional LUKS2 locks
======================
LUKS2 reencryption device lock
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Device in LUKS2 reencryption is protected by an exclusive lock placed in the default
locking directory. The lock's purpose is to exclude multiple processes from
performing reencryption on the same device (identified by LUKS uuid). The lock
is taken no matter the LUKS2 reencryption mode (online or offline).
LUKS2 memory hard global lock
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An optional global lock that makes libcryptsetup serialize memory hard
pbkdf function when deriving a key encryption key from passphrase on unlocking
LUKS2 keyslot. The lock has to be enabled via the CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF
flag. The lock is placed in the default locking directory.
LUKS2 OPAL lock
~~~~~~~~~~~~~~~
Exclusive per device lock taken when manipulating LUKS2 device configured for use with
SED OPAL2 locking range.
Lock ordering
=============
To avoid a deadlock following rules must apply:
- LUKS2 reencrytpion lock must be taken before LUKS2 OPAL lock.
- LUKS2 OPAL lock must be taken before LUKS2 metadata lock.
- LUKS2 memory hard global lock can not be used with other locks.

View File

@@ -1,4 +1,4 @@
# Doxyfile 1.9.1
# Doxyfile 1.9.8
#---------------------------------------------------------------------------
# Project related configuration options
@@ -10,9 +10,9 @@ PROJECT_BRIEF = "Public cryptsetup API"
PROJECT_LOGO =
OUTPUT_DIRECTORY = doxygen_api_docs
CREATE_SUBDIRS = NO
CREATE_SUBDIRS_LEVEL = 8
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
@@ -39,6 +39,7 @@ OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
MARKDOWN_ID_STYLE = DOXYGEN
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
@@ -52,6 +53,7 @@ INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = YES
LOOKUP_CACHE_SIZE = 0
NUM_PROC_THREADS = 1
TIMESTAMP = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -72,6 +74,7 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_HEADERFILE = YES
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
@@ -101,9 +104,12 @@ QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_IF_INCOMPLETE_DOC = YES
WARN_NO_PARAMDOC = NO
WARN_IF_UNDOC_ENUM_VAL = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LINE_FORMAT = "at line $line of file $file"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
@@ -111,6 +117,7 @@ WARN_LOGFILE =
INPUT = doxygen_index.h \
../lib/libcryptsetup.h
INPUT_ENCODING = UTF-8
INPUT_FILE_ENCODING =
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
@@ -126,6 +133,7 @@ FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
FORTRAN_COMMENT_AFTER = 72
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
@@ -158,15 +166,17 @@ HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE = AUTO_LIGHT
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_CODE_FOLDING = YES
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_FEEDURL =
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
@@ -177,6 +187,7 @@ GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
SITEMAP_URL =
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
@@ -189,14 +200,16 @@ GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
FULL_SIDEBAR = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
OBFUSCATE_EMAILS = YES
HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
FORMULA_MACROFILE =
USE_MATHJAX = NO
MATHJAX_VERSION = MathJax_2
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
MATHJAX_EXTENSIONS =
@@ -227,9 +240,7 @@ PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
@@ -240,7 +251,6 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
@@ -261,12 +271,17 @@ XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to Sqlite3 output
#---------------------------------------------------------------------------
GENERATE_SQLITE3 = NO
SQLITE3_OUTPUT = sqlite3
SQLITE3_RECREATE_DB = YES
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
@@ -294,15 +309,14 @@ ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
# Configuration options related to diagram generator tools
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
@@ -318,18 +332,20 @@ CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DIR_GRAPH_MAX_DEPTH = 1
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIA_PATH =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
MSCGEN_TOOL =
MSCFILE_DIRS =

View File

@@ -1,7 +1,7 @@
/*
* libcryptsetup API log example
*
* Copyright (C) 2011-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2024 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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2024 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.

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.

437
docs/v2.7.0-ReleaseNotes Normal file
View File

@@ -0,0 +1,437 @@
Cryptsetup 2.7.0 Release Notes
==============================
Stable release with new features and bug fixes.
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 missing 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 optionally 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 (ENOKEY).
* 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.
* 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.
* 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.
* Update keyring and locking documentation and LUKS2 specification
for OPAL2 support.
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

30
docs/v2.7.1-ReleaseNotes Normal file
View File

@@ -0,0 +1,30 @@
Cryptsetup 2.7.1 Release Notes
==============================
Stable bug-fix release with minor extensions.
All users of cryptsetup 2.7.0 should upgrade to this version.
Changes since version 2.7.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix interrupted LUKS1 decryption resume.
With the replacement of the cryptsetup-reencrypt tool by the cryptsetup
reencrypt command, resuming the interrupted LUKS1 decryption operation
could fail. LUKS2 was not affected.
* Allow --link-vk-to-keyring with --test-passphrase option.
This option allows uploading the volume key in a user-specified kernel
keyring without activating the device.
* Fix crash when --active-name was used in decryption initialization.
* Updates and changes to man pages, including indentation, sorting options
alphabetically, fixing mistakes in crypt_set_keyring_to_link, and fixing
some typos.
* Fix compilation with libargon2 when --disable-internal-argon2 was used.
* Do not require installed argon2.h header and never compile internal
libargon2 code if the crypto library directly supports Argon2.
* Fixes to regression tests to support older Linux distributions.

31
docs/v2.7.2-ReleaseNotes Normal file
View File

@@ -0,0 +1,31 @@
Cryptsetup 2.7.2 Release Notes
==============================
Stable bug-fix release.
All users of cryptsetup 2.7 should upgrade to this version.
Changes since version 2.7.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Fix activation of OPAL-only encrypted LUKS device with tokens.
The issue was caused by an invalid volume key check (assert)
that is impossible without software encryption.
* Fix formatting of OPAL devices with 4096-byte sector size.
* Fix incorrect OPAL locking range alignment calculation if used
over an unaligned device partition.
* Add --hw-opal-factory-reset option description to the manual page.
* Do not check the passphrase quality for OPAL Admin PIN,
as this passphrase already exists.
* Update license for FAQ document to CC BY-SA 4.0.
NOTE: Please note that with OPAL-only (--hw-opal-only) encryption,
the configured OPAL administrator PIN (passphrase) allows unlocking
all configured locking ranges without LUKS keyslot decryption
(without knowledge of LUKS passphrase).
Because of many observed problems with compatibility, cryptsetup
currently DOES NOT use OPAL single-user mode, which would allow such
decoupling of OPAL admin PIN access.

View File

@@ -103,6 +103,8 @@ libcryptsetup_la_SOURCES = \
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 \

View File

@@ -1,9 +1,9 @@
/*
* BITLK (BitLocker-compatible) volume handling
*
* Copyright (C) 2019-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2022 Milan Broz
* Copyright (C) 2019-2022 Vojtech Trefny
* Copyright (C) 2019-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2024 Milan Broz
* Copyright (C) 2019-2024 Vojtech Trefny
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -255,13 +255,16 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
(*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,
@@ -280,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;
@@ -318,6 +325,8 @@ 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 (key_entry_size < BITLK_ENTRY_HEADER_LEN)
return -EINVAL;
string = malloc((key_entry_size - BITLK_ENTRY_HEADER_LEN) * 2 + 1);
if (!string)
return -ENOMEM;
@@ -405,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};
@@ -413,7 +423,6 @@ 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;
@@ -514,7 +523,6 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
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 */
@@ -569,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,
@@ -639,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;
@@ -647,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;
@@ -663,19 +691,29 @@ 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) {
description = malloc((entry_size - BITLK_ENTRY_HEADER_LEN - BITLK_ENTRY_HEADER_LEN) * 2 + 1);
if (!description)
return -ENOMEM;
} 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 || !description) {
if (r < 0) {
free(description);
BITLK_bitlk_vmk_free(vmk);
log_err(cd, _("Failed to convert BITLK volume description"));
@@ -697,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;
@@ -705,7 +744,8 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
log_std(cd, "GUID: \t%s\n", params->guid);
log_std(cd, "Sector size: \t%u [bytes]\n", params->sector_size);
log_std(cd, "Volume size: \t%" PRIu64 " [bytes]\n", params->volume_size);
log_std(cd, "Created: \t%s", ctime((time_t *)&(params->creation_time)));
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);
@@ -773,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] != '-')
@@ -822,13 +862,16 @@ static int parse_external_key_entry(struct crypt_device *cd,
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,
@@ -843,6 +886,8 @@ static int parse_external_key_entry(struct crypt_device *cd,
}
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);
@@ -854,6 +899,8 @@ static int parse_external_key_entry(struct crypt_device *cd,
;
/* 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) {
@@ -887,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);
@@ -899,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;
}
@@ -936,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,
@@ -1074,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;
@@ -1094,7 +1141,7 @@ 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)

View File

@@ -1,9 +1,9 @@
/*
* BITLK (BitLocker-compatible) header definition
*
* Copyright (C) 2019-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2022 Milan Broz
* Copyright (C) 2019-2022 Vojtech Trefny
* Copyright (C) 2019-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2019-2024 Milan Broz
* Copyright (C) 2019-2024 Vojtech Trefny
*
* 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,8 +2,8 @@
* cryptsetup plain device helper functions
*
* Copyright (C) 2004 Jana Saout <jana@saout.de>
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 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

@@ -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

@@ -1,8 +1,8 @@
/*
* Argon2 PBKDF2 library wrapper
*
* Copyright (C) 2016-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2022 Milan Broz
* Copyright (C) 2016-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2024 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,22 +21,23 @@
#include <errno.h>
#include "crypto_backend_internal.h"
/* Check for HAVE_ARGON2_H is run only if libargon2 code is used */
#if USE_INTERNAL_ARGON2 || HAVE_ARGON2_H
#define CONST_CAST(x) (x)(uintptr_t)
#if HAVE_ARGON2_H
#include <argon2.h>
#else
#include "argon2/argon2.h"
#endif
#define CONST_CAST(x) (x)(uintptr_t)
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 +55,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 +79,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;
}

View File

@@ -4,7 +4,7 @@
* Copyright (C) 2010 Lennart Poettering
*
* cryptsetup related changes
* Copyright (C) 2021-2022 Milan Broz
* Copyright (C) 2021-2024 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 @@
/*
* Cipher performance check
*
* Copyright (C) 2018-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2022 Milan Broz
* Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2024 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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2022 Milan Broz
* Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2024 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

@@ -158,7 +158,7 @@ static const uint32_t crc32c_tab[] = {
* whatever they need.
*/
static uint32_t compute_crc32(
const uint32_t *crc32_tab,
const uint32_t *crc32_table,
uint32_t seed,
const unsigned char *buf,
size_t len)
@@ -167,7 +167,7 @@ static uint32_t compute_crc32(
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;
}

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -41,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);

View File

@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 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 userspace API crypto backend implementation (skcipher)
*
* Copyright (C) 2012-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2022 Milan Broz
* Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2024 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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <errno.h>
#include <gcrypt.h>
#include <pthread.h>
#include "crypto_backend_internal.h"
static int crypto_backend_initialised = 0;
@@ -126,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;
@@ -151,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)
@@ -266,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);
}
@@ -341,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);
}
@@ -386,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,
@@ -400,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;
}
@@ -565,6 +698,9 @@ bool crypt_fips_mode(void)
if (fips_checked)
return fips_mode;
if (crypt_backend_init(false /* ignored */))
return false;
fips_mode = gcry_fips_mode_active();
fips_checked = true;

View File

@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation
*
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 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);
}

View File

@@ -1,8 +1,8 @@
/*
* Nettle crypto backend implementation
*
* Copyright (C) 2011-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2022 Milan Broz
* Copyright (C) 2011-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2024 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 @@
/*
* NSS crypto backend implementation
*
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 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 @@
/*
* OPENSSL crypto backend implementation
*
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2022 Milan Broz
* Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 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,7 @@
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
@@ -43,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;
@@ -161,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
@@ -180,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;
}
@@ -231,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)
@@ -276,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
}
@@ -292,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
}
@@ -386,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);
}
@@ -522,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);
}
@@ -574,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
@@ -584,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 */

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-2022 Milan Broz
* Copyright (C) 2014-2024 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

@@ -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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2022 Milan Broz
* Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2024 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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2022 Milan Broz
* Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2024 Milan Broz
* Copyright (C) 2016-2020 Ondrej Mosnacek
*
* This file is free software; you can redistribute it and/or

View File

@@ -4,7 +4,7 @@
* Copyright (C) 2010 Lennart Poettering
*
* cryptsetup related changes
* Copyright (C) 2021-2022 Vojtech Trefny
* Copyright (C) 2021-2024 Vojtech Trefny
* Parts of the original systemd implementation are based on the GLIB utf8
* validation functions.

View File

@@ -435,7 +435,7 @@ static int _reformat_uuid(
const char *uuid_in,
char *uuid_out)
{
uint8_t uuid_bin[UUID_STR_LEN];
uint8_t uuid_bin[FVAULT2_UUID_LEN];
int r;
r = uuid_parse(uuid_in, uuid_bin);

View File

@@ -1,7 +1,7 @@
/*
* Integrity volume handling
*
* Copyright (C) 2016-2022 Milan Broz
* Copyright (C) 2016-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -335,13 +335,62 @@ int INTEGRITY_activate(struct crypt_device *cd,
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 = 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 */
@@ -349,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);
@@ -358,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, 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,
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);
@@ -379,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-2022 Milan Broz
* Copyright (C) 2016-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -75,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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2022 Milan Broz
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -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);
@@ -202,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,
@@ -221,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);
@@ -250,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 */

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup, keyslot unlock helpers
*
* Copyright (C) 2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022 Ondrej Kozina
* Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -173,7 +173,7 @@ static int get_luks1_volume_key_by_keyfile(struct crypt_device *cd,
return r;
}
static int get_key_by_key(struct crypt_device *cd,
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)),
@@ -204,19 +204,73 @@ static int get_volume_key_by_key(struct crypt_device *cd,
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 __attribute__((unused)),
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);
r = LUKS2_token_unlock_key(cd, crypt_get_hdr(cd, CRYPT_LUKS2), kc->u.t.id, kc->u.t.type,
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;
@@ -226,10 +280,10 @@ static int get_luks2_key_by_token(struct crypt_device *cd,
static int get_luks2_volume_key_by_token(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
int keyslot __attribute__((unused)),
int keyslot,
struct volume_key **r_vk)
{
return get_luks2_key_by_token(cd, kc, -2 /* unused */, CRYPT_DEFAULT_SEGMENT, 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,
@@ -261,6 +315,136 @@ static int get_passphrase_by_token(struct crypt_device *cd,
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);
@@ -270,6 +454,26 @@ static void unlock_method_init_internal(struct crypt_keyslot_context *kc)
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)
@@ -283,6 +487,36 @@ void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
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);
}
@@ -299,6 +533,11 @@ void crypt_keyslot_unlock_by_passphrase_init_internal(struct crypt_keyslot_conte
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);
}
@@ -317,6 +556,11 @@ void crypt_keyslot_unlock_by_keyfile_init_internal(struct crypt_keyslot_context
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);
}
@@ -339,9 +583,35 @@ void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *k
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)
@@ -358,7 +628,7 @@ void crypt_keyslot_context_free(struct crypt_keyslot_context *kc)
free(kc);
}
int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
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)
@@ -379,7 +649,7 @@ int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
return 0;
}
int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd __attribute__((unused)),
const char *keyfile,
size_t keyfile_size,
uint64_t keyfile_offset,
@@ -401,7 +671,7 @@ int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
return 0;
}
int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
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,
@@ -424,7 +694,7 @@ int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
return 0;
}
int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
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)
@@ -445,12 +715,76 @@ int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
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,
int crypt_keyslot_context_set_pin(struct crypt_device *cd __attribute__((unused)),
const char *pin, size_t pin_size,
struct crypt_keyslot_context *kc)
{
@@ -482,6 +816,12 @@ const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc)
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>";
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup, keyslot unlock helpers
*
* Copyright (C) 2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022 Ondrej Kozina
* Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -40,6 +40,17 @@ typedef int (*keyslot_context_get_volume_key) (
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,
@@ -71,6 +82,18 @@ struct crypt_keyslot_context {
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;
@@ -78,10 +101,15 @@ struct crypt_keyslot_context {
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_passphrase get_passphrase;
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);
@@ -90,6 +118,12 @@ 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);
@@ -106,6 +140,12 @@ void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *k
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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2022 Milan Broz
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -273,7 +273,7 @@ struct crypt_pbkdf_type {
/** Iteration time set by crypt_set_iteration_time(), for compatibility only. */
#define CRYPT_PBKDF_ITER_TIME_SET (UINT32_C(1) << 0)
/** Never run benchmarks, use pre-set value or defaults. */
/** 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 */
@@ -450,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.
@@ -609,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 */
};
/** @} */
/**
@@ -648,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.
*
@@ -941,6 +1009,23 @@ int crypt_resume_by_token_pin(struct crypt_device *cd,
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);
/** @} */
/**
@@ -1099,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,
@@ -1194,6 +1279,59 @@ int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
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.
*
@@ -1225,7 +1363,7 @@ int crypt_keyslot_context_set_pin(struct crypt_device *cd,
struct crypt_keyslot_context *kc);
/**
* @defgroup crypt-keyslot-context-types Crypt keyslot context
* @defgroup crypt-keyslot-context-types Crypt keyslot context types
* @addtogroup crypt-keyslot-context-types
* @{
*/
@@ -1237,6 +1375,16 @@ int crypt_keyslot_context_set_pin(struct crypt_device *cd,
#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)
/** @} */
/**
@@ -1281,7 +1429,7 @@ int crypt_keyslot_context_get_type(const struct crypt_keyslot_context *kc);
* @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_keyslot_context(struct crypt_device *cd,
@@ -1420,6 +1568,8 @@ uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd,
#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (UINT32_C(1) << 0)
/** Online reencryption in-progress */
#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 (UINT32_C(1) << 31)
@@ -1473,6 +1623,39 @@ 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 -ESRCH error code is returned and you
* should call the function again with an additional keyslot context specified.
*
* NOTE: the API at the moment fully works for single keyslot context only,
* the additional keyslot context currently works only with
* @e CRYPT_KC_TYPE_VK_KEYRING or @e CRYPT_KC_TYPE_KEY contexts.
*
* @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.
*
@@ -1553,6 +1736,9 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
* CRYPT_ACTIVATE_READONLY flag always.
* @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,
@@ -2259,6 +2445,36 @@ int crypt_wipe(struct crypt_device *cd,
/** Use direct-io */
#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 */
);
/** @} */
/**
@@ -2566,6 +2782,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.
@@ -2875,6 +3102,55 @@ 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 -ESRCH. 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.
*
* @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 by 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

@@ -165,3 +165,18 @@ CRYPTSETUP_2.6 {
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 of libcryptsetup
*
* Copyright (C) 2009-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2022 Milan Broz
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 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

@@ -1,7 +1,7 @@
/*
* Helpers for defining versioned symbols
*
* Copyright (C) 2021-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2021-2024 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
@@ -72,9 +72,9 @@
__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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2022 Milan Broz
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -602,7 +602,8 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
hexkey = crypt_safe_alloc(keystr_len);
if (!hexkey)
goto out;
r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description);
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
@@ -1330,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)
@@ -1663,6 +1672,11 @@ int dm_create_device(struct crypt_device *cd, const char *name,
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) &&
@@ -2829,7 +2843,7 @@ static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_
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_task *dmt = NULL;
struct dm_info dmi;
struct dm_deps *deps;
int r = -EINVAL;
@@ -2989,7 +3003,8 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
}
if (vk->key_description) {
r = snprintf(msg, msg_size, "key set :%zu:logon:%s", vk->keylength, 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) {
@@ -3026,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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2022 Milan Broz
* Copyright (C) 2011-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2024 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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2022 Milan Broz
* Copyright (C) 2011-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2024 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-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefore supporting secure data destruction.

View File

@@ -2,7 +2,7 @@
* AFsplitter - Anti forensic information splitter
*
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
*
* AFsplitter diffuses information over a large stripe of data,
* therefore supporting secure data destruction.

View File

@@ -2,8 +2,8 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2022 Milan Broz
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2024 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

@@ -2,8 +2,8 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2022 Milan Broz
* Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2013-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -29,6 +29,7 @@
#include <string.h>
#include <ctype.h>
#include <uuid/uuid.h>
#include <limits.h>
#include "luks.h"
#include "af.h"
@@ -924,8 +925,12 @@ int LUKS_set_key(unsigned int keyIndex,
hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
derived_key->key, hdr->keyBytes,
hdr->keyblock[keyIndex].passwordIterations, 0, 0);
if (r < 0)
if (r < 0) {
if ((crypt_backend_flags() & CRYPT_BACKEND_PBKDF2_INT) &&
hdr->keyblock[keyIndex].passwordIterations > INT_MAX)
log_err(ctx, _("PBKDF2 iteration value overflow."));
goto out;
}
/*
* AF splitting, the volume key stored in vk->key is split to AfKey

View File

@@ -2,7 +2,7 @@
* LUKS - Linux Unified Key Setup
*
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2009-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2009-2024 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

1097
lib/luks2/hw_opal/hw_opal.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
/*
* OPAL utilities
*
* Copyright (C) 2022-2023 Luca Boccassi <bluca@debian.org>
* 2023 Ondrej Kozina <okozina@redhat.com>
*
* 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 _UTILS_OPAL
#define _UTILS_OPAL
#include "internal.h"
struct crypt_lock_handle;
int opal_setup_ranges(struct crypt_device *cd,
struct device *dev,
const struct volume_key *vk,
uint64_t range_start_blocks,
uint64_t range_length_blocks,
uint32_t opal_block_bytes,
uint32_t segment_number,
const void *admin_key,
size_t admin_key_len);
int opal_lock(struct crypt_device *cd, struct device *dev, uint32_t segment_number);
int opal_unlock(struct crypt_device *cd,
struct device *dev,
uint32_t segment_number,
const struct volume_key *vk);
int opal_supported(struct crypt_device *cd, struct device *dev);
int opal_factory_reset(struct crypt_device *cd,
struct device *dev,
const char *password,
size_t password_len);
int opal_reset_segment(struct crypt_device *cd,
struct device *dev,
uint32_t segment_number,
const char *password,
size_t password_len);
int opal_geometry(struct crypt_device *cd,
struct device *dev,
bool *ret_align,
uint32_t *ret_block_size,
uint64_t *ret_alignment_granularity_blocks,
uint64_t *ret_lowest_lba_blocks);
int opal_range_check_attributes_and_get_lock_state(struct crypt_device *cd,
struct device *dev,
uint32_t segment_number,
const struct volume_key *vk,
const uint64_t *check_offset_sectors,
const uint64_t *check_length_sectors,
bool *ret_read_locked,
bool *ret_write_locked);
int opal_exclusive_lock(struct crypt_device *cd,
struct device *opal_device,
struct crypt_lock_handle **opal_lock);
void opal_exclusive_unlock(struct crypt_device *cd, struct crypt_lock_handle *opal_lock);
#endif

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -224,8 +224,7 @@ int LUKS2_keyslot_store(struct crypt_device *cd,
int LUKS2_keyslot_wipe(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int wipe_area_only);
int keyslot);
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct luks2_hdr *hdr, int keyslot);
@@ -277,6 +276,7 @@ crypt_token_info LUKS2_token_status(struct crypt_device *cd,
int LUKS2_token_open_and_activate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
const char *name,
const char *type,
@@ -287,6 +287,7 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd,
int LUKS2_token_unlock_key(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
const char *type,
const char *pin,
@@ -359,7 +360,8 @@ int LUKS2_digest_create(struct crypt_device *cd,
*/
int LUKS2_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
struct volume_key *crypt_key,
struct volume_key *opal_key,
uint32_t flags);
int LUKS2_activate_multi(struct crypt_device *cd,
@@ -378,16 +380,23 @@ int LUKS2_generate_hdr(
struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
const char *cipherName,
const char *cipherMode,
const char *cipher_spec,
const char *integrity,
const char *uuid,
unsigned int sector_size,
uint64_t data_offset,
uint64_t align_offset,
uint64_t required_alignment,
uint64_t metadata_size,
uint64_t keyslots_size);
uint64_t metadata_size_bytes,
uint64_t keyslots_size_bytes,
uint64_t device_size_bytes,
uint32_t opal_segment_number,
uint32_t opal_key_size);
int LUKS2_hdr_get_storage_params(struct crypt_device *cd,
uint64_t alignment_offset_bytes,
uint64_t alignment_bytes,
uint64_t *ret_metadata_size_bytes,
uint64_t *ret_keyslots_size_bytes,
uint64_t *ret_data_offset_bytes);
int LUKS2_check_metadata_area_size(uint64_t metadata_size);
int LUKS2_check_keyslots_area_size(uint64_t keyslots_size);
@@ -414,6 +423,12 @@ int LUKS2_keyslot_area(struct luks2_hdr *hdr,
uint64_t *length);
int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf);
int LUKS2_split_crypt_and_opal_keys(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
struct volume_key **ret_crypt_key,
struct volume_key **ret_opal_key);
/*
* Permanent activation flags stored in header
*/
@@ -457,6 +472,9 @@ int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
size_t passphrase_size,
struct volume_key **vks);
int LUKS2_reencrypt_locked_recovery_by_vks(struct crypt_device *cd,
struct volume_key *vks);
void LUKS2_reencrypt_free(struct crypt_device *cd,
struct luks2_reencrypt *rh);
@@ -479,9 +497,13 @@ int LUKS2_reencrypt_check_device_size(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t check_size,
uint64_t *dev_size,
bool activation,
bool device_exclusive_check,
bool dynamic);
void LUKS2_reencrypt_lookup_key_ids(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vk);
int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks);

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, digest handling
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -157,7 +157,7 @@ int LUKS2_digest_dump(struct crypt_device *cd, int digest)
}
int LUKS2_digest_any_matching(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct luks2_hdr *hdr __attribute__((unused)),
const struct volume_key *vk)
{
int digest;
@@ -174,6 +174,18 @@ int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
int segment,
const struct volume_key *vk)
{
int r = -EINVAL;
unsigned s;
if (segment == CRYPT_ANY_SEGMENT) {
for (s = 0; s < json_segments_count(LUKS2_get_segments_jobj(hdr)); s++) {
if ((r = LUKS2_digest_verify_by_digest(cd, LUKS2_digest_by_segment(hdr, s), vk)) >= 0)
return r;
}
return -EPERM;
}
return LUKS2_digest_verify_by_digest(cd, LUKS2_digest_by_segment(hdr, segment), vk);
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, PBKDF2 digest handler (LUKS1 compatible)
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -147,6 +147,9 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
}
if (!jobj_digest)
return -ENOMEM;
json_object_object_add(jobj_digest, "type", json_object_new_string("pbkdf2"));
json_object_object_add(jobj_digest, "keyslots", json_object_new_array());
json_object_object_add(jobj_digest, "segments", json_object_new_array());
@@ -169,8 +172,13 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
json_object_object_add(jobj_digest, "digest", json_object_new_string(base64_str));
free(base64_str);
if (jobj_digests)
json_object_object_add_by_uint(jobj_digests, digest, jobj_digest);
if (jobj_digests) {
r = json_object_object_add_by_uint(jobj_digests, digest, jobj_digest);
if (r < 0) {
json_object_put(jobj_digest);
return r;
}
}
JSON_DBG(cd, jobj_digest, "Digest JSON:");
return 0;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -256,6 +256,7 @@ static int hdr_read_disk(struct crypt_device *cd,
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
device_alignment(device), hdr_disk,
LUKS2_HDR_BIN_LEN, offset) != LUKS2_HDR_BIN_LEN) {
memset(hdr_disk, 0, LUKS2_HDR_BIN_LEN);
return -EIO;
}
@@ -537,11 +538,20 @@ static int validate_luks2_json_object(struct crypt_device *cd, json_object *jobj
}
static json_object *parse_and_validate_json(struct crypt_device *cd,
const char *json_area, uint64_t max_length)
const char *json_area, uint64_t hdr_size)
{
int json_len, r;
json_object *jobj = parse_json_len(cd, json_area, max_length, &json_len);
json_object *jobj;
uint64_t max_length;
if (hdr_size <= LUKS2_HDR_BIN_LEN || hdr_size > LUKS2_HDR_OFFSET_MAX) {
log_dbg(cd, "LUKS2 header JSON has bogus size 0x%04" PRIx64 ".", hdr_size);
return NULL;
}
max_length = hdr_size - LUKS2_HDR_BIN_LEN;
jobj = parse_json_len(cd, json_area, max_length, &json_len);
if (!jobj)
return NULL;
@@ -635,7 +645,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
state_hdr1 = HDR_FAIL;
r = hdr_read_disk(cd, device, &hdr_disk1, &json_area1, 0, 0);
if (r == 0) {
jobj_hdr1 = parse_and_validate_json(cd, json_area1, be64_to_cpu(hdr_disk1.hdr_size) - LUKS2_HDR_BIN_LEN);
jobj_hdr1 = parse_and_validate_json(cd, json_area1, be64_to_cpu(hdr_disk1.hdr_size));
state_hdr1 = jobj_hdr1 ? HDR_OK : HDR_OBSOLETE;
} else if (r == -EIO)
state_hdr1 = HDR_FAIL_IO;
@@ -647,7 +657,7 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
if (state_hdr1 != HDR_FAIL && state_hdr1 != HDR_FAIL_IO) {
r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, be64_to_cpu(hdr_disk1.hdr_size), 1);
if (r == 0) {
jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN);
jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size));
state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE;
} else if (r == -EIO)
state_hdr2 = HDR_FAIL_IO;
@@ -655,11 +665,12 @@ int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
/*
* No header size, check all known offsets.
*/
hdr_disk2.hdr_size = 0;
for (r = -EINVAL,i = 0; r < 0 && i < ARRAY_SIZE(hdr2_offsets); i++)
r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, hdr2_offsets[i], 1);
if (r == 0) {
jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN);
jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size));
state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE;
} else if (r == -EIO)
state_hdr2 = HDR_FAIL_IO;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -62,6 +62,7 @@ uint32_t crypt_jobj_get_uint32(json_object *jobj);
json_object *crypt_jobj_new_uint64(uint64_t value);
int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object *jobj_val);
int json_object_object_add_by_uint_by_ref(json_object *jobj, unsigned key, json_object **jobj_val_ref);
void json_object_object_del_by_uint(json_object *jobj, unsigned key);
int json_object_copy(json_object *jobj_src, json_object **jobj_dst);
@@ -295,13 +296,24 @@ uint64_t json_segment_get_iv_offset(json_object *jobj_segment);
uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise);
const char *json_segment_get_cipher(json_object *jobj_segment);
uint32_t json_segment_get_sector_size(json_object *jobj_segment);
int json_segment_get_opal_segment_id(json_object *jobj_segment, uint32_t *ret_opal_segment_id);
int json_segment_get_opal_key_size(json_object *jobj_segment, size_t *ret_key_size);
bool json_segment_is_backup(json_object *jobj_segment);
json_object *json_segments_get_segment(json_object *jobj_segments, int segment);
unsigned json_segments_count(json_object *jobj_segments);
void json_segment_remove_flag(json_object *jobj_segment, const char *flag);
uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise);
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption);
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length,
const char *cipher, const char *integrity,
uint32_t sector_size, unsigned reencryption);
json_object *json_segment_create_opal(uint64_t offset, const uint64_t *length,
uint32_t segment_number, uint32_t key_size);
json_object *json_segment_create_opal_crypt(uint64_t offset, const uint64_t *length,
uint32_t segment_number, uint32_t key_size,
uint64_t iv_offset, const char *cipher,
const char *integrity, uint32_t sector_size,
unsigned reencryption);
int json_segments_segment_in_reencrypt(json_object *jobj_segments);
bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2);
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
@@ -338,10 +350,26 @@ uint64_t LUKS2_segment_size(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
bool LUKS2_segment_set_size(struct luks2_hdr *hdr,
int segment,
const uint64_t *segment_size_bytes);
uint64_t LUKS2_opal_segment_size(struct luks2_hdr *hdr,
int segment,
unsigned blockwise);
int LUKS2_segment_is_type(struct luks2_hdr *hdr,
int segment,
const char *type);
bool LUKS2_segment_is_hw_opal(struct luks2_hdr *hdr, int segment);
bool LUKS2_segment_is_hw_opal_crypt(struct luks2_hdr *hdr, int segment);
bool LUKS2_segment_is_hw_opal_only(struct luks2_hdr *hdr, int segment);
int LUKS2_get_opal_segment_number(struct luks2_hdr *hdr, int segment,
uint32_t *ret_opal_segment_number);
int LUKS2_get_opal_key_size(struct luks2_hdr *hdr, int segment);
int LUKS2_segment_by_type(struct luks2_hdr *hdr,
const char *type);
@@ -350,8 +378,11 @@ int LUKS2_last_segment_by_type(struct luks2_hdr *hdr,
int LUKS2_get_default_segment(struct luks2_hdr *hdr);
bool LUKS2_segments_dynamic_size(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr);
int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr);
unsigned LUKS2_reencrypt_vks_count(struct luks2_hdr *hdr);
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
/*

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 header format code
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -204,76 +204,33 @@ int LUKS2_generate_hdr(
struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk,
const char *cipherName,
const char *cipherMode,
const char *cipher_spec,
const char *integrity,
const char *uuid,
unsigned int sector_size, /* in bytes */
uint64_t data_offset, /* in bytes */
uint64_t align_offset, /* in bytes */
uint64_t required_alignment,
uint64_t metadata_size,
uint64_t keyslots_size)
uint64_t metadata_size_bytes,
uint64_t keyslots_size_bytes,
uint64_t device_size_bytes,
uint32_t opal_segment_number,
uint32_t opal_key_size)
{
struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
char cipher[128];
struct json_object *jobj_segment, *jobj_keyslots, *jobj_segments, *jobj_config;
uuid_t partitionUuid;
int r, digest;
uint64_t mdev_size;
if (!metadata_size)
metadata_size = LUKS2_HDR_16K_LEN;
hdr->hdr_size = metadata_size;
assert(cipher_spec || (opal_key_size > 0 && device_size_bytes));
if (data_offset && data_offset < get_min_offset(hdr)) {
log_err(cd, _("Requested data offset is too small."));
return -EINVAL;
}
/* Increase keyslot size according to data offset */
if (!keyslots_size && data_offset)
keyslots_size = data_offset - get_min_offset(hdr);
/* keyslots size has to be 4 KiB aligned */
keyslots_size -= (keyslots_size % 4096);
if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
if (!keyslots_size) {
assert(LUKS2_DEFAULT_HDR_SIZE > 2 * LUKS2_HDR_OFFSET_MAX);
keyslots_size = LUKS2_DEFAULT_HDR_SIZE - get_min_offset(hdr);
/* Decrease keyslots_size due to metadata device being too small */
if (!device_size(crypt_metadata_device(cd), &mdev_size) &&
((keyslots_size + get_min_offset(hdr)) > mdev_size) &&
device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)) &&
(get_min_offset(hdr) <= mdev_size))
keyslots_size = mdev_size - get_min_offset(hdr);
}
/* Decrease keyslots_size if we have smaller data_offset */
if (data_offset && (keyslots_size + get_min_offset(hdr)) > data_offset) {
keyslots_size = data_offset - get_min_offset(hdr);
log_dbg(cd, "Decreasing keyslot area size to %" PRIu64
" bytes due to the requested data offset %"
PRIu64 " bytes.", keyslots_size, data_offset);
}
/* Data offset has priority */
if (!data_offset && required_alignment) {
data_offset = size_round_up(get_min_offset(hdr) + keyslots_size,
(size_t)required_alignment);
data_offset += align_offset;
}
hdr->hdr_size = metadata_size_bytes;
log_dbg(cd, "Formatting LUKS2 with JSON metadata area %" PRIu64
" bytes and keyslots area %" PRIu64 " bytes.",
metadata_size - LUKS2_HDR_BIN_LEN, keyslots_size);
metadata_size_bytes - LUKS2_HDR_BIN_LEN, keyslots_size_bytes);
if (keyslots_size < (LUKS2_HDR_OFFSET_MAX - 2*LUKS2_HDR_16K_LEN))
if (keyslots_size_bytes < (LUKS2_HDR_OFFSET_MAX - 2*LUKS2_HDR_16K_LEN))
log_std(cd, _("WARNING: keyslots area (%" PRIu64 " bytes) is very small,"
" available LUKS2 keyslot count is very limited.\n"),
keyslots_size);
keyslots_size_bytes);
hdr->seqid = 1;
hdr->version = 2;
@@ -291,54 +248,81 @@ int LUKS2_generate_hdr(
uuid_unparse(partitionUuid, hdr->uuid);
if (*cipherMode != '\0')
r = snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
else
r = snprintf(cipher, sizeof(cipher), "%s", cipherName);
if (r < 0 || (size_t)r >= sizeof(cipher))
return -EINVAL;
hdr->jobj = json_object_new_object();
if (!hdr->jobj) {
r = -ENOMEM;
goto err;
}
jobj_keyslots = json_object_new_object();
if (!jobj_keyslots) {
r = -ENOMEM;
goto err;
}
json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots);
json_object_object_add(hdr->jobj, "tokens", json_object_new_object());
jobj_segments = json_object_new_object();
if (!jobj_segments) {
r = -ENOMEM;
goto err;
}
json_object_object_add(hdr->jobj, "segments", jobj_segments);
json_object_object_add(hdr->jobj, "digests", json_object_new_object());
jobj_config = json_object_new_object();
if (!jobj_config) {
r = -ENOMEM;
goto err;
}
json_object_object_add(hdr->jobj, "config", jobj_config);
digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk);
if (digest < 0)
if (digest < 0) {
r = -EINVAL;
goto err;
if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0)
goto err;
jobj_segment = json_segment_create_crypt(data_offset, 0, NULL, cipher, sector_size, 0);
if (!jobj_segment)
goto err;
if (integrity) {
jobj_integrity = json_object_new_object();
json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
json_object_object_add(jobj_segment, "integrity", jobj_integrity);
}
json_object_object_add_by_uint(jobj_segments, 0, jobj_segment);
if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0) {
r = -EINVAL;
goto err;
}
json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size - LUKS2_HDR_BIN_LEN));
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
if (!opal_key_size)
jobj_segment = json_segment_create_crypt(data_offset, 0,
NULL, cipher_spec,
integrity, sector_size,
0);
else if (opal_key_size && cipher_spec)
jobj_segment = json_segment_create_opal_crypt(data_offset, &device_size_bytes,
opal_segment_number, opal_key_size, 0,
cipher_spec, integrity,
sector_size, 0);
else
jobj_segment = json_segment_create_opal(data_offset, &device_size_bytes,
opal_segment_number, opal_key_size);
if (!jobj_segment) {
r = -EINVAL;
goto err;
}
if (json_object_object_add_by_uint(jobj_segments, 0, jobj_segment)) {
json_object_put(jobj_segment);
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size_bytes - LUKS2_HDR_BIN_LEN));
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size_bytes));
JSON_DBG(cd, hdr->jobj, "Header JSON:");
return 0;
err:
json_object_put(hdr->jobj);
hdr->jobj = NULL;
return -EINVAL;
return r;
}
int LUKS2_wipe_header_areas(struct crypt_device *cd,
@@ -379,6 +363,14 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
offset = get_min_offset(hdr);
length = LUKS2_keyslots_size(hdr);
/*
* Skip keyslots area wipe in case it is not defined.
* Otherwise we would wipe whole data device (length == 0)
* starting at offset get_min_offset(hdr).
*/
if (!length)
return 0;
log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
offset, length + offset);
@@ -409,3 +401,80 @@ int LUKS2_set_keyslots_size(struct luks2_hdr *hdr, uint64_t data_offset)
json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
return 0;
}
int LUKS2_hdr_get_storage_params(struct crypt_device *cd,
uint64_t alignment_offset_bytes,
uint64_t alignment_bytes,
uint64_t *ret_metadata_size_bytes,
uint64_t *ret_keyslots_size_bytes,
uint64_t *ret_data_offset_bytes)
{
uint64_t data_offset_bytes, keyslots_size_bytes, metadata_size_bytes, mdev_size_bytes;
assert(cd);
assert(ret_metadata_size_bytes);
assert(ret_keyslots_size_bytes);
assert(ret_data_offset_bytes);
metadata_size_bytes = crypt_get_metadata_size_bytes(cd);
keyslots_size_bytes = crypt_get_keyslots_size_bytes(cd);
data_offset_bytes = crypt_get_data_offset_sectors(cd) * SECTOR_SIZE;
if (!metadata_size_bytes)
metadata_size_bytes = LUKS2_HDR_16K_LEN;
if (data_offset_bytes && data_offset_bytes < 2 * metadata_size_bytes) {
log_err(cd, _("Requested data offset is too small."));
return -EINVAL;
}
/* Increase keyslot size according to data offset */
if (!keyslots_size_bytes && data_offset_bytes)
keyslots_size_bytes = data_offset_bytes - 2 * metadata_size_bytes;
/* keyslots size has to be 4 KiB aligned */
keyslots_size_bytes -= (keyslots_size_bytes % 4096);
if (keyslots_size_bytes > LUKS2_MAX_KEYSLOTS_SIZE)
keyslots_size_bytes = LUKS2_MAX_KEYSLOTS_SIZE;
if (!keyslots_size_bytes) {
assert(LUKS2_DEFAULT_HDR_SIZE > 2 * LUKS2_HDR_OFFSET_MAX);
keyslots_size_bytes = LUKS2_DEFAULT_HDR_SIZE - 2 * metadata_size_bytes;
/* Decrease keyslots_size due to metadata device being too small */
if (!device_size(crypt_metadata_device(cd), &mdev_size_bytes) &&
((keyslots_size_bytes + 2 * metadata_size_bytes) > mdev_size_bytes) &&
device_fallocate(crypt_metadata_device(cd), keyslots_size_bytes + 2 * metadata_size_bytes) &&
((2 * metadata_size_bytes) <= mdev_size_bytes))
keyslots_size_bytes = mdev_size_bytes - 2 * metadata_size_bytes;
}
/* Decrease keyslots_size if we have smaller data_offset */
if (data_offset_bytes && (keyslots_size_bytes + 2 * metadata_size_bytes) > data_offset_bytes) {
keyslots_size_bytes = data_offset_bytes - 2 * metadata_size_bytes;
log_dbg(cd, "Decreasing keyslot area size to %" PRIu64
" bytes due to the requested data offset %"
PRIu64 " bytes.", keyslots_size_bytes, data_offset_bytes);
}
/* Data offset has priority */
if (!data_offset_bytes && alignment_bytes) {
data_offset_bytes = size_round_up(2 * metadata_size_bytes + keyslots_size_bytes,
(size_t)alignment_bytes);
data_offset_bytes += alignment_offset_bytes;
}
if (crypt_get_metadata_size_bytes(cd) && (crypt_get_metadata_size_bytes(cd) != metadata_size_bytes))
log_std(cd, _("WARNING: LUKS2 metadata size changed to %" PRIu64 " bytes.\n"),
metadata_size_bytes);
if (crypt_get_keyslots_size_bytes(cd) && (crypt_get_keyslots_size_bytes(cd) != keyslots_size_bytes))
log_std(cd, _("WARNING: LUKS2 keyslots area size changed to %" PRIu64 " bytes.\n"),
keyslots_size_bytes);
*ret_metadata_size_bytes = metadata_size_bytes;
*ret_keyslots_size_bytes = keyslots_size_bytes;
*ret_data_offset_bytes = data_offset_bytes;
return 0;
}

View File

@@ -1,9 +1,9 @@
/*
* LUKS - Linux Unified Key Setup v2
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2022 Ondrej Kozina
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
* Copyright (C) 2015-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,6 +21,7 @@
*/
#include "luks2_internal.h"
#include "luks2/hw_opal/hw_opal.h"
#include "../integrity/integrity.h"
#include <ctype.h>
#include <uuid/uuid.h>
@@ -88,6 +89,9 @@ struct json_object *LUKS2_array_remove(struct json_object *array, const char *nu
/* Create new array without jobj_removing. */
array_new = json_object_new_array();
if (!array_new)
return NULL;
for (i = 0; i < (int) json_object_array_length(array); i++) {
jobj1 = json_object_array_get_idx(array, i);
if (jobj1 != jobj_removing)
@@ -478,6 +482,9 @@ static int hdr_validate_json_size(struct crypt_device *cd, json_object *hdr_jobj
json = json_object_to_json_string_ext(hdr_jobj,
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
if (!json)
return 1;
json_area_size = crypt_jobj_get_uint64(jobj1);
json_size = (uint64_t)strlen(json);
@@ -637,6 +644,11 @@ static int reqs_reencrypt_online(uint32_t reqs)
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
static int reqs_opal(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_OPAL;
}
/*
* Config section requirements object must be valid.
* Also general segments section must be validated first.
@@ -697,7 +709,7 @@ static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
{
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
uint64_t offset, size;
uint64_t offset, size, opal_segment_size;
int i, r, count, first_backup = -1;
struct interval *intervals = NULL;
@@ -777,6 +789,32 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
if (!strcmp(json_object_get_string(jobj_type), "crypt") &&
hdr_validate_crypt_segment(cd, val, key, jobj_digests, size))
return 1;
/* opal */
if (!strncmp(json_object_get_string(jobj_type), "hw-opal", 7)) {
if (!size) {
log_dbg(cd, "segment type %s does not support dynamic size.",
json_object_get_string(jobj_type));
return 1;
}
if (!json_contains(cd, val, key, "Segment", "opal_segment_number", json_type_int) ||
!json_contains(cd, val, key, "Segment", "opal_key_size", json_type_int) ||
!(jobj_size = json_contains_string(cd, val, key, "Segment", "opal_segment_size")))
return 1;
if (!numbered(cd, "opal_segment_size", json_object_get_string(jobj_size)))
return 1;
if (!json_str_to_uint64(jobj_size, &opal_segment_size) || !opal_segment_size) {
log_dbg(cd, "Illegal OPAL segment size value.");
return 1;
}
if (size > opal_segment_size) {
log_dbg(cd, "segment size overflows OPAL locking range size.");
return 1;
}
if (!strcmp(json_object_get_string(jobj_type), "hw-opal-crypt") &&
hdr_validate_crypt_segment(cd, val, key, jobj_digests, size))
return 1;
}
}
if (first_backup == 0) {
@@ -1575,6 +1613,8 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
return 0;
jobj_flags = json_object_new_array();
if (!jobj_flags)
return -ENOMEM;
for (i = 0; persistent_flags[i].description; i++) {
if (flags & persistent_flags[i].flag) {
@@ -1615,6 +1655,7 @@ static const struct requirement_flag requirements_flags[] = {
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 3, "online-reencrypt-v3" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
{ CRYPT_REQUIREMENT_OPAL, 1, "opal" },
{ 0, 0, NULL }
};
@@ -1707,7 +1748,7 @@ int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint8_t *version)
return -ENOENT;
}
static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
static const struct requirement_flag *stored_requirement_name_by_id(struct luks2_hdr *hdr, uint32_t req_id)
{
json_object *jobj_mandatory, *jobj;
int i, len;
@@ -1786,7 +1827,7 @@ int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
req_id = reqs & requirements_flags[i].flag;
if (req_id) {
/* retain already stored version of requirement flag */
req = stored_requirement_name_by_id(cd, hdr, req_id);
req = stored_requirement_name_by_id(hdr, req_id);
if (req)
jobj = json_object_new_string(req->description);
else
@@ -2090,6 +2131,8 @@ static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj)
if (json_object_object_get_ex(jobj_segment, "encryption", &jobj1))
log_std(cd, "\tcipher: %s\n", json_object_get_string(jobj1));
else
log_std(cd, "\tcipher: (no SW encryption)\n");
if (json_object_object_get_ex(jobj_segment, "sector_size", &jobj1))
log_std(cd, "\tsector: %" PRIu32 " [bytes]\n", crypt_jobj_get_uint32(jobj1));
@@ -2109,6 +2152,18 @@ static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj)
log_std(cd, "\n");
}
json_object_object_get_ex(jobj_segment, "type", &jobj1);
if (!strncmp(json_object_get_string(jobj1), "hw-opal", 7)) {
log_std(cd, "\tHW OPAL encryption:\n");
json_object_object_get_ex(jobj_segment, "opal_segment_number", &jobj1);
log_std(cd, "\t\tOPAL segment number: %" PRIu32 "\n", crypt_jobj_get_uint32(jobj1));
json_object_object_get_ex(jobj_segment, "opal_key_size", &jobj1);
log_std(cd, "\t\tOPAL key: %" PRIu32 " bits\n", crypt_jobj_get_uint32(jobj1) * 8);
json_object_object_get_ex(jobj_segment, "opal_segment_size", &jobj1);
json_str_to_uint64(jobj1, &value);
log_std(cd, "\t\tOPAL segment length: %" PRIu64 " [bytes]\n", value);
}
log_std(cd, "\n");
}
}
@@ -2584,26 +2639,104 @@ int LUKS2_activate_multi(struct crypt_device *cd,
int LUKS2_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
struct volume_key *crypt_key,
struct volume_key *opal_key,
uint32_t flags)
{
int r;
bool dynamic, read_lock, write_lock, opal_lock_on_error = false;
uint32_t opal_segment_number;
uint64_t range_offset_sectors, range_length_sectors, device_length_bytes;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
struct crypt_dm_active_device dmdi = {}, dmd = {
.uuid = crypt_get_uuid(cd)
};
struct crypt_lock_handle *opal_lh = NULL;
/* do not allow activation when particular requirements detected */
if ((r = LUKS2_unmet_requirements(cd, hdr, 0, 0)))
if ((r = LUKS2_unmet_requirements(cd, hdr, CRYPT_REQUIREMENT_OPAL, 0)))
return r;
r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd),
crypt_get_data_offset(cd), crypt_get_integrity(cd) ?: "none",
crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
if (r < 0)
/* Check that cipher is in compatible format */
if (!crypt_get_cipher(cd)) {
log_err(cd, _("No known cipher specification pattern detected in LUKS2 header."));
return -EINVAL;
}
if ((r = LUKS2_get_data_size(hdr, &device_length_bytes, &dynamic)))
return r;
if (dynamic && opal_key) {
log_err(cd, _("OPAL device must have static device size."));
return -EINVAL;
}
if (!dynamic)
dmd.size = device_length_bytes / SECTOR_SIZE;
if (opal_key) {
r = crypt_opal_supported(cd, crypt_data_device(cd));
if (r < 0)
return r;
r = LUKS2_get_opal_segment_number(hdr, CRYPT_DEFAULT_SEGMENT, &opal_segment_number);
if (r < 0)
return -EINVAL;
range_length_sectors = LUKS2_opal_segment_size(hdr, CRYPT_DEFAULT_SEGMENT, 1);
if (crypt_get_integrity_tag_size(cd)) {
if (dmd.size >= range_length_sectors) {
log_err(cd, _("Encrypted OPAL device with integrity must be smaller than locking range."));
return -EINVAL;
}
} else {
if (range_length_sectors != dmd.size) {
log_err(cd, _("OPAL device must have same size as locking range."));
return -EINVAL;
}
}
range_offset_sectors = crypt_get_data_offset(cd) + crypt_dev_partition_offset(device_path(crypt_data_device(cd)));
r = opal_exclusive_lock(cd, crypt_data_device(cd), &opal_lh);
if (r < 0) {
log_err(cd, _("Failed to acquire OPAL lock on device %s."), device_path(crypt_data_device(cd)));
return -EINVAL;
}
r = opal_range_check_attributes_and_get_lock_state(cd, crypt_data_device(cd), opal_segment_number,
opal_key, &range_offset_sectors, &range_length_sectors,
&read_lock, &write_lock);
if (r < 0)
goto out;
opal_lock_on_error = read_lock && write_lock;
if (!opal_lock_on_error && !(flags & CRYPT_ACTIVATE_REFRESH))
log_std(cd, _("OPAL device is %s already unlocked.\n"),
device_path(crypt_data_device(cd)));
r = opal_unlock(cd, crypt_data_device(cd), opal_segment_number, opal_key);
if (r < 0)
goto out;
}
if (LUKS2_segment_is_type(hdr, CRYPT_DEFAULT_SEGMENT, "crypt") ||
LUKS2_segment_is_type(hdr, CRYPT_DEFAULT_SEGMENT, "hw-opal-crypt")) {
r = dm_crypt_target_set(&dmd.segment, 0,
dmd.size, crypt_data_device(cd),
crypt_key, crypt_get_cipher_spec(cd),
crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
crypt_get_integrity(cd) ?: "none",
crypt_get_integrity_tag_size(cd),
crypt_get_sector_size(cd));
} else
r = dm_linear_target_set(&dmd.segment, 0,
dmd.size, crypt_data_device(cd),
crypt_get_data_offset(cd));
if (r < 0)
goto out;
/* Add persistent activation flags */
if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT))
LUKS2_config_get_flags(cd, hdr, &dmd.flags);
@@ -2613,29 +2746,47 @@ int LUKS2_activate(struct crypt_device *cd,
if (crypt_get_integrity_tag_size(cd)) {
if (!LUKS2_integrity_compatible(hdr)) {
log_err(cd, _("Unsupported device integrity configuration."));
return -EINVAL;
r = -EINVAL;
goto out;
}
if (dmd.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
log_err(cd, _("Discard/TRIM is not supported."));
return -EINVAL;
r = -EINVAL;
goto out;
}
r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags, 0);
if (r)
return r;
goto out;
if (!dynamic && dmdi.size != dmd.size) {
log_err(cd, _("Underlying dm-integrity device with unexpected provided data sectors."));
r = -EINVAL;
goto out;
}
dmdi.flags |= CRYPT_ACTIVATE_PRIVATE;
dmdi.uuid = dmd.uuid;
dmd.segment.u.crypt.offset = 0;
dmd.segment.size = dmdi.segment.size;
if (dynamic)
dmd.segment.size = dmdi.segment.size;
r = create_or_reload_device_with_integrity(cd, name, CRYPT_LUKS2, &dmd, &dmdi);
r = create_or_reload_device_with_integrity(cd, name,
opal_key ? CRYPT_LUKS2_HW_OPAL : CRYPT_LUKS2,
&dmd, &dmdi);
} else
r = create_or_reload_device(cd, name, CRYPT_LUKS2, &dmd);
r = create_or_reload_device(cd, name,
opal_key ? CRYPT_LUKS2_HW_OPAL : CRYPT_LUKS2,
&dmd);
dm_targets_free(cd, &dmd);
dm_targets_free(cd, &dmdi);
out:
if (r < 0 && opal_lock_on_error)
opal_lock(cd, crypt_data_device(cd), opal_segment_number);
opal_exclusive_unlock(cd, opal_lh);
return r;
}
@@ -2665,13 +2816,15 @@ static bool contains_reencryption_helper(char **names)
int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr *hdr, struct crypt_dm_active_device *dmd, uint32_t flags)
{
bool dm_opal_uuid;
int r, ret;
struct dm_target *tgt;
crypt_status_info ci;
struct crypt_dm_active_device dmdc;
uint32_t opal_segment_number;
char **dep, deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = { 0 };
const char *namei = NULL;
struct crypt_lock_handle *reencrypt_lock = NULL;
struct crypt_lock_handle *reencrypt_lock = NULL, *opal_lh = NULL;
if (!dmd || !dmd->uuid || strncmp(CRYPT_LUKS2, dmd->uuid, sizeof(CRYPT_LUKS2)-1))
return -EINVAL;
@@ -2684,6 +2837,11 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
if (r < 0 || (size_t)r != (sizeof(deps_uuid_prefix) - 1))
return -EINVAL;
/* check if active device has LUKS2-OPAL dm uuid prefix */
dm_opal_uuid = !crypt_uuid_type_cmp(dmd->uuid, CRYPT_LUKS2_HW_OPAL);
if (dm_opal_uuid && hdr && !LUKS2_segment_is_hw_opal(hdr, CRYPT_DEFAULT_SEGMENT))
return -EINVAL;
tgt = &dmd->segment;
/* TODO: We have LUKS2 dependencies now */
@@ -2726,7 +2884,8 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
tgt = &dmdc.segment;
while (tgt) {
if (tgt->type == DM_CRYPT)
crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY);
crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description,
LOGON_KEY);
tgt = tgt->next;
}
}
@@ -2761,7 +2920,8 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
tgt = &dmdc.segment;
while (tgt) {
if (tgt->type == DM_CRYPT)
crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY);
crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description,
LOGON_KEY);
tgt = tgt->next;
}
}
@@ -2773,7 +2933,35 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr
r = ret;
}
if (!r && dm_opal_uuid) {
if (hdr) {
if (LUKS2_get_opal_segment_number(hdr, CRYPT_DEFAULT_SEGMENT, &opal_segment_number)) {
log_err(cd, _("Device %s was deactivated but hardware OPAL device cannot be locked."),
name);
r = -EINVAL;
goto out;
}
} else {
/* Guess OPAL range number for LUKS2-OPAL device with missing header */
opal_segment_number = 1;
ret = crypt_dev_get_partition_number(device_path(crypt_data_device(cd)));
if (ret > 0)
opal_segment_number = ret;
}
if (crypt_data_device(cd)) {
r = opal_exclusive_lock(cd, crypt_data_device(cd), &opal_lh);
if (r < 0) {
log_err(cd, _("Failed to acquire OPAL lock on device %s."), device_path(crypt_data_device(cd)));
goto out;
}
}
if (!crypt_data_device(cd) || opal_lock(cd, crypt_data_device(cd), opal_segment_number))
log_err(cd, _("Device %s was deactivated but hardware OPAL device cannot be locked."), name);
}
out:
opal_exclusive_unlock(cd, opal_lh);
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
dep = deps;
while (*dep)
@@ -2807,6 +2995,8 @@ int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uin
log_err(cd, _("Operation incompatible with device marked for legacy reencryption. Aborting."));
if (reqs_reencrypt_online(reqs) && !quiet)
log_err(cd, _("Operation incompatible with device marked for LUKS2 reencryption. Aborting."));
if (reqs_opal(reqs) && !quiet)
log_err(cd, _("Operation incompatible with device using OPAL. Aborting."));
/* any remaining unmasked requirement fails the check */
return reqs ? -EINVAL : 0;
@@ -2859,6 +3049,20 @@ int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object
#endif
}
int json_object_object_add_by_uint_by_ref(json_object *jobj, unsigned key, json_object **jobj_val_ref)
{
int r;
assert(jobj);
assert(jobj_val_ref);
r = json_object_object_add_by_uint(jobj, key, *jobj_val_ref);
if (!r)
*jobj_val_ref = NULL;
return r;
}
/* jobj_dst must contain pointer initialized to NULL (see json-c json_object_deep_copy API) */
int json_object_copy(json_object *jobj_src, json_object **jobj_dst)
{
@@ -2872,3 +3076,58 @@ int json_object_copy(json_object *jobj_src, json_object **jobj_dst)
return *jobj_dst ? 0 : -1;
#endif
}
int LUKS2_split_crypt_and_opal_keys(struct crypt_device *cd __attribute__((unused)),
struct luks2_hdr *hdr,
const struct volume_key *vk,
struct volume_key **ret_crypt_key,
struct volume_key **ret_opal_key)
{
int r;
uint32_t opal_segment_number;
size_t opal_user_key_size;
json_object *jobj_segment;
struct volume_key *opal_key, *crypt_key;
assert(vk);
assert(ret_crypt_key);
assert(ret_opal_key);
jobj_segment = LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT);
if (!jobj_segment)
return -EINVAL;
r = json_segment_get_opal_segment_id(jobj_segment, &opal_segment_number);
if (r < 0)
return -EINVAL;
r = json_segment_get_opal_key_size(jobj_segment, &opal_user_key_size);
if (r < 0)
return -EINVAL;
if (vk->keylength < opal_user_key_size)
return -EINVAL;
/* OPAL SEGMENT only */
if (vk->keylength == opal_user_key_size) {
*ret_crypt_key = NULL;
*ret_opal_key = NULL;
return 0;
}
opal_key = crypt_alloc_volume_key(opal_user_key_size, vk->key);
if (!opal_key)
return -ENOMEM;
crypt_key = crypt_alloc_volume_key(vk->keylength - opal_user_key_size,
vk->key + opal_user_key_size);
if (!crypt_key) {
crypt_free_volume_key(opal_key);
return -ENOMEM;
}
*ret_opal_key = opal_key;
*ret_crypt_key = crypt_key;
return 0;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, keyslot handling
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -578,6 +578,8 @@ int LUKS2_keyslot_open(struct crypt_device *cd,
int r_prio, r = -EINVAL;
hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
if (!hdr)
return -EINVAL;
if (keyslot == CRYPT_ANY_SLOT) {
r_prio = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_PREFER,
@@ -676,8 +678,7 @@ int LUKS2_keyslot_store(struct crypt_device *cd,
int LUKS2_keyslot_wipe(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int wipe_area_only)
int keyslot)
{
struct device *device = crypt_metadata_device(cd);
uint64_t area_offset, area_length;
@@ -694,9 +695,6 @@ int LUKS2_keyslot_wipe(struct crypt_device *cd,
if (!jobj_keyslot)
return -ENOENT;
if (wipe_area_only)
log_dbg(cd, "Wiping keyslot %d area only.", keyslot);
r = LUKS2_device_write_lock(cd, hdr, device);
if (r)
return r;
@@ -720,9 +718,6 @@ int LUKS2_keyslot_wipe(struct crypt_device *cd,
}
}
if (wipe_area_only)
goto out;
/* Slot specific wipe */
if (h) {
r = h->wipe(cd, keyslot);
@@ -803,6 +798,9 @@ int placeholder_keyslot_alloc(struct crypt_device *cd,
return -EINVAL;
jobj_keyslot = json_object_new_object();
if (!jobj_keyslot)
return -ENOMEM;
json_object_object_add(jobj_keyslot, "type", json_object_new_string("placeholder"));
/*
* key_size = -1 makes placeholder keyslot impossible to pass validation.
@@ -813,11 +811,19 @@ int placeholder_keyslot_alloc(struct crypt_device *cd,
/* Area object */
jobj_area = json_object_new_object();
if (!jobj_area) {
json_object_put(jobj_keyslot);
return -ENOMEM;
}
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
json_object_object_add(jobj_keyslot, "area", jobj_area);
json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
if (json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot)) {
json_object_put(jobj_keyslot);
return -EINVAL;
}
return 0;
}
@@ -899,7 +905,7 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
return 0;
}
void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_keyslots)
void LUKS2_keyslots_repair(struct crypt_device *cd __attribute__((unused)), json_object *jobj_keyslots)
{
const keyslot_handler *h;
json_object *jobj_type;
@@ -964,14 +970,17 @@ int LUKS2_keyslot_swap(struct crypt_device *cd, struct luks2_hdr *hdr,
json_object_object_del_by_uint(jobj_keyslots, keyslot);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot2);
if (r < 0) {
json_object_put(jobj_keyslot2);
log_dbg(cd, "Failed to swap keyslot %d.", keyslot);
return r;
}
json_object_object_del_by_uint(jobj_keyslots, keyslot2);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot2, jobj_keyslot);
if (r < 0)
if (r < 0) {
json_object_put(jobj_keyslot);
log_dbg(cd, "Failed to swap keyslot2 %d.", keyslot2);
}
return r;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS2 type keyslot handler
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <limits.h>
#include "luks2_internal.h"
/* FIXME: move keyslot encryption to crypto backend */
@@ -264,6 +265,9 @@ static int luks2_keyslot_set_key(struct crypt_device *cd,
pbkdf.parallel_threads);
free(salt);
if (r < 0) {
if ((crypt_backend_flags() & CRYPT_BACKEND_PBKDF2_INT) &&
pbkdf.iterations > INT_MAX)
log_err(cd, _("PBKDF2 iteration value overflow."));
crypt_free_volume_key(derived_key);
return r;
}
@@ -303,7 +307,7 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
char *volume_key, size_t volume_key_len)
{
struct volume_key *derived_key = NULL;
struct crypt_pbkdf_type pbkdf;
struct crypt_pbkdf_type pbkdf, *cd_pbkdf;
char *AfKey = NULL;
size_t AFEKSize;
const char *af_hash = NULL;
@@ -356,6 +360,16 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
goto out;
}
/*
* Print warning when keyslot requires more memory than available
* (if maximum memory was adjusted - no swap, not enough memory),
* but be silent if user set keyslot memory cost above default limit intentionally.
*/
cd_pbkdf = crypt_get_pbkdf(cd);
if (cd_pbkdf->max_memory_kb && pbkdf.max_memory_kb > cd_pbkdf->max_memory_kb &&
pbkdf.max_memory_kb <= DEFAULT_LUKS2_MEMORY_KB)
log_std(cd, _("Warning: keyslot operation could fail as it requires more than available memory.\n"));
/*
* If requested, serialize unlocking for memory-hard KDF. Usually NOOP.
*/
@@ -508,23 +522,42 @@ static int luks2_keyslot_alloc(struct crypt_device *cd,
}
jobj_keyslot = json_object_new_object();
if (!jobj_keyslot) {
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_keyslot, "type", json_object_new_string("luks2"));
json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(volume_key_len));
/* AF object */
jobj_af = json_object_new_object();
if (!jobj_af) {
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_af, "type", json_object_new_string("luks1"));
json_object_object_add(jobj_af, "stripes", json_object_new_int(params->af.luks1.stripes));
json_object_object_add(jobj_keyslot, "af", jobj_af);
/* Area object */
jobj_area = json_object_new_object();
if (!jobj_area) {
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
json_object_object_add(jobj_keyslot, "area", jobj_area);
json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
if (r) {
json_object_put(jobj_keyslot);
return r;
}
r = luks2_keyslot_update_json(cd, jobj_keyslot, params);
@@ -537,6 +570,9 @@ static int luks2_keyslot_alloc(struct crypt_device *cd,
json_object_object_del_by_uint(jobj_keyslots, keyslot);
return r;
err:
json_object_put(jobj_keyslot);
return r;
}
static int luks2_keyslot_open(struct crypt_device *cd,

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, reencryption keyslot handler
*
* Copyright (C) 2016-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2022 Ondrej Kozina
* Copyright (C) 2016-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -145,7 +145,12 @@ static int reenc_keyslot_alloc(struct crypt_device *cd,
else
json_object_object_add(jobj_keyslot, "direction", json_object_new_string("backward"));
json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
if (r) {
json_object_put(jobj_keyslot);
return r;
}
if (LUKS2_check_json_size(cd, hdr)) {
log_dbg(cd, "New keyslot too large to fit in free metadata space.");
json_object_object_del_by_uint(jobj_keyslots, keyslot);
@@ -371,8 +376,7 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
return 0;
}
static int reenc_keyslot_update_needed(struct crypt_device *cd,
json_object *jobj_keyslot,
static int reenc_keyslot_update_needed(json_object *jobj_keyslot,
const struct crypt_params_reencrypt *params,
size_t alignment)
{
@@ -537,8 +541,7 @@ static int reenc_keyslot_load_resilience(struct crypt_device *cd,
return reenc_keyslot_load_resilience_secondary(cd, type, jobj_area, area_length, rp);
}
static bool reenc_keyslot_update_is_valid(struct crypt_device *cd,
json_object *jobj_area,
static bool reenc_keyslot_update_is_valid(json_object *jobj_area,
const struct crypt_params_reencrypt *params)
{
const char *type;
@@ -589,7 +592,7 @@ static int reenc_keyslot_update(struct crypt_device *cd,
if (!params || !params->resilience)
jobj_area_new = reencrypt_keyslot_area_jobj_update_block_size(cd, jobj_area, alignment);
else {
if (!reenc_keyslot_update_is_valid(cd, jobj_area, params)) {
if (!reenc_keyslot_update_is_valid(jobj_area, params)) {
log_err(cd, _("Invalid reencryption resilience mode change requested."));
return -EINVAL;
}
@@ -661,7 +664,7 @@ int LUKS2_keyslot_reencrypt_update_needed(struct crypt_device *cd,
strcmp(json_object_get_string(jobj_type), "reencrypt"))
return -EINVAL;
r = reenc_keyslot_update_needed(cd, jobj_keyslot, params, alignment);
r = reenc_keyslot_update_needed(jobj_keyslot, params, alignment);
if (!r)
log_dbg(cd, "No update of reencrypt keyslot needed.");

View File

@@ -1,9 +1,9 @@
/*
* LUKS - Linux Unified Key Setup v2, LUKS1 conversion code
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Ondrej Kozina
* Copyright (C) 2015-2022 Milan Broz
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Ondrej Kozina
* Copyright (C) 2015-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -67,11 +67,21 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
int r;
keyslot_obj = json_object_new_object();
if (!keyslot_obj) {
r = -ENOMEM;
goto err;
}
json_object_object_add(keyslot_obj, "type", json_object_new_string("luks2"));
json_object_object_add(keyslot_obj, "key_size", json_object_new_int64(hdr_v1->keyBytes));
/* KDF */
jobj_kdf = json_object_new_object();
if (!jobj_kdf) {
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_kdf, "type", json_object_new_string(CRYPT_KDF_PBKDF2));
json_object_object_add(jobj_kdf, "hash", json_object_new_string(hdr_v1->hashSpec));
json_object_object_add(jobj_kdf, "iterations", json_object_new_int64(hdr_v1->keyblock[keyslot].passwordIterations));
@@ -89,6 +99,11 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
/* AF */
jobj_af = json_object_new_object();
if (!jobj_af) {
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_af, "type", json_object_new_string("luks1"));
json_object_object_add(jobj_af, "hash", json_object_new_string(hdr_v1->hashSpec));
/* stripes field ignored, fixed to LUKS_STRIPES (4000) */
@@ -97,6 +112,11 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
/* Area */
jobj_area = json_object_new_object();
if (!jobj_area) {
r = -ENOMEM;
goto err;
}
json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
/* encryption algorithm field */
@@ -124,6 +144,9 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
*keyslot_object = keyslot_obj;
return 0;
err:
json_object_put(keyslot_obj);
return r;
}
static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_object **keyslots_object)
@@ -143,7 +166,12 @@ static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_objec
json_object_put(keyslot_obj);
return r;
}
json_object_object_add_by_uint(keyslot_obj, keyslot, field);
r = json_object_object_add_by_uint(keyslot_obj, keyslot, field);
if (r) {
json_object_put(field);
json_object_put(keyslot_obj);
return r;
}
}
*keyslots_object = keyslot_obj;
@@ -238,7 +266,12 @@ static int json_luks1_segments(const struct luks_phdr *hdr_v1, struct json_objec
json_object_put(segments_obj);
return r;
}
json_object_object_add_by_uint(segments_obj, 0, field);
r = json_object_object_add_by_uint(segments_obj, 0, field);
if (r) {
json_object_put(field);
json_object_put(segments_obj);
return r;
}
*segments_object = segments_obj;
return 0;

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, reencryption helpers
*
* Copyright (C) 2015-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2022 Ondrej Kozina
* Copyright (C) 2015-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2015-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -162,6 +162,7 @@ static uint64_t reencrypt_get_data_offset_old(struct luks2_hdr *hdr)
return reencrypt_data_offset(hdr, 0);
}
#endif
static int reencrypt_digest(struct luks2_hdr *hdr, unsigned new)
{
int segment = LUKS2_get_segment_id_by_flag(hdr, new ? "backup-final" : "backup-previous");
@@ -182,6 +183,21 @@ int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr)
return reencrypt_digest(hdr, 0);
}
unsigned LUKS2_reencrypt_vks_count(struct luks2_hdr *hdr)
{
int digest_old, digest_new;
unsigned vks_count = 0;
if ((digest_new = LUKS2_reencrypt_digest_new(hdr)) >= 0)
vks_count++;
if ((digest_old = LUKS2_reencrypt_digest_old(hdr)) >= 0) {
if (digest_old != digest_new)
vks_count++;
}
return vks_count;
}
/* none, checksums, journal or shift */
static const char *reencrypt_resilience_type(struct luks2_hdr *hdr)
{
@@ -224,7 +240,7 @@ static const char *reencrypt_resilience_hash(struct luks2_hdr *hdr)
static json_object *_enc_create_segments_shift_after(struct luks2_reencrypt *rh, uint64_t data_offset)
{
int reenc_seg, i = 0;
json_object *jobj_copy, *jobj_seg_new = NULL, *jobj_segs_post = json_object_new_object();
json_object *jobj, *jobj_copy = NULL, *jobj_seg_new = NULL, *jobj_segs_post = json_object_new_object();
uint64_t tmp;
if (!rh->jobj_segs_hot || !jobj_segs_post)
@@ -239,17 +255,21 @@ static json_object *_enc_create_segments_shift_after(struct luks2_reencrypt *rh,
while (i < reenc_seg) {
jobj_copy = json_segments_get_segment(rh->jobj_segs_hot, i);
if (!jobj_copy)
if (!jobj_copy || json_object_object_add_by_uint(jobj_segs_post, i++, json_object_get(jobj_copy)))
goto err;
json_object_object_add_by_uint(jobj_segs_post, i++, json_object_get(jobj_copy));
}
jobj_copy = NULL;
if (json_object_copy(json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1), &jobj_seg_new)) {
if (json_object_copy(json_segments_get_segment(rh->jobj_segs_hot, reenc_seg), &jobj_seg_new))
jobj = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1);
if (!jobj) {
jobj = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg);
if (!jobj || json_object_copy(jobj, &jobj_seg_new))
goto err;
json_segment_remove_flag(jobj_seg_new, "in-reencryption");
tmp = rh->length;
} else {
if (json_object_copy(jobj, &jobj_seg_new))
goto err;
json_object_object_add(jobj_seg_new, "offset", crypt_jobj_new_uint64(rh->offset + data_offset));
json_object_object_add(jobj_seg_new, "iv_tweak", crypt_jobj_new_uint64(rh->offset >> SECTOR_SHIFT));
tmp = json_segment_get_size(jobj_seg_new, 0) + rh->length;
@@ -257,10 +277,12 @@ static json_object *_enc_create_segments_shift_after(struct luks2_reencrypt *rh,
/* alter size of new segment, reenc_seg == 0 we're finished */
json_object_object_add(jobj_seg_new, "size", reenc_seg > 0 ? crypt_jobj_new_uint64(tmp) : json_object_new_string("dynamic"));
json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_seg_new);
if (!json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_seg_new))
return jobj_segs_post;
return jobj_segs_post;
err:
json_object_put(jobj_seg_new);
json_object_put(jobj_copy);
json_object_put(jobj_segs_post);
return NULL;
}
@@ -271,7 +293,7 @@ static json_object *reencrypt_make_hot_segments_encrypt_shift(struct luks2_hdr *
{
int sg, crypt_seg, i = 0;
uint64_t segment_size;
json_object *jobj_seg_shrunk, *jobj_seg_new, *jobj_copy, *jobj_enc_seg = NULL,
json_object *jobj_seg_shrunk = NULL, *jobj_seg_new = NULL, *jobj_copy = NULL, *jobj_enc_seg = NULL,
*jobj_segs_hot = json_object_new_object();
if (!jobj_segs_hot)
@@ -290,38 +312,41 @@ static json_object *reencrypt_make_hot_segments_encrypt_shift(struct luks2_hdr *
rh->offset >> SECTOR_SHIFT,
&rh->length,
reencrypt_segment_cipher_new(hdr),
NULL, /* integrity */
reencrypt_get_sector_size_new(hdr),
1);
while (i < sg) {
jobj_copy = LUKS2_get_segment_jobj(hdr, i);
if (!jobj_copy)
if (!jobj_copy || json_object_object_add_by_uint(jobj_segs_hot, i++, json_object_get(jobj_copy)))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, i++, json_object_get(jobj_copy));
}
jobj_copy = NULL;
segment_size = LUKS2_segment_size(hdr, sg, 0);
if (segment_size > rh->length) {
jobj_seg_shrunk = NULL;
if (json_object_copy(LUKS2_get_segment_jobj(hdr, sg), &jobj_seg_shrunk))
goto err;
json_object_object_add(jobj_seg_shrunk, "size", crypt_jobj_new_uint64(segment_size - rh->length));
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_seg_shrunk);
if (json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_seg_shrunk))
goto err;
}
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_enc_seg);
jobj_enc_seg = NULL; /* see err: label */
if (json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_enc_seg))
goto err;
/* first crypt segment after encryption ? */
if (crypt_seg >= 0) {
jobj_seg_new = LUKS2_get_segment_jobj(hdr, crypt_seg);
if (!jobj_seg_new)
if (!jobj_seg_new || json_object_object_add_by_uint(jobj_segs_hot, sg, json_object_get(jobj_seg_new)))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg, json_object_get(jobj_seg_new));
}
return jobj_segs_hot;
err:
json_object_put(jobj_copy);
json_object_put(jobj_seg_new);
json_object_put(jobj_seg_shrunk);
json_object_put(jobj_enc_seg);
json_object_put(jobj_segs_hot);
@@ -343,6 +368,7 @@ static json_object *reencrypt_make_segment_new(struct crypt_device *cd,
crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT),
segment_length,
reencrypt_segment_cipher_new(hdr),
NULL, /* integrity */
reencrypt_get_sector_size_new(hdr), 0);
case CRYPT_REENCRYPT_DECRYPT:
return json_segment_create_linear(data_offset + segment_offset, segment_length, 0);
@@ -357,7 +383,7 @@ static json_object *reencrypt_make_post_segments_forward(struct crypt_device *cd
uint64_t data_offset)
{
int reenc_seg;
json_object *jobj_new_seg_after, *jobj_old_seg, *jobj_old_seg_copy = NULL,
json_object *jobj_old_seg, *jobj_new_seg_after = NULL, *jobj_old_seg_copy = NULL,
*jobj_segs_post = json_object_new_object();
uint64_t fixed_length = rh->offset + rh->length;
@@ -366,7 +392,7 @@ static json_object *reencrypt_make_post_segments_forward(struct crypt_device *cd
reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
if (reenc_seg < 0)
return NULL;
goto err;
jobj_old_seg = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1);
@@ -375,24 +401,26 @@ static json_object *reencrypt_make_post_segments_forward(struct crypt_device *cd
* Set size to 'dynamic' again.
*/
jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, jobj_old_seg ? &fixed_length : NULL);
if (!jobj_new_seg_after)
if (!jobj_new_seg_after || json_object_object_add_by_uint_by_ref(jobj_segs_post, 0, &jobj_new_seg_after))
goto err;
json_object_object_add_by_uint(jobj_segs_post, 0, jobj_new_seg_after);
if (jobj_old_seg) {
if (rh->fixed_length) {
if (json_object_copy(jobj_old_seg, &jobj_old_seg_copy))
goto err;
jobj_old_seg = jobj_old_seg_copy;
fixed_length = rh->device_size - fixed_length;
json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(fixed_length));
json_object_object_add(jobj_old_seg_copy, "size", crypt_jobj_new_uint64(fixed_length));
} else
json_object_get(jobj_old_seg);
json_object_object_add_by_uint(jobj_segs_post, 1, jobj_old_seg);
jobj_old_seg_copy = json_object_get(jobj_old_seg);
if (json_object_object_add_by_uint_by_ref(jobj_segs_post, 1, &jobj_old_seg_copy))
goto err;
}
return jobj_segs_post;
err:
json_object_put(jobj_new_seg_after);
json_object_put(jobj_old_seg_copy);
json_object_put(jobj_segs_post);
return NULL;
}
@@ -405,7 +433,7 @@ static json_object *reencrypt_make_post_segments_backward(struct crypt_device *c
int reenc_seg;
uint64_t fixed_length;
json_object *jobj_new_seg_after, *jobj_old_seg,
json_object *jobj_new_seg_after = NULL, *jobj_old_seg = NULL,
*jobj_segs_post = json_object_new_object();
if (!rh->jobj_segs_hot || !jobj_segs_post)
@@ -413,22 +441,26 @@ static json_object *reencrypt_make_post_segments_backward(struct crypt_device *c
reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
if (reenc_seg < 0)
return NULL;
goto err;
jobj_old_seg = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg - 1);
if (jobj_old_seg)
json_object_object_add_by_uint(jobj_segs_post, reenc_seg - 1, json_object_get(jobj_old_seg));
if (jobj_old_seg) {
json_object_get(jobj_old_seg);
if (json_object_object_add_by_uint_by_ref(jobj_segs_post, reenc_seg - 1, &jobj_old_seg))
goto err;
}
if (rh->fixed_length && rh->offset) {
fixed_length = rh->device_size - rh->offset;
jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset, rh->offset, &fixed_length);
} else
jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset, rh->offset, NULL);
if (!jobj_new_seg_after)
goto err;
json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_new_seg_after);
return jobj_segs_post;
if (jobj_new_seg_after && !json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_new_seg_after))
return jobj_segs_post;
err:
json_object_put(jobj_new_seg_after);
json_object_put(jobj_old_seg);
json_object_put(jobj_segs_post);
return NULL;
}
@@ -448,6 +480,7 @@ static json_object *reencrypt_make_segment_reencrypt(struct crypt_device *cd,
crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT),
segment_length,
reencrypt_segment_cipher_new(hdr),
NULL, /* integrity */
reencrypt_get_sector_size_new(hdr), 1);
case CRYPT_REENCRYPT_DECRYPT:
return json_segment_create_linear(data_offset + segment_offset, segment_length, 1);
@@ -472,6 +505,7 @@ static json_object *reencrypt_make_segment_old(struct crypt_device *cd,
crypt_get_iv_offset(cd) + (segment_offset >> SECTOR_SHIFT),
segment_length,
reencrypt_segment_cipher_old(hdr),
NULL, /* integrity */
reencrypt_get_sector_size_old(hdr),
0);
break;
@@ -488,38 +522,40 @@ static json_object *reencrypt_make_hot_segments_forward(struct crypt_device *cd,
uint64_t device_size,
uint64_t data_offset)
{
json_object *jobj_segs_hot, *jobj_reenc_seg, *jobj_old_seg, *jobj_new_seg;
uint64_t fixed_length, tmp = rh->offset + rh->length;
json_object *jobj_segs_hot = json_object_new_object(), *jobj_reenc_seg = NULL,
*jobj_old_seg = NULL, *jobj_new_seg = NULL;
unsigned int sg = 0;
jobj_segs_hot = json_object_new_object();
if (!jobj_segs_hot)
return NULL;
if (rh->offset) {
jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, &rh->offset);
if (!jobj_new_seg)
if (!jobj_new_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_new_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_new_seg);
}
jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset, rh->offset, rh->offset, &rh->length);
if (!jobj_reenc_seg)
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg);
if (json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_reenc_seg))
goto err;
if (tmp < device_size) {
fixed_length = device_size - tmp;
jobj_old_seg = reencrypt_make_segment_old(cd, hdr, rh, data_offset + data_shift_value(&rh->rp),
rh->offset + rh->length, rh->fixed_length ? &fixed_length : NULL);
if (!jobj_old_seg)
if (!jobj_old_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg, &jobj_old_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_old_seg);
}
return jobj_segs_hot;
err:
json_object_put(jobj_reenc_seg);
json_object_put(jobj_old_seg);
json_object_put(jobj_new_seg);
json_object_put(jobj_segs_hot);
return NULL;
}
@@ -528,29 +564,31 @@ static json_object *reencrypt_make_hot_segments_decrypt_shift(struct crypt_devic
struct luks2_hdr *hdr, struct luks2_reencrypt *rh,
uint64_t device_size, uint64_t data_offset)
{
json_object *jobj_segs_hot, *jobj_reenc_seg, *jobj_old_seg, *jobj_new_seg;
uint64_t fixed_length, tmp = rh->offset + rh->length, linear_length = rh->progress;
json_object *jobj, *jobj_segs_hot = json_object_new_object(), *jobj_reenc_seg = NULL,
*jobj_old_seg = NULL, *jobj_new_seg = NULL;
unsigned int sg = 0;
jobj_segs_hot = json_object_new_object();
if (!jobj_segs_hot)
return NULL;
if (rh->offset) {
jobj_new_seg = LUKS2_get_segment_jobj(hdr, 0);
if (!jobj_new_seg)
jobj = LUKS2_get_segment_jobj(hdr, 0);
if (!jobj)
goto err;
jobj_new_seg = json_object_get(jobj);
if (json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_new_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg++, json_object_get(jobj_new_seg));
if (linear_length) {
jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh,
data_offset,
json_segment_get_size(jobj_new_seg, 0),
json_segment_get_size(jobj, 0),
0,
&linear_length);
if (!jobj_new_seg)
if (!jobj_new_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_new_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_new_seg);
}
}
@@ -558,27 +596,29 @@ static json_object *reencrypt_make_hot_segments_decrypt_shift(struct crypt_devic
rh->offset,
rh->offset,
&rh->length);
if (!jobj_reenc_seg)
if (!jobj_reenc_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_reenc_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg);
if (!rh->offset && (jobj_new_seg = LUKS2_get_segment_jobj(hdr, 1)) &&
!json_segment_is_backup(jobj_new_seg))
json_object_object_add_by_uint(jobj_segs_hot, sg++, json_object_get(jobj_new_seg));
else if (tmp < device_size) {
if (!rh->offset && (jobj = LUKS2_get_segment_jobj(hdr, 1)) &&
!json_segment_is_backup(jobj)) {
jobj_new_seg = json_object_get(jobj);
if (json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_new_seg))
goto err;
} else if (tmp < device_size) {
fixed_length = device_size - tmp;
jobj_old_seg = reencrypt_make_segment_old(cd, hdr, rh,
data_offset + data_shift_value(&rh->rp),
rh->offset + rh->length,
rh->fixed_length ? &fixed_length : NULL);
if (!jobj_old_seg)
if (!jobj_old_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg, &jobj_old_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_old_seg);
}
return jobj_segs_hot;
err:
json_object_put(jobj_reenc_seg);
json_object_put(jobj_old_seg);
json_object_put(jobj_new_seg);
json_object_put(jobj_segs_hot);
return NULL;
}
@@ -589,7 +629,7 @@ static json_object *_dec_create_segments_shift_after(struct crypt_device *cd,
uint64_t data_offset)
{
int reenc_seg, i = 0;
json_object *jobj_copy, *jobj_seg_old, *jobj_seg_new,
json_object *jobj_seg_old, *jobj_copy = NULL, *jobj_seg_old_copy = NULL, *jobj_seg_new = NULL,
*jobj_segs_post = json_object_new_object();
unsigned segs;
uint64_t tmp;
@@ -607,9 +647,8 @@ static json_object *_dec_create_segments_shift_after(struct crypt_device *cd,
if (reenc_seg == 0) {
jobj_seg_new = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, NULL);
if (!jobj_seg_new)
if (!jobj_seg_new || json_object_object_add_by_uint(jobj_segs_post, 0, jobj_seg_new))
goto err;
json_object_object_add_by_uint(jobj_segs_post, 0, jobj_seg_new);
return jobj_segs_post;
}
@@ -617,22 +656,29 @@ static json_object *_dec_create_segments_shift_after(struct crypt_device *cd,
jobj_copy = json_segments_get_segment(rh->jobj_segs_hot, 0);
if (!jobj_copy)
goto err;
json_object_object_add_by_uint(jobj_segs_post, i++, json_object_get(jobj_copy));
json_object_get(jobj_copy);
if (json_object_object_add_by_uint_by_ref(jobj_segs_post, i++, &jobj_copy))
goto err;
jobj_seg_old = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1);
if ((jobj_seg_old = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1)))
jobj_seg_old_copy = json_object_get(jobj_seg_old);
tmp = rh->length + rh->progress;
jobj_seg_new = reencrypt_make_segment_new(cd, hdr, rh, data_offset,
json_segment_get_size(rh->jobj_segment_moved, 0),
data_shift_value(&rh->rp),
jobj_seg_old ? &tmp : NULL);
json_object_object_add_by_uint(jobj_segs_post, i++, jobj_seg_new);
if (!jobj_seg_new || json_object_object_add_by_uint_by_ref(jobj_segs_post, i++, &jobj_seg_new))
goto err;
if (jobj_seg_old)
json_object_object_add_by_uint(jobj_segs_post, i, json_object_get(jobj_seg_old));
if (jobj_seg_old_copy && json_object_object_add_by_uint(jobj_segs_post, i, jobj_seg_old_copy))
goto err;
return jobj_segs_post;
err:
json_object_put(jobj_copy);
json_object_put(jobj_seg_old_copy);
json_object_put(jobj_seg_new);
json_object_put(jobj_segs_post);
return NULL;
}
@@ -643,10 +689,10 @@ static json_object *reencrypt_make_hot_segments_backward(struct crypt_device *cd
uint64_t device_size,
uint64_t data_offset)
{
json_object *jobj_reenc_seg, *jobj_new_seg, *jobj_old_seg = NULL,
uint64_t fixed_length, tmp = rh->offset + rh->length;
json_object *jobj_reenc_seg = NULL, *jobj_new_seg = NULL, *jobj_old_seg = NULL,
*jobj_segs_hot = json_object_new_object();
int sg = 0;
uint64_t fixed_length, tmp = rh->offset + rh->length;
if (!jobj_segs_hot)
return NULL;
@@ -656,26 +702,27 @@ static json_object *reencrypt_make_hot_segments_backward(struct crypt_device *cd
goto err;
json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(rh->offset));
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_old_seg);
if (json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_old_seg))
goto err;
}
jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset, rh->offset, rh->offset, &rh->length);
if (!jobj_reenc_seg)
if (!jobj_reenc_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg++, &jobj_reenc_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg);
if (tmp < device_size) {
fixed_length = device_size - tmp;
jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset + rh->length,
rh->offset + rh->length, rh->fixed_length ? &fixed_length : NULL);
if (!jobj_new_seg)
if (!jobj_new_seg || json_object_object_add_by_uint_by_ref(jobj_segs_hot, sg, &jobj_new_seg))
goto err;
json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_new_seg);
}
return jobj_segs_hot;
err:
json_object_put(jobj_reenc_seg);
json_object_put(jobj_new_seg);
json_object_put(jobj_old_seg);
json_object_put(jobj_segs_hot);
return NULL;
}
@@ -733,6 +780,7 @@ static int reencrypt_make_post_segments(struct crypt_device *cd,
return rh->jobj_segs_post ? 0 : -EINVAL;
}
#endif
static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr)
{
json_object *jobj_keyslot, *jobj_area, *jobj_data_shift;
@@ -847,13 +895,13 @@ void LUKS2_reencrypt_free(struct crypt_device *cd, struct luks2_reencrypt *rh)
free(rh);
}
int LUKS2_reencrypt_max_hotzone_size(struct crypt_device *cd,
#if USE_LUKS2_REENCRYPTION
int LUKS2_reencrypt_max_hotzone_size(struct crypt_device *cd __attribute__((unused)),
struct luks2_hdr *hdr,
const struct reenc_protection *rp,
int reencrypt_keyslot,
uint64_t *r_length)
{
#if USE_LUKS2_REENCRYPTION
int r;
uint64_t dummy, area_length;
@@ -886,11 +934,8 @@ int LUKS2_reencrypt_max_hotzone_size(struct crypt_device *cd,
}
return -EINVAL;
#else
return -ENOTSUP;
#endif
}
#if USE_LUKS2_REENCRYPTION
static size_t reencrypt_get_alignment(struct crypt_device *cd,
struct luks2_hdr *hdr)
{
@@ -971,7 +1016,6 @@ static int reencrypt_offset_backward_moved(struct luks2_hdr *hdr, json_object *j
}
static int reencrypt_offset_forward_moved(struct luks2_hdr *hdr,
json_object *jobj_segments,
uint64_t data_shift,
uint64_t *offset)
{
@@ -1049,7 +1093,7 @@ static int reencrypt_offset(struct luks2_hdr *hdr,
if (di == CRYPT_REENCRYPT_FORWARD) {
if (reencrypt_mode(hdr) == CRYPT_REENCRYPT_DECRYPT &&
LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0) {
r = reencrypt_offset_forward_moved(hdr, jobj_segments, data_shift, offset);
r = reencrypt_offset_forward_moved(hdr, data_shift, offset);
if (!r && *offset > device_size)
*offset = device_size;
return r;
@@ -1386,7 +1430,7 @@ static int reencrypt_init_storage_wrappers(struct crypt_device *cd,
static int reencrypt_context_set_names(struct luks2_reencrypt *rh, const char *name)
{
if (!rh | !name)
if (!rh || !name)
return -EINVAL;
if (*name == '/') {
@@ -1964,9 +2008,7 @@ static int reencrypt_set_decrypt_shift_segments(struct crypt_device *cd,
crypt_reencrypt_direction_info di)
{
int r;
uint64_t first_segment_offset, first_segment_length,
second_segment_offset, second_segment_length,
data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
uint64_t data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *jobj_segments;
if (di == CRYPT_REENCRYPT_BACKWARD)
@@ -1976,47 +2018,49 @@ static int reencrypt_set_decrypt_shift_segments(struct crypt_device *cd,
* future data_device layout:
* [encrypted first segment (max data shift size)][gap (data shift size)][second encrypted data segment]
*/
first_segment_offset = 0;
first_segment_length = moved_segment_length;
if (dev_size > moved_segment_length) {
second_segment_offset = data_offset + first_segment_length;
second_segment_length = 0;
}
jobj_segments = json_object_new_object();
if (!jobj_segments)
return -ENOMEM;
r = -EINVAL;
jobj_segment_first = json_segment_create_crypt(first_segment_offset,
crypt_get_iv_offset(cd), &first_segment_length,
crypt_get_cipher_spec(cd), crypt_get_sector_size(cd), 0);
jobj_segment_first = json_segment_create_crypt(0, crypt_get_iv_offset(cd),
&moved_segment_length, crypt_get_cipher_spec(cd),
NULL, crypt_get_sector_size(cd), 0);
if (!jobj_segment_first) {
log_dbg(cd, "Failed generate 1st segment.");
return r;
goto err;
}
r = json_object_object_add_by_uint_by_ref(jobj_segments, 0, &jobj_segment_first);
if (r)
goto err;
if (dev_size > moved_segment_length) {
jobj_segment_second = json_segment_create_crypt(second_segment_offset,
crypt_get_iv_offset(cd) + (first_segment_length >> SECTOR_SHIFT),
second_segment_length ? &second_segment_length : NULL,
jobj_segment_second = json_segment_create_crypt(data_offset + moved_segment_length,
crypt_get_iv_offset(cd) + (moved_segment_length >> SECTOR_SHIFT),
NULL,
crypt_get_cipher_spec(cd),
NULL, /* integrity */
crypt_get_sector_size(cd), 0);
if (!jobj_segment_second) {
json_object_put(jobj_segment_first);
r = -EINVAL;
log_dbg(cd, "Failed generate 2nd segment.");
return r;
goto err;
}
r = json_object_object_add_by_uint_by_ref(jobj_segments, 1, &jobj_segment_second);
if (r)
goto err;
}
json_object_object_add(jobj_segments, "0", jobj_segment_first);
if (jobj_segment_second)
json_object_object_add(jobj_segments, "1", jobj_segment_second);
r = LUKS2_segments_set(cd, hdr, jobj_segments, 0);
return r ?: LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, 0, 1, 0);
if (!(r = LUKS2_segments_set(cd, hdr, jobj_segments, 0)))
return LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, 0, 1, 0);
err:
json_object_put(jobj_segment_first);
json_object_put(jobj_segment_second);
json_object_put(jobj_segments);
return r;
}
static int reencrypt_make_targets(struct crypt_device *cd,
@@ -2429,6 +2473,7 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
uint64_t data_offset,
const struct crypt_params_reencrypt *params)
{
const char *type;
int r, segment, moved_segment = -1, digest_old = -1, digest_new = -1;
json_object *jobj_tmp, *jobj_segment_new = NULL, *jobj_segment_old = NULL, *jobj_segment_bcp = NULL;
uint32_t sector_size = params->luks2 ? params->luks2->sector_size : SECTOR_SIZE;
@@ -2460,9 +2505,17 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
if (r)
goto err;
moved_segment = segment++;
json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), moved_segment, jobj_segment_bcp);
if (!strcmp(json_segment_type(jobj_segment_bcp), "crypt"))
LUKS2_digest_segment_assign(cd, hdr, moved_segment, digest_old, 1, 0);
r = json_object_object_add_by_uint_by_ref(LUKS2_get_segments_jobj(hdr), moved_segment, &jobj_segment_bcp);
if (r)
goto err;
if (!(type = json_segment_type(LUKS2_get_segment_jobj(hdr, moved_segment)))) {
r = -EINVAL;
goto err;
}
if (!strcmp(type, "crypt") && ((r = LUKS2_digest_segment_assign(cd, hdr, moved_segment, digest_old, 1, 0))))
goto err;
}
/* FIXME: Add detection for case (digest old == digest new && old segment == new segment) */
@@ -2478,6 +2531,7 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
json_segment_get_iv_offset(jobj_tmp),
device_size ? &device_size : NULL,
json_segment_get_cipher(jobj_tmp),
NULL, /* integrity */
json_segment_get_sector_size(jobj_tmp),
0);
} else {
@@ -2505,10 +2559,14 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
r = LUKS2_segment_set_flag(jobj_segment_old, "backup-previous");
if (r)
goto err;
json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), segment, jobj_segment_old);
jobj_segment_old = NULL;
if (digest_old >= 0)
LUKS2_digest_segment_assign(cd, hdr, segment, digest_old, 1, 0);
r = json_object_object_add_by_uint_by_ref(LUKS2_get_segments_jobj(hdr), segment, &jobj_segment_old);
if (r)
goto err;
if (digest_old >= 0 && (r = LUKS2_digest_segment_assign(cd, hdr, segment, digest_old, 1, 0)))
goto err;
segment++;
if (digest_new >= 0) {
@@ -2520,7 +2578,7 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
}
jobj_segment_new = json_segment_create_crypt(segment_offset,
crypt_get_iv_offset(cd),
NULL, cipher, sector_size, 0);
NULL, cipher, NULL, sector_size, 0);
} else if (params->mode == CRYPT_REENCRYPT_DECRYPT) {
segment_offset = data_offset;
if (modify_offset(&segment_offset, data_shift, params->direction)) {
@@ -2538,10 +2596,13 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
r = LUKS2_segment_set_flag(jobj_segment_new, "backup-final");
if (r)
goto err;
json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), segment, jobj_segment_new);
jobj_segment_new = NULL;
if (digest_new >= 0)
LUKS2_digest_segment_assign(cd, hdr, segment, digest_new, 1, 0);
r = json_object_object_add_by_uint_by_ref(LUKS2_get_segments_jobj(hdr), segment, &jobj_segment_new);
if (r)
goto err;
if (digest_new >= 0 && (r = LUKS2_digest_segment_assign(cd, hdr, segment, digest_new, 1, 0)))
goto err;
/* FIXME: also check occupied space by keyslot in shrunk area */
if (params->direction == CRYPT_REENCRYPT_FORWARD && data_shift &&
@@ -2556,6 +2617,7 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
err:
json_object_put(jobj_segment_new);
json_object_put(jobj_segment_old);
json_object_put(jobj_segment_bcp);
return r;
}
@@ -2590,7 +2652,6 @@ static int reencrypt_verify_keys(struct crypt_device *cd,
}
static int reencrypt_upload_single_key(struct crypt_device *cd,
struct luks2_hdr *hdr,
int digest,
struct volume_key *vks)
{
@@ -2615,11 +2676,11 @@ static int reencrypt_upload_keys(struct crypt_device *cd,
return 0;
if (digest_new >= 0 && !crypt_is_cipher_null(reencrypt_segment_cipher_new(hdr)) &&
(r = reencrypt_upload_single_key(cd, hdr, digest_new, vks)))
(r = reencrypt_upload_single_key(cd, digest_new, vks)))
return r;
if (digest_old >= 0 && !crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr)) &&
(r = reencrypt_upload_single_key(cd, hdr, digest_old, vks))) {
(r = reencrypt_upload_single_key(cd, digest_old, vks))) {
crypt_drop_keyring_key(cd, vks);
return r;
}
@@ -3256,7 +3317,17 @@ static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
return 0;
}
#else
int LUKS2_reencrypt_max_hotzone_size(struct crypt_device *cd __attribute__((unused)),
struct luks2_hdr *hdr __attribute__((unused)),
const struct reenc_protection *rp __attribute__((unused)),
int reencrypt_keyslot __attribute__((unused)),
uint64_t *r_length __attribute__((unused)))
{
return -ENOTSUP;
}
#endif
static int reencrypt_lock_internal(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock)
{
int r;
@@ -3705,7 +3776,7 @@ out:
return r;
}
#endif
static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *name,
const char *passphrase,
@@ -3716,7 +3787,6 @@ static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *cipher_mode,
const struct crypt_params_reencrypt *params)
{
#if USE_LUKS2_REENCRYPTION
int r;
crypt_reencrypt_info ri;
struct volume_key *vks = NULL;
@@ -3778,11 +3848,22 @@ out:
crypt_drop_keyring_key(cd, vks);
crypt_free_volume_key(vks);
return r < 0 ? r : LUKS2_find_keyslot(hdr, "reencrypt");
}
#else
static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *name __attribute__((unused)),
const char *passphrase __attribute__((unused)),
size_t passphrase_size __attribute__((unused)),
int keyslot_old __attribute__((unused)),
int keyslot_new __attribute__((unused)),
const char *cipher __attribute__((unused)),
const char *cipher_mode __attribute__((unused)),
const struct crypt_params_reencrypt *params __attribute__((unused)))
{
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
#endif
}
#endif
int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
const char *name,
@@ -3797,14 +3878,20 @@ int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
char *passphrase;
size_t passphrase_size;
if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase_description)
if (onlyLUKS2reencrypt(cd) || !passphrase_description)
return -EINVAL;
if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (params->flags & CRYPT_REENCRYPT_RESUME_ONLY))
return -EINVAL;
r = keyring_get_passphrase(passphrase_description, &passphrase, &passphrase_size);
if (device_is_dax(crypt_data_device(cd)) > 0) {
log_err(cd, _("Reencryption is not supported for DAX (persistent memory) devices."));
return -EINVAL;
}
r = crypt_keyring_get_user_key(cd, passphrase_description, &passphrase, &passphrase_size);
if (r < 0) {
log_err(cd, _("Failed to read passphrase from keyring (error %d)."), r);
log_dbg(cd, "crypt_keyring_get_user_key failed (error %d)", r);
log_err(cd, _("Failed to read passphrase from keyring."));
return -EINVAL;
}
@@ -3826,11 +3913,16 @@ int crypt_reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *cipher_mode,
const struct crypt_params_reencrypt *params)
{
if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase)
if (onlyLUKS2reencrypt(cd) || !passphrase)
return -EINVAL;
if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (params->flags & CRYPT_REENCRYPT_RESUME_ONLY))
return -EINVAL;
if (device_is_dax(crypt_data_device(cd)) > 0) {
log_err(cd, _("Reencryption is not supported for DAX (persistent memory) devices."));
return -EINVAL;
}
return reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params);
}
@@ -4112,14 +4204,12 @@ static int reencrypt_teardown(struct crypt_device *cd, struct luks2_hdr *hdr,
return r;
}
#endif
int crypt_reencrypt_run(
struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
void *usrptr)
{
#if USE_LUKS2_REENCRYPTION
int r;
crypt_reencrypt_info ri;
struct luks2_hdr *hdr;
@@ -4127,7 +4217,7 @@ int crypt_reencrypt_run(
reenc_status_t rs;
bool quit = false;
if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT))
if (onlyLUKS2reencrypt(cd))
return -EINVAL;
hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
@@ -4180,19 +4270,9 @@ int crypt_reencrypt_run(
r = reencrypt_teardown(cd, hdr, rh, rs, quit, progress, usrptr);
return r;
#else
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
#endif
}
int crypt_reencrypt(
struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
{
return crypt_reencrypt_run(cd, progress, NULL);
}
#if USE_LUKS2_REENCRYPTION
static int reencrypt_recovery(struct crypt_device *cd,
struct luks2_hdr *hdr,
uint64_t device_size,
@@ -4228,7 +4308,27 @@ out:
return r;
}
#else /* USE_LUKS2_REENCRYPTION */
int crypt_reencrypt_run(
struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
void *usrptr)
{
UNUSED(progress);
UNUSED(usrptr);
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
}
#endif
int crypt_reencrypt(
struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
{
return crypt_reencrypt_run(cd, progress, NULL);
}
/*
* use only for calculation of minimal data device size.
* The real data offset is taken directly from segments!
@@ -4246,7 +4346,7 @@ int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise)
/* internal only */
int LUKS2_reencrypt_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr,
uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic)
uint64_t check_size, uint64_t *dev_size, bool device_exclusive_check, bool dynamic)
{
int r;
uint64_t data_offset, real_size = 0;
@@ -4255,7 +4355,8 @@ int LUKS2_reencrypt_check_device_size(struct crypt_device *cd, struct luks2_hdr
(LUKS2_get_segment_by_flag(hdr, "backup-moved-segment") || dynamic))
check_size += reencrypt_data_shift(hdr);
r = device_check_access(cd, crypt_data_device(cd), activation ? DEV_EXCL : DEV_OK);
r = device_check_access(cd, crypt_data_device(cd),
device_exclusive_check ? DEV_EXCL : DEV_OK);
if (r)
return r;
@@ -4333,6 +4434,39 @@ out:
return r < 0 ? r : keyslot;
}
int LUKS2_reencrypt_locked_recovery_by_vks(struct crypt_device *cd,
struct volume_key *vks)
{
uint64_t minimal_size, device_size;
int r = -EINVAL;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
struct volume_key *vk = NULL;
log_dbg(cd, "Entering reencryption crash recovery.");
if (LUKS2_get_data_size(hdr, &minimal_size, NULL))
return r;
if (crypt_use_keyring_for_vk(cd))
vk = vks;
while (vk) {
r = LUKS2_volume_key_load_in_keyring_by_digest(cd, vk, crypt_volume_key_get_id(vk));
if (r < 0)
goto out;
vk = crypt_volume_key_next(vk);
}
if (LUKS2_reencrypt_check_device_size(cd, hdr, minimal_size, &device_size, true, false))
goto out;
r = reencrypt_recovery(cd, hdr, device_size, vks);
out:
if (r < 0)
crypt_drop_keyring_key(cd, vks);
return r;
}
#endif
crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
struct crypt_params_reencrypt *params)

View File

@@ -1,9 +1,9 @@
/*
* LUKS - Linux Unified Key Setup v2, reencryption digest helpers
*
* Copyright (C) 2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022 Ondrej Kozina
* Copyright (C) 2022 Milan Broz
* Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2022-2024 Ondrej Kozina
* Copyright (C) 2022-2024 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -375,6 +375,22 @@ int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
}
void LUKS2_reencrypt_lookup_key_ids(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vk)
{
int digest_old, digest_new;
digest_old = LUKS2_reencrypt_digest_old(hdr);
digest_new = LUKS2_reencrypt_digest_new(hdr);
while (vk) {
if (digest_old >= 0 && LUKS2_digest_verify_by_digest(cd, digest_old, vk) == digest_old)
crypt_volume_key_set_id(vk, digest_old);
if (digest_new >= 0 && LUKS2_digest_verify_by_digest(cd, digest_new, vk) == digest_new)
crypt_volume_key_set_id(vk, digest_new);
vk = vk->next;
}
}
int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vks)

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, internal segment handling
*
* Copyright (C) 2018-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2022 Ondrej Kozina
* Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2018-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -91,6 +91,33 @@ uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise)
return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
}
static uint64_t json_segment_get_opal_size(json_object *jobj_segment, unsigned blockwise)
{
json_object *jobj;
if (!jobj_segment ||
!json_object_object_get_ex(jobj_segment, "opal_segment_size", &jobj))
return 0;
return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
}
static bool json_segment_set_size(json_object *jobj_segment, const uint64_t *size_bytes)
{
json_object *jobj;
if (!jobj_segment)
return false;
jobj = size_bytes ? crypt_jobj_new_uint64(*size_bytes) : json_object_new_string("dynamic");
if (!jobj)
return false;
json_object_object_add(jobj_segment, "size", jobj);
return true;
}
const char *json_segment_get_cipher(json_object *jobj_segment)
{
json_object *jobj;
@@ -116,6 +143,37 @@ uint32_t json_segment_get_sector_size(json_object *jobj_segment)
return i < 0 ? SECTOR_SIZE : i;
}
int json_segment_get_opal_segment_id(json_object *jobj_segment, uint32_t *ret_opal_segment_id)
{
json_object *jobj_segment_id;
assert(ret_opal_segment_id);
if (!json_object_object_get_ex(jobj_segment, "opal_segment_number", &jobj_segment_id))
return -EINVAL;
*ret_opal_segment_id = json_object_get_int(jobj_segment_id);
return 0;
}
int json_segment_get_opal_key_size(json_object *jobj_segment, size_t *ret_key_size)
{
json_object *jobj_key_size;
assert(ret_key_size);
if (!jobj_segment)
return -EINVAL;
if (!json_object_object_get_ex(jobj_segment, "opal_key_size", &jobj_key_size))
return -EINVAL;
*ret_key_size = json_object_get_int(jobj_key_size);
return 0;
}
static json_object *json_segment_get_flags(json_object *jobj_segment)
{
json_object *jobj;
@@ -245,24 +303,94 @@ json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length,
return jobj;
}
static bool json_add_crypt_fields(json_object *jobj_segment, uint64_t iv_offset,
const char *cipher, const char *integrity,
uint32_t sector_size, unsigned reencryption)
{
json_object *jobj_integrity;
assert(cipher);
json_object_object_add(jobj_segment, "iv_tweak", crypt_jobj_new_uint64(iv_offset));
json_object_object_add(jobj_segment, "encryption", json_object_new_string(cipher));
json_object_object_add(jobj_segment, "sector_size", json_object_new_int(sector_size));
if (integrity) {
jobj_integrity = json_object_new_object();
if (!jobj_integrity)
return false;
json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
json_object_object_add(jobj_segment, "integrity", jobj_integrity);
}
if (reencryption)
LUKS2_segment_set_flag(jobj_segment, "in-reencryption");
return true;
}
json_object *json_segment_create_crypt(uint64_t offset,
uint64_t iv_offset, const uint64_t *length,
const char *cipher, uint32_t sector_size,
unsigned reencryption)
const char *cipher, const char *integrity,
uint32_t sector_size, unsigned reencryption)
{
json_object *jobj = _segment_create_generic("crypt", offset, length);
if (!jobj)
return NULL;
json_object_object_add(jobj, "iv_tweak", crypt_jobj_new_uint64(iv_offset));
json_object_object_add(jobj, "encryption", json_object_new_string(cipher));
json_object_object_add(jobj, "sector_size", json_object_new_int(sector_size));
if (reencryption)
LUKS2_segment_set_flag(jobj, "in-reencryption");
if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, sector_size, reencryption))
return jobj;
json_object_put(jobj);
return NULL;
}
static void json_add_opal_fields(json_object *jobj_segment, const uint64_t *length,
uint32_t segment_number, uint32_t key_size)
{
assert(jobj_segment);
assert(length);
json_object_object_add(jobj_segment, "opal_segment_number", json_object_new_int(segment_number));
json_object_object_add(jobj_segment, "opal_key_size", json_object_new_int(key_size));
json_object_object_add(jobj_segment, "opal_segment_size", crypt_jobj_new_uint64(*length));
}
json_object *json_segment_create_opal(uint64_t offset, const uint64_t *length,
uint32_t segment_number, uint32_t key_size)
{
json_object *jobj = _segment_create_generic("hw-opal", offset, length);
if (!jobj)
return NULL;
json_add_opal_fields(jobj, length, segment_number, key_size);
return jobj;
}
json_object *json_segment_create_opal_crypt(uint64_t offset, const uint64_t *length,
uint32_t segment_number, uint32_t key_size,
uint64_t iv_offset, const char *cipher,
const char *integrity, uint32_t sector_size,
unsigned reencryption)
{
json_object *jobj = _segment_create_generic("hw-opal-crypt", offset, length);
if (!jobj)
return NULL;
json_add_opal_fields(jobj, length, segment_number, key_size);
if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, sector_size, reencryption))
return jobj;
json_object_put(jobj);
return NULL;
}
uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, int segment, unsigned blockwise)
{
return json_segment_get_offset(LUKS2_get_segment_jobj(hdr, segment), blockwise);
@@ -288,11 +416,85 @@ uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwi
return json_segment_get_size(LUKS2_get_segment_jobj(hdr, segment), blockwise);
}
uint64_t LUKS2_opal_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise)
{
return json_segment_get_opal_size(LUKS2_get_segment_jobj(hdr, segment), blockwise);
}
bool LUKS2_segment_set_size(struct luks2_hdr *hdr, int segment, const uint64_t *segment_size_bytes)
{
return json_segment_set_size(LUKS2_get_segment_jobj(hdr, segment), segment_size_bytes);
}
int LUKS2_segment_is_type(struct luks2_hdr *hdr, int segment, const char *type)
{
return !strcmp(json_segment_type(LUKS2_get_segment_jobj(hdr, segment)) ?: "", type);
}
static bool json_segment_is_hw_opal_only(json_object *jobj_segment)
{
const char *type = json_segment_type(jobj_segment);
if (!type)
return false;
return !strcmp(type, "hw-opal");
}
static bool json_segment_is_hw_opal_crypt(json_object *jobj_segment)
{
const char *type = json_segment_type(jobj_segment);
if (!type)
return false;
return !strcmp(type, "hw-opal-crypt");
}
static bool json_segment_is_hw_opal(json_object *jobj_segment)
{
return json_segment_is_hw_opal_crypt(jobj_segment) ||
json_segment_is_hw_opal_only(jobj_segment);
}
bool LUKS2_segment_is_hw_opal_only(struct luks2_hdr *hdr, int segment)
{
return json_segment_is_hw_opal_only(LUKS2_get_segment_jobj(hdr, segment));
}
bool LUKS2_segment_is_hw_opal_crypt(struct luks2_hdr *hdr, int segment)
{
return json_segment_is_hw_opal_crypt(LUKS2_get_segment_jobj(hdr, segment));
}
bool LUKS2_segment_is_hw_opal(struct luks2_hdr *hdr, int segment)
{
return json_segment_is_hw_opal(LUKS2_get_segment_jobj(hdr, segment));
}
int LUKS2_get_opal_segment_number(struct luks2_hdr *hdr, int segment, uint32_t *ret_opal_segment_number)
{
json_object *jobj_segment = LUKS2_get_segment_jobj(hdr, segment);
assert(ret_opal_segment_number);
if (!json_segment_is_hw_opal(jobj_segment))
return -ENOENT;
return json_segment_get_opal_segment_id(jobj_segment, ret_opal_segment_number);
}
int LUKS2_get_opal_key_size(struct luks2_hdr *hdr, int segment)
{
size_t key_size = 0;
json_object *jobj_segment = LUKS2_get_segment_jobj(hdr, segment);
if (json_segment_get_opal_key_size(jobj_segment, &key_size) < 0)
return 0;
return key_size;
}
int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, const char *type)
{
json_object *jobj_segments;
@@ -424,3 +626,27 @@ bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
return true;
}
bool LUKS2_segments_dynamic_size(struct luks2_hdr *hdr)
{
json_object *jobj_segments, *jobj_size;
assert(hdr);
jobj_segments = LUKS2_get_segments_jobj(hdr);
if (!jobj_segments)
return false;
json_object_object_foreach(jobj_segments, key, val) {
UNUSED(key);
if (json_segment_is_backup(val))
continue;
if (json_object_object_get_ex(val, "size", &jobj_size) &&
!strcmp(json_object_get_string(jobj_size), "dynamic"))
return true;
}
return false;
}

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, token handling
*
* Copyright (C) 2016-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2022 Milan Broz
* Copyright (C) 2016-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2024 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,7 +25,9 @@
#include "luks2_internal.h"
#if USE_EXTERNAL_TOKENS
#define TOKENS_PATH_MAX PATH_MAX
static bool external_tokens_enabled = true;
static char external_tokens_path[TOKENS_PATH_MAX] = EXTERNAL_LUKS2_TOKENS_PATH;
#else
static bool external_tokens_enabled = false;
#endif
@@ -51,7 +53,56 @@ void crypt_token_external_disable(void)
const char *crypt_token_external_path(void)
{
return external_tokens_enabled ? EXTERNAL_LUKS2_TOKENS_PATH : NULL;
#if USE_EXTERNAL_TOKENS
return external_tokens_enabled ? external_tokens_path : NULL;
#else
return NULL;
#endif
}
#if USE_EXTERNAL_TOKENS
int crypt_token_set_external_path(const char *path)
{
int r;
char tokens_path[TOKENS_PATH_MAX];
if (!path)
path = EXTERNAL_LUKS2_TOKENS_PATH;
else if (*path != '/')
return -EINVAL;
r = snprintf(tokens_path, sizeof(tokens_path), "%s", path);
if (r < 0 || (size_t)r >= sizeof(tokens_path))
return -EINVAL;
(void)strcpy(external_tokens_path, tokens_path);
return 0;
}
#else
#pragma GCC diagnostic ignored "-Wunused-parameter"
int crypt_token_set_external_path(const char *path)
{
return -ENOTSUP;
}
#endif
static bool token_validate_v1(struct crypt_device *cd, const crypt_token_handler *h)
{
if (!h)
return false;
if (!h->name) {
log_dbg(cd, "Error: token handler does not provide name attribute.");
return false;
}
if (!h->open) {
log_dbg(cd, "Error: token handler does not provide open function.");
return false;
}
return true;
}
#if USE_EXTERNAL_TOKENS
@@ -77,27 +128,7 @@ static void *token_dlvsym(struct crypt_device *cd,
return sym;
}
#endif
static bool token_validate_v1(struct crypt_device *cd, const crypt_token_handler *h)
{
if (!h)
return false;
if (!h->name) {
log_dbg(cd, "Error: token handler does not provide name attribute.");
return false;
}
if (!h->open) {
log_dbg(cd, "Error: token handler does not provide open function.");
return false;
}
return true;
}
#if USE_EXTERNAL_TOKENS
static bool token_validate_v2(struct crypt_device *cd, const struct crypt_token_handler_internal *h)
{
if (!h)
@@ -127,12 +158,10 @@ static bool external_token_name_valid(const char *name)
return true;
}
#endif
static int
crypt_token_load_external(struct crypt_device *cd, const char *name, struct crypt_token_handler_internal *ret)
{
#if USE_EXTERNAL_TOKENS
struct crypt_token_handler_v2 *token;
void *h;
char buf[PATH_MAX];
@@ -192,11 +221,40 @@ crypt_token_load_external(struct crypt_device *cd, const char *name, struct cryp
ret->version = 2;
return 0;
#else
return -ENOTSUP;
#endif
}
void crypt_token_unload_external_all(struct crypt_device *cd)
{
int i;
for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
if (token_handlers[i].version < 2)
continue;
log_dbg(cd, "Unloading %s token handler.", token_handlers[i].u.v2.name);
free(CONST_CAST(void *)token_handlers[i].u.v2.name);
if (dlclose(CONST_CAST(void *)token_handlers[i].u.v2.dlhandle))
log_dbg(cd, "%s", dlerror());
}
}
#else /* USE_EXTERNAL_TOKENS */
static int crypt_token_load_external(struct crypt_device *cd __attribute__((unused)),
const char *name __attribute__((unused)),
struct crypt_token_handler_internal *ret __attribute__((unused)))
{
return -ENOTSUP;
}
void crypt_token_unload_external_all(struct crypt_device *cd __attribute__((unused)))
{
}
#endif
static int is_builtin_candidate(const char *type)
{
return !strncmp(type, LUKS2_BUILTIN_TOKEN_PREFIX, LUKS2_BUILTIN_TOKEN_PREFIX_LEN);
@@ -243,25 +301,6 @@ int crypt_token_register(const crypt_token_handler *handler)
return 0;
}
void crypt_token_unload_external_all(struct crypt_device *cd)
{
#if USE_EXTERNAL_TOKENS
int i;
for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
if (token_handlers[i].version < 2)
continue;
log_dbg(cd, "Unloading %s token handler.", token_handlers[i].u.v2.name);
free(CONST_CAST(void *)token_handlers[i].u.v2.name);
if (dlclose(CONST_CAST(void *)token_handlers[i].u.v2.dlhandle))
log_dbg(cd, "%s", dlerror());
}
#endif
}
static const void
*LUKS2_token_handler_type(struct crypt_device *cd, const char *type)
{
@@ -423,12 +462,12 @@ static const char *token_json_to_string(json_object *jobj_token)
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
}
static int token_is_usable(struct luks2_hdr *hdr, json_object *jobj_token, int segment,
static int token_is_usable(struct luks2_hdr *hdr, json_object *jobj_token, int keyslot, int segment,
crypt_keyslot_priority minimal_priority, bool requires_keyslot)
{
crypt_keyslot_priority keyslot_priority;
json_object *jobj_array;
int i, keyslot, len, r = -ENOENT;
int i, slot, len, r = -ENOENT;
if (!jobj_token)
return -EINVAL;
@@ -451,16 +490,19 @@ static int token_is_usable(struct luks2_hdr *hdr, json_object *jobj_token, int s
return -ENOENT;
for (i = 0; i < len; i++) {
keyslot = atoi(json_object_get_string(json_object_array_get_idx(jobj_array, i)));
slot = atoi(json_object_get_string(json_object_array_get_idx(jobj_array, i)));
keyslot_priority = LUKS2_keyslot_priority_get(hdr, keyslot);
if (keyslot != CRYPT_ANY_SLOT && slot != keyslot)
continue;
keyslot_priority = LUKS2_keyslot_priority_get(hdr, slot);
if (keyslot_priority == CRYPT_SLOT_PRIORITY_INVALID)
return -EINVAL;
if (keyslot_priority < minimal_priority)
continue;
r = LUKS2_keyslot_for_segment(hdr, keyslot, segment);
r = LUKS2_keyslot_for_segment(hdr, slot, segment);
if (r != -ENOENT)
return r;
}
@@ -480,6 +522,7 @@ static int translate_errno(struct crypt_device *cd, int ret_val, const char *typ
static int token_open(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
json_object *jobj_token,
const char *type,
@@ -507,7 +550,7 @@ static int token_open(struct crypt_device *cd,
return -ENOENT;
}
r = token_is_usable(hdr, jobj_token, segment, priority, requires_keyslot);
r = token_is_usable(hdr, jobj_token, keyslot, segment, priority, requires_keyslot);
if (r < 0) {
if (r == -ENOENT)
log_dbg(cd, "Token %d unusable for segment %d with desired keyslot priority %d.",
@@ -569,32 +612,22 @@ static void update_return_errno(int r, int *stored)
*stored = r;
}
static int LUKS2_keyslot_open_by_token(struct crypt_device *cd,
static int try_token_keyslot_unlock(struct crypt_device *cd,
struct luks2_hdr *hdr,
const char *type,
json_object *jobj_token_keyslots,
int token,
int segment,
crypt_keyslot_priority priority,
const char *buffer,
size_t buffer_len,
struct volume_key **vk)
struct volume_key **r_vk)
{
json_object *jobj;
crypt_keyslot_priority keyslot_priority;
json_object *jobj_token, *jobj_token_keyslots, *jobj_type, *jobj;
unsigned int num = 0;
int i, r = -ENOENT, stored_retval = -ENOENT;
unsigned int num = 0;
jobj_token = LUKS2_get_token_jobj(hdr, token);
if (!jobj_token)
return -EINVAL;
if (!json_object_object_get_ex(jobj_token, "type", &jobj_type))
return -EINVAL;
json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots);
if (!jobj_token_keyslots)
return -EINVAL;
/* Try to open keyslot referenced in token */
for (i = 0; i < (int) json_object_array_length(jobj_token_keyslots) && r < 0; i++) {
jobj = json_object_array_get_idx(jobj_token_keyslots, i);
num = atoi(json_object_get_string(jobj));
@@ -604,8 +637,8 @@ static int LUKS2_keyslot_open_by_token(struct crypt_device *cd,
if (keyslot_priority < priority)
continue;
log_dbg(cd, "Trying to open keyslot %u with token %d (type %s).",
num, token, json_object_get_string(jobj_type));
r = LUKS2_keyslot_open(cd, num, segment, buffer, buffer_len, vk);
num, token, type);
r = LUKS2_keyslot_open(cd, num, segment, buffer, buffer_len, r_vk);
/* short circuit on fatal error */
if (r < 0 && r != -EPERM && r != -ENOENT)
return r;
@@ -620,6 +653,53 @@ static int LUKS2_keyslot_open_by_token(struct crypt_device *cd,
return num;
}
static int LUKS2_keyslot_open_by_token(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
int segment,
crypt_keyslot_priority min_priority,
const char *buffer,
size_t buffer_len,
struct volume_key **vk)
{
json_object *jobj_token, *jobj_token_keyslots, *jobj_type;
crypt_keyslot_priority priority = CRYPT_SLOT_PRIORITY_PREFER;
int r = -ENOENT, stored_retval = -ENOENT;
jobj_token = LUKS2_get_token_jobj(hdr, token);
if (!jobj_token)
return -EINVAL;
if (!json_object_object_get_ex(jobj_token, "type", &jobj_type))
return -EINVAL;
json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots);
if (!jobj_token_keyslots)
return -EINVAL;
/* with specific keyslot just ignore priorities and unlock */
if (keyslot != CRYPT_ANY_SLOT) {
log_dbg(cd, "Trying to open keyslot %u with token %d (type %s).",
keyslot, token, json_object_get_string(jobj_type));
return LUKS2_keyslot_open(cd, keyslot, segment, buffer, buffer_len, vk);
}
/* Try to open keyslot referenced in token */
while (priority >= min_priority) {
r = try_token_keyslot_unlock(cd, hdr, json_object_get_string(jobj_type),
jobj_token_keyslots, token, segment,
priority, buffer, buffer_len, vk);
if (r == -EINVAL || r >= 0)
return r;
if (r == -EPERM)
stored_retval = r;
priority--;
}
return stored_retval;
}
static bool token_is_blocked(int token, uint32_t *block_list)
{
/* it is safe now, but have assert in case LUKS2_TOKENS_MAX grows */
@@ -640,6 +720,7 @@ static int token_open_priority(struct crypt_device *cd,
struct luks2_hdr *hdr,
json_object *jobj_tokens,
const char *type,
int keyslot,
int segment,
crypt_keyslot_priority priority,
const char *pin,
@@ -660,9 +741,10 @@ static int token_open_priority(struct crypt_device *cd,
token = atoi(slot);
if (token_is_blocked(token, block_list))
continue;
r = token_open(cd, hdr, token, val, type, segment, priority, pin, pin_size, &buffer, &buffer_size, usrptr, true);
r = token_open(cd, hdr, keyslot, token, val, type, segment, priority, pin, pin_size,
&buffer, &buffer_size, usrptr, true);
if (!r) {
r = LUKS2_keyslot_open_by_token(cd, hdr, token, segment, priority,
r = LUKS2_keyslot_open_by_token(cd, hdr, keyslot, token, segment, priority,
buffer, buffer_size, vk);
LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
}
@@ -679,8 +761,9 @@ static int token_open_priority(struct crypt_device *cd,
return *stored_retval;
}
static int token_open_any(struct crypt_device *cd, struct luks2_hdr *hdr, const char *type, int segment,
const char *pin, size_t pin_size, void *usrptr, struct volume_key **vk)
static int token_open_any(struct crypt_device *cd, struct luks2_hdr *hdr, const char *type,
int keyslot, int segment, const char *pin, size_t pin_size, void *usrptr,
struct volume_key **vk)
{
json_object *jobj_tokens;
int r, retval = -ENOENT;
@@ -692,17 +775,22 @@ static int token_open_any(struct crypt_device *cd, struct luks2_hdr *hdr, const
if (!type)
usrptr = NULL;
r = token_open_priority(cd, hdr, jobj_tokens, type, segment, CRYPT_SLOT_PRIORITY_PREFER,
if (keyslot != CRYPT_ANY_SLOT)
return token_open_priority(cd, hdr, jobj_tokens, type, keyslot, segment, CRYPT_SLOT_PRIORITY_IGNORE,
pin, pin_size, usrptr, &retval, &blocked, vk);
r = token_open_priority(cd, hdr, jobj_tokens, type, keyslot, segment, CRYPT_SLOT_PRIORITY_PREFER,
pin, pin_size, usrptr, &retval, &blocked, vk);
if (break_loop_retval(r))
return r;
return token_open_priority(cd, hdr, jobj_tokens, type, segment, CRYPT_SLOT_PRIORITY_NORMAL,
return token_open_priority(cd, hdr, jobj_tokens, type, keyslot, segment, CRYPT_SLOT_PRIORITY_NORMAL,
pin, pin_size, usrptr, &retval, &blocked, vk);
}
int LUKS2_token_unlock_key(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
const char *type,
const char *pin,
@@ -714,6 +802,7 @@ int LUKS2_token_unlock_key(struct crypt_device *cd,
char *buffer;
size_t buffer_size;
json_object *jobj_token;
crypt_keyslot_priority min_priority;
int r = -ENOENT;
assert(vk);
@@ -724,13 +813,27 @@ int LUKS2_token_unlock_key(struct crypt_device *cd,
if (segment < 0 && segment != CRYPT_ANY_SEGMENT)
return -EINVAL;
if (keyslot != CRYPT_ANY_SLOT || token != CRYPT_ANY_TOKEN)
min_priority = CRYPT_SLOT_PRIORITY_IGNORE;
else
min_priority = CRYPT_SLOT_PRIORITY_NORMAL;
if (keyslot != CRYPT_ANY_SLOT) {
r = LUKS2_keyslot_for_segment(hdr, keyslot, segment);
if (r < 0) {
if (r == -ENOENT)
log_dbg(cd, "Keyslot %d unusable for segment %d.", keyslot, segment);
return r;
}
}
if (token >= 0 && token < LUKS2_TOKENS_MAX) {
if ((jobj_token = LUKS2_get_token_jobj(hdr, token))) {
r = token_open(cd, hdr, token, jobj_token, type, segment, CRYPT_SLOT_PRIORITY_IGNORE,
r = token_open(cd, hdr, keyslot, token, jobj_token, type, segment, min_priority,
pin, pin_size, &buffer, &buffer_size, usrptr, true);
if (!r) {
r = LUKS2_keyslot_open_by_token(cd, hdr, token, segment, CRYPT_SLOT_PRIORITY_IGNORE,
buffer, buffer_size, vk);
r = LUKS2_keyslot_open_by_token(cd, hdr, keyslot, token, segment,
min_priority, buffer, buffer_size, vk);
LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
}
}
@@ -745,7 +848,7 @@ int LUKS2_token_unlock_key(struct crypt_device *cd,
* success (>= 0) or any other negative errno short-circuits token activation loop
* immediately
*/
r = token_open_any(cd, hdr, type, segment, pin, pin_size, usrptr, vk);
r = token_open_any(cd, hdr, type, keyslot, segment, pin, pin_size, usrptr, vk);
else
r = -EINVAL;
@@ -754,6 +857,7 @@ int LUKS2_token_unlock_key(struct crypt_device *cd,
int LUKS2_token_open_and_activate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int token,
const char *name,
const char *type,
@@ -763,15 +867,15 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd,
void *usrptr)
{
bool use_keyring;
int keyslot, r, segment;
struct volume_key *vk = NULL;
int r, segment;
struct volume_key *p_crypt, *p_opal, *crypt_key = NULL, *opal_key = NULL, *vk = NULL;
if (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY)
segment = CRYPT_ANY_SEGMENT;
else
segment = CRYPT_DEFAULT_SEGMENT;
r = LUKS2_token_unlock_key(cd, hdr, token, type, pin, pin_size, segment, usrptr, &vk);
r = LUKS2_token_unlock_key(cd, hdr, keyslot, token, type, pin, pin_size, segment, usrptr, &vk);
if (r < 0)
return r;
@@ -779,23 +883,39 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd,
keyslot = r;
if (!crypt_use_keyring_for_vk(cd))
if (LUKS2_segment_is_hw_opal(hdr, CRYPT_DEFAULT_SEGMENT)) {
r = LUKS2_split_crypt_and_opal_keys(cd, hdr, vk, &crypt_key, &opal_key);
if (r < 0) {
crypt_free_volume_key(vk);
return r;
}
p_crypt = crypt_key;
p_opal = opal_key ?: vk;
} else {
p_crypt = vk;
p_opal = NULL;
}
if (!crypt_use_keyring_for_vk(cd) || !p_crypt)
use_keyring = false;
else
use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
(flags & CRYPT_ACTIVATE_KEYRING_KEY));
if (use_keyring) {
if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot)))
if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, p_crypt, keyslot)))
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
}
if (r >= 0 && name)
r = LUKS2_activate(cd, name, vk, flags);
r = LUKS2_activate(cd, name, p_crypt, p_opal, flags);
if (r < 0)
crypt_drop_keyring_key(cd, vk);
crypt_drop_keyring_key(cd, p_crypt);
crypt_free_volume_key(vk);
crypt_free_volume_key(crypt_key);
crypt_free_volume_key(opal_key);
return r < 0 ? r : keyslot;
}
@@ -995,8 +1115,9 @@ int LUKS2_token_unlock_passphrase(struct crypt_device *cd,
if (token >= 0 && token < LUKS2_TOKENS_MAX) {
if ((jobj_token = LUKS2_get_token_jobj(hdr, token)))
r = token_open(cd, hdr, token, jobj_token, type, CRYPT_ANY_SEGMENT, CRYPT_SLOT_PRIORITY_IGNORE,
pin, pin_size, &buffer, &buffer_size, usrptr, false);
r = token_open(cd, hdr, CRYPT_ANY_SLOT, token, jobj_token, type,
CRYPT_ANY_SEGMENT, CRYPT_SLOT_PRIORITY_IGNORE, pin, pin_size,
&buffer, &buffer_size, usrptr, false);
} else if (token == CRYPT_ANY_TOKEN) {
json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens);
@@ -1005,7 +1126,7 @@ int LUKS2_token_unlock_passphrase(struct crypt_device *cd,
json_object_object_foreach(jobj_tokens, slot, val) {
token = atoi(slot);
r = token_open(cd, hdr, token, val, type, CRYPT_ANY_SEGMENT, CRYPT_SLOT_PRIORITY_IGNORE,
r = token_open(cd, hdr, CRYPT_ANY_SLOT, token, val, type, CRYPT_ANY_SEGMENT, CRYPT_SLOT_PRIORITY_IGNORE,
pin, pin_size, &buffer, &buffer_size, usrptr, false);
/*

View File

@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup v2, kernel keyring token
*
* Copyright (C) 2016-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2022 Ondrej Kozina
* Copyright (C) 2016-2024 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -40,14 +40,11 @@ int keyring_open(struct crypt_device *cd,
json_object_object_get_ex(jobj_token, "key_description", &jobj_key);
r = keyring_get_passphrase(json_object_get_string(jobj_key), buffer, buffer_len);
if (r == -ENOTSUP) {
log_dbg(cd, "Kernel keyring features disabled.");
r = crypt_keyring_get_user_key(cd, json_object_get_string(jobj_key), buffer, buffer_len);
if (r == -ENOTSUP)
return -ENOENT;
} else if (r < 0) {
log_dbg(cd, "keyring_get_passphrase failed (error %d)", r);
else if (r < 0)
return -EPERM;
}
return 0;
}

116
lib/meson.build Normal file
View File

@@ -0,0 +1,116 @@
subdir('crypto_backend')
lib_build_dir = meson.current_build_dir()
libutils_io = static_library('utils_io',
files(
'utils_io.c',
))
libcryptsetup_sym_path = join_paths(meson.current_source_dir(), 'libcryptsetup.sym')
libcryptsetup_deps = [
uuid,
devmapper,
libargon2_external,
jsonc,
blkid,
dl,
]
libcryptsetup_sources = files(
'bitlk/bitlk.c',
'fvault2/fvault2.c',
'integrity/integrity.c',
'loopaes/loopaes.c',
'luks1/af.c',
'luks1/keyencryption.c',
'luks1/keymanage.c',
'luks2/hw_opal/hw_opal.c',
'luks2/luks2_digest.c',
'luks2/luks2_digest_pbkdf2.c',
'luks2/luks2_disk_metadata.c',
'luks2/luks2_json_format.c',
'luks2/luks2_json_metadata.c',
'luks2/luks2_keyslot.c',
'luks2/luks2_keyslot_luks2.c',
'luks2/luks2_keyslot_reenc.c',
'luks2/luks2_luks1_convert.c',
'luks2/luks2_reencrypt.c',
'luks2/luks2_reencrypt_digest.c',
'luks2/luks2_segment.c',
'luks2/luks2_token.c',
'luks2/luks2_token_keyring.c',
'tcrypt/tcrypt.c',
'verity/rs_decode_char.c',
'verity/rs_encode_char.c',
'verity/verity.c',
'verity/verity_fec.c',
'verity/verity_hash.c',
'crypt_plain.c',
'keyslot_context.c',
'libdevmapper.c',
'random.c',
'setup.c',
'utils.c',
'utils_benchmark.c',
'utils_blkid.c',
'utils_crypt.c',
'utils_device.c',
'utils_device_locking.c',
'utils_devpath.c',
'utils_keyring.c',
'utils_loop.c',
'utils_pbkdf.c',
'utils_safe_memory.c',
'utils_storage_wrappers.c',
'utils_wipe.c',
'volumekey.c',
)
if enable_static
libcryptsetup = static_library('cryptsetup',
libcryptsetup_sources,
dependencies: libcryptsetup_deps,
link_with: [
libcrypto_backend,
libutils_io,
],
install: true)
else
libcryptsetup = library('cryptsetup',
libcryptsetup_sources,
dependencies: libcryptsetup_deps,
version: libcryptsetup_version,
link_args: [
'-Wl,--version-script=' +
libcryptsetup_sym_path,
],
link_with: [
libcrypto_backend,
libutils_io,
],
install: true)
endif
lib_tools_files = files(
'utils_blkid.c',
'utils_crypt.c',
'utils_io.c',
'utils_loop.c',
)
lib_utils_crypt_files = files(
'utils_crypt.c',
)
lib_ssh_token_files = files(
'utils_io.c',
'utils_loop.c',
)
install_headers(
'libcryptsetup.h',
)
pkgconfig.generate(
libcryptsetup,
name: 'libcryptsetup',
version: PACKAGE_VERSION,
description: 'cryptsetup library')

View File

@@ -1,7 +1,7 @@
/*
* cryptsetup kernel RNG access functions
*
* Copyright (C) 2010-2022 Red Hat, Inc. All rights reserved.
* Copyright (C) 2010-2024 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

File diff suppressed because it is too large Load Diff

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